temporary branch
This commit is contained in:
@@ -21,14 +21,20 @@ import static com.axelor.apps.base.service.administration.AbstractBatch.FETCH_LI
|
||||
|
||||
import com.axelor.apps.account.db.Account;
|
||||
import com.axelor.apps.account.db.AccountConfig;
|
||||
import com.axelor.apps.account.db.AccountManagement;
|
||||
import com.axelor.apps.account.db.AnalyticDistributionTemplate;
|
||||
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||
import com.axelor.apps.account.db.Journal;
|
||||
import com.axelor.apps.account.db.Move;
|
||||
import com.axelor.apps.account.db.MoveLine;
|
||||
import com.axelor.apps.account.db.Tax;
|
||||
import com.axelor.apps.account.db.TaxLine;
|
||||
import com.axelor.apps.account.db.repo.AccountManagementRepository;
|
||||
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||
import com.axelor.apps.account.db.repo.AnalyticMoveLineRepository;
|
||||
import com.axelor.apps.account.db.repo.JournalRepository;
|
||||
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||
import com.axelor.apps.account.service.AccountManagementAccountService;
|
||||
import com.axelor.apps.account.service.AnalyticMoveLineService;
|
||||
import com.axelor.apps.account.service.ReconcileService;
|
||||
@@ -52,8 +58,11 @@ import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
import com.axelor.apps.sale.db.SaleOrder;
|
||||
import com.axelor.apps.sale.db.SaleOrderLine;
|
||||
import com.axelor.apps.sale.db.repo.SaleOrderRepository;
|
||||
import com.axelor.apps.stock.db.InventoryLine;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.InventoryLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockLocationRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.supplychain.db.repo.SupplychainBatchRepository;
|
||||
@@ -61,6 +70,9 @@ import com.axelor.apps.supplychain.service.config.AccountConfigSupplychainServic
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.math.BigDecimal;
|
||||
@@ -69,8 +81,10 @@ import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AccountingCutOffServiceImpl implements AccountingCutOffService {
|
||||
@@ -640,4 +654,347 @@ public class AccountingCutOffServiceImpl implements AccountingCutOffService {
|
||||
}
|
||||
return stockMoveLineIdList;
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Move generateStockAccountMove(StockMove stockMove) throws AxelorException {
|
||||
List<StockMoveLine> stockMoveLines = stockMove.getStockMoveLineList();
|
||||
Map<StockMoveLine, Map<String, Account>> stockAccounts = new HashMap<>();
|
||||
Company company = stockMove.getCompany();
|
||||
Currency currency = stockMove.getCompany().getCurrency();
|
||||
Partner partner = stockMove.getPartner();
|
||||
LocalDate moveDate = stockMove.getEstimatedDate();
|
||||
Journal journal = this.setJournal(stockMove);
|
||||
for (StockMoveLine line : stockMoveLines) {
|
||||
Map<String, Account> accountMap = new HashMap<String, Account>();
|
||||
AccountManagement accountManagement =
|
||||
Beans.get(AccountManagementRepository.class)
|
||||
.all()
|
||||
.filter("self.product = ?1 and self.company = ?2", line.getProduct(), company)
|
||||
.fetchOne();
|
||||
if(stockMove.getToStockLocation().getTypeSelect() == StockLocationRepository.TYPE_EXTERNAL){
|
||||
Account stockAccount = null ;
|
||||
if(line.getProduct().getFamilleProduit().getId() == 67L || line.getProduct().getFamilleProduit().getId() == 68L){
|
||||
stockAccount = Beans.get(AccountRepository.class).find(595L);
|
||||
|
||||
}else if(line.getProduct().getFamilleProduit().getId() == 59L){
|
||||
stockAccount = Beans.get(AccountRepository.class).find(3518L);
|
||||
}else{
|
||||
stockAccount = Beans.get(AccountRepository.class).find(4113L);
|
||||
}
|
||||
accountMap.put("stockAccount", stockAccount);
|
||||
}else{
|
||||
accountMap.put("stockAccount", accountManagement.getStockAccount());
|
||||
}
|
||||
|
||||
accountMap.put("purchaseAccount", accountManagement.getPurchaseAccount());
|
||||
accountMap.put("consumptionAccount", accountManagement.getConsumptionAccount());
|
||||
stockAccounts.put(line, accountMap);
|
||||
}
|
||||
|
||||
Move move =
|
||||
moveCreateService.createMove(
|
||||
journal,
|
||||
company,
|
||||
currency,
|
||||
partner,
|
||||
moveDate,
|
||||
null,
|
||||
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||
|
||||
int counter = 0;
|
||||
for (StockMoveLine line : stockMoveLines) {
|
||||
|
||||
Account acc = stockAccounts.get(line).get("purchaseAccount");
|
||||
Account acc2 = stockAccounts.get(line).get("stockAccount");
|
||||
|
||||
if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING
|
||||
&& stockMove.getPartner() == stockMove.getCompany().getPartner()) {
|
||||
acc = stockAccounts.get(line).get("consumptionAccount");
|
||||
acc2 = stockAccounts.get(line).get("stockAccount");
|
||||
} else if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING
|
||||
&& stockMove.getPartner() != stockMove.getCompany().getPartner()) {
|
||||
acc2 = stockAccounts.get(line).get("stockAccount");
|
||||
acc = stockAccounts.get(line).get("purchaseAccount");
|
||||
} else if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_OUTGOING
|
||||
&& stockMove.getPartner() == stockMove.getCompany().getPartner()) {
|
||||
acc = stockAccounts.get(line).get("consumptionAccount");
|
||||
acc2 = stockAccounts.get(line).get("stockAccount");
|
||||
}
|
||||
|
||||
BigDecimal amountInCurrency = line.getUnitPriceUntaxed().multiply(line.getRealQty());
|
||||
String description = stockMove.getStockMoveSeq() + "-" + line.getProduct().getCode();
|
||||
if (line.getTrackingNumber() != null) {
|
||||
description += "-" + line.getTrackingNumber().getTrackingNumberSeq();
|
||||
}
|
||||
|
||||
if(line.getRealQty().compareTo(BigDecimal.ZERO) > 0 ){
|
||||
|
||||
MoveLine moveLine =
|
||||
moveLineService.createMoveLine(
|
||||
move,
|
||||
partner,
|
||||
acc,
|
||||
amountInCurrency,
|
||||
isDebit(stockMove),
|
||||
moveDate,
|
||||
++counter,
|
||||
stockMove.getStockMoveSeq(),
|
||||
description);
|
||||
moveLine.setDate(moveDate);
|
||||
moveLine.setDueDate(moveDate);
|
||||
moveLine.setAccountId(acc.getId());
|
||||
moveLine.setAccountCode(acc.getCode());
|
||||
|
||||
MoveLine moveLine2 =
|
||||
moveLineService.createMoveLine(
|
||||
move,
|
||||
partner,
|
||||
acc2,
|
||||
amountInCurrency,
|
||||
!isDebit(stockMove),
|
||||
moveDate,
|
||||
++counter,
|
||||
stockMove.getStockMoveSeq(),
|
||||
description);
|
||||
moveLine2.setDate(moveDate);
|
||||
moveLine2.setDueDate(moveDate);
|
||||
moveLine2.setAccountId(acc2.getId());
|
||||
moveLine2.setAccountCode(acc2.getCode());
|
||||
|
||||
|
||||
move.addMoveLineListItem(moveLine);
|
||||
move.addMoveLineListItem(moveLine2);
|
||||
}
|
||||
|
||||
}
|
||||
stockMove.setIsVentilated(true);
|
||||
move.setIgnoreInAccountingOk(false);
|
||||
move.setStatusSelect(MoveRepository.STATUS_DAYBOOK);
|
||||
move.setStockMove(stockMove);
|
||||
return move;
|
||||
}
|
||||
|
||||
public List<Long> massGenerationMove(List<Long> ids) throws AxelorException {
|
||||
|
||||
List<Long> movesId = new ArrayList<>();
|
||||
|
||||
for (Long id : ids) {
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(id);
|
||||
Move move = this.generateStockAccountMove(stockMove);
|
||||
movesId.add(move.getId());
|
||||
}
|
||||
;
|
||||
return movesId;
|
||||
}
|
||||
|
||||
public boolean isDebit(StockMove stockMove) throws AxelorException {
|
||||
boolean isDebit;
|
||||
// stockMove.getToStockLocation().getTypeSelect() == StockLocationRepository.TYPE_VIRTUAL
|
||||
if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING) {
|
||||
isDebit = false;
|
||||
} else if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_OUTGOING) {
|
||||
isDebit = true;
|
||||
} else
|
||||
throw new AxelorException(
|
||||
stockMove,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.MOVE_1),
|
||||
stockMove.getId());
|
||||
return isDebit;
|
||||
}
|
||||
|
||||
public Journal setJournal(StockMove stockMove) throws AxelorException {
|
||||
Journal journal;
|
||||
// stockMove.getToStockLocation().getTypeSelect() == StockLocationRepository.TYPE_VIRTUAL
|
||||
if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING) {
|
||||
journal = Beans.get(JournalRepository.class).find(10L);
|
||||
} else if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_OUTGOING) {
|
||||
journal = Beans.get(JournalRepository.class).find(30L);
|
||||
} else
|
||||
throw new AxelorException(
|
||||
stockMove,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.MOVE_1),
|
||||
stockMove.getId());
|
||||
return journal;
|
||||
}
|
||||
|
||||
public boolean isDebitInventoryLine(InventoryLine inventoryLine) throws AxelorException {
|
||||
boolean isDebit;
|
||||
// stockMove.getToStockLocation().getTypeSelect() == StockLocationRepository.TYPE_VIRTUAL
|
||||
if (inventoryLine.getGap().compareTo(BigDecimal.ZERO) < 0) {
|
||||
isDebit = false;
|
||||
} else if (inventoryLine.getGap().compareTo(BigDecimal.ZERO) > 0) {
|
||||
isDebit = true;
|
||||
} else
|
||||
throw new AxelorException(
|
||||
inventoryLine,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
"Ecart = 0",
|
||||
inventoryLine.getId());
|
||||
return isDebit;
|
||||
}
|
||||
|
||||
|
||||
public Boolean isGapPositive(InventoryLine line){
|
||||
if(line.getGap().compareTo(BigDecimal.ZERO) > 0){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Move generateInventoryLineMove(InventoryLine inventoryLine) throws AxelorException {
|
||||
|
||||
Map<InventoryLine, Map<String, Account>> stockAccounts = new HashMap<>();
|
||||
Company company = inventoryLine.getInventory().getCompany();
|
||||
Currency currency = inventoryLine.getInventory().getCompany().getCurrency();
|
||||
Partner partner = inventoryLine.getInventory().getCompany().getPartner();
|
||||
LocalDate moveDate = inventoryLine.getInventory().getPlannedEndDateT().toLocalDate();
|
||||
Journal journal = Beans.get(JournalRepository.class).find(10L);
|
||||
|
||||
Map<String, Account> accountMap = new HashMap<String, Account>();
|
||||
AccountManagement accountManagement =
|
||||
Beans.get(AccountManagementRepository.class)
|
||||
.all()
|
||||
.filter("self.product = ?1 and self.company = ?2", inventoryLine.getProduct(), company)
|
||||
.fetchOne();
|
||||
|
||||
if(accountManagement.getStockAccount() == null || accountManagement.getConsumptionAccount() == null){
|
||||
throw new AxelorException(
|
||||
inventoryLine,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.VENTILATE_STATE_6),
|
||||
inventoryLine.getProduct().getFullName());
|
||||
}
|
||||
|
||||
accountMap.put("stockAccount", accountManagement.getStockAccount());
|
||||
accountMap.put("consumptionAccount", accountManagement.getConsumptionAccount());
|
||||
|
||||
stockAccounts.put(inventoryLine, accountMap);
|
||||
|
||||
Move move =
|
||||
moveCreateService.createMove(
|
||||
journal,
|
||||
company,
|
||||
currency,
|
||||
partner,
|
||||
moveDate,
|
||||
null,
|
||||
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||
|
||||
int counter = 0;
|
||||
|
||||
|
||||
Account acc = stockAccounts.get(inventoryLine).get("consumptionAccount");
|
||||
Account acc2 = stockAccounts.get(inventoryLine).get("stockAccount");
|
||||
|
||||
if(inventoryLine.getJustifiedGap()){
|
||||
if(isGapPositive(inventoryLine)){
|
||||
acc = stockAccounts.get(inventoryLine).get("consumptionAccount");
|
||||
acc2 = stockAccounts.get(inventoryLine).get("stockAccount");
|
||||
}else if(!isGapPositive(inventoryLine)){
|
||||
acc = stockAccounts.get(inventoryLine).get("stockAccount");
|
||||
acc2 = stockAccounts.get(inventoryLine).get("consumptionAccount");
|
||||
}
|
||||
}else{
|
||||
if(isGapPositive(inventoryLine)){
|
||||
acc = Beans.get(AccountRepository.class).find(1360L);
|
||||
acc2 = stockAccounts.get(inventoryLine).get("stockAccount");
|
||||
}else if(!isGapPositive(inventoryLine)){
|
||||
acc = stockAccounts.get(inventoryLine).get("stockAccount");
|
||||
acc2 = Beans.get(AccountRepository.class).find(1400L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BigDecimal amountInCurrency = inventoryLine.getGapValue().multiply(inventoryLine.getGap());
|
||||
String description = inventoryLine.getInventory().getInventorySeq() + "-" + inventoryLine.getProduct().getCode();
|
||||
if (inventoryLine.getTrackingNumber() != null) {
|
||||
description += "-" + inventoryLine.getTrackingNumber().getTrackingNumberSeq();
|
||||
}
|
||||
|
||||
MoveLine moveLine =
|
||||
moveLineService.createMoveLine(
|
||||
move,
|
||||
partner,
|
||||
acc,
|
||||
amountInCurrency,
|
||||
isDebitInventoryLine(inventoryLine),
|
||||
moveDate,
|
||||
++counter,
|
||||
inventoryLine.getInventory().getInventorySeq(),
|
||||
description);
|
||||
moveLine.setDescription(description);
|
||||
moveLine.setDate(moveDate);
|
||||
moveLine.setDueDate(moveDate);
|
||||
moveLine.setAccountId(acc.getId());
|
||||
moveLine.setAccountCode(acc.getCode());
|
||||
moveLine.setAccountName(acc.getName());
|
||||
|
||||
MoveLine moveLine2 =
|
||||
moveLineService.createMoveLine(
|
||||
move,
|
||||
partner,
|
||||
acc2,
|
||||
amountInCurrency,
|
||||
!isDebitInventoryLine(inventoryLine),
|
||||
moveDate,
|
||||
++counter,
|
||||
inventoryLine.getInventory().getInventorySeq(),
|
||||
description);
|
||||
moveLine2.setDescription(description);
|
||||
moveLine2.setDate(moveDate);
|
||||
moveLine2.setDueDate(moveDate);
|
||||
moveLine2.setAccountId(acc2.getId());
|
||||
moveLine2.setAccountCode(acc2.getCode());
|
||||
moveLine2.setAccountName(acc2.getName());
|
||||
|
||||
|
||||
|
||||
move.addMoveLineListItem(moveLine);
|
||||
move.addMoveLineListItem(moveLine2);
|
||||
move.setInventoryLine(inventoryLine);
|
||||
inventoryLine.setIsVentilated(true);
|
||||
|
||||
move.setIgnoreInAccountingOk(false);
|
||||
move.setStatusSelect(MoveRepository.STATUS_DAYBOOK);
|
||||
return move;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List<Long> massGenerationInventoryLineMove(List<Long> ids) throws AxelorException {
|
||||
|
||||
List<Long> movesId = new ArrayList<>();
|
||||
|
||||
for (Long id : ids) {
|
||||
InventoryLine line = Beans.get(InventoryLineRepository.class).find(id);
|
||||
Move move = this.generateInventoryLineMove(line);
|
||||
movesId.add(move.getId());
|
||||
}
|
||||
return movesId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public boolean isPurchase(StockMove stockMove){
|
||||
// boolean isPurchase;
|
||||
// Partner partner = stockMove.getPartner() ;
|
||||
// if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING && stockMove.getPartner()
|
||||
// == stockMove.getCompany().getPartner()) {
|
||||
// isPurchase = false;
|
||||
// }
|
||||
// else if(stockMove.getTypeSelect() == StockMoveRepository.TYPE_INCOMING &&
|
||||
// stockMove.getPartner() != stockMove.getCompany().getPartner()){
|
||||
// isPurchase = true;
|
||||
// }else if(stockMove.getTypeSelect() == StockMoveRepository.TYPE_OUTGOING &&
|
||||
// stockMove.getPartner() == stockMove.getCompany().getPartner()){
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -179,14 +179,23 @@ public class BudgetSupplychainService extends BudgetService {
|
||||
return;
|
||||
}
|
||||
|
||||
purchaseOrderLineList
|
||||
.stream()
|
||||
.flatMap(x -> x.getBudgetDistributionList().stream())
|
||||
.forEach(
|
||||
budgetDistribution -> {
|
||||
Budget budget = budgetDistribution.getBudget();
|
||||
updateLines(budget);
|
||||
computeTotalAmountCommitted(budget);
|
||||
});
|
||||
}
|
||||
boolean idbudgetDistExist = true;
|
||||
for (PurchaseOrderLine line : purchaseOrderLineList) {
|
||||
if(line.getBudgetDistributionList() == null){
|
||||
idbudgetDistExist = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(idbudgetDistExist){
|
||||
purchaseOrderLineList
|
||||
.stream()
|
||||
.flatMap(x -> x.getBudgetDistributionList().stream())
|
||||
.forEach(
|
||||
budgetDistribution -> {
|
||||
Budget budget = budgetDistribution.getBudget();
|
||||
updateLines(budget);
|
||||
computeTotalAmountCommitted(budget);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
package com.axelor.apps.supplychain.service;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.MalformedURLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.axelor.apps.account.db.Account;
|
||||
import com.axelor.apps.account.db.Invoice;
|
||||
import com.axelor.apps.account.db.InvoiceLine;
|
||||
import com.axelor.apps.account.db.InvoiceTemplate;
|
||||
import com.axelor.apps.account.db.PaymentVoucher;
|
||||
import com.axelor.apps.account.db.TaxLine;
|
||||
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||
import com.axelor.apps.account.db.repo.InvoiceLineRepository;
|
||||
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||
import com.axelor.apps.account.db.repo.PaymentVoucherRepository;
|
||||
import com.axelor.apps.account.db.repo.TaxLineRepository;
|
||||
import com.axelor.apps.account.service.InvoiceTemplateService;
|
||||
import com.axelor.apps.account.service.invoice.InvoiceLineServiceImpl;
|
||||
import com.axelor.apps.account.service.invoice.InvoiceServiceImpl;
|
||||
import com.axelor.apps.account.service.invoice.generator.InvoiceLineGenerator;
|
||||
import com.axelor.apps.account.service.payment.paymentvoucher.PaymentVoucherConfirmService;
|
||||
import com.axelor.apps.base.db.Product;
|
||||
import com.axelor.apps.base.db.Wizard;
|
||||
import com.axelor.apps.base.db.repo.ProductRepository;
|
||||
import com.axelor.apps.purchase.db.ImportationFolder;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrder;
|
||||
import com.axelor.apps.stock.db.ImportationFolderCostPrice;
|
||||
import com.axelor.apps.stock.db.StockLocation;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrderLine;
|
||||
import com.axelor.apps.stock.db.repo.ImportationFolderCostPriceRepository;
|
||||
import com.axelor.apps.purchase.db.repo.ImportationFolderRepository;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderLineRepository;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderLineService;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderService;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.supplychain.service.invoice.generator.InvoiceLineGeneratorSupplyChain;
|
||||
import com.axelor.auth.AuthUtils;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.schema.actions.ActionView;
|
||||
import com.axelor.meta.schema.actions.ActionView.ActionViewBuilder;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
|
||||
import wslite.json.JSONException;
|
||||
|
||||
public class ImportationFolderServiceImpl {
|
||||
|
||||
@Inject protected ImportationFolderRepository importationFolderRepository;
|
||||
private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
|
||||
@Transactional
|
||||
public List<Long> calculateAvgPriceAndGenerateInvoice(List<StockMoveLine> stockMoveLines, ImportationFolder importationFolder)
|
||||
throws MalformedURLException, JSONException, AxelorException {
|
||||
|
||||
Set<StockMove> stockMovesSet = new HashSet<>();
|
||||
HashMap<String,List<StockMove>> stockMovesMap = new HashMap<>();
|
||||
|
||||
for (StockMoveLine stockMoveLine : stockMoveLines) {
|
||||
stockMovesSet.add(stockMoveLine.getStockMove());
|
||||
}
|
||||
|
||||
List<Long> invoiceIds = new ArrayList<>();
|
||||
|
||||
for (StockMove stockMove : stockMovesSet) {
|
||||
// Use the 'ref' as the key, and add the object to the corresponding list
|
||||
stockMovesMap
|
||||
.computeIfAbsent(stockMove.getSupplierShipmentRef(), k -> new ArrayList<>())
|
||||
.add(stockMove);
|
||||
}
|
||||
|
||||
stockMovesMap.forEach((ref, stockMoveList) -> {
|
||||
|
||||
// List<StockMove> stockMoveList = new ArrayList<>(stockMovesSet);
|
||||
if(stockMoveList.size() > 0) {
|
||||
|
||||
Optional<Invoice> invoiceOpt;
|
||||
try {
|
||||
invoiceOpt = Beans.get(StockMoveMultiInvoiceService.class).createInvoiceFromMultiIncomingStockMove(stockMoveList);
|
||||
|
||||
Invoice invoice = invoiceOpt.get();
|
||||
Product product = Beans.get(ProductRepository.class).find(8931L);
|
||||
BigDecimal freightPrice = importationFolder.getFreight();
|
||||
StockLocation stockLocation = importationFolder.getStockMoveLineList().get(0).getStockMove().getToStockLocation();
|
||||
TaxLine taxLine = null;
|
||||
if(stockLocation.getId() == 61 || stockLocation.getId() == 60){
|
||||
taxLine = Beans.get(TaxLineRepository.class).find(27L);
|
||||
}else{
|
||||
if(importationFolder.getStockMoveLineList().get(0).getPurchaseOrderLine() == null){
|
||||
throw new AxelorException(
|
||||
importationFolder,
|
||||
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||
"Purchase order missing",
|
||||
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION));
|
||||
}
|
||||
|
||||
taxLine = importationFolder.getStockMoveLineList().get(0).getPurchaseOrderLine().getTaxLine();
|
||||
}
|
||||
|
||||
|
||||
InvoiceLineGenerator invoiceLineGenerator =
|
||||
new InvoiceLineGeneratorSupplyChain(
|
||||
invoice,
|
||||
product,
|
||||
product.getName(),
|
||||
freightPrice,
|
||||
freightPrice,
|
||||
freightPrice,
|
||||
"",
|
||||
BigDecimal.ONE,
|
||||
product.getUnit(),
|
||||
taxLine,
|
||||
100,
|
||||
BigDecimal.ZERO,
|
||||
0,
|
||||
freightPrice,
|
||||
freightPrice,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
null) {
|
||||
@Override
|
||||
public List<InvoiceLine> creates() throws AxelorException {
|
||||
|
||||
InvoiceLine invoiceLine = this.createInvoiceLine();
|
||||
invoiceLine.setPrice(stockMoveList.get(0).getStockMoveLineList().get(0).getFreight());
|
||||
Long categoryId = importationFolder.getStockMoveLineList().get(0).getProduct().getFamilleProduit().getId();
|
||||
Account account = null;
|
||||
switch (categoryId.intValue()) {
|
||||
case 67:
|
||||
account= Beans.get(AccountRepository.class).find(1430L);
|
||||
break;
|
||||
case 68:
|
||||
account= Beans.get(AccountRepository.class).find(1430L);
|
||||
break;
|
||||
case 59:
|
||||
account= Beans.get(AccountRepository.class).find(1431L);
|
||||
break;
|
||||
default:
|
||||
account= Beans.get(AccountRepository.class).find(1431L);
|
||||
break;
|
||||
}
|
||||
invoiceLine.setAccount(account);
|
||||
List<InvoiceLine> invoiceLines = new ArrayList<InvoiceLine>();
|
||||
invoiceLines.add(invoiceLine);
|
||||
|
||||
return invoiceLines;
|
||||
}
|
||||
};
|
||||
|
||||
List<InvoiceLine> invoiceLines = invoiceLineGenerator.creates();
|
||||
invoice.addInvoiceLineListItem(invoiceLines.get(0));
|
||||
|
||||
logger.debug("invoice.getInvoiceLineList() ********** ",invoice.getInvoiceLineList());
|
||||
|
||||
BigDecimal inTaxTotal = BigDecimal.ZERO;
|
||||
BigDecimal exTaxTotal = BigDecimal.ZERO;
|
||||
BigDecimal taxTotal = BigDecimal.ZERO;
|
||||
|
||||
for (InvoiceLine invoiceLine : invoice.getInvoiceLineList()) {
|
||||
BigDecimal currencyRate = BigDecimal.ZERO;
|
||||
// if(invoiceLine.getProduct().getId() == product.getId()){
|
||||
currencyRate = importationFolder.getStockMoveLineList().get(0).getCurrencyRate();
|
||||
// }else{
|
||||
// currencyRate = invoiceLine.getStockMoveLine().getCurrencyRate();
|
||||
// }
|
||||
|
||||
inTaxTotal = inTaxTotal.add(invoiceLine.getInTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
exTaxTotal = exTaxTotal.add(invoiceLine.getExTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
taxTotal = taxTotal.add(inTaxTotal.subtract(exTaxTotal));
|
||||
|
||||
BigDecimal price = (invoiceLine.getPrice().multiply(currencyRate)).setScale(2,RoundingMode.HALF_UP);
|
||||
|
||||
invoiceLine.setPrice(price);
|
||||
invoiceLine.setPriceDiscounted(invoiceLine.getPriceDiscounted().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
invoiceLine.setInTaxTotal(invoiceLine.getInTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
invoiceLine.setExTaxTotal(invoiceLine.getExTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
invoiceLine.setInTaxPrice(invoiceLine.getInTaxPrice().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
invoiceLine.setCompanyExTaxTotal(invoiceLine.getCompanyExTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
invoiceLine.setCompanyInTaxTotal(invoiceLine.getCompanyInTaxTotal().multiply(currencyRate).setScale(2,RoundingMode.HALF_UP));
|
||||
|
||||
Beans.get(InvoiceLineRepository.class).save(invoiceLine);
|
||||
|
||||
logger.debug("currencyRate****** {}",currencyRate);
|
||||
logger.debug("Invoice line in importation folder {}",invoiceLine.toString());
|
||||
|
||||
}
|
||||
|
||||
invoice.setInTaxTotal(inTaxTotal);
|
||||
invoice.setExTaxTotal(exTaxTotal);
|
||||
invoice.setCompanyExTaxTotal(exTaxTotal);
|
||||
invoice.setCompanyInTaxTotal(inTaxTotal);
|
||||
invoice.setAmountRemaining(inTaxTotal);
|
||||
invoice.setCurrency(invoice.getCompany().getCurrency());
|
||||
invoice.setTaxTotal(taxTotal);
|
||||
invoice.setImportationFolder(importationFolder);
|
||||
invoice.setIsImportationPartnerInvoice(true);
|
||||
|
||||
importationFolder.setInvoicedFolder(true);
|
||||
|
||||
Invoice generatedInvoice = Beans.get(InvoiceRepository.class).save(invoice);
|
||||
invoiceIds.add(generatedInvoice.getId());
|
||||
} catch (AxelorException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
return invoiceIds;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String computeCostPrice(ImportationFolder importationFolder) {
|
||||
|
||||
List<StockMoveLine> stockMoveLines = importationFolder.getStockMoveLineList();
|
||||
String message = "";
|
||||
BigDecimal costPrice = BigDecimal.ZERO;
|
||||
Set<Product> productSet = new HashSet<>();
|
||||
|
||||
|
||||
for (StockMoveLine line : stockMoveLines) {
|
||||
productSet.add(line.getProduct());
|
||||
}
|
||||
|
||||
|
||||
this.resetCostPriceList(importationFolder);
|
||||
|
||||
if(productSet.size() > 1) {
|
||||
List<Invoice> supplierInvoices = importationFolder.getInvoices().stream().filter(t -> t.getIsImportationPartnerInvoice()).collect(Collectors.toList());
|
||||
// BigDecimal totalQty = stockMoveLines.stream().map(StockMoveLine::getRealQty).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal totalNetMass = stockMoveLines.stream().map(StockMoveLine::getNetMass).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal totalVolume = stockMoveLines.stream().map(StockMoveLine::getVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal freight = importationFolder.getFreight().multiply(stockMoveLines.get(0).getCurrencyRate()).setScale(2,RoundingMode.HALF_EVEN);
|
||||
|
||||
Map<Product,Double> splitting = new HashMap<>();
|
||||
Map<Product,Double> splittingQty = new HashMap<>();
|
||||
List<InvoiceLine> invoiceLines = new ArrayList<>();
|
||||
BigDecimal totalInvoiceWithoutFreight = BigDecimal.ZERO;
|
||||
BigDecimal totalQty = BigDecimal.ZERO;
|
||||
|
||||
for (Invoice supplierInvoice : supplierInvoices) {
|
||||
BigDecimal freightInvoice = BigDecimal.ZERO;
|
||||
Optional<InvoiceLine> invoiceLine = supplierInvoice.getInvoiceLineList().stream().filter(t -> t.getProduct().getId() == 8931L).findAny();
|
||||
if(invoiceLine.isPresent()){
|
||||
freightInvoice = invoiceLine.get().getInTaxTotal();
|
||||
}
|
||||
BigDecimal invoiceWithoutFreight = supplierInvoice.getInTaxTotal().subtract(freightInvoice).setScale(2, RoundingMode.HALF_EVEN);
|
||||
totalInvoiceWithoutFreight = totalInvoiceWithoutFreight.add(invoiceWithoutFreight);
|
||||
invoiceLines.addAll(supplierInvoice.getInvoiceLineList());
|
||||
// total qty without freight qty = 1
|
||||
}
|
||||
totalQty =invoiceLines.stream().filter(t -> t.getProduct().getId() != 8931L).map(InvoiceLine::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
splittingQty = invoiceLines.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
t -> t.getProduct(),
|
||||
Collectors.summingDouble(o -> o.getQty().doubleValue())));
|
||||
|
||||
if(importationFolder.getValorisation() == 1){
|
||||
splitting = invoiceLines.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
t -> t.getProduct(),
|
||||
Collectors.summingDouble(o -> o.getInTaxTotal().doubleValue())));
|
||||
}else if(importationFolder.getValorisation() == 2){
|
||||
splitting = invoiceLines.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
t -> t.getProduct(),
|
||||
Collectors.summingDouble(o -> o.getQty().doubleValue())));
|
||||
}else if(importationFolder.getValorisation() == 3){
|
||||
splitting = stockMoveLines.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
t -> t.getProduct(),
|
||||
Collectors.summingDouble(o -> o.getNetMass().doubleValue())));
|
||||
|
||||
}else if(importationFolder.getValorisation() == 4){
|
||||
splitting = stockMoveLines.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
t -> t.getProduct(),
|
||||
Collectors.summingDouble(o -> o.getVolume().doubleValue())));
|
||||
}
|
||||
|
||||
List<Invoice> invoices = importationFolder.getInvoices().stream().filter(t -> !t.getIsImportationPartnerInvoice()).collect(Collectors.toList());
|
||||
BigDecimal totalApproachs = invoices.stream().map(Invoice::getInTaxTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
|
||||
for (Product product : productSet) {
|
||||
Stream<InvoiceLine> invoiceLineStream = invoiceLines.stream().filter(t -> t.getProduct() == product);
|
||||
|
||||
BigDecimal productQty = new BigDecimal(splitting.get(product));
|
||||
BigDecimal productQty2 = new BigDecimal(splittingQty.get(product));
|
||||
BigDecimal freightSplit = BigDecimal.ZERO;
|
||||
// BigDecimal freightPerInvoiceForProduct= invoiceLineStream.findFirst().get().getInvoice().getInvoiceLineList().stream().filter(t -> t.getProduct().getId() == 8931L).findFirst().get().getInTaxTotal();
|
||||
|
||||
// total per product
|
||||
BigDecimal totalInvoiceProduct = invoiceLineStream.map(InvoiceLine::getInTaxTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
BigDecimal percent = BigDecimal.ZERO;
|
||||
|
||||
if(totalInvoiceWithoutFreight.compareTo(BigDecimal.ZERO) == 0){
|
||||
percent = productQty.divide(totalQty,10,RoundingMode.HALF_EVEN);
|
||||
}else{
|
||||
switch (importationFolder.getValorisation()) {
|
||||
case 1:
|
||||
percent = totalInvoiceProduct.divide(totalInvoiceWithoutFreight,10,RoundingMode.HALF_EVEN);
|
||||
break;
|
||||
case 2:
|
||||
percent = productQty.divide(totalQty,2,RoundingMode.HALF_EVEN);
|
||||
break;
|
||||
case 3:
|
||||
percent = productQty.divide(totalNetMass,2,RoundingMode.HALF_EVEN);
|
||||
break;
|
||||
case 4:
|
||||
percent = productQty.divide(totalVolume,2,RoundingMode.HALF_EVEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freightSplit = freight.multiply(percent).setScale(2, RoundingMode.HALF_EVEN);
|
||||
|
||||
BigDecimal totalApproachsPerProduct = totalApproachs.multiply(percent).setScale(2, RoundingMode.HALF_EVEN);
|
||||
|
||||
BigDecimal allPerProduct = totalApproachsPerProduct.add(totalInvoiceProduct).add(freightSplit);
|
||||
|
||||
System.out.println("---------------------------------------------------------------------");
|
||||
System.out.println("allPerProduct *************"+allPerProduct.toString());
|
||||
System.out.println("totalApproachsPerProduct *************"+totalApproachsPerProduct.toString());
|
||||
System.out.println("totalInvoiceProduct *************"+totalInvoiceProduct.toString());
|
||||
System.out.println("freightSplit *************"+freightSplit.toString());
|
||||
System.out.println("productQty2 *************"+productQty2.toString());
|
||||
System.out.println("---------------------------------------------------------------------");
|
||||
|
||||
costPrice = allPerProduct.divide(productQty2,10, RoundingMode.HALF_EVEN);
|
||||
|
||||
message += "Cost price of " + product.getName() + " is " + costPrice + " || ";
|
||||
|
||||
List<StockMoveLine> lines = stockMoveLines.stream().filter(t -> t.getProduct() == product).collect(Collectors.toList());
|
||||
for (StockMoveLine line : lines) {
|
||||
this.computeCostPriceAndPersist(importationFolder, line, freightSplit,percent, totalInvoiceProduct,totalInvoiceProduct,costPrice);
|
||||
}
|
||||
|
||||
}
|
||||
}else{
|
||||
|
||||
List<Invoice> invoices = importationFolder.getInvoices();
|
||||
BigDecimal inTaxTotal = invoices.stream().map(Invoice::getInTaxTotal).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2,RoundingMode.HALF_UP);
|
||||
BigDecimal totalQty = stockMoveLines.stream().map(StockMoveLine::getRealQty).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
costPrice = inTaxTotal.divide(totalQty,10, RoundingMode.HALF_UP);
|
||||
|
||||
// this.resetCostPriceList(importationFolder);
|
||||
|
||||
for (StockMoveLine stockMoveLine : stockMoveLines) {
|
||||
this.computeCostPriceAndPersist(importationFolder, stockMoveLine,null,null,null,null, costPrice);
|
||||
}
|
||||
|
||||
message = "CostPrice is : " + costPrice.toString();
|
||||
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void setStockMoveLineCurrenyRate(List<StockMoveLine> stockMoveLineList, BigDecimal currencyRate) {
|
||||
for (StockMoveLine stockMoveLine : stockMoveLineList) {
|
||||
stockMoveLine.setCurrencyRate(currencyRate);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setStockMoveLineFreight(List<StockMoveLine> stockMoveLineList, BigDecimal freight) {
|
||||
for (StockMoveLine stockMoveLine : stockMoveLineList) {
|
||||
stockMoveLine.setFreight(freight);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void resetCostPriceList(ImportationFolder importationFolder){
|
||||
importationFolder.getImportationFolderCostPriceList().clear();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void computeCostPriceAndPersist(ImportationFolder importationFolder,StockMoveLine stockMoveLine,BigDecimal freightSplit,BigDecimal precent,BigDecimal totalApproachsPerProduct,BigDecimal totalInvoiceProduct,BigDecimal costPrice) {
|
||||
|
||||
ImportationFolderCostPrice importationFolderCostPrice = new ImportationFolderCostPrice();
|
||||
importationFolderCostPrice.setImportationFolder(importationFolder);
|
||||
importationFolderCostPrice.setStockMoveLine(stockMoveLine);
|
||||
importationFolderCostPrice.setCostPrice(costPrice);
|
||||
importationFolderCostPrice.setValorisation(importationFolder.getValorisation());
|
||||
importationFolderCostPrice.setPercent(precent);
|
||||
importationFolderCostPrice.setFreightSplit(freightSplit);
|
||||
importationFolderCostPrice.setTotalApproach(totalApproachsPerProduct);
|
||||
importationFolderCostPrice.setTotalInvoice(totalInvoiceProduct);
|
||||
importationFolderCostPrice.setProduct(stockMoveLine.getProduct());
|
||||
importationFolder.addImportationFolderCostPriceListItem(importationFolderCostPrice);
|
||||
importationFolderRepository.save(importationFolder);
|
||||
}
|
||||
|
||||
|
||||
// public void valisateCostPrice(ActionRequest request, ActionResponse response) {
|
||||
@Transactional
|
||||
public void validateCostPrice(ImportationFolderCostPrice importationFolderCostPrice) {
|
||||
|
||||
ImportationFolderCostPriceRepository importationFolderCostPriceRepository = Beans.get(ImportationFolderCostPriceRepository.class);
|
||||
|
||||
StockMove stockMove = importationFolderCostPrice.getStockMoveLine().getStockMove();
|
||||
Long productId = importationFolderCostPrice.getProduct().getId();
|
||||
Long stockMoveId = stockMove.getId();
|
||||
LocalDate toDate = LocalDate.now();
|
||||
BigDecimal costPrice = importationFolderCostPrice.getCostPrice();
|
||||
|
||||
try {
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).resetValorization(productId, stockMoveId, toDate,false);
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).fillStockMoveLines(productId, toDate, stockMoveId,false);
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).valorize(productId, stockMoveId, toDate, costPrice,false,false);
|
||||
importationFolderCostPrice.setStatusSelect(2);
|
||||
importationFolderCostPrice.setValidationDate(LocalDate.now());
|
||||
importationFolderCostPriceRepository.save(importationFolderCostPrice);
|
||||
// response.setReload(true);
|
||||
} catch (Exception e) {
|
||||
logger.debug(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void setStockMoveLineNetMass(List<StockMoveLine> stockMoveLineList, BigDecimal netMass) {
|
||||
for (StockMoveLine stockMoveLine : stockMoveLineList) {
|
||||
stockMoveLine.setNetMass(netMass);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setStockMoveLineVolume(List<StockMoveLine> stockMoveLineList, BigDecimal volume) {
|
||||
for (StockMoveLine stockMoveLine : stockMoveLineList) {
|
||||
stockMoveLine.setVolume(volume);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void rejectImportationFolder(ImportationFolder importationFolder, String rejectionRaison) {
|
||||
|
||||
importationFolder.setStatusSelect(ImportationFolderRepository.STATUS_REJECTED);
|
||||
importationFolder.setRejectionRaison(rejectionRaison);
|
||||
importationFolder.setRejectedDate(LocalDate.now());
|
||||
importationFolder.setRejectedByUser(AuthUtils.getUser());
|
||||
importationFolder.setRejectedInstanceSelect(1);
|
||||
importationFolderRepository.save(importationFolder);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Invoice generateFromModel(ImportationFolder importationFolder,InvoiceTemplate invoiceTemplate) throws AxelorException{
|
||||
Invoice invoice = Beans.get(InvoiceTemplateService.class).generateInvoiceFromTemplate(invoiceTemplate);
|
||||
invoice.setImportationFolder(importationFolder);
|
||||
invoice.setIsInvoiceApproach(true);
|
||||
return Beans.get(InvoiceRepository.class).save(invoice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ public class MrpLineServiceImpl implements MrpLineService {
|
||||
maturityDate,
|
||||
"MRP-" + appBaseService.getTodayDate().toString(), // TODO sequence on mrp
|
||||
null,
|
||||
"",
|
||||
stockLocation,
|
||||
appBaseService.getTodayDate(),
|
||||
Beans.get(PartnerPriceListService.class)
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
*/
|
||||
package com.axelor.apps.supplychain.service;
|
||||
|
||||
import com.axelor.apps.base.db.ABCAnalysis;
|
||||
import com.axelor.apps.base.db.ABCAnalysisLine;
|
||||
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.db.repo.ABCAnalysisLineRepository;
|
||||
import com.axelor.apps.base.db.repo.ABCAnalysisRepository;
|
||||
import com.axelor.apps.base.db.repo.ProductRepository;
|
||||
import com.axelor.apps.base.service.UnitConversionService;
|
||||
import com.axelor.apps.base.service.app.AppBaseService;
|
||||
@@ -46,18 +50,23 @@ 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.MrpLineSaleAndMargin;
|
||||
import com.axelor.apps.supplychain.db.MrpLineSophal;
|
||||
import com.axelor.apps.supplychain.db.MrpLineType;
|
||||
import com.axelor.apps.supplychain.db.ProductionMasterPlan;
|
||||
import com.axelor.apps.supplychain.db.SalesMasterPlan;
|
||||
import com.axelor.apps.supplychain.db.repo.MrpForecastRepository;
|
||||
import com.axelor.apps.supplychain.db.repo.MrpLineRepository;
|
||||
import com.axelor.apps.supplychain.db.repo.MrpLineSaleAndMarginRepository;
|
||||
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.db.repo.ProductionMasterPlanRepository;
|
||||
import com.axelor.apps.supplychain.db.repo.SalesMasterPlanRepository;
|
||||
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;
|
||||
@@ -71,12 +80,17 @@ import java.lang.invoke.MethodHandles;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.time.format.TextStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
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;
|
||||
@@ -106,6 +120,8 @@ public class MrpServiceImpl implements MrpService {
|
||||
protected Map<Long, Double> productQty;
|
||||
protected Mrp mrp;
|
||||
protected LocalDate today;
|
||||
public List<MrpForecast> mrpForecastListAll;
|
||||
|
||||
|
||||
@Inject
|
||||
public MrpServiceImpl(
|
||||
@@ -181,7 +197,9 @@ public class MrpServiceImpl implements MrpService {
|
||||
public void resetSophalLine(Mrp mrp) {
|
||||
|
||||
Beans.get(MrpLineSophalRepository.class).all().filter("self.mrp.id = ?1", mrp.getId()).remove();
|
||||
|
||||
Beans.get(MrpLineSaleAndMarginRepository.class).all().filter("self.mrp.id = ?1", mrp.getId()).remove();
|
||||
Beans.get(SalesMasterPlanRepository.class).all().filter("self.mrp.id = ?1", mrp.getId()).remove();
|
||||
Beans.get(ProductionMasterPlanRepository.class).all().filter("self.mrp.id = ?1", mrp.getId()).remove();
|
||||
|
||||
mrp.setStatusSelect(MrpRepository.STATUS_DRAFT);
|
||||
|
||||
@@ -1113,11 +1131,11 @@ public class MrpServiceImpl implements MrpService {
|
||||
|
||||
return mrp;
|
||||
}
|
||||
|
||||
|
||||
public void createAvailableMrpLineSophal(Mrp mrp) throws AxelorException {
|
||||
this.resetSophalLine(mrp);
|
||||
today = appBaseService.getTodayDate();
|
||||
LocalDate endDate = mrp.getEndDate();
|
||||
|
||||
Set<StockLocation> slList2 = Sets.newHashSet();
|
||||
this.mrp = mrp;
|
||||
@@ -1128,17 +1146,31 @@ public class MrpServiceImpl implements MrpService {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.productQty = new HashMap<>();
|
||||
|
||||
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())));
|
||||
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());
|
||||
@@ -1150,91 +1182,413 @@ public class MrpServiceImpl implements MrpService {
|
||||
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());
|
||||
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());
|
||||
|
||||
mrpForecastListAll = new ArrayList<>();
|
||||
|
||||
|
||||
mrpForecastListAll.addAll( mrpForecastRepository
|
||||
.all()
|
||||
.filter(
|
||||
"self.product.id in (?1) AND self.stockLocation in (?2) AND self.statusSelect = ?3 AND self.forecastDate < ?4",
|
||||
this.productMap.keySet(),
|
||||
slList2.stream().collect(Collectors.toList()),
|
||||
MrpForecastRepository.STATUS_CONFIRMED,
|
||||
LocalDate.parse(String.valueOf(LocalDate.now().getYear())+"-01-01")
|
||||
)
|
||||
.order("monthSelect")
|
||||
.fetch());
|
||||
|
||||
log.debug(mrpForecastList.toString());
|
||||
}
|
||||
|
||||
for (Map.Entry<Long, Double> 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);
|
||||
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<MrpForecast> mrpForecastList, Map<Long, Double> 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;
|
||||
}
|
||||
public void createMrpLineSophal(
|
||||
Mrp mrp,
|
||||
Product product,
|
||||
Unit unit,
|
||||
BigDecimal qty,
|
||||
List<MrpForecast> mrpForecastList,
|
||||
Map<Long, Double> productQty)
|
||||
throws AxelorException {
|
||||
|
||||
MrpLineSophal mrpLineSophal = new MrpLineSophal();
|
||||
mrpLineSophal.setQty(qty);
|
||||
BigDecimal reelQty = qty;
|
||||
BigDecimal sumQty = BigDecimal.ZERO;
|
||||
Collections.sort(mrpForecastList, Comparator.comparingInt(MrpForecast ::getMonthSelect));
|
||||
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());
|
||||
}
|
||||
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();
|
||||
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);
|
||||
mrpLineSophal.setSecurityStock(
|
||||
sumQty.divide(new BigDecimal(totalForecast), 5, RoundingMode.HALF_EVEN));
|
||||
Beans.get(MrpLineSophalRepository.class).save(mrpLineSophal);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void createMargeAndSaleLineSophal(
|
||||
Mrp mrp,
|
||||
Product product,
|
||||
List<MrpForecast> mrpForecastList,
|
||||
BigDecimal qty
|
||||
)
|
||||
throws AxelorException {
|
||||
|
||||
MrpLineSaleAndMargin mrpLineSaleAndMargin = new MrpLineSaleAndMargin();
|
||||
|
||||
ArrayList<Integer> lastThreeMonths = new ArrayList<>();
|
||||
lastThreeMonths.add(10);
|
||||
lastThreeMonths.add(11);
|
||||
lastThreeMonths.add(12);
|
||||
BigDecimal totalLastThree = BigDecimal.ZERO;
|
||||
BigDecimal avgLastThree = BigDecimal.ZERO;
|
||||
|
||||
|
||||
totalLastThree = mrpForecastList.stream().filter(t -> (t.getForecastDate().getYear() == (LocalDate.now().getYear() - 1)) && (t.getProduct().getId() == product.getId()) && lastThreeMonths.contains(t.getMonthSelect())).map(MrpForecast::getQty)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
|
||||
avgLastThree = totalLastThree.divide(new BigDecimal("3"),2,RoundingMode.HALF_UP);
|
||||
|
||||
log.debug("******* mrpForecastList {}",mrpForecastList);
|
||||
log.debug("******* lastThreeMonths {}",lastThreeMonths);
|
||||
log.debug("******* totalLastThree {}",totalLastThree);
|
||||
log.debug("******* avgLastThree {}",avgLastThree);
|
||||
|
||||
BigDecimal maxJan = getMaxOfMonth(1, product, mrpForecastList);
|
||||
BigDecimal maxFeb = getMaxOfMonth(2, product, mrpForecastList);
|
||||
BigDecimal maxMar = getMaxOfMonth(3, product, mrpForecastList);
|
||||
BigDecimal maxApril = getMaxOfMonth(4, product, mrpForecastList);
|
||||
BigDecimal maxMay = getMaxOfMonth(5, product, mrpForecastList);
|
||||
BigDecimal maxJune = getMaxOfMonth(6, product, mrpForecastList);
|
||||
BigDecimal maxJuly = getMaxOfMonth(7, product, mrpForecastList);
|
||||
BigDecimal maxAugust = getMaxOfMonth(8, product, mrpForecastList);
|
||||
BigDecimal maxSep = getMaxOfMonth(9, product, mrpForecastList);
|
||||
BigDecimal maxOct = getMaxOfMonth(10, product, mrpForecastList);
|
||||
BigDecimal maxNov = getMaxOfMonth(11, product, mrpForecastList);
|
||||
BigDecimal maxDec = getMaxOfMonth(12, product, mrpForecastList);
|
||||
|
||||
BigDecimal maxFirstQuarter = maxJan.add(maxFeb).add(maxMar).divide(new BigDecimal("3"), RoundingMode.HALF_UP);
|
||||
BigDecimal maxSecQuarter = maxJune.add(maxApril).add(maxMay).divide(new BigDecimal("3"), RoundingMode.HALF_UP);
|
||||
BigDecimal maxthirdQuarter = maxSep.add(maxJuly).add(maxAugust).divide(new BigDecimal("3"), RoundingMode.HALF_UP);
|
||||
BigDecimal maxforthQuarter = maxOct.add(maxNov).add(maxDec).divide(new BigDecimal("3"), RoundingMode.HALF_UP);
|
||||
|
||||
|
||||
if(maxFirstQuarter.compareTo(avgLastThree) > 0){
|
||||
mrpLineSaleAndMargin.setFirstQuarterMax(maxFirstQuarter);
|
||||
}else{
|
||||
maxFirstQuarter = avgLastThree;
|
||||
mrpLineSaleAndMargin.setFirstQuarterMax(maxFirstQuarter);
|
||||
}
|
||||
|
||||
|
||||
mrpLineSaleAndMargin.setSecondQuarterMax(maxSecQuarter);
|
||||
mrpLineSaleAndMargin.setThirdQuarterMax(maxthirdQuarter);
|
||||
mrpLineSaleAndMargin.setForthQuarterMax(maxforthQuarter);
|
||||
|
||||
String className = "";
|
||||
List<ABCAnalysisLine> abcAnalysisLines = Beans.get(ABCAnalysisLineRepository.class).all().fetch();
|
||||
ABCAnalysisLine abcAnalysisLine = abcAnalysisLines.stream().filter(t -> t.getProduct() == product).findFirst().get();
|
||||
if(abcAnalysisLine == null) {
|
||||
throw new AxelorException(
|
||||
mrp,
|
||||
TraceBackRepository.CATEGORY_NO_VALUE,
|
||||
"ABC classification needed");
|
||||
}else{
|
||||
className = abcAnalysisLine.getAbcAnalysisClass().getName();
|
||||
}
|
||||
|
||||
|
||||
BigDecimal firstQuarterMargin = BigDecimal.ZERO;
|
||||
BigDecimal secondQuarterMargin = BigDecimal.ZERO;
|
||||
BigDecimal thirdQuarterMargin = BigDecimal.ZERO;
|
||||
BigDecimal fourthQuarterMargin = BigDecimal.ZERO;
|
||||
|
||||
switch (className) {
|
||||
case "A":
|
||||
firstQuarterMargin = maxFirstQuarter.add(maxFirstQuarter.multiply(new BigDecimal("0.15")));
|
||||
secondQuarterMargin = maxSecQuarter.add(maxSecQuarter.multiply(new BigDecimal("0.20"))) ;
|
||||
thirdQuarterMargin = maxthirdQuarter.add(maxthirdQuarter.multiply(new BigDecimal("0.15")));
|
||||
fourthQuarterMargin = maxforthQuarter.add(maxforthQuarter.multiply(new BigDecimal("0.15")));
|
||||
|
||||
break;
|
||||
case "B":
|
||||
firstQuarterMargin = maxFirstQuarter.add(maxFirstQuarter.multiply(new BigDecimal("0.10")));
|
||||
secondQuarterMargin = maxSecQuarter.add(maxSecQuarter.multiply(new BigDecimal("0.10"))) ;
|
||||
thirdQuarterMargin = maxthirdQuarter.add(maxthirdQuarter.multiply(new BigDecimal("0.10")));
|
||||
fourthQuarterMargin = maxforthQuarter.add(maxforthQuarter.multiply(new BigDecimal("0.10")));
|
||||
break;
|
||||
case "C":
|
||||
firstQuarterMargin = maxFirstQuarter.add(maxFirstQuarter.multiply(new BigDecimal("0.05")));
|
||||
secondQuarterMargin = maxSecQuarter.add(maxSecQuarter.multiply(new BigDecimal("0.05"))) ;
|
||||
thirdQuarterMargin = maxthirdQuarter.add(maxthirdQuarter.multiply(new BigDecimal("0.05")));
|
||||
fourthQuarterMargin = maxforthQuarter.add(maxforthQuarter.multiply(new BigDecimal("0.05")));
|
||||
break;
|
||||
default:
|
||||
firstQuarterMargin = maxFirstQuarter;
|
||||
secondQuarterMargin = maxSecQuarter;
|
||||
thirdQuarterMargin = maxthirdQuarter;
|
||||
fourthQuarterMargin = maxforthQuarter;
|
||||
break;
|
||||
}
|
||||
|
||||
BigDecimal j = getMaxLastYear(2, product, mrpForecastList);
|
||||
BigDecimal f = getMaxLastYear(3, product, mrpForecastList);
|
||||
BigDecimal max = j.max(f);
|
||||
|
||||
log.debug("sssssss margin {} max : {} class {} ",firstQuarterMargin,maxFirstQuarter,className);
|
||||
log.debug("last year jan {} feb {}",j,f);
|
||||
log.debug("maxxxxxxxxxxx {}",max);
|
||||
|
||||
firstQuarterMargin = firstQuarterMargin.add(max);
|
||||
|
||||
mrpLineSaleAndMargin.setFirstQuarterMarge(firstQuarterMargin.setScale(0,RoundingMode.CEILING));
|
||||
mrpLineSaleAndMargin.setSecondQuarterMarge(secondQuarterMargin.setScale(0,RoundingMode.CEILING));
|
||||
mrpLineSaleAndMargin.setThirdQuarterMarge(thirdQuarterMargin.setScale(0,RoundingMode.CEILING));
|
||||
mrpLineSaleAndMargin.setForthQuarterMarge(fourthQuarterMargin.setScale(0,RoundingMode.CEILING));
|
||||
|
||||
|
||||
this.createdSalesMasterPlanLine(firstQuarterMargin, secondQuarterMargin, thirdQuarterMargin, fourthQuarterMargin, product, mrp);
|
||||
|
||||
mrpLineSaleAndMargin.setProduct(product);
|
||||
mrpLineSaleAndMargin.setProductOrigin(product);
|
||||
mrpLineSaleAndMargin.setMrp(mrp);
|
||||
Beans.get(MrpLineSaleAndMarginRepository.class).save(mrpLineSaleAndMargin);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void createdProductionMasterPlan(Product product,Mrp mrp,BigDecimal qty, BigDecimal batchQty) throws AxelorException {
|
||||
|
||||
this.createMargeAndSaleLineSophal(mrp, product, mrpForecastListAll,qty);
|
||||
|
||||
|
||||
ProductionMasterPlan productionMasterPlan = new ProductionMasterPlan();
|
||||
int currentMonth = LocalDate.now().getMonth().getValue();
|
||||
BigDecimal decreasingQty = qty;
|
||||
BigDecimal currentMargin= BigDecimal.ZERO;
|
||||
BigDecimal remaining= BigDecimal.ZERO;
|
||||
BigDecimal annualQty= BigDecimal.ZERO;
|
||||
BigDecimal batchQtyPerMonth = BigDecimal.ZERO;
|
||||
|
||||
|
||||
for (int index = currentMonth; index < 13; index++) {
|
||||
currentMargin = getCurrentSaleMargin(product, mrp, index);
|
||||
|
||||
if(decreasingQty.compareTo(currentMargin) > 0) {
|
||||
remaining = decreasingQty.subtract(currentMargin);
|
||||
decreasingQty = BigDecimal.ZERO;
|
||||
}else{
|
||||
remaining = BigDecimal.ZERO;
|
||||
decreasingQty = currentMargin.subtract(decreasingQty);
|
||||
}
|
||||
|
||||
batchQtyPerMonth = decreasingQty.divide(batchQty,0,RoundingMode.UP);
|
||||
|
||||
annualQty = annualQty.add(decreasingQty);
|
||||
|
||||
switch (index) {
|
||||
case 1:
|
||||
productionMasterPlan.setJanuary(decreasingQty);
|
||||
productionMasterPlan.setJanuaryBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 2:
|
||||
productionMasterPlan.setFebruary(decreasingQty);
|
||||
productionMasterPlan.setFebruaryBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 3:
|
||||
productionMasterPlan.setMarch(decreasingQty);
|
||||
productionMasterPlan.setMarchBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 4:
|
||||
productionMasterPlan.setApril(decreasingQty);
|
||||
productionMasterPlan.setAprilBatchQty(batchQtyPerMonth);
|
||||
case 5:
|
||||
productionMasterPlan.setMay(decreasingQty);
|
||||
productionMasterPlan.setMayBatchQty(batchQtyPerMonth);
|
||||
case 6:
|
||||
productionMasterPlan.setJuin(decreasingQty);
|
||||
productionMasterPlan.setJuinBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 7:
|
||||
productionMasterPlan.setJuly(decreasingQty);
|
||||
productionMasterPlan.setJulyBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 8:
|
||||
productionMasterPlan.setAugust(decreasingQty);
|
||||
productionMasterPlan.setAugustBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 9:
|
||||
productionMasterPlan.setSeptember(decreasingQty);
|
||||
productionMasterPlan.setSeptemberBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 10:
|
||||
productionMasterPlan.setOctober(decreasingQty);
|
||||
productionMasterPlan.setOctoberBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 11:
|
||||
productionMasterPlan.setNovember(decreasingQty);
|
||||
productionMasterPlan.setNovemberBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
case 12:
|
||||
productionMasterPlan.setDecember(decreasingQty);
|
||||
productionMasterPlan.setDecemberBatchQty(batchQtyPerMonth);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(remaining.compareTo(BigDecimal.ZERO) > 0){
|
||||
decreasingQty = decreasingQty.add(remaining);
|
||||
}else{
|
||||
decreasingQty = BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
productionMasterPlan.setAnnualQty(annualQty);
|
||||
productionMasterPlan.setMrp(mrp);
|
||||
productionMasterPlan.setProduct(product);
|
||||
|
||||
Beans.get(ProductionMasterPlanRepository.class).save(productionMasterPlan);
|
||||
|
||||
}
|
||||
|
||||
BigDecimal getMaxOfMonth(int monthSelect,Product product,List<MrpForecast> mrpForecastList){
|
||||
return mrpForecastList.stream().filter(t -> t.getProduct() == product && t.getMonthSelect() == monthSelect).map(t -> t.getQty()).max(Comparator.naturalOrder()).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
|
||||
BigDecimal getMaxLastYear(int monthSelect,Product product,List<MrpForecast> mrpForecastList){
|
||||
int lastYear = LocalDate.now().getYear() - 1;
|
||||
return mrpForecastList.stream().filter(t -> t.getProduct() == product && t.getMonthSelect() == monthSelect && t.getForecastDate().getYear() == lastYear).map(t -> t.getQty()).max(Comparator.naturalOrder()).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void createdSalesMasterPlanLine(BigDecimal firstQuarterMargin,BigDecimal secondQuarterMargin,BigDecimal thirdQuarterMargin,BigDecimal fourthQuarterMargin,Product product,Mrp mrp){
|
||||
SalesMasterPlan salesMasterPlan = new SalesMasterPlan();
|
||||
salesMasterPlan.setJanuary(firstQuarterMargin);
|
||||
salesMasterPlan.setFebruary(firstQuarterMargin);
|
||||
salesMasterPlan.setMarch(firstQuarterMargin);
|
||||
salesMasterPlan.setApril(secondQuarterMargin);
|
||||
salesMasterPlan.setMay(secondQuarterMargin);
|
||||
salesMasterPlan.setJuin(secondQuarterMargin);
|
||||
salesMasterPlan.setJuly(thirdQuarterMargin);
|
||||
salesMasterPlan.setAugust(thirdQuarterMargin);
|
||||
salesMasterPlan.setSeptember(thirdQuarterMargin);
|
||||
salesMasterPlan.setOctober(fourthQuarterMargin);
|
||||
salesMasterPlan.setNovember(fourthQuarterMargin);
|
||||
salesMasterPlan.setDecember(fourthQuarterMargin);
|
||||
salesMasterPlan.setAnnualQty((firstQuarterMargin.add(secondQuarterMargin).add(thirdQuarterMargin).add(fourthQuarterMargin)).multiply(new BigDecimal("3")));
|
||||
salesMasterPlan.setMrp(mrp);
|
||||
salesMasterPlan.setProduct(product);
|
||||
Beans.get(SalesMasterPlanRepository.class).save(salesMasterPlan);
|
||||
}
|
||||
|
||||
private BigDecimal getCurrentSaleMargin(Product product,Mrp mrp,int monthSelect){
|
||||
|
||||
MrpLineSaleAndMargin mrpLineSaleAndMargin = Beans.get(MrpLineSaleAndMarginRepository.class).all().fetchStream().filter(t -> t.getProduct() == product && t.getMrp() == mrp).findFirst().orElse(null);
|
||||
|
||||
if(mrpLineSaleAndMargin != null){
|
||||
if(monthSelect == 1 || monthSelect == 2 || monthSelect == 3){
|
||||
return mrpLineSaleAndMargin.getFirstQuarterMarge();
|
||||
|
||||
}else if(monthSelect == 4 || monthSelect == 5 || monthSelect == 6){
|
||||
return mrpLineSaleAndMargin.getSecondQuarterMarge();
|
||||
|
||||
}else if(monthSelect == 7 || monthSelect == 8 || monthSelect == 9){
|
||||
return mrpLineSaleAndMargin.getThirdQuarterMarge();
|
||||
|
||||
}else if(monthSelect == 10 || monthSelect == 11 || monthSelect == 12){
|
||||
return mrpLineSaleAndMargin.getForthQuarterMarge();
|
||||
|
||||
}else{
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean contains(final Object[] objects, final int key)
|
||||
{
|
||||
return Arrays.stream(objects).anyMatch(n-> (int) n ==key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class ProductStockLocationServiceImpl implements ProductStockLocationServ
|
||||
return sumSaleOrderQty;
|
||||
}
|
||||
|
||||
protected BigDecimal getPurchaseOrderQty(
|
||||
public BigDecimal getPurchaseOrderQty(
|
||||
Product product, Company company, StockLocation stockLocation) throws AxelorException {
|
||||
if (product == null || product.getUnit() == null) {
|
||||
return BigDecimal.ZERO;
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.axelor.apps.account.db.BudgetLine;
|
||||
import com.axelor.apps.account.db.repo.BudgetDistributionRepository;
|
||||
import com.axelor.apps.account.service.app.AppAccountService;
|
||||
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||
import com.axelor.apps.base.db.CancelReason;
|
||||
import com.axelor.apps.base.db.Company;
|
||||
import com.axelor.apps.base.db.Currency;
|
||||
import com.axelor.apps.base.db.Partner;
|
||||
@@ -31,6 +32,7 @@ import com.axelor.apps.base.db.TradingName;
|
||||
import com.axelor.apps.base.service.app.AppBaseService;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrder;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrderLine;
|
||||
import com.axelor.apps.purchase.db.PurchaseRequest;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderServiceImpl;
|
||||
import com.axelor.apps.sale.db.SaleOrder;
|
||||
@@ -42,24 +44,31 @@ import com.axelor.apps.supplychain.service.app.AppSupplychainService;
|
||||
import com.axelor.apps.tool.date.DateTool;
|
||||
import com.axelor.auth.AuthUtils;
|
||||
import com.axelor.auth.db.User;
|
||||
import com.axelor.db.EntityHelper;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.dms.db.DMSFile;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.db.MetaFile;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
|
||||
import wslite.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.MalformedURLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import wslite.json.JSONException;
|
||||
|
||||
public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImpl {
|
||||
|
||||
@@ -97,6 +106,7 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
LocalDate deliveryDate,
|
||||
String internalReference,
|
||||
String externalReference,
|
||||
String notes,
|
||||
StockLocation stockLocation,
|
||||
LocalDate orderDate,
|
||||
PriceList priceList,
|
||||
@@ -119,6 +129,7 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
deliveryDate,
|
||||
internalReference,
|
||||
externalReference,
|
||||
notes, // notes
|
||||
orderDate,
|
||||
priceList,
|
||||
supplierPartner,
|
||||
@@ -174,11 +185,19 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
throws AxelorException {
|
||||
String numSeq = "";
|
||||
String externalRef = "";
|
||||
String notes = "";
|
||||
int statusSelect = 1;
|
||||
Set<PurchaseRequest> purchaseRequestSet = new HashSet<PurchaseRequest>();
|
||||
|
||||
for (PurchaseOrder purchaseOrderLocal : purchaseOrderList) {
|
||||
if (!numSeq.isEmpty()) {
|
||||
numSeq += "-";
|
||||
}
|
||||
numSeq += purchaseOrderLocal.getPurchaseOrderSeq();
|
||||
numSeq +=
|
||||
purchaseOrderLocal.getPurchaseOrderSeq()
|
||||
+ (purchaseOrderLocal.getInternalReference() == null
|
||||
? ""
|
||||
: purchaseOrderLocal.getInternalReference() + "-");
|
||||
|
||||
if (!externalRef.isEmpty()) {
|
||||
externalRef += "|";
|
||||
@@ -186,6 +205,12 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
if (purchaseOrderLocal.getExternalReference() != null) {
|
||||
externalRef += purchaseOrderLocal.getExternalReference();
|
||||
}
|
||||
purchaseRequestSet.addAll(
|
||||
purchaseOrderLocal.getPurchaseRequestSet().stream().collect(Collectors.toSet()));
|
||||
if (purchaseOrderLocal.getNotes() != null) {
|
||||
notes += purchaseOrderLocal.getNotes() + " ";
|
||||
}
|
||||
statusSelect = purchaseOrderLocal.getStatusSelect();
|
||||
}
|
||||
|
||||
PurchaseOrder purchaseOrderMerged =
|
||||
@@ -197,23 +222,48 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
null,
|
||||
numSeq,
|
||||
externalRef,
|
||||
notes,
|
||||
stockLocation,
|
||||
LocalDate.now(),
|
||||
priceList,
|
||||
supplierPartner,
|
||||
tradingName);
|
||||
|
||||
super.attachPurchaseRequestToNewOrder(
|
||||
purchaseRequestSet, purchaseOrderMerged, purchaseOrderList);
|
||||
|
||||
super.attachToNewPurchaseOrder(purchaseOrderList, purchaseOrderMerged);
|
||||
|
||||
this.computePurchaseOrder(purchaseOrderMerged);
|
||||
|
||||
purchaseOrderMerged.setStatusSelect(statusSelect);
|
||||
|
||||
purchaseOrderRepo.save(purchaseOrderMerged);
|
||||
|
||||
this.attachAttachment(purchaseOrderList, purchaseOrderMerged);
|
||||
|
||||
super.removeOldPurchaseOrders(purchaseOrderList);
|
||||
|
||||
return purchaseOrderMerged;
|
||||
}
|
||||
|
||||
public Set<MetaFile> getMetaFiles(PurchaseOrder po) throws AxelorException, IOException {
|
||||
|
||||
List<DMSFile> metaAttachments =
|
||||
Query.of(DMSFile.class)
|
||||
.filter(
|
||||
"self.relatedId = ?1 AND self.relatedModel = ?2",
|
||||
po.getId(),
|
||||
EntityHelper.getEntityClass(po).getName())
|
||||
.fetch();
|
||||
Set<MetaFile> metaFiles = Sets.newHashSet();
|
||||
for (DMSFile metaAttachment : metaAttachments) {
|
||||
if (!metaAttachment.getIsDirectory()) metaFiles.add(metaAttachment.getMetaFile());
|
||||
}
|
||||
|
||||
return metaFiles;
|
||||
}
|
||||
|
||||
public void updateAmountToBeSpreadOverTheTimetable(PurchaseOrder purchaseOrder) {
|
||||
List<Timetable> timetableList = purchaseOrder.getTimetableList();
|
||||
BigDecimal totalHT = purchaseOrder.getExTaxTotal();
|
||||
@@ -340,7 +390,8 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public void validatePurchaseOrder(PurchaseOrder purchaseOrder) throws AxelorException, MalformedURLException, JSONException {
|
||||
public void validatePurchaseOrder(PurchaseOrder purchaseOrder)
|
||||
throws AxelorException, MalformedURLException, JSONException {
|
||||
super.validatePurchaseOrder(purchaseOrder);
|
||||
|
||||
if (appSupplychainService.getAppSupplychain().getSupplierStockMoveGenerationAuto()
|
||||
@@ -379,4 +430,12 @@ public class PurchaseOrderServiceSupplychainImpl extends PurchaseOrderServiceImp
|
||||
purchaseOrderLine.setBudget(budget);
|
||||
}
|
||||
}
|
||||
|
||||
public void finishSockMoves(
|
||||
PurchaseOrder purchaseOrder, CancelReason raison, String cancelReasonStr)
|
||||
throws AxelorException {
|
||||
Beans.get(PurchaseOrderStockServiceImpl.class)
|
||||
.cancelReceiptWithRaison(purchaseOrder, raison, cancelReasonStr);
|
||||
this.finishPurchaseOrder(purchaseOrder, cancelReasonStr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.axelor.apps.supplychain.service;
|
||||
|
||||
import com.axelor.apps.account.db.TaxLine;
|
||||
import com.axelor.apps.base.db.Address;
|
||||
import com.axelor.apps.base.db.CancelReason;
|
||||
import com.axelor.apps.base.db.Company;
|
||||
import com.axelor.apps.base.db.Partner;
|
||||
import com.axelor.apps.base.db.Product;
|
||||
@@ -464,6 +465,25 @@ public class PurchaseOrderStockServiceImpl implements PurchaseOrderStockService
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelReceiptWithRaison(
|
||||
PurchaseOrder purchaseOrder, CancelReason cancelReason, String cancelReasonStr)
|
||||
throws AxelorException {
|
||||
|
||||
List<StockMove> stockMoveList =
|
||||
Beans.get(StockMoveRepository.class)
|
||||
.all()
|
||||
.filter(
|
||||
"self.originTypeSelect = ? AND self.originId = ? AND self.statusSelect = 2",
|
||||
StockMoveRepository.ORIGIN_PURCHASE_ORDER,
|
||||
purchaseOrder.getId())
|
||||
.fetch();
|
||||
|
||||
for (StockMove stockMove : stockMoveList) {
|
||||
|
||||
stockMoveService.cancel(stockMove, cancelReason, cancelReasonStr);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStockMoveProduct(PurchaseOrderLine purchaseOrderLine) throws AxelorException {
|
||||
return isStockMoveProduct(purchaseOrderLine, purchaseOrderLine.getPurchaseOrder());
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ public class SaleOrderPurchaseServiceImpl implements SaleOrderPurchaseService {
|
||||
null,
|
||||
saleOrder.getSaleOrderSeq(),
|
||||
saleOrder.getExternalReference(),
|
||||
saleOrder.getDescription(),
|
||||
saleOrder.getDirectOrderLocation()
|
||||
? saleOrder.getStockLocation()
|
||||
: Beans.get(StockLocationService.class)
|
||||
|
||||
@@ -126,7 +126,7 @@ public class SaleOrderServiceSupplychainImpl extends SaleOrderServiceImpl {
|
||||
IExceptionMessage.SUPPLYCHAIN_MISSING_CANCEL_REASON_ON_CHANGING_SALE_ORDER);
|
||||
}
|
||||
for (StockMove stockMove : stockMoves) {
|
||||
stockMoveService.cancel(stockMove, cancelReason);
|
||||
stockMoveService.cancel(stockMove, cancelReason, "");
|
||||
stockMoveRepository.remove(stockMove);
|
||||
}
|
||||
}
|
||||
@@ -191,67 +191,63 @@ public class SaleOrderServiceSupplychainImpl extends SaleOrderServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
// same move
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public StockMove splitInto2SameMove(
|
||||
StockMove originalStockMove, List<StockMoveLine> modifiedStockMoveLines)
|
||||
throws AxelorException {
|
||||
|
||||
// same move
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public StockMove splitInto2SameMove(
|
||||
StockMove originalStockMove, List<StockMoveLine> modifiedStockMoveLines)
|
||||
throws AxelorException {
|
||||
StockMoveRepository stockMoveRepo = Beans.get(StockMoveRepository.class);
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
|
||||
StockMoveRepository stockMoveRepo = Beans.get(StockMoveRepository.class);
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
|
||||
modifiedStockMoveLines =
|
||||
modifiedStockMoveLines
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getQty().compareTo(BigDecimal.ZERO) != 0)
|
||||
.collect(Collectors.toList());
|
||||
for (StockMoveLine moveLine : modifiedStockMoveLines) {
|
||||
StockMoveLine newStockMoveLine = new StockMoveLine();
|
||||
// Set quantity in new stock move line
|
||||
newStockMoveLine = stockMoveLineRepo.copy(moveLine, false);
|
||||
newStockMoveLine.setQty(moveLine.getQty());
|
||||
newStockMoveLine.setRealQty(moveLine.getQty());
|
||||
newStockMoveLine.setProductTypeSelect(moveLine.getProductTypeSelect());
|
||||
newStockMoveLine.setSaleOrderLine(moveLine.getSaleOrderLine());
|
||||
// add stock move line
|
||||
originalStockMove.addStockMoveLineListItem(newStockMoveLine);
|
||||
|
||||
// find the original move line to update it
|
||||
Optional<StockMoveLine> correspondingMoveLine =
|
||||
originalStockMove
|
||||
.getStockMoveLineList()
|
||||
modifiedStockMoveLines =
|
||||
modifiedStockMoveLines
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getId().equals(moveLine.getId()))
|
||||
.findFirst();
|
||||
if (BigDecimal.ZERO.compareTo(moveLine.getQty()) > 0
|
||||
|| (correspondingMoveLine.isPresent()
|
||||
&& moveLine.getQty().compareTo(correspondingMoveLine.get().getRealQty()) > 0)) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||
I18n.get(""),
|
||||
originalStockMove);
|
||||
}
|
||||
.filter(stockMoveLine -> stockMoveLine.getQty().compareTo(BigDecimal.ZERO) != 0)
|
||||
.collect(Collectors.toList());
|
||||
for (StockMoveLine moveLine : modifiedStockMoveLines) {
|
||||
StockMoveLine newStockMoveLine = new StockMoveLine();
|
||||
// Set quantity in new stock move line
|
||||
newStockMoveLine = stockMoveLineRepo.copy(moveLine, false);
|
||||
newStockMoveLine.setQty(moveLine.getQty());
|
||||
newStockMoveLine.setRealQty(moveLine.getQty());
|
||||
newStockMoveLine.setProductTypeSelect(moveLine.getProductTypeSelect());
|
||||
newStockMoveLine.setSaleOrderLine(moveLine.getSaleOrderLine());
|
||||
// add stock move line
|
||||
originalStockMove.addStockMoveLineListItem(newStockMoveLine);
|
||||
|
||||
if (correspondingMoveLine.isPresent()) {
|
||||
// Update quantity in original stock move.
|
||||
// If the remaining quantity is 0, remove the stock move line
|
||||
BigDecimal remainingQty = correspondingMoveLine.get().getQty().subtract(moveLine.getQty());
|
||||
if (BigDecimal.ZERO.compareTo(remainingQty) == 0) {
|
||||
// Remove the stock move line
|
||||
originalStockMove.removeStockMoveLineListItem(correspondingMoveLine.get());
|
||||
} else {
|
||||
correspondingMoveLine.get().setQty(remainingQty);
|
||||
correspondingMoveLine.get().setRealQty(remainingQty);
|
||||
// find the original move line to update it
|
||||
Optional<StockMoveLine> correspondingMoveLine =
|
||||
originalStockMove
|
||||
.getStockMoveLineList()
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getId().equals(moveLine.getId()))
|
||||
.findFirst();
|
||||
if (BigDecimal.ZERO.compareTo(moveLine.getQty()) > 0
|
||||
|| (correspondingMoveLine.isPresent()
|
||||
&& moveLine.getQty().compareTo(correspondingMoveLine.get().getRealQty()) > 0)) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY, I18n.get(""), originalStockMove);
|
||||
}
|
||||
|
||||
if (correspondingMoveLine.isPresent()) {
|
||||
// Update quantity in original stock move.
|
||||
// If the remaining quantity is 0, remove the stock move line
|
||||
BigDecimal remainingQty = correspondingMoveLine.get().getQty().subtract(moveLine.getQty());
|
||||
if (BigDecimal.ZERO.compareTo(remainingQty) == 0) {
|
||||
// Remove the stock move line
|
||||
originalStockMove.removeStockMoveLineListItem(correspondingMoveLine.get());
|
||||
} else {
|
||||
correspondingMoveLine.get().setQty(remainingQty);
|
||||
correspondingMoveLine.get().setRealQty(remainingQty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!originalStockMove.getStockMoveLineList().isEmpty()) {
|
||||
return stockMoveRepo.save(originalStockMove);
|
||||
} else {
|
||||
return null;
|
||||
if (!originalStockMove.getStockMoveLineList().isEmpty()) {
|
||||
return stockMoveRepo.save(originalStockMove);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ public class SaleOrderStockServiceImpl implements SaleOrderStockService {
|
||||
@Override
|
||||
public StockMoveLine createStockMoveLine(
|
||||
StockMove stockMove, SaleOrderLine saleOrderLine, BigDecimal qty) throws AxelorException {
|
||||
int scale = Beans.get(AppBaseService.class).getNbDecimalDigitForSalePrice();
|
||||
int scale = Beans.get(AppBaseService.class).getNbDecimalDigitForSalePrice();
|
||||
|
||||
if (this.isStockMoveProduct(saleOrderLine)) {
|
||||
|
||||
@@ -374,11 +374,7 @@ public class SaleOrderStockServiceImpl implements SaleOrderStockService {
|
||||
saleOrderLine.getUnit(), unit, qty, qty.scale(), saleOrderLine.getProduct());
|
||||
priceDiscounted =
|
||||
unitConversionService.convert(
|
||||
unit,
|
||||
saleOrderLine.getUnit(),
|
||||
priceDiscounted,
|
||||
scale,
|
||||
saleOrderLine.getProduct());
|
||||
unit, saleOrderLine.getUnit(), priceDiscounted, scale, saleOrderLine.getProduct());
|
||||
requestedReservedQty =
|
||||
unitConversionService.convert(
|
||||
saleOrderLine.getUnit(),
|
||||
@@ -397,10 +393,7 @@ public class SaleOrderStockServiceImpl implements SaleOrderStockService {
|
||||
companyUnitPriceUntaxed =
|
||||
saleOrderLine
|
||||
.getCompanyExTaxTotal()
|
||||
.divide(
|
||||
saleOrderLine.getQty(),
|
||||
scale,
|
||||
RoundingMode.HALF_EVEN);
|
||||
.divide(saleOrderLine.getQty(), scale, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
StockMoveLine stockMoveLine =
|
||||
|
||||
@@ -21,18 +21,15 @@ import com.axelor.apps.account.db.AccountConfig;
|
||||
import com.axelor.apps.account.db.Invoice;
|
||||
import com.axelor.apps.account.db.InvoiceLine;
|
||||
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||
import com.axelor.apps.account.service.AccountService;
|
||||
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||
import com.axelor.apps.account.service.invoice.InvoiceService;
|
||||
import com.axelor.apps.account.service.invoice.generator.InvoiceGenerator;
|
||||
import com.axelor.apps.account.service.invoice.generator.InvoiceLineGenerator;
|
||||
import com.axelor.apps.account.service.invoice.workflow.ventilate.VentilateState;
|
||||
import com.axelor.apps.base.db.Product;
|
||||
import com.axelor.apps.base.db.Sequence;
|
||||
import com.axelor.apps.base.service.AddressService;
|
||||
import com.axelor.apps.base.service.administration.SequenceService;
|
||||
import com.axelor.apps.base.service.app.AppBaseService;
|
||||
import com.axelor.apps.base.service.app.AppService;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrder;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrderLine;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
@@ -191,8 +188,11 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
|
||||
invoice.setNote(saleOrder.getInvoiceComments());
|
||||
invoice.setProformaComments(saleOrder.getProformaComments());
|
||||
|
||||
//todo sophal
|
||||
invoice.setInvoiceId(Beans.get(SequenceService.class).getSequenceNumber(getSequence(invoice), Beans.get(AppBaseService.class).getTodayDate()));
|
||||
// todo sophal
|
||||
invoice.setInvoiceId(
|
||||
Beans.get(SequenceService.class)
|
||||
.getSequenceNumber(
|
||||
getSequence(invoice), Beans.get(AppBaseService.class).getTodayDate()));
|
||||
|
||||
if (invoice != null) {
|
||||
Set<StockMove> stockMoveSet = invoice.getStockMoveSet();
|
||||
@@ -230,10 +230,10 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
|
||||
this.extendInternalReference(stockMove, invoice);
|
||||
invoice.setAddressStr(
|
||||
Beans.get(AddressService.class).computeAddressStr(invoice.getAddress()));
|
||||
invoice.setPayerPartner(stockMove.getPayerPartner());
|
||||
invoice.setDeliveryPartner(stockMove.getDeliveryPartner());
|
||||
invoice.setStamp(stockMove.getStamp());
|
||||
invoice.setFixTax(stockMove.getFixTax());
|
||||
invoice.setPayerPartner(stockMove.getPayerPartner());
|
||||
invoice.setDeliveryPartner(stockMove.getDeliveryPartner());
|
||||
invoice.setStamp(stockMove.getStamp());
|
||||
invoice.setFixTax(stockMove.getFixTax());
|
||||
if (invoice != null) {
|
||||
Set<StockMove> stockMoveSet = invoice.getStockMoveSet();
|
||||
if (stockMoveSet == null) {
|
||||
@@ -572,24 +572,23 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
|
||||
|
||||
AccountConfig accountConfig = accountConfigService.getAccountConfig(invoice.getCompany());
|
||||
switch (invoice.getOperationTypeSelect()) {
|
||||
case InvoiceRepository.OPERATION_TYPE_SUPPLIER_PURCHASE:
|
||||
return accountConfigService.getSuppInvSequence(accountConfig);
|
||||
case InvoiceRepository.OPERATION_TYPE_SUPPLIER_PURCHASE:
|
||||
return accountConfigService.getSuppInvSequence(accountConfig);
|
||||
|
||||
case InvoiceRepository.OPERATION_TYPE_SUPPLIER_REFUND:
|
||||
return accountConfigService.getSuppRefSequence(accountConfig);
|
||||
case InvoiceRepository.OPERATION_TYPE_SUPPLIER_REFUND:
|
||||
return accountConfigService.getSuppRefSequence(accountConfig);
|
||||
|
||||
case InvoiceRepository.OPERATION_TYPE_CLIENT_SALE:
|
||||
return accountConfigService.getCustInvSequence(accountConfig);
|
||||
case InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND:
|
||||
return accountConfigService.getCustRefSequence(accountConfig);
|
||||
case InvoiceRepository.OPERATION_TYPE_CLIENT_SALE:
|
||||
return accountConfigService.getCustInvSequence(accountConfig);
|
||||
case InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND:
|
||||
return accountConfigService.getCustRefSequence(accountConfig);
|
||||
|
||||
default:
|
||||
throw new AxelorException(
|
||||
invoice,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get("Invoice type missing %s"),
|
||||
invoice.getInvoiceId());
|
||||
}
|
||||
|
||||
default:
|
||||
throw new AxelorException(
|
||||
invoice,
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get("Invoice type missing %s"),
|
||||
invoice.getInvoiceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,18 @@ package com.axelor.apps.supplychain.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.PriceListService;
|
||||
import com.axelor.apps.base.service.UnitConversionService;
|
||||
import com.axelor.apps.base.service.app.AppBaseService;
|
||||
import com.axelor.apps.base.service.tax.AccountManagementService;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrder;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrderLine;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderLineRepository;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderLineService;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderLineServiceImpl;
|
||||
import com.axelor.apps.purchase.service.PurchaseOrderServiceImpl;
|
||||
import com.axelor.apps.sale.db.SaleOrderLine;
|
||||
import com.axelor.apps.stock.db.StockLocation;
|
||||
import com.axelor.apps.stock.db.StockLocationLine;
|
||||
@@ -32,26 +39,37 @@ import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.TrackingNumber;
|
||||
import com.axelor.apps.stock.db.TrackingNumberConfiguration;
|
||||
import com.axelor.apps.stock.db.repo.StockLocationLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockLocationRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.stock.db.repo.TrackingNumberRepository;
|
||||
import com.axelor.apps.stock.service.StockLocationLineService;
|
||||
import com.axelor.apps.stock.service.StockLocationLineServiceImpl;
|
||||
import com.axelor.apps.stock.service.StockMoveLineServiceImpl;
|
||||
import com.axelor.apps.stock.service.StockMoveToolService;
|
||||
import com.axelor.apps.stock.service.TrackingNumberService;
|
||||
import com.axelor.apps.stock.service.WeightedAveragePriceService;
|
||||
import com.axelor.apps.stock.service.app.AppStockService;
|
||||
import com.axelor.apps.supplychain.exception.IExceptionMessage;
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RequestScoped
|
||||
public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImpl
|
||||
@@ -59,6 +77,9 @@ public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImp
|
||||
|
||||
protected AccountManagementService accountManagementService;
|
||||
protected PriceListService priceListService;
|
||||
protected PurchaseOrderLineRepository purchaseOrderLineRepo;
|
||||
protected PurchaseOrderLineService purchaseOrderLineService;
|
||||
protected List<StockMoveLine> stockMoveLines;
|
||||
|
||||
@Inject
|
||||
public StockMoveLineServiceSupplychainImpl(
|
||||
@@ -72,6 +93,8 @@ public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImp
|
||||
WeightedAveragePriceService weightedAveragePriceService,
|
||||
TrackingNumberRepository trackingNumberRepo,
|
||||
AccountManagementService accountManagementService,
|
||||
PurchaseOrderLineRepository purchaseOrderLineRepository,
|
||||
PurchaseOrderLineService purchaseOrderLineService,
|
||||
PriceListService priceListService) {
|
||||
super(
|
||||
trackingNumberService,
|
||||
@@ -85,6 +108,7 @@ public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImp
|
||||
trackingNumberRepo);
|
||||
this.accountManagementService = accountManagementService;
|
||||
this.priceListService = priceListService;
|
||||
this.stockMoveLines = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,7 +145,7 @@ public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImp
|
||||
stockMoveLine.setRequestedReservedQty(BigDecimal.ZERO);
|
||||
stockMoveLine.setSaleOrderLine(saleOrderLine);
|
||||
stockMoveLine.setPurchaseOrderLine(purchaseOrderLine);
|
||||
if(saleOrderLine != null){
|
||||
if (saleOrderLine != null) {
|
||||
stockMoveLine.setShp(saleOrderLine.getShp());
|
||||
stockMoveLine.setPpa(saleOrderLine.getPpa());
|
||||
stockMoveLine.setPvg(saleOrderLine.getPvg());
|
||||
@@ -456,4 +480,421 @@ public class StockMoveLineServiceSupplychainImpl extends StockMoveLineServiceImp
|
||||
stockMoveLine.setAvailableStatusSelect(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void resetValorization(Long productId, Long stockMoveId, LocalDate toDateTime,Boolean excludeValotisationStocklocation) {
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(stockMoveId);
|
||||
Product product = Beans.get(ProductRepository.class).find(productId);
|
||||
|
||||
if(excludeValotisationStocklocation){
|
||||
this.stockMoveLines = getStockMoveLines(product, toDateTime, stockMove,true);
|
||||
}else{
|
||||
this.stockMoveLines = getStockMoveLines(product, toDateTime, stockMove,false);
|
||||
}
|
||||
|
||||
|
||||
List<StockMoveLine> lines = new ArrayList<>();
|
||||
|
||||
if(this.stockMoveLines.size() > 1){
|
||||
lines = sliceStockMoveLines(this.stockMoveLines,stockMoveId,product);
|
||||
}else{
|
||||
lines.addAll(stockMoveLines);
|
||||
}
|
||||
|
||||
for (StockMoveLine stockMoveLine : lines) {
|
||||
stockMoveLine.setIsWapUpdated(false);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillStockMoveLines(Long productId,LocalDate toDateTime,Long stockMoveId,Boolean excludeValotisationStocklocation){
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(stockMoveId);
|
||||
Product product = Beans.get(ProductRepository.class).find(productId);
|
||||
this.stockMoveLines = getStockMoveLines(product, toDateTime, stockMove,excludeValotisationStocklocation);
|
||||
|
||||
System.out.println("***********************stockMoveLines****************************");
|
||||
System.out.println(this.stockMoveLines);
|
||||
System.out.println("***********************stockMoveLines****************************");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void valorize(Long productId, Long stockMoveId, LocalDate toDateTime, BigDecimal price,Boolean updatePo,Boolean excludeValotisationStocklocation)
|
||||
throws AxelorException {
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(stockMoveId);
|
||||
Product product = Beans.get(ProductRepository.class).find(productId);
|
||||
int scale = appBaseService.getNbDecimalDigitForUnitPrice();
|
||||
|
||||
this.updateStockMoveLinePrices(product, price, stockMove, false, null);
|
||||
|
||||
// if(updatePo){
|
||||
// this.updatePurchaseOrderPrices(stockMove, product, price);
|
||||
// }
|
||||
|
||||
List<StockMoveLine> lines = sliceStockMoveLines(this.stockMoveLines,stockMoveId,product);
|
||||
|
||||
BigDecimal currentQty = this.getTotalQty(product, stockMove.getCompany(),false);
|
||||
BigDecimal oldWap = this.getPreviousWap(lines.get(0),false);
|
||||
|
||||
if(excludeValotisationStocklocation){
|
||||
currentQty = this.getTotalQty(product, stockMove.getCompany(),true);
|
||||
oldWap = this.getPreviousWap(lines.get(0),true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (StockMoveLine stockMoveLine : lines) {
|
||||
if (stockMoveLine.getStockMove().getFromStockLocation().getTypeSelect()
|
||||
== StockLocationRepository.TYPE_VIRTUAL && stockMoveLine.getStockMove().getToStockLocation().getId() != 6L) {
|
||||
currentQty = currentQty.subtract(stockMoveLine.getRealQty());
|
||||
} else if (stockMoveLine.getStockMove().getToStockLocation().getTypeSelect()
|
||||
== StockLocationRepository.TYPE_VIRTUAL || (stockMoveLine.getStockMove().getToStockLocation().getId() == 6L && stockMoveLine.getStockMove().getFromStockLocation().getTypeSelect()
|
||||
!= StockLocationRepository.TYPE_VIRTUAL)) {
|
||||
currentQty = currentQty.add(stockMoveLine.getRealQty());
|
||||
}
|
||||
System.out.println("..................>>>>>>>>>>>>>>>><<<<<"+currentQty.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
BigDecimal newQty = lines.get(0).getRealQty();
|
||||
BigDecimal newPrice = price;
|
||||
|
||||
BigDecimal newWap =
|
||||
newQty
|
||||
.multiply(newPrice)
|
||||
.add(currentQty.multiply(oldWap))
|
||||
.divide(currentQty.add(newQty), scale, BigDecimal.ROUND_HALF_UP);
|
||||
|
||||
|
||||
|
||||
this.updateStockMoveLinePrices(product, price, stockMove, true, newWap);
|
||||
|
||||
int index = 1;
|
||||
List<StockMoveLine> lines2 = new ArrayList<>();
|
||||
if(lines.size() > 1){
|
||||
lines2 = this.stockMoveLineStartingFromIndex(index, lines);
|
||||
}
|
||||
|
||||
for (StockMoveLine stockMoveLine : lines2) {
|
||||
// stockMoveLine.getStockMove().getFromStockLocation().getTypeSelect() !=
|
||||
// StockLocationRepository.TYPE_VIRTUAL &&
|
||||
|
||||
if (stockMoveLine.getStockMove().getPartner() == stockMove.getCompany().getPartner()
|
||||
|| stockMoveLine.getStockMove().getPartner() == null) {
|
||||
stockMoveLine.setUnitPriceTaxed(newWap);
|
||||
stockMoveLine.setUnitPriceUntaxed(newWap);
|
||||
stockMoveLine.setCompanyUnitPriceUntaxed(newWap);
|
||||
stockMoveLine.setWapPrice(newWap);
|
||||
stockMoveLine.setIsWapUpdated(true);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
} else if (stockMoveLine.getStockMove().getPartner().getId()
|
||||
!= stockMove.getCompany().getPartner().getId()
|
||||
&& stockMoveLine.getIsWapUpdated() == false) {
|
||||
index++;
|
||||
this.valorize(
|
||||
productId,
|
||||
stockMoveLine.getStockMove().getId(),
|
||||
toDateTime,
|
||||
stockMoveLine.getUnitPriceUntaxed(),updatePo,excludeValotisationStocklocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePurchaseOrderPrices(StockMove stockMove, Product product, BigDecimal price)
|
||||
throws AxelorException {
|
||||
if (StockMoveRepository.ORIGIN_PURCHASE_ORDER.equals(stockMove.getOriginTypeSelect())
|
||||
&& stockMove.getOriginId() != null) {
|
||||
PurchaseOrder purchaseOrder =
|
||||
Beans.get(PurchaseOrderRepository.class).find(stockMove.getOriginId());
|
||||
purchaseOrder.setCurrency(purchaseOrder.getCompany().getCurrency());
|
||||
List<PurchaseOrderLine> purchaseOrderLines =
|
||||
purchaseOrder
|
||||
.getPurchaseOrderLineList()
|
||||
.stream()
|
||||
.filter(t -> t.getProduct().getId() == product.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// if(purchaseOrderLines == null || purchaseOrderLines.isEmpty()){
|
||||
// return;
|
||||
// }
|
||||
for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLines) {
|
||||
this.updatePrice(purchaseOrderLine, price);
|
||||
}
|
||||
Beans.get(PurchaseOrderRepository.class).save(purchaseOrder);
|
||||
Beans.get(PurchaseOrderServiceImpl.class)._computePurchaseOrder(purchaseOrder);
|
||||
}
|
||||
}
|
||||
|
||||
public List<StockMoveLine> stockMoveLineStartingFromIndex(
|
||||
int index, List<StockMoveLine> stockMoveLines) {
|
||||
List<StockMoveLine> newStockMoveLines = new ArrayList<>();
|
||||
if (index > stockMoveLines.size()) {
|
||||
return newStockMoveLines;
|
||||
}
|
||||
for (int i = index; i < stockMoveLines.size(); i++) {
|
||||
newStockMoveLines.add(stockMoveLines.get(i));
|
||||
}
|
||||
return newStockMoveLines;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void updateStockMoveLinePrices(
|
||||
Product product,
|
||||
BigDecimal price,
|
||||
StockMove stockMove,
|
||||
boolean updatePmp,
|
||||
BigDecimal newWapPrice) {
|
||||
List<StockMoveLine> stockMoveLines =
|
||||
// stockMoveLineRepository
|
||||
// .all()
|
||||
// .filter(
|
||||
// "self.stockMove.id = ?1 and self.product.id = ?2 and self.stockMove.statusSelect = 3 and self.realQty > 0",
|
||||
// stockMoveId,
|
||||
// productId)
|
||||
// .fetch();
|
||||
stockMove.getStockMoveLineList().stream().filter(t -> (t.getProduct().getId() == product.getId() && t.getRealQty().compareTo(BigDecimal.ZERO) > 0)).collect(Collectors.toList());
|
||||
if (!updatePmp) {
|
||||
for (StockMoveLine stockMoveLine : stockMoveLines) {
|
||||
stockMoveLine.setCompanyUnitPriceUntaxed(price);
|
||||
stockMoveLine.setUnitPriceTaxed(price);
|
||||
stockMoveLine.setUnitPriceUntaxed(price);
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
}
|
||||
stockMove.setExTaxTotal(stockMoveToolService.compute(stockMove));
|
||||
Beans.get(StockMoveRepository.class).save(stockMove);
|
||||
} else {
|
||||
// Product product = Beans.get(ProductRepository.class).find(productId);
|
||||
for (StockMoveLine stockMoveLine : stockMoveLines) {
|
||||
stockMoveLine.setWapPrice(newWapPrice);
|
||||
stockMoveLine.setIsWapUpdated(true);
|
||||
product.setAvgPrice(newWapPrice);
|
||||
List<StockLocationLine> locationLines =
|
||||
Beans.get(StockLocationLineServiceImpl.class).getStockLocationLines(product);
|
||||
for (StockLocationLine stockLocationLine : locationLines) {
|
||||
stockLocationLine.setAvgPrice(newWapPrice);
|
||||
Beans.get(StockLocationLineRepository.class).save(stockLocationLine);
|
||||
}
|
||||
Beans.get(StockMoveLineRepository.class).save(stockMoveLine);
|
||||
Beans.get(ProductRepository.class).save(product);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updatePrice(PurchaseOrderLine purchaseOrderLine, BigDecimal price)
|
||||
throws AxelorException {
|
||||
System.out.println("updateOrderLinePrices......................");
|
||||
System.out.println(purchaseOrderLine.toString());
|
||||
purchaseOrderLine.setPrice(price);
|
||||
purchaseOrderLine.setPriceDiscounted(price);
|
||||
Beans.get(PurchaseOrderLineServiceImpl.class)
|
||||
.compute(purchaseOrderLine, purchaseOrderLine.getPurchaseOrder());
|
||||
Beans.get(PurchaseOrderLineRepository.class).save(purchaseOrderLine);
|
||||
}
|
||||
|
||||
public List<StockMoveLine> getStockMoveLines(
|
||||
Product product, LocalDate toDate, StockMove stockMove,Boolean excludeValotisationStocklocation) {
|
||||
|
||||
String query =
|
||||
"self.stockMove.statusSelect = ?1 AND self.stockMove.realDate <= ?2 AND self.product = ?3 AND self.stockMove.realDate >= ?4 AND self.realQty > 0 AND (self.archived is null OR self.archived is false)";
|
||||
|
||||
if (excludeValotisationStocklocation) {
|
||||
query += " AND (self.stockMove.toStockLocation.excludeValorisation is true or self.stockMove.fromStockLocation.excludeValorisation is true)";
|
||||
}else{
|
||||
query += " AND ((self.stockMove.toStockLocation.excludeValorisation is false or self.stockMove.toStockLocation.excludeValorisation is null) AND (self.stockMove.fromStockLocation.excludeValorisation is false or self.stockMove.fromStockLocation.excludeValorisation is null))";
|
||||
}
|
||||
|
||||
System.out.println("***************getStockMoveLines************");
|
||||
System.out.println(query);
|
||||
System.out.println("***************getStockMoveLines************");
|
||||
|
||||
|
||||
List<Object> params = Lists.newArrayList();
|
||||
params.add(StockMoveRepository.STATUS_REALIZED);
|
||||
params.add(toDate);
|
||||
params.add(product);
|
||||
params.add(stockMove.getRealDate());
|
||||
// params.add(stockMove.getRealDate());
|
||||
// params.add(stockMove.getId());
|
||||
List<StockMoveLine> lines =
|
||||
stockMoveLineRepository
|
||||
.all()
|
||||
.filter(query, params.toArray())
|
||||
.order("stockMove.realDate")
|
||||
// .order("id")
|
||||
.fetch();
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
public BigDecimal getPreviousWap(StockMoveLine stockMoveLine,Boolean excludeValotisationStocklocation) {
|
||||
String query =
|
||||
"self.stockMove.statusSelect = ?1 AND self.product = ?2 and self.stockMove.realDate < ?3 AND self.realQty > 0";
|
||||
|
||||
if (excludeValotisationStocklocation) {
|
||||
query += " AND (self.stockMove.toStockLocation.excludeValorisation is true or self.stockMove.fromStockLocation.excludeValorisation is true)";
|
||||
}
|
||||
|
||||
StockMoveLine l = stockMoveLineRepository.find(stockMoveLine.getId());
|
||||
List<Object> params = Lists.newArrayList();
|
||||
params.add(StockMoveRepository.STATUS_REALIZED);
|
||||
params.add(l.getProduct());
|
||||
params.add(l.getStockMove().getRealDate());
|
||||
|
||||
StockMoveLine line =
|
||||
stockMoveLineRepository
|
||||
.all()
|
||||
.order("-stockMove.realDate")
|
||||
.order("-id")
|
||||
.filter(query, params.toArray())
|
||||
.fetchOne();
|
||||
|
||||
if (line == null || line.getWapPrice() == null) {
|
||||
return stockMoveLine.getUnitPriceUntaxed();
|
||||
}
|
||||
return line.getWapPrice();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public BigDecimal getTotalQty(Product product, Company company,Boolean excludeValotisationStocklocation) {
|
||||
Long productId = product.getId();
|
||||
String query =
|
||||
"SELECT new list(self.id, self.avgPrice, self.currentQty) FROM StockLocationLine as self "
|
||||
+ "WHERE self.product.id = "
|
||||
+ productId
|
||||
+ "AND self.stockLocation.id not in (6) AND self.stockLocation.typeSelect != "
|
||||
+ StockLocationRepository.TYPE_VIRTUAL;
|
||||
|
||||
if (excludeValotisationStocklocation) {
|
||||
query += " AND (self.stockLocation.excludeValorisation is true)";
|
||||
}else{
|
||||
query += " AND (self.stockLocation.excludeValorisation is false or self.stockLocation.excludeValorisation is null)";
|
||||
}
|
||||
|
||||
if (company != null) {
|
||||
query += " AND self.stockLocation.company = " + company.getId();
|
||||
}
|
||||
|
||||
|
||||
BigDecimal qtyTot = BigDecimal.ZERO;
|
||||
List<List<Object>> results = JPA.em().createQuery(query).getResultList();
|
||||
if (results.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
for (List<Object> result : results) {
|
||||
BigDecimal qty = (BigDecimal) result.get(2);
|
||||
qtyTot = qtyTot.add(qty);
|
||||
}
|
||||
if (qtyTot.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
|
||||
System.out.println("***************query*************");
|
||||
System.out.println(query);
|
||||
System.out.println("***************qtyTot*************");
|
||||
System.out.println(qtyTot);
|
||||
|
||||
return qtyTot;
|
||||
}
|
||||
|
||||
// lines
|
||||
public List<StockMoveLine> lines = new ArrayList<>();
|
||||
|
||||
public void showLines(Long productId, Long stockMoveId, LocalDate toDateTime, BigDecimal price) {
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(stockMoveId);
|
||||
Product product = Beans.get(ProductRepository.class).find(productId);
|
||||
List<StockMoveLine> lines = getStockMoveLines(product, toDateTime, stockMove,false);
|
||||
System.out.println("*****************************************************");
|
||||
for (StockMoveLine line : lines) {
|
||||
System.out.println(line.getStockMove().getStockMoveSeq());
|
||||
}
|
||||
System.out.println("*****************************************************");
|
||||
int index = 1;
|
||||
List<StockMoveLine> lines2 = this.stockMoveLineStartingFromIndex(index, lines);
|
||||
System.out.println("********************lines2*********************************");
|
||||
for (StockMoveLine stockMoveLine : lines2) {
|
||||
if (stockMoveLine.getStockMove().getPartner() == stockMove.getCompany().getPartner()
|
||||
|| stockMoveLine.getStockMove().getPartner() == null) {
|
||||
System.out.println("Interne ***** " + stockMoveLine.getStockMove().getStockMoveSeq());
|
||||
} else if (stockMoveLine.getStockMove().getPartner().getId()
|
||||
!= stockMove.getCompany().getPartner().getId()) {
|
||||
index++;
|
||||
System.out.println(
|
||||
"Externe ***** "
|
||||
+ stockMoveLine.getStockMove().getStockMoveSeq()
|
||||
+ " ,id : "
|
||||
+ stockMoveLine.getStockMove().getId());
|
||||
this.showLines(productId, stockMoveLine.getStockMove().getId(), toDateTime, price);
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println("***********************lines2******************************");
|
||||
}
|
||||
|
||||
public void valorizeAll(LocalDate fromDateTime, Long productCategoryId) throws AxelorException {
|
||||
// ,67
|
||||
String query =
|
||||
"self.stockMove.statusSelect = ?1 "+
|
||||
"and self.stockMove.realDate >= ?2 and self.realQty > 0 and "+
|
||||
"self.product.familleProduit.id in ("+String.valueOf(productCategoryId)+") and self.stockMove.fromStockLocation.id = 12 and self.stockMove.partner.id != 853";
|
||||
List<Object> params = Lists.newArrayList();
|
||||
params.add(StockMoveRepository.STATUS_REALIZED);
|
||||
params.add(fromDateTime);
|
||||
|
||||
List<StockMoveLine> lines =
|
||||
stockMoveLineRepository
|
||||
.all()
|
||||
.filter(query, params.toArray())
|
||||
.order("stockMove.realDate")
|
||||
.order("id")
|
||||
.fetch();
|
||||
|
||||
|
||||
List<StockMoveLine> distinctLines = new ArrayList<>();
|
||||
List<Product> products = new ArrayList<>();
|
||||
|
||||
for (StockMoveLine line : lines) {
|
||||
if(products.indexOf(line.getProduct()) == -1){
|
||||
distinctLines.add(line);
|
||||
products.add(line.getProduct());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int index = lines.size();
|
||||
for (StockMoveLine line : distinctLines) {
|
||||
System.out.println("Starting ............... "+String.valueOf(index));
|
||||
System.out.println("Size ............... "+String.valueOf(distinctLines.size()));
|
||||
System.out.println(line.getStockMove().getStockMoveSeq());
|
||||
System.out.println(line.getProductName());
|
||||
System.out.println(line.getProduct().getId());
|
||||
this.resetValorization(line.getProduct().getId(), line.getStockMove().getId(), LocalDate.now(),false);
|
||||
this.fillStockMoveLines(line.getProduct().getId(), LocalDate.now(), line.getStockMove().getId(),false);
|
||||
this.valorize(line.getProduct().getId(), line.getStockMove().getId(), LocalDate.now(), line.getUnitPriceUntaxed(), false,false);
|
||||
System.out.println("End .....................");
|
||||
index --;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List<StockMoveLine> sliceStockMoveLines(List<StockMoveLine> lines,Long stockMoveId,Product product){
|
||||
|
||||
StockMoveLine emp = lines.stream().filter((t) -> {
|
||||
return t.getStockMove().getId() == stockMoveId && t.getProduct() == product;
|
||||
}).findFirst().orElse(null);
|
||||
|
||||
int index = lines.indexOf(emp);
|
||||
|
||||
List<StockMoveLine> slicedLines = new ArrayList<>();
|
||||
|
||||
for (int i = index; i < lines.size(); i++) {
|
||||
slicedLines.add(lines.get(i));
|
||||
}
|
||||
return slicedLines;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
import com.axelor.apps.sale.db.SaleOrder;
|
||||
import com.axelor.apps.sale.db.repo.SaleOrderRepository;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.supplychain.exception.IExceptionMessage;
|
||||
import com.axelor.apps.tool.StringTool;
|
||||
@@ -46,7 +45,6 @@ import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -523,16 +521,17 @@ public class StockMoveMultiInvoiceServiceImpl implements StockMoveMultiInvoiceSe
|
||||
} else {
|
||||
stockMoveList.forEach(
|
||||
stockMove -> {
|
||||
|
||||
Set<Invoice> invoiceSet = new HashSet<>();
|
||||
invoiceSet.add(invoice);
|
||||
stockMove.setInvoiceSet(invoiceSet);
|
||||
|
||||
String sqlString = String.format("INSERT INTO public.account_invoice_stock_move_set( invoice_set, stock_move_set) VALUES (:invoiceSet, :stockMoveSet)");
|
||||
javax.persistence.Query query = JPA.em().createNativeQuery(sqlString);
|
||||
query.setParameter("invoiceSet", invoice.getId());
|
||||
query.setParameter("stockMoveSet", stockMove.getId());
|
||||
JPA.runInTransaction(query::executeUpdate);
|
||||
Set<Invoice> invoiceSet = new HashSet<>();
|
||||
invoiceSet.add(invoice);
|
||||
stockMove.setInvoiceSet(invoiceSet);
|
||||
|
||||
String sqlString =
|
||||
String.format(
|
||||
"INSERT INTO public.account_invoice_stock_move_set( invoice_set, stock_move_set) VALUES (:invoiceSet, :stockMoveSet)");
|
||||
javax.persistence.Query query = JPA.em().createNativeQuery(sqlString);
|
||||
query.setParameter("invoiceSet", invoice.getId());
|
||||
query.setParameter("stockMoveSet", stockMove.getId());
|
||||
JPA.runInTransaction(query::executeUpdate);
|
||||
});
|
||||
return Optional.of(invoice);
|
||||
}
|
||||
@@ -679,7 +678,9 @@ public class StockMoveMultiInvoiceServiceImpl implements StockMoveMultiInvoiceSe
|
||||
/** This method will throw an exception if the given stock move is already invoiced. */
|
||||
protected void checkIfAlreadyInvoiced(StockMove stockMove) throws AxelorException {
|
||||
if (stockMove.getInvoiceSet() != null
|
||||
&& stockMove.getInvoiceSet().stream()
|
||||
&& stockMove
|
||||
.getInvoiceSet()
|
||||
.stream()
|
||||
.anyMatch(invoice -> invoice.getStatusSelect() != InvoiceRepository.STATUS_CANCELED)) {
|
||||
String templateMessage;
|
||||
if (stockMove.getTypeSelect() == StockMoveRepository.TYPE_OUTGOING) {
|
||||
@@ -827,7 +828,11 @@ public class StockMoveMultiInvoiceServiceImpl implements StockMoveMultiInvoiceSe
|
||||
? purchaseOrderRepository.find(stockMove.getOriginId())
|
||||
: null;
|
||||
if (purchaseOrder != null) {
|
||||
externalRefList.add(purchaseOrder.getExternalReference());
|
||||
if (purchaseOrder.getExternalReference() != null) {
|
||||
if (!purchaseOrder.getExternalReference().isEmpty()) {
|
||||
externalRefList.add(purchaseOrder.getExternalReference());
|
||||
}
|
||||
}
|
||||
}
|
||||
internalRefList.add(
|
||||
stockMove.getStockMoveSeq()
|
||||
|
||||
@@ -443,73 +443,69 @@ public class StockMoveServiceSupplychainImpl extends StockMoveServiceImpl
|
||||
}
|
||||
|
||||
// same move
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public StockMove splitInto2SameMove(
|
||||
StockMove originalStockMove, List<StockMoveLine> modifiedStockMoveLines)
|
||||
throws AxelorException {
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public StockMove splitInto2SameMove(
|
||||
StockMove originalStockMove, List<StockMoveLine> modifiedStockMoveLines)
|
||||
throws AxelorException {
|
||||
|
||||
StockMoveRepository stockMoveRepo = Beans.get(StockMoveRepository.class);
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
StockMoveRepository stockMoveRepo = Beans.get(StockMoveRepository.class);
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
|
||||
modifiedStockMoveLines =
|
||||
modifiedStockMoveLines
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getQty().compareTo(BigDecimal.ZERO) != 0)
|
||||
.collect(Collectors.toList());
|
||||
for (StockMoveLine moveLine : modifiedStockMoveLines) {
|
||||
StockMoveLine newStockMoveLine = new StockMoveLine();
|
||||
// Set quantity in new stock move line
|
||||
newStockMoveLine = stockMoveLineRepo.copy(moveLine, false);
|
||||
newStockMoveLine.setQty(moveLine.getQty());
|
||||
newStockMoveLine.setRealQty(moveLine.getQty());
|
||||
newStockMoveLine.setProductTypeSelect(moveLine.getProductTypeSelect());
|
||||
newStockMoveLine.setSaleOrderLine(moveLine.getSaleOrderLine());
|
||||
newStockMoveLine.setPurchaseOrderLine(moveLine.getPurchaseOrderLine());
|
||||
newStockMoveLine.setCompanyUnitPriceUntaxed(moveLine.getCompanyUnitPriceUntaxed());
|
||||
newStockMoveLine.setUg(moveLine.getUg());
|
||||
newStockMoveLine.setPpa(moveLine.getPpa());
|
||||
newStockMoveLine.setPvg(moveLine.getPvg());
|
||||
newStockMoveLine.setStklim(moveLine.getStklim());
|
||||
newStockMoveLine.setShp(moveLine.getShp());
|
||||
// add stock move line
|
||||
originalStockMove.addStockMoveLineListItem(newStockMoveLine);
|
||||
|
||||
// find the original move line to update it
|
||||
Optional<StockMoveLine> correspondingMoveLine =
|
||||
originalStockMove
|
||||
.getStockMoveLineList()
|
||||
modifiedStockMoveLines =
|
||||
modifiedStockMoveLines
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getId().equals(moveLine.getId()))
|
||||
.findFirst();
|
||||
if (BigDecimal.ZERO.compareTo(moveLine.getQty()) > 0
|
||||
|| (correspondingMoveLine.isPresent()
|
||||
&& moveLine.getQty().compareTo(correspondingMoveLine.get().getRealQty()) > 0)) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||
I18n.get(""),
|
||||
originalStockMove);
|
||||
}
|
||||
.filter(stockMoveLine -> stockMoveLine.getQty().compareTo(BigDecimal.ZERO) != 0)
|
||||
.collect(Collectors.toList());
|
||||
for (StockMoveLine moveLine : modifiedStockMoveLines) {
|
||||
StockMoveLine newStockMoveLine = new StockMoveLine();
|
||||
// Set quantity in new stock move line
|
||||
newStockMoveLine = stockMoveLineRepo.copy(moveLine, false);
|
||||
newStockMoveLine.setQty(moveLine.getQty());
|
||||
newStockMoveLine.setRealQty(moveLine.getQty());
|
||||
newStockMoveLine.setProductTypeSelect(moveLine.getProductTypeSelect());
|
||||
newStockMoveLine.setSaleOrderLine(moveLine.getSaleOrderLine());
|
||||
newStockMoveLine.setPurchaseOrderLine(moveLine.getPurchaseOrderLine());
|
||||
newStockMoveLine.setCompanyUnitPriceUntaxed(moveLine.getCompanyUnitPriceUntaxed());
|
||||
newStockMoveLine.setUg(moveLine.getUg());
|
||||
newStockMoveLine.setPpa(moveLine.getPpa());
|
||||
newStockMoveLine.setPvg(moveLine.getPvg());
|
||||
newStockMoveLine.setStklim(moveLine.getStklim());
|
||||
newStockMoveLine.setShp(moveLine.getShp());
|
||||
// add stock move line
|
||||
originalStockMove.addStockMoveLineListItem(newStockMoveLine);
|
||||
|
||||
if (correspondingMoveLine.isPresent()) {
|
||||
// Update quantity in original stock move.
|
||||
// If the remaining quantity is 0, remove the stock move line
|
||||
BigDecimal remainingQty = correspondingMoveLine.get().getQty().subtract(moveLine.getQty());
|
||||
if (BigDecimal.ZERO.compareTo(remainingQty) == 0) {
|
||||
// Remove the stock move line
|
||||
originalStockMove.removeStockMoveLineListItem(correspondingMoveLine.get());
|
||||
} else {
|
||||
correspondingMoveLine.get().setQty(remainingQty);
|
||||
correspondingMoveLine.get().setRealQty(remainingQty);
|
||||
// find the original move line to update it
|
||||
Optional<StockMoveLine> correspondingMoveLine =
|
||||
originalStockMove
|
||||
.getStockMoveLineList()
|
||||
.stream()
|
||||
.filter(stockMoveLine -> stockMoveLine.getId().equals(moveLine.getId()))
|
||||
.findFirst();
|
||||
if (BigDecimal.ZERO.compareTo(moveLine.getQty()) > 0
|
||||
|| (correspondingMoveLine.isPresent()
|
||||
&& moveLine.getQty().compareTo(correspondingMoveLine.get().getRealQty()) > 0)) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY, I18n.get(""), originalStockMove);
|
||||
}
|
||||
|
||||
if (correspondingMoveLine.isPresent()) {
|
||||
// Update quantity in original stock move.
|
||||
// If the remaining quantity is 0, remove the stock move line
|
||||
BigDecimal remainingQty = correspondingMoveLine.get().getQty().subtract(moveLine.getQty());
|
||||
if (BigDecimal.ZERO.compareTo(remainingQty) == 0) {
|
||||
// Remove the stock move line
|
||||
originalStockMove.removeStockMoveLineListItem(correspondingMoveLine.get());
|
||||
} else {
|
||||
correspondingMoveLine.get().setQty(remainingQty);
|
||||
correspondingMoveLine.get().setRealQty(remainingQty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!originalStockMove.getStockMoveLineList().isEmpty()) {
|
||||
return stockMoveRepo.save(originalStockMove);
|
||||
} else {
|
||||
return null;
|
||||
if (!originalStockMove.getStockMoveLineList().isEmpty()) {
|
||||
return stockMoveRepo.save(originalStockMove);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ public class StockRulesServiceSupplychainImpl extends StockRulesServiceImpl {
|
||||
supplierPartner.getCurrency(),
|
||||
today.plusDays(supplierPartner.getDeliveryDelay()),
|
||||
stockRules.getName(),
|
||||
"",
|
||||
null,
|
||||
stockLocation,
|
||||
today,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 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 com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.supplychain.db.SupplierRating;
|
||||
|
||||
public interface SupplierRatingService {
|
||||
|
||||
public void calculatRating(SupplierRating supplierRating);
|
||||
|
||||
public void createRating(StockMove stockMove);
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
package com.axelor.apps.supplychain.service;
|
||||
|
||||
import com.axelor.apps.account.db.PaymentCondition;
|
||||
import com.axelor.apps.base.db.Partner;
|
||||
import com.axelor.apps.base.db.Product;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrder;
|
||||
import com.axelor.apps.purchase.db.PurchaseOrderLine;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderLineRepository;
|
||||
import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.supplychain.db.SupplierRating;
|
||||
import com.axelor.apps.supplychain.db.repo.SupplierRatingRepository;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SupplierRatingServiceImpl implements SupplierRatingService {
|
||||
|
||||
public final int COEF_PAYMENT_DELAY = 1;
|
||||
public final int COEF_DELIVERY_TIME = 1;
|
||||
public final int COEF_COMPLIANCE_WITH_TECHNICAL_SPECIFICATIONS = 3;
|
||||
public final int COEF_PRICE = 3;
|
||||
public final int COEF_QUANTITY_COMPLIANCE = 1;
|
||||
public final int COEF_COMPLAINT_MANAGEMENT = 1;
|
||||
public final int COEF_PRICE_STABILITY = 1;
|
||||
public final int SUM_COEF =
|
||||
COEF_PAYMENT_DELAY
|
||||
+ COEF_DELIVERY_TIME
|
||||
+ COEF_COMPLIANCE_WITH_TECHNICAL_SPECIFICATIONS
|
||||
+ COEF_PRICE
|
||||
+ COEF_QUANTITY_COMPLIANCE
|
||||
+ COEF_COMPLAINT_MANAGEMENT
|
||||
+ COEF_PRICE_STABILITY;
|
||||
|
||||
public void calculatRating(SupplierRating supplierRating) {
|
||||
Integer paymentDelayRatingSelect = supplierRating.getPaymentDelayRatingSelect();
|
||||
Integer deliveryTimeRatingSelect = supplierRating.getDeliveryTimeRatingSelect();
|
||||
Integer complianceWithTechnicalSpecificationsRatingSelect =
|
||||
supplierRating.getComplianceWithTechnicalSpecificationsRatingSelect();
|
||||
Integer priceRatingSelect = supplierRating.getPriceRatingSelect();
|
||||
Integer quantityComplianceRatingSelect = supplierRating.getQuantityComplianceRatingSelect();
|
||||
Integer complaintManagementRatingSelect = supplierRating.getComplaintManagementRatingSelect();
|
||||
Integer priceStabilityRatingSelect = supplierRating.getPriceStabilityRatingSelect();
|
||||
|
||||
// Calculate the overall score based on ratings
|
||||
int score =
|
||||
(paymentDelayRatingSelect * COEF_PAYMENT_DELAY)
|
||||
+ (deliveryTimeRatingSelect * COEF_DELIVERY_TIME)
|
||||
+ (complianceWithTechnicalSpecificationsRatingSelect
|
||||
* COEF_COMPLIANCE_WITH_TECHNICAL_SPECIFICATIONS)
|
||||
+ (priceRatingSelect * COEF_PRICE)
|
||||
+ (quantityComplianceRatingSelect * COEF_QUANTITY_COMPLIANCE)
|
||||
+ (complaintManagementRatingSelect * COEF_COMPLAINT_MANAGEMENT)
|
||||
+ (priceStabilityRatingSelect * COEF_PRICE_STABILITY);
|
||||
|
||||
// Set the overall score
|
||||
BigDecimal overallScore =
|
||||
BigDecimal.valueOf(score * 20)
|
||||
.divide(BigDecimal.valueOf(SUM_COEF * 3), 2, BigDecimal.ROUND_HALF_UP);
|
||||
supplierRating.setOverallScore(overallScore);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void createRating(StockMove stockMove) {
|
||||
|
||||
StockMove stockMoveOrigin = stockMove.getStockMoveOrigin();
|
||||
Boolean isWithBackorder = stockMove.getIsWithBackorder();
|
||||
|
||||
if (stockMoveOrigin == null) {
|
||||
LocalDateTime realDate;
|
||||
if (isWithBackorder == true) {
|
||||
realDate = stockMove.getRealDate();
|
||||
} else {
|
||||
realDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
Partner partner = stockMove.getPartner();
|
||||
|
||||
// Stock Move Lines
|
||||
List<StockMoveLine> stockMoveLinesList = stockMove.getStockMoveLineList();
|
||||
|
||||
// Purchase Order
|
||||
Long originId = stockMove.getOriginId();
|
||||
PurchaseOrder purchaseOrder = Beans.get(PurchaseOrderRepository.class).find(originId);
|
||||
|
||||
// Purchase Order Lines
|
||||
List<PurchaseOrderLine> purchaseOrderLinesList = purchaseOrder.getPurchaseOrderLineList();
|
||||
|
||||
// Délai de payment
|
||||
PaymentCondition paymentCondition = purchaseOrder.getPaymentCondition();
|
||||
Integer paymentTime = paymentCondition.getPaymentTime();
|
||||
Integer paymentDelayRatingSelect = calculatPaymentDelayRatingSelect(paymentTime);
|
||||
|
||||
// Date
|
||||
LocalDate estimatedDate = purchaseOrder.getDeliveryDate();
|
||||
Integer deliveryTimeRatingSelect = calculatDeliveryTimeRatingSelect(estimatedDate, realDate);
|
||||
|
||||
// Quantité
|
||||
Integer quantityComplianceRatingSelect =
|
||||
calculatQuantityComplianceRatingSelect(stockMoveLinesList);
|
||||
|
||||
// Stabilité des prix
|
||||
Integer priceStabilityRatingSelect =
|
||||
calculatPriceStabilityRatingSelectLastPrice(purchaseOrderLinesList, partner);
|
||||
|
||||
// Creation
|
||||
SupplierRating supplierRating = new SupplierRating();
|
||||
supplierRating.setPaymentDelayRatingSelect(paymentDelayRatingSelect);
|
||||
supplierRating.setDeliveryTimeRatingSelect(deliveryTimeRatingSelect);
|
||||
supplierRating.setQuantityComplianceRatingSelect(quantityComplianceRatingSelect);
|
||||
supplierRating.setPriceStabilityRatingSelect(priceStabilityRatingSelect);
|
||||
supplierRating.setPurchaseOrder(purchaseOrder);
|
||||
supplierRating.setSupplierPartner(partner);
|
||||
Beans.get(SupplierRatingRepository.class).save(supplierRating);
|
||||
|
||||
} else {
|
||||
// Purchase Order
|
||||
Long originId = stockMove.getOriginId();
|
||||
PurchaseOrder purchaseOrder = Beans.get(PurchaseOrderRepository.class).find(originId);
|
||||
|
||||
List<StockMove> originStockMoves =
|
||||
Beans.get(StockMoveRepository.class)
|
||||
.all()
|
||||
.fetch()
|
||||
.stream()
|
||||
.filter(t -> t.getOriginId() == originId && t.getStatusSelect() == 3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Purchase Order Lines
|
||||
List<PurchaseOrderLine> purchaseOrderLinesList = purchaseOrder.getPurchaseOrderLineList();
|
||||
|
||||
// Related Stock Moves Lines
|
||||
List<StockMoveLine> originStockMovesLines = new ArrayList<>();
|
||||
for (StockMove originStockMove : originStockMoves) {
|
||||
// Stock Move Lines
|
||||
List<StockMoveLine> originStockMovesLinesList = originStockMove.getStockMoveLineList();
|
||||
originStockMovesLines.addAll(originStockMovesLinesList);
|
||||
}
|
||||
// Quantité
|
||||
Integer quantityComplianceRatingSelect =
|
||||
calculatQuantityComplianceRatingSelect(purchaseOrderLinesList, originStockMovesLines);
|
||||
|
||||
// update
|
||||
SupplierRating supplierRating = purchaseOrder.getSupplierRating();
|
||||
supplierRating.setQuantityComplianceRatingSelect(quantityComplianceRatingSelect);
|
||||
}
|
||||
}
|
||||
|
||||
private Integer calculatPaymentDelayRatingSelect(Integer paymentTime) {
|
||||
Integer paymentDelayRatingSelect;
|
||||
if (paymentTime == 0) {
|
||||
paymentDelayRatingSelect = 0;
|
||||
} else if (paymentTime <= 15) {
|
||||
paymentDelayRatingSelect = 1;
|
||||
} else if (paymentTime <= 30) {
|
||||
paymentDelayRatingSelect = 2;
|
||||
} else {
|
||||
paymentDelayRatingSelect = 3;
|
||||
}
|
||||
return paymentDelayRatingSelect;
|
||||
}
|
||||
|
||||
private Integer calculatDeliveryTimeRatingSelect(LocalDate estimatedDate, LocalDateTime realDate) {
|
||||
int deliveryTimeRatingSelect;
|
||||
if (realDate.toLocalDate().isBefore(estimatedDate.plusDays(1))) {
|
||||
deliveryTimeRatingSelect = 3;
|
||||
} else if (realDate.toLocalDate().isBefore(estimatedDate.plusDays(5))) {
|
||||
deliveryTimeRatingSelect = 2;
|
||||
} else if (realDate.toLocalDate().isBefore(estimatedDate.plusDays(15))) {
|
||||
deliveryTimeRatingSelect = 1;
|
||||
} else {
|
||||
deliveryTimeRatingSelect = 0;
|
||||
}
|
||||
return deliveryTimeRatingSelect;
|
||||
}
|
||||
|
||||
private Integer calculatQuantityComplianceRatingSelect(List<StockMoveLine> stockMoveLinesList) {
|
||||
// Calculate total ordered quantity
|
||||
BigDecimal totalOrderedQty = BigDecimal.ZERO;
|
||||
BigDecimal totalReceivedQty = BigDecimal.ZERO;
|
||||
for (StockMoveLine stockMoveLine : stockMoveLinesList) {
|
||||
BigDecimal orderedQty = stockMoveLine.getQty();
|
||||
totalOrderedQty = totalOrderedQty.add(orderedQty);
|
||||
BigDecimal receivedQty = stockMoveLine.getRealQty();
|
||||
totalReceivedQty = totalReceivedQty.add(receivedQty);
|
||||
}
|
||||
|
||||
// Calculate quantity compliance
|
||||
BigDecimal compliancePercentage;
|
||||
if (totalOrderedQty.compareTo(BigDecimal.ZERO) != 0) {
|
||||
compliancePercentage =
|
||||
totalReceivedQty
|
||||
.divide(totalOrderedQty, 2, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
} else {
|
||||
// Handle division by zero if necessary
|
||||
compliancePercentage = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
System.out.println("totalOrderedQty1:" + totalOrderedQty);
|
||||
System.out.println("totalReceivedQty1:" + totalReceivedQty);
|
||||
System.out.println("compliancePercentage1:" + compliancePercentage);
|
||||
|
||||
// Determine quantityComplianceRatingSelect based on compliancePercentage
|
||||
Integer quantityComplianceRatingSelect;
|
||||
if (compliancePercentage.compareTo(BigDecimal.valueOf(100)) >= 0) {
|
||||
quantityComplianceRatingSelect = 3;
|
||||
} else if (compliancePercentage.compareTo(BigDecimal.valueOf(80)) >= 0) {
|
||||
quantityComplianceRatingSelect = 2;
|
||||
} else if (compliancePercentage.compareTo(BigDecimal.valueOf(70)) >= 0) {
|
||||
quantityComplianceRatingSelect = 1;
|
||||
} else {
|
||||
quantityComplianceRatingSelect = 0;
|
||||
}
|
||||
return quantityComplianceRatingSelect;
|
||||
}
|
||||
|
||||
private Integer calculatQuantityComplianceRatingSelect(
|
||||
List<PurchaseOrderLine> purchaseOrderLineslist, List<StockMoveLine> stockMoveLinesList) {
|
||||
// Calculate total ordered quantity
|
||||
BigDecimal totalOrderedQty = BigDecimal.ZERO;
|
||||
BigDecimal totalReceivedQty = BigDecimal.ZERO;
|
||||
for (StockMoveLine stockMoveLine : stockMoveLinesList) {
|
||||
BigDecimal receivedQty = stockMoveLine.getRealQty();
|
||||
totalReceivedQty = totalReceivedQty.add(receivedQty);
|
||||
}
|
||||
|
||||
for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLineslist) {
|
||||
BigDecimal orderedQty = purchaseOrderLine.getQty();
|
||||
totalOrderedQty = totalOrderedQty.add(orderedQty);
|
||||
}
|
||||
// Calculate quantity compliance
|
||||
BigDecimal compliancePercentage;
|
||||
if (totalOrderedQty.compareTo(BigDecimal.ZERO) != 0) {
|
||||
compliancePercentage =
|
||||
totalReceivedQty
|
||||
.divide(totalOrderedQty, 2, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
} else {
|
||||
// Handle division by zero if necessary
|
||||
compliancePercentage = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
System.out.println("totalOrderedQty2:" + totalOrderedQty);
|
||||
System.out.println("totalReceivedQty2:" + totalReceivedQty);
|
||||
System.out.println("compliancePercentage2:" + compliancePercentage);
|
||||
|
||||
// Determine quantityComplianceRatingSelect based on compliancePercentage
|
||||
Integer quantityComplianceRatingSelect;
|
||||
if (compliancePercentage.compareTo(BigDecimal.valueOf(100)) >= 0) {
|
||||
quantityComplianceRatingSelect = 3;
|
||||
} else if (compliancePercentage.compareTo(BigDecimal.valueOf(80)) >= 0) {
|
||||
quantityComplianceRatingSelect = 2;
|
||||
} else if (compliancePercentage.compareTo(BigDecimal.valueOf(70)) >= 0) {
|
||||
quantityComplianceRatingSelect = 1;
|
||||
} else {
|
||||
quantityComplianceRatingSelect = 0;
|
||||
}
|
||||
return quantityComplianceRatingSelect;
|
||||
}
|
||||
|
||||
private Integer calculatPriceStabilityRatingSelect(
|
||||
List<PurchaseOrderLine> purchaseOrderLinesList, Partner partner) {
|
||||
List<Product> products = new ArrayList<>();
|
||||
for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLinesList) {
|
||||
Product product = purchaseOrderLine.getProduct();
|
||||
products.add(product);
|
||||
}
|
||||
|
||||
List<BigDecimal> averages = new ArrayList<>();
|
||||
for (Product product : products) {
|
||||
BigDecimal avg = calculateAvgProduct(product, partner);
|
||||
averages.add(avg);
|
||||
}
|
||||
|
||||
List<BigDecimal> differences = new ArrayList<>();
|
||||
for (int i = 0; i < purchaseOrderLinesList.size(); i++) {
|
||||
BigDecimal price = purchaseOrderLinesList.get(i).getPrice();
|
||||
BigDecimal avg = averages.get(i);
|
||||
|
||||
BigDecimal difference = price.subtract(avg);
|
||||
BigDecimal percentage =
|
||||
difference.divide(avg, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
|
||||
|
||||
differences.add(percentage.abs());
|
||||
}
|
||||
|
||||
BigDecimal totalDifference = BigDecimal.ZERO;
|
||||
for (BigDecimal difference : differences) {
|
||||
totalDifference = totalDifference.add(difference);
|
||||
}
|
||||
|
||||
// Calculate the average percentage difference
|
||||
BigDecimal averageDifference =
|
||||
totalDifference.divide(BigDecimal.valueOf(differences.size()), 2, BigDecimal.ROUND_HALF_UP);
|
||||
|
||||
// Determine priceStabilityRatingSelect based on the average percentage difference
|
||||
Integer priceStabilityRatingSelect;
|
||||
if (averageDifference.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
priceStabilityRatingSelect = 3; // Stable prices
|
||||
} else if (averageDifference.compareTo(BigDecimal.valueOf(5)) <= 0) {
|
||||
priceStabilityRatingSelect = 2; // Moderately stable prices
|
||||
} else if (averageDifference.compareTo(BigDecimal.valueOf(10)) <= 0) {
|
||||
priceStabilityRatingSelect = 1; // Unstable prices
|
||||
} else {
|
||||
priceStabilityRatingSelect = 0;
|
||||
}
|
||||
|
||||
return priceStabilityRatingSelect;
|
||||
}
|
||||
|
||||
private Integer calculatPriceStabilityRatingSelectLastPrice(
|
||||
List<PurchaseOrderLine> purchaseOrderLinesList, Partner partner) {
|
||||
List<Product> products = new ArrayList<>();
|
||||
for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLinesList) {
|
||||
Product product = purchaseOrderLine.getProduct();
|
||||
products.add(product);
|
||||
}
|
||||
|
||||
List<BigDecimal> lastPrices = new ArrayList<>();
|
||||
for (Product product : products) {
|
||||
BigDecimal lastPrice = getLastPriceProduct(product, partner);
|
||||
lastPrices.add(lastPrice);
|
||||
}
|
||||
|
||||
List<BigDecimal> differences = new ArrayList<>();
|
||||
for (int i = 0; i < purchaseOrderLinesList.size(); i++) {
|
||||
BigDecimal price = purchaseOrderLinesList.get(i).getPrice();
|
||||
BigDecimal lastPrice = lastPrices.get(i);
|
||||
|
||||
BigDecimal difference = price.subtract(lastPrice);
|
||||
BigDecimal percentage =
|
||||
difference
|
||||
.divide(lastPrice, 4, BigDecimal.ROUND_HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
|
||||
differences.add(percentage);
|
||||
}
|
||||
|
||||
BigDecimal totalDifference = BigDecimal.ZERO;
|
||||
for (BigDecimal difference : differences) {
|
||||
totalDifference = totalDifference.add(difference);
|
||||
}
|
||||
|
||||
// Calculate the average percentage difference
|
||||
BigDecimal averageDifference =
|
||||
totalDifference.divide(BigDecimal.valueOf(differences.size()), 2, BigDecimal.ROUND_HALF_UP);
|
||||
|
||||
// Determine priceStabilityRatingSelect based on the average percentage difference
|
||||
Integer priceStabilityRatingSelect;
|
||||
if (averageDifference.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
priceStabilityRatingSelect = 3; // Stable prices
|
||||
} else if (averageDifference.compareTo(BigDecimal.valueOf(5)) <= 0) {
|
||||
priceStabilityRatingSelect = 2; // Moderately stable prices
|
||||
} else if (averageDifference.compareTo(BigDecimal.valueOf(10)) <= 0) {
|
||||
priceStabilityRatingSelect = 1; // Unstable prices
|
||||
} else {
|
||||
priceStabilityRatingSelect = 0;
|
||||
}
|
||||
|
||||
return priceStabilityRatingSelect;
|
||||
}
|
||||
|
||||
private BigDecimal calculateAvgProduct(Product product, Partner partner) {
|
||||
// Beans.get(PurchaseOrderRepository.class).find(originId);
|
||||
/*List<PurchaseOrderLine> purchaseOrderLines = Beans.get(PurchaseOrderLineRepository.class)
|
||||
.all()
|
||||
.filter("self.purchaseOrder.supplierPartner = :partner AND self.product = :product")
|
||||
.bind("partner", partner)
|
||||
.bind("product", product)
|
||||
.fetch();*/
|
||||
|
||||
List<PurchaseOrderLine> purchaseOrderLines =
|
||||
Beans.get(PurchaseOrderLineRepository.class)
|
||||
.all()
|
||||
.fetch()
|
||||
.stream()
|
||||
.filter(
|
||||
t ->
|
||||
t.getPurchaseOrder().getSupplierPartner() == partner
|
||||
&& t.getProduct() == product)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (purchaseOrderLines != null && !purchaseOrderLines.isEmpty()) {
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLines) {
|
||||
BigDecimal price = purchaseOrderLine.getPrice();
|
||||
total = total.add(price);
|
||||
}
|
||||
BigDecimal avgPrice =
|
||||
total.divide(BigDecimal.valueOf(purchaseOrderLines.size()), 2, BigDecimal.ROUND_HALF_UP);
|
||||
return avgPrice;
|
||||
}
|
||||
// Handle the case where there are no purchase order lines for the given product and partner
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private BigDecimal getLastPriceProduct(Product product, Partner partner) {
|
||||
|
||||
List<PurchaseOrderLine> purchaseOrderLines = Beans.get(PurchaseOrderLineRepository.class)
|
||||
.all()
|
||||
.filter("self.purchaseOrder.supplierPartner = :partner AND self.product = :product")
|
||||
.bind("partner", partner)
|
||||
.bind("product", product)
|
||||
.fetch();
|
||||
|
||||
PurchaseOrderLine lastPurchaseOrderLine =
|
||||
purchaseOrderLines.isEmpty() ? null : purchaseOrderLines.get(purchaseOrderLines.size() - 1);
|
||||
if (lastPurchaseOrderLine != null) {
|
||||
BigDecimal price = lastPurchaseOrderLine.getPrice();
|
||||
return price;
|
||||
} else {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
package com.axelor.apps.supplychain.web;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.MalformedURLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.axelor.apps.account.db.Invoice;
|
||||
import com.axelor.apps.account.db.InvoiceLine;
|
||||
import com.axelor.apps.account.db.InvoiceTemplate;
|
||||
import com.axelor.apps.account.db.PaymentVoucher;
|
||||
import com.axelor.apps.account.db.repo.InvoiceTemplateRepository;
|
||||
import com.axelor.apps.base.db.Product;
|
||||
import com.axelor.apps.base.db.Wizard;
|
||||
import com.axelor.apps.purchase.db.ImportationFolder;
|
||||
import com.axelor.apps.purchase.db.repo.ImportationFolderRepository;
|
||||
import com.axelor.apps.purchase.service.print.ImportationFolderPrintService;
|
||||
import com.axelor.apps.report.engine.ReportSettings;
|
||||
import com.axelor.apps.stock.db.ImportationFolderCostPrice;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.StockProductionRequest;
|
||||
import com.axelor.apps.stock.db.repo.ImportationFolderCostPriceRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.stock.exception.IExceptionMessage;
|
||||
import com.axelor.apps.stock.service.StockMoveService;
|
||||
import com.axelor.apps.stock.service.stockmove.print.StockProductionRequestPrintService;
|
||||
import com.axelor.apps.supplychain.service.ImportationFolderServiceImpl;
|
||||
import com.axelor.apps.supplychain.service.StockMoveLineServiceSupplychainImpl;
|
||||
import com.axelor.apps.supplychain.service.app.AppSupplychainService;
|
||||
import com.axelor.common.ObjectUtils;
|
||||
import com.axelor.db.mapper.Mapper;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.schema.actions.ActionView;
|
||||
import com.axelor.meta.schema.actions.ActionView.ActionViewBuilder;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.axelor.rpc.Context;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import wslite.json.JSONException;
|
||||
|
||||
public class ImportationFolderController {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public void calculateAvgPrice(ActionRequest request, ActionResponse response)
|
||||
throws MalformedURLException, JSONException, AxelorException {
|
||||
|
||||
ImportationFolder iimportationFolder =
|
||||
(ImportationFolder) request.getContext().asType(ImportationFolder.class);
|
||||
ImportationFolder importationFolder =
|
||||
Beans.get(ImportationFolderRepository.class).find(iimportationFolder.getId());
|
||||
List<StockMoveLine> stockMoveLines = importationFolder.getStockMoveLineList();
|
||||
|
||||
List<Long> invoiceIds =
|
||||
Beans.get(ImportationFolderServiceImpl.class).calculateAvgPriceAndGenerateInvoice(stockMoveLines, importationFolder);
|
||||
|
||||
response.setView(
|
||||
ActionView.define("Invoice")
|
||||
.model(Invoice.class.getName())
|
||||
.add("grid", "invoice-grid")
|
||||
.add("form", "invoice-form")
|
||||
.domain("self.id in (" + Joiner.on(",").join(invoiceIds) + ")")
|
||||
.param("forceEdit", "true")
|
||||
.context("todayDate", Beans.get(AppSupplychainService.class).getTodayDate())
|
||||
.map());
|
||||
|
||||
}
|
||||
|
||||
public void computeCostPrice(ActionRequest request, ActionResponse response)
|
||||
throws MalformedURLException, JSONException, AxelorException {
|
||||
|
||||
ImportationFolder iimportationFolder =
|
||||
(ImportationFolder) request.getContext().asType(ImportationFolder.class);
|
||||
ImportationFolder importationFolder =
|
||||
Beans.get(ImportationFolderRepository.class).find(iimportationFolder.getId());
|
||||
|
||||
String msg = Beans.get(ImportationFolderServiceImpl.class).computeCostPrice(importationFolder);
|
||||
|
||||
response.setAlert(msg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void setStockMoveLineCurrenyRate(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
List<HashMap> selectedStockMoveLineMapList =
|
||||
(List<HashMap>) request.getContext().get("stockMoveLineList");
|
||||
Map importationFolderMap = (Map<String, Object>) request.getContext().get("importationFolder");
|
||||
if (selectedStockMoveLineMapList == null) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_14));
|
||||
return;
|
||||
}
|
||||
|
||||
List<StockMoveLine> stockMoveLineList = new ArrayList<>();
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
for (HashMap map : selectedStockMoveLineMapList) {
|
||||
StockMoveLine stockMoveLine = (StockMoveLine) Mapper.toBean(StockMoveLine.class, map);
|
||||
stockMoveLineList.add(stockMoveLineRepo.find(stockMoveLine.getId()));
|
||||
}
|
||||
|
||||
if (stockMoveLineList.isEmpty()) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_15));
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal currencyRate = new BigDecimal(request.getContext().get("currencyRate").toString());
|
||||
if (currencyRate == null || currencyRate.compareTo(BigDecimal.ZERO) < 0) {
|
||||
response.setFlash("Please enter a valid currency rate");
|
||||
return;
|
||||
}
|
||||
|
||||
ImportationFolder importationFolder = Mapper.toBean(ImportationFolder.class, importationFolderMap);
|
||||
importationFolder = Beans.get(ImportationFolderRepository.class).find(importationFolder.getId());
|
||||
Beans.get(ImportationFolderServiceImpl.class)
|
||||
.setStockMoveLineCurrenyRate(stockMoveLineList, currencyRate);
|
||||
response.setCanClose(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void setStockMoveLineFreight(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
List<HashMap> selectedStockMoveLineMapList =
|
||||
(List<HashMap>) request.getContext().get("stockMoveLineList");
|
||||
Map importationFolderMap = (Map<String, Object>) request.getContext().get("importationFolder");
|
||||
if (selectedStockMoveLineMapList == null) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_14));
|
||||
return;
|
||||
}
|
||||
|
||||
List<StockMoveLine> stockMoveLineList = new ArrayList<>();
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
for (HashMap map : selectedStockMoveLineMapList) {
|
||||
StockMoveLine stockMoveLine = (StockMoveLine) Mapper.toBean(StockMoveLine.class, map);
|
||||
stockMoveLineList.add(stockMoveLineRepo.find(stockMoveLine.getId()));
|
||||
}
|
||||
|
||||
if (stockMoveLineList.isEmpty()) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_15));
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal freight = new BigDecimal(request.getContext().get("freight").toString());
|
||||
if (freight == null || freight.compareTo(BigDecimal.ZERO) < 0) {
|
||||
response.setFlash("Please enter a valid freight");
|
||||
return;
|
||||
}
|
||||
|
||||
ImportationFolder importationFolder = Mapper.toBean(ImportationFolder.class, importationFolderMap);
|
||||
importationFolder = Beans.get(ImportationFolderRepository.class).find(importationFolder.getId());
|
||||
Beans.get(ImportationFolderServiceImpl.class).setStockMoveLineFreight(stockMoveLineList, freight);
|
||||
response.setCanClose(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void setStockMoveLineNetMass(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
List<HashMap> selectedStockMoveLineMapList =
|
||||
(List<HashMap>) request.getContext().get("stockMoveLineList");
|
||||
Map importationFolderMap = (Map<String, Object>) request.getContext().get("importationFolder");
|
||||
if (selectedStockMoveLineMapList == null) {
|
||||
response.setFlash("No selected move line");
|
||||
return;
|
||||
}
|
||||
|
||||
List<StockMoveLine> stockMoveLineList = new ArrayList<>();
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
for (HashMap map : selectedStockMoveLineMapList) {
|
||||
StockMoveLine stockMoveLine = (StockMoveLine) Mapper.toBean(StockMoveLine.class, map);
|
||||
stockMoveLineList.add(stockMoveLineRepo.find(stockMoveLine.getId()));
|
||||
}
|
||||
|
||||
if (stockMoveLineList.isEmpty()) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_15));
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal netMass = new BigDecimal(request.getContext().get("netMass").toString());
|
||||
if (netMass == null || netMass.compareTo(BigDecimal.ZERO) < 0) {
|
||||
response.setFlash("Please enter a valid mass");
|
||||
return;
|
||||
}
|
||||
|
||||
ImportationFolder importationFolder = Mapper.toBean(ImportationFolder.class, importationFolderMap);
|
||||
importationFolder = Beans.get(ImportationFolderRepository.class).find(importationFolder.getId());
|
||||
Beans.get(ImportationFolderServiceImpl.class)
|
||||
.setStockMoveLineNetMass(stockMoveLineList, netMass);
|
||||
response.setCanClose(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void setStockMoveLineVolume(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
List<HashMap> selectedStockMoveLineMapList =
|
||||
(List<HashMap>) request.getContext().get("stockMoveLineList");
|
||||
Map importationFolderMap = (Map<String, Object>) request.getContext().get("importationFolder");
|
||||
if (selectedStockMoveLineMapList == null) {
|
||||
response.setFlash("No selected move line");
|
||||
return;
|
||||
}
|
||||
|
||||
List<StockMoveLine> stockMoveLineList = new ArrayList<>();
|
||||
StockMoveLineRepository stockMoveLineRepo = Beans.get(StockMoveLineRepository.class);
|
||||
for (HashMap map : selectedStockMoveLineMapList) {
|
||||
StockMoveLine stockMoveLine = (StockMoveLine) Mapper.toBean(StockMoveLine.class, map);
|
||||
stockMoveLineList.add(stockMoveLineRepo.find(stockMoveLine.getId()));
|
||||
}
|
||||
|
||||
if (stockMoveLineList.isEmpty()) {
|
||||
response.setFlash(I18n.get(IExceptionMessage.STOCK_MOVE_15));
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal volume = new BigDecimal(request.getContext().get("volume").toString());
|
||||
if (volume == null || volume.compareTo(BigDecimal.ZERO) < 0) {
|
||||
response.setFlash("Please enter a valid mass");
|
||||
return;
|
||||
}
|
||||
|
||||
ImportationFolder importationFolder = Mapper.toBean(ImportationFolder.class, importationFolderMap);
|
||||
importationFolder = Beans.get(ImportationFolderRepository.class).find(importationFolder.getId());
|
||||
Beans.get(ImportationFolderServiceImpl.class)
|
||||
.setStockMoveLineVolume(stockMoveLineList, volume);
|
||||
response.setCanClose(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void validateCostPrice(ActionRequest request, ActionResponse response) {
|
||||
|
||||
ImportationFolderCostPrice importationFolderCostPrice =
|
||||
Beans.get(ImportationFolderCostPriceRepository.class)
|
||||
.find(request.getContext().asType(ImportationFolderCostPrice.class).getId());
|
||||
// sophal refresh purchase order price
|
||||
|
||||
try {
|
||||
Beans.get(ImportationFolderServiceImpl.class).validateCostPrice(importationFolderCostPrice);
|
||||
response.setReload(true);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void confirmRejectView(ActionRequest request, ActionResponse response) {
|
||||
ImportationFolder ImportationFolderContext = request.getContext().asType(ImportationFolder.class);
|
||||
ImportationFolder importationFolder =
|
||||
Beans.get(ImportationFolderRepository.class).find(ImportationFolderContext.getId());
|
||||
|
||||
ActionViewBuilder confirmView =
|
||||
ActionView.define("Confirm rejection")
|
||||
.model(Wizard.class.getName())
|
||||
.add("form", "action-importation-folder-rejection-form")
|
||||
.param("popup", "true")
|
||||
.param("show-toolbar", "false")
|
||||
.param("show-confirm", "false")
|
||||
.param("popup-save", "false")
|
||||
.param("forceEdit", "true");
|
||||
|
||||
confirmView.context("importationFolderId", importationFolder.getId());
|
||||
response.setView(confirmView.map());
|
||||
}
|
||||
|
||||
|
||||
public void rejectImportationFolder(ActionRequest request, ActionResponse response)
|
||||
throws AxelorException {
|
||||
|
||||
int importationFolderId = (int) request.getContext().get("importationFolderId");
|
||||
String rejectionRaison = (String) request.getContext().get("rejectionRaison");
|
||||
String rejectionInstance = (String) request.getContext().get("$rejectedInstanceSelect");
|
||||
ImportationFolder importationFolder =
|
||||
Beans.get(ImportationFolderRepository.class).find((long) importationFolderId);
|
||||
|
||||
Beans.get(ImportationFolderServiceImpl.class).rejectImportationFolder(importationFolder, rejectionRaison);
|
||||
|
||||
response.setCanClose(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void print(ActionRequest request, ActionResponse response) {
|
||||
|
||||
Context context = request.getContext();
|
||||
String fileLink;
|
||||
String title;
|
||||
|
||||
ImportationFolderPrintService importationFolderPrintService = Beans.get(ImportationFolderPrintService.class);
|
||||
|
||||
try {
|
||||
if (context.get("id") != null) {
|
||||
ImportationFolder importationFolder = request.getContext().asType(ImportationFolder.class);
|
||||
title = importationFolderPrintService.getFileName(importationFolder);
|
||||
fileLink =
|
||||
importationFolderPrintService.printCostPriceSheet(
|
||||
importationFolder, ReportSettings.FORMAT_PDF);
|
||||
logger.debug("Printing " + title);
|
||||
} else {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.INVENTORY_3_DATA_NULL_OR_EMPTY));
|
||||
}
|
||||
response.setView(ActionView.define(title).add("html", fileLink).map());
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void generateFromModel(ActionRequest request, ActionResponse response) throws AxelorException{
|
||||
Long importationFolderId = (Long) request.getContext().get("id");
|
||||
ImportationFolder importationFolder =
|
||||
Beans.get(ImportationFolderRepository.class).find((long) importationFolderId);
|
||||
InvoiceTemplate template = (InvoiceTemplate) request.getContext().get("$invoiceTemplate");
|
||||
InvoiceTemplate invoiceTemplate = Beans.get(InvoiceTemplateRepository.class).find(template.getId());
|
||||
|
||||
Invoice invoice = Beans.get(ImportationFolderServiceImpl.class).generateFromModel(importationFolder, invoiceTemplate);
|
||||
|
||||
response.setView(
|
||||
ActionView.define("Invoice")
|
||||
.model(Invoice.class.getName())
|
||||
.add("grid", "invoice-grid")
|
||||
.add("form", "invoice-form")
|
||||
.param("forceEdit", "true")
|
||||
.context("_showRecord", String.valueOf(invoice.getId()))
|
||||
.context("_operationTypeSelect", invoice.getOperationTypeSelect())
|
||||
.context("todayDate", Beans.get(AppSupplychainService.class).getTodayDate())
|
||||
.map());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.axelor.apps.supplychain.web;
|
||||
|
||||
public class ImportationFolderCostPriceController {
|
||||
|
||||
}
|
||||
@@ -17,23 +17,11 @@
|
||||
*/
|
||||
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;
|
||||
@@ -44,9 +32,6 @@ 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 {
|
||||
@@ -143,10 +128,10 @@ public class MrpController {
|
||||
* @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);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.axelor.apps.supplychain.web;
|
||||
|
||||
import com.axelor.apps.account.service.app.AppAccountService;
|
||||
import com.axelor.apps.base.db.AppBudget;
|
||||
import com.axelor.apps.base.db.CancelReason;
|
||||
import com.axelor.apps.base.db.Company;
|
||||
import com.axelor.apps.base.db.Currency;
|
||||
import com.axelor.apps.base.db.Partner;
|
||||
@@ -176,6 +177,9 @@ public class PurchaseOrderController {
|
||||
// purchase orders
|
||||
boolean existLocationDiff = false;
|
||||
boolean allTradingNamesAreNull = true;
|
||||
// determine diff in status select
|
||||
boolean eqStatusSelect = true;
|
||||
int statusSelect = -1;
|
||||
|
||||
PurchaseOrder purchaseOrderTemp;
|
||||
int count = 1;
|
||||
@@ -191,7 +195,11 @@ public class PurchaseOrderController {
|
||||
commonLocation = purchaseOrderTemp.getStockLocation();
|
||||
commonTradingName = purchaseOrderTemp.getTradingName();
|
||||
allTradingNamesAreNull = commonTradingName == null;
|
||||
statusSelect = purchaseOrderTemp.getStatusSelect();
|
||||
} else {
|
||||
if (purchaseOrderTemp.getStatusSelect() != statusSelect) {
|
||||
eqStatusSelect = false;
|
||||
}
|
||||
if (commonCurrency != null && !commonCurrency.equals(purchaseOrderTemp.getCurrency())) {
|
||||
commonCurrency = null;
|
||||
}
|
||||
@@ -255,6 +263,12 @@ public class PurchaseOrderController {
|
||||
com.axelor.apps.purchase.exception.IExceptionMessage
|
||||
.PURCHASE_ORDER_MERGE_ERROR_TRADING_NAME));
|
||||
}
|
||||
if (!eqStatusSelect) {
|
||||
fieldErrors.append(
|
||||
I18n.get(
|
||||
com.axelor.apps.purchase.exception.IExceptionMessage
|
||||
.PURCHASE_ORDER_MERGE_ERROR_STATUS_SELECT));
|
||||
}
|
||||
|
||||
if (fieldErrors.length() > 0) {
|
||||
response.setFlash(fieldErrors.toString());
|
||||
@@ -414,4 +428,20 @@ public class PurchaseOrderController {
|
||||
TraceBackService.trace(response, e, ResponseMessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public void finishPurchaseOrder(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
PurchaseOrder purchaseOrder = request.getContext().asType(PurchaseOrder.class);
|
||||
purchaseOrder = Beans.get(PurchaseOrderRepository.class).find(purchaseOrder.getId());
|
||||
CancelReason cancelReason = (CancelReason) request.getContext().get("cancelReason");
|
||||
String cancelReasonStr = (String) request.getContext().get("cancelReasonStr");
|
||||
System.out.println(">>>>>>>>>>>>>>>>>>> " + cancelReasonStr);
|
||||
Beans.get(PurchaseOrderServiceSupplychainImpl.class)
|
||||
.finishSockMoves(purchaseOrder, cancelReason, cancelReasonStr);
|
||||
|
||||
response.setReload(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,10 @@ import com.axelor.apps.base.db.Company;
|
||||
import com.axelor.apps.sale.db.SaleOrder;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.stock.service.StockMoveService;
|
||||
import com.axelor.apps.supplychain.db.SupplyChainConfig;
|
||||
import com.axelor.apps.supplychain.exception.IExceptionMessage;
|
||||
import com.axelor.apps.supplychain.service.SaleOrderReservedQtyService;
|
||||
import com.axelor.apps.supplychain.service.SaleOrderServiceSupplychainImpl;
|
||||
import com.axelor.apps.supplychain.service.SaleOrderStockService;
|
||||
import com.axelor.apps.supplychain.service.StockMoveServiceSupplychain;
|
||||
import com.axelor.apps.supplychain.service.StockMoveServiceSupplychainImpl;
|
||||
@@ -38,8 +35,6 @@ import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -17,15 +17,22 @@
|
||||
*/
|
||||
package com.axelor.apps.supplychain.web;
|
||||
|
||||
import com.axelor.apps.base.db.repo.FamilleProduitRepository;
|
||||
import com.axelor.apps.stock.db.StockMoveLine;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveLineRepository;
|
||||
import com.axelor.apps.supplychain.service.StockMoveLineServiceSupplychainImpl;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.axelor.rpc.Context;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.xpath.operations.Bool;
|
||||
|
||||
public class StockMoveLineController {
|
||||
|
||||
@@ -175,4 +182,60 @@ public class StockMoveLineController {
|
||||
}
|
||||
response.setValue("subLineList", subLines);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void valorize(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
Long productId = new Long((Integer) ((Map) request.getContext().get("product")).get("id"));
|
||||
Long stockMoveId =
|
||||
new Long((Integer) ((Map) request.getContext().get("stockMove")).get("id"));
|
||||
LocalDate fromDateTime = LocalDate.parse(request.getContext().get("fromDateTime").toString());
|
||||
BigDecimal val = new BigDecimal(request.getContext().get("val").toString());
|
||||
Boolean updatePo = false;
|
||||
if(request.getContext().get("updatePo") != null){
|
||||
updatePo = (Boolean) request.getContext().get("updatePo");
|
||||
}
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).resetValorization(productId, stockMoveId, fromDateTime,false);
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).fillStockMoveLines(productId, fromDateTime, stockMoveId,false);
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).valorize(productId, stockMoveId, fromDateTime, val,updatePo,false);
|
||||
response.setNotify("Recalcul Terminé");
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void valorizeAll(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
|
||||
LocalDate fromDateTime = LocalDate.parse(request.getContext().get("fromDateTime").toString());
|
||||
Long productCategoryId = new Long((Integer) ((Map) request.getContext().get("productCategory")).get("id"));
|
||||
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class).valorizeAll(fromDateTime,productCategoryId);
|
||||
response.setNotify("Recalcul Terminé");
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void showLines(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
Long productId = new Long((Integer) ((Map) request.getContext().get("product")).get("id"));
|
||||
Long stockMoveId =
|
||||
new Long((Integer) ((Map) request.getContext().get("stockMove")).get("id"));
|
||||
LocalDate fromDateTime = LocalDate.parse(request.getContext().get("fromDateTime").toString());
|
||||
BigDecimal val = new BigDecimal(request.getContext().get("val").toString());
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class)
|
||||
.resetValorization(productId, stockMoveId, fromDateTime,false);
|
||||
Beans.get(StockMoveLineServiceSupplychainImpl.class)
|
||||
.showLines(productId, stockMoveId, fromDateTime, val);
|
||||
response.setNotify("Recalcul Terminé");
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.axelor.apps.supplychain.web;
|
||||
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.supplychain.db.SupplierRating;
|
||||
import com.axelor.apps.supplychain.service.SupplierRatingServiceImpl;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import javax.inject.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SupplierRatingController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SupplierRatingController.class);
|
||||
|
||||
private SupplierRatingServiceImpl service;
|
||||
|
||||
@Inject
|
||||
public SupplierRatingController(SupplierRatingServiceImpl service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public void rating(ActionRequest request, ActionResponse response) {
|
||||
|
||||
SupplierRating supplierRating = request.getContext().asType(SupplierRating.class);
|
||||
|
||||
Integer paymentDelayRatingSelect = supplierRating.getPaymentDelayRatingSelect();
|
||||
Integer deliveryTimeRatingSelect = supplierRating.getDeliveryTimeRatingSelect();
|
||||
Integer complianceWithTechnicalSpecificationsRatingSelect =
|
||||
supplierRating.getComplianceWithTechnicalSpecificationsRatingSelect();
|
||||
Integer priceRatingSelect = supplierRating.getPriceRatingSelect();
|
||||
Integer quantityComplianceRatingSelect = supplierRating.getQuantityComplianceRatingSelect();
|
||||
Integer complaintManagementRatingSelect = supplierRating.getComplaintManagementRatingSelect();
|
||||
Integer priceStabilityRatingSelect = supplierRating.getPriceStabilityRatingSelect();
|
||||
|
||||
if (paymentDelayRatingSelect != null
|
||||
&& deliveryTimeRatingSelect != null
|
||||
&& complianceWithTechnicalSpecificationsRatingSelect != null
|
||||
&& priceRatingSelect != null
|
||||
&& quantityComplianceRatingSelect != null
|
||||
&& complaintManagementRatingSelect != null
|
||||
&& priceStabilityRatingSelect != null) {
|
||||
service.calculatRating(supplierRating);
|
||||
response.setValue("overallScore", supplierRating.getOverallScore());
|
||||
} else {
|
||||
String message = "You should fill all Fields First.";
|
||||
response.setFlash(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void rateSupplier(ActionRequest request, ActionResponse response) {
|
||||
System.out.println("Start");
|
||||
StockMove stockMovetemp = request.getContext().asType(StockMove.class);
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(stockMovetemp.getId());
|
||||
service.createRating(stockMove);
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,27 @@
|
||||
*/
|
||||
package com.axelor.apps.supplychain.web;
|
||||
|
||||
import com.axelor.apps.account.db.Move;
|
||||
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||
import com.axelor.apps.base.db.Batch;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
import com.axelor.apps.supplychain.db.SupplychainBatch;
|
||||
import com.axelor.apps.supplychain.db.repo.SupplychainBatchRepository;
|
||||
import com.axelor.apps.supplychain.service.AccountingCutOffServiceImpl;
|
||||
import com.axelor.apps.supplychain.service.batch.SupplychainBatchService;
|
||||
import com.axelor.common.ObjectUtils;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.schema.actions.ActionView;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class SupplychainBatchController {
|
||||
@@ -53,4 +66,75 @@ public class SupplychainBatchController {
|
||||
response.setFlash(batch.getComments());
|
||||
response.setReload(true);
|
||||
}
|
||||
|
||||
public void generateMove(ActionRequest request, ActionResponse response) throws AxelorException {
|
||||
StockMove stockMove = request.getContext().asType(StockMove.class);
|
||||
stockMove = Beans.get(StockMoveRepository.class).find(stockMove.getId());
|
||||
Move move = Beans.get(AccountingCutOffServiceImpl.class).generateStockAccountMove(stockMove);
|
||||
response.setView(
|
||||
ActionView.define(stockMove.getStockMoveSeq())
|
||||
.model(Move.class.getName())
|
||||
.add("form", "move-form")
|
||||
.add("grid", "move-grid")
|
||||
.param("forceTitle", "true")
|
||||
.context("_showRecord", move.getId().toString())
|
||||
.domain("self.id = " + move.getId())
|
||||
.map());
|
||||
}
|
||||
|
||||
public void massGenerationMove(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Long> ids =
|
||||
(List)
|
||||
(((List) request.getContext().get("_ids"))
|
||||
.stream()
|
||||
.filter(ObjectUtils::notEmpty)
|
||||
.map(input -> Long.parseLong(input.toString()))
|
||||
.collect(Collectors.toList()));
|
||||
List<Long> moveList = Beans.get(AccountingCutOffServiceImpl.class).massGenerationMove(ids);
|
||||
|
||||
if (moveList != null && !moveList.isEmpty()) {
|
||||
response.setView(
|
||||
ActionView.define(I18n.get(IExceptionMessage.MOVE_TEMPLATE_3))
|
||||
.model(Move.class.getName())
|
||||
.add("grid", "move-grid")
|
||||
.add("form", "move-form")
|
||||
.domain("self.id in (" + Joiner.on(",").join(moveList) + ")")
|
||||
.map());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void generateInventoryLineMove(ActionRequest request, ActionResponse response) {
|
||||
try {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Long> ids =
|
||||
(List)
|
||||
(((List) request.getContext().get("_ids"))
|
||||
.stream()
|
||||
.filter(ObjectUtils::notEmpty)
|
||||
.map(input -> Long.parseLong(input.toString()))
|
||||
.collect(Collectors.toList()));
|
||||
List<Long> moveList = Beans.get(AccountingCutOffServiceImpl.class).massGenerationInventoryLineMove(ids);
|
||||
|
||||
if (moveList != null && !moveList.isEmpty()) {
|
||||
response.setView(
|
||||
ActionView.define(I18n.get(IExceptionMessage.MOVE_TEMPLATE_3))
|
||||
.model(Move.class.getName())
|
||||
.add("grid", "move-grid")
|
||||
.add("form", "move-form")
|
||||
.domain("self.id in (" + Joiner.on(",").join(moveList) + ")")
|
||||
.map());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.axelor.inject.Beans;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -113,7 +114,7 @@ public class ImportSupplyChain {
|
||||
StockMove stockMove = Beans.get(StockMoveRepository.class).find(id);
|
||||
stockMoveService.copyQtyToRealQty(stockMove);
|
||||
stockMoveService.realize(stockMove);
|
||||
stockMove.setRealDate(purchaseOrder.getDeliveryDate());
|
||||
stockMove.setRealDate(LocalDateTime.now());
|
||||
}
|
||||
purchaseOrder.setValidationDate(purchaseOrder.getOrderDate());
|
||||
purchaseOrder.setValidatedByUser(AuthUtils.getUser());
|
||||
@@ -137,7 +138,7 @@ public class ImportSupplyChain {
|
||||
invoice.setOriginDate(date.minusDays(15));
|
||||
|
||||
invoiceService.validateAndVentilate(invoice);
|
||||
purchaseOrderServiceSupplychainImpl.finishPurchaseOrder(purchaseOrder);
|
||||
purchaseOrderServiceSupplychainImpl.finishPurchaseOrder(purchaseOrder, "");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -187,7 +188,7 @@ public class ImportSupplyChain {
|
||||
stockMoveService.copyQtyToRealQty(stockMove);
|
||||
stockMoveService.validate(stockMove);
|
||||
if (saleOrder.getConfirmationDateTime() != null) {
|
||||
stockMove.setRealDate(saleOrder.getConfirmationDateTime().toLocalDate());
|
||||
stockMove.setRealDate(LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="testUnit" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
|
||||
<properties>
|
||||
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/bdd_sophal" />
|
||||
|
||||
<property name="javax.persistence.jdbc.user" value="postgres" />
|
||||
<property name="javax.persistence.jdbc.password" value="Ijlv=bB^hSG@PV$,9jkhHzO*74" />
|
||||
|
||||
<!--
|
||||
value="create" to build a new database on each run;
|
||||
value="update" to modify an existing database;
|
||||
value="create-drop" means the same as "create" but also drops tables when Hibernate closes;
|
||||
value="validate" makes no changes to the database
|
||||
-->
|
||||
<property name="hibernate.hbm2ddl.auto" value="update" />
|
||||
|
||||
<!--
|
||||
<property name="hibernate.show_sql" value="true"/>
|
||||
-->
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -8,6 +8,7 @@
|
||||
<entity sequential="true" name="Move" lang="java">
|
||||
|
||||
<many-to-one name="stockMove" ref="com.axelor.apps.stock.db.StockMove" title="Stock move"/>
|
||||
<many-to-one name="inventoryLine" ref="com.axelor.apps.stock.db.InventoryLine" title="Stock inventory line"/>
|
||||
|
||||
</entity>
|
||||
</domain-models>
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
<integer name="scenario" title="Scenario" selection="mrp.scenario.select"/>
|
||||
<boolean name="displayProductWithoutProposal" title="Display product without proposal" default="false"/>
|
||||
<boolean name="includeBOM" title="Include Bom" default="false"/>
|
||||
<boolean name="includePurchaseQty" title="Include Purchase qty" default="false"/>
|
||||
<boolean name="includeFutureQty" title="Include Future qty" default="false"/>
|
||||
<boolean name="includeBomWaste" title="Include Bom waste" default="false"/>
|
||||
<boolean name="includeStockRule" title="Include stock rule" default="false"/>
|
||||
|
||||
<extra-code><![CDATA[
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="supplychain" package="com.axelor.apps.supplychain.db"/>
|
||||
|
||||
<entity name="MrpLineSaleAndMargin" lang="java">
|
||||
<many-to-one name="mrp" ref="com.axelor.apps.supplychain.db.Mrp" title="Mrp"/>
|
||||
<many-to-one name="product" ref="com.axelor.apps.base.db.Product" title="Product"/>
|
||||
|
||||
<decimal name="firstQuarterMax" title="First Quarter" />
|
||||
<decimal name="secondQuarterMax" title="Second Quarter" />
|
||||
<decimal name="thirdQuarterMax" title="Third Quarter" />
|
||||
<decimal name="forthQuarterMax" title="Forth Quarter" />
|
||||
<decimal name="firstQuarterMarge" title="First Quarter" />
|
||||
<decimal name="secondQuarterMarge" title="Second Quarter" />
|
||||
<decimal name="thirdQuarterMarge" title="Third Quarter" />
|
||||
<decimal name="forthQuarterMarge" title="Forth Quarter" />
|
||||
<many-to-one name="company" ref="com.axelor.apps.base.db.Company" title="Company" transient="true"/>
|
||||
<many-to-one name="unit" ref="com.axelor.apps.base.db.Unit" title="Unit" transient="true"/>
|
||||
<many-to-one name="productOrigin" ref="com.axelor.apps.base.db.Product" title="Product Origin"/>
|
||||
|
||||
|
||||
<extra-code><![CDATA[
|
||||
// AVAILABLE SCENARIOS
|
||||
public static final int MIN = 1;
|
||||
public static final int MAX = 2;
|
||||
public static final int HIST = 3;
|
||||
]]></extra-code>
|
||||
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@@ -7,6 +7,9 @@
|
||||
<many-to-one name="mrp" ref="com.axelor.apps.supplychain.db.Mrp" title="Mrp"/>
|
||||
<many-to-one name="product" ref="com.axelor.apps.base.db.Product" title="Product"/>
|
||||
<decimal name="qty" title="Qty"/>
|
||||
<decimal name="initialQty" title="Initial Qty"/>
|
||||
<decimal name="purchaseOrderQty" title="Purchase Order Qty"/>
|
||||
<decimal name="futureQty" title="Future Qty"/>
|
||||
<decimal name="january" title="January" />
|
||||
<decimal name="february" title="February" />
|
||||
<decimal name="march" title="March" />
|
||||
@@ -23,6 +26,7 @@
|
||||
<many-to-one name="company" ref="com.axelor.apps.base.db.Company" title="Company" transient="true"/>
|
||||
<many-to-one name="unit" ref="com.axelor.apps.base.db.Unit" title="Unit" transient="true"/>
|
||||
<decimal name="securityStock" title="Security Stock" />
|
||||
<decimal name="totalQtyUsed" title="Total qty used" />
|
||||
<many-to-one name="productOrigin" ref="com.axelor.apps.base.db.Product" title="Product Origin"/>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="base" package="com.axelor.apps.base.db"/>
|
||||
|
||||
<entity name="Partner" lang="java">
|
||||
<one-to-many name="supplierRatingList" title="Supplier Rating List" ref="com.axelor.apps.supplychain.db.SupplierRating" mappedBy="supplierPartner"/>
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="supplychain" package="com.axelor.apps.supplychain.db"/>
|
||||
|
||||
<entity name="ProductionMasterPlan" lang="java">
|
||||
<many-to-one name="mrp" ref="com.axelor.apps.supplychain.db.Mrp" title="Mrp"/>
|
||||
<many-to-one name="product" ref="com.axelor.apps.base.db.Product" title="Product"/>
|
||||
<decimal name="annualQty" title="Annual Qty"/>
|
||||
<decimal name="annualBatchQty" title="Annual batch Qty"/>
|
||||
<decimal name="january" title="January" />
|
||||
<decimal name="february" title="February" />
|
||||
<decimal name="march" title="March" />
|
||||
<decimal name="april" title="April" />
|
||||
<decimal name="may" title="May" />
|
||||
<decimal name="juin" title="Juin" />
|
||||
<decimal name="july" title="July" />
|
||||
<decimal name="august" title="August" />
|
||||
<decimal name="september" title="September" />
|
||||
<decimal name="october" title="October" />
|
||||
<decimal name="november" title="November" />
|
||||
<decimal name="december" title="December" />
|
||||
<decimal name="januaryBatchQty" title="January batch qty" />
|
||||
<decimal name="februaryBatchQty" title="February batch qty" />
|
||||
<decimal name="marchBatchQty" title="March batch qty" />
|
||||
<decimal name="aprilBatchQty" title="April batch qty" />
|
||||
<decimal name="mayBatchQty" title="May batch qty" />
|
||||
<decimal name="juinBatchQty" title="Juin batch qty" />
|
||||
<decimal name="julyBatchQty" title="July batch qty" />
|
||||
<decimal name="augustBatchQty" title="August batch qty" />
|
||||
<decimal name="septemberBatchQty" title="September batch qty" />
|
||||
<decimal name="octoberBatchQty" title="October batch qty" />
|
||||
<decimal name="novemberBatchQty" title="November batch qty" />
|
||||
<decimal name="decemberBatchQty" title="December batch qty" />
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@@ -20,6 +20,9 @@
|
||||
<boolean name="interco" title="Interco"/>
|
||||
<boolean name="createdByInterco" default="false"/>
|
||||
|
||||
<!-- Supplier Rating -->
|
||||
<one-to-one name="supplierRating" title="Supplier Rating List" ref="com.axelor.apps.supplychain.db.SupplierRating" mappedBy="purchaseOrder"/>
|
||||
|
||||
<many-to-one name="budget" ref="com.axelor.apps.account.db.Budget" title="Budget"/>
|
||||
<long name="generatedSaleOrderId"/>
|
||||
</entity>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="supplychain" package="com.axelor.apps.supplychain.db"/>
|
||||
|
||||
<entity name="SalesMasterPlan" lang="java">
|
||||
<many-to-one name="mrp" ref="com.axelor.apps.supplychain.db.Mrp" title="Mrp"/>
|
||||
<many-to-one name="product" ref="com.axelor.apps.base.db.Product" title="Product"/>
|
||||
<decimal name="annualQty" title="Annual Qty"/>
|
||||
<decimal name="january" title="January" />
|
||||
<decimal name="february" title="February" />
|
||||
<decimal name="march" title="March" />
|
||||
<decimal name="april" title="April" />
|
||||
<decimal name="may" title="May" />
|
||||
<decimal name="juin" title="Juin" />
|
||||
<decimal name="july" title="July" />
|
||||
<decimal name="august" title="August" />
|
||||
<decimal name="september" title="September" />
|
||||
<decimal name="october" title="October" />
|
||||
<decimal name="november" title="November" />
|
||||
<decimal name="december" title="December" />
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@@ -21,6 +21,8 @@
|
||||
<one-to-many name="subLineList" ref="com.axelor.apps.stock.db.StockMoveLine"
|
||||
mappedBy="parentLine" title="Pack lines" />
|
||||
|
||||
<many-to-one name="account" ref="com.axelor.apps.account.db.Account" title="Accounting.Account"/>
|
||||
|
||||
<finder-method name="findAllBySaleOrder"
|
||||
using="com.axelor.apps.sale.db.SaleOrder:saleOrder" all="true"
|
||||
filter="self.stockMove.originTypeSelect LIKE 'com.axelor.apps.sale.db.SaleOrder' AND self.stockMove.originId = :saleOrder.id" />
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="supplychain" package="com.axelor.apps.supplychain.db"/>
|
||||
|
||||
<entity name="SupplierRating" lang="java">
|
||||
|
||||
<many-to-one name="supplierPartner" ref="com.axelor.apps.base.db.Partner" required="true" title="Supplier"/>
|
||||
<one-to-one name="purchaseOrder" ref="com.axelor.apps.purchase.db.PurchaseOrder" required="true" title="Order"/>
|
||||
<integer name="paymentDelayRatingSelect" title="Delay payment rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="deliveryTimeRatingSelect" title="Delivery time rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="complianceWithTechnicalSpecificationsRatingSelect" title="Compliance with technical specifications rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="priceRatingSelect" title="Price rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="quantityComplianceRatingSelect" title="Quantity compliance rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="complaintManagementRatingSelect" title="Complaint management rating" selection="supplier.rating.icon.select"/>
|
||||
<integer name="priceStabilityRatingSelect" title="Price stability rating" selection="supplier.rating.icon.select"/>
|
||||
<string name="description" title="Description" large="true"/>
|
||||
<decimal name="overallScore" title="Overall score"/>
|
||||
|
||||
<track>
|
||||
<field name="paymentDelayRatingSelect" />
|
||||
<field name="deliveryTimeRatingSelect" />
|
||||
<field name="complianceWithTechnicalSpecificationsRatingSelect" />
|
||||
<field name="priceRatingSelect" />
|
||||
<field name="quantityComplianceRatingSelect" />
|
||||
<field name="complaintManagementRatingSelect" />
|
||||
<field name="priceStabilityRatingSelect" />
|
||||
<field name="description" />
|
||||
<field name="overallScore" />
|
||||
</track>
|
||||
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.axelor.apps.supplychain;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.axelor.app.AxelorModule;
|
||||
import com.axelor.apps.base.db.repo.ProductRepository;
|
||||
import com.axelor.apps.base.module.AdminModule;
|
||||
import com.axelor.apps.base.module.BaseModule;
|
||||
import com.axelor.apps.base.service.ProductService;
|
||||
import com.axelor.apps.base.service.ProductServiceImpl;
|
||||
import com.axelor.apps.base.service.user.UserService;
|
||||
import com.axelor.apps.message.module.MessageModule;
|
||||
import com.axelor.apps.stock.module.StockModule;
|
||||
import com.axelor.apps.stock.service.StockMoveService;
|
||||
import com.axelor.apps.supplychain.TestStockMove.MyModule;
|
||||
import com.axelor.apps.tool.module.ToolModule;
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.db.JpaModule;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ObjectMapperProvider;
|
||||
import com.axelor.test.GuiceModules;
|
||||
import com.axelor.test.GuiceRunner;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import com.axelor.apps.stock.db.StockMove;
|
||||
import com.axelor.apps.stock.db.repo.StockMoveRepository;
|
||||
|
||||
|
||||
@RunWith(GuiceRunner.class)
|
||||
@GuiceModules({MyModule.class})
|
||||
public class TestStockMove {
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
|
||||
static ProductRepository productRepository ;
|
||||
|
||||
@Inject
|
||||
public StockMoveRepository stockMoveRepository;
|
||||
|
||||
public static class MyModule extends AxelorModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class);
|
||||
install(new JpaModule("testUnit", true, true));
|
||||
bind(Beans.class).asEagerSingleton();
|
||||
install(new ToolModule());
|
||||
install(new MessageModule());
|
||||
install(new AdminModule());
|
||||
install(new BaseModule());
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunc() throws AxelorException {
|
||||
assertNotNull(productRepository.all().fetch().get(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 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.db;
|
||||
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.db.JpaModel;
|
||||
import com.axelor.db.Query;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.MoreObjects.ToStringHelper;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Entity
|
||||
@Table(name = "STOCK_MOVE")
|
||||
public class StockMove extends JpaModel {
|
||||
|
||||
public StockMove() {}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -2,17 +2,25 @@
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="testUnit" transaction-type="RESOURCE_LOCAL">
|
||||
<persistence-unit name="baseProduct" transaction-type="RESOURCE_LOCAL">
|
||||
<description>
|
||||
Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide
|
||||
</description>
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
|
||||
|
||||
<!-- Provided in latest release of hibernate
|
||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||
-->
|
||||
|
||||
<properties>
|
||||
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/axelor-test" />
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/bdd_sophal" />
|
||||
|
||||
<property name="javax.persistence.jdbc.user" value="axelor" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
<property name="javax.persistence.jdbc.user" value="postgres" />
|
||||
<property name="javax.persistence.jdbc.password" value="Ijlv=bB^hSG@PV$,9jkhHzO*74" />
|
||||
|
||||
<!--
|
||||
value="create" to build a new database on each run;
|
||||
|
||||
Reference in New Issue
Block a user