View Javadoc
1   package fr.ifremer.tutti.service.pupitri;
2   
3   /*
4    * #%L
5    * Tutti :: Service
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.collect.ImmutableSet;
26  import fr.ifremer.tutti.persistence.entities.referential.Species;
27  import fr.ifremer.tutti.type.WeightUnit;
28  import fr.ifremer.tutti.util.Weights;
29  import org.apache.commons.lang3.mutable.MutableFloat;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.nuiton.decorator.Decorator;
33  
34  import java.util.ArrayList;
35  import java.util.Iterator;
36  import java.util.LinkedHashSet;
37  import java.util.List;
38  import java.util.Set;
39  
40  import static org.nuiton.i18n.I18n.t;
41  
42  /**
43   * Result of a pupitri import.
44   *
45   * Created on 12/17/13.
46   *
47   * @author Tony Chemit - chemit@codelutin.com
48   * @since 3.0
49   */
50  public class PupitriImportResult {
51  
52      /** Logger. */
53      private static final Log log = LogFactory.getLog(PupitriImportResult.class);
54  
55      /**
56       * Nombre de lignes importes depuis le fichier tremie.
57       */
58      private int nbTrunkImported;
59  
60      /**
61       * Nombre de lignes rejetes depuis le fichier tremie.
62       */
63      private int nbTrunkNotImported;
64  
65      /**
66       * Nombre d'espèces importées depuis le fichier carrousel.
67       */
68      private int nbCarrousselImported;
69  
70      /**
71       * Poids total trié cumulé depuis le fichier tremie.
72       */
73      private Float sortedWeight;
74  
75      /**
76       * Poids total rejeté cumulé depuis le fichier tremie.
77       */
78      private Float rejectedWeight;
79  
80      /**
81       * Poids total du VRAC cumulé depuis le fichier carrousel.
82       */
83      private Float carrouselSortedWeight;
84  
85      /**
86       * Poids total du HORS-VRAC cumulé depuis le fichier carrousel.
87       */
88      private Float carrouselUnsortedWeight;
89  
90      /**
91       * Liste des lots lus depuis le fichier carrousel. Chaque lot est un tuple (espece,trie).
92       */
93      private final List<PupitriSpeciesContext> catches;
94  
95      /**
96       * Ensemble de identifiants d'espèces non importés depuis el fichier carrousel.
97       *
98       * @since 3.10
99       */
100     private final Set<String> notImportedSpeciesIds;
101 
102     /**
103      * Poids total des espèces du mélange cumulé depuis le fichier carrousel, i.e de toutes les lignes dont
104      * l'espèce appartient à l'ensemble {@link PupitriSpeciesContext#MELAG_SPECIES}.
105      *
106      * @since 3.4.2
107      */
108     private MutableFloat melagTotalWeight;
109 
110     /**
111      * Poids total des espèces du mélange cumulé depuis le fichier carrousel, i.e de toutes les lignes dont
112      * l'espèce appartient à l'ensemble {@link PupitriSpeciesContext#MELAG_SPECIES}. Poids renseigné par l'utilisateur.
113      *
114      * @since 4.5
115      */
116     private Float editedMelagTotalWeight;
117 
118     /**
119      * Poids total des lots echantillone cumulé depuis le fichier carrousel, i.e toutes les lignes dont le signe de
120      * l'espèce est {@code T}.
121      *
122      * @since 3.4.2
123      */
124     private MutableFloat melagSortedWeight;
125 
126     /**
127      * Commentaire à ajouter sur tous les lots importés en tant que MELAG.
128      *
129      * @since 3.10
130      */
131     private String melagComment;
132 
133     /**
134      * L'identifiant de la pièce-jointe du rapport généré suite à l'import.
135      *
136      * @since 3.11
137      */
138     private String reportAttachmentId;
139 
140     /**
141      * Le nom du rapport généré suite à l'import.
142      *
143      * @since 3.11
144      */
145     private String reportAttachmentFilename;
146 
147     public PupitriImportResult() {
148         this.catches = new ArrayList<>();
149         this.notImportedSpeciesIds = new LinkedHashSet<>();
150     }
151 
152     public boolean isFishingOperationFound() {
153         return nbTrunkImported + nbCarrousselImported > 0;
154     }
155 
156     public int getNbTrunkImported() {
157         return nbTrunkImported;
158     }
159 
160     public int getNbTrunkNotImported() {
161         return nbTrunkNotImported;
162     }
163 
164     public int getNbCarrousselImported() {
165         return nbCarrousselImported;
166     }
167 
168     public int getNbCarrousselNotImported() {
169         return notImportedSpeciesIds.size();
170     }
171 
172     public Float getSortedWeight() {
173         return sortedWeight;
174     }
175 
176     public Float getRejectedWeight() {
177         return rejectedWeight;
178     }
179 
180     public Float getCarrouselSortedWeight() {
181         return carrouselSortedWeight;
182     }
183 
184     public Float getCarrouselUnsortedWeight() {
185         return carrouselUnsortedWeight;
186     }
187 
188     public List<PupitriSpeciesContext> getCatches() {
189         return catches;
190     }
191 
192     public Float getMelagTotalWeight() {
193         return melagTotalWeight == null ? null : melagTotalWeight.floatValue();
194     }
195 
196     public void setMelagTotalWeight(float melagTotalWeight) {
197         this.melagTotalWeight.setValue(melagTotalWeight);
198     }
199 
200     public Float getEditedMelagTotalWeight() {
201         return editedMelagTotalWeight;
202     }
203 
204     public void setEditedMelagTotalWeight(float editedMelagTotalWeight) {
205         this.editedMelagTotalWeight = editedMelagTotalWeight;
206     }
207 
208     public Float getMelagSortedWeight() {
209         return melagSortedWeight == null ? null : melagSortedWeight.floatValue();
210     }
211 
212     public String getMelagComment() {
213         return melagComment;
214     }
215 
216     public Set<String> getNotImportedSpeciesIds() {
217         return ImmutableSet.copyOf(notImportedSpeciesIds);
218     }
219 
220     public String getReportAttachmentId() {
221         return reportAttachmentId;
222     }
223 
224     public String getReportAttachmentFilename() {
225         return reportAttachmentFilename;
226     }
227 
228     /**
229      * @return {@code true} if there is a total melag weight defined (at least one species MELA-GNE found).
230      * @since 3.4.2
231      */
232     public boolean isFoundTotalMelag() {
233         return melagTotalWeight != null;
234     }
235 
236     /**
237      * @return {@code true} if at least one species has a sorted melag weight.
238      * @since 3.4.2
239      */
240     public boolean isFoundSortedMelag() {
241         return melagSortedWeight != null;
242     }
243 
244     void incrementNbTrunkImported() {
245         this.nbTrunkImported++;
246     }
247 
248     void incrementNbTrunkNotImported() {
249         this.nbTrunkNotImported++;
250     }
251 
252     void setSortedWeight(Float sortedWeight) {
253         this.sortedWeight = sortedWeight;
254     }
255 
256     void setRejectedWeight(Float rejectedWeight) {
257         this.rejectedWeight = rejectedWeight;
258     }
259 
260     void setReportAttachmentId(String reportAttachmentId) {
261         this.reportAttachmentId = reportAttachmentId;
262     }
263 
264     void setReportAttachmentFilename(String reportAttachmentFilename) {
265         this.reportAttachmentFilename = reportAttachmentFilename;
266     }
267 
268     void flushCarrouselResult(CarrouselImportRequestResult carrouselImportRequestResult) {
269 
270         // set carrousel sorted weight
271         this.carrouselSortedWeight = WeightUnit.KG.round(carrouselImportRequestResult.getCarrouselSortedWeight());
272         this.carrouselUnsortedWeight = WeightUnit.KG.round(carrouselImportRequestResult.getCarrouselUnsortedWeight());
273 
274         // set nb carrousel imported batches
275         this.nbCarrousselImported = carrouselImportRequestResult.getNbCarrousselImported();
276         this.notImportedSpeciesIds.addAll(carrouselImportRequestResult.getNotImportedSpeciesIds());
277 
278         List<PupitriSpeciesContext> incomingCatches = carrouselImportRequestResult.getCatches();
279 
280         for (PupitriSpeciesContext aCatch : incomingCatches) {
281             addCatch(aCatch);
282         }
283 
284     }
285 
286     void prepareMelag(Decorator<Species> speciesDecorator) {
287 
288         boolean useMelag = isFoundTotalMelag() && isFoundSortedMelag();
289 
290         float melagRatio = 1f;
291 
292         if (useMelag) {
293             melagRatio = melagSortedWeight.floatValue() / editedMelagTotalWeight;
294 
295             if (log.isInfoEnabled()) {
296                 log.info("Use Melag (sorted weight: " + melagSortedWeight.floatValue() + " / total weight: " + editedMelagTotalWeight + ")");
297             }
298         }
299 
300 
301         String unitLabel = WeightUnit.KG.getShortLabel();
302 
303         StringBuilder melagCommentBuilder = new StringBuilder(t("tutti.service.pupitri.import.createMelag.comment.part1") + "\n");
304 
305         Iterator<PupitriSpeciesContext> iterator = catches.iterator();
306         while (iterator.hasNext()) {
307             PupitriSpeciesContext aCatch = iterator.next();
308 
309             if (useMelag && aCatch.isMelagMetaSpecies()) {
310 
311                 // remove the MELAG species from import
312                 iterator.remove();
313                 continue;
314 
315             }
316 
317             if (aCatch.isForMelag()) {
318 
319                 if (useMelag) {
320 
321                     // compute the weight from melag
322 
323                     Float sampleWeight = aCatch.getWeight(Signs.MELAG);
324                     Float weight = WeightUnit.KG.round(sampleWeight / melagRatio);
325 
326                     if (!aCatch.containsSign(Signs.BIG)) {
327 
328                         // No BIG batch associated with this melag species
329                         // use default batch
330                         // see https://forge.codelutin.com/issues/5742
331                         aCatch.setMelagElevatedWeight(Signs.DEFAULT, weight);
332 
333                         if (log.isInfoEnabled()) {
334                             log.info("Add melag batch for " + aCatch + " as default (no G found) : " + weight);
335                         }
336 
337                     } else {
338 
339                         // also found a big batch associated with this melga species
340                         // transform it as a small batch instead of default
341                         // see https://forge.codelutin.com/issues/5742
342                         aCatch.setMelagElevatedWeight(Signs.SMALL, weight);
343 
344                         if (log.isInfoEnabled()) {
345                             log.info("Add melag batch for " + aCatch + " as small (G found) : " + weight);
346                         }
347 
348                     }
349 
350                     melagCommentBuilder.append(t("tutti.service.pupitri.import.createMelag.comment.part2", sampleWeight, unitLabel, speciesDecorator.toString(aCatch.getSpecies()))).append("\n");
351 
352                 } else {
353 
354                     // move the melag weight as a default weight
355 
356                     aCatch.moveMelagToDefaultSign();
357 
358                 }
359             }
360 
361         }
362 
363         if (useMelag) {
364 
365             melagCommentBuilder.append(t("tutti.service.pupitri.import.createMelag.comment.part3", editedMelagTotalWeight, unitLabel)).append("\n");
366 
367             if (WeightUnit.KG.isNotEquals(editedMelagTotalWeight, melagTotalWeight.floatValue())) {
368                 melagCommentBuilder.append(t("tutti.service.pupitri.import.createMelag.comment.part4", melagTotalWeight.floatValue(), unitLabel, editedMelagTotalWeight, unitLabel)).append("\n");
369             }
370 
371             melagComment = melagCommentBuilder.toString();
372             if (log.isInfoEnabled()) {
373                 log.info("Melag comment:\n" + melagComment);
374             }
375 
376         }
377 
378     }
379 
380     private void addCatch(PupitriSpeciesContext aCatch) {
381 
382         catches.add(aCatch);
383 
384         if (aCatch.isMelagMetaSpecies()) {
385 
386             if (log.isInfoEnabled()) {
387                 log.info("Found a MELAG catch: " + aCatch);
388             }
389             // add weight to melag
390             addMelagTotalWeight(aCatch.getWeight(Signs.DEFAULT));
391 
392         }
393 
394         if (aCatch.isForMelag()) {
395 
396             // add weight to sorted melag
397             if (log.isInfoEnabled()) {
398                 log.info("Found a catch used in MELAG: " + aCatch);
399             }
400             addMelagSortedWeight(aCatch.getWeight(Signs.MELAG));
401 
402         }
403 
404     }
405 
406     private void addMelagTotalWeight(float weight) {
407 
408         if (melagTotalWeight == null) {
409             melagTotalWeight = new MutableFloat();
410         }
411         melagTotalWeight.add(weight);
412 
413     }
414 
415     private void addMelagSortedWeight(float weight) {
416 
417         if (melagSortedWeight == null) {
418             melagSortedWeight = new MutableFloat();
419         }
420         melagSortedWeight.add(weight);
421 
422     }
423 }