Author: bleny Date: 2013-03-22 14:19:12 +0100 (Fri, 22 Mar 2013) New Revision: 32 Url: http://forge.codelutin.com/projects/franciaflex-magalie/repository/revisions... Log: refs #2162: consider already removed items Added: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/StorageMovementDao.java trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStorageMovementDao.java trunk/magalie-services/src/test/java/com/franciaflex/magalie/FakeMagalieServiceContext.java Modified: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/Dao.java trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/AbstractJpaDao.java trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStoredArticleDao.java trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/ArticleStorageService.java trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/DefaultMagalieServiceContext.java trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/MagalieServiceContext.java trunk/magalie-services/src/test/java/com/franciaflex/magalie/AbstractMagalieServiceTest.java trunk/magalie-services/src/test/java/com/franciaflex/magalie/JpaEntityManagerRule.java trunk/magalie-services/src/test/java/com/franciaflex/magalie/services/ArticleStorageServiceTest.java Modified: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/Dao.java =================================================================== --- trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/Dao.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/Dao.java 2013-03-22 13:19:12 UTC (rev 32) @@ -14,5 +14,4 @@ boolean contains(E entity); - void commit(); } Added: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/StorageMovementDao.java =================================================================== --- trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/StorageMovementDao.java (rev 0) +++ trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/StorageMovementDao.java 2013-03-22 13:19:12 UTC (rev 32) @@ -0,0 +1,17 @@ +package com.franciaflex.magalie.dao; + +import com.franciaflex.magalie.entity.Article; +import com.franciaflex.magalie.entity.StorageMovement; + +import java.util.List; + +/** + * @author bleny + */ +public interface StorageMovementDao extends Dao<StorageMovement> { + + List<StorageMovement> findAllByArticle(Article article); + + void persistAll(Iterable<StorageMovement> storageMovements); + +} Modified: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/AbstractJpaDao.java =================================================================== --- trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/AbstractJpaDao.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/AbstractJpaDao.java 2013-03-22 13:19:12 UTC (rev 32) @@ -41,8 +41,4 @@ return entityManager.contains(entity); } - @Override - public void commit() { - entityManager.getTransaction().commit(); - } } Added: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStorageMovementDao.java =================================================================== --- trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStorageMovementDao.java (rev 0) +++ trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStorageMovementDao.java 2013-03-22 13:19:12 UTC (rev 32) @@ -0,0 +1,39 @@ +package com.franciaflex.magalie.dao.jpa; + +import com.franciaflex.magalie.dao.StorageMovementDao; +import com.franciaflex.magalie.entity.Article; +import com.franciaflex.magalie.entity.StorageMovement; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.Query; +import java.util.List; + +public class JpaStorageMovementDao extends AbstractJpaDao<StorageMovement> implements StorageMovementDao { + + public JpaStorageMovementDao(EntityManager entityManager) { + super(entityManager); + } + + @Override + protected Class<StorageMovement> getEntityClass() { + return StorageMovement.class; + } + + @Override + public List<StorageMovement> findAllByArticle(Article article) { + Query query = entityManager.createQuery("from StorageMovement sm where sm.article = :article"); + query.setParameter("article", article); + return query.getResultList(); + } + + @Override + public void persistAll(Iterable<StorageMovement> storageMovements) { + EntityTransaction transaction = entityManager.getTransaction(); + transaction.begin(); + for (StorageMovement storageMovement : storageMovements) { + persist(storageMovement); + } + transaction.commit(); + } +} Modified: trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStoredArticleDao.java =================================================================== --- trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStoredArticleDao.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-persistence/src/main/java/com/franciaflex/magalie/dao/jpa/JpaStoredArticleDao.java 2013-03-22 13:19:12 UTC (rev 32) @@ -23,7 +23,10 @@ public List<StoredArticle> findAllForArticle(Article article) { Query query = entityManager.createQuery("from StoredArticle sa where sa.article = :article"); query.setParameter("article", article); - List resultList = query.getResultList(); + List<StoredArticle> resultList = query.getResultList(); + for (StoredArticle storedArticle : resultList) { + entityManager.detach(storedArticle); + } return resultList; } } Modified: trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/ArticleStorageService.java =================================================================== --- trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/ArticleStorageService.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/ArticleStorageService.java 2013-03-22 13:19:12 UTC (rev 32) @@ -1,18 +1,24 @@ package com.franciaflex.magalie.services; import com.franciaflex.magalie.StoredArticles; +import com.franciaflex.magalie.dao.StorageMovementDao; import com.franciaflex.magalie.dao.StoredArticleDao; import com.franciaflex.magalie.entity.Article; import com.franciaflex.magalie.entity.MagalieUser; +import com.franciaflex.magalie.entity.Site; +import com.franciaflex.magalie.entity.StorageMovement; import com.franciaflex.magalie.entity.StoredArticle; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import java.util.Date; import java.util.List; import java.util.Set; @@ -73,6 +79,10 @@ double quantity = 0; + List<StorageMovement> newStorageMovements = Lists.newLinkedList(); + + Date orderDate = serviceContext.getDate(); + for (StoredArticle storedArticle : sortedStoredArticles) { double quantityLeft = requestedQuantity - quantity; @@ -85,9 +95,21 @@ quantity += quantityWithdrawn; - // TODO brendan 18/03/13 enregistrer le mouvement - // quantityInSite -= quantityWithdrawn; + StorageMovement newStorageMovement = new StorageMovement(); + newStorageMovement.setArticle(article); + + newStorageMovement.setOrderDate(orderDate); + + newStorageMovement.setMagalieUser(magalieUser); + + newStorageMovement.setSite(storedArticle.getSite()); + + // we remove from the stock so negative number + newStorageMovement.setQuantity( -1. * quantityWithdrawn); + + newStorageMovements.add(newStorageMovement); + } WithdrawArticleFromSiteTask withdrawArticleFromSiteTask = new WithdrawArticleFromSiteTask(storedArticle, quantityWithdrawn); @@ -96,6 +118,10 @@ } + StorageMovementDao storageMovementDao = serviceContext.getStorageMovementDao(); + + storageMovementDao.persistAll(newStorageMovements); + return withdrawTask; } @@ -104,10 +130,45 @@ StoredArticleDao storedArticleDao = serviceContext.getStoredArticleDao(); - // TODO brendan 18/03/13 remove storage movement, remove sites in error + List<StoredArticle> storedArticles = storedArticleDao.findAllForArticle(article); - return storedArticleDao.findAllForArticle(article); + // consider storage movements and compute actually available quantities + StorageMovementDao storageMovementDao = serviceContext.getStorageMovementDao(); + + List<StorageMovement> storageMovements = storageMovementDao.findAllByArticle(article); + + ImmutableMap<Site,StoredArticle> storedArticlesBySite = + Maps.uniqueIndex( + storedArticles, + StoredArticles.getSiteFunction() + ); + + for (StorageMovement storageMovement : storageMovements) { + + Site site = storageMovement.getSite(); + + StoredArticle storedArticle = storedArticlesBySite.get(site); + + double actualQuantity = storedArticle.getQuantity() + storageMovement.getQuantity(); + + if (actualQuantity > 0.) { + + storedArticle.setQuantity(actualQuantity); + + } else { + + // site is empty, do not include it as a site where you can take an article + storedArticles.remove(storedArticle); + + } + + } + + // TODO brendan 21/03/13 consider sites in error + + return storedArticles; + } protected double getAvailableQuantity(Article article) { @@ -147,4 +208,5 @@ return accessibleQuantity; } + } Modified: trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/DefaultMagalieServiceContext.java =================================================================== --- trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/DefaultMagalieServiceContext.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/DefaultMagalieServiceContext.java 2013-03-22 13:19:12 UTC (rev 32) @@ -3,17 +3,20 @@ import com.franciaflex.magalie.MagalieApplicationConfig; import com.franciaflex.magalie.MagalieTechnicalException; import com.franciaflex.magalie.dao.ArticleDao; +import com.franciaflex.magalie.dao.MagalieUserDao; import com.franciaflex.magalie.dao.RequestedArticleDao; +import com.franciaflex.magalie.dao.StorageMovementDao; import com.franciaflex.magalie.dao.StoredArticleDao; import com.franciaflex.magalie.dao.jpa.JpaArticleDao; import com.franciaflex.magalie.dao.jpa.JpaMagalieUserDao; -import com.franciaflex.magalie.dao.MagalieUserDao; import com.franciaflex.magalie.dao.jpa.JpaRequestedArticleDao; +import com.franciaflex.magalie.dao.jpa.JpaStorageMovementDao; import com.franciaflex.magalie.dao.jpa.JpaStoredArticleDao; import javax.persistence.EntityManager; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Date; public class DefaultMagalieServiceContext implements MagalieServiceContext { @@ -25,6 +28,7 @@ this.entityManager = entityManager; } + @Override public MagalieApplicationConfig getMagalieApplicationConfig() { return magalieApplicationConfig; } @@ -69,6 +73,12 @@ } @Override + public Date getDate() { + Date now = new Date(); + return now; + } + + @Override public MagalieUserDao getMagalieUserDao() { return new JpaMagalieUserDao(entityManager); } @@ -87,4 +97,9 @@ public ArticleDao getArticleDao() { return new JpaArticleDao(entityManager); } + + @Override + public StorageMovementDao getStorageMovementDao() { + return new JpaStorageMovementDao(entityManager); + } } Modified: trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/MagalieServiceContext.java =================================================================== --- trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/MagalieServiceContext.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/main/java/com/franciaflex/magalie/services/MagalieServiceContext.java 2013-03-22 13:19:12 UTC (rev 32) @@ -23,16 +23,22 @@ * #L% */ +import com.franciaflex.magalie.MagalieApplicationConfig; import com.franciaflex.magalie.dao.ArticleDao; import com.franciaflex.magalie.dao.MagalieUserDao; import com.franciaflex.magalie.dao.RequestedArticleDao; +import com.franciaflex.magalie.dao.StorageMovementDao; import com.franciaflex.magalie.dao.StoredArticleDao; +import java.util.Date; + /** * @author bleny */ public interface MagalieServiceContext { + Date getDate(); + <E extends MagalieService> E newService(Class<E> serviceClass); MagalieUserDao getMagalieUserDao(); @@ -42,4 +48,8 @@ RequestedArticleDao getRequestedArticleDao(); ArticleDao getArticleDao(); + + StorageMovementDao getStorageMovementDao(); + + MagalieApplicationConfig getMagalieApplicationConfig(); } Modified: trunk/magalie-services/src/test/java/com/franciaflex/magalie/AbstractMagalieServiceTest.java =================================================================== --- trunk/magalie-services/src/test/java/com/franciaflex/magalie/AbstractMagalieServiceTest.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/test/java/com/franciaflex/magalie/AbstractMagalieServiceTest.java 2013-03-22 13:19:12 UTC (rev 32) @@ -1,13 +1,13 @@ package com.franciaflex.magalie; import com.franciaflex.magalie.entity.AbstractJpaEntity; -import com.franciaflex.magalie.services.DefaultMagalieServiceContext; import com.franciaflex.magalie.services.MagalieService; import com.franciaflex.magalie.services.MagalieServiceContext; import com.google.common.collect.Lists; import org.junit.Rule; import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; import java.util.Collection; import java.util.List; import java.util.Map; @@ -22,7 +22,7 @@ protected JpaEntityManagerRule jpaEntityManagerRule; - protected MagalieServiceContext serviceContext; + protected FakeMagalieServiceContext serviceContext; protected static MagalieApplicationConfig getMagalieApplicationConfig() { @@ -57,7 +57,7 @@ if (serviceContext == null) { - DefaultMagalieServiceContext serviceContext = new DefaultMagalieServiceContext(); + FakeMagalieServiceContext serviceContext = new FakeMagalieServiceContext(); serviceContext.setMagalieApplicationConfig(getMagalieApplicationConfig()); @@ -74,13 +74,17 @@ toPersist.addAll(fixtures.<Collection<? extends AbstractJpaEntity>>fixture("articles")); toPersist.addAll(fixtures.<Collection<? extends AbstractJpaEntity>>fixture("storedArticles")); + EntityTransaction transaction = entityManager.getTransaction(); + + transaction.begin(); + for (AbstractJpaEntity entity : toPersist) { entityManager.persist(entity); } - entityManager.getTransaction().commit(); + transaction.commit(); this.serviceContext = serviceContext; Added: trunk/magalie-services/src/test/java/com/franciaflex/magalie/FakeMagalieServiceContext.java =================================================================== --- trunk/magalie-services/src/test/java/com/franciaflex/magalie/FakeMagalieServiceContext.java (rev 0) +++ trunk/magalie-services/src/test/java/com/franciaflex/magalie/FakeMagalieServiceContext.java 2013-03-22 13:19:12 UTC (rev 32) @@ -0,0 +1,29 @@ +package com.franciaflex.magalie; + +import com.franciaflex.magalie.services.DefaultMagalieServiceContext; +import com.google.common.base.Preconditions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Date; + +public class FakeMagalieServiceContext extends DefaultMagalieServiceContext { + + private static final Log log = LogFactory.getLog(FakeMagalieServiceContext.class); + + protected Date date; + + @Override + public Date getDate() { + Preconditions.checkState(date != null, "you must provide a date before running service test"); + if (log.isTraceEnabled()) { + log.trace("injecting fake date in service: " + date); + } + return date; + } + + public void setDate(Date date) { + this.date = date; + } + +} Modified: trunk/magalie-services/src/test/java/com/franciaflex/magalie/JpaEntityManagerRule.java =================================================================== --- trunk/magalie-services/src/test/java/com/franciaflex/magalie/JpaEntityManagerRule.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/test/java/com/franciaflex/magalie/JpaEntityManagerRule.java 2013-03-22 13:19:12 UTC (rev 32) @@ -65,11 +65,9 @@ entityManager = entityManagerFactory.createEntityManager(); if (log.isDebugEnabled()) { - log.debug("created entityManager " + entityManager + " and opened transaction"); + log.debug("created entityManager " + entityManager); } - entityManager.getTransaction().begin(); - open = true; } Modified: trunk/magalie-services/src/test/java/com/franciaflex/magalie/services/ArticleStorageServiceTest.java =================================================================== --- trunk/magalie-services/src/test/java/com/franciaflex/magalie/services/ArticleStorageServiceTest.java 2013-03-21 13:55:30 UTC (rev 31) +++ trunk/magalie-services/src/test/java/com/franciaflex/magalie/services/ArticleStorageServiceTest.java 2013-03-22 13:19:12 UTC (rev 32) @@ -10,6 +10,9 @@ import org.junit.Before; import org.junit.Test; +import java.text.ParseException; +import java.util.Date; + public class ArticleStorageServiceTest extends AbstractMagalieServiceTest { private static final Log log = LogFactory.getLog(ArticleStorageServiceTest.class); @@ -17,10 +20,12 @@ protected ArticleStorageService service; @Before - public void setUp() { + public void setUp() throws ParseException { service = newService(ArticleStorageService.class); + serviceContext.setDate(new Date(1363948427576l)); + } @Test @@ -123,4 +128,61 @@ Assert.assertEquals(30., site2.getQuantity(), DELTA); } + @Test + public void testWithdrawArticleConsiderAlreadyRemovedItem() throws Exception { + + MagalieUser alexandre = fixture("alexandre"); + MagalieUser cathy = fixture("cathy"); + + Article article = fixture("article1"); + + WithdrawTask withdrawTask = null; + + try { + withdrawTask = service.withdrawArticle(alexandre, article, 30.); + if (log.isDebugEnabled()) { + log.debug("withdrawTask = " + withdrawTask); + } + Assert.assertEquals(2, withdrawTask.getSites().size()); + WithdrawArticleFromSiteTask site1 = Iterables.get(withdrawTask.getSites(), 0, null); + Assert.assertEquals(20., site1.getQuantity(), DELTA); + Assert.assertEquals("B2", site1.getLocationCode()); + WithdrawArticleFromSiteTask site2 = Iterables.get(withdrawTask.getSites(), 1, null); + Assert.assertEquals(10., site2.getQuantity(), DELTA); + Assert.assertEquals("A1", site2.getLocationCode()); + } catch (RequiredDriverLicenceException e) { + if (log.isDebugEnabled()) { + log.debug("exception raised = " + e); + } + Assert.fail(); + } catch (UnavailableArticleException e) { + if (log.isDebugEnabled()) { + log.debug("exception raised = " + e); + } + Assert.fail(); + } + + try { + withdrawTask = service.withdrawArticle(cathy, article, 30.); + if (log.isDebugEnabled()) { + log.debug("withdrawTask = " + withdrawTask); + } + Assert.assertEquals(1, withdrawTask.getSites().size()); + WithdrawArticleFromSiteTask site1 = Iterables.get(withdrawTask.getSites(), 0, null); + Assert.assertEquals(30., site1.getQuantity(), DELTA); + Assert.assertEquals("A1", site1.getLocationCode()); + } catch (RequiredDriverLicenceException e) { + if (log.isDebugEnabled()) { + log.debug("exception raised = " + e); + } + Assert.fail(); + } catch (UnavailableArticleException e) { + if (log.isDebugEnabled()) { + log.debug("exception raised = " + e); + } + Assert.fail(); + } + } + + }