diff --git a/.gitignore b/.gitignore index ae3b4089f2..6bac5ff293 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ test-modules/functional-tests/src/main/resources/**/*.png build.gradle.swp node_modules/ modules/openlmis-web/src/test/coverage/ +modules/openlmis-web/src/test/karma/ local-ftp-data/ diff --git a/build.gradle b/build.gradle index d3ae478c6c..dcec3cd624 100644 --- a/build.gradle +++ b/build.gradle @@ -54,9 +54,9 @@ subprojects { 'commons-io:commons-io:2.4' - testCompile 'junit:junit:4.8.2', + testCompile 'org.hamcrest:hamcrest-all:1.3', 'org.mockito:mockito-all:1.9.5', - 'org.hamcrest:hamcrest-all:1.3', + 'junit:junit:4.8.2', 'cglib:cglib:2.2.2', 'org.powermock:powermock-mockito-release-full:1.5', 'com.natpryce:make-it-easy:3.1.0' diff --git a/modules/core/src/main/java/org/openlmis/core/domain/BaseModel.java b/modules/core/src/main/java/org/openlmis/core/domain/BaseModel.java index 34ce59592d..f28974301f 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/BaseModel.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/BaseModel.java @@ -44,4 +44,12 @@ public abstract class BaseModel { public BaseModel(Long id) { this.id = id; } + + /** + * Determines if this BaseModel has an id set or not. + * @return true if it has an id set, false otherwise + */ + public boolean hasId() { + return id != null ? true : false; + } } diff --git a/modules/core/src/main/java/org/openlmis/core/domain/DosageUnit.java b/modules/core/src/main/java/org/openlmis/core/domain/DosageUnit.java index da94632cde..a5d421f307 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/DosageUnit.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/DosageUnit.java @@ -14,6 +14,9 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.openlmis.core.exception.DataException; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; /** * DosageUnit represents the Dosage Unit for any product. @@ -22,7 +25,20 @@ @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class DosageUnit extends BaseModel { +public class DosageUnit extends BaseModel implements Importable { + @ImportField(mandatory = true, name="Dosage Unit Code") private String code; + + @ImportField(mandatory = true, name="Display Order") private int displayOrder; + + /** + * Validation method for an instantiated DosageUnit. A valid dosage unit has a code and a display order. + * @throws DataException if this dosage unit is not defined well. + */ + public void isValid() { + if (code == null + || code.length() == 0 + || displayOrder <= 0 ) throw new DataException("error.reference.data.missing"); + } } diff --git a/modules/core/src/main/java/org/openlmis/core/domain/FacilityOperator.java b/modules/core/src/main/java/org/openlmis/core/domain/FacilityOperator.java index 2a6eb40c86..fbc799442f 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/FacilityOperator.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/FacilityOperator.java @@ -12,14 +12,21 @@ import lombok.Data; import lombok.EqualsAndHashCode; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; /** * FacilityOperator represents the operator for facility, the authority responsible for running a facility (for eg. WHO, MOH etc.) */ @Data @EqualsAndHashCode(callSuper = false) -public class FacilityOperator extends BaseModel { +public class FacilityOperator extends BaseModel implements Importable { + @ImportField(name="Facility Operator Code", mandatory=true) private String code; + + @ImportField(name="Name", mandatory=true) private String text; + + @ImportField(name="Display Order", mandatory=true) private Integer displayOrder; -} +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/openlmis/core/domain/FacilityProgramProduct.java b/modules/core/src/main/java/org/openlmis/core/domain/FacilityProgramProduct.java index 81c59a1b0a..9d4ecec4a4 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/FacilityProgramProduct.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/FacilityProgramProduct.java @@ -54,6 +54,16 @@ public ProductGroup getActiveProductGroup() { return null; } + /** + * Calculates the ideal stock amount (ISA) the facility should be stocked to + * with the associated product. + * @param population the population of the facility that will be served by the + * product's stock. + * @param numberOfMonthsInPeriod the number of months the ideal stock amount + * will need to serve the facility. + * @return the ideal stock amount of the associated product for the associated + * facility or null if the ISA is not calculable. + */ public Integer calculateIsa(Long population, Integer numberOfMonthsInPeriod) { Integer idealQuantity; if (this.overriddenIsa != null) @@ -63,10 +73,25 @@ else if (this.programProductIsa == null || population == null) else idealQuantity = this.programProductIsa.calculate(population); - idealQuantity = Math.round(idealQuantity * ((float) numberOfMonthsInPeriod / this.getProduct().getPackSize())); + idealQuantity = idealQuantity * numberOfMonthsInPeriod; return idealQuantity < 0 ? 0 : idealQuantity; } + /** + * Calculates the ideal stock amount (ISA) in terms of pack size. i.e. the + * number of whole deliverable units that a facility would be stocked to for the associated + * product. + * @return the number of whole deliverable units of the associated product that meets or + * exceeds the ISA or null if the ISA is not calculable. + * @see #calculateIsa(Long, Integer) + */ + public Integer calculateIsaByPackSize(Long population, Integer numberOfMonthsInPeriod) { + Integer idealQuantity = calculateIsa(population, numberOfMonthsInPeriod); + if (idealQuantity == null) return null; + + return new Double(Math.ceil( (float) idealQuantity / this.getProduct().getPackSize() )).intValue(); + } + @JsonIgnore public Double getWhoRatio(String productCode) { ProgramProductISA programProductIsa = this.getProgramProductIsa(); diff --git a/modules/core/src/main/java/org/openlmis/core/domain/FacilityType.java b/modules/core/src/main/java/org/openlmis/core/domain/FacilityType.java index 866e0a9b8f..933827c35e 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/FacilityType.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/FacilityType.java @@ -14,6 +14,8 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; import static org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_EMPTY; @@ -25,14 +27,29 @@ @NoArgsConstructor @JsonSerialize(include = NON_EMPTY) @EqualsAndHashCode(callSuper = false) -public class FacilityType extends BaseModel { +public class FacilityType extends BaseModel implements Importable { + + @ImportField(name="Facility Type Code", mandatory=true) private String code; + + @ImportField(name="Name", mandatory=true) private String name; + + @ImportField(name="Description") private String description; + private Integer levelId; + + @ImportField(name="Nominal Max Month", mandatory=true) private Integer nominalMaxMonth; + + @ImportField(name="Nominal EOP", mandatory=true) private Double nominalEop; + + @ImportField(name="Display Order", mandatory=true) private Integer displayOrder; + + @ImportField(name="Active", mandatory=true, type="boolean") private boolean active; public FacilityType(String code) { diff --git a/modules/core/src/main/java/org/openlmis/core/domain/GeographicLevel.java b/modules/core/src/main/java/org/openlmis/core/domain/GeographicLevel.java index 25e9283ddb..a13d4465b1 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/GeographicLevel.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/GeographicLevel.java @@ -16,6 +16,8 @@ import lombok.NoArgsConstructor; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; import static org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_EMPTY; @@ -28,10 +30,17 @@ @NoArgsConstructor @EqualsAndHashCode(callSuper = false) @JsonSerialize(include = NON_EMPTY) -public class GeographicLevel extends BaseModel { +public class GeographicLevel extends BaseModel implements Importable { + + @ImportField(name="Geographic Level Code", mandatory = true) String code; + + @ImportField(name="Name", mandatory = true) String name; + + @ImportField(name="Level Number", mandatory = true) Integer levelNumber; + private static Integer ROOT_LEVEL_NUMBER = 1; public GeographicLevel(Long id, String code, String name, Integer levelNumber) { diff --git a/modules/core/src/main/java/org/openlmis/core/domain/ProductForm.java b/modules/core/src/main/java/org/openlmis/core/domain/ProductForm.java index 602dc99476..567501d06c 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/ProductForm.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/ProductForm.java @@ -14,6 +14,9 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.openlmis.core.exception.DataException; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; /** * ProductForm represents real world entity for product form. @@ -22,7 +25,20 @@ @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class ProductForm extends BaseModel { +public class ProductForm extends BaseModel implements Importable { + @ImportField(name="Product Form Code", mandatory=true) private String code; - private int displayOrder; + + @ImportField(name="Display Order", mandatory=true) + private Integer displayOrder; + + /** + * Validates this product form. + * @throws DataException if this object is not well-formed. + */ + public void isValid() { + if (code == null + || code.length() == 0 + || displayOrder == null) throw new DataException("error.reference.data.missing"); + } } diff --git a/modules/core/src/main/java/org/openlmis/core/domain/Program.java b/modules/core/src/main/java/org/openlmis/core/domain/Program.java index b6131867af..1fbd8db075 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/Program.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/Program.java @@ -14,7 +14,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; import static org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_EMPTY; @@ -26,15 +29,28 @@ @NoArgsConstructor @EqualsAndHashCode(callSuper = false) @JsonSerialize(include = NON_EMPTY) -public class Program extends BaseModel { +public class Program extends BaseModel implements Importable { + @ImportField(name="Program Code", mandatory=true) private String code; + + @ImportField(name="Name", mandatory=true) private String name; + + @ImportField(name="Description") private String description; - private Boolean active; - private Boolean budgetingApplies; + + @ImportField(name="Active", mandatory=true, type="boolean") + private Boolean active = true; + + @ImportField(name="Budgeting Applies", type="boolean") + private Boolean budgetingApplies = false; + private boolean templateConfigured; + private boolean regimenTemplateConfigured; + + @ImportField(name="Push", mandatory=true, type="boolean") private boolean push; public Program(Long id) { diff --git a/modules/core/src/main/java/org/openlmis/core/domain/RegimenCategory.java b/modules/core/src/main/java/org/openlmis/core/domain/RegimenCategory.java index 8bbd1b57d5..d0e1d92aa0 100644 --- a/modules/core/src/main/java/org/openlmis/core/domain/RegimenCategory.java +++ b/modules/core/src/main/java/org/openlmis/core/domain/RegimenCategory.java @@ -14,6 +14,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.openlmis.upload.Importable; +import org.openlmis.upload.annotation.ImportField; /** * RegimenCategory represents category for a regimen (for eg. Adult or Child) @@ -22,10 +24,15 @@ @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class RegimenCategory extends BaseModel { +public class RegimenCategory extends BaseModel implements Importable { + @ImportField(name="Regimen Category Code", mandatory=true) private String code; + + @ImportField(name="Name", mandatory=true) private String name; + + @ImportField(name="Display Order", mandatory=true) private Integer displayOrder; } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/DosageUnitRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/DosageUnitRepository.java new file mode 100644 index 0000000000..7d0e6e7d15 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/DosageUnitRepository.java @@ -0,0 +1,55 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.DosageUnit; +import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.mapper.DosageUnitMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Repository; + +@Repository +@NoArgsConstructor +public class DosageUnitRepository { + + private DosageUnitMapper duMapper; + + @Autowired + public DosageUnitRepository(DosageUnitMapper dosageUnitMapper) { + this.duMapper = dosageUnitMapper; + } + + public DosageUnit getByCode(String code) { + return duMapper.getByCode(code); + } + + public DosageUnit getExisting(DosageUnit du) { + return duMapper.getByCode(du.getCode()); + } + + public void insert(DosageUnit du) { + du.isValid(); + if(getByCode(du.getCode()) != null) throw new DataException("error.duplicate.dosage.unit.code"); + + try { + duMapper.insert(du); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length", dive); + } + } + + public void update(DosageUnit du) { + duMapper.update(du); + } +} diff --git a/modules/core/src/main/java/org/openlmis/core/repository/FacilityOperatorRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/FacilityOperatorRepository.java new file mode 100644 index 0000000000..eeae5f85db --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/FacilityOperatorRepository.java @@ -0,0 +1,84 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.FacilityOperator; +import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.mapper.FacilityOperatorMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Repository for managing {@link org.openlmis.core.domain.FacilityOperator} entities and related operations. + */ +@Repository +@NoArgsConstructor +public class FacilityOperatorRepository { + private FacilityOperatorMapper facilityOperatorMapper; + + @Autowired + public FacilityOperatorRepository(FacilityOperatorMapper facilityOperatorMapper) { + this.facilityOperatorMapper = facilityOperatorMapper; + } + + /** + * Gets the FacilityOperator that has the given code. + * @param code the code, case insensitive + * @return the FacilityOperator with the given code or null if no such FacilityOperator exists with the given code. + */ + public FacilityOperator getByCode(String code) { + if(code == null) return null; + return facilityOperatorMapper.getByCode(code); + } + + /** + * Saves a FacilityOperator entity to persistent storage. If + * {@link org.openlmis.core.domain.FacilityOperator#hasId()} is true, then the id will be used to + * update the existing entity, otherwise a new one will be created. + * @param facilityOperator the FacilityOperator to save. + * @throws org.openlmis.core.exception.DataException if unable to save entity. + * @throws java.lang.NullPointerException if facilityOperator is null. + */ + public void save(FacilityOperator facilityOperator) { + if(facilityOperator == null) throw new NullPointerException("facilityOperator argument is null"); + + try { + if(facilityOperator.hasId()) facilityOperatorMapper.update(facilityOperator); + else facilityOperatorMapper.insert(facilityOperator); + } catch(DuplicateKeyException dke) { + throw new DataException("error.duplicate.facility.operator.code"); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length"); + } + } + + /** + * Gets the FacilityOperator by it's persistence id. + * @param id the id of the FacilityOperator to find + * @return the FacilityOperator with the given id or null if no such FacilityOperator exists with given id. + */ + public FacilityOperator getById(long id) { + return facilityOperatorMapper.getById(id); + } + + /** + * Gets all the FacilityOperators in descending order by their display order. + * @return a list of all persisted FacilityOperator entities. + */ + public List getAll() { + return facilityOperatorMapper.getAll(); + } +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/openlmis/core/repository/FacilityRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/FacilityRepository.java index 22ef09de83..4d830fbba1 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/FacilityRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/FacilityRepository.java @@ -33,15 +33,28 @@ @NoArgsConstructor public class FacilityRepository { - @Autowired private FacilityMapper mapper; + private FacilityTypeRepository facilityTypeRepository; + @Autowired private CommaSeparator commaSeparator; - @Autowired private GeographicZoneRepository geographicZoneRepository; + private FacilityOperatorRepository facilityOperatorRepository; + + @Autowired + public FacilityRepository(FacilityMapper facilityMapper, + FacilityTypeRepository facilityTypeRepository, + GeographicZoneRepository geographicZoneRepository, + FacilityOperatorRepository facilityOperatorRepository) { + this.mapper = facilityMapper; + this.facilityTypeRepository = facilityTypeRepository; + this.geographicZoneRepository = geographicZoneRepository; + this.facilityOperatorRepository = facilityOperatorRepository; + } + public void save(Facility facility) { try { validateAndSetFacilityOperatedBy(facility); @@ -89,7 +102,7 @@ private void validateAndSetFacilityType(Facility facility) { throw new DataException("error.reference.data.facility.type.missing"); String facilityTypeCode = facilityType.getCode(); - FacilityType existingFacilityType = mapper.getFacilityTypeForCode(facilityTypeCode); + FacilityType existingFacilityType = facilityTypeRepository.getByCode(facilityTypeCode); if (existingFacilityType == null) throw new DataException("error.reference.data.invalid.facility.type"); @@ -107,15 +120,7 @@ private void validateAndSetFacilityOperatedBy(Facility facility) { if (operatedById == null) throw new DataException("error.reference.data.invalid.operated.by"); - facility.setOperatedBy(mapper.getFacilityOperatorById(operatedById)); - } - - public List getAllTypes() { - return mapper.getAllTypes(); - } - - public List getAllOperators() { - return mapper.getAllOperators(); + facility.setOperatedBy(facilityOperatorRepository.getById(operatedById)); } public Facility getHomeFacility(Long userId) { @@ -153,13 +158,6 @@ public Facility getHomeFacilityForRights(Long userId, String... rightNames) { return mapper.getHomeFacilityWithRights(userId, commaSeparateRightNames(rightNames)); } - public FacilityType getFacilityTypeByCode(FacilityType facilityType) { - facilityType = mapper.getFacilityTypeForCode(facilityType.getCode()); - if (facilityType == null) { - throw new DataException("error.facility.type.code.invalid"); - } - return facilityType; - } public Facility getByCode(String code) { return mapper.getByCode(code); diff --git a/modules/core/src/main/java/org/openlmis/core/repository/FacilityTypeRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/FacilityTypeRepository.java new file mode 100644 index 0000000000..af85753711 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/FacilityTypeRepository.java @@ -0,0 +1,97 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.Facility; +import org.openlmis.core.domain.FacilityType; +import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.mapper.FacilityTypeMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Repository for managing persistence of {@link org.openlmis.core.domain.FacilityType} entities and related operations. + */ +@Repository +@NoArgsConstructor +public class FacilityTypeRepository { + + public static final String ERROR_FACILITY_TYPE_CODE_INVALID = "error.facility.type.code.invalid"; + + private FacilityTypeMapper mapper; + + @Autowired + public FacilityTypeRepository(FacilityTypeMapper facilityTypeMapper) { + this.mapper = facilityTypeMapper; + } + + /** + * Gets a FacilityType by it's associated code. + * @param code the code of the FacilityType. + * @return the FacilityType with the given code or null if no FacilityType exists with the given code. + */ + public FacilityType getByCode(String code) { + if(code == null) return null; + return mapper.getByCode(code); + } + + /** + * Gets a FacilityType by it's associated code, will throw an exception if no such code exists. + * @param code the code to find by + * @return the FacilityType with the given code + * @throws DataException if no such code exists. + */ + public FacilityType getByCodeOrThrowException(String code) throws DataException { + FacilityType facType = getByCode(code); + if(facType == null) throw new DataException(ERROR_FACILITY_TYPE_CODE_INVALID); + return facType; + } + + /** + * Gets all persisted FacilityType entities ordered by display order (ascending) and then name. + * @return all FacilityType entities. + */ + public List getAll() { + return mapper.getAll(); + } + + /** + * Saves the given FacilityType to persistent storage. + * @param facilityType the FacilityType to save. + * @throws java.lang.NullPointerException if facilityType is null. + * @throws DataException if unable to save facilityType. + */ + public void save(FacilityType facilityType) { + if(facilityType == null) throw new NullPointerException("FacilityType argument is null"); + + try { + if(facilityType.hasId()) mapper.update(facilityType); + else mapper.insert(facilityType); + } catch(DuplicateKeyException dke) { + throw new DataException("error.duplicate.facility.type", dke); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length", dive); + } + } + + public FacilityType getFacilityTypeByCode(FacilityType facilityType) { + facilityType = mapper.getByCode(facilityType.getCode()); + if (facilityType == null) { + throw new DataException("error.facility.type.code.invalid"); + } + return facilityType; + } +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/openlmis/core/repository/GeographicLevelRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/GeographicLevelRepository.java new file mode 100644 index 0000000000..98f5c75a50 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/GeographicLevelRepository.java @@ -0,0 +1,64 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.GeographicLevel; +import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.mapper.GeographicLevelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Repository for managing persistent storage/retrieval of {@link org.openlmis.core.domain.GeographicLevel} entities. + */ +@Repository +@NoArgsConstructor +public class GeographicLevelRepository { + private GeographicLevelMapper mapper; + + @Autowired + public GeographicLevelRepository(GeographicLevelMapper mapper) { + this.mapper = mapper; + } + + public int getLowestGeographicLevel() {return mapper.getLowestGeographicLevel();} + + public GeographicLevel getGeographicLevelByCode(String code) {return mapper.getGeographicLevelByCode(code);} + + public List getAll() {return mapper.getAll();} + + public GeographicLevel getByCode(String code) {return mapper.getByCode(code);} + + /** + * Saves the given {@link org.openlmis.core.domain.GeographicLevel}. If the GeographicLevel already exists, + * then it will attempt to update it. + * @param geographicLevel the geographic level to save. + * @throws DataException if unable - malformed or attempting to save a new geographic level with a duplicate identity. + * i.e. {@link #getByCode(String)} is not null. + */ + public void save(GeographicLevel geographicLevel) { + try { + if(geographicLevel.hasId()) + mapper.update(geographicLevel); + else + mapper.insert(geographicLevel); + } catch(DuplicateKeyException dke) { + throw new DataException("error.duplicate.geographic.level.code"); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length"); + } + } +} diff --git a/modules/core/src/main/java/org/openlmis/core/repository/GeographicZoneRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/GeographicZoneRepository.java index e464e99936..800aa58c06 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/GeographicZoneRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/GeographicZoneRepository.java @@ -15,7 +15,6 @@ import org.openlmis.core.domain.GeographicZone; import org.openlmis.core.domain.Pagination; import org.openlmis.core.exception.DataException; -import org.openlmis.core.repository.mapper.GeographicLevelMapper; import org.openlmis.core.repository.mapper.GeographicZoneMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; @@ -33,12 +32,12 @@ public class GeographicZoneRepository { private GeographicZoneMapper mapper; - private GeographicLevelMapper geographicLevelMapper; + private GeographicLevelRepository geographicLevelRepository; @Autowired - public GeographicZoneRepository(GeographicZoneMapper mapper, GeographicLevelMapper geographicLevelMapper) { + public GeographicZoneRepository(GeographicZoneMapper mapper, GeographicLevelRepository geographicLevelRepository) { this.mapper = mapper; - this.geographicLevelMapper = geographicLevelMapper; + this.geographicLevelRepository = geographicLevelRepository; } public GeographicZone getByCode(String code) { @@ -46,7 +45,7 @@ public GeographicZone getByCode(String code) { } public Integer getLowestGeographicLevel() { - return geographicLevelMapper.getLowestGeographicLevel(); + return geographicLevelRepository.getLowestGeographicLevel(); } public List getAllGeographicZones() { @@ -67,10 +66,6 @@ public void save(GeographicZone zone) { } } - public GeographicLevel getGeographicLevelByCode(String code) { - return mapper.getGeographicLevelByCode(code); - } - public GeographicZone getById(Long id) { return mapper.getWithParentById(id); } @@ -84,7 +79,7 @@ public List searchByName(String searchParam, Pagination paginati } public List getAllGeographicLevels() { - return geographicLevelMapper.getAll(); + return geographicLevelRepository.getAll(); } public List getAllGeographicZonesAbove(GeographicLevel geographicLevel) { diff --git a/modules/core/src/main/java/org/openlmis/core/repository/ProductFormRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/ProductFormRepository.java index ff1fe61397..b829a1fd13 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/ProductFormRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/ProductFormRepository.java @@ -12,28 +12,66 @@ import lombok.NoArgsConstructor; import org.openlmis.core.domain.ProductForm; +import org.openlmis.core.exception.DataException; import org.openlmis.core.repository.mapper.ProductFormMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Repository; import java.util.List; /** - * ProductFormRepository is Repository class for ProductForm related database operations. + * Repository relating to persisting {@link org.openlmis.core.domain.ProductForm} entities. */ - @Repository @NoArgsConstructor public class ProductFormRepository { @Autowired - ProductFormMapper mapper; + private ProductFormMapper pfMapper; + + ProductFormRepository(ProductFormMapper productFormMapper) {this.pfMapper = productFormMapper;} + + /** + * Gets existing {@link org.openlmis.core.domain.ProductForm} by it's code. + * @param code the ProductForm's code. + * @return The ProductForm that has that code, or null if no such ProductForm + * exists with the given code. + */ + public ProductForm getByCode(String code) {return pfMapper.getByCode(code);} + /** + * Insert a new {@link org.openlmis.core.domain.ProductForm}. + * @param pf {@link org.openlmis.core.domain.ProductForm} to insert. + * @throws DataException if entity is invalid or already exists. + */ + public void insert(ProductForm pf) { + pf.isValid(); + if(getByCode(pf.getCode()) != null) throw new DataException("error.duplicate.dosage.unit.code"); + + try { + pfMapper.insert(pf); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length", dive); + } + } + public List getAll() { - return mapper.getAll(); + return pfMapper.getAll(); } - public ProductForm getByCode(String code) { - return mapper.getByCode(code); + /** + * Updates an existing {@link org.openlmis.core.domain.ProductForm}. + * @param pf {@link org.openlmis.core.domain.ProductForm} to update. + * @throws DataException if entity is invalid. + */ + public void update(ProductForm pf) { + pf.isValid(); + + try { + pfMapper.update(pf); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length", dive); + } } -} +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/openlmis/core/repository/ProgramRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/ProgramRepository.java index 74fc0fae54..eec35e45d6 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/ProgramRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/ProgramRepository.java @@ -39,6 +39,14 @@ public ProgramRepository(ProgramMapper programMapper) { this.mapper = programMapper; } + public void insert(Program p) { + mapper.insert(p); + } + + public void update(Program p) { + mapper.update(p); + } + public List getByFacility(Long facilityId) { return mapper.getByFacilityId(facilityId); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/RegimenCategoryRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/RegimenCategoryRepository.java new file mode 100644 index 0000000000..5faa875d12 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/RegimenCategoryRepository.java @@ -0,0 +1,70 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.RegimenCategory; +import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.mapper.RegimenCategoryMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@NoArgsConstructor +public class RegimenCategoryRepository { + private RegimenCategoryMapper mapper; + + @Autowired + public RegimenCategoryRepository(RegimenCategoryMapper regimenCategoryMapper) { + this.mapper = regimenCategoryMapper; + } + + /** + * Gets a list of all stored RegimenCategory entities. + * @return an sorted list by display order and then name, ascending. + */ + public List getAll() { + return mapper.getAll(); + } + + /** + * Finds a stored RegimenCategory with the given code. + * @param code the code to find by, case insensitive + * @return the RegimenCategory with the given code, or null if no such code exists. + */ + public RegimenCategory getByCode(String code) { + if(code == null) return null; + return mapper.getByCode(code); + } + + /** + * Saves the given RegimenCategory entity if possible. + * @param regimenCategory the RegimenCategory to save. + * @throws java.lang.NullPointerException if regimenCategory is null. + * @throws org.openlmis.core.exception.DataException if unable to save. + */ + public void save(RegimenCategory regimenCategory) { + if(regimenCategory == null) throw new NullPointerException("RegimenCategory argument is null"); + + try { + if(regimenCategory.hasId()) mapper.update(regimenCategory); + else mapper.insert(regimenCategory); + } catch (DuplicateKeyException dke) { + throw new DataException("error.duplicate.regimen.category", dke); + } catch(DataIntegrityViolationException dive) { + throw new DataException("error.incorrect.length", dive); + } + } +} diff --git a/modules/core/src/main/java/org/openlmis/core/repository/RegimenRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/RegimenRepository.java index 6359af8dc2..faededc069 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/RegimenRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/RegimenRepository.java @@ -36,10 +36,6 @@ public List getByProgram(Long programId) { return mapper.getByProgram(programId); } - public List getAllRegimenCategories() { - return regimenCategoryMapper.getAll(); - } - public void save(List regimens, Long userId) { for (Regimen regimen : regimens) { regimen.setModifiedBy(userId); diff --git a/modules/core/src/main/java/org/openlmis/core/repository/UserRepository.java b/modules/core/src/main/java/org/openlmis/core/repository/UserRepository.java index 88ebced5ee..025ae75c9d 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/UserRepository.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/UserRepository.java @@ -137,10 +137,6 @@ public void insertEmailNotification(SimpleMailMessage emailMessage) { userMapper.insertEmailNotification(emailMessage.getTo()[0], emailMessage.getSubject(), emailMessage.getText()); } - public void updateUserPassword(Long userId, String password) { - userMapper.updateUserPassword(userId, password); - } - public void disable(Long userId, Long modifiedBy) { userMapper.disable(userId, modifiedBy); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/DosageUnitMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/DosageUnitMapper.java index 32388a8327..1525efd146 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/DosageUnitMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/DosageUnitMapper.java @@ -10,7 +10,10 @@ package org.openlmis.core.repository.mapper; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import org.openlmis.core.domain.DosageUnit; import org.springframework.stereotype.Repository; @@ -22,10 +25,26 @@ @Repository public interface DosageUnitMapper { - // Used by mapper + @Insert({"INSERT INTO dosage_units", + "(code, displayOrder, createdBy, createdDate, modifiedBy, modifiedDate)", + "VALUES", + "(#{code}, #{displayOrder}, #{createdBy}, NOW(), #{modifiedBy}, NOW())"}) + @Options(useGeneratedKeys = true) + void insert(DosageUnit dosageUnit); + + @Update({"UPDATE dosage_units SET code = #{code},", + "displayOrder = #{displayOrder},", + "modifiedBy=#{modifiedBy},", + "modifiedDate=NOW()", + "WHERE id = #{id}"}) + void update(DosageUnit dosageUnit); + @Select("SELECT * FROM dosage_units WHERE id = #{id}") DosageUnit getById(Long id); @Select("SELECT * FROM dosage_units") List getAll(); + + @Select("SELECT * FROM dosage_units WHERE LOWER(code) = LOWER(#{code})") + DosageUnit getByCode(String code); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityMapper.java index d8977c6262..82c4654f24 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityMapper.java @@ -13,8 +13,6 @@ import org.apache.ibatis.annotations.*; import org.apache.ibatis.session.RowBounds; import org.openlmis.core.domain.Facility; -import org.openlmis.core.domain.FacilityOperator; -import org.openlmis.core.domain.FacilityType; import org.springframework.stereotype.Repository; import java.util.Date; @@ -55,22 +53,6 @@ public interface FacilityMapper { @Results(value = {@Result(property = "id", column = "facilityId")}) Facility getHomeFacility(Long userId); - @Select("SELECT * FROM facility_types ORDER BY displayOrder NULLS LAST, LOWER(name)") - List getAllTypes(); - - @Select("SELECT * FROM facility_types WHERE id = #{id}") - public FacilityType getFacilityTypeById(Long id); - - @Select("SELECT * FROM facility_operators ORDER BY displayOrder") - List getAllOperators(); - - @Select("SELECT * FROM facility_operators WHERE id = #{id}") - public FacilityOperator getFacilityOperatorById(Long id); - - @Select("SELECT code FROM facility_operators WHERE id = #{id}") - @SuppressWarnings("unused") - public String getFacilityOperatorCodeFor(Long id); - @Select("SELECT id FROM facility_operators WHERE LOWER(code) = LOWER(#{code})") Long getOperatedByIdForCode(String code); @@ -79,9 +61,9 @@ public interface FacilityMapper { @Result(property = "geographicZone", column = "geographicZoneId", javaType = Long.class, one = @One(select = "org.openlmis.core.repository.mapper.GeographicZoneMapper.getWithParentById")), @Result(property = "facilityType", column = "typeId", javaType = Long.class, - one = @One(select = "getFacilityTypeById")), + one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")), @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, - one = @One(select = "getFacilityOperatorById")) + one = @One(select = "org.openlmis.core.repository.mapper.FacilityOperatorMapper.getById")) }) Facility getById(Long id); @@ -94,9 +76,9 @@ public interface FacilityMapper { @Result(property = "geographicZone", column = "geographicZoneId", javaType = Long.class, one = @One(select = "org.openlmis.core.repository.mapper.GeographicZoneMapper.getWithParentById")), @Result(property = "facilityType", column = "typeId", javaType = Long.class, - one = @One(select = "getFacilityTypeById")), + one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")), @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, - one = @One(select = "getFacilityOperatorById")), + one = @One(select = "org.openlmis.core.repository.mapper.FacilityOperatorMapper.getById")), @Result(property = "supportedPrograms", column = "id", javaType = List.class, many = @Many(select = "org.openlmis.core.repository.mapper.ProgramSupportedMapper.getAllByFacilityId")) }) @@ -116,9 +98,6 @@ public interface FacilityMapper { "comment = #{comment}, enabled = #{enabled}, modifiedBy = #{modifiedBy}, modifiedDate = (COALESCE(#{modifiedDate}, NOW())) WHERE id=#{id}") void update(Facility facility); - @Select("SELECT * FROM facility_types WHERE LOWER(code) = LOWER(#{code})") - FacilityType getFacilityTypeForCode(String facilityTypeCode); - @Update({"UPDATE facilities SET enabled = #{enabled}, active=#{active}, " + "modifiedBy=#{modifiedBy}, modifiedDate = NOW() WHERE id =#{id}"}) void updateEnabledAndActiveFor(Facility facility); @@ -139,9 +118,9 @@ public interface FacilityMapper { @Results(value = { @Result(property = "geographicZone.id", column = "geographicZoneId"), @Result(property = "facilityType", column = "typeId", javaType = Long.class, - one = @One(select = "getFacilityTypeById")), + one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")), @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, - one = @One(select = "getFacilityOperatorById")) + one = @One(select = "org.openlmis.core.repository.mapper.FacilityOperatorMapper.getById")) }) List getFacilitiesBy(@Param(value = "programId") Long programId, @Param(value = "requisitionGroupIds") String requisitionGroupIds); @@ -151,8 +130,8 @@ List getFacilitiesBy(@Param(value = "programId") Long programId, "WHERE U.id = #{userId} AND RR.rightName = ANY(#{commaSeparatedRights}::VARCHAR[]) AND RA.supervisoryNodeId IS NULL"}) @Results(value = { @Result(property = "geographicZone.id", column = "geographicZoneId"), - @Result(property = "facilityType", column = "typeId", javaType = Long.class, one = @One(select = "getFacilityTypeById")), - @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, one = @One(select = "getFacilityOperatorById")) + @Result(property = "facilityType", column = "typeId", javaType = Long.class, one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")), + @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, one = @One(select = "org.openlmis.core.repository.mapper.FacilityOperatorMapper.getById")) }) Facility getHomeFacilityWithRights(@Param("userId") Long userId, @Param("commaSeparatedRights") String commaSeparatedRights); @@ -163,9 +142,9 @@ Facility getHomeFacilityWithRights(@Param("userId") Long userId, @Results(value = { @Result(property = "geographicZone.id", column = "geographicZoneId"), @Result(property = "facilityType", column = "typeId", javaType = Long.class, - one = @One(select = "getFacilityTypeById")), + one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")), @Result(property = "operatedBy", column = "operatedById", javaType = Long.class, - one = @One(select = "getFacilityOperatorById")) + one = @One(select = "org.openlmis.core.repository.mapper.FacilityOperatorMapper.getById")) }) List getAllInRequisitionGroups(@Param("requisitionGroupIds") String requisitionGroupIds); @@ -200,7 +179,7 @@ List getAllInDeliveryZoneFor(@Param("deliveryZoneId") Long deliveryZon @Results(value = { @Result(property = "geographicZone.id", column = "geographicZoneId"), @Result(property = "facilityType", column = "typeId", javaType = Long.class, - one = @One(select = "getFacilityTypeById")) + one = @One(select = "org.openlmis.core.repository.mapper.FacilityTypeMapper.getById")) }) List getChildFacilities(Facility facility); diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityOperatorMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityOperatorMapper.java new file mode 100644 index 0000000000..86f434d4c8 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityOperatorMapper.java @@ -0,0 +1,56 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository.mapper; + +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.openlmis.core.domain.FacilityOperator; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface FacilityOperatorMapper { + + @Insert({"INSERT INTO facility_operators (code" + , ", text" + , ", displayOrder" + , ", createdBy" + , ", createdDate" + , ", modifiedBy" + , ", modifiedDate" + , ") VALUES (#{code}" + , ", #{text}" + , ", #{displayOrder}" + , ", #{createdBy}" + , ", NOW()" + , ", #{modifiedBy}" + , ", NOW() )"}) + void insert(FacilityOperator facilityOperator); + + @Update({"UPDATE facility_operators SET code = #{code}" + , ", text = #{text}" + , ", displayOrder = #{displayOrder}" + , ", modifiedBy = #{modifiedBy}" + , ", modifiedDate = NOW()" + , "WHERE id = #{id}"}) + void update(FacilityOperator facilityOperator); + + @Select("SELECT * FROM facility_operators WHERE LOWER(code) = LOWER(#{code})") + FacilityOperator getByCode(String code); + + @Select("SELECT * FROM facility_operators ORDER BY displayOrder") + List getAll(); + + @Select("SELECT * FROM facility_operators WHERE id = #{id}") + FacilityOperator getById(Long id); +} \ No newline at end of file diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityTypeMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityTypeMapper.java new file mode 100644 index 0000000000..26a54fd235 --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/FacilityTypeMapper.java @@ -0,0 +1,72 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository.mapper; + +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.openlmis.core.domain.FacilityType; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface FacilityTypeMapper { + + @Select("SELECT * FROM facility_types WHERE LOWER(code) = LOWER(#{lower})") + FacilityType getByCode(String code); + + @Select("SELECT * FROM facility_types WHERE id = #{id}") + public FacilityType getById(Long id); + + @Insert({"INSERT INTO facility_types (code" + , ", name" + , ", description" + , ", levelId" + , ", nominalMaxMonth" + , ", nominalEop" + , ", displayOrder" + , ", active" + , ", createdBy" + , ", createdDate" + , ", modifiedBy" + , ", modifiedDate" + , ") VALUES (#{code}" + , ", #{name}" + , ", #{description}" + , ", #{levelId}" + , ", #{nominalMaxMonth}" + , ", #{nominalEop}" + , ", #{displayOrder}" + , ", #{active}" + , ", #{createdBy}" + , ", NOW()" + , ", #{modifiedBy}" + , ", NOW()" + , ")"}) + void insert(FacilityType facilityType); + + @Update({"UPDATE facility_types SET code = #{code}" + , ", name = #{name}" + , ", description = #{description}" + , ", levelId = #{levelId}" + , ", nominalMaxMonth = #{nominalMaxMonth}" + , ", nominalEop = #{nominalEop}" + , ", displayOrder = #{displayOrder}" + , ", active = #{active}" + , ", modifiedBy = #{modifiedBy}" + , ", modifiedDate = NOW()" + , "WHERE id = #{id}"}) + void update(FacilityType facilityType); + + @Select("SELECT * FROM facility_types ORDER BY displayOrder NULLS LAST, LOWER(name)") + List getAll(); +} diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicLevelMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicLevelMapper.java index 9633c9518b..254871cba1 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicLevelMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicLevelMapper.java @@ -10,7 +10,9 @@ package org.openlmis.core.repository.mapper; +import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import org.openlmis.core.domain.GeographicLevel; import org.springframework.stereotype.Repository; @@ -28,4 +30,34 @@ public interface GeographicLevelMapper { @Select("SELECT * FROM geographic_levels ORDER BY levelNumber") List getAll(); + + @Select("SELECT * FROM geographic_levels WHERE LOWER(code) = LOWER(#{code})") + GeographicLevel getByCode(String code); + + @Select("SELECT * FROM geographic_levels WHERE LOWER(code) = LOWER(#{code})") + GeographicLevel getGeographicLevelByCode(String code); + + @Insert({"INSERT INTO geographic_levels (code" + , ", name" + , ", levelNumber" + , ", createdBy" + , ", createdDate" + , ", modifiedBy" + , ", modifiedDate)" + , "VALUES (#{code}" + , ", #{name}" + , ", #{levelNumber}" + , ", #{createdBy}" + , ", NOW()" + , ", #{modifiedBy}" + , ", NOW())"}) + void insert(GeographicLevel geographicLevel); + + @Update({"UPDATE geographic_levels SET code = #{code}" + , ", name = #{name}" + , ", levelNumber = #{levelNumber}" + , ", modifiedBy = #{modifiedBy}" + , ", modifiedDate = #{modifiedDate}" + , "WHERE LOWER(code) = LOWER(#{code})"}) + void update(GeographicLevel geographicLevel); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicZoneMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicZoneMapper.java index 15c93fb90c..b053901f0c 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicZoneMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/GeographicZoneMapper.java @@ -35,9 +35,6 @@ public interface GeographicZoneMapper { @Options(useGeneratedKeys = true) Integer insert(GeographicZone geographicZone); - @Select("SELECT * FROM geographic_levels WHERE LOWER(code) = LOWER(#{code})") - GeographicLevel getGeographicLevelByCode(String code); - @Select({"SELECT GZ.id, GZ.code, GZ.name, GL.id AS levelId, GL.code AS levelCode, GL.name AS levelName, GL.levelNumber AS levelNumber ", "FROM geographic_zones GZ, geographic_levels GL ", "WHERE GZ.levelId = GL.id AND LOWER(GZ.code) <> 'root' AND ", diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProductFormMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProductFormMapper.java index 6ff8d160f6..868a3d0366 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProductFormMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProductFormMapper.java @@ -10,7 +10,10 @@ package org.openlmis.core.repository.mapper; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import org.openlmis.core.domain.ProductForm; import org.springframework.stereotype.Repository; @@ -29,7 +32,21 @@ public interface ProductFormMapper { @Select("SELECT * FROM product_forms") List getAll(); - + @Select("SELECT * FROM product_forms WHERE LOWER(code) = LOWER(#{code})") ProductForm getByCode(String code); + + @Insert({"INSERT INTO product_forms", + "(code, displayOrder, createdBy, createdDate, modifiedBy, modifiedDate)", + "VALUES", + "(#{code}, #{displayOrder}, #{createdBy}, NOW(), #{modifiedBy}, NOW())"}) + @Options(useGeneratedKeys = true) + void insert(ProductForm productForm); + + @Update({"UPDATE product_forms SET code = #{code},", + "displayOrder = #{displayOrder},", + "modifiedBy=#{modifiedBy},", + "modifiedDate=NOW()", + "WHERE id = #{id}"}) + void update(ProductForm productForm); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProgramMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProgramMapper.java index e5b1d438c9..bf6172eb1c 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProgramMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/ProgramMapper.java @@ -24,11 +24,35 @@ @Repository public interface ProgramMapper { - @Insert({"INSERT INTO programs(code, name, description, active, push)", - "VALUES (#{code}, #{name}, #{description}, #{active}, #{push})"}) + @Insert({"INSERT INTO programs(code" + , ", name" + , ", description" + , ", active" + , ", budgetingApplies" + , ", templateConfigured" + , ", regimenTemplateConfigured, push)" + , " VALUES (#{code}" + , ", #{name}" + , ", #{description}" + , ", #{active}" + , ", #{budgetingApplies}" + , ", #{templateConfigured}" + , ", #{regimenTemplateConfigured}" + , ", #{push})"}) @Options(useGeneratedKeys = true) Integer insert(Program program); + @Update({"UPDATE programs SET name = #{name}" + , ", code = #{code}" + , ", description = #{description}" + , ", active = #{active}" + , ", budgetingApplies = #{budgetingApplies}" + , ", templateConfigured = #{templateConfigured}" + , ", regimenTemplateConfigured = #{regimenTemplateConfigured}" + , ", push = #{push}" + , " WHERE id = #{id}"}) + void update(Program p); + @Select({"SELECT P.*", "FROM programs P, programs_supported PS", "WHERE P.id = PS.programId AND", @@ -117,13 +141,9 @@ List getProgramsForUserByFacilityAndRights(@Param("facilityId") Long fa @Select("SELECT * FROM programs ORDER BY templateConfigured DESC, name") List getAll(); - @Select("SELECT * FROM programs WHERE LOWER(code) = LOWER(#{code})") Program getByCode(String code); - @Select("SELECT * FROM programs ORDER BY regimenTemplateConfigured DESC, name") - List getAllByRegimenTemplate(); - @Update("UPDATE programs SET regimenTemplateConfigured = true WHERE id = #{id}") void setRegimenTemplateConfigured(Long id); diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/RegimenCategoryMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/RegimenCategoryMapper.java index fda06b5bfc..700b8b5f42 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/RegimenCategoryMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/RegimenCategoryMapper.java @@ -10,7 +10,9 @@ package org.openlmis.core.repository.mapper; +import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import org.openlmis.core.domain.RegimenCategory; import org.springframework.stereotype.Repository; @@ -27,4 +29,31 @@ public interface RegimenCategoryMapper { @Select({"SELECT * FROM regimen_categories WHERE id = #{id}"}) RegimenCategory getById(Long id); + + @Select("SELECT * FROM regimen_categories WHERE LOWER(code) = LOWER(#{code})") + RegimenCategory getByCode(String code); + + @Insert({"INSERT INTO regimen_categories (code" + , ", name" + , ", displayOrder" + , ", createdBy" + , ", createdDate" + , ", modifiedBy" + , ", modifiedDate" + , ") VALUES ( #{code}" + , ", #{name}" + , ", #{displayOrder}" + , ", #{createdBy}" + , ", NOW()" + , ", #{modifiedBy}" + , ", NOW())"}) + void insert(RegimenCategory regimenCategory); + + @Update({"UPDATE regimen_categories SET code = #{code}" + , ", name = #{name}" + , ", displayOrder = #{displayOrder}" + , ", modifiedBy = #{modifiedBy}" + , ", modifiedDate = NOW()" + , "WHERE id = #{id}"}) + void update(RegimenCategory regimenCategory); } diff --git a/modules/core/src/main/java/org/openlmis/core/repository/mapper/UserMapper.java b/modules/core/src/main/java/org/openlmis/core/repository/mapper/UserMapper.java index c437970bfa..74fb6a9a25 100644 --- a/modules/core/src/main/java/org/openlmis/core/repository/mapper/UserMapper.java +++ b/modules/core/src/main/java/org/openlmis/core/repository/mapper/UserMapper.java @@ -86,10 +86,6 @@ List getUsersWithRightInNodeForProgram(@Param("program") Program program, int insertEmailNotification(@Param(value = "receiver") String receiver, @Param(value = "subject") String subject, @Param(value = "content") String content); - @Update("UPDATE users SET password = #{password} WHERE id = #{userId}") - void updateUserPassword(@Param(value = "userId") Long userId, @Param(value = "password") String password); - - @Update("UPDATE users SET active = FALSE, modifiedBy = #{modifiedBy}, modifiedDate = NOW() WHERE id = #{userId}") void disable(@Param(value = "userId") Long userId, @Param(value = "modifiedBy") Long modifiedBy); diff --git a/modules/core/src/main/java/org/openlmis/core/service/DosageUnitService.java b/modules/core/src/main/java/org/openlmis/core/service/DosageUnitService.java new file mode 100644 index 0000000000..c5b07a730b --- /dev/null +++ b/modules/core/src/main/java/org/openlmis/core/service/DosageUnitService.java @@ -0,0 +1,39 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.service; + +import lombok.NoArgsConstructor; +import org.openlmis.core.domain.DosageUnit; +import org.openlmis.core.repository.DosageUnitRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +@Service +@NoArgsConstructor +public class DosageUnitService { + + private DosageUnitRepository duRep; + + @Autowired + public DosageUnitService(DosageUnitRepository dosageUnitRepository) { + this.duRep = dosageUnitRepository; + } + + public DosageUnit getExisting(DosageUnit du) { + return duRep.getExisting(du); + } + + public void save(DosageUnit du) { + if( du.hasId() ) duRep.update(du); + else duRep.insert(du); + } +} diff --git a/modules/core/src/main/java/org/openlmis/core/service/FacilityService.java b/modules/core/src/main/java/org/openlmis/core/service/FacilityService.java index 32c1502daa..728c624ce0 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/FacilityService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/FacilityService.java @@ -21,6 +21,7 @@ import org.openlmis.core.dto.FacilityFeedDTO; import org.openlmis.core.exception.DataException; import org.openlmis.core.repository.FacilityRepository; +import org.openlmis.core.repository.FacilityTypeRepository; import org.openlmis.core.repository.GeographicZoneRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -47,6 +48,9 @@ public class FacilityService { @Autowired private FacilityRepository facilityRepository; + @Autowired + private FacilityTypeRepository facilityTypeRepository; + @Autowired private ProgramSupportedService programSupportedService; @@ -71,11 +75,7 @@ public void update(Facility facility) { } public List getAllTypes() { - return facilityRepository.getAllTypes(); - } - - public List getAllOperators() { - return facilityRepository.getAllOperators(); + return facilityTypeRepository.getAll(); } public List getAllZones() { @@ -158,7 +158,7 @@ public List getForUserAndRights(Long userId, String... rightNames) { } public FacilityType getFacilityTypeByCode(FacilityType facilityType) { - return facilityRepository.getFacilityTypeByCode(facilityType); + return facilityTypeRepository.getByCodeOrThrowException(facilityType.getCode()); } public Facility getByCode(Facility facility) { diff --git a/modules/core/src/main/java/org/openlmis/core/service/GeographicZoneService.java b/modules/core/src/main/java/org/openlmis/core/service/GeographicZoneService.java index fedb7e8d31..11804ccfe9 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/GeographicZoneService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/GeographicZoneService.java @@ -14,6 +14,7 @@ import org.openlmis.core.domain.GeographicLevel; import org.openlmis.core.domain.GeographicZone; import org.openlmis.core.domain.Pagination; +import org.openlmis.core.repository.GeographicLevelRepository; import org.openlmis.core.repository.GeographicZoneRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -36,6 +37,9 @@ public class GeographicZoneService { @Autowired GeographicZoneRepository repository; + @Autowired + GeographicLevelRepository geoLevelRepo; + @Autowired public void setPageSize(@Value("${search.page.size}") String pageSize) { this.pageSize = Integer.parseInt(pageSize); @@ -43,7 +47,7 @@ public void setPageSize(@Value("${search.page.size}") String pageSize) { public void save(GeographicZone geographicZone) { geographicZone.validateMandatoryFields(); - geographicZone.setLevel(repository.getGeographicLevelByCode(geographicZone.getLevel().getCode())); + geographicZone.setLevel(geoLevelRepo.getGeographicLevelByCode(geographicZone.getLevel().getCode())); geographicZone.validateLevel(); if (!geographicZone.isRootLevel()) { diff --git a/modules/core/src/main/java/org/openlmis/core/service/ProductFormService.java b/modules/core/src/main/java/org/openlmis/core/service/ProductFormService.java index 1410682780..a84bdaffeb 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/ProductFormService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/ProductFormService.java @@ -20,19 +20,22 @@ import java.util.List; /** - * Exposes the services for handling ProductForm entity. + * Service responsible for managing {@link org.openlmis.core.domain.ProductForm} entities. */ - @Service @NoArgsConstructor public class ProductFormService { - @Autowired private ProductFormRepository repository; + @Autowired + public ProductFormService(ProductFormRepository productFormRepository) {repository = productFormRepository;} + public List getAll() { return repository.getAll(); } + + public ProductForm getExisting(ProductForm pf) {return repository.getByCode(pf.getCode());} public ProductForm validateAndReturn(ProductForm form) { if (form == null) return null; @@ -45,4 +48,9 @@ public ProductForm validateAndReturn(ProductForm form) { return form; } + + public void save(ProductForm pf) { + if(pf.hasId()) repository.update(pf); + else repository.insert(pf); + } } diff --git a/modules/core/src/main/java/org/openlmis/core/service/ProgramProductService.java b/modules/core/src/main/java/org/openlmis/core/service/ProgramProductService.java index 7cfd57fc93..126b4d1372 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/ProgramProductService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/ProgramProductService.java @@ -14,11 +14,11 @@ import lombok.NoArgsConstructor; import org.openlmis.core.domain.*; import org.openlmis.core.exception.DataException; -import org.openlmis.core.repository.FacilityRepository; +import org.openlmis.core.repository.FacilityTypeRepository; import org.openlmis.core.repository.ProgramProductRepository; import org.openlmis.core.repository.ProgramRepository; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -33,7 +33,7 @@ * Exposes the services for handling ProgramProduct entity. */ -@Component +@Service @NoArgsConstructor public class ProgramProductService { @@ -50,7 +50,7 @@ public class ProgramProductService { private ProgramRepository programRepository; @Autowired - private FacilityRepository facilityRepository; + private FacilityTypeRepository facilityTypeRepository; @Autowired private ProductCategoryService categoryService; @@ -119,7 +119,7 @@ public List getByProductCode(String productCode) { public List getProgramProductsBy(String programCode, String facilityTypeCode) { FacilityType facilityType = new FacilityType(); if ((facilityTypeCode = trimToNull(facilityTypeCode)) != null) { - facilityType = facilityRepository.getFacilityTypeByCode(new FacilityType(facilityTypeCode)); + facilityType = facilityTypeRepository.getByCodeOrThrowException(facilityTypeCode); } return programProductRepository.getProgramProductsBy(programRepository.getIdByCode(trimToEmpty(programCode)), facilityType.getCode()); diff --git a/modules/core/src/main/java/org/openlmis/core/service/ProgramService.java b/modules/core/src/main/java/org/openlmis/core/service/ProgramService.java index 1beb4a44fb..d2358798a3 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/ProgramService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/ProgramService.java @@ -97,6 +97,11 @@ public void setFeedSendFlag(Program program, Boolean sendFeed) { programRepository.setFeedSendFlag(program, sendFeed); } + public void save(Program program) { + if(program.hasId()) programRepository.update(program); + else programRepository.insert(program); + } + public void notifyProgramChange() { List programsForNotifications = programRepository.getProgramsForNotification(); for (Program program : programsForNotifications) { diff --git a/modules/core/src/main/java/org/openlmis/core/service/RegimenService.java b/modules/core/src/main/java/org/openlmis/core/service/RegimenService.java index 16f6e90a6c..974a5c3607 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/RegimenService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/RegimenService.java @@ -12,6 +12,7 @@ import org.openlmis.core.domain.Regimen; import org.openlmis.core.domain.RegimenCategory; +import org.openlmis.core.repository.RegimenCategoryRepository; import org.openlmis.core.repository.RegimenRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -28,6 +29,9 @@ public class RegimenService { @Autowired RegimenRepository repository; + @Autowired + private RegimenCategoryRepository regimenCategoryRepository; + @Autowired ProgramService programService; @@ -40,7 +44,7 @@ public List getByProgram(Long programId) { } public List getAllRegimenCategories() { - return repository.getAllRegimenCategories(); + return regimenCategoryRepository.getAll(); } } diff --git a/modules/core/src/main/java/org/openlmis/core/service/UserService.java b/modules/core/src/main/java/org/openlmis/core/service/UserService.java index 2ea2cf5a3d..29b35ae46a 100644 --- a/modules/core/src/main/java/org/openlmis/core/service/UserService.java +++ b/modules/core/src/main/java/org/openlmis/core/service/UserService.java @@ -130,7 +130,7 @@ private void prepareForEmailNotification(User user, String passwordResetLink) { } public void updateUserPassword(Long userId, String password) { - userRepository.updateUserPassword(userId, Encoder.hash(password)); + userRepository.updateUserPasswordAndActivate(userId, Encoder.hash(password)); } @Transactional diff --git a/modules/core/src/main/java/org/openlmis/core/upload/AbstractModelPersistenceHandler.java b/modules/core/src/main/java/org/openlmis/core/upload/AbstractModelPersistenceHandler.java index 4909ffa5c3..1360e3b25f 100644 --- a/modules/core/src/main/java/org/openlmis/core/upload/AbstractModelPersistenceHandler.java +++ b/modules/core/src/main/java/org/openlmis/core/upload/AbstractModelPersistenceHandler.java @@ -34,6 +34,12 @@ public abstract class AbstractModelPersistenceHandler implements RecordHandler expectedRegimenCategories = new ArrayList<>(); - when(regimenCategoryMapper.getAll()).thenReturn(expectedRegimenCategories); - - List regimenCategories = repository.getAllRegimenCategories(); - - assertThat(regimenCategories, is(expectedRegimenCategories)); - verify(regimenCategoryMapper).getAll(); - } - } diff --git a/modules/core/src/test/java/org/openlmis/core/repository/UserRepositoryTest.java b/modules/core/src/test/java/org/openlmis/core/repository/UserRepositoryTest.java index f3d670d595..b3e926460c 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/UserRepositoryTest.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/UserRepositoryTest.java @@ -222,15 +222,6 @@ public void shouldUpdateUserIfUserWithUserNameAlreadyExist() throws Exception { verify(userMapper).update(user); } - @Test - public void shouldUpdateUserPasword() { - Long userId = 1l; - String password = "newPassword"; - - userRepository.updateUserPassword(userId, password); - - verify(userMapper).updateUserPassword(userId, password); - } @Test public void shouldSetActiveForUser() { diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/DosageUnitMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/DosageUnitMapperIT.java index 8ec153ea29..1a9458f83f 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/DosageUnitMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/DosageUnitMapperIT.java @@ -26,20 +26,48 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -@Category(IntegrationTests.class) -@ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") @RunWith(SpringJUnit4ClassRunner.class) -@Transactional +@ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") @TransactionConfiguration(defaultRollback = true, transactionManager = "openLmisTransactionManager") +@Transactional +@Category(IntegrationTests.class) public class DosageUnitMapperIT { @Autowired - DosageUnitMapper mapper; + private DosageUnitMapper duMapper; @Test public void shouldGetAllDosageUnits() throws Exception { - List result = mapper.getAll(); - + List result = duMapper.getAll(); assertThat(result.size(), is(7)); + } + + @Test + public void shouldInsertDosageUnitByCode() { + DosageUnit du = new DosageUnit(); + du.setCode("du code"); + du.setDisplayOrder(1); + duMapper.insert(du); + + DosageUnit returnedDu = duMapper.getByCode("DU CODE"); + + assertThat(returnedDu.getCode(), is(du.getCode())); + assertThat(returnedDu.getDisplayOrder(), is(du.getDisplayOrder())); + } + + @Test + public void shouldUpdateDosageUnit() { + DosageUnit du = new DosageUnit(); + du.setCode("someCode"); + du.setDisplayOrder(1); + duMapper.insert(du); + + DosageUnit returnedDu = duMapper.getByCode("someCode"); + returnedDu.setCode("someOtherCode"); + duMapper.update(returnedDu); + + DosageUnit updatedDu = duMapper.getByCode("someOtherCode"); + assertThat(updatedDu.getCode(), is(returnedDu.getCode())); + assertThat(updatedDu.getDisplayOrder(), is(returnedDu.getDisplayOrder())); } } \ No newline at end of file diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityMapperIT.java index e46864e036..8f831f21d4 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityMapperIT.java @@ -60,6 +60,9 @@ public class FacilityMapperIT { @Autowired FacilityMapper mapper; + @Autowired + FacilityTypeMapper facilityTypeMapper; + @Autowired RequisitionGroupMapper requisitionGroupMapper; @@ -123,25 +126,6 @@ public void shouldFetchAllFacilitiesAvailable() throws Exception { assertEquals(facilities.get(1).getCode(), trz002.getCode()); } - @Test - public void shouldGetAllFacilityTypes() throws Exception { - List facilityTypes = mapper.getAllTypes(); - - assertThat(facilityTypes.size(), is(11)); - FacilityType facilityType = facilityTypes.get(0); - assertThat(facilityType.getCode(), is("lvl3_hospital")); - assertThat(facilityType.getName(), is("Lvl3 Hospital")); - assertThat(facilityType.getDescription(), is("State Hospital")); - assertThat(facilityType.getLevelId(), is(nullValue())); - assertThat(facilityType.getNominalMaxMonth(), is(3)); - assertThat(facilityType.getNominalEop(), is(0.5)); - assertThat(facilityType.isActive(), is(true)); - - for (int index = 0; index < facilityTypes.size(); index++) { - assertThat(facilityTypes.get(index).getDisplayOrder(), is(index + 1)); - } - } - @Test public void shouldGetAllParentFacilitiesByModifiedDate() { Facility facility1 = make(a(defaultFacility)); @@ -164,16 +148,6 @@ public void shouldGetAllParentFacilitiesByModifiedDate() { assertThat(facilities.get(0).getId(), is(facility2.getId())); } - @Test - public void shouldGetAllOperators() throws Exception { - List allOperators = mapper.getAllOperators(); - assertThat(allOperators.size(), is(4)); - FacilityOperator facilityOperator = allOperators.get(0); - assertThat(facilityOperator.getCode(), is("MoH")); - assertThat(facilityOperator.getText(), is("MoH")); - assertThat(facilityOperator.getDisplayOrder(), is(1)); - } - @Test public void shouldReturnFacilityForAUser() throws Exception { mapper.insert(make(a(defaultFacility))); @@ -301,34 +275,6 @@ public void shouldReturnFacilityOperatorIdForCode() { assertThat(id, is(nullValue())); } - @Test - public void shouldReturnFacilityTypeForCode() { - FacilityType facilityType = mapper.getFacilityTypeForCode(FACILITY_TYPE_CODE); - assertThat(facilityType.getId(), is(1L)); - - facilityType = mapper.getFacilityTypeForCode("InValid"); - assertThat(facilityType, is(nullValue())); - } - - @Test - public void shouldReturnFacilityTypeById() { - FacilityType facilityTypeWithId = mapper.getFacilityTypeForCode(FACILITY_TYPE_CODE); - - FacilityType facilityType = mapper.getFacilityTypeById(facilityTypeWithId.getId()); - assertThat(facilityType, is(notNullValue())); - assertThat(facilityType.getId(), is(facilityTypeWithId.getId())); - assertThat(facilityType.getCode(), is(FACILITY_TYPE_CODE)); - } - - @Test - public void shouldReturnFacilityOperatorById() throws Exception { - Long id = mapper.getOperatedByIdForCode(OPERATED_BY_MOH); - - FacilityOperator operator = mapper.getFacilityOperatorById(id); - assertThat(operator.getId(), is(id)); - assertThat(operator.getCode(), is(OPERATED_BY_MOH)); - } - @Test public void shouldUpdateEnabledAndActiveForAFacility() throws Exception { Facility facility = make(a(defaultFacility)); @@ -477,7 +423,7 @@ public void shouldGetFacilityByCode() throws Exception { GeographicZone zone1 = new GeographicZone(1000L, "Z1", "Z1", level, zone0); geographicZoneMapper.insert(zone1); - List allTypes = mapper.getAllTypes(); + List allTypes = facilityTypeMapper.getAll(); FacilityType facilityType = allTypes.get(1); Facility facility = insertFacility("CODE123", facilityType, zone1, null); @@ -917,7 +863,7 @@ public void shouldUpdateOnlyTypeAndGeoZoneInVirtualFacilities() throws Exception GeographicZone zone2 = new GeographicZone(2000L, "Z2", "Z2", level, zone1); geographicZoneMapper.insert(zone2); - List allTypes = mapper.getAllTypes(); + List allTypes = facilityTypeMapper.getAll(); FacilityType facilityType1 = allTypes.get(1); FacilityType facilityType2 = allTypes.get(2); diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityOperatorMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityOperatorMapperIT.java new file mode 100644 index 0000000000..a36a3e0df6 --- /dev/null +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityOperatorMapperIT.java @@ -0,0 +1,102 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository.mapper; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.openlmis.core.domain.Facility; +import org.openlmis.core.domain.FacilityOperator; +import org.openlmis.db.categories.IntegrationTests; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; + +@Category(IntegrationTests.class) +@ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") +@RunWith(SpringJUnit4ClassRunner.class) +@Transactional +@TransactionConfiguration(defaultRollback = true, transactionManager = "openLmisTransactionManager") +public class FacilityOperatorMapperIT { + + @Autowired + private FacilityOperatorMapper mapper; + + @Test + public void shouldInsertAndUpdateFacilityOperatorByCode() { + FacilityOperator facOp = new FacilityOperator(); + facOp.setCode("someCode"); + facOp.setText("someText"); + facOp.setDisplayOrder(1); + + // insert + mapper.insert(facOp); + + // test insert + FacilityOperator retFacOp = mapper.getByCode(facOp.getCode()); + assertThat(retFacOp, is(facOp)); + + // update + retFacOp.setCode("aNewCode"); + retFacOp.setText("aNewText"); + retFacOp.setDisplayOrder(2); + mapper.update(retFacOp); + + // test update + FacilityOperator updatedFacOp = mapper.getByCode(retFacOp.getCode()); + assertThat(updatedFacOp, is(retFacOp)); + } + + @Test + public void shouldIgnoreCaseWhenFindByCode() { + FacilityOperator facOp = new FacilityOperator(); + facOp.setCode("somecode"); + facOp.setText("sometext"); + facOp.setDisplayOrder(1); + + mapper.insert(facOp); + + FacilityOperator retFacOp = mapper.getByCode("SOMECODE"); + assertThat(retFacOp, notNullValue()); + assertThat(retFacOp, is(facOp)); + } + + @Test + public void shouldReturnNullWithInvalidId() { + assertThat(mapper.getById(9919L), nullValue()); + } + + @Test + public void shouldGetAllByDisplayOrder() { + List allManualSort = mapper.getAll(); + + Collections.sort(allManualSort, new Comparator() { + @Override + public int compare(FacilityOperator o1, FacilityOperator o2) { + return o1.getDisplayOrder().compareTo(o2.getDisplayOrder()); + } + }); + + List all = mapper.getAll(); + assertThat(all.size(), greaterThan(1)); + assertThat(all, equalTo(allManualSort)); + } +} diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityTypeMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityTypeMapperIT.java new file mode 100644 index 0000000000..c9e6ff1b48 --- /dev/null +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/FacilityTypeMapperIT.java @@ -0,0 +1,97 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2013 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. + * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +package org.openlmis.core.repository.mapper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.openlmis.core.domain.Facility; +import org.openlmis.core.domain.FacilityType; +import org.openlmis.db.categories.IntegrationTests; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.greaterThan; + +@Category(IntegrationTests.class) +@ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") +@RunWith(SpringJUnit4ClassRunner.class) +@Transactional +@TransactionConfiguration(defaultRollback = true, transactionManager = "openLmisTransactionManager") +public class FacilityTypeMapperIT { + @Autowired + private FacilityTypeMapper mapper; + + private FacilityType facType; + + @Before + public void setup() { + // seed a facility type to use for testing + facType = new FacilityType(); + facType.setCode("someCode"); // this code is used for later testing, don't change + facType.setName("someName"); + facType.setDescription("someDescription"); + facType.setNominalMaxMonth(1); + facType.setNominalEop(1D); + facType.setDisplayOrder(1); + facType.setActive(true); + + mapper.insert(facType); + } + + @Test + public void shouldGetById() { + FacilityType persistentFacType = mapper.getByCode(facType.getCode()); + FacilityType facTypeFoundById = mapper.getById(persistentFacType.getId()); + assertThat(facTypeFoundById, notNullValue()); + assertThat(facTypeFoundById, is(persistentFacType)); + } + + @Test + public void shouldUpdateByCodeCaseInsensitive() { + // test get by code + FacilityType retFacType = mapper.getByCode(facType.getCode()); + assertThat(retFacType, notNullValue()); + assertThat(retFacType, is(facType)); + + // update and test get by code case insensitive + retFacType.setName("someOtherName"); + mapper.update(retFacType); + FacilityType updatedFacType = mapper.getByCode(facType.getCode().toUpperCase()); + assertThat(updatedFacType, is(retFacType)); + } + + @Test + public void shouldGetAll() { + List all = mapper.getAll(); + assertThat(all.size(), greaterThan(0)); + } + + @Test + public void shouldReturnNullIfGetByCodeIsNull() { + assertThat(mapper.getByCode(null), nullValue()); + } + + @Test + public void shouldReturnNullIfGetByCodeIsEmptyString() { + assertThat(mapper.getByCode(""), nullValue()); + } +} diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicLevelMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicLevelMapperIT.java index f0faae2540..8b5fc53289 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicLevelMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicLevelMapperIT.java @@ -10,6 +10,7 @@ package org.openlmis.core.repository.mapper; +import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -21,9 +22,13 @@ import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; @Category(IntegrationTests.class) @@ -36,18 +41,66 @@ public class GeographicLevelMapperIT { @Autowired private GeographicLevelMapper mapper; + private GeographicLevel provGeoLevel; + + @Before + public void init() { + provGeoLevel = new GeographicLevel(); + provGeoLevel.setCode("myprov"); + provGeoLevel.setName("Province"); + provGeoLevel.setLevelNumber(2); + mapper.insert(provGeoLevel); + } + @Test public void shouldGetLowestGeographicLevel() { - assertThat(mapper.getLowestGeographicLevel(), is(4)); + // get a list of all the geo levels and the lowest level that should be present + List allGeoLevels = mapper.getAll(); + int lowestLevel = mapper.getLowestGeographicLevel(); + + // sort all geo levels by their level number + Collections.sort(allGeoLevels, new Comparator() { + public int compare(GeographicLevel o1, GeographicLevel o2) { + return Integer.compare(o1.getLevelNumber(), o2.getLevelNumber()); + } + }); + GeographicLevel lowestGeoLevel = allGeoLevels.get(allGeoLevels.size() - 1); + + assertThat(lowestLevel, is(lowestGeoLevel.getLevelNumber())); + } + + @Test + public void shouldGetGeographicLevelByCode() throws Exception { + String code = provGeoLevel.getCode(); + GeographicLevel geographicLevel = mapper.getGeographicLevelByCode(code); + assertThat(geographicLevel, is(provGeoLevel)); } @Test public void shouldReturnAllTheGeoLevels() { List levels = mapper.getAll(); - assertThat(levels.size(), is(4)); - assertThat(levels.get(0).getLevelNumber(), is(1)); - assertThat(levels.get(1).getLevelNumber(), is(2)); - assertThat(levels.get(2).getLevelNumber(), is(3)); - assertThat(levels.get(3).getLevelNumber(), is(4)); + assertThat(levels.size(), not(0)); + } + + @Test + public void shouldRetrieveGeographicLevelByCode() { + String code = provGeoLevel.getCode(); + GeographicLevel geoRet = mapper.getByCode(code); + + assertThat(geoRet, notNullValue()); + assertThat(geoRet, is(provGeoLevel)); + } + + @Test + public void shouldUpdateGeographicLevel() { + GeographicLevel geoRet = mapper.getByCode(provGeoLevel.getCode()); + geoRet.setName("Some new name"); + geoRet.setLevelNumber(3); + + mapper.update(geoRet); + + GeographicLevel geoUpdated = mapper.getByCode(provGeoLevel.getCode()); + assertThat(geoUpdated, notNullValue()); + assertThat(geoUpdated, is(geoRet)); } } diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicZoneMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicZoneMapperIT.java index 8ca6ce1d17..534170dac1 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicZoneMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/GeographicZoneMapperIT.java @@ -57,14 +57,6 @@ public void shouldSaveGeographicZone() throws Exception { assertThat(returnedZone, is(geographicZone)); } - @Test - public void shouldGetGeographicLevelByCode() throws Exception { - String code = "state"; - GeographicLevel geographicLevel = mapper.getGeographicLevelByCode(code); - assertThat(geographicLevel.getName(), is("State")); - assertThat(geographicLevel.getId(), is(2L)); - } - @Test public void shouldGetNullIfZoneNotPresent() throws Exception { GeographicZone nullZone = mapper.getGeographicZoneByCode("some random code"); diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProductFormMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProductFormMapperIT.java index 53ca4df560..eceb15e45a 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProductFormMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProductFormMapperIT.java @@ -10,7 +10,6 @@ package org.openlmis.core.repository.mapper; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -27,37 +26,62 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -@Category(IntegrationTests.class) @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") -@Transactional @TransactionConfiguration(defaultRollback = true, transactionManager = "openLmisTransactionManager") +@Transactional +@Category(IntegrationTests.class) public class ProductFormMapperIT { @Autowired - ProductFormMapper mapper; + private ProductFormMapper pfMapper; @Test - public void shouldGetProductFormById() throws Exception { + public void shouldInsertProductFormByCode() { + ProductForm pf = new ProductForm(); + pf.setCode("somecode"); + pf.setDisplayOrder(1); + pfMapper.insert(pf); + + ProductForm retPf = pfMapper.getByCode("somecode"); - ProductForm returnedProductForm = mapper.getById(1l); + assertThat(retPf.getCode(), is(pf.getCode())); + assertThat(retPf.getDisplayOrder(), is(pf.getDisplayOrder())); + } - assertThat(returnedProductForm.getCode(), is("Tablet")); + @Test + public void shouldUpdateProductFormByCode() { + // insert seed + ProductForm pf = new ProductForm(); + pf.setCode("somecode"); + pf.setDisplayOrder(1); + pfMapper.insert(pf); + + // update seed + pf.setDisplayOrder(2); + pfMapper.update(pf); + + // pull from DB and check update worked + ProductForm pfRet = pfMapper.getByCode("somecode"); + assertThat(pfRet.getDisplayOrder(), is(2)); } + @Test + public void shouldGetProductFormById() throws Exception { + ProductForm returnedProductForm = pfMapper.getById(1l); + assertThat(returnedProductForm.getCode(), is("Tablet")); + } + @Test public void shouldGetAllProductForms() throws Exception { - List result = mapper.getAll(); - + List result = pfMapper.getAll(); assertThat(result.size(), is(17)); } - + @Test public void shouldReturnProductFormIdForCode() { - ProductForm form = mapper.getByCode("Capsule"); - + ProductForm form = pfMapper.getByCode("Capsule"); assertThat(form.getCode(), is("Capsule")); assertThat(form.getDisplayOrder(), is(2)); } - } diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProgramMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProgramMapperIT.java index e2984cd8d4..8015df30d0 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProgramMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/ProgramMapperIT.java @@ -33,6 +33,7 @@ import static com.natpryce.makeiteasy.MakeItEasy.*; import static junit.framework.Assert.assertEquals; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.*; import static org.openlmis.core.builder.FacilityBuilder.defaultFacility; import static org.openlmis.core.builder.ProgramBuilder.*; @@ -71,6 +72,37 @@ public class ProgramMapperIT { @Autowired QueryExecutor queryExecutor; + @Test + public void shouldInsertProgram() { + Program p = make(a(defaultProgram)); + programMapper.insert(p); + + Program pRet = programMapper.getById(p.getId()); + assertThat(pRet, notNullValue()); + assertThat(pRet, is(p)); + } + + @Test + public void shouldUpdateProgram() { + Program p = make(a(defaultProgram)); + programMapper.insert(p); + + p = programMapper.getById(p.getId()); + p.setCode("abc"); + p.setActive(false); + p.setBudgetingApplies(false); + p.setDescription("something to update"); + p.setName("something to update"); + p.setPush(false); + p.setRegimenTemplateConfigured(false); + p.setTemplateConfigured(false); + programMapper.update(p); + + Program pRet = programMapper.getById(p.getId()); + assertThat(pRet, notNullValue()); + assertThat(pRet, is(p)); + } + @Test public void shouldGetProgramsWhichAreActiveByFacilityCode() { Facility facility = make(a(FacilityBuilder.defaultFacility)); @@ -287,15 +319,6 @@ public void shouldGetProgramsForAUserByFacilityAndRights() throws Exception { assertTrue(programs.contains(activeProgram)); } - - @Test - public void shouldGetAllProgramsInOrderByRegimentTemplateConfiguredAndName() { - insertProgram(make(a(defaultProgram, with(regimenTemplateConfigured, true)))); - List programs = programMapper.getAllByRegimenTemplate(); - assertThat(programs.size(), is(6)); - assertThat(programs.get(0).getCode(), is(ProgramBuilder.PROGRAM_CODE)); - } - @Test public void shouldSetRegimenTemplateConfigured() { Program program = insertProgram(make(a(defaultProgram, with(programCode, "p1"), with(regimenTemplateConfigured, false)))); diff --git a/modules/core/src/test/java/org/openlmis/core/repository/mapper/RegimenCategoryMapperIT.java b/modules/core/src/test/java/org/openlmis/core/repository/mapper/RegimenCategoryMapperIT.java index 45ca0a15ce..9aa1b36008 100644 --- a/modules/core/src/test/java/org/openlmis/core/repository/mapper/RegimenCategoryMapperIT.java +++ b/modules/core/src/test/java/org/openlmis/core/repository/mapper/RegimenCategoryMapperIT.java @@ -21,9 +21,13 @@ import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertThat; @Category(IntegrationTests.class) @@ -43,9 +47,49 @@ public void shouldGetAllRegimenCategories() { assertThat(regimenCategories.get(0).getCode(), is("ADULTS")); } + @Test + public void shouldGetAllRegimenCategoriesSorted() { + List all = regimenCategoryMapper.getAll(); + assertThat(all.size(), greaterThan(1)); + + // manually sort by display order and then name + Collections.sort(all, new Comparator() { + public int compare(RegimenCategory o1, RegimenCategory o2) { + int onDispOrd = o1.getDisplayOrder().compareTo(o2.getDisplayOrder()); + if(onDispOrd != 0) return onDispOrd; + return o1.getName().compareTo(o2.getName()); + } + }); + + List allFromDb = regimenCategoryMapper.getAll(); + assertThat(allFromDb, is(all)); + } + @Test public void shouldGetRegimenById() { RegimenCategory adultCategory = regimenCategoryMapper.getById(1L); assertThat(adultCategory.getCode(), is("ADULTS")); } + + + @Test + public void shouldInsertAndUpdateWithCaseInsensitiveCode() { + RegimenCategory regCat = new RegimenCategory(); + regCat.setCode("somecode"); + regCat.setName("someName"); + regCat.setDisplayOrder(1); + + // insert and test case insensitive get by code + regimenCategoryMapper.insert(regCat); + RegimenCategory retRegCat = regimenCategoryMapper.getByCode("SOMECODE"); + assertThat(retRegCat, notNullValue()); + assertThat(retRegCat, is(regCat)); + + // update something and test it + retRegCat.setName("some other name"); + retRegCat.setDisplayOrder(2); + regimenCategoryMapper.update(retRegCat); + RegimenCategory updatedRegCat = regimenCategoryMapper.getByCode("SOMECODE"); + assertThat(updatedRegCat, is(retRegCat)); + } } diff --git a/modules/core/src/test/java/org/openlmis/core/service/GeographicZoneServiceTest.java b/modules/core/src/test/java/org/openlmis/core/service/GeographicZoneServiceTest.java index 0c2d543665..bfbc24fb0e 100644 --- a/modules/core/src/test/java/org/openlmis/core/service/GeographicZoneServiceTest.java +++ b/modules/core/src/test/java/org/openlmis/core/service/GeographicZoneServiceTest.java @@ -20,6 +20,7 @@ import org.openlmis.core.domain.GeographicLevel; import org.openlmis.core.domain.GeographicZone; import org.openlmis.core.domain.Pagination; +import org.openlmis.core.repository.GeographicLevelRepository; import org.openlmis.core.repository.GeographicZoneRepository; import org.openlmis.db.categories.UnitTests; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -45,6 +46,9 @@ public class GeographicZoneServiceTest { @Mock GeographicZoneRepository repository; + @Mock + GeographicLevelRepository geoLevelRepo; + @InjectMocks GeographicZoneService service; @@ -60,12 +64,12 @@ public void shouldSaveGeographicZone() throws Exception { GeographicLevel childLevel = new GeographicLevel(2345L, "child level", "child level", 2); GeographicZone childZone = new GeographicZone(null, "child zone", "child zone", childLevel, rootZone); - when(repository.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); + when(geoLevelRepo.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); when(repository.getByCode(childZone.getParent().getCode())).thenReturn(rootZone); service.save(childZone); - verify(repository).getGeographicLevelByCode("child level"); + verify(geoLevelRepo).getGeographicLevelByCode("child level"); verify(repository).getByCode("root zone"); assertThat(childZone.getLevel().getId(), is(2345L)); assertThat(childZone.getParent().getId(), is(1234L)); @@ -79,7 +83,7 @@ public void shouldThrowAnExceptionIfParentCodeIsInvalid() throws Exception { GeographicLevel childLevel = new GeographicLevel(2345L, "child level", "child level", 2); GeographicZone childZone = new GeographicZone(null, "child zone", "child zone", childLevel, invalidZone); - when(repository.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); + when(geoLevelRepo.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); when(repository.getByCode(childZone.getParent().getCode())).thenReturn(null); expectedEx.expect(dataExceptionMatcher("error.geo.zone.parent.invalid")); @@ -119,7 +123,7 @@ public void shouldThrowExceptionIfLevelIsNotRootAndStillParentIsNull() throws Ex GeographicLevel level = new GeographicLevel(1L, "abc", "abc", 2); GeographicZone zone = new GeographicZone(1L, "xyz", "xyz", level, null); - when(repository.getGeographicLevelByCode(zone.getLevel().getCode())).thenReturn(level); + when(geoLevelRepo.getGeographicLevelByCode(zone.getLevel().getCode())).thenReturn(level); expectedEx.expect(dataExceptionMatcher("error.invalid.hierarchy")); @@ -133,7 +137,7 @@ public void shouldUpdateZoneIfZonePreviouslyPresent() throws Exception { GeographicLevel childLevel = new GeographicLevel(2345L, "child level", "child level", 2); GeographicZone childZone = new GeographicZone(2345L, "child zone", "child zone", childLevel, rootZone); - when(repository.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); + when(geoLevelRepo.getGeographicLevelByCode(childZone.getLevel().getCode())).thenReturn(childLevel); when(repository.getByCode(childZone.getParent().getCode())).thenReturn(rootZone); childZone.setName("new name"); @@ -161,7 +165,7 @@ public void shouldThrowExceptionIfParentSpecifiedForTopMostLevelGeographicZone() GeographicZone parent = new GeographicZone(1L, "xyz", "xyz", null, null); GeographicZone country = new GeographicZone(1L, "xyz", "xyz", level, parent); - when(repository.getGeographicLevelByCode(country.getLevel().getCode())).thenReturn(level); + when(geoLevelRepo.getGeographicLevelByCode(country.getLevel().getCode())).thenReturn(level); when(repository.getByCode(country.getParent().getCode())).thenReturn(parent); expectedEx.expect(dataExceptionMatcher("error.invalid.hierarchy")); @@ -174,7 +178,7 @@ public void shouldThrowExceptionIfParentSetToItsSiblingInHierarchy() throws Exce GeographicZone country1 = new GeographicZone(1L, "xyz", "xyz", level, null); GeographicZone country2 = new GeographicZone(1L, "xyz", "xyz", level, country1); - when(repository.getGeographicLevelByCode(country2.getLevel().getCode())).thenReturn(level); + when(geoLevelRepo.getGeographicLevelByCode(country2.getLevel().getCode())).thenReturn(level); when(repository.getByCode(country2.getParent().getCode())).thenReturn(country1); expectedEx.expect(dataExceptionMatcher("error.invalid.hierarchy")); @@ -188,7 +192,7 @@ public void shouldThrowExceptionIfParentIsSetToALowerInHierarchyGeographicLevel( GeographicZone country1 = new GeographicZone(1L, "xyz", "xyz", lowerLevel, null); GeographicZone country2 = new GeographicZone(1L, "xyz", "xyz", higherLevel, country1); - when(repository.getGeographicLevelByCode(country2.getLevel().getCode())).thenReturn(higherLevel); + when(geoLevelRepo.getGeographicLevelByCode(country2.getLevel().getCode())).thenReturn(higherLevel); when(repository.getByCode(country2.getParent().getCode())).thenReturn(country1); expectedEx.expect(dataExceptionMatcher("error.invalid.hierarchy")); diff --git a/modules/core/src/test/java/org/openlmis/core/service/ProgramProductServiceTest.java b/modules/core/src/test/java/org/openlmis/core/service/ProgramProductServiceTest.java index 1529bc46bf..ef56cd626b 100644 --- a/modules/core/src/test/java/org/openlmis/core/service/ProgramProductServiceTest.java +++ b/modules/core/src/test/java/org/openlmis/core/service/ProgramProductServiceTest.java @@ -22,6 +22,7 @@ import org.openlmis.core.domain.*; import org.openlmis.core.exception.DataException; import org.openlmis.core.repository.FacilityRepository; +import org.openlmis.core.repository.FacilityTypeRepository; import org.openlmis.core.repository.ProgramProductRepository; import org.openlmis.core.repository.ProgramRepository; import org.openlmis.db.categories.UnitTests; @@ -58,6 +59,9 @@ public class ProgramProductServiceTest { @Mock private FacilityRepository facilityRepository; + @Mock + private FacilityTypeRepository facilityTypeRepository; + @Mock private ProductCategoryService categoryService; @@ -294,13 +298,13 @@ public void shouldGetAllProgramProductsByProgramCodeAndFacilityTypeCode() { List expectedProgramProducts = new ArrayList<>(); when(programRepository.getIdByCode("P1")).thenReturn(10L); FacilityType warehouse = new FacilityType("warehouse"); - when(facilityRepository.getFacilityTypeByCode(warehouse)).thenReturn(warehouse); + when(facilityTypeRepository.getByCodeOrThrowException(warehouse.getCode())).thenReturn(warehouse); when(programProductRepository.getProgramProductsBy(10L, "warehouse")).thenReturn(expectedProgramProducts); List programProducts = service.getProgramProductsBy(" P1", " warehouse"); assertThat(programProducts, is(expectedProgramProducts)); - verify(facilityRepository).getFacilityTypeByCode(warehouse); + verify(facilityTypeRepository).getByCodeOrThrowException(warehouse.getCode()); verify(programRepository).getIdByCode("P1"); verify(programProductRepository).getProgramProductsBy(10L, "warehouse"); } @@ -315,7 +319,7 @@ public void shouldGetAllProgramProductsByProgramCodeForNullFacilityTypeCode() { List programProducts = service.getProgramProductsBy("P1", null); assertThat(programProducts, is(expectedProgramProducts)); - verify(facilityRepository, never()).getFacilityTypeByCode(any(FacilityType.class)); + verify(facilityTypeRepository, never()).getByCodeOrThrowException(null); verify(programRepository).getIdByCode("P1"); verify(programProductRepository).getProgramProductsBy(10L, null); } diff --git a/modules/core/src/test/java/org/openlmis/core/service/RegimenServiceTest.java b/modules/core/src/test/java/org/openlmis/core/service/RegimenServiceTest.java index 77831a1e59..5b9af7d1be 100644 --- a/modules/core/src/test/java/org/openlmis/core/service/RegimenServiceTest.java +++ b/modules/core/src/test/java/org/openlmis/core/service/RegimenServiceTest.java @@ -18,6 +18,7 @@ import org.mockito.runners.MockitoJUnitRunner; import org.openlmis.core.domain.Regimen; import org.openlmis.core.domain.RegimenCategory; +import org.openlmis.core.repository.RegimenCategoryRepository; import org.openlmis.core.repository.RegimenRepository; import java.util.ArrayList; @@ -37,6 +38,9 @@ public class RegimenServiceTest { @Mock ProgramService programService; + @Mock + private RegimenCategoryRepository regimenCategoryRepository; + @InjectMocks RegimenService service; @@ -72,12 +76,12 @@ public void shouldGetRegimensByProgram() { @Test public void shouldGetAllRegimenCategories() { List expectedRegimenCategories = new ArrayList<>(); - when(repository.getAllRegimenCategories()).thenReturn(expectedRegimenCategories); + when(regimenCategoryRepository.getAll()).thenReturn(expectedRegimenCategories); List regimenCategories = service.getAllRegimenCategories(); assertThat(regimenCategories, is(expectedRegimenCategories)); - verify(repository).getAllRegimenCategories(); + verify(regimenCategoryRepository).getAll(); } } diff --git a/modules/core/src/test/java/org/openlmis/core/service/UserServiceTest.java b/modules/core/src/test/java/org/openlmis/core/service/UserServiceTest.java index 8bef8ee9ac..c202c604d0 100644 --- a/modules/core/src/test/java/org/openlmis/core/service/UserServiceTest.java +++ b/modules/core/src/test/java/org/openlmis/core/service/UserServiceTest.java @@ -322,7 +322,7 @@ public void shouldUpdateUserPassword() { userService.updateUserPassword(userId, newPassword); - verify(userRepository).updateUserPassword(userId, hashedPassword); + verify(userRepository).updateUserPasswordAndActivate(userId, hashedPassword); } @Test diff --git a/modules/db/src/main/resources/db/migration/V109__alter_requisition_line_items_add_column_previous_stock_in_hand.sql b/modules/db/src/main/resources/db/migration/V109_1__alter_requisition_line_items_add_column_previous_stock_in_hand.sql similarity index 100% rename from modules/db/src/main/resources/db/migration/V109__alter_requisition_line_items_add_column_previous_stock_in_hand.sql rename to modules/db/src/main/resources/db/migration/V109_1__alter_requisition_line_items_add_column_previous_stock_in_hand.sql diff --git a/modules/db/src/main/resources/db/migration/V109__alter_epi_use_line_items_add_ideal_quantity_units.sql b/modules/db/src/main/resources/db/migration/V109__alter_epi_use_line_items_add_ideal_quantity_units.sql new file mode 100644 index 0000000000..7520065172 --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V109__alter_epi_use_line_items_add_ideal_quantity_units.sql @@ -0,0 +1,11 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE epi_inventory_line_items ADD COLUMN idealquantitybypacksize numeric; \ No newline at end of file diff --git a/modules/db/src/main/resources/db/migration/V131_1__add_created_and_modified_dosage_units.sql b/modules/db/src/main/resources/db/migration/V131_1__add_created_and_modified_dosage_units.sql new file mode 100644 index 0000000000..9462dfccdc --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V131_1__add_created_and_modified_dosage_units.sql @@ -0,0 +1,14 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE dosage_units ADD COLUMN createdBy INTEGER; +ALTER TABLE dosage_units ADD COLUMN modifiedBy INTEGER; +ALTER TABLE dosage_units ADD COLUMN modifiedDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(); + diff --git a/modules/db/src/main/resources/db/migration/V132_1__add_created_and_modified_product_forms.sql b/modules/db/src/main/resources/db/migration/V132_1__add_created_and_modified_product_forms.sql new file mode 100644 index 0000000000..27fce5a2cf --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V132_1__add_created_and_modified_product_forms.sql @@ -0,0 +1,13 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE product_forms ADD COLUMN createdBy INTEGER; +ALTER TABLE product_forms ADD COLUMN modifiedBy INTEGER; +ALTER TABLE product_forms ADD COLUMN modifiedDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(); diff --git a/modules/db/src/main/resources/db/migration/V133_1__add_created_and_modified_geographic_levels.sql b/modules/db/src/main/resources/db/migration/V133_1__add_created_and_modified_geographic_levels.sql new file mode 100644 index 0000000000..32b321b5c8 --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V133_1__add_created_and_modified_geographic_levels.sql @@ -0,0 +1,13 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE geographic_levels ADD COLUMN createdBy INTEGER; +ALTER TABLE geographic_levels ADD COLUMN modifiedBy INTEGER; +ALTER TABLE geographic_levels ADD COLUMN modifiedDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(); diff --git a/modules/db/src/main/resources/db/migration/V134_1__add_created_and_modified_facility_operators.sql b/modules/db/src/main/resources/db/migration/V134_1__add_created_and_modified_facility_operators.sql new file mode 100644 index 0000000000..d1ef76caee --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V134_1__add_created_and_modified_facility_operators.sql @@ -0,0 +1,13 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE facility_operators ADD COLUMN createdBy INTEGER; +ALTER TABLE facility_operators ADD COLUMN modifiedBy INTEGER; +ALTER TABLE facility_operators ADD COLUMN modifiedDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(); diff --git a/modules/db/src/main/resources/db/migration/V135_1__add_created_and_modified_facility_types.sql b/modules/db/src/main/resources/db/migration/V135_1__add_created_and_modified_facility_types.sql new file mode 100644 index 0000000000..eba9aa12f1 --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V135_1__add_created_and_modified_facility_types.sql @@ -0,0 +1,13 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE facility_types ADD COLUMN createdBy INTEGER; +ALTER TABLE facility_types ADD COLUMN modifiedBy INTEGER; +ALTER TABLE facility_types ADD COLUMN modifiedDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(); diff --git a/modules/db/src/main/resources/db/migration/V144__alter_template_parameters.sql b/modules/db/src/main/resources/db/migration/V144__alter_template_parameters.sql new file mode 100644 index 0000000000..3612aa81e9 --- /dev/null +++ b/modules/db/src/main/resources/db/migration/V144__alter_template_parameters.sql @@ -0,0 +1,11 @@ +-- +-- This program is part of the OpenLMIS logistics management information system platform software. +-- Copyright © 2013 VillageReach +-- +-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +--   +-- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details. +-- You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  +-- + +ALTER TABLE template_parameters ADD COLUMN selectSql TEXT; diff --git a/modules/distribution/src/main/java/org/openlmis/distribution/domain/CoverageLineItem.java b/modules/distribution/src/main/java/org/openlmis/distribution/domain/CoverageLineItem.java index 195aa36038..d8a173b21a 100644 --- a/modules/distribution/src/main/java/org/openlmis/distribution/domain/CoverageLineItem.java +++ b/modules/distribution/src/main/java/org/openlmis/distribution/domain/CoverageLineItem.java @@ -17,7 +17,7 @@ import org.openlmis.core.domain.BaseModel; import org.openlmis.core.domain.Facility; -import static java.lang.Math.ceil; +import static java.lang.Math.round; /** * CoverageLineItem is a base class holding facilityVisitId and targetGroup. TargetGroup is calculated on basis of @@ -44,7 +44,7 @@ public CoverageLineItem(FacilityVisit facilityVisit, Facility facility, TargetGr protected Integer calculateTargetGroup(Double whoRatio, Long catchmentPopulation, Integer processingPeriodMonths) { Integer targetGroup = null; if (whoRatio != null && catchmentPopulation != null) { - targetGroup = (int) ceil((catchmentPopulation * whoRatio * processingPeriodMonths) / (100 * 12)); + targetGroup = (int) round((catchmentPopulation * whoRatio * processingPeriodMonths) / (100 * 12)); } return targetGroup; } diff --git a/modules/distribution/src/main/java/org/openlmis/distribution/domain/EpiInventoryLineItem.java b/modules/distribution/src/main/java/org/openlmis/distribution/domain/EpiInventoryLineItem.java index e2cb79558c..e3e35ab72e 100644 --- a/modules/distribution/src/main/java/org/openlmis/distribution/domain/EpiInventoryLineItem.java +++ b/modules/distribution/src/main/java/org/openlmis/distribution/domain/EpiInventoryLineItem.java @@ -31,6 +31,7 @@ public class EpiInventoryLineItem extends BaseModel { private Long facilityVisitId; private Integer idealQuantity; + private Integer idealQuantityByPackSize; private Integer existingQuantity; private Integer spoiledQuantity; private Integer deliveredQuantity; @@ -43,6 +44,7 @@ public EpiInventoryLineItem(Long facilityVisitId, FacilityProgramProduct facilit this.facilityVisitId = facilityVisitId; this.programProductId = facilityProgramProduct.getId(); this.idealQuantity = facilityProgramProduct.calculateIsa(population, numberOfMonths); + this.idealQuantityByPackSize = facilityProgramProduct.calculateIsaByPackSize(population, numberOfMonths); this.productName = facilityProgramProduct.getProduct().getPrimaryName(); this.productCode = facilityProgramProduct.getProduct().getCode(); this.productDisplayOrder = facilityProgramProduct.getDisplayOrder(); diff --git a/modules/distribution/src/main/java/org/openlmis/distribution/domain/ReasonForNotVisiting.java b/modules/distribution/src/main/java/org/openlmis/distribution/domain/ReasonForNotVisiting.java index 3feb22d204..9bea34b3ef 100644 --- a/modules/distribution/src/main/java/org/openlmis/distribution/domain/ReasonForNotVisiting.java +++ b/modules/distribution/src/main/java/org/openlmis/distribution/domain/ReasonForNotVisiting.java @@ -18,7 +18,10 @@ public enum ReasonForNotVisiting { ROAD_IMPASSABLE, TRANSPORT_UNAVAILABLE, HEALTH_CENTER_CLOSED, + REFRIGERATORS_NOT_WORKING, + NO_REFRIGERATORS, FUEL_FUNDS_UNAVAILABLE, + PERDIEM_FUNDS_UNAVAILABLE, HEALTH_CENTER_NOT_IN_DLS, OTHER } diff --git a/modules/distribution/src/main/java/org/openlmis/distribution/repository/mapper/EpiInventoryLineItemMapper.java b/modules/distribution/src/main/java/org/openlmis/distribution/repository/mapper/EpiInventoryLineItemMapper.java index 10415f9055..132980721a 100644 --- a/modules/distribution/src/main/java/org/openlmis/distribution/repository/mapper/EpiInventoryLineItemMapper.java +++ b/modules/distribution/src/main/java/org/openlmis/distribution/repository/mapper/EpiInventoryLineItemMapper.java @@ -26,8 +26,8 @@ @Repository public interface EpiInventoryLineItemMapper { - @Insert({"INSERT INTO epi_inventory_line_items (facilityVisitId, programProductId, productCode, productName, productDisplayOrder, idealQuantity, createdBy, modifiedBy) VALUES ", - "(#{facilityVisitId}, #{programProductId}, #{productCode}, #{productName}, #{productDisplayOrder}, #{idealQuantity}, #{createdBy}, #{modifiedBy})"}) + @Insert({"INSERT INTO epi_inventory_line_items (facilityVisitId, programProductId, productCode, productName, productDisplayOrder, idealQuantity, idealQuantityByPackSize, createdBy, modifiedBy) VALUES ", + "(#{facilityVisitId}, #{programProductId}, #{productCode}, #{productName}, #{productDisplayOrder}, #{idealQuantity}, #{idealQuantityByPackSize}, #{createdBy}, #{modifiedBy})"}) @Options(useGeneratedKeys = true) void insertLineItem(EpiInventoryLineItem lineItem); diff --git a/modules/distribution/src/test/java/org/openlmis/distribution/domain/ChildCoverageLineItemTest.java b/modules/distribution/src/test/java/org/openlmis/distribution/domain/ChildCoverageLineItemTest.java index 0365a14837..9a7c75134e 100644 --- a/modules/distribution/src/test/java/org/openlmis/distribution/domain/ChildCoverageLineItemTest.java +++ b/modules/distribution/src/test/java/org/openlmis/distribution/domain/ChildCoverageLineItemTest.java @@ -71,7 +71,7 @@ public void shouldRoundTargetGroupCorrectly() throws Exception { ChildCoverageLineItem childCoverageLineItem = new ChildCoverageLineItem(facilityVisit, facility, targetGroupProduct, "BCG", period.getNumberOfMonths()); assertThat(childCoverageLineItem.getVaccination(), is("BCG")); - assertThat(childCoverageLineItem.getTargetGroup(), is(44)); + assertThat(childCoverageLineItem.getTargetGroup(), is(43)); assertThat(childCoverageLineItem.getFacilityVisitId(), is(3L)); } diff --git a/modules/distribution/src/test/java/org/openlmis/distribution/domain/EpiInventoryLineItemTest.java b/modules/distribution/src/test/java/org/openlmis/distribution/domain/EpiInventoryLineItemTest.java index d511669070..34e91944f2 100644 --- a/modules/distribution/src/test/java/org/openlmis/distribution/domain/EpiInventoryLineItemTest.java +++ b/modules/distribution/src/test/java/org/openlmis/distribution/domain/EpiInventoryLineItemTest.java @@ -38,10 +38,12 @@ public void shouldCreateEpiInventoryLineItemFromFacilityProgramProduct() throws facilityProgramProduct.setProduct(product); FacilityProgramProduct spyFPP = spy(facilityProgramProduct); doReturn(567).when(spyFPP).calculateIsa(420L, 5); + doReturn(57).when(spyFPP).calculateIsaByPackSize(420L, 5); EpiInventoryLineItem lineItem = new EpiInventoryLineItem(6L, spyFPP, 420L, 5); assertThat(lineItem.getIdealQuantity(), is(567)); + assertThat(lineItem.getIdealQuantityByPackSize(), is(57)); assertThat(lineItem.getProductName(), is("Primary Name")); assertThat(lineItem.getProductCode(), is("P10")); assertThat(lineItem.getProductDisplayOrder(), is(1)); diff --git a/modules/openlmis-web/karma.config.js b/modules/openlmis-web/karma.config.js index 29896ebf9e..8ebaf2dc69 100644 --- a/modules/openlmis-web/karma.config.js +++ b/modules/openlmis-web/karma.config.js @@ -51,18 +51,23 @@ module.exports = function (config) { plugins: [ 'karma-jasmine', 'karma-coverage', + 'karma-htmlfile-reporter', 'karma-firefox-launcher' ], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' - reporters: ['progress', 'coverage'], + reporters: ['progress', 'coverage', 'html'], coverageReporter: { type: 'html', dir: '../../../test/coverage/' }, + htmlReporter: { + outputFile: '../../../test/karma/units.html' + }, + preprocessors: { 'js/**/*.js': ['coverage'] }, diff --git a/modules/openlmis-web/package.json b/modules/openlmis-web/package.json index 4edeb817b0..18395b1614 100644 --- a/modules/openlmis-web/package.json +++ b/modules/openlmis-web/package.json @@ -9,6 +9,11 @@ "grunt-contrib-watch": "~0.5.3", "grunt-contrib-uglify": "~0.2.4", "matchdep": "~0.1.2", - "grunt": "~0.4.1" + "grunt": "~0.4.1", + "karma": "~0.12.19", + "karma-coverage": "~0.2.5", + "karma-htmlfile-reporter": "~0.1", + "karma-jasmine": "~0.1.5", + "karma-firefox-launcher": "~0.1.3" } } diff --git a/modules/openlmis-web/src/main/java/org/openlmis/web/controller/FacilityController.java b/modules/openlmis-web/src/main/java/org/openlmis/web/controller/FacilityController.java index 441d239c93..27be873565 100644 --- a/modules/openlmis-web/src/main/java/org/openlmis/web/controller/FacilityController.java +++ b/modules/openlmis-web/src/main/java/org/openlmis/web/controller/FacilityController.java @@ -15,6 +15,7 @@ import org.openlmis.core.domain.FacilityType; import org.openlmis.core.domain.Pagination; import org.openlmis.core.exception.DataException; +import org.openlmis.core.repository.FacilityOperatorRepository; import org.openlmis.core.service.FacilityService; import org.openlmis.core.service.ProgramService; import org.openlmis.web.model.FacilityReferenceData; @@ -58,6 +59,9 @@ public class FacilityController extends BaseController { @Autowired private FacilityService facilityService; + @Autowired + private FacilityOperatorRepository facilityOperatorRepository; + @Autowired private ProgramService programService; @@ -102,7 +106,7 @@ public List getHomeFacility(HttpServletRequest httpServletRequest) { public Map getReferenceData() { FacilityReferenceData facilityReferenceData = new FacilityReferenceData(); return facilityReferenceData.addFacilityTypes(facilityService.getAllTypes()). - addFacilityOperators(facilityService.getAllOperators()). + addFacilityOperators(facilityOperatorRepository.getAll()). addGeographicZones(facilityService.getAllZones()). addPrograms(programService.getAll()).get(); } diff --git a/modules/openlmis-web/src/main/resources/applicationContext.xml b/modules/openlmis-web/src/main/resources/applicationContext.xml index 1076847732..42479d7f29 100644 --- a/modules/openlmis-web/src/main/resources/applicationContext.xml +++ b/modules/openlmis-web/src/main/resources/applicationContext.xml @@ -279,6 +279,69 @@ + + + + + org.openlmis.core.domain.DosageUnit + + + + + + + + + org.openlmis.core.domain.ProductForm + + + + + + + + + org.openlmis.core.domain.Program + + + + + + + + + org.openlmis.core.domain.GeographicLevel + + + + + + + + + org.openlmis.core.domain.FacilityOperator + + + + + + + + + org.openlmis.core.domain.FacilityType + + + + + + + + + org.openlmis.core.domain.RegimenCategory + + + + diff --git a/modules/openlmis-web/src/main/resources/default.properties b/modules/openlmis-web/src/main/resources/default.properties index 625da53e32..4ba94bac65 100644 --- a/modules/openlmis-web/src/main/resources/default.properties +++ b/modules/openlmis-web/src/main/resources/default.properties @@ -85,4 +85,4 @@ openlmis.conn.pool.statementCacheNumDeferredCloseThreads = 0 openlmis.conn.pool.testConnectionOnCheckin = false openlmis.conn.pool.unreturnedConnectionTimeout = 0 -locales.supported = en, pt, es +locales.supported = en, pt, es, fr diff --git a/modules/openlmis-web/src/main/resources/messages.properties b/modules/openlmis-web/src/main/resources/messages.properties index 2a800c014c..35e833533a 100644 --- a/modules/openlmis-web/src/main/resources/messages.properties +++ b/modules/openlmis-web/src/main/resources/messages.properties @@ -11,4 +11,5 @@ label.locale.en = English label.locale.pt = portugu\u00EAs label.locale.es = espa\u00F1ol +label.locale.fr = Français diff --git a/modules/openlmis-web/src/main/resources/messages_en.properties b/modules/openlmis-web/src/main/resources/messages_en.properties index 0e854ccbb2..a775997cc6 100644 --- a/modules/openlmis-web/src/main/resources/messages_en.properties +++ b/modules/openlmis-web/src/main/resources/messages_en.properties @@ -141,6 +141,8 @@ upload.record.error = {0} in Record No. "{1}" error.upload.invalid.header = "Invalid Headers in upload file: {0}" error.upload.missing.mandatory.columns = "Missing Mandatory columns in upload file: {0}" error.upload.header.missing = "Header for column ({0}) is missing." +label.dosage.units = Dosage Units +label.product.forms = Product Forms error.duplicate.product.code.program.code = Duplicate entry for Product Code and Program Code combination found error.duplicate.facility.approved.product = Duplicate facility approved product. @@ -148,10 +150,14 @@ error.duplicate.facility.code = Duplicate Facility Code error.duplicate.delivery.zone = Duplicate delivery zone Code found error.duplicate.delivery.zone.program = Duplicate Delivery zone code and Program code combination found error.duplicate.delivery.zone.member = Duplicate Delivery Zone code and Member code combination found +error.duplicate.dosage.unit.code = Duplicate Dosage Unit code found +error.duplicate.product.form.code = Duplicate Product Form code found error.duplicate.geographic.zone.code = Duplicate Geographic Zone Code +error.duplicate.geographic.level.code = Duplicate Geographic Level Code error.duplicate.product.category = Duplicate Product Category error.duplicate.product.group.code = Duplicate Product Group Code error.duplicate.product.code = Duplicate Product Code +error.duplicate.program.code = Duplicate Program Code error.duplicate.program.product.combination = Duplicate entry for Product Code and Program Code combination found error.duplicate.program.product = Duplicate Program Product error.duplicate.program.supported = Facility has already been mapped to the program @@ -164,6 +170,8 @@ error.duplicate.employee.id = Duplicate employee id error.duplicate.email = Duplicate email address error.duplicate.user.name = Duplicate User Name error.duplicate.role = Duplicate Role found +error.duplicate.facility.operator.code = Duplicate Facility Operator Code +error.duplicate.facility.type = Duplicate Facility Type message.user.created.success.email.sent = User "{0} {1}" has been successfully created, password link has been sent on registered Email address message.user.updated.success = User "{0} {1}" has been successfully updated email.sent = Email sent @@ -636,6 +644,7 @@ placeholder.select.product = -- Select product -- placeholder.search.by.status = Search by status... placeholder.new.password = New password placeholder.reenter.password = Re-enter new password +placeholder.password.rules = Password should be between 8 to 10 characters, should not contain spaces and contain at least 1 number. placeholder.type.comment = Type your comment here msg.product.added = Products added successfully error.correct.highlighted = Please correct the highlighted fields before submitting @@ -784,6 +793,8 @@ label.supply.lines = Supply Lines label.facility.approved.products = Facility Approved Products label.product.prices.program = Product Prices per Program label.product.category = Product Category +label.programs = Programs +label.geographic.levels = Geographic Levels label.geographic.zones = Geographic Zones label.product.groups = Product Groups label.delivery.zones = Delivery Zones @@ -1077,7 +1088,10 @@ label.reason.for.no.visit = Why did no one visit? label.bad.weather = Road impassable or bad weather label.no.transport = Transport not available label.facility.closed = The health centre was closed at the time of visit -label.unavailable.funds = Per diem or fuel funds not available +label.unavailable.funds.fuel = Fuel funds not available +label.unavailable.funds.perdiem = Per diem funds not available +label.refrigerators.not.working = Non-Functional Refrigerators +label.no.refrigerators = No Refrigerators label.not.part.of.program = The health center is not part of the DLS program msg.pod.save.success = POD saved successfully! @@ -1352,3 +1366,9 @@ label.doses.per.month = Doses per month label.price.per.pack = Price per pack error.program.products.not.done = Mark all program products as 'Done' before saving the form facility.approved.product.does.not.exist = Facility Approved Product does not exist. + +label.facility.operators = Facility Operators +label.facility.types = Facility Types + +error.duplicate.regimen.category = Duplicate Regimen Category +label.regimen.categories = Regimen Categories diff --git a/modules/openlmis-web/src/main/resources/messages_es.properties b/modules/openlmis-web/src/main/resources/messages_es.properties index 483057c7f0..a1da2b4220 100644 --- a/modules/openlmis-web/src/main/resources/messages_es.properties +++ b/modules/openlmis-web/src/main/resources/messages_es.properties @@ -637,6 +637,7 @@ placeholder.select.product = - Seleccione producto - placeholder.search.by.status = B\u00FAsqueda por el estado ... placeholder.new.password = Nueva contrase\u00F1a placeholder.reenter.password = Vuelva a introducir la contrase\u00F1a nueva +placeholder.password.rules = La contraseña debe tener entre 8 y 10 caracteres , no debe contener espacios y contener al menos 1 número. placeholder.type.comment = Escriba su comentario aqu\u00ED msg.product.added = Productos agregado con \u00E9xito error.correct.highlighted = Corrija los campos resaltados que antes de presentar @@ -1062,7 +1063,8 @@ label.bad.weather=Road imp\u2202\u0192\u00A9\u02D9\u2206\u02DAweather label.no.transport=Tran\u2211\u00B4\u2020\u00A5\u00A8\u02C6\u2248\u00E7\u221A\u222B\u02DClable label.facility.closed=The hea\u2202\u2206\u02DA\u00AC\u221A\u222B\u02DC visit label.not.part.of.program=The health c\u00A9\u2202\u00DF\u0192\u2202\u0192\u00A9\u02DA\u00AC\u02D9\u00A9\u0192\u2206\u02D9\u0192\u2248\u00A9\u222B\u221Ae DLS program\ -label.unavailable.funds=Per die\u2206\u00A9\u0192\u02D9\u00B5\u00A9\u2206\u2264\u02D9\u00B5 ds not available +label.unavailable.funds.fuel=Fondos de combustible no está disponible +label.unavailable.funds.perdiem=Per diem fondos no disponible msg.pod.save.success = POD saved˚ succes¬sfully! create.user.order.fulfillment.roles = Order Fulfillment Roles∂ @@ -1225,6 +1227,10 @@ header.max.months.of.stock = Max mon¬ths of stock header.min.months.of.stock = Min mon∆ƒths of stock header.global.active = Global act˙†∂ive header.active.at.program = Act˙∂ive at program +label.dosage.units=Dosis Unidades +error.duplicate.dosage.unit.code=Código de unidad de dosificación es duplicado +error.duplicate.product.form.code=Duplicar el código de forma del producto foun +label.product.forms=Formas del producto msg.records.found = {0} rec∂ƒ∂ç©¥˙¨ˆ∆ød label.clear.search = Clƒ©ç√˙ ©¨∆rch msg.enter.product.code.name = Enter prod∆©˚uct code or name @@ -1333,3 +1339,14 @@ label.doses.per.month = Dos∑es per month label.price.per.pack = Price∑ per pack error.program.products.not.done = Mark all progßΩ∂≈ƒç©√˙∫∆˜ts as 'Done' before saving the form facility.approved.product.does.not.exist = Facility Ap¨ˆ¨ved Produ©˙††††∆¨es not exist. + +error.duplicate.program.code=Duplicar Código del Programa +label.programs=Programas +label.geographic.levels=Niveles Geográficos +error.duplicate.geographic.level.code=Duplicate Code Nivel Geographic +error.duplicate.facility.operator.code=Duplicar Facilidad Código Operador +label.facility.operators=Operadores de Instalaciones +error.duplicate.facility.type=Duplicar Tipo de Instalaciones +label.facility.types=Tipos de Instalaciones +error.duplicate.regimen.category=Duplicar Régimen Categoría +label.regimen.categories=Régimen Categorías diff --git a/modules/openlmis-web/src/main/resources/messages_fr.properties b/modules/openlmis-web/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..5adf51fe0e --- /dev/null +++ b/modules/openlmis-web/src/main/resources/messages_fr.properties @@ -0,0 +1,1371 @@ +# +# This program is part of the OpenLMIS logistics management information system platform software. +# Copyright \u00A9 2013 VillageReach +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +# \u00A0 +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\u00A0 See the GNU Affero General Public License for more details. +# You should have received a copy of the GNU Affero General Public License along with this program.\u00A0 If not, see http://www.gnu.org/licenses. \u00A0For additional information contact info@OpenLMIS.org.\u00A0 +# + +label.currency.symbol = $ +button.add = Ajouter +button.add.new = Ajouter nouveau +button.cancel = Annuler +button.remove = Supprimer +button.create = Créer +button.ok = OK +button.close = Fermer +button.done = Terminé +button.save = Enregistrer +button.retry = Refaire +button.submit = Soumettre +button.yes = Oui +button.no = Non +button.edit = Corriger +button.restore = Restaurer +button.delete = Supprimer +button.disable = Désactiver +button.enable = Activer +button.authorize = Autoriser +button.approve = Approuver +button.print = Imprimer +button.proceed = Procéder +button.test.calculation = Eprouver le calcul +button.edit.formula = Corriger la formule +button.search = Rechercher +button.convert.to.order = Transformer en commande +button.use.calculated = Utilisez calculé +button.use.all.calculated = Restaurer tout aux ISAs déjà calculés +button.add.new.row = + Ajouter nouvelle ligne +msg.loading = Chargement ... +label.active = Actif +label.inactive = Inactif +label.products = Produits +label.product = Produit +label.calculated.isa = ISA Calculé +label.overridden.isa = ISA Substitué +message.isa.save.success = ISA enregistré avec succès + +label.app.header = Système Informatisé d’Information Logistique +msg.password.change.success = Mot de passe modifié\! +msg.sign.in = Connectez-vous s'il vous plait avec votre nouveau mot de passe +label.change.password = Modifier votre mot de passe +label.sign.in = Se connecter +button.sign.in = Se connecter +label.product.name = Nom du produit +label.isa.formula = Formule d'ISA +label.program.product = Configuré ISA du produit +label.isa.formula.modal = Formule d'ISA pour + +label.isa.formula.modal.formula.variables = Variables de formule +label.isa.formula.modal.minimum.value = Quantité minimale +label.who.ratio = Pourcentage de la population ciblée +label.doses.per.patient.per.year = Doses par patient par an +label.average.wastage.rate = Facteur le gaspillage +label.buffer.stock.level = Niveau du stock de sécurité +label.adjustment.quantity = La quantité de réglage +label.isa.minimum.value = Quantité minimale d'ISA +label.isa.maximum.value = Quantité maximale d'ISA +error.enter.numeric.value = Saisissez le quantité numérique +error.enter.number.only = Saisissez uniquement des chiffres + +label.isa.monthly.restock.amount = Montant de réapprovisionnement mensuel \= {min, max} +label.isa.population.of = Quantité calculée pour une population de +label.isa.doses.of = Doses de +label.isa.will.need = seront +label.isa.per.month = par mois +message.no.products.mapped= Aucun produit tracé au programme sélectionné +error.number.only = Uniquement chiffres +error.invalid.date.format = Saisir les date en format\: MM/AAAA +error.reason.required = Saisissez un motif s'il vous plait +label.category = Catégorie/Classe +label.product.code = Code/nom de produit +label.no.products = Pas de produits. +label.confirm.action = Vérifier action +msg.rnr.save.success = R&R enregistré avec succès\! +msg.rnr.submitted.success = R&R soumis avec succès\! +msg.rnr.authorized.success = R&R autorisé avec succès\! +msg.rnr.approved.success = R&R a approuvé avec succès\! +msg.rnr.not.started = Pas encore commencé +msg.rnr.previous.pending = R&R précédent en attente +msg.no.period.available = Aucune période actuelle défini. Contactez l'administrateur s'il vous plait +msg.question.confirmation = Êtes-vous sûr? Vérifiez s'il vous plaît. +msg.select.atleast.one.rnr = Sélectionner au moins une réquisition à convertir en commande +msg.rnr.converted.to.order = La/Les réquisition(s) a/ont été convertis aux commandes +msg.error.occurred = Erreur +msg.rnr.submitted.without.supervisor = Il n'existe pas un nodule de surveillance pour avancer le traitement de ce R&R. Contactez l'administrateur s'il vous plait. +msg.rnr.authorized.without.supervisor = Il n'y a pas un superviseur désigné pour la révision et l'approbation de ce R&R. Contactez l'administrateur s'il vous plait +msg.rnr.approved.without.supervisor = Il n'y a pas un superviseur désigné pour la révision et l'approbation de ce R&R. Contactez l'administrateur s'il vous plait +msg.no.product.in.order = Aucun produit dans cet ordre +msg.no.rnr.found = Aucune réquisition trouvée +error.rnr.validation = Il y a des fautes dans la R&R, pour continuer, corrigez-les +error.stock.on.hand.negative = Le calcul du stockage actuel est négatif, validez les données s'il vous plait +error.quantity.consumed.negative = Le calcul de la quantité total consommé est négatif, validez les données s'il vous plait +error.arithmetically.invalid = Les données sont arithmétiquement incorrectes, vérifiez-les s'il vous plait + +label.rnr.add.non.full.supply = Ajouter les produits approvisionnés non-complétés +error.rnr.required.fields.missing = Dans le R&R, remplissez touts les champs souligner avant de soumettre +error.rnr.authorization = R&R déjà autorisé +error.rnr.submission = R&R déjà soumis +rnr.already.approved = R&R déjà approuvé +error.requisition.not.initiated = Réquisition pas encore lancé +error.requisition.not.submitted = Réquisition pas encore soumis +error.requisition.not.exist = Réquisition n'existe pas. Initiez-le s'il vous plait +error.no.requisition.group = Le programme sélectionné n'est pas lié avec un calendrier spécifique pour la génération d'un R&R. Contactez l'administrateur pour corriger cette faute. +error.user.needs.to.enter.requested.quantity.reason = Si "{0}" s'est affiché, "{1}" doit être affiché aussi +error.rnr.previous.not.filled = Complétez s'il vous plait tous les R&R de la/les période(s) précédente(s) +error.rnr.template.not.defined = Contactez l'administrateur pour définir le modèle R&R pour ce programme +error.interdependent.fields.can.not.be.calculated = Champs interdépendants (''{0} '', ''[1} '') ne peuvent pas être de type Calculé en même temps +error.column.should.be.visible.if.user.input = Si l'utilisateur a saisit '' {0} '' il devrait être visible +msg.rnr.arithmeticValidation.turned.on = Pour effectuer la validation arithmétique, le système attribue ses valeurs par défaut pour A, B et D s'ils ne sont pas disponible pour saisie par l'utilisateur +error.rnr.operation.unauthorized = L'utilisateur n'est pas autorisé +error.rnr.not.found = Réquisition introuvable +error.supervisory.node.invalid = Code de nodule de surveillance non valide +error.supervisory.node.not.top.node = Nodule de surveillance n'est pas la nodule la plus en haut +error.supervisory.node.parent.not.exist = Nodule de surveillance n'existe pas +error.minimum.greater.than.maximum = Valeur maximale ne peut être inférieure à la valeur minimale + +#UPLOAD +link.admin.upload = Télécharger +link.download.csv = Télécharger CSV +upload.select.type = Sélectionnez un type de téléchargement +upload.select.file = Sélectionnez un fichier à télécharger +upload.incorrect.file = Fichier incorrecte +upload.file.empty = Fichier est vide +upload.incorrect.file.format = Format de fichier incorrect. Se il vous plaît télécharger {0} données dans un fichier «.csv». +upload.file.successful = Fichier téléchargé avec succès. "Nombre de données traités\: {0}". +upload.label.type = Type de téléchargement +upload.label.file= Fichier +upload.record.error = {0} dans donnée "{1}" +error.upload.invalid.header = "En-têtes incorrectes dans le fichier de téléchargement\: {0}" +error.upload.missing.mandatory.columns = "Colonnes obligatoires manquants dans le fichier de téléchargement\: {0}" +error.upload.header.missing = "En-tête de la colonne ({0}) est manquant." +label.dosage.units = Unités de dosage +label.product.forms = Formulaires de produits + +error.duplicate.product.code.program.code = Saisie en double pour la combinaison du code de produit et du code de programme trouvé +error.duplicate.facility.approved.product = Produit approuvé par une formation sanitaire en double +error.duplicate.facility.code = Code en double d'formation sanitaire +error.duplicate.delivery.zone = Code en double de commune de livraison trouvé +error.duplicate.delivery.zone.program = Combinaison en double du code de commune de livraison et le code du programme trouvé +error.duplicate.delivery.zone.member = Combinaison en double du code de zone de livraison et le code de membre trouvé +error.duplicate.dosage.unit.code = Code en double d'unité de dosage trouvée +error.duplicate.product.form.code = Code en double pour la formulaire de produit trouvé +error.duplicate.geographic.zone.code = Code en double de la zone géographique +error.duplicate.geographic.level.code = Code en double du niveau géographique +error.duplicate.product.category = Catégorie de produit en double +error.duplicate.product.group.code = Code de groupe des produits en double +error.duplicate.product.code = Code de produit en double +error.duplicate.program.code = Code de produit en double +error.duplicate.program.product.combination = Saisie trouvé en double pour la combinaison du code du produit et le code du programme +error.duplicate.program.product = Produit de programme en double +error.duplicate.program.supported = Cette formation sanitaire a été déjà tracée au programme +error.duplicate.requisition.group.code = Code de groupe de réquisition trouvé en double +error.duplicate.requisition.group.member = Membre du groupe de réquisition trouvé en double +error.duplicate.requisition.group.program.schedule = Combinaison du code du groupe de réquisition et le code du programme trouvé en double +error.duplicate.supervisory.node = Nodule de surveillance trouvé en double +error.duplicate.supply.line = Saisie trouvée en double pour la conduite de livraison +error.duplicate.employee.id = Identifiant d'employé en double +error.duplicate.email = Adresse email en double +error.duplicate.user.name = Nom d'utilisateur en double +error.duplicate.role = Rôle trouvé en double +error.duplicate.facility.operator.code = Code de gérant d’formation sanitaire en double +error.duplicate.facility.type = Type d’formation sanitaire en double +message.user.created.success.email.sent = Le compte de "{0} {1}" a été créé. Un lien vers le mot de passe a été envoyé dans la boîte éléctronique enregistrée. +message.user.updated.success = Utilisateur "{0} {1}" à été mis à jour +email.sent = Email envoyé +password.reset = Mot de passe restauré + +error.schedule.code.exist = Un calendrier avec ce code existe déjà +schedule.without.code = Le calendrier ne peut pas être enregistré sans son code +schedule.without.name = Le calendrier ne peut pas être enregistré sans son nom +schedule.code.invalid = Code de calendrier non valide +schedule.add.period=Ajouter période +error.period.without.schedule = Période ne peut pas être enregistré sans son calendrier parent +error.period.without.start.date = Période ne peut pas être enregistré sans une date de démarrage +error.period.without.end.date = Période ne peut pas être enregistré sans une date de fin +error.period.without.name = Période ne peut pas être enregistré sans son nom +error.period.exist.for.schedule = Ce nom de période existe déjà dans ce calendrier +error.period.invalid.dates = Date de fin pour la période ne peut pas être antérieure à la date de démarrage +error.period.start.date.less.than.last.period.end.date = Pour cette période, la date de démarrage est plus petite que la date de fin pour la période précédente +error.period.start.date = Pour cette période, la date de démarrage est plus petite que le date actuel +program.code.invalid = Code de programme non valide +error.program.not.push = Ce programme ne soutient pas le mécanisme "poussé" +product.code.invalid = Code de produit non valide +programProduct.product.program.invalid = Combinaison non valide du produit et du calendrier +facilityType.invalid = Type de formation sanitaire non valide +programProduct.program.invalid.code = Code de programme non valide +programProductPrice.invalid.price.per.dosage = Prix d'une dose à l'unité non valide +programProduct.invalid.current.price= Prix d'un paquet à l'unité non valide +supported.programs.invalid = Un programme actif doit avoir une date de démarrage +product.category.name.duplicate = Nom de catégorie de produit trouvé en double +error.reference.data.missing = Données de référence non valide/manquant +error.reference.data.facility.type.missing = Données de référence obligatoires manquant pour "Type de formation sanitaire" +error.reference.data.invalid.facility.type = Données de référence non valides pour "Type de formation sanitaire" +error.reference.data.invalid.operated.by = Données de référence non valides pour "Géré Par" +error.reference.data.invalid.product = Données de référence non valides pour "Catégorie de Produit" +error.reference.data.invalid.product.group = Données de référence non valides pour "Groupe des produits" +error.reference.data.invalid.geo.zone.code = Données de référence non valide pour "Code de Zone Géographique" +error.reference.data.invalid.product.form = Données de référence non valides pour "Forme de Produit" +error.reference.data.invalid.program = Données de référence non valides pour "Code de Programme" +error.reference.data.invalid.dosage.unit = Données de référence non valides pour "Dose unitaire" +error.geo.zone.not.at.lowest.level = Le code de la zone géographique doit être sur le niveau inferieur dans votre hiérarchie +error.incorrect.length = Longueur des données incorrecte +error.requisition.group.not.exist = Groupe de réquisition n'existe pas +error.no.program.mapped.requisition.group = Aucun programme tracé dans ce Groupe de réquisition +error.schedule.not.found = Calendrier introuvable +error.geo.level.invalid = Code de niveau géographique non valide +error.invalid.hierarchy = Hiérarchie non valide +error.geo.zone.parent.invalid = Code de parent de la zone géographique non valide +error.facility.program.mapping.exists = Cette formation sanitaire était déjà tracée au programme +error.facility.requisition.group.mapping.exists = Traçage d’formation sanitaire au groupe de réquisition existe déjà +error.facility.allocation.product.save = Erreur en enregistrant l'allocation des produits de cette formation sanitaire pour ce programme + +user.data.length.incorrect = Mauvais type ou longueur des données +user.login.error = Le nom ou mot de passe que vous avez saisi est incorrecte. Essayez à nouveau de se connecter, s'il vous plait +user.email.invalid = Format d'adresse email est incorrecte +user.email.not.found = Aucune adresse email n’enregistré à votre compte. Contactez l'administrateur. +user.userName.invalid = Format incorrect, les espaces ne sont pas permis dans le nom d'utilisateur +user.email.incorrect = Saisissez une adresse email valable +user.username.incorrect = Saisissez un nom d'utilisateur valable +supervisor.user.not.found = Le nom d'utilisateur d'un superviseur n'existe pas dans le système +user.password.reset.token.invalid = Ce lien n'est plus valable +user.needs.to.enter.dependent.field = L'utilisateur doit saisir "{0}" pour que "{1}" puisse être calculé +error.password.invalid =Le mot de passe n'est pas valable. Un mot de passe doit être comprise d'entre 08 et 10 caractères, avec au moins une chiffre, et ne peut pas inclure des espaces. +error.password.mismatch = Les mots de passe saisis ne correspondent pas. + +unexpected.exception = Il y avait une faute\! Réessayer plus tard s'il vous plait + +form.error = Il y a quelques fautes dans le formulaire. Corrigez-les s'il vous plait + +#emails +account.created.email.subject = Compte créé\: Restaurer votre mot de passe +forgot.password.email.subject = Mot de passe oublié +password.reset.email.body = Salut {0} {1}, \n\n\n\nVotre nom d'utilisateur est\: {2}\n\n\n\nS'il vous plaît utilisez le lien pour créer un nouveau mot de passe. {3}\n\n\n\nMerci + + +create.user.label = Ajouter utilisateur +edit.user.label = Modifier utilisateur +missing.value = Remplissez cette donnée +label.missing.values = Remplissez toutes les données obligatoires +label.basicInformation = Informations de base +create.user.userName = Nom d'utilisateur +create.user.invalid.userName = Format incorrect, les espaces ne sont pas permis dans le nom d'utilisateur +create.user.email= Email +create.user.employeeId = Identifiant d'employé +create.user.firstName = Prénom +create.user.lastName = Nom de famille +create.user.jobTitle = Titre +create.user.officePhone = Numéro de téléphone de bureau +create.user.cellPhone = Numéro de téléphone cellulaire +create.user.primaryNotificationMethod = Méthode de notification principale +create.user.homeFacility= Formation sanitaire principale de l'utilisateur +create.user.supervisoryRoles = Rôles superviseurs +create.user.adminRoles = Rôles administratifs et gestionnaires +program.header = Programme +label.supervisory.node = Nodule de surveillance +confirm.programRole.deletion = Tous les programmes et les rôles pour cette formation sanitaire seront supprimés +create.user.role = Rôles +create.user.selectProgram = Sélectionnez un programme s'il vous plait +create.user.selectSupervisoryNode = Sélectionnez un nodule de surveillance s'il vous plait +create.user.selectRoles = Sélectionnez les rôles s'il vous plait +create.user.deleteRoles = Supprimer rôles +create.user.delete.warning = Tous les rôles pour ce programme et cette nodule pour l'utilisateur seront supprimées +create.user.homeRoles.delete.warning =Tous les rôles pour ce programme pour l'utilisateur seront supprimées +create.user.homeFacility.roles = Rôles de la formation sanitaire principale +msg.no.matches = Aucun résultat trouvé pour '{0}' +msg.one.match = 1 résultat trouvé pour '{0}' +msg.many.matches = {0} résultats trouvés pour '{1}' + +search.threeCharacters = Au moins trois (03) caractères +search.viewHere = Visualiser ici + +message.setProgramStartDate = Régler la date de début du programme +message.dateChangeConfirmMessage = Commençant à cette date, les personnels de cette formation sanitaire soumettront les R&R déjà échues +search.facility.header = Recherche une formation sanitaire +create.facility.addNew = Ajouter une nouvelle formation sanitaire +label.facility.edit = Modifier l'formation sanitaire +delete.facility.header = Supprimer l'formation sanitaire +disable.facility.header = Désactiver l'formation sanitaire +disable.facility.confirm = "{0}" / "{1}" sera désactivée dans le système +delete.facility.program.header = Supprimer programme soutenu +delete.facility.program.confirm = Programme soutenu "{0}" sera supprimé de cette formation sanitaire +create.facility.basicInformation = Informations de base +create.facility.code = Code de formation sanitaire +create.facility.gln = GLN +create.facility.name = Nom de formation sanitaire + +select.value = Sélectionnez une valeur s'il vous plait +create.facility.operatedBy = Géré par +create.facility.serviceDeliveryPoint = Endroit de livraison du service? +create.facility.activeFacility = Formation sanitaire actif? +create.facility.goLiveDate = Date de démarrage en direct +create.facility.goDownDate = Date de fin +create.facility.description = Description de la formation sanitaire +create.facility.contactInformation = Contact +create.facility.addressLine1 = Adresse 1e ligne +create.facility.addressLine2 = Adresse 2e ligne +create.facility.phone = Téléphone +create.facility.fax = Fax +create.facility.programsSupported = Programmes soutenus +create.facility.programs = Programmes +create.facility.active = Actif? +create.facility.startDate = Date de début +create.facility.programType = Type de programme +label.allocate = Allouer +label.request = Demander +label.isa.header = Valeurs d'ISA pour +label.new.regimen = Nouvelle régime +link.modify.isa = Modifier valuers d'ISA +create.facility.mandatoryStartDate = Date de début est obligatoire +create.facility.removeProgram = &heures; +create.facility.geographicalInformation = Informations Géographiques +label.geographic.zone = Zone géographique +label.catchment.population = Population de la zone géographique +integer.value = Chiffre devrait être nombre entier +label.latitude = Latitude +label.longitude = Longitude +create.facility.altitude = Altitude +label.latitude.value = La valeur doit être saisie en chiffres et entre -999,99999 et 999,99999 (05 décimales) +label.longitude.value = La valeur doit être saisie en chiffres et entre -999,99999 et 999,99999 (05 décimales) +create.facility.altitude.value = La valeur doit être saisie en chiffres et entre -999,9999 et 999,9999 (04 décimales) +create.facility.otherInformation = Informations Divers +create.facility.coldStorageGrossCapacity = Capacité brute du stockage frigorifique +create.facility.coldStorageNetCapacity = Capacité total du stockage frigorifique +create.facility.coldStorageCapacity.value = La valeur doit être saisie en chiffres et doit être moins de 9999,9999 +create.facility.electricityAvailable = Electricité disponible à la formation sanitaire? +create.facility.internetConnection = Connexion internet disponible à la formation sanitaire? +create.facility.electronicSCC = La formation sanitaire à un SCC électronique ? +create.facility.electronicDAR = La formation sanitaire à un DAR électronique ? +create.facility.enabled = La formation sanitaire est activée ? +create.facility.suppliesOthers = La formation sanitaire approvisionne d'autres ? +create.facility.comments = Commentaires +create.facility.enableFacility = Activer formation sanitaire +create.facility.activateFacility = Activer formation sanitaire +create.facility.setFacilityActive = Voulez-vous activer cette formation sanitaire? +disable.facility.success = "{0}" / "{1}" est maintenant désactivé +enable.facility.success = "{0}" / "{1}" est maintenant activé + +message.role.created.success = "{0}" créé avec succès +message.role.updated.success = "{0}" mise à jour avec succès +error.role.without.name = Rôle ne peut pas être créée sans nom. +error.role.without.rights = Pour créer un rôle, il faut designer des droits liés à-t-il +create.role.addNew = Ajouter nouvelle rôle +edit.role.edit=Modifier rôle +create.role.roleName=Nom de rôle +create.role.description=Description de rôle +create.role.roleType=Type de rôle +create.role.mixedWarning=Un rôle unique ne peut pas être composée d’un mélange de deux types +create.role.adminRole=Rôle administratif et gestionnaire +create.role.programBasedRole=Rôle basé sur un programme et une formation sanitaire +create.role.assignRights=Droits désignés +create.role.adminRights=Droits administratifs et gestionnaires +create.role.reportRights=Droits des rôles +create.role.selectRightWarning=Sélectionnez au moins un droit pour cette rôle +create.user.deleteAdminRoles=Vous avez sélectionné de supprimer ce rôle, étés-vous sur? +create.user.deleteAdminRoleHeader= Supprimer rôle administratif +error.duplicate.programNode.combination = La combinaison de ce programme et ce module est déjà sélectionné +error.duplicate.requisition.group.program.combination = Code de groupe de réquisition et code du programme trouvé en double +error.program.type.not.supported.requisitions = Ce type de programme n’est pas soutenu pour réquisitions +error.requisition.group.not.exists = Code de group de réquisition n'existe pas +error.schedule.not.exists = Code de calendrier n'existe pas +error.direct.delivery.drop.off.facility.combination.incorrect = Combinaison incorrecte de la livraison directe et l'formation sanitaire approvisionnée +error.drop.off.facility.not.defined = Code d'formation sanitaire approvisionnée n'est pas défini +error.drop.off.facility.not.present = Code d'formation sanitaire approvisionnée n'existe pas +error.select.value = Sélectionnez une valeur s'il vous plait +error.shipment.file = Erreur dans le fichier de livraison + +#REPORTS +reports.header= Rapports +no.reports.message= Pas de rapport +report.name.label = Nom du rapport +view.label = Afficher +report.type.pdf = PDF +report.type.xls = XLS +report.type.csv = CSV +report.type.html = HTML +create.report.addNew = Ajouter un nouveau rapport +create.report.reportName=Nom du rapport +create.report.uploadFile=Télécharger un fichier +create.report.success= Rapport créé avec succès +report.template.error.file.empty = Fichier téléchargé est vide +report.template.error.file.type = Fichier téléchargé ne pas avoir le type requis (jrxml) +report.template.error.file.missing = Fichier modèle est obligatoire pour créer rapport +report.template.name.already.exists = Rapport avec le même nom existe déjà +report.template.error.file.invalid = Fichier téléchargé ne est pas valide +report.template.error.reading.file = Erreur pendant la lecture du fichier modèle pour le rapport +report.template.parameter.display.name.missing = Nom d’affichage manquant pour le paramètre "{0}" +report.template.extra.properties = Caractéristique non identifiée trouve pour paramètre "{0}" +error.enabled.false=Formation sanitaire désactivée désignée comme active trouvée + +messages.commentBox.noComment=Aucun commentaire n'a encore été ajouté. +comments.header = Commentaires +label.by = Par\: + + +header.code = Code +header.name = Nom +header.rights=Droits +label.description = Description +header.lastModified = Dernière mise à jour +facility.feed.invalid.url = URL valide pour l'alimentation de l'formation sanitaire +header.view.requisitions = Afficher réquisitions + +app.title = Open-LMIS + +#CONFIGURE RNR +template.save.success = Modèle enregistré avec succès\! +requisition.template.header=Rapport Configurer et Réquisition modèle +template.header.display=Afficher +template.header.label=Nom +template.header.source=Source +message.arithmeticValidation.status=Quantité totale consommée (C) et le stock disponible (E) sont configurés comme saisies de l'utilisateur. Validation des saisie (C \= à + B +/- D -E) est +message.arithmeticValidation.toggle=Tournez {0} +template.configured=Configuré +template.configure=Configurer +template.programName = Programme\: +template.change = (Modifier) +configure.rnr.header = Configurer R & amp; Modèle R +link.edit = Éditer + +#ROLE +program.facility.rights=Droit basé sur programme et formation sanitaire +roles.header = Rôles +header.change.roleType = Modifier type de rôle +confirm.roleType.change = Si vous modifiez le type, toutes les sélections dans le type actuel seront supprimées. Voulez-vous continuer? + +#PERIODS +error.identify.schedule = Erreur\: identification du calendrier +error.endDate= Date de fin pour la période ne peut pas être antérieure à la date de début +schedules.header = Calendriers +period.schedule.header = Calendrier +period.start.date = Date de début (JJ/MM/AAAA) +period.end.date = Date de fin (JJ/MM/AAAA) +period.total.days=Nombre de jours\: +period.number.of.months = Nombre de mois\: +periods.header = Périodes +period.header.endDate = Date de fin +period.header.startDate = Date de début +period.header.totalDays = Nombre de jours total +period.header.numOfMonths = Nombre de mois +period.header.name = Nom +label.period.start.date = Date de démarrage de la période +label.period.end.date = Date de fin de la période +label.date.submitted = Date soumis +label.date.modified = Date modifié +label.supplying.depot = Entrepôt d'approvisionnement +label.status = Etat +label.order.no = No. de commande +label.facility.code.name = Nom de code de l'formation sanitaire +label.facility.ftp.details = Détails FTP pour l'formation sanitaire +label.order.date.time = Date/Heure de commande +label.order.status = Etat de commande + +label.newPeriod = Nouvelle Période +label.back.schedules= Retournez aux calendriers +label.search.user=Rechercher des utilisateurs +label.rnr.status=Etat de R&R + +#MAIN MENU +menu.header.facilities= Unités sanitaires +menu.header.roles = Rôles +menu.header.schedules = Calendriers +menu.header.users = Utilisateurs + + +error.login.username = Saisissiez votre nom d'utilisateur s'il vous plait +error.login.password = Saisissiez votre mot de passe s'il vous plait +error.authorisation = Vous n'êtes pas autorisé à afficher la page demandée. +email.sent.message= Email envoyé\! +email.check.message= Vérifiez votre email s'il vous plait et cliquez sur le lien indiqué pour modifier votre mot de passe +reset.password.message = Saisissiez votre adresse email OU votre nom d'utilisateur s'il vous plait et nous vous enverrons un message à votre boite électronique enregistré avec un lien pour modifier votre mot de passe. +label.or = OU +welcome.to.message = Bienvenue dans +label.logistics.management = Système Informatisé \n +label.information.systems = d’Information Logistique (SIIL) +link.forgot.password = Mot de passe oublié? +enter.emailInfo = Saisissiez s'il vous plait soit votre email, soit votre nom d'utilisateur +sending.label= Envoi en cours ... + +link.home = Accueil +link.requisitions = Réquisitions +link.requisitions.create.authorize = Créer / Autoriser +link.requisition.approve = Approuver +link.requisitions.convertToOrder = Convertir à la commande +link.requisition.view = Afficher +link.orders = Commandes +link.orders.view = Afficher les commandes +link.pod.manage = Gérer POD +link.reports = Rapports +link.administration = Administration +link.admin.configure = Configurer +link.admin.configure.requisitionTemplate = & R Modèle +link.admin.configure.programProductISA = ISA du programme de produit +link.admin.manage = Gérer + +link.logout = Se déconnecter +message.loggedInAs = Connecté comme +label.initiate.requisition=Initier le Rapport et la Réquisition +label.requisition.facilityType=Type d'formation sanitaire\: +label.requisition.facilityName=Nom d'formation sanitaire +label.program=Programme +label.myFacility=Ma formation sanitaire +label.supervised.Facility=Unités Sanitaires encadrées par moi +label.full.supply.products=Produit(s) complétement(s) approvisionnés +label.non.full.supply.products=Produit(s) pas complétement(s) approvisionnés +label.approve.requisitions=Approuver des réquisitions +label.losses.adjustments=Pertes et modifications +label.add.losses.adjustments=Ajouter une nouvelle perte/modification +label.losses.total=Totale +label.requisition.convertOrder=Convertir réquisitions à commande +label.requisition.list=Liste de réquisition +message.no.rnr.pending.approval=Aucun R & R n’en attente d’approbation +message.no.requisitions.for.conversion= Aucune réquisition à convertir en commande +option.value.all=Tous +option.value.program=Programme +option.value.facility.code=Code d'formation sanitaire +option.value.facility.name=Nom d'formation sanitaire +label.facility=Formation sanitaire +label.facility.operatedBy=Gérer par +label.facility.maximumStock=Niveau de stock maximum +label.emergency.order.point=Point de commande d'urgence +label.facility.reportingPeriod=Période de rapportage +label.requisition=Rapport et Réquisition pour +label.total.cost.full.supply=Montant pour approvisionnement complet des produits +label.total.cost.non.full.supply=Montant pour approvisionnement non-complet des produits +label.total.rnr.cost=Montant R&;R \: +label.order.list=Liste des commandes +label.date.range=Période +label.from=À partir de +label.to=À +message.no.order=Pas de réquisitions ont été encore libérés comme commandes +error.one.page=Erreurs trouvés sur page 01 +error.multiple.pages=Erreurs trouvés sur page {0} + +message.facility.created.success=Formation sanitaire "{0}" créée avec succès +message.facility.updated.success=Formation sanitaire "{0}" mise à jour avec succès + +message.period.added.success=Période ajoutée avec succès +message.period.deleted.success=Période supprimée avec succès +message.schedule.created.success={0} créé avec succès +message.schedule.updated.success={0} mis à jour avec succès + +deliveryZone.code.invalid = Code de la commune de livraison non valide +error.facility.code.invalid = Code de l'formation sanitaire non valide +warehouse.code.invalid = Code de l'entrepôt non valide +facility.exists.for.program.in.multiple.zones = Code de l'formation sanitaire existe pour le même programme dans plusieurs communes de livraison +no.program.mapped.for.delivery.zone = Aucun programme tracé aux ces communes de livraison + +incorrect.date.format= Format de date incorrecte au champ \: {0} {1} {2} +missing.mandatory=Format de date incorrecte au champ \: {0} {1} {2} +incorrect.data.type=Données obligatoires manquants au champ \: {0} {1} {2} +incorrect.file.format = Format de fichier incorrect, nom de colonne manquant +column.do.not.match = Colonnes ne correspond pas aux en-têtes\: {0} {1} {2} {3} +of.record.no = de Donnée No. +in.record.no = en Donnée No. + +#Distribution +link.distributions = Distributions +label.distribution.deliveryZone = Commune de Livraison +link.manage = Gérer +label.manage.distribution = Gérer une Distribution + +label.period = Période +label.periods = Période(s) +create.facility.select.facilityType = --Sélectionnez type de Formation Sanitaire-- +create.facility.select.operatedBy = --Sélectionnez Formation Sanitaire gérée par-- +label.select.geographic.zone = --Sélectionnez zone géographique-- +label.noProgramLeft= --Il ne reste plus des programmes-- +label.select.deliveryZone = --Sélectionnez une Commune de Livraison’-- +label.select.period = --Sélectionnez période-- +label.noneAssigned = --Aucun désigné-- +label.drop.down.select = --Sélectionnez-- +label.select.type=--Sélectionnez Type-- +label.select.facility = --Sélectionnez Formation Sanitaire-- +label.select.program = --Sélectionnez Programme-- +label.none.assigned = --Aucun désigné-- +label.all = Tous + +option.distribution.viewLoadAmount = Afficher somme de stockage à l'entrepôt +option.distribution.inputFacilityData = Saisir les données des formations sanitaires + +#Shipment +error.negative.shipped.quantity = Quantité envoyée ne peut pas être négatif +error.unknown.order = Numéro de commande inconnu +error.unknown.product = Code de produit inconnu +error.duplicate.order = Numéro de commande déjà traité + +#Regimens +regimens.saved.successfully=Régimes enregistré avec succès +error.duplicate.regimen.code = On ne peut pas ajouter un code de régime en double pour le même programme +error.regimens.not.done = Marquez tous les régimes comme "fini" avant d'enregistrer la formulaire +error.regimen.null.label = Les noms de colonnes ne peuvent pas être vides +label.admin.configure.regimenTemplate = Modelé de régime +label.regimen.category = Catégorie +label.regimens = Régime(s) +label.reporting.fields = Champs de reportage +error.regimens.none.selected = Au moins une colonne doit être sélectionnée +label.data.type = Type de saisie +label.column.label = Nom de colonne +label.visible = Visible + +#Reporting fields +regimen.reporting.patients.on.treatment = Nombre de patients actuellements en traitement +regimen.reporting.patients.initiated.treatment = Nombre de patients attendant traitement +regimen.reporting.patients.stopped.treatment = Nombre de patients non plus traités +regimen.reporting.patients.remarks = Commentaires +regimen.reporting.dataType.numeric = Numérique +regimen.reporting.dataType.text = Texte + +label.on=ALLUMER +label.off=ENTEINDRE + +#placeholders +placeholder.username=Nom d'utilisateur +placeholder.password=Mot de passe +placeholder.email = Email +placeholder.filter.products= Filtrer produits +placeholder.facility.search = Saisir le nom ou le code d'formation sanitaire +placeholder.search=Rechercher +placeholder.code=Code +placeholder.name= Nom +placeholder.description.optional = Description (optionnelle) +placeholder.user.search=Saisissez nom d'utilisateur, prénom, nom de famille ou email +placeholder.add.role = + Ajouter rôle +label.in = dans +placeholder.quantity=Quantité +placeholder.explanation=Explication +placeholder.select.category = --Sélectionnez catégorie-- +placeholder.select.product = --Sélectionnez produit-- +placeholder.search.by.status = Recherchez par état +placeholder.new.password = Nouveau mot de passe +placeholder.reenter.password = Saisissez à nouveau votre mot de passe +placeholder.password.rules = Le mot de passe n'est pas valable. Un mot de passe doit être comprise d'entre 08 et 10 caractères, avec au moins une chiffre, et ne peut pas inclure des espaces. +placeholder.type.comment = Saisissez vos commentaires ici +msg.product.added = Produits ajoutés avec succès +error.correct.highlighted = Corrigez les champs souligner avant de soumettre s'il vous plait +msg.no.matches.found = Aucune correspondance trouvée +label.select.node = --Sélectionnez nodule-- +label.select.program.supported = --Sélectionnez programme soutenu-- +label.no.programs.left = --Il ne reste plus des programmes-- +label.column.source.calculated = Calculé +label.column.source.user.input = Saisie d'utilisateur +label.column.source.reference.data = Données de référence + +description.column.product.code = Identificateur unique pour chaque commodité +description.column.product = Nom principal du produit +description.column.dispensing.unit = Unité de distribution pour ce produit +description.column.beginning.balance = Stockage réel pendant la période précédente. Quantité en unités de distribution. +description.column.quantity.received = Quantité totale reçue pendant la dernière période. Quantité en unités de distribution. +description.column.total = Bilan au début et quantité reçue +description.column.quantity.dispensed = Quantité distribuée/consommé pendant la dernière période de rapportage. Quantité en unités de distribution. +description.column.losses.adjustments = Toutes les genres de pertes/modifications faites à l'formation sanitaire +description.column.stock.in.hand = Quantité actuelle du stock réel. Quantité en unités de distribution. +description.column.new.patient.count = Nouvelles données de patients +description.column.stock.out.days = Nombre de jours total que l'formation sanitaire avait des hors-stock +description.column.normalized.consumption = Quantité totale consommé, corrigé pour les jours avec les hors-stocks. Quantité en unités de distribution +description.column.period.normalized.consumption = Consommation moyenne mensuelle, ces trois derniers mois. Quantité en unités de distribution. +description.column.amc = Calcul de stockage maximum, basé sur la consommation et maximum nombre de mois de stock. Quantité en unités de distribution. +description.column.max.stock.quantity = Calcul de stockage maximum, basé sur la consommation et maximum nombre de mois de stock. Quantité en unités de distribution. +description.column.calculated.order.quantity = Quantité réelle prévue après avoir soustrait le stockage actuel. Quantité en unités de distribution. +description.column.quantity.requested = Requête de dérogation de la quantité calculé. Quantité en unités de distribution. +description.column.reason.for.requested.quantity = Explication d'une commande pour une quantité d'autre que la quantité de commande calculé +description.column.quantity.approved = Dernière quantité approuvée. Quantité en unités de distribution +description.column.packs.to.ship = Cartons totaux pour livraison, basé sur la taille des cartons et avec l'arrondissage des valeurs. +description.column.price = Prix par carton. Zéro si pas spécifie. +description.column.cost = Cout total du produit. Zéro si le prix n'est pas défini. +description.column.expiration.date = Date de péremption (MM/AAAA) +description.column.remarks = Autres commentaires + +indicator.column.product.code = O +indicator.column.remarks = L +indicator.column.expiration.date = G +indicator.column.cost = Q +indicator.column.price = T +indicator.column.packs.to.ship = V +indicator.column.quantity.approved = K +indicator.column.reason.for.requested.quantity = W +indicator.column.quantity.requested = J +indicator.column.calculated.order.quantity = I +indicator.column.max.stock.quantity = H +indicator.column.amc = P +indicator.column.normalized.consumption = N +indicator.column.period.normalized.consumption = Z +indicator.column.stock.out.days = X +indicator.column.new.patient.count = F +indicator.column.stock.in.hand = E +indicator.column.losses.adjustments = D +indicator.column.quantity.dispensed = C +indicator.column.total = Y +indicator.column.quantity.received = B +indicator.column.beginning.balance = A +indicator.column.dispensing.unit = U +indicator.column.product = R + +formula.column.cost = V * T +formula.column.packs.to.ship = K/U + règles d'arrondissage +formula.column.calculated.order.quantity = H - E +formula.column.max.stock.quantity = P * StockMaxMensuel +formula.column.amc = (N/M + Ng-1/M + ...Ng-(g-1)/M)/g +formula.column.normalised.consumption = C * (M*30)/((M*30)-X) + ( F* No de comprimés par mois / doses par unité de disitribution) +formula.column.period.normalised.consumption = N*M +formula.column.stock.in.hand = A+B(+/-)D-C +formula.column.losses.adjustments = D1 + D2+D3...DN +formula.column.quantity.dispensed = A + B (+/-) D - E +formula.column.total = A + B + +right.configure.rnr = Admin - Configurer Modèles de Réquisition +right.manage.facility = Admin - Gérer Unités Sanitaires +right.manage.role = Admin - Gérer Rôles +right.manage.schedule = Admin - Gérer Calendriers +right.manage.user = Admin - Gérer Utilisateurs +right.upload = Admin - Gérer Téléchargements +right.view.report = Rapports - Afficher +right.manage.report = Rapports - Gérer +right.view.requisition = Réquisition - Afficher +right.create.requisition = Réquisition - Créer +right.authorize.requisition = Réquisition - Autoriser +right.approve.requisition = Réquisition - Approuver +right.convert.to.order = Réquisition - Convertir à commande +right.view.order = Commande - Afficher +right.manage.program.product = Admin - Gérer Produit de Programme +right.manage.distribution = Allocation - Gérer Distribution +right.manage.regimen.template = Admin - Gérer Modèle de Régime + +create.role.mixed.warning = N.B. Les rôles individuels ne peuvent pas être un mélange de ces types +label.allocation.program.rights = Programme d'allocation basé sur les droits +label.request.program.rights = Programme de requête basé sur les droits +button.view.load.amount = Afficher quantités à charger +label.warehouse.load.amount = Quantité Totale ā Collecter [dans des flacons] +label.population = Population +label.delivery.zone = Commune de Livraison +label.zone = Zone +msg.no.records.found = Aucune donnée trouvée +create.user.allocationRoles = Communes de Livraison +label.select.zone = --Sélectionnez Zone-- +error.select.delivery.zone = Sélectionnez une commune de livraison s'il vous plait +error.select.program = Sélectionnez un programme s'il vous plait +error.select.roles = Sélectionnez des rôles s'il vous plait +error.delivery.zone.program.combination = Combinaison de zone et programme déjà sélectionnée +msg.roles.delivery.zone.deletion = Tous les rôles assignés à cette commune de livraison pour l'utilisateur seront supprimés +label.total = Totale +button.initiate.distribution = Démarrer distribution +label.initiated.distributions = Distributions déjà lancées + +#Distribution +message.distribution.created.success = Les données pour la selection {0}, {1}, {2} ont été téléchargées +message.distribution.already.exists = Cette distribution a été déjà lancée par "{0}" à "{1}". Voulez-vous continuer? +message.distribution.already.cached = Les données sélectionnées pour {0}, {1}, {2} ont été déjà placée en mémoire-cache +message.no.facility.selected = Aucune formation sanitaire sélectionnée +message.no.distribution.initiated = Aucune distribution enregistrée en mémoire-cache + +label.zone.total = Quantité Totale +label.record.data = Energistrer les Données +label.view.data = Afficher données +label.sync = Synchroniser +label.distribution.initiated = Distribution déjà lancée +message.no.facility.available = Programme "{0}" n'est soutenu par aucune formation sanitaire dans la zone de livraison "{1}" + + +error.authentication.failed = Échec de l'authentification +error.mandatory.fields.missing = Champs obligatoires manquants +error.reference.data.parent.facility.virtual = L'unité sanitaire ne peut pas être une formation sanitaire virtuelle +error.agent.already.registered = Agent déjà enregistré +error.agent.not.virtual = Agent n'est pas une formation sanitaire virtuelle +error.invalid.agent.code = Code d'agent non valide +message.success.agent.created = CHW créé avec succès +message.success.agent.updated = CHW mise en jour avec succès +error.active.invalid = Actif devrait être Vrai / Faux +error.agent.deleted = CHW ne peux pas être mise à jour, comme il a été supprimé + +#UPLOAD menu +label.program.supported.facilities = Programmes soutenus par les unités sanitaires +label.supervisory.nodes = Nodules de surveillance +label.requisition.group = Groupes de réquisition +label.map.program.schedule = Tracer les groupes de réquisitions aux programmes + calendrier +label.requisition.group.member = Membres de groupe de réquisition +label.program.products = Produit de Programme +label.supply.lines = Conduite d'approvisionnement +label.facility.approved.products = Produits approuvés par l'formation sanitaire +label.product.prices.program = Prix de produits par programme +label.product.category = Catégorie de produit +label.programs = Programmes +label.geographic.levels = Niveaux géographique +label.geographic.zones = Zones géographique +label.product.groups = Groupes de produit +label.delivery.zones = Communes de Livraison +label.map.delivery.zone.program.schedules = Tracer les communes de livraison aux calendriers de programme +label.delivery.zone.members = Membres de communes de livraison +label.delivery.zone.warehouses = Entrepôts de commune de livraison + +button.reset.password=Restaurer votre mot de passe +password.reset.success=Mot de passe a été restauré avec succès +message.reset.password=Mot de passe restauré pour + +label.summary = Résumé +label.total.cost.full.supply.items = Coût total des produits d'approvisionnement complet +label.total.cost.non.full.supply.items = Coût total des produits d'approvisionnement non complet +label.total.cost = Montant +label.submitted.by = Soumis par +label.date = Date +label.authorized.by = Autorisé par + +disable.user.header=Désactiver l'utilisateur +disable.user.confirm=Utilisateur "{0} {1}" sera désactivé +msg.user.disable.success = Utilisateur "{0} {1}" a été désactivé + + +label.refrigerator.temperature = A quelle température était l'équipement de la chaîne du froid quand vous êtes arrivé? +label.not.recorded = ND +label.refrigerator.working.correctly = Marchait-t-il correctement à votre depart? (2-8°C) +label.yes = Oui +label.no = Non +label.dont.know = Je ne sais pas +label.celcius.symbol = C +label.number.low.alarms = Nombre d’alarme inferieure à 2°C depuis votre dernière visite +label.number.high.alarms = Nombre d’alarme superieure à 8°C depuis votre dernière visite +label.problem.last.visit = Y a-t-il eu un problème avec l'équipement de la chaîne du froid depuis la dernière visite? +label.what.problems = Quels sont les problèmes? +label.operator.error = Panneaux Solaires / Batteries +label.burner.problem = Maintenance / Problème de brûleur + +#haha +label.gas.problem = Défaut de pétrole +#haha + +label.egp.fault = Faute électrique +label.thermostat.setting = Réglage du thermostat +label.other = Autre +label.notes = Remarques + +enable.user.header=Activer utilisateur +enable.user.confirm=Utilisateur "{0} {1}" sera activé dans le système +msg.user.restore.success = Utilisateur "{0} {1}" à été activé + + +label.refrigerator.brand = Type +label.refrigerator.model = Année d’installation +label.refrigerator.serial.number = Marque - Modèle +label.refrigerators = Réfrigérateurs +label.new.refrigerator = Nouveau Réfrigérateur +label.change.facility = Changer de formation sanitaire + +header.order.number = Numéro de commande\n +header.product.code = Code de produit +header.quantity.ordered = Quantité commandée +header.pack.size = Taille du paquet +header.quantity.approved = Quantité Approuvée +header.order.date = Date de la commande +delete.refrigerator.readings.header= Supprimer Réfrigérateur +delete.refrigerator.readings.confirm= Êtes-vous sûr de vouloir supprimer ce réfrigérateur? + +label.is.verified = Est vérifié? + +error.duplicate.serial.number = Identifiant / Numéro de série en double + +right.configure.edi = Admin - Configurer EDI +link.admin.configure.edi = Fichier EDI +label.order.file.format = Fichier de commande +label.shipment.file.format = Fichier d'envoi +header.template.type = Type +label.admin.configure.edi.file = Configurez le format de ficher EDI +label.order.file.prefix = Préfixe du fichier de commande +label.include = Inclure +label.data.field = Champ de données +label.column.header = En-tête de colonne +label.column.include.headers = Inclure les en-têtes de colonnes +order.file.template.saved.success = Configuration des fichiers de commande enregistrée avec succès\! + +message.no.refrigerators.added = Aucun réfrigérateur ajouté + +label.not.applicable = Pas applicable +error.redundant.warehouse = Entrepôt redondant spécifié + +label.visit.information = Informations sur la visite / Observations +label.epi.inventory = Inventaire +label.epi.use = Utilisation du PEV +label.coverage = Couverture +label.observations = Observations + +header.quantity.shipped = Quantité livrée +header.cost = Coût +header.packed.date = Date d'emballage +header.ship.date = Date d'envoi +link.order.file.template= Fichier de commande +link.shipment.file.template= Fichier de livraison +header.epi.use = Informations sur le stock + +label.page.of = Page {0} de +label.position= Position +shipment.file.configuration.success = Configuration de fichier d'envoi enregistrer avec succès\! +file.duplicate.position= Les numéros de position ne peuvent pas avoir des valeurs en double +header.shipped.date=Date d'envoi +file.invalid.position = Numéro de position ne peut être vide ni zéro pour un champ inclus + +header.epi.use.doses=Antigen (doses) +header.epi.use.startingStock=Stock en début de période +header.epi.use.received=Stock reçue durant la période +header.epi.use.total=Totale +header.epi.use.distributed=Doses Administrées +header.epi.use.loss=Pertes +header.epi.use.endingStock=Stock en fin de période +link.previous=Précédent +link.next=Suivant + +message.no.product.groups = Aucun produit ajouté\n +button.apply.nr.all = Appliquer ND à tous les champs +label.apply.nr.all = Appliquer ND à tous les champs +message.apply.nr = Cette action effacera toutes les données sur le formulaire et définira tous les domaines en ND. Voulez-vous continuer? +label.name = Nom +label.title = Titre +label.verified.by = Vérifié par +label.confirmed.by = Confirmé par + +msg.rnr.already.converted.to.order = Certaines réquisitions ont été déjà converties en commandes, s’il vous plaît d'essayer à nouveau. + +order.ftpComment.connection.refused=Impossible de se connecter +order.ftpComment.incorrect.login=Certificats non valides +order.ftpComment.permission.denied=Autorisations inappropriées +label.comment=Commentaire +order.ftpComment.supplyline.missing=Conduite d'approvisionnement manquante +order.ftpComment.ftpcredential.missing=Certificats de FTP manquants +label.order.RELEASED= Libéré +label.order.PACKED = Emballé +label.order.IN_ROUTE = En route +label.order.READY_TO_PACK = Prêt à emballer +label.order.RECEIVED = Stock reçue durant la période +label.order.TRANSFER_FAILED = Échec du transfert + +error.facility.type.code.invalid = Type d'formation sanitaire non valide +file.mandatory.columns.not.included = Colonnes obligatoires doivent être inclus + +label.requisition.type = Type +requisition.type.regular = Régulier +requisition.type.emergency = Urgence + +message.no.search.results = Aucun résultat de recherche +error.page.not.found = Page introuvable +placeholder.search.product = Recherche de produit ... + +msg.rnr.current.period.already.submitted = R & R pour la période actuelle a été déjà soumis +msg.no.rnr.awaiting.authorization = Aucunes réquisitions n’en attente d’autorisation + +label.fulfillment.based.rights = Droits basés sur la réalisation +right.fulfillment.fill.shipment = Commande - Remplir envoi + +create.user.warehouse.roles = Rôles d'entrepôt +warehouse.header = Entrepôt + +button.show = Afficher +message.no.facility.synced = Aucune formation sanitaire dans la zone sélectionnée, le programme et la période ne sont prêts pour synchronisation +message.facility.synced.successfully = {0} synchronisation a réussit +label.select.warehouse = --Sélectionnez Entrepôt-- +create.user.select.warehouse = Sélectionnez un entrepôt, s'il vous plait + +msg.roles.fulfillment.delete.warning = Tous les rôles assignés à cet utilisateur pour cet entrepôt seront supprimés +label.distribution.legend.not.started = Pas encore commencé +label.distribution.legend.partial.complete = Partiellement accompli +label.distribution.legend.not.complete = Fini +label.distribution.legend.synchronized = Synchronisé +label.distribution.legend.cannot.synchronize = Déjà Téléchargé + +error.facility.data.already.synced = Données sur l'formation sanitaire déjà synchronisé +label.delete.distribution.header = Supprimer la distribution +label.confirm.delete.distribution = Êtes-vous sûr de vouloir supprimer cette distribution? Toutes les données pas encore synchronisées avec le serveur seront perdues. + +header.facility.code = Code de l'formation sanitaire +header.program.code = Code de programme +label.budget.file.format = Fichier de budget +header.period.start.date = Date de début de la période +header.allocatedBudget = Budget alloué +header.notes = Remarques +budget.file.configuration.success = Configuration du fichier de budget enregistrer avec succès + +error.restapi.delivery.already.confirmed = Livraison déjà confirmé +error.restapi.invalid.order = Numéro de commande non valide +error.invalid.product.code = {0} Code de produit non valide +message.success.pod.updated = POD mis à jour avec succès +error.permission.denied = Ce utilisateur n'est pas autorisé +right.fulfillment.manage.pod = Commande - Gérer POD +error.upload.network.server.down = Téléchargement échoué\: Erreur du réseau ou de serveur +error.invalid.received.quantity = Quantité reçue non valide + +sync.distribution.header = Synchroniser la distribution +sync.distribution.confirm = Vous avez choisi de synchroniser les données pour les formulaires des unités sanitaires déjà remplis, vérifiez s'il vous plait + +label.facilities.synced = Unités sanitaires synchronisées +label.facilities.already.synced = Unités sanitaires déjà synchronisées +label.facilities.synchronization.failed = Synchronisation échoué + +label.distribution.synchronization.progress = Synchronisation en cours ... +label.distribution.synchronization.status = Etat de synchronisation + +description.column.skip = Sauter ce produit +indicator.column.skip = S +message.sync.failure.retry = La synchronisation de certaines unités sanitaires a échoué. Vérifier votre connexion internet et réessayer. + +error.number.of.line.items.mismatch = Les produits ne correspondent pas avec la réquisition +error.approval.not.allowed = Approbation pas autorisé +error.invalid.requisition.id = Identifiant de Réquisition non valide +error.facility.inoperative = Formation Sanitaire inopérante + +error.program.configuration.missing = Configuration du programme manquant +rnr.approval.not.allowed = Approbation pas autorisée +error.restapi.quantity.approved.negative = Quantité approuvée non valide +invalid.product.codes = Codes de produit non valide {0} +error.rnr.already.initiated = R & R déjà initié + +label.no.losses.adjustment = Il n'y a pas des pertes ni ajustements + +create.user.restrictLogin = Limitez connexion? + + +label.select.all = Tous +label.select.none = Aucun +error.invalid.regimen = Régime non valide trouvée +budget.invalid.date.format = Format non valide de date {0} trouvé en donnée {1} +budget.facility.code.invalid = Code non valide d'formation sanitaire {0} trouvé en donnée {1} +budget.program.code.invalid = Code non valide de programme {0} trouvé en donnée {1} +budget.start.date.invalid = Période indéfinie pour le date de démarrage {0} pour formation sanitaire {1}, programme {2} dans donnée nombre {3} +budget.allocated.budget.invalid = Montant budgétaire non valide {0} trouvé dans donnée nombre {1} +budget.allocated.negative = Budget négatif +budget.allocated.invalid = Montant budgétaire non valide {0} trouvé dans donnée nombre {1} + +header.pod.manage = Gérer Preuve de Livraison +link.update.pod = Actualiser POD + +label.allocated.budget = Budget alloué +allocated.budget.header = Coût R & R +label.full.supply=Approvisionnement complète +label.non.full.supply=Approvisionnement non complet +msg.budget.not.allocated = Non alloué +msg.cost.exceeds.budget = Le coût total dépasse le budget alloué + +label.vials.unit = Produits [entrer des données dans des flacons] +label.ideal.quantity = Besoins +label.existing.quantity = Quantité Disponible [dans des flacons] +label.delivered.quantity = Quantité Livrée [dans des flacons] +label.spoiled.quantity = Avaries [dans des flacons] +label.epi.inventory.header = Inventaire\: Informations sur les livraisons et les stocks + +label.coverage.complete.vaccinated = Enfants complètement vaccinés (doses) +label.coverage.health.center = Stratégie Fixe +label.coverage.outreach = Stratégie Avancée +label.coverage.females = Filles +label.coverage.males = Garçons + +error.invalid.pack.size = Taille de paquet non valide + +label.coverage.full = Couverture complète +label.coverage.children = Couverture par antigéne +label.coverage.adults = Couverture VAT + +header.full.supply = Approvisionnement complet +header.product.name = Nom de produit +header.unit.of.issue = Unité de distribution +header.packs.to.ship = Paquets d'envoyer +header.quantity.received = Quantité reçue +header.proof.of.delivery = Preuve de livraison + +label.child.vaccination.doses = Vaccination des enfants (doses) +label.coverage.target.Group = Groupe cible +label.children.age.group.zero.eleven.months = 0-11 mois +label.children.age.group.twelve.twenty.three.months = 12-23 mois +label.child.coverage.first.total = Totale +label.coverage.rate = Taux de couverture +label.child.coverage.second.total = Totale +label.child.coverage.total.vaccination = Vaccination totale +label.coverage.opened.vials = Flacons ouverts +label.coverage.opened.vials.wastage.rate = Taux de gaspillage des flacons ouverts +label.was.facility.visited = Le {0} a-t-il été visité en {1}? +label.visit.date = Date de visite +label.vehicle.id = Identifiant du véhicule +label.reason.for.no.visit = Pourquoi? +label.bad.weather = Chemin impraticable ou mauvais temps +label.no.transport = Transport non disponible +label.facility.closed = Formation sanitaire fermée lors de la distribution +label.unavailable.funds.fuel = Fonds de carburant non disponible +label.unavailable.funds.perdiem = Fonds de per diem non disponible +label.refrigerators.not.working = Réfrigérateurs non fonctionnels +label.no.refrigerators = Aucun réfrigérateur +label.not.part.of.program = L'formation sanitaire n'est pas inclus dans le programme +msg.pod.save.success = POD enregistré avec succès\! + + +create.user.order.fulfillment.roles = Rôles de réalisation de commande +msg.pod.submit.success = Preuve de livraison soumise avec succès +error.quantity.received.invalid = Quantité reçue ne peut pas être vide\n +error.pod.already.submitted = Preuve de livraison déjà soumis + +error.cost.negative = Le cout d'envoi ne peut pas être négatif +invalid.quantity.shipped = La quantité envoyée ne peut pas être composée de plus que 08 caractères + +label.coverage.adult = Couverture VAT +label.adult.group.vaccinations = Vaccinations de VAT en groupe (doses) +label.coverage.pregnant.women = Femmes enceintes +label.coverage.mif = Femmes de 15-49 ans +label.coverage.community = Communauté +label.coverage.students = Elèves +label.coverage.workers = Travailleurs +label.coverage.students.not.mif = Elèves sauf femmes de 15-49 ans +label.coverage.workers.not.mif = Travailleurs sauf femmes de 15-49 ans +label.coverage.other.not.mif = Autres sauf femmes de 15-49 ans + +error.invalid.returned.quantity = Quantité retournée non valide +header.quantity.returned = Quantité Retourné + +label.adult.tetanus.first = 1ere dose de VAT +label.adult.tetanus.second.fifth = 2eme - 5eme dose de VAT +label.total.tetanus = Totale de VAT + +label.receivedBy = Reçu par +label.deliveredBy = Livré par +label.receivedDate = Date de réception + +link.go.online = Allez en ligne +msg.unable.connect.server = Impossible de se connecter au serveur +label.proof.of.delivery.for = Preuve de livraison pour {0} +label.total.shipped.packs = Total de paquets envoyés +label.total.received.packs = Totale de paquets reçus +label.total.returned.packs = Totale de paquets retournés + +msg.status.initiated = INITIE +msg.status.completed = FINI +msg.status.synced = SYNCHRONISE + +message.downloading.app.data = Téléchargement de données de l'application +message.downloading.in.progress = Ne cliquez pas sur le bouton de navigation précèdent, ni fermez la fenêtre de votre navigateur, ni vous déconnectez +message.downloading.success = Données de l'application ont été enregistré en mémoire-cache +message.downloading.failed = Téléchargement des données de l'application échoué +label.pod.products = Produit(s) + +header.replaced.product.code = Code de produit remplacé + +label.new.patient.count = Nombre de nouveaux patients +label.dispensing.units.for.new.patients = Unités de distribution pour les nouveaux patients + +msg.email.notification.subject = Une action est requise à votre part +msg.email.notification.body = Cher(e) {0},{1} Ce message est a l’intention de vous informer que {2} a complété son Rapport et Réquisition pour la période de {3}, et votre attention doit être portée. Pour le traité, connectez-vous comme {4} s’il vous plait.{5} {6} {7} Merci. + + +right.system.settings = Admin – Réglage du système +link.admin.system.settings = Réglage du système +label.admin.configure.system.settings = Configurer réglage du système\n +header.configure.order.number = Configurer le nombre de la commande +label.configure.order.number = Numéro de commande +label.sequence.code = Code de séquence +label.rnr.type.suffix = Suffixe régulière/d’urgence (R/E) +label.order.number.prefix = Préfixe de nombre de commande +order.number.configure.success = Configuration du nombre de commande enregistrée avec succès +header.field = Champ +error.saving.order.configuration = Erreur en enregistrement de la configuration du nombre de commande + +label.default.category = Autre + +message.geo.zone.created.success = Zone géographique "{0}" créée avec succès +message.geo.zone.updated.success = Zone géographique "{0}" actualisée avec succès + +right.manage.geo.zone = Admin – Gérer zone géographique +right.manage.supervisory.node = Admin - Gérer Nodule de Surveillance +right.upload.report = Admin – Télécharger rapport +menu.header.geographic.zones = Zones géographique + +search.geo.zone.header = Rechercher des zones géographique +placeholder.geo.zone.search = Saisir nom/nom de parent + +menu.header.supervisory.nodes = Nodules de Surveillance +label.search.supervisory.node = Rechercher des nodules de surveillance +option.value.supervisory.node.parent = Nodule de surveillance parent +option.value.supervisory.node = Nodule de surveillance + +option.value.geo.zone.parent = Zone géographique parent +option.value.geo.zone = Zone géographique +header.level = Niveau +header.parent = Parent +header.supervisory.node.name = Nom de nodule de surveillance +header.geo.zone.add.new = Ajouter une nouvelle zone géographique +header.geo.zone.edit = Modifier zone géographique + +label.select.geographic.level = --Sélectionnez le niveau géographique-- + +label.select.parent.zone = --Sélectionnez la zone parent-- +header.supervisory.node.add.new = Ajouter un nodule de surveillance +header.supervisory.node.edit = Modifier nodule de surveillance +header.parent.node = Nodule parent +placeholder.parent.node.search = Saisissez le nom du nodule parent +label.associated.facility = Formation sanitaire affiliée +label.no.facility.selected = Aucune formation sanitaire sélectionnée +link.select.facility = (Sélectionnez une formation sanitaire) + +menu.header.requisition.groups = Groupes de réquisition +option.value.requisition.group = Groupe de réquisition +label.facility.count = Nombre de unités sanitaires +header.requisition.group.name = Nom de groupe de réquisition +right.manage.requisition.group = Admin – Gérer les groupes de réquisition +label.search.requisition.group = Rechercher des groupes de réquisition +message.supervisory.node.created.success = Nodule de surveillance "{0}" créé avec succès +message.supervisory.node.updated.success = Nodule de surveillance "{0}" actualisé avec succès +error.supervisory.node.parent.invalid = Code de nodule parent non valide +placeholder.supervisory.node.search = Saisissez nom de nodule de surveillance + +label.facility.type = Type d'formation sanitaire +label.facility.name = Nom d'formation sanitaire +label.members = Membres +label.add.members = Ajouter membres +error.duplicate.code.supervisory.node = Code de nodule de surveillance en double +too.many.results.found = Trop de résultats trouvés. S’il vous plait d’affiner votre recherche. +error.duplicate.facility = formation sanitaire "{0}" a été déjà ajoutée +message.requisition.group.created.success = Groupe de réquisition "{0}" a été crée avec succès +message.requisition.group.updated.success = Groupe de réquisition "{0}" a été actualisé avec succès +header.requisition.group.add.new = Ajouter un groupe de réquisition +header.requisition.group.edit = Modifier un groupe de réquisition +error.duplicate.code.requisition.group = Code de groupe de réquisition en double + +label.facility.enabled = Activé +filter.header = Filtrer +button.set.filters = Unite sanitaire affiliées +button.apply.filters = Appliquer + +placeholder.geographic.zone.search = Saisir le nom de zone géographique +right.manage.supply.line = Admin – Gérer les conduites d’approvisionnement +label.change.facility.type = --Sélectionner la Formation Sanitaire— +menu.header.supply.lines = Conduite d’approvisionnement +label.supplying.facility = Formation sanitaire d’approvisionnement +label.search.supply.line = Rechercher des conduites d’approvisionnement + +message.supply.line.created.success = Conduite d’approvisionnement crée avec succès +message.supply.line.updated.success = Conduite d’approvisionnement actualisé avec succès + +label.facility.export.orders = L’formation sanitaire exporte des commandes ? +error.supplying.facility.already.assigned = Une formation sanitaire d’approvisionnement a été déjà désigné pour ce nodule de surveillance et programme +header.supply.line.add.new = Ajouter une conduite d’approvisionnement +header.supply.line.edit = Modifier conduite d’approvisionnement +placeholder.node.search = Saisir nom de nodule +right.manage.facility.approved.products = Admin – Gérer les produits approuvés par l’formation sanitaire +header.facility.approved.products = Produits approuvés par l'formation sanitaire +msg.please.select.program.facility.type = Pour afficher la liste des produits, sélectionnez un programme et un type d’formation sanitaire +label.search.products = Rechercher des produits +header.strength = Concentration +header.unit.of.measure = Unité +header.max.months.of.stock = Mois de stock maximum +header.min.months.of.stock = Mois de stock minimum +header.global.active = Actif mondial +header.active.at.program = Actif au programme +msg.records.found = {0} donnée(s) trouvée(s) +label.clear.search = Effacer la recherche +msg.enter.product.code.name = Saisir le code ou le nom de produit +label.program.and.schedules = Programmes et calendriers +facilities.added.successfully = Unités sanitaires ajouter avec succès +add.selected.facilities = Ajouter des formations sanitaires sélectionnées +label.programs = Programmes +label.direct.delivery = Livraison directe +label.drop.off.facility = Formation sanitaire de livraison + +label.select.schedule = --Sélectionnez un calandrer-- +label.expand.all = Déplier tous +label.collapse.all = Réduire tous +label.add.facility.approved.products = Ajouter des produits pour {0} à {1} +message.facility.type.approved.products.added.successfully = {0} produit(s) est/sont ajouté(s) avec succès + +header.products = Produits +option.value.product = Produit +right.manage.products = Admin – Gérer les produits +header.dispensing.unit = Unité de distribution +label.no.category = Pas catégorisé +error.program.schedules.not.done = Avant d’enregistrer le formulaire, marquez tous les calendriers de programme comme 'Fini' +message.facility.approved.product.updated.success = "{0}" actualisé avec succès + +create.report.description = Description +label.search.product = Rechercher des produits +message.facility.approved.product.deleted.success = Produit "{0}" supprimé avec sucés +msg.delete.facility.approved.product.confirmation = Produit "{0}" sera supprimé des assignation "{1}" et "{2}" +link.clear = Effacer +message.product.created.success = Produit "{0}" créé avec succès +message.product.null = Produit est nul +header.product.basic.information = Informations de base +header.product.primary.name = Nom principal du produit +header.product.add.new = Ajouter un produit +header.product.edit = Modifier un produit +label.product.archived = Archivé +label.product.tracer = Témoins +label.product.fullSupply = Approvisionnement complet +label.product.active = Produit actif +label.product.roundToZero = Arrondir à zéro +label.product.packRoundingThreshold = Limite d’arrondissage d’emballage +label.product.packSize = Taille d’emballage +label.product.dosesPerDispensingUnit = Dose par unité de distribution +label.product.dispensingUnit = Unité de distribution +label.product.dosageUnit = Unité de dose +label.product.strength = Concentration +label.product.form = Forme de produit +label.product.description = Description +label.product.group = Groupe de produit +label.product.fullName = Nom entier de produit +label.product.type = Type de produit +placeholder.select.product.group = --Sélectionnez le groupe de produit-- +placeholder.select.product.form = --Sélectionnez la forme de produit-- +placeholder.select.product.dosageUnit = --Sélectionnez l’unité de distribution-- + +label.reporting.right.view = Afficher - +create.role.reporting.rights = Droits de rapportage +create.user.reportingRoles = Rôles de rapportage +message.product.updated.success = Produit "{0}" mis à jour avec succès +message.error.page = Il y avait une faute \! Contactez l’administrateur s’il vous plait. +option.value.facility = Formation sanitaire +header.geographic.zone = Zone géographique +header.facility.type = Type +header.facility.active = Actif +header.facility.enabled = Activé +header.parameter = Paramètre +header.parameter.value = Valeur +header.parameter.description = Description +header.user.name = Nom +header.user.userName = Nom d'utilisateur +header.user.email = Email +header.user.verified = Vérifié +header.user.active = Actif +label.product.generic.name = Nom générique du produit +label.product.alternate.name = Autre nom du produit +label.product.alternate.product.code = Autre code du produit +label.product.alternate.pack.size = Autre taille d’emballage +label.product.manufacturer = Fabriquant +label.product.manufacturer.product.code = Code de produit de fabriquant +label.product.manufacturer.bar.code = Code a barres de fabriquant +label.product.record.last.updated = Dernier mise à jour des données du produit +label.product.GTIN = GTIN +label.product.expected.shelf.life = Durée de conservation prévue +label.product.contraceptive.couple.years.of.protection = Ans de protection pour une couple par un contraceptif +label.product.alternate.MoH.bar.code = Autre code à barres du MoS +label.product.store.refrigerated = Conserver en réfrigération +label.product.store.at.room.temperature = Conserver à la température ambiante +label.product.hazardous = Matière dangereuse +label.product.flammable = Inflammable +label.product.controlled.substance = Substance réglementée +label.product.light.sensitive = Photosensible +label.product.Approved.by.WHO = Approuvé par l’OMS +label.product.pack.length = Longueur de paquet (cm) +label.product.pack.width = Largeur de paquet (cm) +label.product.pack.height = Hauteur de paquet (cm) +label.product.pack.weight = Poids de paquet (cm) +label.product.pack.per.carton = Paquets par carton +label.product.carton.length = Longueur de carton (cm) +label.product.carton.width = Largeur de carton (cm) +label.product.carton.height = Hauteur de carton (cm) +label.product.cartons.per.pallet = Cartons par palette +label.product.special.storage.instructions = Instructions spéciales pour la conservation +label.product.special.transport.instructions = \ Instructions spéciales pour le transport +link.product.other.information = Autres informations +user.is.disabled = Utilisateur a été désactivé. Mot de passe ne peut pas être restauré +link.product.programs.associated = Programmes affilés +label.display.order = Ordre d’affichage +label.doses.per.month = Doses par mois +label.price.per.pack = Prix par paquet +error.program.products.not.done = Avant d’enregistrer le formulaire, marquez tous les produits de programme comme 'Fini' +facility.approved.product.does.not.exist = Ce produit approuvé par une formation sanitaire n’existe pas. + +label.facility.operators = Gérants de formations sanitaires +label.facility.types = Types de formations sanitaires + +error.duplicate.regimen.category = Catégorie de régime en double +label.regimen.categories = Catégories de régime diff --git a/modules/openlmis-web/src/main/resources/messages_pt.properties b/modules/openlmis-web/src/main/resources/messages_pt.properties index bb69b6c5b7..4291342867 100644 --- a/modules/openlmis-web/src/main/resources/messages_pt.properties +++ b/modules/openlmis-web/src/main/resources/messages_pt.properties @@ -636,6 +636,7 @@ placeholder.select.product = - Selecione um produto - placeholder.search.by.status = Busca por status ... placeholder.new.password = Nova senha placeholder.reenter.password = Digite a nova senha +placeholder.password.rules = A senha deve ter entre 8 a 10 caracteres , não deve conter espaços e conter pelo menos um número. placeholder.type.comment = Digite aqui seu coment\u00E1rio msg.product.added = Este produto foi adicionado com sucesso error.correct.highlighted = Por favor, corrija os campos destacados antes da apresenta\u00E7\u00E3o @@ -1063,7 +1064,8 @@ label.bad.weather=Road im\u2211\u00B4\u2020\u00A5\u00A8\u02C6eather label.no.transport=Tra\u02DC\u00DF\u2202\u0192\u00A9\u02D9\u2206\u02DA\u00E7\u221A\u222Bilable label.facility.closed=The \u02DC\u0192\u02D9\u2206\u00A9\u02D9\u2206\u00A9\u0192\u02D9\u0192\u00A9e time of visit label.not.part.of.program=The health center is not p\u2202\u0192\u00A9\u02D9\u2206art of the DLS program\ -label.unavailable.funds=Per di\u00AE\u00B4\u2020\u2206\u00A5\u00A5\u2020\u00A8\u00A5\u02C6\u00A8\u2026\u02C6\u02DA\u02D9\u2206\u00A9\u00B5\u0192t available +label.unavailable.funds.fuel=Fundos de combustível não disponível +label.unavailable.funds.perdiem=Fundos de per diem não disponível msg.pod.save.success = POD saved succe™ssfully! @@ -1116,6 +1118,8 @@ message.downloading.success = Applicat˙©¨data˙©¥∫¨ø¨ˆˆµ¨∆µøˆ message.downloading.failed = A˙©˙©∆˙∆˚˜ion data d©˙ƒ¨©ˆ¨˜ø˚iled label.pod.products = Prod∆˙©˙∆˙√(s) header.replaced.product.code=Repl\u00E7\u02D9\u00A9\u2206\u02DAoduct +label.no.refrigerators=Sem Geleria +label.refrigerators.not.working=Geleira Avariada label.new.patient.count=N\u00A9\u0192\u00A5\u00A9\u0192\u00A0\u00A9\u00A5\u02D9\u00A8nt Count label.dispensing.units.for.new.patients=Dis\u00E7\u00A9\u02D9\u02D9\u00A9\u00DF\u03A9\u2202\u2248\u2248\u2248\u2248\u2248\u2248\u2202 for ne\u221A\u2248\u0192\u2248\u0192\u2248\u0192\u00A9 @@ -1223,6 +1227,10 @@ header.max.months.of.stock = Max mon˚¨ths of stock header.min.months.of.stock = Min montåßhs of stock header.global.active = Global a©ctive header.active.at.program = Acti∆˙©ve at program +label.dosage.units=Unidades de dosagem +error.duplicate.dosage.unit.code=Código Duplicate Unidade Dosagem encontrado +error.duplicate.product.form.code=Duplicar código formar o produto fundações +label.product.forms=Formulários de produtos msg.records.found = {0} re∂ƒç√©¨ˆ∆˚øπd label.clear.search = Cleƒ©∆˙ ∆˙˚ø˚rch msg.enter.product.code.name = Enter prod∆©∆˙uct code or name @@ -1335,3 +1343,13 @@ label.price.per.pack = Pric∂e per pack error.program.products.not.done = Mark all program products as 'ß∂ƒç©√˙ˆ∆˜ the form facility.approved.product.does.not.exist = Fß∂´†ility Ap¨ˆ¨ved Produ©˙††††∆¨es not exist. +error.duplicate.program.code=Duplicar código do programa +label.programs=Programas +label.geographic.levels=Níveis Geográficos +error.duplicate.geographic.level.code=Duplicate Código Geográfico Nível +error.duplicate.facility.operator.code=Duplicar Facilidade Código de operador +label.facility.operators=Operadores de instalações +error.duplicate.facility.type=Duplicar Tipo de Instalação +label.facility.types=Tipos de Instalação +error.duplicate.regimen.category=Duplicar Regime Categoria +label.regimen.categories=Regime Categorias diff --git a/modules/openlmis-web/src/main/resources/openlmis_logging.xml b/modules/openlmis-web/src/main/resources/openlmis_logging.xml index ae815b262c..2f91d35cf0 100644 --- a/modules/openlmis-web/src/main/resources/openlmis_logging.xml +++ b/modules/openlmis-web/src/main/resources/openlmis_logging.xml @@ -55,6 +55,16 @@ + + + + + + + + + + diff --git a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/adult-coverage-controller.js b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/adult-coverage-controller.js index 423745e126..f6b86d1244 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/adult-coverage-controller.js +++ b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/adult-coverage-controller.js @@ -41,4 +41,8 @@ function AdultCoverageController($scope, $routeParams, distributionService) { $scope.adultCoverage.setNotRecorded(); }); }; + + $scope.getFormattedPercent = function (number) { + return utils.getFormattedPercent(number); + }; } diff --git a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/child-coverage-controller.js b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/child-coverage-controller.js index 799e4d6e9a..e21ff6065a 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/child-coverage-controller.js +++ b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/child-coverage-controller.js @@ -104,6 +104,10 @@ function ChildCoverageController($scope, $routeParams, distributionService) { return (isUndefined(targetGroup) ? null : (targetGroup === 0 ? null : Math.round((total / targetGroup) * 100))); }; + $scope.getFormattedAsPercent = function (number) { + return utils.getFormattedPercent(number); + }; + $scope.calculateWastageRate = function (productsForVaccination) { var totalDosesConsumed = 0; var totalVaccinations = 0; diff --git a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/visit-info-controller.js b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/visit-info-controller.js index 3a01baf0e6..5211fff2b8 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/visit-info-controller.js +++ b/modules/openlmis-web/src/main/webapp/public/js/distribution/controller/visit-info-controller.js @@ -16,7 +16,10 @@ function VisitInfoController($scope, distributionService, $routeParams) { badWeather: "ROAD_IMPASSABLE", noTransport: "TRANSPORT_UNAVAILABLE", facilityClosed: "HEALTH_CENTER_CLOSED", - unavailableFunds: "FUEL_FUNDS_UNAVAILABLE", + unavailableFuelFunds: "FUEL_FUNDS_UNAVAILABLE", + unavailablePerDiemFunds: "PERDIEM_FUNDS_UNAVAILABLE", + refrigeratorsNotWorking: "REFRIGERATORS_NOT_WORKING", + noRefrigerators: "NO_REFRIGERATORS", notPartOfProgram: "HEALTH_CENTER_NOT_IN_DLS", other: "OTHER" }; diff --git a/modules/openlmis-web/src/main/webapp/public/js/distribution/model/adult-coverage.js b/modules/openlmis-web/src/main/webapp/public/js/distribution/model/adult-coverage.js index 6dafdb09c4..56c2bb0a62 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/distribution/model/adult-coverage.js +++ b/modules/openlmis-web/src/main/webapp/public/js/distribution/model/adult-coverage.js @@ -143,7 +143,7 @@ AdultCoverageLineItem.prototype.totalTetanus = function () { AdultCoverageLineItem.prototype.coverageRate = function () { if (isUndefined(this.targetGroup) || this.targetGroup === 0) return null; - return Math.round((this.totalTetanus() / this.targetGroup) * 100); + return Math.round((this.totalTetanus2To5() / this.targetGroup) * 100); }; function OpenedVialLineItem(lineItem) { diff --git a/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-non-full-supply-controller.js b/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-non-full-supply-controller.js index 0ca28fe733..f6c1041b55 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-non-full-supply-controller.js +++ b/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-non-full-supply-controller.js @@ -9,7 +9,7 @@ */ function CreateNonFullSupplyController($scope, messageService) { - var map = _.map($scope.facilityApprovedProducts, function (facilitySupportedProduct) { + var map = _.map($scope.facilityApprovedNFSProducts, function (facilitySupportedProduct) { return facilitySupportedProduct.programProduct.productCategory; }); @@ -97,7 +97,7 @@ function CreateNonFullSupplyController($scope, messageService) { _.pluck($scope.addedNonFullSupplyProducts, 'productCode') .concat(_.pluck($scope.rnr.nonFullSupplyLineItems, 'productCode')); if ($scope.nonFullSupplyProductCategory !== undefined) { - $scope.nonFullSupplyProductsToDisplay = $.grep($scope.facilityApprovedProducts, function (facilityApprovedProduct) { + $scope.nonFullSupplyProductsToDisplay = $.grep($scope.facilityApprovedNFSProducts, function (facilityApprovedProduct) { return $.inArray(facilityApprovedProduct.programProduct.product.code, addedNonFullSupplyProductList) == -1 && $.inArray(facilityApprovedProduct.programProduct.productCategory.name, [$scope.nonFullSupplyProductCategory.name]) === 0; }); diff --git a/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-requisition-controller.js b/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-requisition-controller.js index 7043da5c1d..2d0f9544c5 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-requisition-controller.js +++ b/modules/openlmis-web/src/main/webapp/public/js/rnr/controller/create/create-requisition-controller.js @@ -8,7 +8,7 @@ * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  */ -function CreateRequisitionController($scope, requisitionData, pageSize, rnrColumns, lossesAndAdjustmentsTypes, facilityApprovedProducts, requisitionRights, regimenTemplate, $location, Requisitions, $routeParams, $dialog, requisitionService, $q) { +function CreateRequisitionController($scope, requisitionData, pageSize, rnrColumns, lossesAndAdjustmentsTypes, facilityApprovedNFSProducts, requisitionRights, regimenTemplate, $location, Requisitions, $routeParams, $dialog, requisitionService, $q) { var NON_FULL_SUPPLY = 'nonFullSupply'; var FULL_SUPPLY = 'fullSupply'; @@ -19,7 +19,7 @@ function CreateRequisitionController($scope, requisitionData, pageSize, rnrColum resetCostsIfNull(); $scope.lossesAndAdjustmentTypes = lossesAndAdjustmentsTypes; - $scope.facilityApprovedProducts = facilityApprovedProducts; + $scope.facilityApprovedNFSProducts = facilityApprovedNFSProducts; $scope.visibleColumns = requisitionService.getMappedVisibleColumns(rnrColumns, RegularRnrLineItem.frozenColumns, ['quantityApproved']); @@ -28,7 +28,7 @@ function CreateRequisitionController($scope, requisitionData, pageSize, rnrColum $scope.requisitionRights = requisitionRights; $scope.regimenColumns = regimenTemplate ? regimenTemplate.columns : []; $scope.visibleRegimenColumns = _.where($scope.regimenColumns, {'visible': true}); - $scope.addNonFullSupplyLineItemButtonShown = _.findWhere($scope.programRnrColumnList, {'name': 'quantityRequested'}); + $scope.addNonFullSupplyLineItemButtonShown = facilityApprovedNFSProducts.length > 0; $scope.errorPages = {fullSupply: [], nonFullSupply: []}; $scope.regimenCount = $scope.rnr.regimenLineItems.length; @@ -307,13 +307,15 @@ CreateRequisitionController.resolve = { return deferred.promise; }, - facilityApprovedProducts: function ($q, $timeout, $route, FacilityApprovedProducts) { + facilityApprovedNFSProducts: function ($q, $timeout, $route, FacilityApprovedNonFullSupplyProducts) { var deferred = $q.defer(); $timeout(function () { - FacilityApprovedProducts.get({facilityId: $route.current.params.facility, programId: $route.current.params.program}, - function (data) { - deferred.resolve(data.nonFullSupplyProducts); - }, {}); + FacilityApprovedNonFullSupplyProducts.get( + {facilityId: $route.current.params.facility, programId: $route.current.params.program}, + function (data) { + deferred.resolve(data.nonFullSupplyProducts); + }, + {} ); }, 100); return deferred.promise; }, diff --git a/modules/openlmis-web/src/main/webapp/public/js/rnr/model/regular-rnr-line-item.js b/modules/openlmis-web/src/main/webapp/public/js/rnr/model/regular-rnr-line-item.js index 6ad687d3a4..a3793349b0 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/rnr/model/regular-rnr-line-item.js +++ b/modules/openlmis-web/src/main/webapp/public/js/rnr/model/regular-rnr-line-item.js @@ -308,7 +308,7 @@ var RegularRnrLineItem = base2.Base.extend({ }, validateRequiredFieldsForNonFullSupply: function () { - if (_.findWhere(this.programRnrColumnList, {name: 'quantityRequested'}).visible) { + if (_.findWhere(this.programRnrColumnList, {name: 'quantityRequested'})) { return !(isUndefined(this.quantityRequested) || isUndefined(this.reasonForRequestedQuantity)); } return false; diff --git a/modules/openlmis-web/src/main/webapp/public/js/rnr/services/requisition-service.js b/modules/openlmis-web/src/main/webapp/public/js/rnr/services/requisition-service.js index 3ce72c152c..2a703976de 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/rnr/services/requisition-service.js +++ b/modules/openlmis-web/src/main/webapp/public/js/rnr/services/requisition-service.js @@ -101,16 +101,28 @@ services.factory('requisitionService', function (messageService) { return 'scrollable'; }); + var nfsColumns = {fixed: [], scrollable: []}; // non-full supply columns + nfsColumns.fixed = _.filter(fullSupplyVisibleColumns.fixed, function (column) { + return _.contains(['product', 'productCode'], column.name); + }); + + nfsColumns.scrollable = _.filter(fullSupplyVisibleColumns.scrollable, function (column) { + return _.contains(RegularRnrLineItem.visibleForNonFullSupplyColumns, column.name); + }); + + // find columns needed for non-full supply products: requested quantity and the reason for the request + // these are needed/displayed regardless of how the R&R form is setup - ie all non-full supply product requests + // always have a requested quantity and the associated reason for the request + // ensure these are in the list of scrollable columns. + var nfsReqQuantityColumns = _.filter(rnrColumns, function (column) { + return _.contains(['quantityRequested', 'reasonForRequestedQuantity'], column.name); + }); + if(nfsReqQuantityColumns.length === 0) throw new Error('Requested Quantity column(s) not found'); + nfsColumns.scrollable = _.union(nfsColumns.scrollable, nfsReqQuantityColumns); + return { fullSupply: fullSupplyVisibleColumns, - nonFullSupply: { - fixed: _.filter(fullSupplyVisibleColumns.fixed, function (column) { - return _.contains(['product', 'productCode'], column.name); - }), - scrollable: _.filter(fullSupplyVisibleColumns.scrollable, function (column) { - return _.contains(RegularRnrLineItem.visibleForNonFullSupplyColumns, column.name); - }) - } + nonFullSupply: nfsColumns }; } diff --git a/modules/openlmis-web/src/main/webapp/public/js/shared/services/services.js b/modules/openlmis-web/src/main/webapp/public/js/shared/services/services.js index fdef03a921..7a3758ad8e 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/shared/services/services.js +++ b/modules/openlmis-web/src/main/webapp/public/js/shared/services/services.js @@ -149,7 +149,7 @@ services.factory('ForgotPassword', function ($resource) { return $resource('/forgot-password.json', {}, {}); }); -services.factory('FacilityApprovedProducts', function ($resource) { +services.factory('FacilityApprovedNonFullSupplyProducts', function ($resource) { return $resource('/facilityApprovedProducts/facility/:facilityId/program/:programId/nonFullSupply.json', {}, {}); }); diff --git a/modules/openlmis-web/src/main/webapp/public/js/shared/util.js b/modules/openlmis-web/src/main/webapp/public/js/shared/util.js index 5f5d562dcd..becb932524 100644 --- a/modules/openlmis-web/src/main/webapp/public/js/shared/util.js +++ b/modules/openlmis-web/src/main/webapp/public/js/shared/util.js @@ -53,6 +53,10 @@ var utils = { } }); return sum; + }, + + getFormattedPercent: function(number) { + return (number === null) ? '' : number + '%'; } }; diff --git a/modules/openlmis-web/src/main/webapp/public/less/content.less b/modules/openlmis-web/src/main/webapp/public/less/content.less index 2f7d3124e4..ed50ded31e 100644 --- a/modules/openlmis-web/src/main/webapp/public/less/content.less +++ b/modules/openlmis-web/src/main/webapp/public/less/content.less @@ -2328,6 +2328,10 @@ input[placeholder].placeholder { } form { margin-bottom: 0; + + #passwordRules { + padding: 1em; + } } } diff --git a/modules/openlmis-web/src/main/webapp/public/less/login.less b/modules/openlmis-web/src/main/webapp/public/less/login.less index 93a61d658b..31db67ca45 100644 --- a/modules/openlmis-web/src/main/webapp/public/less/login.less +++ b/modules/openlmis-web/src/main/webapp/public/less/login.less @@ -187,6 +187,13 @@ input[type="color"]:focus, padding: 0 0 12px 3px; } +.powered-by { + text-align: right; + padding: 0px 10px; + font-size: 0.7em; + color: #a2a2a2; +} + .modal-login { width: 692px; margin-left: -346px; diff --git a/modules/openlmis-web/src/main/webapp/public/pages/admin/user/partials/user-reset-password.html b/modules/openlmis-web/src/main/webapp/public/pages/admin/user/partials/user-reset-password.html index 3ca2975de9..25617dcb31 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/admin/user/partials/user-reset-password.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/admin/user/partials/user-reset-password.html @@ -21,22 +21,26 @@

-
- - -
+ +
+ + +
+
+ + +
+
+ +
+ +
+
-
-
- - -
-
-
diff --git a/modules/openlmis-web/src/main/webapp/public/pages/login-form.html b/modules/openlmis-web/src/main/webapp/public/pages/login-form.html index c0339081cb..1c1a8b0d17 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/login-form.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/login-form.html @@ -40,5 +40,8 @@

+
+ Powered by OpenLMIS +
diff --git a/modules/openlmis-web/src/main/webapp/public/pages/login.html b/modules/openlmis-web/src/main/webapp/public/pages/login.html index 44b93c6cbf..226a8c3f4a 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/login.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/login.html @@ -9,11 +9,11 @@ ~ You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  --> - + - Open-LMIS + diff --git a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/adult-coverage.html b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/adult-coverage.html index 5ef4741abb..cef9de3bae 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/adult-coverage.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/adult-coverage.html @@ -127,7 +127,7 @@

- + @@ -146,7 +146,7 @@

- + diff --git a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/child-coverage.html b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/child-coverage.html index 36011260eb..a693fff3c4 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/child-coverage.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/child-coverage.html @@ -116,7 +116,7 @@

+ ng-bind="getFormattedAsPercent(calculateCoverageRate(getTotal(lineItem.healthCenter11Months, lineItem.outreach11Months), lineItem.targetGroup))"> @@ -206,7 +206,7 @@

ng-hide="hideCell('{{lineItem.vaccination}}')" rowspan="{{productsMap[lineItem.vaccination].rowSpan}}"> + ng-bind="getFormattedAsPercent(calculateWastageRate(productsMap[lineItem.vaccination]))"> diff --git a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/epi-inventory.html b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/epi-inventory.html index 6f0fe72260..c152ff7bdb 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/epi-inventory.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/epi-inventory.html @@ -49,10 +49,10 @@

- - - -- + + + --
diff --git a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/visit-info.html b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/visit-info.html index fa6095ec29..02bc81334a 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/visit-info.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/logistics/distribution/partials/visit-info.html @@ -119,12 +119,33 @@

+
+ + +
+
+ + +
- + value="{{reasons.unavailableFuelFunds}}"/> + +
+
+ +
+ ng-disabled="formDisabled || !(addNonFullSupplyLineItemButtonShown)" openlmis-message="button.add"/>
diff --git a/modules/openlmis-web/src/main/webapp/public/pages/partials/reset-password-form.html b/modules/openlmis-web/src/main/webapp/public/pages/partials/reset-password-form.html index 500eb19096..29549c4fa3 100644 --- a/modules/openlmis-web/src/main/webapp/public/pages/partials/reset-password-form.html +++ b/modules/openlmis-web/src/main/webapp/public/pages/partials/reset-password-form.html @@ -19,13 +19,22 @@

- - -
+
+
+