diff --git a/modules/axelor-open-suite/axelor-production/src/main/java/com/axelor/apps/production/service/MrpServiceProductionImpl.java b/modules/axelor-open-suite/axelor-production/src/main/java/com/axelor/apps/production/service/MrpServiceProductionImpl.java index 404556c..655a8d4 100644 --- a/modules/axelor-open-suite/axelor-production/src/main/java/com/axelor/apps/production/service/MrpServiceProductionImpl.java +++ b/modules/axelor-open-suite/axelor-production/src/main/java/com/axelor/apps/production/service/MrpServiceProductionImpl.java @@ -19,7 +19,9 @@ package com.axelor.apps.production.service; import com.axelor.apps.base.db.Company; import com.axelor.apps.base.db.Product; +import com.axelor.apps.base.db.Unit; import com.axelor.apps.base.db.repo.ProductRepository; +import com.axelor.apps.base.service.UnitConversionService; import com.axelor.apps.production.db.BillOfMaterial; import com.axelor.apps.production.db.ManufOrder; import com.axelor.apps.production.db.OperationOrder; @@ -36,11 +38,14 @@ import com.axelor.apps.stock.db.repo.StockRulesRepository; import com.axelor.apps.stock.service.StockLocationService; import com.axelor.apps.stock.service.StockRulesService; import com.axelor.apps.supplychain.db.Mrp; +import com.axelor.apps.supplychain.db.MrpForecast; import com.axelor.apps.supplychain.db.MrpLine; import com.axelor.apps.supplychain.db.MrpLineOrigin; +import com.axelor.apps.supplychain.db.MrpLineSophal; import com.axelor.apps.supplychain.db.MrpLineType; import com.axelor.apps.supplychain.db.repo.MrpForecastRepository; import com.axelor.apps.supplychain.db.repo.MrpLineRepository; +import com.axelor.apps.supplychain.db.repo.MrpLineSophalRepository; import com.axelor.apps.supplychain.db.repo.MrpLineTypeRepository; import com.axelor.apps.supplychain.db.repo.MrpRepository; import com.axelor.apps.supplychain.service.MrpLineService; @@ -48,12 +53,18 @@ import com.axelor.apps.supplychain.service.MrpServiceImpl; import com.axelor.apps.tool.StringTool; import com.axelor.db.JPA; import com.axelor.exception.AxelorException; +import com.axelor.inject.Beans; import com.google.inject.Inject; import com.google.inject.persist.Transactional; import java.lang.invoke.MethodHandles; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.LocalDate; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -437,4 +448,106 @@ public class MrpServiceProductionImpl extends MrpServiceImpl { this.createManufOrderMrpLines(); return mrp; } + + @Override + public void createAvailableMrpLineSophal(Mrp mrp) throws AxelorException{ + super.createAvailableMrpLineSophal(mrp); + } + + + @Transactional + @Override + public void createMrpLineSophal(Mrp mrp, Product product,Unit unit,BigDecimal qty,List mrpForecastList, Map productQty) throws AxelorException{ + + if(mrp.getIncludeBOM()){ + + BillOfMaterial defaultBillOfMaterial = product.getDefaultBillOfMaterial(); + + if (defaultBillOfMaterial != null) { + + for (BillOfMaterial billOfMaterial : defaultBillOfMaterial.getBillOfMaterialSet()) { + List forecastList = mrpForecastList.stream().filter(t -> t.getProduct() == product).collect(Collectors.toList()); + + Product subProduct = billOfMaterial.getProduct(); + + if (this.isMrpProduct(subProduct)) { + + Double prodQty = productQty.get(subProduct.getId()) == null ? Double.parseDouble("0") : productQty.get(subProduct.getId()); + BigDecimal reelQty =new BigDecimal(prodQty); + + createMrpLineSophalProd(mrp, subProduct,product, reelQty ,billOfMaterial.getQty(),defaultBillOfMaterial.getQty(),forecastList); + } + } + + } + }else{ + super.createMrpLineSophal(mrp, product,unit, qty, mrpForecastList,productQty); + } +} + + @Transactional + public void createMrpLineSophalProd(Mrp mrp,Product product,Product parentProduct,BigDecimal qty,BigDecimal reorderdQty,BigDecimal defaultQty, List forecastList){ + MrpLineSophal mrpLineSophal = new MrpLineSophal(); + mrpLineSophal.setQty(qty); + BigDecimal reelQty = qty; + BigDecimal sumQty = BigDecimal.ZERO; + for (MrpForecast forecast : forecastList) { + + if(forecast.getProduct().getId() == parentProduct.getId()){ + BigDecimal dividedQty = (forecast.getQty().multiply(reorderdQty)).divide(defaultQty); + reelQty = reelQty.subtract(dividedQty); + sumQty = sumQty.add(dividedQty); + BigDecimal displayedQty = reelQty; + switch (forecast.getMonthSelect()) { + case 1: + mrpLineSophal.setJanuary(displayedQty); + break; + case 2: + mrpLineSophal.setFebruary(displayedQty); + break; + case 3: + mrpLineSophal.setMarch(displayedQty); + break; + case 4: + mrpLineSophal.setApril(displayedQty); + case 5: + mrpLineSophal.setMay(displayedQty); + case 6: + mrpLineSophal.setJuin(displayedQty); + break; + case 7: + mrpLineSophal.setJuly(displayedQty); + break; + case 8: + mrpLineSophal.setAugust(displayedQty); + break; + case 9: + mrpLineSophal.setSeptember(displayedQty); + break; + case 10: + mrpLineSophal.setOctober(displayedQty); + break; + case 11: + mrpLineSophal.setNovember(displayedQty); + break; + case 12: + mrpLineSophal.setDecember(displayedQty); + break; + default: + break; + } + } + } + mrpLineSophal.setMrp(mrp); + mrpLineSophal.setProduct(product); + mrpLineSophal.setUnit(product.getPurchasesUnit()); + mrpLineSophal.setProductOrigin(parentProduct); + + Stream filter = forecastList.stream().filter(t -> t.getProduct().getId() == parentProduct.getId()); + Long totalForecast = filter.count(); + + mrpLineSophal.setSecurityStock(sumQty.divide(new BigDecimal(totalForecast) ,5, RoundingMode.HALF_EVEN)); + Beans.get(MrpLineSophalRepository.class).save(mrpLineSophal); + } + } diff --git a/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/service/MrpServiceImpl.java b/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/service/MrpServiceImpl.java index 268609c..2027d95 100644 --- a/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/service/MrpServiceImpl.java +++ b/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/service/MrpServiceImpl.java @@ -46,15 +46,18 @@ import com.axelor.apps.supplychain.db.MrpFamily; import com.axelor.apps.supplychain.db.MrpForecast; import com.axelor.apps.supplychain.db.MrpLine; import com.axelor.apps.supplychain.db.MrpLineOrigin; +import com.axelor.apps.supplychain.db.MrpLineSophal; import com.axelor.apps.supplychain.db.MrpLineType; import com.axelor.apps.supplychain.db.repo.MrpForecastRepository; import com.axelor.apps.supplychain.db.repo.MrpLineRepository; +import com.axelor.apps.supplychain.db.repo.MrpLineSophalRepository; import com.axelor.apps.supplychain.db.repo.MrpLineTypeRepository; import com.axelor.apps.supplychain.db.repo.MrpRepository; import com.axelor.apps.supplychain.exception.IExceptionMessage; import com.axelor.apps.tool.StringTool; import com.axelor.db.JPA; import com.axelor.db.Model; +import com.axelor.db.Query; import com.axelor.exception.AxelorException; import com.axelor.exception.db.repo.TraceBackRepository; import com.axelor.i18n.I18n; @@ -66,12 +69,14 @@ import com.google.inject.Inject; import com.google.inject.persist.Transactional; import java.lang.invoke.MethodHandles; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.LocalDate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collector; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; @@ -98,6 +103,7 @@ public class MrpServiceImpl implements MrpService { protected List stockLocationList; protected Map productMap; + protected Map productQty; protected Mrp mrp; protected LocalDate today; @@ -171,6 +177,17 @@ public class MrpServiceImpl implements MrpService { mrpRepository.save(mrp); } + @Transactional + public void resetSophalLine(Mrp mrp) { + + Beans.get(MrpLineSophalRepository.class).all().filter("self.mrp.id = ?1", mrp.getId()).remove(); + + + mrp.setStatusSelect(MrpRepository.STATUS_DRAFT); + + mrpRepository.save(mrp); + } + protected void completeMrp(Mrp mrp) throws AxelorException { log.debug("Complete MRP"); @@ -1096,4 +1113,128 @@ public class MrpServiceImpl implements MrpService { return mrp; } + + + public void createAvailableMrpLineSophal(Mrp mrp) throws AxelorException { + this.resetSophalLine(mrp); + today = appBaseService.getTodayDate(); + + Set slList2 = Sets.newHashSet(); + this.mrp = mrp; + try { + this.assignProductAndLevel(this.getProductList()); + + } catch (AxelorException e) { + e.printStackTrace(); + } + + this.productQty = new HashMap<>(); + + try { + + stockLocationLineRepository.all().filter("self.product.id in ?1 and self.stockLocation is not null and self.currentQty > 0 and self.stockLocation.isNotInMrp is false",this.productMap.keySet()) + .fetch().forEach(t ->slList2.add(t.getStockLocation())); + + this.productQty = stockLocationLineRepository.all() + .filter("self.product.id in (?1) and self.stockLocation is not null and self.currentQty > 0 and self.stockLocation.isNotInMrp is false",this.productMap.keySet()) + .fetch().stream().filter(t -> !t.getStockLocation().getIsNotInMrp()).collect(Collectors.groupingBy(t -> t.getProduct().getId(),Collectors.summingDouble(o->o.getCurrentQty().doubleValue()))); + + + } catch (Exception e) { + log.debug(e.toString()); + } + + List mrpForecastList = new ArrayList<>(); + + if (mrp.getMrpForecastSet().isEmpty()) { + Integer scenario = mrp.getScenario(); + + mrpForecastList.addAll( + mrpForecastRepository + .all() + .filter( + "self.product.id in (?1) AND self.stockLocation in (?2) AND self.forecastDate "+( scenario == 3 ? "<=" : ">=")+" ?3 AND self.statusSelect = ?4 AND self.scenario = ?5", + this.productMap.keySet(), + slList2.stream().collect(Collectors.toList()), + today, + MrpForecastRepository.STATUS_CONFIRMED, + scenario) + .order("monthSelect") + .fetch()); + + log.debug(mrpForecastList.toString()); + } + + for (Map.Entry entry : productQty.entrySet()) { + Product product = productRepository.find(entry.getKey()); + BigDecimal qty = new BigDecimal(entry.getValue()); + if(this.productMap.get(product.getId()) == 0){ + this.createMrpLineSophal(mrp, product,product.getUnit(), qty,mrpForecastList,productQty); + } + } + } + + @Transactional + public void createMrpLineSophal(Mrp mrp, Product product,Unit unit,BigDecimal qty,List mrpForecastList, Map productQty) throws AxelorException { + + MrpLineSophal mrpLineSophal = new MrpLineSophal(); + mrpLineSophal.setQty(qty); + BigDecimal reelQty = qty; + BigDecimal sumQty = BigDecimal.ZERO; + for (MrpForecast forecast : mrpForecastList) { + if(forecast.getProduct() == product){ + reelQty = reelQty.subtract(forecast.getQty()); + BigDecimal displayedQty = reelQty; + sumQty = sumQty.add(forecast.getQty()); + switch (forecast.getMonthSelect()) { + case 1: + mrpLineSophal.setJanuary(displayedQty); + break; + case 2: + mrpLineSophal.setFebruary(displayedQty); + break; + case 3: + mrpLineSophal.setMarch(displayedQty); + break; + case 4: + mrpLineSophal.setApril(displayedQty); + case 5: + mrpLineSophal.setMay(displayedQty); + case 6: + mrpLineSophal.setJuin(displayedQty); + break; + case 7: + mrpLineSophal.setJuly(displayedQty); + break; + case 8: + mrpLineSophal.setAugust(displayedQty); + break; + case 9: + mrpLineSophal.setSeptember(displayedQty); + break; + case 10: + mrpLineSophal.setOctober(displayedQty); + break; + case 11: + mrpLineSophal.setNovember(displayedQty); + break; + case 12: + mrpLineSophal.setDecember(displayedQty); + break; + default: + break; + } + } + } + mrpLineSophal.setMrp(mrp); + mrpLineSophal.setProduct(product); + mrpLineSophal.setUnit(product.getUnit()); + mrpLineSophal.setCompany(mrp.getStockLocation().getCompany()); + + Long totalForecast = mrpForecastList.stream().filter(t -> t.getProduct() == product).count(); + + mrpLineSophal.setSecurityStock(sumQty.divide(new BigDecimal(totalForecast),5, RoundingMode.HALF_EVEN)); + Beans.get(MrpLineSophalRepository.class).save(mrpLineSophal); + + } } diff --git a/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/web/MrpController.java b/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/web/MrpController.java index a394fe3..a18aaa4 100644 --- a/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/web/MrpController.java +++ b/modules/axelor-open-suite/axelor-supplychain/src/main/java/com/axelor/apps/supplychain/web/MrpController.java @@ -17,12 +17,25 @@ */ package com.axelor.apps.supplychain.web; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.axelor.apps.ReportFactory; +import com.axelor.apps.base.db.Function; +import com.axelor.apps.base.db.Product; import com.axelor.apps.report.engine.ReportSettings; import com.axelor.apps.supplychain.db.Mrp; +import com.axelor.apps.supplychain.db.repo.MrpForecastRepository; +import com.axelor.apps.supplychain.db.repo.MrpLineRepository; import com.axelor.apps.supplychain.db.repo.MrpRepository; import com.axelor.apps.supplychain.report.IReport; +import com.axelor.apps.supplychain.service.MrpLineServiceImpl; import com.axelor.apps.supplychain.service.MrpService; +import com.axelor.apps.supplychain.service.MrpServiceImpl; import com.axelor.exception.AxelorException; import com.axelor.exception.service.TraceBackService; import com.axelor.i18n.I18n; @@ -31,6 +44,9 @@ import com.axelor.meta.schema.actions.ActionView; import com.axelor.rpc.ActionRequest; import com.axelor.rpc.ActionResponse; import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; +import com.axelor.apps.supplychain.db.MrpForecast; +import com.axelor.apps.supplychain.db.MrpLineSophal; @Singleton public class MrpController { @@ -121,4 +137,16 @@ public class MrpController { TraceBackService.trace(response, e); } } + + /** + * @param request + * @param response + * @throws AxelorException + */ + public void calculationCbn(ActionRequest request, ActionResponse response) throws AxelorException { + Mrp mrp = Beans.get(MrpRepository.class).find(request.getContext().asType(Mrp.class).getId()); + Beans.get(MrpServiceImpl.class).createAvailableMrpLineSophal(mrp); + response.setReload(true); + } + } diff --git a/modules/axelor-open-suite/axelor-supplychain/src/main/resources/domains/Mrp.xml b/modules/axelor-open-suite/axelor-supplychain/src/main/resources/domains/Mrp.xml index 9269a5e..b316c8a 100644 --- a/modules/axelor-open-suite/axelor-supplychain/src/main/resources/domains/Mrp.xml +++ b/modules/axelor-open-suite/axelor-supplychain/src/main/resources/domains/Mrp.xml @@ -16,7 +16,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +