Author: fdesbois Date: 2010-02-12 00:58:46 +0000 (Fri, 12 Feb 2010) New Revision: 347 Added: trunk/suiviobsmer-ui/src/main/webapp/img/synthesis-ind-allegro-reactivity.png Modified: trunk/changelog.txt trunk/pom.xml trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/SuiviObsmerContext.java trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImpl.java trunk/suiviobsmer-business/src/main/xmi/suiviobsmer.zargo trunk/suiviobsmer-business/src/test/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImplTest.java trunk/suiviobsmer-ui/src/main/java/fr/ifremer/suiviobsmer/ui/pages/Synthesis.java trunk/suiviobsmer-ui/src/main/resources/fr/ifremer/suiviobsmer/ui/pages/Synthesis.properties trunk/suiviobsmer-ui/src/main/webapp/Synthesis.tml trunk/suiviobsmer-ui/src/main/webapp/css/synthesis.css Log: Evo #1985 : Indicator for allegro reactivity. Seems to be a wrong calcul using HQL method AVG(day(tideBegin - dataInput)). Moreover a hack was created for H2 which does'nt support this syntax... Must be refactor to be calculated in Java and not in HQL. It's a shame, tests are OK with H2 using only AVG(tideBegin - dataInput)... Difficult to test with Postgresql because of specificity of clear method in ToPIA for dropping database. Modified: trunk/changelog.txt =================================================================== --- trunk/changelog.txt 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/changelog.txt 2010-02-12 00:58:46 UTC (rev 347) @@ -9,6 +9,8 @@ Evolutions ++++++++++ +- [fdesbois] Evo #1985 : Synthèse : indicateur nombre de jour moyen entre date + de saisie dans Allegro et date de fin de marée des contacts - [fdesbois] Evo #2022 : Plan d'échantillonnage : Export CSV - [fdesbois] Evo #1986 : Synthèse : indicateur sur les états des contacts - [fdesbois] Evo #1984 : Synthèse : indicateur de non respect du nombre Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/pom.xml 2010-02-12 00:58:46 UTC (rev 347) @@ -222,7 +222,7 @@ <!-- libraries version --> <nuitonutils.version>1.1.3</nuitonutils.version> - <topia.version>2.3.0-beta-8-SNAPSHOT</topia.version> + <topia.version>2.3.0-beta-8</topia.version> <eugene.version>2.0.0-beta-4</eugene.version> <tapestry.version>5.1.0.5</tapestry.version> Modified: trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/SuiviObsmerContext.java =================================================================== --- trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/SuiviObsmerContext.java 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/SuiviObsmerContext.java 2010-02-12 00:58:46 UTC (rev 347) @@ -219,6 +219,8 @@ public static <E extends TopiaEntity> boolean prepareTopiaId(Class<E> entityClass, E entity) { String topiaId = entity.getTopiaId(); + // TODO-FD20100211 : add this behavior in topia in a + // new method createOrUpdate if (StringUtils.isEmpty(entity.getTopiaId())) { topiaId = TopiaId.create(entityClass); entity.setTopiaId(topiaId); Modified: trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImpl.java =================================================================== --- trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImpl.java 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-business/src/main/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImpl.java 2010-02-12 00:58:46 UTC (rev 347) @@ -49,6 +49,7 @@ import java.util.SortedMap; import java.util.TreeMap; import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.framework.TopiaContextImplementor; import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.framework.TopiaQuery.Op; import org.nuiton.topia.persistence.TopiaEntity; @@ -414,4 +415,79 @@ return results.values(); } + @Override + public Map<String, Double> getContactDataInputDateReactivity(Company company, PeriodDates period) throws SuiviObsmerException { + TopiaContext transaction = null; + // Carefull with results, the company may not be present in the map : + // only if there is no unfinished sampleRow or no contact done + Map<String, Double> results = new HashMap<String, Double>(); + try { + transaction = rootContext.beginTransaction(); + + ContactDAO dao = SuiviObsmerModelDAOHelper.getContactDAO(transaction); + + String contact = "C"; + TopiaQuery query = dao.createQuery(contact); + + String companyKey = contact + "." + Contact.OBSERVER + "." + WaoUser.COMPANY; + String companyName = companyKey + "." + Company.NAME; + + if (company != null) { + query.add(companyKey, company); + } + + String tideBegin = contact + "." + Contact.TIDE_BEGIN_DATE; + period.initDayOfMonthExtremities(); + query.add(tideBegin + " BETWEEN :fromDate AND :thruDate"). + addParam("fromDate", period.getFromDate()). + addParam("thruDate", period.getThruDate()); + + String dataInput = contact + "." + Contact.DATA_INPUT_DATE; + query.addNotNull(dataInput); + + // FIXME-FD20100212 Hack for H2 which not managed day for date diff + TopiaContextImplementor context = (TopiaContextImplementor)transaction; + String dialect = context.getHibernateConfiguration().getProperty("hibernate.dialect"); + + String avg = "AVG(day(" + dataInput + " - " + tideBegin + "))"; + if (dialect.contains("H2Dialect")) { + avg = "AVG(" + dataInput + " - " + tideBegin + ")"; + } + + query.setSelect(companyName, avg).addGroup(companyName); + + if (log.isTraceEnabled()) { + log.trace("Exec query : " + query); + } + + List<Object[]> res = query.execute(); + + for (Object[] row : res) { + String rowCompanyName = (String)row[0]; + Double rowAverage = (Double)row[1]; + if (log.isTraceEnabled()) { + log.trace("Company : " + rowCompanyName); + log.trace("Res : " + rowAverage.doubleValue()); + } + if (rowAverage < 0) { + rowAverage = 0.; + } + results.put(rowCompanyName, rowAverage); + } + + + } catch (Exception eee) { + String msgEnd = ""; + if (company != null) { + msgEnd = " pour la société " + company.getName(); + } + SuiviObsmerContext.serviceException(transaction, + "Impossible de récupérer l'indicateur de réactivité sur " + + "les dates de saisies dans Allegro" + msgEnd, eee); + } finally { + SuiviObsmerContext.closeTransaction(transaction); + } + return results; + } + } Modified: trunk/suiviobsmer-business/src/main/xmi/suiviobsmer.zargo =================================================================== (Binary files differ) Modified: trunk/suiviobsmer-business/src/test/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImplTest.java =================================================================== --- trunk/suiviobsmer-business/src/test/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImplTest.java 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-business/src/test/java/fr/ifremer/suiviobsmer/services/ServiceSynthesisImplTest.java 2010-02-12 00:58:46 UTC (rev 347) @@ -416,4 +416,96 @@ assertEquals(0, data.get(ContactState.BOAT_UNAVAILABLE).intValue()); } + /** + * Test of getBoardingBoats method, of class ServiceSynthesisImpl. + */ + @Test + public void testGetContactDataInputDateReactivity() throws Exception { + log.info("getContactDataInputDateReactivity"); + /** PREPARE DATA **/ + InputStream input = getClass().getResourceAsStream("/import/navires.csv"); + ServiceBoat serviceBoat = new ServiceBoatImpl(); + serviceBoat.importBoatCsv(input); + List<Boat> boats = serviceBoat.getBoatsByImmatriculations("174258"); + Boat boat = boats.get(0); + + List<Boat> boats2 = serviceBoat.getBoatsByImmatriculations("177474"); + Boat boat2 = boats2.get(0); + + TopiaContext transaction = SuiviObsmerContext.getTopiaRootContext().beginTransaction(); + + CompanyDAO companyDAO = SuiviObsmerModelDAOHelper.getCompanyDAO(transaction); + Company company = companyDAO.create(Company.NAME, "TARTANPION"); + Company company2 = companyDAO.create(Company.NAME, "BIS"); + + WaoUserDAO userDAO = SuiviObsmerModelDAOHelper.getWaoUserDAO(transaction); + WaoUser user = userDAO.create(WaoUser.FIRST_NAME,"Jean", WaoUser.LAST_NAME, "Michmuche", + WaoUser.COMPANY, company); + company.addWaoUser(user); + WaoUser user2 = userDAO.create(WaoUser.FIRST_NAME,"Bill", WaoUser.LAST_NAME, "Murray", + WaoUser.COMPANY, company2); + company2.addWaoUser(user2); + + transaction.commitTransaction(); + + input = getClass().getResourceAsStream("/import/zonesPeche.csv"); + ServiceReferential serviceReferential = new ServiceReferentialImpl(); + serviceReferential.importFishingZoneCsv(input); + + input = getClass().getResourceAsStream("/import/echantillonnage.csv"); + ServiceSampling serviceSampling = new ServiceSamplingImpl(); + serviceSampling.importSamplingPlanCsv(input); + + SampleRowDAO rowDAO = SuiviObsmerModelDAOHelper.getSampleRowDAO(transaction); + SampleRow row = rowDAO.findByCode("2010_0001"); + SampleRow row2 = rowDAO.findByCode("2009_0006"); + + transaction.closeContext(); + + + ServiceContact serviceContact = new ServiceContactImpl(); + // First contact : OK + Contact contact1 = new ContactImpl(); + contact1.setObserver(user); + Date begin = DateUtils.createDate(3, 3, 2009); + contact1.setTideBeginDate(begin); + Date inputDate = DateUtils.createDate(15, 4, 2009); + contact1.setDataInputDate(inputDate); + serviceContact.saveContact(contact1, false); + + Contact contact2 = new ContactImpl(); + contact2.setObserver(user); + begin = DateUtils.createDate(3, 3, 2009); + contact2.setTideBeginDate(begin); + inputDate = DateUtils.createDate(15, 3, 2009); + contact2.setDataInputDate(inputDate); + serviceContact.saveContact(contact2, false); + + Contact contact3 = new ContactImpl(); + contact3.setObserver(user2); + begin = DateUtils.createDate(3, 3, 2009); + contact3.setTideBeginDate(begin); + contact3.setDataInputDate(begin); + serviceContact.saveContact(contact3, false); + + /** EXEC METHOD **/ + + PeriodDates period = new PeriodDates(begin, begin); + + // result for company TARTANPION + Map<String, Double> results = + service.getContactDataInputDateReactivity(company, period); + + assertEquals(1, results.size()); + + // 12 days for contact1 + 43 days for contact2 / 2 = 27.5 days + assertEquals(28, results.get(company.getName()), 0.01); + + // result for company BIS using admin mode (no company filtered) + results = service.getContactDataInputDateReactivity(null, period); + + // 0 days for contact3 / 1 = O days + assertEquals(0, results.get(company2.getName()), 0.01); + } + } \ No newline at end of file Modified: trunk/suiviobsmer-ui/src/main/java/fr/ifremer/suiviobsmer/ui/pages/Synthesis.java =================================================================== --- trunk/suiviobsmer-ui/src/main/java/fr/ifremer/suiviobsmer/ui/pages/Synthesis.java 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-ui/src/main/java/fr/ifremer/suiviobsmer/ui/pages/Synthesis.java 2010-02-12 00:58:46 UTC (rev 347) @@ -126,6 +126,12 @@ return new SimpleDateFormat("dd/MM/yyyy"); } + public NumberFormat getNumberFormat() { + NumberFormat result = NumberFormat.getNumberInstance(); + result.setMaximumFractionDigits(1); + return result; + } + @Log Object onAction(String actionType, String actionValue) { // Delegator action (menu) @@ -397,7 +403,44 @@ return (double)getNbContactStates() / (double)contactStateStats.getTotal(); } -// void onSuccessFromFilterPeriodForContactStates() { -// } + /********************* INDICATOR : NONCOMPLIANCEBOARDING ******************/ + private Map<String, Double> allegroReactivity; + + @Persist + private PeriodDates periodForAllegroReactivity; + + @Property + private Map.Entry<String, Double> allegroReactivityEntry; + + public Map<String, Double> getAllegroReactivity() + throws SuiviObsmerException { + if (allegroReactivity == null) { + Company company = !user.getAdmin() ? user.getCompany() : null; + allegroReactivity = + serviceSynthesis.getContactDataInputDateReactivity(company, getPeriodForAllegroReactivity()); + } + return allegroReactivity; + } + + public PeriodDates getPeriodForAllegroReactivity() { + if (periodForAllegroReactivity == null) { + periodForAllegroReactivity = PeriodDates.createMonthsPeriodFromToday(-3); + } + return periodForAllegroReactivity; + } + + public Double getAllegroReactivityValue() throws SuiviObsmerException { + return getAllegroReactivity().get(user.getCompany().getName()); + } + + public String getAllegroReactivityStyle() throws SuiviObsmerException { + double value = user.getAdmin() ? + allegroReactivityEntry.getValue() : getAllegroReactivityValue(); + if (value >= 15.) { + return " warn"; + } + return ""; + } + } Modified: trunk/suiviobsmer-ui/src/main/resources/fr/ifremer/suiviobsmer/ui/pages/Synthesis.properties =================================================================== --- trunk/suiviobsmer-ui/src/main/resources/fr/ifremer/suiviobsmer/ui/pages/Synthesis.properties 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-ui/src/main/resources/fr/ifremer/suiviobsmer/ui/pages/Synthesis.properties 2010-02-12 00:58:46 UTC (rev 347) @@ -12,4 +12,7 @@ companyForBoarding-label: Soci\u00E9t\u00E9 periodBeginForContactStates-label: du -periodEndForContactStates-label: au \ No newline at end of file +periodEndForContactStates-label: au + +periodBeginForAllegroReactivity-label: du +periodEndForAllegroReactivity-label: au \ No newline at end of file Modified: trunk/suiviobsmer-ui/src/main/webapp/Synthesis.tml =================================================================== --- trunk/suiviobsmer-ui/src/main/webapp/Synthesis.tml 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-ui/src/main/webapp/Synthesis.tml 2010-02-12 00:58:46 UTC (rev 347) @@ -30,6 +30,12 @@ title="Indicateur sur les états des contacts" /> </a> </li> + <li> + <a t:type="actionlink" t:context="[actionSynthesisId,'IND_ALLEGRO_REACTIVITY']" t:zone="so-synthesis-main"> + <img src="${asset:context:}/img/synthesis-ind-allegro-reactivity.png" alt="Indicateur" + title="Indicateur de réactivité sur la saisie des données dans Allegro" /> + </a> + </li> </ul> </div> <div t:type="zone" t:id="delegator" class="fleft" t:update="show" id="so-synthesis-main"> @@ -226,4 +232,51 @@ </table> </div> </t:block> + <!-- IND3 : ALLEGRO_REACTIVITY --> + <t:block t:id="ind3"> + <div class="ind-table acenter" id="so-allegroreactivity"> + <h2>Réactivité de la saisie dans Allegro par rapport à la date de fin de la marée</h2> + <br /> + <p> + Ce résultat est une moyenne du nombre de jours entre la date de saisie dans Allegro et la date de fin de la marée des contacts. + </p> + <br /> + <p> + <form t:type="form" t:id="filterPeriodForAllegroReactivity"> + <label>Période : </label> + <t:label t:for="periodBeginForAllegroReactivity" /> + <input t:type="datefield" class="width70" t:id="periodBeginForAllegroReactivity" t:value="periodForAllegroReactivity.fromDate" t:format="MM/yyyy"/> + <t:label t:for="periodEndForAllegroReactivity" /> + <input t:type="datefield" class="width70" t:id="periodEndForAllegroReactivity" t:value="periodForAllegroReactivity.thruDate" t:format="MM/yyyy" /> + <input t:type="submit" class="ico search-32px" t:id="searchForAllegroReactivity" value="Search" + title="Calcul de la moyenne du nombre de jours entre la date de saisie dans Allegro et la date de fin de marée sur la période sélectionnée"/> + </form> + </p> + <t:if t:test="user.admin"> + <table class="t-data-grid"> + <thead> + <tr> + <th class="company">Société</th> + <th>Indicateur</th> + </tr> + </thead> + <tbody> + <tr t:type="loop" t:source="allegroReactivity.entrySet()" t:value="allegroReactivityEntry"> + <td class="company">${allegroReactivityEntry.key}</td> + <td class="number${allegroReactivityStyle}"> + <t:output t:value="allegroReactivityEntry.value" t:format="numberFormat" /> + </td> + </tr> + </tbody> + </table> + <p:else> + <div class="indicator"> + <p class="number${allegroReactivityStyle}"> + <t:output t:value="allegroReactivityValue" t:format="numberFormat" /> + </p> + </div> + </p:else> + </t:if> + </div> + </t:block> </t:layout> Modified: trunk/suiviobsmer-ui/src/main/webapp/css/synthesis.css =================================================================== --- trunk/suiviobsmer-ui/src/main/webapp/css/synthesis.css 2010-02-11 20:04:33 UTC (rev 346) +++ trunk/suiviobsmer-ui/src/main/webapp/css/synthesis.css 2010-02-12 00:58:46 UTC (rev 347) @@ -54,7 +54,7 @@ div#so-synthesis-menu { border-right: 2px solid #133852; padding-left: 15px; - height: 406px; + height: 478px; width: 10%; } @@ -63,7 +63,7 @@ } div#so-synthesis-menu ul li { - padding-bottom: 20px; + padding-bottom: 10px; } div.indicator { @@ -147,3 +147,6 @@ text-align: center; } +div#so-allegroreactivity td.warn { + color: red; +} Added: trunk/suiviobsmer-ui/src/main/webapp/img/synthesis-ind-allegro-reactivity.png =================================================================== (Binary files differ) Property changes on: trunk/suiviobsmer-ui/src/main/webapp/img/synthesis-ind-allegro-reactivity.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream