BrightSide Workbench Full Report + Source Code
DossierDWReport.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2018 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.dossier.dw;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Date;
24 import java.util.EnumMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import org.turro.dossier.db.DossierPU;
29 import org.turro.dossier.dossier.DossierData;
30 import org.turro.dossier.dossier.DossierReportItem;
31 import org.turro.dossier.dossier.DossierValues;
32 import org.turro.dossier.entity.Dossier;
33 import org.turro.dossier.entity.IssueParticipantRole;
34 import org.turro.dossier.entity.IssueResolution;
35 import org.turro.dossier.entity.IssueStatus;
36 import org.turro.dossier.entity.IssueType;
37 import org.turro.dossier.search.DossierIds;
38 import org.turro.elephant.db.WhereClause;
39 import org.turro.i18n.I_;
40 import org.turro.jpa.Dao;
41 import org.turro.math.Round;
42 import org.turro.util.PhraseBuilder;
43 
48 public class DossierDWReport {
49 
50  private DossierValues prevision, reality;
51  private HashSet<DossierReportItem> items;
52  private String participantId;
53  private IssueParticipantRole role;
54  private Collection<DossierIds> dossierIds;
55 
56  public void setReportValues(Dossier dossier) {
57  setReportValues(null, null, dossier.getId());
58  }
59 
60  public void setReportValues(String participantId, IssueParticipantRole role, Long dossierId) {
61  ArrayList al = new ArrayList();
62  al.add(new DossierIds(dossierId, 0L, null));
63  setReportValues(participantId, role, al);
64  }
65 
66  public void setReportValues(String participantId, IssueParticipantRole role, Collection<DossierIds> dossierIds) {
67  this.participantId = participantId;
68  this.role = role;
69  this.dossierIds = dossierIds;
70  prevision = null;
71  reality = null;
72  items = null;
73  }
74 
75  public double getIssueCount() {
76  return (double) getItems().size();
77  }
78 
80  if(prevision == null) {
81  prevision = new DossierValues();
82  for(DossierReportItem dri : getItems()) {
83  prevision.expenses += dri.prevision.expenses;
84  prevision.hours += dri.prevision.hours;
85  prevision.price += dri.prevision.price;
86  }
87  }
88  return prevision;
89  }
90 
92  if(reality == null) {
93  reality = new DossierValues();
94  for(DossierReportItem dri : getItems()) {
95  reality.expenses += dri.reality.expenses;
96  reality.hours += dri.reality.hours;
97  reality.price += dri.reality.price;
98  }
99  }
100  return reality;
101  }
102 
103  public DossierData getData() {
104  return new DossierData(getPrevision(), getReality());
105  }
106 
107  public double getIssueCountByType(IssueType type) {
108  double count = 0;
109  for(DossierReportItem dri : getItems()) {
110  if(dri.type.equals(type)) {
111  count++;
112  }
113  }
114  return count;
115  }
116 
117  public double getIssueCountByStatus(IssueStatus status) {
118  double count = 0;
119  for(DossierReportItem dri : getItems()) {
120  if(dri.status.equals(status)) {
121  count++;
122  }
123  }
124  return count;
125  }
126 
127  public double getIssueCountByResolution(IssueResolution resolution) {
128  double count = 0;
129  for(DossierReportItem dri : getItems()) {
130  if(dri.status.isFinished() && dri.resolution.equals(resolution)) {
131  count++;
132  }
133  }
134  return count;
135  }
136 
137  public double getPositivelySolved() {
138  double count = 0;
139  for(DossierReportItem dri : getItems()) {
140  if(dri.status.isFinished() && dri.resolution.isSolved()) {
141  count++;
142  }
143  }
144  return count;
145  }
146 
147  public double getNegativelySolved() {
148  double count = 0;
149  for(DossierReportItem dri : getItems()) {
150  if(dri.status.isFinished() && !(dri.resolution.isSolved()) && !(dri.resolution.isRejected())) {
151  count++;
152  }
153  }
154  return count;
155  }
156 
157  public double getSolved() {
158  double count = 0;
159  for(DossierReportItem dri : getItems()) {
160  if(dri.status.isFinished()) {
161  count++;
162  }
163  }
164  return count;
165  }
166 
167  public double getOnWork() {
168  double count = 0;
169  for(DossierReportItem dri : getItems()) {
170  if(dri.status.isWorking()) {
171  count++;
172  }
173  }
174  return count;
175  }
176 
177  public double getStandBy() {
178  double count = 0;
179  for(DossierReportItem dri : getItems()) {
180  if(dri.status.isStandBy()) {
181  count++;
182  }
183  }
184  return count;
185  }
186 
187  public Collection<String> getIssuesPathByType(String type) {
188  ArrayList<String> list = new ArrayList<>();
189  for(DossierReportItem dri : getItems()) {
190  if(I_.byKey(dri.type.toString()).equals(type)) {
191  list.add("/issue/" + dri.issueId);
192  }
193  }
194  return list;
195  }
196 
197  public Collection<String> getIssuesPathByStatus(String status) {
198  ArrayList<String> list = new ArrayList<>();
199  for(DossierReportItem dri : getItems()) {
200  if(I_.byKey(dri.status.toString()).equals(status)) {
201  list.add("/issue/" + dri.issueId);
202  }
203  }
204  return list;
205  }
206 
207  public Collection<String> getIssuesPathByResolution(String resolution) {
208  ArrayList<String> list = new ArrayList<>();
209  for(DossierReportItem dri : getItems()) {
210  if(I_.byKey(dri.resolution.toString()).equals(resolution)) {
211  list.add("/issue/" + dri.issueId);
212  }
213  }
214  return list;
215  }
216 
217 
218  public Map<IssueType, Double> getIssuesByType() {
219  Map type = new EnumMap<>(IssueType.class);
220  for(IssueType is : IssueType.values()) {
221  double d = getIssueCountByType(is);
222  if(d > 0.0) type.put(is, d);
223  }
224  return type;
225  }
226 
227  public Map<IssueStatus, Double> getIssuesByStatus() {
228  Map status = new EnumMap<>(IssueStatus.class);
229  for(IssueStatus is : IssueStatus.values()) {
230  double d = getIssueCountByStatus(is);
231  if(d > 0.0) status.put(is, d);
232  }
233  return status;
234  }
235 
236  public Map<IssueResolution, Double> getIssuesByResolution() {
237  Map resolution = new EnumMap<>(IssueResolution.class);
238  for(IssueResolution is : IssueResolution.values()) {
239  double d = getIssueCountByResolution(is);
240  if(d > 0.0) resolution.put(is, d);
241  }
242  return resolution;
243  }
244 
245  public Double getEfectivity() {
246  double solved = getSolved();
247  return new Round(solved > 0 ? getPositivelySolved() / solved : 0).perCent(2);
248  }
249 
250  public Double getDaySpanAverage() {
251  double issues = 0, days = 0;
252  for(DossierReportItem dri : getItems()) {
253  if(dri.status.isFinished() && dri.startDate != null &&
254  dri.solvedDate != null && dri.startDate.before(dri.solvedDate)) {
255  issues++;
256  days = (dri.solvedDate.getTime() - dri.startDate.getTime()) / (24 * 60 * 60 * 1000);
257  }
258  }
259  return new Round(issues > 0 ? days / issues : 0).decimals(2).value();
260  }
261 
262  private String getInValue(Collection<DossierIds> dossierIds) {
263  PhraseBuilder pb = new PhraseBuilder();
264  pb.addWord("(");
265  for(DossierIds id : dossierIds) {
266  pb.addWord(id.dossierId + "");
267  pb.addPendingSeparator(",");
268  }
269  pb.cancelSeparator();
270  pb.addWord(")");
271  return pb.toString();
272  }
273 
274  private HashSet<DossierReportItem> getItems() {
275  if(items == null) {
276  items = new HashSet<>();
277  init(participantId, role, dossierIds);
278  }
279  return items;
280  }
281 
282  private void init(String participantId, IssueParticipantRole role, Collection<DossierIds> dossierIds) {
283  Dao dao = new DossierPU();
284  WhereClause wc = new WhereClause();
285  wc.addClause("select distinct issueId, type, status, resolution,");
286  wc.addClause("pexpenses, phours, pprice,");
287  wc.addClause("startDate, solvedDate,");
288  wc.addClause("commentCount, rexpenses,");
289  wc.addClause("rhours, rprice");
290  wc.addClause("from DWIssue as issue where 1=1");
291  if(participantId != null) {
292  wc.addClause("and participantId = :idContact");
293  wc.addClause("and participantRole = :role");
294  wc.addNamedValue("idContact", participantId);
295  wc.addNamedValue("role", role);
296  }
297  if(dossierIds != null && !dossierIds.isEmpty()) {
298  wc.addClause("and issue.dossierId in " + getInValue(dossierIds));
299  }
300  wc.addClause("and (issue.startDate <= :startDate or issue.startDate is null)");
301  wc.addNamedValue("startDate", new Date());
302  List<Object[]> l = dao.getResultList(wc);
303  for(Object[] result : l) {
304  DossierReportItem dri = new DossierReportItem();
305  dri.issueId = (Long) result[0];
306  dri.type = (IssueType) result[1];
307  dri.status = (IssueStatus) result[2];
308  dri.resolution = (IssueResolution) result[3];
309  dri.prevision.expenses = (Double) result[4];
310  dri.prevision.hours = (Double) result[5];
311  dri.prevision.price = (Double) result[6];
312  dri.setStartDate((Date) result[7], (Date) result[7]);
313  dri.solvedDate = (Date) result[8];
314  dri.commentCount = result[9] == null ? 0 : (Long) result[9];
315  dri.reality.expenses = result[10] == null ? 0 : (Double) result[10];
316  dri.reality.hours = result[11] == null ? 0 : (Double) result[11];
317  dri.reality.price = result[12] == null ? 0 : (Double) result[12];
318  items.add(dri);
319  }
320  }
321 
322 }
Collection< String > getIssuesPathByStatus(String status)
void setReportValues(String participantId, IssueParticipantRole role, Long dossierId)
Map< IssueResolution, Double > getIssuesByResolution()
double getIssueCountByType(IssueType type)
Collection< String > getIssuesPathByType(String type)
double getIssueCountByResolution(IssueResolution resolution)
Map< IssueStatus, Double > getIssuesByStatus()
void setReportValues(String participantId, IssueParticipantRole role, Collection< DossierIds > dossierIds)
Map< IssueType, Double > getIssuesByType()
double getIssueCountByStatus(IssueStatus status)
Collection< String > getIssuesPathByResolution(String resolution)
static String byKey(String key)
Definition: I_.java:83
Round decimals(int digits)
Definition: Round.java:32
double perCent(int digits)
Definition: Round.java:38