branch feature/8157 updated (6f61c6a -> 6afd5b0)
This is an automated email from the git hooks/post-receive script. New change to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git omits 6f61c6a ajout de l'action de rapport de prélèvement pour la campagne (refs #8157) omits 23c74c2 service d'export du rapport de prélèvements (refs #8157) omits 94561d5 récup du nombre de prélèvement par classe de taille pour une espece/maturité/sexe (refs #8157) omits 614fb6d i18n adds 927e936 prise en compte du cas de l'intervalle 1 (fixes #8208) adds 9c43cc8 Merge branch 'feature/8208' into 'develop' adds f7abf93 conversion des centimetres en millimetres avant d'envoyer à l'algo de prelevements (refs #8207) adds 856ac6e Merge branch 'feature/8207' into 'develop' new 2dbbf8d i18n new 946cdbe récup du nombre de prélèvement par classe de taille pour une espece/maturité/sexe (refs #8157) new 9b441cb service d'export du rapport de prélèvements (refs #8157) new 20ebc02 ajout de l'action de rapport de prélèvement pour la campagne (refs #8157) new 6afd5b0 i18n (fixes #8157) This update added new revisions after undoing existing revisions. That is to say, some revisions that were in the old version of the branch are not in the new version. This situation occurs when a user --force pushes a change and generates a repository containing something like this: * -- * -- B -- O -- O -- O (6f61c6a) \ N -- N -- N refs/heads/feature/8157 (6afd5b0) You should already have received notification emails for all of the O revisions, and so the following emails describe only the N revisions from the common base, B. Any revisions marked "omits" are not gone; other references still refer to them. Any revisions marked "discards" are gone forever. The 5 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 6afd5b0048cc405368c6d4d84e7c3e9f79901874 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 23:34:13 2016 +0200 i18n (fixes #8157) commit 20ebc02ceb4c8b8ba71b14983e1d2c39354c8628 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:45:49 2016 +0200 ajout de l'action de rapport de prélèvement pour la campagne (refs #8157) commit 9b441cbfc69eb4197612b566b8635669db8033e7 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:45:21 2016 +0200 service d'export du rapport de prélèvements (refs #8157) commit 946cdbee506fd82f8f4f41702972592a3a4e33e1 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:43:17 2016 +0200 récup du nombre de prélèvement par classe de taille pour une espece/maturité/sexe (refs #8157) commit 2dbbf8d4ce1d697fdc96bef49bd203b17ce9dc25 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:41:55 2016 +0200 i18n Summary of changes: .../main/java/fr/ifremer/tutti/util/Numbers.java | 24 ++++++++++ .../main/java/fr/ifremer/tutti/util/Weights.java | 5 +- .../service/sampling/CruiseSamplingCache.java | 56 ++++++++++++---------- .../sampling/CruiseSamplingInternalCache.java | 2 +- .../resources/i18n/tutti-service_fr_FR.properties | 3 ++ .../frequency/IndividualObservationUICache.java | 15 +++--- .../species/frequency/SpeciesFrequencyUIModel.java | 8 ++++ .../resources/i18n/tutti-ui-swing_fr_FR.properties | 4 +- 8 files changed, 78 insertions(+), 39 deletions(-) -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 2dbbf8d4ce1d697fdc96bef49bd203b17ce9dc25 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:41:55 2016 +0200 i18n --- .../fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java index c2bec12..6406a1a 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCacheLoader.java @@ -40,6 +40,8 @@ import java.util.Collection; import java.util.List; import java.util.Optional; +import static org.nuiton.i18n.I18n.t; + /** * Pour charger le cache. * @@ -86,7 +88,7 @@ public class CruiseSamplingCacheLoader { FishingOperation fishingOperation = persistenceService.getFishingOperation(fishingOperationId); - progressionModel.increments("Chargement du cache d'échantillons pour le trait : " + fishingOperationDecorator.toString(fishingOperation)); + progressionModel.increments(t("tutti.cruise.cacheLoader.loading.fishingOperation", fishingOperationDecorator.toString(fishingOperation))); List<IndividualObservationBatch> allIndividualObservationBatchsForFishingOperation = persistenceService.getAllIndividualObservationBatchsForFishingOperation(fishingOperationId); -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 946cdbee506fd82f8f4f41702972592a3a4e33e1 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:43:17 2016 +0200 récup du nombre de prélèvement par classe de taille pour une espece/maturité/sexe (refs #8157) --- .../service/sampling/CruiseSamplingCache.java | 5 +++ .../sampling/CruiseSamplingInternalCache.java | 41 +++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java index 3fc5dea..5b9d06c 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingCache.java @@ -50,6 +50,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; /** * @author Kevin Morin (Code Lutin) @@ -750,4 +751,8 @@ public class CruiseSamplingCache implements Closeable { (key, highestSamplingCode) -> code.equals(highestSamplingCode) ? code - 1 : highestSamplingCode); } + public TreeMap<Integer, Integer> getSamplingNbByLengthStepForCruise(int speciesId, CaracteristicQualitativeValue gender, Boolean maturity, int minSize, Integer maxSize) { + return totalCruiseCache.getSamplingNbByLengthStep(speciesId, gender, maturity, minSize, maxSize); + } + } diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingInternalCache.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingInternalCache.java index bb4ff26..2c11465 100644 --- a/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingInternalCache.java +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/sampling/CruiseSamplingInternalCache.java @@ -54,10 +54,11 @@ class CruiseSamplingInternalCache implements Closeable { public static String createSamplingKey(Species species, CaracteristicQualitativeValue gender, Boolean maturity, int lengthStep) { Objects.requireNonNull(species); - return species.getReferenceTaxonId() - + KEY_SEPARATOR + (gender == null ? null : gender.getId()) - + KEY_SEPARATOR + maturity - + KEY_SEPARATOR + lengthStep; + return createSamplingKey(species.getReferenceTaxonId(), gender, maturity) + lengthStep; + } + + public static String createSamplingKey(int speciesId, CaracteristicQualitativeValue gender, Boolean maturity) { + return speciesId + KEY_SEPARATOR + (gender == null ? null : gender.getId()) + KEY_SEPARATOR + maturity + KEY_SEPARATOR; } public static String addPrefixKey(Serializable prefix, String key) { @@ -173,6 +174,37 @@ class CruiseSamplingInternalCache implements Closeable { return result; } + /** + * Get the number of samplings by lengthstep for a species, maturity and gender, for the lengthsteps between min size and max size + * @param speciesId + * @param gender + * @param maturity + * @param minSize + * @param maxSize + * @return a map of the number of samplings for each lengthstep in millimeters + */ + public TreeMap<Integer, Integer> getSamplingNbByLengthStep(int speciesId, CaracteristicQualitativeValue gender, Boolean maturity, int minSize, Integer maxSize) { + String keyPrefix = createSamplingKey(speciesId, gender, maturity); + + TreeMap<Integer, Integer> result = new TreeMap<>(); + + Iterator<Map.Entry<String, SamplingData>> iterator = data.entrySet().iterator(); + + int keyPrefixLength = keyPrefix.length(); + while (iterator.hasNext()) { + Map.Entry<String, SamplingData> entry = iterator.next(); + String key = entry.getKey(); + + if (key.startsWith(keyPrefix)) { + int lengthStep = Integer.parseInt(key.substring(keyPrefixLength)); + if (lengthStep >= minSize && (maxSize == null || lengthStep <= maxSize)) { + result.put(lengthStep, entry.getValue().getSamplingNb()); + } + } + } + return result; + } + private class SamplingData { private MutableInt observationNb = new MutableInt(0); @@ -208,4 +240,5 @@ class CruiseSamplingInternalCache implements Closeable { } + } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 9b441cbfc69eb4197612b566b8635669db8033e7 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:45:21 2016 +0200 service d'export du rapport de prélèvements (refs #8157) --- .../cps/CalcifiedPiecesSamplingExportService.java | 156 +++++++++++++++++++++ .../export/cps/CalcifiedPiecesSamplingRow.java | 76 ++++++++++ .../cps/CalcifiedPiecesSamplingRowModel.java | 63 +++++++++ .../resources/i18n/tutti-service_en_GB.properties | 10 ++ .../resources/i18n/tutti-service_fr_FR.properties | 10 ++ 5 files changed, 315 insertions(+) diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java new file mode 100644 index 0000000..7e103a6 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingExportService.java @@ -0,0 +1,156 @@ +package fr.ifremer.tutti.service.export.cps; + +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.io.Files; +import fr.ifremer.adagio.core.dao.referential.pmfm.QualitativeValueId; +import fr.ifremer.tutti.persistence.ProgressionModel; +import fr.ifremer.tutti.persistence.entities.protocol.CalcifiedPiecesSamplingDefinition; +import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol; +import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol; +import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; +import fr.ifremer.tutti.persistence.entities.referential.Species; +import fr.ifremer.tutti.persistence.entities.referential.Speciess; +import fr.ifremer.tutti.service.AbstractTuttiService; +import fr.ifremer.tutti.service.DecoratorService; +import fr.ifremer.tutti.service.PersistenceService; +import fr.ifremer.tutti.service.TuttiDataContext; +import fr.ifremer.tutti.service.TuttiServiceContext; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.csv.Export; +import org.nuiton.decorator.Decorator; +import org.nuiton.jaxx.application.ApplicationTechnicalException; + +import java.io.BufferedWriter; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +import static org.nuiton.i18n.I18n.t; + +/** + * @author Kevin Morin (Code Lutin) + * @since 4.5 + */ +public class CalcifiedPiecesSamplingExportService extends AbstractTuttiService { + + private static final Log log = LogFactory.getLog(CalcifiedPiecesSamplingExportService.class); + + protected PersistenceService persistenceService; + protected DecoratorService decoratorService; + + @Override + public void setServiceContext(TuttiServiceContext context) { + super.setServiceContext(context); + persistenceService = getService(PersistenceService.class); + decoratorService = getService(DecoratorService.class); + } + + /** + * Export selected cruise with the csv sumatra format. + * + * @param file where to generate report + * @since 2.0 + */ + public void exportCruiseCalcifiedPiecesSamplingsReport(File file, + ProgressionModel progressionModel) { + + Preconditions.checkNotNull(file, "Cannot export to a null file"); + + TuttiDataContext dataContext = context.getDataContext(); + Preconditions.checkState(dataContext.isCruiseSamplingCacheLoaded()); + + List<CalcifiedPiecesSamplingRow> rows = Lists.newArrayList(); + + CalcifiedPiecesSamplingRowModel csvModel = new CalcifiedPiecesSamplingRowModel(context.getConfig().getCsvSeparator()); + + TuttiProtocol protocol = dataContext.getProtocol(); + + Map<Integer, Species> referenceSpeciesByReferenceTaxonId = Maps.uniqueIndex(dataContext.getReferentSpecies(), Speciess.GET_REFERECE_TAXON_ID_AS_INT); + + List<SpeciesProtocol> speciesInAlogirthm = + protocol.getSpecies().stream().filter(speciesProtocol -> !speciesProtocol.isCalcifiedPiecesSamplingDefinitionEmpty()).collect(Collectors.toList()); + + progressionModel.adaptTotal(progressionModel.getTotal() + speciesInAlogirthm.size()); + + Decorator<Species> speciesDecorator = decoratorService.getDecoratorByType(Species.class, DecoratorService.WITH_SURVEY_CODE); + + speciesInAlogirthm.forEach(speciesProtocol -> { + + Species species = referenceSpeciesByReferenceTaxonId.get(speciesProtocol.getSpeciesReferenceTaxonId()); + if (log.isDebugEnabled()) { + log.debug("export species " + species.getReferenceTaxonId() + " " + speciesDecorator.toString(species)); + } + progressionModel.increments(t("tutti.service.cpsExport.step.export.species", speciesDecorator.toString(species))); + + Collection<CalcifiedPiecesSamplingDefinition> cpsDefs = speciesProtocol.getCalcifiedPiecesSamplingDefinition(); + + cpsDefs.forEach(cpsDef -> { + if (cpsDef.isSex()) { + dataContext.getGenderValues().forEach(gender -> rows.addAll(getRows(species, cpsDef, gender))); + + } else { + rows.addAll(getRows(species, cpsDef, null)); + } + }); + }); + + BufferedWriter writer = null; + try { + writer = Files.newWriter(file, Charsets.UTF_8); + Export export = Export.newExport(csvModel, rows); + export.write(writer); + writer.close(); + + } catch (Exception e) { + throw new ApplicationTechnicalException(t("tutti.service.cpsExport.error", file), e); + } finally { + IOUtils.closeQuietly(writer); + } + } + + protected List<CalcifiedPiecesSamplingRow> getRows(Species species, CalcifiedPiecesSamplingDefinition cpsDef, CaracteristicQualitativeValue gender) { + Preconditions.checkState(context.getDataContext().isCruiseSamplingCacheLoaded()); + + Integer speciesId = species.getReferenceTaxonId(); + Boolean maturity = cpsDef.getMaturity(); + Integer maxByLenghtStep = cpsDef.getMaxByLenghtStep(); + int minSize = cpsDef.getMinSize(); + Integer maxSize = cpsDef.getMaxSize(); + + if (log.isDebugEnabled()) { + log.debug("create rows for " + speciesId + " (mat: " + maturity + ", sex: " + gender.getName() + ", max/lengthstep : " + maxByLenghtStep + ", min: " + minSize + ", max: " + maxSize + ")"); + } + + TreeMap<Integer, Integer> samplingNbByLengthStep = + context.getDataContext().getOptionalCruiseSamplingCache().get() + .getSamplingNbByLengthStepForCruise(speciesId, gender, maturity, minSize, maxSize); + + List<CalcifiedPiecesSamplingRow> rows = new ArrayList<>(); + samplingNbByLengthStep.keySet().forEach(lengthStep -> { + CalcifiedPiecesSamplingRow row = new CalcifiedPiecesSamplingRow(); + row.setSpecies(species); + row.setMaturity(maturity); + row.setSex(gender == null ? null : QualitativeValueId.fromValue(gender.getIdAsInt())); + row.setMaxByLengthStep(maxByLenghtStep); + row.setLengthStep(lengthStep); + row.setSamplingNb(samplingNbByLengthStep.getOrDefault(lengthStep, 0)); + rows.add(row); + }); + + if (log.isDebugEnabled()) { + log.debug("==> " + rows.size() + " found"); + } + + return rows; + } + +} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRow.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRow.java new file mode 100644 index 0000000..c719b51 --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRow.java @@ -0,0 +1,76 @@ +package fr.ifremer.tutti.service.export.cps; + +import fr.ifremer.adagio.core.dao.referential.pmfm.QualitativeValueId; +import fr.ifremer.tutti.persistence.entities.referential.Species; + +import java.io.Serializable; + +/** + * @author Kevin Morin (Code Lutin) + * @since 4.5 + */ +public class CalcifiedPiecesSamplingRow implements Serializable { + + + public static final String PROPERTY_SPECIES = "species"; + public static final String PROPERTY_LENGTH_STEP = "lengthStep"; + public static final String PROPERTY_MATURITY = "maturity"; + public static final String PROPERTY_SEX = "sex"; + public static final String PROPERTY_SAMPLING_NB = "samplingNb"; + public static final String PROPERTY_MAX_BY_LENGTH_STEP = "maxByLengthStep"; + + protected Species species; + protected int lengthStep; + protected Boolean maturity; + protected QualitativeValueId sex; + protected int samplingNb; + protected Integer maxByLengthStep; + + public int getLengthStep() { + return lengthStep; + } + + public void setLengthStep(int lengthStep) { + this.lengthStep = lengthStep; + } + + public Boolean getMaturity() { + return maturity; + } + + public void setMaturity(Boolean maturity) { + this.maturity = maturity; + } + + public Integer getMaxByLengthStep() { + return maxByLengthStep; + } + + public void setMaxByLengthStep(Integer maxByLengthStep) { + this.maxByLengthStep = maxByLengthStep; + } + + public int getSamplingNb() { + return samplingNb; + } + + public void setSamplingNb(int samplingNb) { + this.samplingNb = samplingNb; + } + + public QualitativeValueId getSex() { + return sex; + } + + public void setSex(QualitativeValueId sex) { + this.sex = sex; + } + + public Species getSpecies() { + return species; + } + + public void setSpecies(Species species) { + this.species = species; + } +} diff --git a/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRowModel.java b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRowModel.java new file mode 100644 index 0000000..81cb5af --- /dev/null +++ b/tutti-service/src/main/java/fr/ifremer/tutti/service/export/cps/CalcifiedPiecesSamplingRowModel.java @@ -0,0 +1,63 @@ +package fr.ifremer.tutti.service.export.cps; + +import fr.ifremer.adagio.core.dao.referential.pmfm.QualitativeValueId; +import fr.ifremer.tutti.persistence.entities.referential.Species; +import fr.ifremer.tutti.service.csv.AbstractTuttiImportExportModel; +import fr.ifremer.tutti.service.csv.TuttiCsvUtil; +import org.nuiton.csv.ValueFormatter; + +import static org.nuiton.i18n.I18n.t; + +/** + * @author Kevin Morin (Code Lutin) + * @since 4.5 + */ +public class CalcifiedPiecesSamplingRowModel extends AbstractTuttiImportExportModel<CalcifiedPiecesSamplingRow> { + + public CalcifiedPiecesSamplingRowModel(char separator) { + super(separator); + + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.surveyCode"), CalcifiedPiecesSamplingRow.PROPERTY_SPECIES, new ValueFormatter<Species>() { + + @Override + public String format(Species species) { + return String.valueOf(species.getSurveyCode()); + } + }); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.geniusName"), CalcifiedPiecesSamplingRow.PROPERTY_SPECIES, new ValueFormatter<Species>() { + + @Override + public String format(Species species) { + return String.valueOf(species.getName()); + } + }); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.lengthStep"), CalcifiedPiecesSamplingRow.PROPERTY_LENGTH_STEP, TuttiCsvUtil.PRIMITIVE_INTEGER); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.maturity"), CalcifiedPiecesSamplingRow.PROPERTY_MATURITY, new ValueFormatter<Boolean>() { + + @Override + public String format(Boolean maturity) { + if (maturity == null) { + return ""; + } + return maturity ? t("tutti.maturity.mature") : t("tutti.maturity.immature"); + } + }); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.gender"), CalcifiedPiecesSamplingRow.PROPERTY_SEX, new ValueFormatter<QualitativeValueId>() { + + @Override + public String format(QualitativeValueId sex) { + if (sex == null) { + return ""; + } + return t(sex.getDescription()); + } + }); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.samplingNb"), CalcifiedPiecesSamplingRow.PROPERTY_SAMPLING_NB, TuttiCsvUtil.PRIMITIVE_INTEGER); + newColumnForExport(t("tutti.service.calcifiedPiecesSamplingReport.header.maxByLengthStep"), CalcifiedPiecesSamplingRow.PROPERTY_MAX_BY_LENGTH_STEP, TuttiCsvUtil.INTEGER); + } + + @Override + public CalcifiedPiecesSamplingRow newEmptyInstance() { + return new CalcifiedPiecesSamplingRow(); + } +} diff --git a/tutti-service/src/main/resources/i18n/tutti-service_en_GB.properties b/tutti-service/src/main/resources/i18n/tutti-service_en_GB.properties index 5d79d71..1514c68 100644 --- a/tutti-service/src/main/resources/i18n/tutti-service_en_GB.properties +++ b/tutti-service/src/main/resources/i18n/tutti-service_en_GB.properties @@ -6,6 +6,7 @@ tutti.caracteristicType.gearUseFeature= tutti.caracteristicType.individualObservation= tutti.caracteristicType.lengthStep= tutti.caracteristicType.vesselUseFeature= +tutti.cruise.cacheLoader.loading.fishingOperation= tutti.csv.import.error.on.field= tutti.csv.import.error.on.row= tutti.decorator.null.infinite= @@ -80,8 +81,17 @@ tutti.service.bigfinImport.warning.species.notInProtocol= tutti.service.bigfinImport.warning.species.tooCategorized= tutti.service.bigfinImport.warning.speciesBatch.tooCategorized= tutti.service.bigfinimport.error.no.protocol= +tutti.service.calcifiedPiecesSamplingReport.header.gender= +tutti.service.calcifiedPiecesSamplingReport.header.geniusName= +tutti.service.calcifiedPiecesSamplingReport.header.lengthStep= +tutti.service.calcifiedPiecesSamplingReport.header.maturity= +tutti.service.calcifiedPiecesSamplingReport.header.maxByLengthStep= +tutti.service.calcifiedPiecesSamplingReport.header.samplingNb= +tutti.service.calcifiedPiecesSamplingReport.header.surveyCode= tutti.service.compressZipFile.error= tutti.service.context.serviceInstanciation.error= +tutti.service.cpsExport.error= +tutti.service.cpsExport.step.export.species= tutti.service.csv.caracteristic.qualitativeValue.notFound= tutti.service.csv.parse.entityNotFound= tutti.service.csv.parse.foreignEntityNotFound= diff --git a/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties b/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties index c064cbe..cd062bf 100644 --- a/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties +++ b/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties @@ -3,6 +3,7 @@ tutti.caracteristicType.INDIVIDUAL_OBSERVATION=Observations individuelles tutti.caracteristicType.LENGTH_STEP=Classes de tailles tutti.caracteristicType.VESSEL_USE_FEATURE=Autres caractéristiques tutti.caracteristicType.lengthStep= +tutti.cruise.cacheLoader.loading.fishingOperation=Chargement du cache d'échantillons pour le trait \: %s tutti.csv.import.error.on.field=Colonne %s \: %s tutti.csv.import.error.on.row=Des erreurs ont été détectées à la ligne %s \:\n %s tutti.decorator.null.infinite=∞ @@ -69,8 +70,17 @@ tutti.service.bigfinImport.warning.species.notInProtocol=[Enregistrement %s] L'e tutti.service.bigfinImport.warning.species.tooCategorized=L'espèce '<strong>%1s</strong>' est trop catégorisée (pas limitée à '<strong>%2s</strong>' et '<strong>%3s</strong>') tutti.service.bigfinImport.warning.speciesBatch.tooCategorized=[Enregistrement %s] Le lot '<strong>%1s</strong>' contient des sous catégories, on ne peut pas y ajouter des mensurations. tutti.service.bigfinimport.error.no.protocol=Impossible de faire un import Bigfin sans protocol. +tutti.service.calcifiedPiecesSamplingReport.header.gender=Sexe +tutti.service.calcifiedPiecesSamplingReport.header.geniusName=Nom scientifique +tutti.service.calcifiedPiecesSamplingReport.header.lengthStep=Classe de taille (mm) +tutti.service.calcifiedPiecesSamplingReport.header.maturity=Maturité +tutti.service.calcifiedPiecesSamplingReport.header.maxByLengthStep=Max/classe de taille +tutti.service.calcifiedPiecesSamplingReport.header.samplingNb=Nombre de prélèvements +tutti.service.calcifiedPiecesSamplingReport.header.surveyCode=Code campagne tutti.service.compressZipFile.error=Erreur lors de la compression du dossier %1s dans le fichier %2s tutti.service.context.serviceInstanciation.error=Erreur lors de l'instanciation du service %s +tutti.service.cpsExport.error=Erreur à l'export du rapport des prélèvements +tutti.service.cpsExport.step.export.species=Export des prélèvements pour l'espèce %s tutti.service.csv.caracteristic.qualitativeValue.notFound=La caractéristique qualitative %s n'a pas de value d'id %s tutti.service.csv.parse.entityNotFound=L'entité de type %1s avec la propriété %2s de valeur %3s n'a pas été trouvée tutti.service.csv.parse.foreignEntityNotFound=L'entité de type %1s avec l'identifiant %3s n'a pas été trouvée -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 20ebc02ceb4c8b8ba71b14983e1d2c39354c8628 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 15:45:49 2016 +0200 ajout de l'action de rapport de prélèvement pour la campagne (refs #8157) --- .../filtered-resources/tutti-help-fr.properties | 26 +---- .../fr/ifremer/tutti/ui/swing/TuttiUIContext.java | 5 + .../ui/swing/content/home/SelectCruiseUI.jaxx | 1 + .../ui/swing/content/home/SelectCruiseUI.jcss | 10 +- .../CalcifiedPiecesSamplingReportAction.java | 117 +++++++++++++++++++++ .../resources/i18n/tutti-ui-swing_en_GB.properties | 10 ++ .../resources/i18n/tutti-ui-swing_fr_FR.properties | 10 ++ 7 files changed, 154 insertions(+), 25 deletions(-) diff --git a/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties b/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties index d4a116c..7c914a8 100644 --- a/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties +++ b/tutti-ui-swing/src/main/filtered-resources/tutti-help-fr.properties @@ -1,28 +1,5 @@ -### -# #%L -# Tutti :: UI -# $Id:$ -# $HeadURL:$ -# %% -# Copyright (C) 2012 - 2016 Ifremer -# %% -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public -# License along with this program. If not, see -# <http://www.gnu.org/licenses/gpl-3.0.html>. -# #L% -### #Generated by org.nuiton.jaxx.plugin.GenerateHelpIdsMojo -#Tue Mar 22 13:24:39 CET 2016 +#Fri Apr 01 10:33:42 CEST 2016 tutti.config.help=config.html tutti.createAccidentalBatch.action.cancel.help=editFishingOperation.html\#captureCapturesAccidentellesActions tutti.createAccidentalBatch.action.saveAndClose.help=editFishingOperation.html\#captureCapturesAccidentellesActions @@ -487,6 +464,7 @@ tutti.report.field.fishingOperation.help=report.html\#fields tutti.report.field.outputFile.help=report.html\#fields tutti.report.field.report.help=report.html\#fields tutti.report.help=report.html +tutti.selectCruise.action.calcifiedPiecesSamplingReport.help= tutti.selectCruise.action.cloneProtocol.help=selectCruise.html\#actions tutti.selectCruise.action.deleteProtocol.help=selectCruise.html\#actions tutti.selectCruise.action.editCatches.help=selectCruise.html\#actions diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java index 58bbab6..ea9de60 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/TuttiUIContext.java @@ -39,6 +39,7 @@ import fr.ifremer.tutti.service.catches.WeightCleaningService; import fr.ifremer.tutti.service.catches.WeightComputingService; import fr.ifremer.tutti.service.catches.multipost.MultiPostExportService; import fr.ifremer.tutti.service.catches.multipost.MultiPostImportService; +import fr.ifremer.tutti.service.export.cps.CalcifiedPiecesSamplingExportService; import fr.ifremer.tutti.service.export.pdf.CatchesPdfExportService; import fr.ifremer.tutti.service.export.sumatra.CatchesSumatraExportService; import fr.ifremer.tutti.service.export.toconfirmreport.ToConfirmReportService; @@ -750,6 +751,10 @@ public class TuttiUIContext extends AbstractBean implements Closeable, UIMessage return serviceContext.getService(CatchesSumatraExportService.class); } + public CalcifiedPiecesSamplingExportService getCalcifiedPiecesSamplingExportService() { + return serviceContext.getService(CalcifiedPiecesSamplingExportService.class); + } + public MultiPostImportService getMultiPostImportService() { return serviceContext.getService(MultiPostImportService.class); } diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jaxx b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jaxx index 0e049d5..c14782f 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jaxx +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jaxx @@ -65,6 +65,7 @@ <JButton id='editCruiseButton'/> <JButton id='sendCruiseReportButton'/> <JButton id='exportCruiseForSumatraButton'/> + <JButton id='calcifiedPiecesSamplingReportButton'/> <JButton id='speciesToConfirmReportForCruiseButton'/> <JButton id='newProtocolButton'/> <JButton id='importProtocolButton'/> diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jcss b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jcss index 1582844..e77fc74 100644 --- a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jcss +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/SelectCruiseUI.jcss @@ -90,7 +90,7 @@ BeanFilterableComboBox { #editCruiseComboBox { enabled: {model.isProgramFound() && model.isCruiseFound()}; - _comboboxActions: {Arrays.asList(editCruiseButton, sendCruiseReportButton, exportCruiseForSumatraButton, speciesToConfirmReportForCruiseButton)}; + _comboboxActions: {Arrays.asList(editCruiseButton, sendCruiseReportButton, exportCruiseForSumatraButton, calcifiedPiecesSamplingReportButton, speciesToConfirmReportForCruiseButton)}; } #editCruiseButton { @@ -118,6 +118,14 @@ BeanFilterableComboBox { _help: {"tutti.selectCruise.action.exportCruiseForSumatra.help"}; } +#calcifiedPiecesSamplingReportButton { + actionIcon: report; + text: "tutti.selectCruise.action.calcifiedPiecesSamplingReport"; + toolTipText: "tutti.selectCruise.action.calcifiedPiecesSamplingReport.tip"; + _applicationAction: {fr.ifremer.tutti.ui.swing.content.home.actions.CalcifiedPiecesSamplingReportAction.class}; + _help: {"tutti.selectCruise.action.calcifiedPiecesSamplingReport.help"}; +} + #speciesToConfirmReportForCruiseButton { actionIcon: report; text: "tutti.selectCruise.action.speciesToConfirmReportForCruise"; diff --git a/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java new file mode 100644 index 0000000..d898c18 --- /dev/null +++ b/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/home/actions/CalcifiedPiecesSamplingReportAction.java @@ -0,0 +1,117 @@ +package fr.ifremer.tutti.ui.swing.content.home.actions; + +import com.google.common.base.Preconditions; +import fr.ifremer.tutti.persistence.ProgressionModel; +import fr.ifremer.tutti.persistence.entities.data.Cruise; +import fr.ifremer.tutti.service.export.cps.CalcifiedPiecesSamplingExportService; +import fr.ifremer.tutti.service.sampling.CruiseSamplingCacheLoader; +import fr.ifremer.tutti.ui.swing.content.MainUIHandler; +import fr.ifremer.tutti.ui.swing.content.actions.AbstractMainUITuttiAction; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.DateUtil; + +import java.io.File; +import java.util.Date; + +import static org.nuiton.i18n.I18n.t; + +/** + * @author Kevin Morin (Code Lutin) + * @since 4.5 + */ +public class CalcifiedPiecesSamplingReportAction extends AbstractMainUITuttiAction { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(CalcifiedPiecesSamplingReportAction.class); + + protected File file; + +// protected SumatraExportResult sumatraExportResult; + + public CalcifiedPiecesSamplingReportAction(MainUIHandler handler) { + super(handler, false); + } + + @Override + public boolean prepareAction() throws Exception { + + boolean doAction = super.prepareAction(); + + if (doAction && !getDataContext().isProtocolFilled()) { + displayErrorMessage( + t("tutti.exportCpsCsv.title.missing.protocol"), + t("tutti.exportCpsCsv.message.missing.protocol") + ); + doAction = false; + } + + if (doAction && !getDataContext().getProtocol().isUseCalcifiedPieceSampling()) { + displayErrorMessage( + t("tutti.exportCpsCsv.title.sampling.notActivated"), + t("tutti.exportCpsCsv.message.sampling.notActivated") + ); + doAction = false; + } + + if (doAction) { + + String date = DateUtil.formatDate(new Date(), "dd-MM-yyyy"); + String exportFilename = t("tutti.exportCpsCsv.fileName", getDataContext().getCruise().getName(), date); + + // choose file to export + file = saveFile( + exportFilename, + "csv", + t("tutti.exportCpsCsv.title.choose.exportFile"), + t("tutti.exportCpsCsv.action.chooseFile"), + "^.+\\.csv$", t("tutti.common.file.csv") + ); + doAction = file != null; + } + return doAction; + } + + @Override + public void doAction() throws Exception { + Cruise cruise = getDataContext().getCruise(); + Preconditions.checkNotNull(cruise); + Preconditions.checkNotNull(file); + + if (log.isInfoEnabled()) { + log.info("Will export cps for cruise " + cruise.getId() + + " to file: " + file); + } + ProgressionModel pm = new ProgressionModel(); + setProgressionModel(pm); + + long cruiseFishingOperationIds = getDataContext().getCruiseFishingOperationIds().stream().count(); + pm.setTotal((int) (1 + cruiseFishingOperationIds)); + + if (!getDataContext().isCruiseSamplingCacheLoaded()) { + CruiseSamplingCacheLoader cruiseSamplingCacheLoader = new CruiseSamplingCacheLoader(getContext().getPersistenceService(), + getContext().getDecoratorService(), getProgressionModel()); + getDataContext().loadCruiseSamplingCache(cruiseSamplingCacheLoader); + } + + + // export sampling report + + CalcifiedPiecesSamplingExportService service = getContext().getCalcifiedPiecesSamplingExportService(); + service.exportCruiseCalcifiedPiecesSamplingsReport(file, pm); + } + + @Override + public void postSuccessAction() { + super.postSuccessAction(); + sendMessage(t("tutti.exportCpsCsv.action.success", file)); + } + + @Override + public void releaseAction() { + file = null; + super.releaseAction(); + } + +} diff --git a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties index e9c7a23..34764e9 100644 --- a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties +++ b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_en_GB.properties @@ -1681,6 +1681,14 @@ tutti.error.update.bad.url.syntax= tutti.error.update.could.not.found.url= tutti.error.update.could.not.reach.url= tutti.error.write.startActionFile=could not write action content to file %s +tutti.exportCpsCsv.action.chooseFile= +tutti.exportCpsCsv.action.success= +tutti.exportCpsCsv.fileName= +tutti.exportCpsCsv.message.missing.protocol= +tutti.exportCpsCsv.message.sampling.notActivated= +tutti.exportCpsCsv.title.choose.exportFile= +tutti.exportCpsCsv.title.missing.protocol= +tutti.exportCpsCsv.title.sampling.notActivated= tutti.exportCruise.action.computeNbSteps= tutti.exportCruise.action.exportErrors= tutti.exportCruise.action.success= @@ -2355,6 +2363,8 @@ tutti.rtpEdit.askCancelEditBeforeLeaving= tutti.rtpEdit.askSaveBeforeLeaving= tutti.rtpEdit.title= tutti.selectBenthos.title= +tutti.selectCruise.action.calcifiedPiecesSamplingReport= +tutti.selectCruise.action.calcifiedPiecesSamplingReport.tip= tutti.selectCruise.action.chooseCruiseExportFile= tutti.selectCruise.action.chooseProgramExportFile= tutti.selectCruise.action.cloneProtocol= diff --git a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties index 867d16b..153d119 100644 --- a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties +++ b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties @@ -1567,6 +1567,14 @@ tutti.error.update.bad.url.syntax=Mise à jour impossible (le format de l'url <s tutti.error.update.could.not.found.url=Mise à jour impossible (l'url <strong>%s</strong> n'existe pas) tutti.error.update.could.not.reach.url=Mise à jour impossible (l'url <strong>%s</strong> n'est pas joignable) tutti.error.write.startActionFile=impossible d'écrire dans le fichier %s +tutti.exportCpsCsv.action.chooseFile=Exporter +tutti.exportCpsCsv.action.success=Le rapport des prélèvements de la campagne a été exporté daans le fichier <strong>%s</strong>. +tutti.exportCpsCsv.fileName=Rapport_prelevement_%1$s_%2$s +tutti.exportCpsCsv.message.missing.protocol=<html><body>Pas de protocole renseigné, impossible d'exporter le rapport de prélèvement.</body></html> +tutti.exportCpsCsv.message.sampling.notActivated=<html><body>L'algorithme de prélèvement n'a pas été activé dans le protocole, impossible d'exporter le rapport de prélèvement.</body></html> +tutti.exportCpsCsv.title.choose.exportFile=Exporter le rapport de prélèvement +tutti.exportCpsCsv.title.missing.protocol=Pas de protocole renseigné +tutti.exportCpsCsv.title.sampling.notActivated=Algorithme de prélèvement non activé tutti.exportCruise.action.computeNbSteps=Calcul du nombre d'opérations à réaliser tutti.exportCruise.action.exportErrors=Des erreurs sont apparues pendant l'élévation des poids de la campagne <strong>%s</strong>.<br/>L'export a cependant été réalisé.<hr/>Erreur(s) rencontrée(s) \: <br/>%s tutti.exportCruise.action.success=La campagne <strong>%s</strong> a été exportée dans le fichier <strong>%s</strong>. @@ -2162,6 +2170,8 @@ tutti.rtpEdit.askCancelEditBeforeLeaving=Les relations taille-poids ne sont pas tutti.rtpEdit.askSaveBeforeLeaving=Des modifications n'ont pas été enregistrées tutti.rtpEdit.title=Relations taille-poids de l'espèce %s tutti.selectBenthos.title=Choisissez une espèce du benthos +tutti.selectCruise.action.calcifiedPiecesSamplingReport=Exporter le rapport de prélèvements +tutti.selectCruise.action.calcifiedPiecesSamplingReport.tip=Exporter le rapport de prélèvements tutti.selectCruise.action.chooseCruiseExportFile=Exporter tutti.selectCruise.action.chooseProgramExportFile=Exporter tutti.selectCruise.action.cloneProtocol=Cloner -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/8157 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 6afd5b0048cc405368c6d4d84e7c3e9f79901874 Author: Kevin Morin <morin@codelutin.com> Date: Fri Apr 1 23:34:13 2016 +0200 i18n (fixes #8157) --- tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties | 3 +++ .../src/main/resources/i18n/tutti-ui-swing_fr_FR.properties | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties b/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties index cd062bf..e528d17 100644 --- a/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties +++ b/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties @@ -1,3 +1,6 @@ +adagio.enumeration.QualitativeValueId.SEX_FEMALE.description=Femelle +adagio.enumeration.QualitativeValueId.SEX_MALE.description=Male +adagio.enumeration.QualitativeValueId.SEX_UNDEFINED.description=Inconnu tutti.caracteristicType.GEAR_USE_FEATURE=Caractéristiques de l'engin tutti.caracteristicType.INDIVIDUAL_OBSERVATION=Observations individuelles tutti.caracteristicType.LENGTH_STEP=Classes de tailles diff --git a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties index 153d119..122a40d 100644 --- a/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties +++ b/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properties @@ -1572,7 +1572,7 @@ tutti.exportCpsCsv.action.success=Le rapport des prélèvements de la campagne a tutti.exportCpsCsv.fileName=Rapport_prelevement_%1$s_%2$s tutti.exportCpsCsv.message.missing.protocol=<html><body>Pas de protocole renseigné, impossible d'exporter le rapport de prélèvement.</body></html> tutti.exportCpsCsv.message.sampling.notActivated=<html><body>L'algorithme de prélèvement n'a pas été activé dans le protocole, impossible d'exporter le rapport de prélèvement.</body></html> -tutti.exportCpsCsv.title.choose.exportFile=Exporter le rapport de prélèvement +tutti.exportCpsCsv.title.choose.exportFile=Rapport de prélèvements tutti.exportCpsCsv.title.missing.protocol=Pas de protocole renseigné tutti.exportCpsCsv.title.sampling.notActivated=Algorithme de prélèvement non activé tutti.exportCruise.action.computeNbSteps=Calcul du nombre d'opérations à réaliser @@ -2170,7 +2170,7 @@ tutti.rtpEdit.askCancelEditBeforeLeaving=Les relations taille-poids ne sont pas tutti.rtpEdit.askSaveBeforeLeaving=Des modifications n'ont pas été enregistrées tutti.rtpEdit.title=Relations taille-poids de l'espèce %s tutti.selectBenthos.title=Choisissez une espèce du benthos -tutti.selectCruise.action.calcifiedPiecesSamplingReport=Exporter le rapport de prélèvements +tutti.selectCruise.action.calcifiedPiecesSamplingReport=Rapport de prélèvements tutti.selectCruise.action.calcifiedPiecesSamplingReport.tip=Exporter le rapport de prélèvements tutti.selectCruise.action.chooseCruiseExportFile=Exporter tutti.selectCruise.action.chooseProgramExportFile=Exporter -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm