/** * Axelor Business Solutions * * Copyright (C) 2016 Axelor (<http://axelor.com>). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.axelor.apps.supplychain.service; import java.math.BigDecimal; import java.util.Arrays; import org.hibernate.proxy.HibernateProxy; import org.joda.time.LocalDate; import com.axelor.apps.base.db.Company; import com.axelor.apps.base.db.Partner; import com.axelor.apps.base.db.Product; import com.axelor.apps.base.db.Unit; import com.axelor.apps.base.service.UnitConversionService; import com.axelor.apps.base.service.administration.GeneralService; import com.axelor.apps.base.service.user.UserService; import com.axelor.apps.purchase.db.PurchaseOrder; import com.axelor.apps.purchase.db.PurchaseOrderLine; import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository; import com.axelor.apps.purchase.service.PurchaseOrderLineService; import com.axelor.apps.sale.db.SaleOrderLine; import com.axelor.apps.stock.db.Location; import com.axelor.apps.stock.db.MinStockRules; import com.axelor.apps.stock.db.repo.MinStockRulesRepository; import com.axelor.apps.stock.service.MinStockRulesService; 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.MrpLineType; import com.axelor.apps.supplychain.db.repo.MrpLineTypeRepository; import com.axelor.apps.supplychain.exception.IExceptionMessage; import com.axelor.auth.db.User; import com.axelor.db.Model; import com.axelor.exception.AxelorException; import com.axelor.exception.db.IException; import com.axelor.i18n.I18n; import com.axelor.inject.Beans; import com.google.inject.Inject; import com.google.inject.persist.Transactional; public class MrpLineServiceImpl implements MrpLineService { protected PurchaseOrderServiceSupplychainImpl purchaseOrderServiceSupplychainImpl; protected PurchaseOrderLineService purchaseOrderLineService; protected PurchaseOrderRepository purchaseOrderRepo; protected MinStockRulesService minStockRulesService; protected LocalDate today; protected User user; @Inject public MrpLineServiceImpl(GeneralService generalService, UserService userService, PurchaseOrderServiceSupplychainImpl purchaseOrderServiceSupplychainImpl, PurchaseOrderLineService purchaseOrderLineService, PurchaseOrderRepository purchaseOrderRepo, MinStockRulesService minStockRulesService) { this.purchaseOrderServiceSupplychainImpl = purchaseOrderServiceSupplychainImpl; this.purchaseOrderLineService = purchaseOrderLineService; this.purchaseOrderRepo = purchaseOrderRepo; this.minStockRulesService = minStockRulesService; this.today = generalService.getTodayDate(); this.user = userService.getUser(); } public void generateProposal(MrpLine mrpLine) throws AxelorException { if(mrpLine.getMrpLineType().getElementSelect() == MrpLineTypeRepository.ELEMENT_PURCHASE_PROPOSAL) { this.generatePurchaseProposal(mrpLine); } } @Transactional(rollbackOn = {AxelorException.class, Exception.class}) protected void generatePurchaseProposal(MrpLine mrpLine) throws AxelorException { Product product = mrpLine.getProduct(); Location location = mrpLine.getLocation(); LocalDate maturityDate = mrpLine.getMaturityDate(); Partner supplierPartner = product.getDefaultSupplierPartner(); if(supplierPartner == null) { throw new AxelorException(String.format(I18n.get(IExceptionMessage.MRP_LINE_1), product.getFullName()), IException.CONFIGURATION_ERROR); } Company company = location.getCompany(); PurchaseOrder purchaseOrder = purchaseOrderRepo.save(purchaseOrderServiceSupplychainImpl.createPurchaseOrder( this.user, company, null, supplierPartner.getCurrency(), maturityDate, "MRP-"+this.today.toString(), //TODO sequence on mrp null, location, this.today, supplierPartner.getPurchasePriceList(), supplierPartner)); Unit unit = product.getPurchasesUnit(); BigDecimal qty = mrpLine.getQty(); if(unit == null){ unit = product.getUnit(); } else{ qty = Beans.get(UnitConversionService.class).convertWithProduct(product.getUnit(), unit, qty, product); } purchaseOrder.addPurchaseOrderLineListItem( purchaseOrderLineService.createPurchaseOrderLine( purchaseOrder, product, null, null, qty, unit)); purchaseOrderServiceSupplychainImpl.computePurchaseOrder(purchaseOrder); } public MrpLine createMrpLine(Product product, int maxLevel, MrpLineType mrpLineType, BigDecimal qty, LocalDate maturityDate, BigDecimal cumulativeQty, Location location, Model... models) { MrpLine mrpLine = new MrpLine(); mrpLine.setProduct(product); mrpLine.setMaxLevel(maxLevel); mrpLine.setMrpLineType(mrpLineType); if(mrpLineType.getTypeSelect() == MrpLineTypeRepository.TYPE_OUT) { mrpLine.setQty(qty.negate()); } else { mrpLine.setQty(qty); } mrpLine.setMaturityDate(maturityDate); mrpLine.setCumulativeQty(cumulativeQty); mrpLine.setLocation(location); mrpLine.setMinQty(this.getMinQty(product, location)); this.createMrpLineOrigins(mrpLine, models); return mrpLine; } protected BigDecimal getMinQty(Product product, Location location) { MinStockRules minStockRules = minStockRulesService.getMinStockRules(product, location, MinStockRulesRepository.TYPE_FUTURE); if(minStockRules != null) { return minStockRules.getMinQty(); } return BigDecimal.ZERO; } protected void createMrpLineOrigins(MrpLine mrpLine, Model... models) { if(models != null) { for(Model model : Arrays.asList(models)) { mrpLine.addMrpLineOriginListItem(this.createMrpLineOrigin(model)); mrpLine.setRelatedToSelectName(this.computeReleatedName(model)); } } } public MrpLineOrigin createMrpLineOrigin(Model model) { Class<?> klass = model.getClass(); if ( model instanceof HibernateProxy ) { klass = ( (HibernateProxy) model ).getHibernateLazyInitializer().getPersistentClass(); } MrpLineOrigin mrpLineOrigin = new MrpLineOrigin(); mrpLineOrigin.setRelatedToSelect(klass.getCanonicalName()); mrpLineOrigin.setRelatedToSelectId(model.getId()); return mrpLineOrigin; } public MrpLineOrigin copyMrpLineOrigin(MrpLineOrigin mrpLineOrigin) { MrpLineOrigin copyMrpLineOrigin = new MrpLineOrigin(); copyMrpLineOrigin.setRelatedToSelect(mrpLineOrigin.getRelatedToSelect()); copyMrpLineOrigin.setRelatedToSelectId(mrpLineOrigin.getRelatedToSelectId()); return copyMrpLineOrigin; } protected String computeReleatedName(Model model) { if(model instanceof SaleOrderLine) { return ((SaleOrderLine) model).getSaleOrder().getSaleOrderSeq(); } else if(model instanceof PurchaseOrderLine) { return ((PurchaseOrderLine) model).getPurchaseOrder().getPurchaseOrderSeq(); } else if(model instanceof MrpForecast) { MrpForecast mrpForecast = (MrpForecast) model; return mrpForecast.getId()+"-"+mrpForecast.getForecastDate(); } return null; } }