Author: fdesbois Date: 2010-04-19 19:59:47 +0000 (Mon, 19 Apr 2010) New Revision: 455 Log: Evo #2100 : - Migration done (new column + calcul for estimated values) - ContactStatus class to manage property change on Contact (contactState, tideBeginDate, validations) - Remove deprecated methods in SampleRow (calcul is done in ServiceContact) Added: trunk/wao-business/src/main/java/fr/ifremer/wao/bean/ContactStatus.java Modified: trunk/wao-business/src/main/java/fr/ifremer/wao/PostgresMigrationCallback.java trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleMonthImpl.java trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleRowImpl.java trunk/wao-business/src/main/java/fr/ifremer/wao/service/ServiceContactImpl.java trunk/wao-business/src/main/xmi/wao.zargo trunk/wao-business/src/test/java/fr/ifremer/wao/entity/SampleRowImplTest.java trunk/wao-business/src/test/java/fr/ifremer/wao/service/ServiceContactImplTest.java trunk/wao-ui/src/main/java/fr/ifremer/wao/ui/pages/Contacts.java Modified: trunk/wao-business/src/main/java/fr/ifremer/wao/PostgresMigrationCallback.java =================================================================== --- trunk/wao-business/src/main/java/fr/ifremer/wao/PostgresMigrationCallback.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/main/java/fr/ifremer/wao/PostgresMigrationCallback.java 2010-04-19 19:59:47 UTC (rev 455) @@ -85,8 +85,20 @@ @Override protected void createSampleMonthEstimatedTidesColumn_1_2b(List<String> queries) { queries.add("ALTER TABLE SampleMonth ADD estimatedTidesValue INTEGER;"); - // TODO : calculate estimatedTidesValue for all existing contacts + // Calculate estimatedTidesValue for all existing contacts // estimatedTidesValue = nbContacts with state BOARDING_DONE + // sampleRows must match + tideBeginDate must match with periodDate + queries.add("UPDATE SampleMonth S SET " + + "estimatedTidesValue = (" + + " SELECT COUNT(*) FROM Contact C" + + " WHERE C.sampleRow = S.sampleRow" + + " AND C.state = " + ContactState.BOARDING_DONE.ordinal() + + " AND date_part('month', C.tideBeginDate) = " + + "date_part('month', S.periodDate)" + + " AND date_part('year', C.tideBeginDate) = " + + "date_part('year', S.periodDate)" + + "), " + + "topiaVersion = S.topiaVersion + 1;"); } } Added: trunk/wao-business/src/main/java/fr/ifremer/wao/bean/ContactStatus.java =================================================================== --- trunk/wao-business/src/main/java/fr/ifremer/wao/bean/ContactStatus.java (rev 0) +++ trunk/wao-business/src/main/java/fr/ifremer/wao/bean/ContactStatus.java 2010-04-19 19:59:47 UTC (rev 455) @@ -0,0 +1,321 @@ + +package fr.ifremer.wao.bean; + +import fr.ifremer.wao.WaoDAOHelper; +import fr.ifremer.wao.entity.Contact; +import fr.ifremer.wao.entity.SampleMonth; +import fr.ifremer.wao.entity.SampleMonthDAO; +import fr.ifremer.wao.entity.SampleRow; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.apache.commons.lang.BooleanUtils; +import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.framework.TopiaQuery; +import org.nuiton.util.PeriodDates; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class is used to know status changed between an old contact and a new + * one (new change to apply). There is three different cases for constructor + * parameters : + * <ul> + * <li>CREATE : olContact is null and newContact is defined</li> + * <li>UPDATE : both oldContact and newContact are defined</li> + * <li>DELETE : oldContact is defined and newContact is null</li> + * </ul> + * Three fields of contact are considered to be changed for sampleMonth calcul + * on tides value : + * <ul> + * <li> + * STATE : check the change on {@link ContactState#BOARDING_DONE} state. + * Use {@link #isContactDoneChanged() } method to check the change. + * This change is important to manage estimated tides value on sampleMonth + * referenced by the contact retrieve with {@link #getSampleMonth(TopiaContext)} + * </li> + * <li> + * VALIDATION : check the change on validationCompany and validationProgram. + * Use {@link #isContactValidateChanged() } method to check the change. + * This change is important to manage real tides value on sampleMonth + * referenced by the contact retrieve with {@link #getSampleMonth(TopiaContext)} + * </li> + * <li> + * TIDE BEGIN DATE : check the change on tideBeginDate month. + * Use {@link #isTideBeginDateMonthChanged() } method to check the change. + * This change is important to manage both estimated and real tides value on + * the old sampleMonth referenced by the old contact retrieve with + * {@link #getOldSampleMonth(TopiaContext)} + * </ul> + * + * + * Created: 19 avr. 2010 + * + * @author fdesbois + */ +public class ContactStatus { + + private static final Logger logger = + LoggerFactory.getLogger(ContactStatus.class); + + protected Contact oldContact; + + protected Contact newContact; + + protected SampleRow sampleRow; + + protected SampleMonth oldSampleMonth; + + protected SampleMonth sampleMonth; + + public ContactStatus(Contact old, Contact contact) { + this.oldContact = old; + this.newContact = contact; + this.sampleRow = contact != null ? + newContact.getSampleRow() : oldContact.getSampleRow(); + } + + public boolean isOldContactValidate() { + return isContactValidate(Context.OLD); + } + + public boolean isNewContactValidate() { + return isContactValidate(Context.NEW); + } + + /** + * Return true if oldContact validate is not the same as newContact + * validate. + * + * @return true if contact validate has changed. + * @see #isContactValidate(Context) + */ + public boolean isContactValidateChanged() { + return isOldContactValidate() != isNewContactValidate(); + } + + public boolean isOldContactDone() { + return isContactDone(Context.OLD); + } + + public boolean isNewContactDone() { + return isContactDone(Context.NEW); + } + + /** + * Return true if oldContact state is not the same as newContact state. + * Check only for {@link ContactState#BOARDING_DONE} changed. + * + * @return true if contact state has changed. + * @see #isContactDone(Context) + */ + public boolean isContactDoneChanged() { + return isOldContactDone() != isNewContactDone(); + } + + /** + * Return true if tideBeginDate has changed its month between oldContact + * and newContact. The both oldContact and newContact dates must be not + * null. + * + * @return true if tideBeginDate status changed + */ + public boolean isTideBeginDateMonthChanged() { + if (oldContact == null || newContact == null) { + return false; + } + DateFormat dateFormat = new SimpleDateFormat("MM/yyyy"); + Date oldTideBeginDate = oldContact.getTideBeginDate(); + Date newTideBeginDate = newContact.getTideBeginDate(); + // Only if old not null and new not null + if (oldTideBeginDate != null && newTideBeginDate != null) { + String oldTideBeginStr = dateFormat.format(oldTideBeginDate); + String newTideBeginStr = dateFormat.format(newTideBeginDate); + return !oldTideBeginStr.equals(newTideBeginStr); + } + return false; + } + + public SampleRow getSampleRow() { + return sampleRow; + } + + /** + * Retrive the old SampleMonth referenced by the tideBeginDate of the + * old contact. + * + * @param transaction to retrieve the sampleMonth from database + * @return the sampleMonth found or throw NullSampleMonthException + * @throws TopiaException + * @throws NullSampleMonthException + */ + public SampleMonth getOldSampleMonth(TopiaContext transaction) + throws TopiaException, NullSampleMonthException { + if (oldSampleMonth == null) { + oldSampleMonth = getExistingSampleMonth(transaction, Context.OLD); + } + return oldSampleMonth; + } + + /** + * Retrive the SampleMonth referenced by the tideBeginDate of the + * new contact. + * + * @param transaction to retrieve the sampleMonth from database + * @return the sampleMonth found or throw NullSampleMonthException + * @throws TopiaException + * @throws NullSampleMonthException + */ + public SampleMonth getSampleMonth(TopiaContext transaction) + throws TopiaException, NullSampleMonthException { + if (sampleMonth == null) { + sampleMonth = getExistingSampleMonth(transaction, Context.NEW); + } + return sampleMonth; + } + + /** + * This exception is used to indicate that a problem is occured during + * retrieving sampleMonth corresponding to a contact. + * Used in {@link fr.ifremer.wao.service.ServiceContact} + */ + public static final class NullSampleMonthException extends Exception { + + private static final long serialVersionUID = 1L; + + public NullSampleMonthException(String message) { + super(message); + } + } + + protected enum Context { + OLD, NEW; + } + + /** + * Retrieve existing sampleMonth corresponding to the contact. The + * sampleMonth must match with contact sampleRow, also the tideBeginDate + * (day) of the contact must match the sampleMonth periodDate (month). + * + * @param transaction used to find the sampleMonth + * @param context OLD or NEW + * @return the sampleMonth found if exists, or NullSampleMonthException + * will be thrown + * @throws TopiaException + * @throws NullSampleMonthException if month was not found + */ + protected SampleMonth getExistingSampleMonth(TopiaContext transaction, + Context context) throws TopiaException, NullSampleMonthException { + + // Reference date for query + Date tideBeginDate = null; + + switch(context) { + case OLD: tideBeginDate = oldContact.getTideBeginDate(); break; + // newContact may be null in CREATE case, so we use the previous + // one + case NEW: tideBeginDate = newContact != null ? + newContact.getTideBeginDate() : oldContact.getTideBeginDate(); + } + + SampleMonthDAO monthDAO = WaoDAOHelper.getSampleMonthDAO(transaction); + TopiaQuery query = monthDAO.createQuery(); + + PeriodDates period = new PeriodDates(tideBeginDate, tideBeginDate); + period.initDayOfMonthExtremities(); + + // Bind sampleMonth.sampleRow with contact sampleRow + query.add(SampleMonth.SAMPLE_ROW, sampleRow). + add(SampleMonth.PERIOD_DATE + " BETWEEN :fromDate AND :thruDate"). + addParam("fromDate", period.getFromDate()). + addParam("thruDate", period.getThruDate()); + //add(SampleMonth.PERIOD_DATE, period); + SampleMonth result = monthDAO.findByQuery(query); + if (result == null) { + throw new NullSampleMonthException("Aucun mois correspondant pour" + + " la ligne du plan d'échantillonnage " + + sampleRow.getCode() + + " et la date de début de marée du contact " + + tideBeginDate); + } + return result; + } + + /** + * Return true if contact is validate depends on {@code context}. The + * oldContact validation will be tested for an {@link Context#OLD} context + * and the newContact will be tested for a {@link Context#NEW} context. + * The validation is tested as validationCompany must be TRUE and + * validationProgram must be not FALSE (otherwise TRUE or NULL). + * + * @param context to check the good contact + * @return true depends on validationCompany and validationProgram of + * the contact (oldContact or newContact depends on context in argument). + */ + protected boolean isContactValidate(Context context) { + Contact contact = context == Context.OLD ? oldContact : newContact; + + Boolean validationCompany = contact != null ? + contact.getValidationCompany() : null; + Boolean validationProgram = contact != null ? + contact.getValidationProgram() : null; + + if (logger.isTraceEnabled()) { + logger.trace(context + " validation company = " + validationCompany + + " _ validation program = " + validationProgram); + } + + boolean contactValidate = + BooleanUtils.isTrue(validationCompany) && + BooleanUtils.isNotFalse(validationProgram); + return contactValidate; + } + + /** + * Return true if contact state is {@link ContactState#BOARDING_DONE} + * depends on {@code context}. To check oldContact state, use + * {@link Context#OLD} and to check newContact state, use + * {@link Context#NEW}. A null contact will return false. + * + * @param context to check the good contact + * @return true if the contact state is {@link ContactState#BOARDING_DONE} + */ + protected boolean isContactDone(Context context) { + Contact contact = context == Context.OLD ? oldContact : newContact; + ContactState contactState = contact != null ? + contact.getContactState() : null; + + if (logger.isTraceEnabled()) { + logger.trace(context + " contact state = " + contactState); + } + boolean contactDone = ContactState.BOARDING_DONE.equals(contactState); + return contactDone; + } + + @Override + public String toString() { + DateFormat dateFormat = new SimpleDateFormat("MM/yyyy"); + String oldMonth = oldContact != null && + oldContact.getTideBeginDate() != null ? + dateFormat.format(oldContact.getTideBeginDate()) : ""; + + String newMonth = newContact != null && + newContact.getTideBeginDate() != null ? + dateFormat.format(newContact.getTideBeginDate()) : ""; + + StringBuilder builder = + new StringBuilder("\nContactStatus : VALIDATE :: "). + append("oldValidate = ").append(isOldContactValidate()). + append(" _ newValidate = ").append(isNewContactValidate()). + append("\nContactStatus : CONTACT_STATE :: "). + append("oldDone = ").append(isOldContactDone()). + append(" _ newDone = ").append(isNewContactDone()). + append("\nContactStatus : TIDE_BEGIN_DATE :: "). + append("oldMonth = ").append(oldMonth). + append(" _ newMonth = ").append(newMonth). + append(" _ changed = ").append(isTideBeginDateMonthChanged()); + + return builder.toString(); + } +} Property changes on: trunk/wao-business/src/main/java/fr/ifremer/wao/bean/ContactStatus.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL" Modified: trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleMonthImpl.java =================================================================== --- trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleMonthImpl.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleMonthImpl.java 2010-04-19 19:59:47 UTC (rev 455) @@ -59,40 +59,59 @@ * remove time with a negative nbDays. * If nbDays is negative and superior to the current value, * the real tides value will be set to 0. + * * @param nbDays to add or remove (if negative) - * @throws WaoException for saving problem - * @deprecated the realTideTime will be automatically update on contact - * change */ @Override - @Deprecated - public void addRealTideTime(int nbDays) throws WaoException { - TopiaContext transaction = null; - try { - transaction = WaoUtils.beginTransaction(); + public void addRealTideTime(int nbDays) { +// TopiaContext transaction = null; +// try { +// transaction = WaoUtils.beginTransaction(); +// +// SampleMonthDAO dao = WaoDAOHelper.getSampleMonthDAO(transaction); +// SampleMonth month = dao.findByTopiaId(getTopiaId()); +// int result = month.getRealTidesValue() + nbDays; +// if (result < 0) { +// result = 0; +// } +// +// month.setRealTidesValue(result); +// if (log.isDebugEnabled()) { +// log.debug("Change realTideTime from " + +// month.getRealTidesValue() + " to " + result); +// } +// +// transaction.commitTransaction(); +// //transaction.closeContext(); +// } catch (Exception eee) { +// WaoUtils.treateError(transaction, eee, +// I18n.n_("wao.error.sampleMonth.addRealTideTime"), +// formatMonth(), getSampleRow().getCode()); +// } finally { +// WaoUtils.closeTransaction(transaction); +// } + int result = getRealTidesValue() + nbDays; + if (result < 0) { + result = 0; + } + if (log.isDebugEnabled()) { + log.debug("Change realTides : " + getRealTidesValue() + + " -> " + result + " _ date = " + periodDate); + } + setRealTidesValue(result); + } - SampleMonthDAO dao = WaoDAOHelper.getSampleMonthDAO(transaction); - SampleMonth month = dao.findByTopiaId(getTopiaId()); - int result = month.getRealTidesValue() + nbDays; - if (result < 0) { - result = 0; - } - - month.setRealTidesValue(result); - if (log.isDebugEnabled()) { - log.debug("Change realTideTime from " + - month.getRealTidesValue() + " to " + result); - } - - transaction.commitTransaction(); - //transaction.closeContext(); - } catch (Exception eee) { - WaoUtils.treateError(transaction, eee, - I18n.n_("wao.error.sampleMonth.addRealTideTime"), - formatMonth(), getSampleRow().getCode()); - } finally { - WaoUtils.closeTransaction(transaction); + @Override + public void addEstimatedTideTime(int nbDays) { + int result = getEstimatedTidesValue() + nbDays; + if (result < 0) { + result = 0; } + if (log.isDebugEnabled()) { + log.debug("Change estimatedTides : " + getEstimatedTidesValue() + + " -> " + result + " _ date = " + periodDate); + } + setEstimatedTidesValue(result); } @Override Modified: trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleRowImpl.java =================================================================== --- trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleRowImpl.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/main/java/fr/ifremer/wao/entity/SampleRowImpl.java 2010-04-19 19:59:47 UTC (rev 455) @@ -159,18 +159,6 @@ } /** - * Return the first fishingZone of the list linked with the SampleRow. - * @return a FishingZone or null if there is no fishingZone linked with the SampleRow - */ -// @Override -// public FishingZone getFirstFishingZone() { -// if (getFishingZone().size() > 0) { -// return getFishingZone().get(0); -// } -// return null; -// } - - /** * Get the facade of the sampleRow. The row has normally only one facade in the FishingZone list. * * @return the facade name of the row @@ -288,42 +276,6 @@ } @Override - @Deprecated - public boolean addRealTideTime(Contact contact) throws WaoException { - if (contact.getTideEndDate() == null || - contact.getTideBeginDate() == null) { - return false; - } - //int nbDays = contact.getTideNbDays(); //getDifferenceDays(contact); - SampleMonth month = getSampleMonth(contact.getTideBeginDate()); - if (month == null) { - return false; - } - if (log.isTraceEnabled()) { - log.trace("Add 1 tide for " + month.formatMonth() + - " [" + this.getCode() + "]"); - } - month.addRealTideTime(1); - return true; - } - - @Override - @Deprecated - public void removeRealTideTime(Contact contact) throws WaoException { - if (contact.getTideEndDate() == null || - contact.getTideBeginDate() == null) { - return; - } - //int nbDays = contact.getTideNbDays(); //getDifferenceDays(contact); - SampleMonth month = getSampleMonth(contact.getTideBeginDate()); - if (log.isTraceEnabled()) { - log.trace("Remove 1 tide for " + month.formatMonth() + - " [" + this.getCode() + "]"); - } - month.addRealTideTime(-1); - } - - @Override public void setPeriod(PeriodDates period) { period.initDayOfMonthExtremities(); setPeriodBegin(period.getFromDate()); Modified: trunk/wao-business/src/main/java/fr/ifremer/wao/service/ServiceContactImpl.java =================================================================== --- trunk/wao-business/src/main/java/fr/ifremer/wao/service/ServiceContactImpl.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/main/java/fr/ifremer/wao/service/ServiceContactImpl.java 2010-04-19 19:59:47 UTC (rev 455) @@ -41,7 +41,6 @@ import java.util.Map; import com.csvreader.CsvReader; import com.csvreader.CsvWriter; -import org.apache.commons.lang.BooleanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.nuiton.topia.TopiaContext; @@ -49,6 +48,8 @@ import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.framework.TopiaQuery; import fr.ifremer.wao.*; +import fr.ifremer.wao.bean.ContactStatus; +import fr.ifremer.wao.bean.ContactStatus.NullSampleMonthException; import fr.ifremer.wao.bean.ContactFilter; import fr.ifremer.wao.bean.ContactState; import fr.ifremer.wao.bean.ImportResults; @@ -56,8 +57,6 @@ import fr.ifremer.wao.entity.*; import fr.ifremer.wao.io.*; import fr.ifremer.wao.io.WaoCsvHeader.*; -import org.apache.commons.lang.StringUtils; -import org.nuiton.util.PeriodDates; import org.nuiton.util.beans.BinderBuilder; import org.nuiton.util.beans.BinderProvider; @@ -184,6 +183,11 @@ //context.prepareTopiaId(Contact.class, contact); if (delete) { + // Need to decrement estimated value if contactFound has + // BOARDING_DONE state and may be real value (normally not allowed) + updateSampleMonthTidesValue(transaction, contactFound, null, true); + + // Execute delete dao.delete(contactFound); } else { createOrUpdateContact(dao, contact, contactFound, true); @@ -578,11 +582,16 @@ * estimated is update when contact state {@link ContactState#BOARDING_DONE} * is changed. The real is update when contact validationCompany is changed. * The {@code calculateReal} flag determines if the real tides has to be - * calculated or not. + * calculated or not. Three cases : + * <ul> + * <li>CREATE : {@code oldContact} = null and {@code contact} is defined</li> + * <li>UPDATE : both {@code oldContact} and {@code contact} are defined</li> + * <li>DELETE : {@code oldContact} is defined and {@code contact} = null</li> + * </ul> * * @param transaction used to update the SampleMonth * @param oldContact old state of the contact - * @param contact changed + * @param contact changed can be null for delete case * @param calculateReal to calculate real tides value * @throws TopiaException * @throws NullSampleMonthException if SampleMonth can't be found @@ -592,164 +601,75 @@ Contact contact, boolean calculateReal) throws TopiaException, NullSampleMonthException { - SampleMonthDAO monthDAO = WaoDAOHelper.getSampleMonthDAO(transaction); + if (oldContact == null && contact == null) { + throw new IllegalArgumentException("Both contact and oldContact" + + " can't be null to update sampleMonth tides value"); + } + // Instantiate contact status which provide status on oldContact and + // contact changes + ContactStatus status = new ContactStatus(oldContact, contact); + if (log.isDebugEnabled()) { - log.debug("oldState = " + (oldContact != null ? - oldContact.getContactState() : "null") + - " _ newState = " + contact.getContactState()); + log.debug(status.toString()); } - boolean oldContactDone = oldContact != null && - oldContact.getContactState().equals(ContactState.BOARDING_DONE); + // Month of TideBeginDate has changed, must decrement values on + // old sampleMonth + boolean tideBeginDateChanged = false; + if (oldContact != null && contact != null && + status.isTideBeginDateMonthChanged()) { - boolean newContactDone = contact.getContactState(). - equals(ContactState.BOARDING_DONE); + tideBeginDateChanged = status.isTideBeginDateMonthChanged(); - boolean contactStateChanged = oldContact == null || - !contact.getContactState().equals(oldContact.getContactState()); + // Retrieve oldMonth from status + // Must exists otherwise the oldContact couln't have been saved + SampleMonth oldMonth = status.getOldSampleMonth(transaction); - SampleMonth sampleMonth = null; - // Estimated tides calcul - if ((oldContactDone || newContactDone) && contactStateChanged) { - if (log.isDebugEnabled()) { - log.debug("Calculate estimated tides value for date : " + - contact.getTideBeginDate()); + // Apply changes on oldMonth + if (status.isOldContactValidate()) { + // decrement real tides + oldMonth.addRealTideTime(-1); } - - sampleMonth = getExistingSampleMonthForContact(monthDAO, contact); - - if (oldContactDone) { - // dec estimatedTides - int estimated = sampleMonth.getEstimatedTidesValue(); - if (estimated > 0) { - sampleMonth.setEstimatedTidesValue(estimated - 1); - } - if (log.isDebugEnabled()) { - log.debug("Decrement : " + estimated + " -> " + - sampleMonth.getEstimatedTidesValue()); - } - } else if (newContactDone) { - // inc estimatedTides - int estimated = sampleMonth.getEstimatedTidesValue(); - sampleMonth.setEstimatedTidesValue(estimated + 1); - if (log.isDebugEnabled()) { - log.debug("Increment : " + estimated + " -> " + - sampleMonth.getEstimatedTidesValue()); - } + if (status.isOldContactDone()) { + // decrement estimated tides + oldMonth.addEstimatedTideTime(-1); } } - // Real tides calcul (only if needed) - if (calculateReal) { - Boolean oldValidationCompany = oldContact != null ? - oldContact.getValidationCompany() : null; - Boolean newValidationCompany = contact.getValidationCompany(); + // Validation of contact has changed in status, modify realTides + if (calculateReal && + (status.isContactValidateChanged() || tideBeginDateChanged)) { - boolean oldContactValidate = - BooleanUtils.isTrue(oldValidationCompany); - boolean newContactValidate = - BooleanUtils.isTrue(newValidationCompany); + SampleMonth sampleMonth = status.getSampleMonth(transaction); - boolean contactValidationChanged = oldContact == null || - (oldValidationCompany != null && - !oldValidationCompany.equals(newValidationCompany)); - - if (log.isDebugEnabled()) { - log.debug("oldValidation = " + oldContactValidate + - " _ newValidation = " + newContactValidate); + if (status.isNewContactValidate()) { + // increment real tides + sampleMonth.addRealTideTime(1); + // never decrement if tideBeginDate has changed + } else if (status.isOldContactValidate() && !tideBeginDateChanged) { + // decrement real tides + sampleMonth.addRealTideTime(-1); } + } - if ((oldContactValidate || newContactValidate) && - contactValidationChanged) { - if (log.isDebugEnabled()) { - log.debug("Calculate real tides value for date : " + - contact.getTideBeginDate()); - } + // ContactState of contact has changed in status, modify estimatedTides + if (status.isContactDoneChanged() || tideBeginDateChanged) { - // Do not retrieve the sampleMonth if it is already defined from - // previous calcul on estimatedTidesValue - if (sampleMonth == null) { - sampleMonth = getExistingSampleMonthForContact( - monthDAO, contact); - } + SampleMonth sampleMonth = status.getSampleMonth(transaction); - if (oldContactValidate) { - // dec realTides - int real = sampleMonth.getRealTidesValue(); - if (real > 0) { - sampleMonth.setRealTidesValue(real - 1); - } - if (log.isDebugEnabled()) { - log.debug("Decrement : " + real + " -> " + - sampleMonth.getRealTidesValue()); - } - } else if (newContactValidate) { - // inc realTides - int real = sampleMonth.getRealTidesValue(); - sampleMonth.setRealTidesValue(real + 1); - if (log.isDebugEnabled()) { - log.debug("Increment : " + real + " -> " + - sampleMonth.getRealTidesValue()); - } - } + if (status.isNewContactDone()) { + // increment estimated tides + sampleMonth.addEstimatedTideTime(1); + // never decrement if tideBeginDate has changed + } else if (status.isOldContactDone() && !tideBeginDateChanged) { + // decrement estimated tides + sampleMonth.addEstimatedTideTime(-1); } } } /** - * This exception is used to indicate that a problem is occured during - * retrieving sampleMonth corresponding to a contact. - * @see #updateSampleMonthTidesValue(TopiaContext, Contact, Contact, boolean) - */ - public static final class NullSampleMonthException extends Exception { - - private static final long serialVersionUID = 1L; - - public NullSampleMonthException(String message) { - super(message); - } - } - - /** - * Retrieve existing sampleMonth corresponding to the {@code contact}. The - * sampleMonth must match with contact sampleRow, also the tideBeginDate - * (day) of the contact must match the sampleMonth periodDate (month). - * - * @param monthDAO used to find the sampleMonth - * @param contact reference - * @return the sampleMonth found if exists, or NullSampleMonthException - * will be thrown - * @throws TopiaException - * @throws NullSampleMonthException if month was not found - */ - protected SampleMonth getExistingSampleMonthForContact( - SampleMonthDAO monthDAO, Contact contact) - throws TopiaException, NullSampleMonthException { - TopiaQuery query = monthDAO.createQuery(); - - PeriodDates period = new PeriodDates( - contact.getTideBeginDate(), contact.getTideBeginDate()); - period.initDayOfMonthExtremities(); - - // Bind sampleMonth.sampleRow with contact sampleRow - query.add(SampleMonth.SAMPLE_ROW, contact.getSampleRow()). - add(SampleMonth.PERIOD_DATE + " BETWEEN :fromDate AND :thruDate"). - addParam("fromDate", period.getFromDate()). - addParam("thruDate", period.getThruDate()); - //add(SampleMonth.PERIOD_DATE, period); - SampleMonth result = monthDAO.findByQuery(query); - if (result == null) { - throw new NullSampleMonthException("Aucun mois correspondant pour" + - " la ligne du plan d'échantillonnage " + - contact.getSampleRow().getCode() + - " et la date de début de marée du contact " + - contact.getTideBeginDate()); - } - return result; - } - - /** * Update the elligible boat depends on contact creation. The * {@code contact} reference can only be created for a sampleRow and a * boat if both are linked with an elligibleBoat. So this method is Modified: trunk/wao-business/src/main/xmi/wao.zargo =================================================================== (Binary files differ) Modified: trunk/wao-business/src/test/java/fr/ifremer/wao/entity/SampleRowImplTest.java =================================================================== --- trunk/wao-business/src/test/java/fr/ifremer/wao/entity/SampleRowImplTest.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/test/java/fr/ifremer/wao/entity/SampleRowImplTest.java 2010-04-19 19:59:47 UTC (rev 455) @@ -114,67 +114,67 @@ return resultRow; } - @Test - public void testAddRealTideTime() throws Exception { - log.info("addRealTideTime"); - - /** PREPARE DATA **/ - SampleRow row = prepareData(); - - Contact contact = new ContactImpl(); - Date beginDate = DateUtils.createDate(12, 4, 2009); - Date endDate = DateUtils.createDate(15, 4, 2009); - contact.setTideBeginDate(beginDate); - contact.setTideEndDate(endDate); - - /** EXEC METHOD **/ - row.addRealTideTime(contact); - SampleMonth result = getRowFromContext().getSampleMonth(beginDate); - assertEquals(1, result.getRealTidesValue()); - +// @Test +// public void testAddRealTideTime() throws Exception { +// log.info("addRealTideTime"); +// +// /** PREPARE DATA **/ +// SampleRow row = prepareData(); +// +// Contact contact = new ContactImpl(); +// Date beginDate = DateUtils.createDate(12, 4, 2009); +// Date endDate = DateUtils.createDate(15, 4, 2009); +// contact.setTideBeginDate(beginDate); +// contact.setTideEndDate(endDate); +// +// /** EXEC METHOD **/ +// row.addRealTideTime(contact); +// SampleMonth result = getRowFromContext().getSampleMonth(beginDate); +// assertEquals(1, result.getRealTidesValue()); +// +//// // Reinit result for next test +//// result.addRealTideTime(-1); +//// // Test with a more than one day interval dates from contact +//// endDate = DateUtils.createDate(18, 4, 2009); +//// contact.setTideEndDate(endDate); +//// +//// getRowFromContext().addRealTideTime(contact); +//// result = getRowFromContext().getSampleMonth(beginDate); +//// assertEquals(1, result.getRealTidesValue()); +// } +// +// @Test +// public void testRemoveRealTideTime() throws Exception { +// log.info("addRealTideTime"); +// +// /** PREPARE DATA **/ +// SampleRow row = prepareData(); +// +// Contact contact = new ContactImpl(); +// Date beginDate = DateUtils.createDate(12, 4, 2009); +// Date endDate = DateUtils.createDate(12, 4, 2009); +// contact.setTideBeginDate(beginDate); +// contact.setTideEndDate(endDate); +// +// /** EXEC METHOD **/ +// row.removeRealTideTime(contact); +// SampleMonth result = getRowFromContext().getSampleMonth(beginDate); +// // result stay at 0, can't remove 1 tide from 0 +// assertEquals(0, result.getRealTidesValue()); +// // // Reinit result for next test -// result.addRealTideTime(-1); -// // Test with a more than one day interval dates from contact +// result.addRealTideTime(12); +// +// // Test with a more than one day interval dates from contact : only one tide to remove // endDate = DateUtils.createDate(18, 4, 2009); // contact.setTideEndDate(endDate); // -// getRowFromContext().addRealTideTime(contact); +// getRowFromContext().removeRealTideTime(contact); // result = getRowFromContext().getSampleMonth(beginDate); -// assertEquals(1, result.getRealTidesValue()); - } +// assertEquals(11, result.getRealTidesValue()); +// } @Test - public void testRemoveRealTideTime() throws Exception { - log.info("addRealTideTime"); - - /** PREPARE DATA **/ - SampleRow row = prepareData(); - - Contact contact = new ContactImpl(); - Date beginDate = DateUtils.createDate(12, 4, 2009); - Date endDate = DateUtils.createDate(12, 4, 2009); - contact.setTideBeginDate(beginDate); - contact.setTideEndDate(endDate); - - /** EXEC METHOD **/ - row.removeRealTideTime(contact); - SampleMonth result = getRowFromContext().getSampleMonth(beginDate); - // result stay at 0, can't remove 1 tide from 0 - assertEquals(0, result.getRealTidesValue()); - - // Reinit result for next test - result.addRealTideTime(12); - - // Test with a more than one day interval dates from contact : only one tide to remove - endDate = DateUtils.createDate(18, 4, 2009); - contact.setTideEndDate(endDate); - - getRowFromContext().removeRealTideTime(contact); - result = getRowFromContext().getSampleMonth(beginDate); - assertEquals(11, result.getRealTidesValue()); - } - - @Test public void testIsFinished() throws Exception { log.info("isFinished()"); Modified: trunk/wao-business/src/test/java/fr/ifremer/wao/service/ServiceContactImplTest.java =================================================================== --- trunk/wao-business/src/test/java/fr/ifremer/wao/service/ServiceContactImplTest.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-business/src/test/java/fr/ifremer/wao/service/ServiceContactImplTest.java 2010-04-19 19:59:47 UTC (rev 455) @@ -25,7 +25,7 @@ import fr.ifremer.wao.io.WaoCsvHeader.BOAT; import fr.ifremer.wao.io.WaoCsvHeader.CONTACT; import fr.ifremer.wao.io.WaoCsvHeader.SAMPLING; -import fr.ifremer.wao.service.ServiceContactImpl.NullSampleMonthException; +import fr.ifremer.wao.bean.ContactStatus.NullSampleMonthException; import java.io.IOException; import java.io.InputStream; import java.text.ParseException; @@ -39,6 +39,7 @@ import org.mockito.MockitoAnnotations; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaException; +import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.util.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -137,6 +138,9 @@ Date monthDate = DateUtils.createDate(1, 3, 2010); sampleMonth = monthDAO.create(SampleMonth.SAMPLE_ROW, sampleRow, SampleMonth.PERIOD_DATE, monthDate); + monthDate = DateUtils.createDate(1, 4, 2010); + monthDAO.create(SampleMonth.SAMPLE_ROW, sampleRow, + SampleMonth.PERIOD_DATE, monthDate); Date contactDate = DateUtils.createDate(18, 3, 2010); when(contact.getTideBeginDate()).thenReturn(contactDate); @@ -159,44 +163,46 @@ throws TopiaException, NullSampleMonthException { logger.info("testGetExistingSampleMonthForContact"); - /** PREPARE DATA **/ - prepareData(false, false); - - /** EXEC METHOD **/ - logger.info("test 1 : SampleMonth exists for contact"); - TopiaContext transaction = manager.getContext().beginTransaction(); - try { - SampleMonthDAO monthDAO = - WaoDAOHelper.getSampleMonthDAO(transaction); - - // Contact is valid for the sampleMonth - - SampleMonth result = - service.getExistingSampleMonthForContact(monthDAO, contact); - - assertEquals(sampleMonth, result); - - } finally { - transaction.closeContext(); - } - - logger.info("test 2 : contact tideBeginDate doesn't match with any" + - " SampleMonth"); - transaction = manager.getContext().beginTransaction(); - try { - SampleMonthDAO monthDAO = - WaoDAOHelper.getSampleMonthDAO(transaction); - - Date contactDate = DateUtils.createDate(18, 10, 2010); - when(contact.getTideBeginDate()).thenReturn(contactDate); - - service.getExistingSampleMonthForContact(monthDAO, contact); - } catch (Exception eee) { - logger.error("Error : " + eee.getMessage()); - assertEquals(NullSampleMonthException.class, eee.getClass()); - } finally { - transaction.closeContext(); - } +// /** PREPARE DATA **/ +// prepareData(false, false); +// +// /** EXEC METHOD **/ +// logger.info("test 1 : SampleMonth exists for contact"); +// TopiaContext transaction = manager.getContext().beginTransaction(); +// try { +// SampleMonthDAO monthDAO = +// WaoDAOHelper.getSampleMonthDAO(transaction); +// +// // Contact is valid for the sampleMonth +// +// SampleMonth result = +// service.getExistingSampleMonthForContact(monthDAO, +// contact.getSampleRow(), contact.getTideBeginDate()); +// +// assertEquals(sampleMonth, result); +// +// } finally { +// transaction.closeContext(); +// } +// +// logger.info("test 2 : contact tideBeginDate doesn't match with any" + +// " SampleMonth"); +// transaction = manager.getContext().beginTransaction(); +// try { +// SampleMonthDAO monthDAO = +// WaoDAOHelper.getSampleMonthDAO(transaction); +// +// Date contactDate = DateUtils.createDate(18, 10, 2010); +// when(contact.getTideBeginDate()).thenReturn(contactDate); +// +// service.getExistingSampleMonthForContact(monthDAO, +// contact.getSampleRow(), contact.getTideBeginDate()); +// } catch (Exception eee) { +// logger.error("Error : " + eee.getMessage()); +// assertEquals(NullSampleMonthException.class, eee.getClass()); +// } finally { +// transaction.closeContext(); +// } } @Test @@ -206,9 +212,12 @@ /** PREPARE DATA **/ prepareData(false, false); - Date tideBeginDate = contact.getTideBeginDate(); + Date tideBeginDate = new Date(contact.getTideBeginDate().getTime()); when(contactReference.getTideBeginDate()).thenReturn(tideBeginDate); when(contactReference.getSampleRow()).thenReturn(sampleRow); + // WARN : by default mockito doesn't initialize Boolean type with null + when(contactReference.getValidationProgram()).thenReturn(null); + when(contact.getValidationProgram()).thenReturn(null); /** EXEC METHOD **/ logger.info("test 1 : ContactState changed from null to BOARDING_DONE" + @@ -233,12 +242,12 @@ "BOAT_REFUSED -> decrement estimated tides value"); transaction = manager.getContext().beginTransaction(); try { - when(contact.getContactState()). - thenReturn(ContactState.BOAT_REFUSED); - when(contactReference.getContactState()). thenReturn(ContactState.BOARDING_DONE); + when(contact.getContactState()). + thenReturn(ContactState.BOAT_REFUSED); + service.updateSampleMonthTidesValue(transaction, contactReference, contact, false); @@ -250,6 +259,7 @@ logger.info("test 2 : verification sampleMonth estimated tides = 0"); checkTidesValue(0, false); + // Reset contactState to BOARDING_DONE for next test when(contact.getContactState()). thenReturn(ContactState.BOARDING_DONE); @@ -257,10 +267,10 @@ "FALSE -> do nothing"); transaction = manager.getContext().beginTransaction(); try { + when(contactReference.getValidationCompany()).thenReturn(null); + when(contact.getValidationCompany()).thenReturn(Boolean.FALSE); - when(contactReference.getValidationCompany()).thenReturn(null); - service.updateSampleMonthTidesValue(transaction, contactReference, contact, true); @@ -276,11 +286,11 @@ "TRUE -> increment real tides value"); transaction = manager.getContext().beginTransaction(); try { - when(contact.getValidationCompany()).thenReturn(Boolean.TRUE); - when(contactReference.getValidationCompany()). thenReturn(Boolean.FALSE); + when(contact.getValidationCompany()).thenReturn(Boolean.TRUE); + service.updateSampleMonthTidesValue(transaction, contactReference, contact, true); @@ -291,6 +301,113 @@ logger.info("test 4 : verification sampleMonth real tides = 1"); checkTidesValue(1, true); + + // ContactReference after saving contact will normally have this value : + when(contactReference.getValidationCompany()).thenReturn(Boolean.TRUE); + + logger.info("test 5 : CompanyValidation doesn't changed but " + + "ProgramValidation is set to FALSE -> decrement real tides"); + transaction = manager.getContext().beginTransaction(); + try { + when(contact.getValidationProgram()).thenReturn(Boolean.FALSE); + + service.updateSampleMonthTidesValue(transaction, contactReference, + contact, true); + + transaction.commitTransaction(); + } finally { + transaction.closeContext(); + } + + logger.info("test 5 : verification sampleMonth real tides = 0"); + checkTidesValue(0, true); + + logger.info("test 6 : Prepare data for delete case"); + // PREPARE DATA : update estimated to 1 and real to 1 + transaction = manager.getContext().beginTransaction(); + try { + // Will update estimatedTides up to 1 + // contact has already BOARDING_DONE + when(contactReference.getContactState()). + thenReturn(ContactState.BOARDING_EXPECTED); + + // Will update realTides up to 1 + // contact has already validationCompany = TRUE + when(contactReference.getValidationCompany()).thenReturn(null); + when(contact.getValidationProgram()).thenReturn(Boolean.TRUE); + + service.updateSampleMonthTidesValue(transaction, contactReference, + contact, true); + + transaction.commitTransaction(); + } finally { + transaction.closeContext(); + } + + // ContactReference after saving contact will normally have this values + when(contactReference.getValidationProgram()).thenReturn(Boolean.TRUE); + when(contactReference.getValidationCompany()).thenReturn(Boolean.TRUE); + + logger.info("test 6 : Delete contact (new contact is null) -> " + + "decrement realTides, estimatedTides doesn't change"); + transaction = manager.getContext().beginTransaction(); + try { + // ContactReference as a state != BOARDING_DONE, don't decrement + // estimatedTides + service.updateSampleMonthTidesValue(transaction, contactReference, + null, true); + + transaction.commitTransaction(); + } finally { + transaction.closeContext(); + } + + logger.info("test 6 : verification sampleMonth real tides = 0" + + "and estimated tides = 1"); + checkTidesValue(0, true); + checkTidesValue(1, false); + + logger.info("test 7 : SampleMonth will change from 03/2010 to 04/2010" + + " -> decrement estimated tides from oldMonth"); + transaction = manager.getContext().beginTransaction(); + try { + // contactReference BOARDING_DONE, validations true/true + // contact BOARDING_DONE, validations true/true + when(contactReference.getContactState()). + thenReturn(ContactState.BOARDING_DONE); + when(contact.getContactState()). + thenReturn(ContactState.BOARDING_DONE); + when(contact.getTideBeginDate()). + thenReturn(DateUtils.createDate(3, 4, 2010)); + + service.updateSampleMonthTidesValue(transaction, contactReference, + contact, true); + + transaction.commitTransaction(); + } finally { + transaction.closeContext(); + } + + logger.info("test 7 : verification old sampleMonth estimated tides = 0"); + checkTidesValue(0, false); + + logger.info("test 7 : verification new sampleMonth estimated " + + "tides = 1 and real tides = 1"); + transaction = manager.getContext().beginTransaction(); + try { + SampleMonthDAO dao = WaoDAOHelper.getSampleMonthDAO(transaction); + + TopiaQuery query = dao.createQuery(); + query.add(SampleMonth.PERIOD_DATE, DateUtils.createDate(1, 4, 2010)); + + SampleMonth month = dao.findByQuery(query); + + assertEquals(1, month.getEstimatedTidesValue()); + assertEquals(1, month.getRealTidesValue()); + + } finally { + transaction.closeContext(); + } } protected void checkTidesValue(int expected, boolean real) Modified: trunk/wao-ui/src/main/java/fr/ifremer/wao/ui/pages/Contacts.java =================================================================== --- trunk/wao-ui/src/main/java/fr/ifremer/wao/ui/pages/Contacts.java 2010-04-19 13:15:21 UTC (rev 454) +++ trunk/wao-ui/src/main/java/fr/ifremer/wao/ui/pages/Contacts.java 2010-04-19 19:59:47 UTC (rev 455) @@ -480,7 +480,7 @@ contactEdited.setValidationProgram(Boolean.TRUE); } else { // For company accepted, addRealTideTime - contactEdited.getSampleRow().addRealTideTime(contactEdited); +// contactEdited.getSampleRow().addRealTideTime(contactEdited); contactEdited.setValidationCompany(Boolean.TRUE); } } @@ -492,7 +492,7 @@ contactEdited = getContacts().get(contactId); if (user.isAdmin()) { // For program refused, removeRealTideTime - contactEdited.getSampleRow().removeRealTideTime(contactEdited); +// contactEdited.getSampleRow().removeRealTideTime(contactEdited); contactEdited.setValidationProgram(Boolean.FALSE); } else { contactEdited.setValidationCompany(Boolean.FALSE); @@ -506,16 +506,16 @@ contactEdited = getContacts().get(contactId); if (user.isAdmin()) { // For program unvalidate from previous refused validation, addRealTideTime - if (BooleanUtils.isFalse(contactEdited.getValidationProgram())) { - contactEdited.getSampleRow().addRealTideTime(contactEdited); - } +// if (BooleanUtils.isFalse(contactEdited.getValidationProgram())) { +// contactEdited.getSampleRow().addRealTideTime(contactEdited); +// } contactEdited.setValidationProgram(null); } else { // For company unvalidate from previous accepted validation, // removeRealTideTime - if (BooleanUtils.isTrue(contactEdited.getValidationCompany())) { - contactEdited.getSampleRow().removeRealTideTime(contactEdited); - } +// if (BooleanUtils.isTrue(contactEdited.getValidationCompany())) { +// contactEdited.getSampleRow().removeRealTideTime(contactEdited); +// } contactEdited.setValidationCompany(null); } }