use of com.axelor.apps.stock.db.StockMove in project axelor-open-suite by axelor.
the class StockMoveMultiInvoiceServiceImpl method createInvoiceFromMultiOutgoingStockMove.
@Override
@Transactional(rollbackOn = { Exception.class })
public Optional<Invoice> createInvoiceFromMultiOutgoingStockMove(List<StockMove> stockMoveList) throws AxelorException {
if (stockMoveList == null || stockMoveList.isEmpty()) {
return Optional.empty();
}
Set<Address> deliveryAddressSet = new HashSet<>();
// create dummy invoice from the first stock move
Invoice dummyInvoice = createDummyOutInvoice(stockMoveList.get(0));
// Check if field constraints are respected
for (StockMove stockMove : stockMoveList) {
completeInvoiceInMultiOutgoingStockMove(dummyInvoice, stockMove);
if (stockMove.getToAddressStr() != null) {
deliveryAddressSet.add(stockMove.getToAddress());
}
}
/* check if some other fields are different and assign a default value */
if (dummyInvoice.getAddress() == null) {
dummyInvoice.setAddress(Beans.get(PartnerService.class).getInvoicingAddress(dummyInvoice.getPartner()));
dummyInvoice.setAddressStr(Beans.get(AddressService.class).computeAddressStr(dummyInvoice.getAddress()));
}
fillReferenceInvoiceFromMultiOutStockMove(stockMoveList, dummyInvoice);
InvoiceGenerator invoiceGenerator = new InvoiceGenerator(InvoiceRepository.OPERATION_TYPE_CLIENT_SALE, dummyInvoice.getCompany(), dummyInvoice.getPaymentCondition(), dummyInvoice.getPaymentMode(), dummyInvoice.getAddress(), dummyInvoice.getPartner(), dummyInvoice.getContactPartner(), dummyInvoice.getCurrency(), dummyInvoice.getPriceList(), dummyInvoice.getInternalReference(), dummyInvoice.getExternalReference(), dummyInvoice.getInAti(), null, dummyInvoice.getTradingName(), dummyInvoice.getGroupProductsOnPrintings()) {
@Override
public Invoice generate() throws AxelorException {
Invoice invoice = super.createInvoiceHeader();
invoice.setPartnerTaxNbr(partner.getTaxNbr());
return invoice;
}
};
Invoice invoice = invoiceGenerator.generate();
invoice.setAddressStr(dummyInvoice.getAddressStr());
StringBuilder deliveryAddressStr = new StringBuilder();
AddressService addressService = Beans.get(AddressService.class);
for (Address address : deliveryAddressSet) {
deliveryAddressStr.append(addressService.computeAddressStr(address).replaceAll("\n", ", ") + "\n");
}
invoice.setDeliveryAddressStr(deliveryAddressStr.toString());
List<InvoiceLine> invoiceLineList = new ArrayList<>();
for (StockMove stockMoveLocal : stockMoveList) {
stockMoveInvoiceService.checkSplitSalePartiallyInvoicedStockMoveLines(stockMoveLocal, stockMoveLocal.getStockMoveLineList());
List<InvoiceLine> createdInvoiceLines = stockMoveInvoiceService.createInvoiceLines(invoice, stockMoveLocal, stockMoveLocal.getStockMoveLineList(), null);
if (stockMoveLocal.getTypeSelect() == StockMoveRepository.TYPE_INCOMING) {
createdInvoiceLines.forEach(this::negateInvoiceLinePrice);
}
invoiceLineList.addAll(createdInvoiceLines);
}
invoiceGenerator.populate(invoice, invoiceLineList);
invoiceRepository.save(invoice);
invoice = toPositivePriceInvoice(invoice);
if (invoice.getExTaxTotal().signum() == 0 && stockMoveList.stream().allMatch(StockMove::getIsReversion)) {
invoice.setOperationTypeSelect(InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND);
}
stockMoveList.forEach(invoice::addStockMoveSetItem);
return Optional.of(invoice);
}
use of com.axelor.apps.stock.db.StockMove in project axelor-open-suite by axelor.
the class StockMoveMultiInvoiceServiceImpl method generateMultipleInvoices.
@Override
public Entry<List<Long>, String> generateMultipleInvoices(List<Long> stockMoveIdList) {
StockMoveRepository stockMoveRepository = Beans.get(StockMoveRepository.class);
List<Long> invoiceIdList = new ArrayList<>();
StringBuilder stockMovesInError = new StringBuilder();
List<StockMove> stockMoveList;
Query<StockMove> stockMoveQuery = stockMoveRepository.all().filter("self.id IN :stockMoveIdList").bind("stockMoveIdList", stockMoveIdList).order("id");
int offset = 0;
while (!(stockMoveList = stockMoveQuery.fetch(AbstractBatch.FETCH_LIMIT, offset)).isEmpty()) {
for (StockMove stockMove : stockMoveList) {
offset++;
try {
Invoice invoice = stockMoveInvoiceService.createInvoice(stockMove, 0, null);
if (invoice != null) {
invoiceIdList.add(invoice.getId());
}
} catch (Exception e) {
if (stockMovesInError.length() > 0) {
stockMovesInError.append("<br/>");
}
stockMovesInError.append(String.format(I18n.get(IExceptionMessage.STOCK_MOVE_GENERATE_INVOICE), stockMove.getName(), e.getLocalizedMessage()));
break;
}
}
JPA.clear();
}
return new SimpleImmutableEntry<>(invoiceIdList, stockMovesInError.toString());
}
use of com.axelor.apps.stock.db.StockMove in project axelor-open-suite by axelor.
the class StockMoveInvoiceServiceImpl method createInvoiceFromPurchaseOrder.
@Override
@Transactional(rollbackOn = { Exception.class })
public Invoice createInvoiceFromPurchaseOrder(StockMove stockMove, PurchaseOrder purchaseOrder, Map<Long, BigDecimal> qtyToInvoiceMap) throws AxelorException {
if (!supplyChainConfigService.getSupplyChainConfig(stockMove.getCompany()).getActivateIncStockMovePartialInvoicing() && computeNonCanceledInvoiceQty(stockMove).signum() > 0) {
throw new AxelorException(TraceBackRepository.CATEGORY_INCONSISTENCY, I18n.get(IExceptionMessage.STOCK_MOVE_PARTIAL_INVOICE_ERROR));
}
InvoiceGenerator invoiceGenerator = purchaseOrderInvoiceService.createInvoiceGenerator(purchaseOrder, stockMove.getIsReversion());
Invoice invoice = invoiceGenerator.generate();
invoiceGenerator.populate(invoice, this.createInvoiceLines(invoice, stockMove, stockMove.getStockMoveLineList(), qtyToInvoiceMap));
if (invoice != null) {
// do not create empty invoices
if (invoice.getInvoiceLineList() == null || invoice.getInvoiceLineList().isEmpty()) {
return null;
}
this.extendInternalReference(stockMove, invoice);
invoice.setAddressStr(Beans.get(AddressService.class).computeAddressStr(invoice.getAddress()));
if (invoice != null) {
Set<StockMove> stockMoveSet = invoice.getStockMoveSet();
if (stockMoveSet == null) {
stockMoveSet = new HashSet<>();
invoice.setStockMoveSet(stockMoveSet);
}
stockMoveSet.add(stockMove);
}
invoiceRepository.save(invoice);
}
return invoice;
}
use of com.axelor.apps.stock.db.StockMove in project axelor-open-suite by axelor.
the class StockMoveInvoiceServiceImpl method createInvoiceLine.
@Override
public InvoiceLine createInvoiceLine(Invoice invoice, StockMoveLine stockMoveLine, BigDecimal qty) throws AxelorException {
Product product = stockMoveLine.getProduct();
boolean isTitleLine = false;
int sequence = InvoiceLineGenerator.DEFAULT_SEQUENCE;
SaleOrderLine saleOrderLine = stockMoveLine.getSaleOrderLine();
PurchaseOrderLine purchaseOrderLine = stockMoveLine.getPurchaseOrderLine();
if (saleOrderLine != null) {
sequence = saleOrderLine.getSequence();
} else if (purchaseOrderLine != null) {
if (purchaseOrderLine.getIsTitleLine()) {
isTitleLine = true;
}
sequence = purchaseOrderLine.getSequence();
}
// do not create lines with no qties
if ((qty == null || qty.signum() == 0 || stockMoveLine.getRealQty().signum() == 0) && !isTitleLine) {
return null;
}
if (product == null && !isTitleLine) {
throw new AxelorException(TraceBackRepository.CATEGORY_CONFIGURATION_ERROR, I18n.get(IExceptionMessage.STOCK_MOVE_INVOICE_1), stockMoveLine.getStockMove().getStockMoveSeq());
}
InvoiceLineGenerator invoiceLineGenerator = new InvoiceLineGeneratorSupplyChain(invoice, product, stockMoveLine.getProductName(), stockMoveLine.getDescription(), qty, stockMoveLine.getUnit(), sequence, false, stockMoveLine.getSaleOrderLine(), stockMoveLine.getPurchaseOrderLine(), stockMoveLine) {
@Override
public List<InvoiceLine> creates() throws AxelorException {
InvoiceLine invoiceLine = this.createInvoiceLine();
List<InvoiceLine> invoiceLines = new ArrayList<>();
invoiceLines.add(invoiceLine);
return invoiceLines;
}
};
List<InvoiceLine> invoiceLines = invoiceLineGenerator.creates();
InvoiceLine invoiceLine = null;
if (invoiceLines != null && !invoiceLines.isEmpty()) {
invoiceLine = invoiceLines.get(0);
if (!stockMoveLine.getIsMergedStockMoveLine()) {
// not a consolidated line so we can set the reference.
invoiceLine.setStockMoveLine(stockMoveLine);
} else {
// set the reference to a correct stock move line by following either the sale order line or
// purchase order line. We cannot have a consolidated line without purchase order line or
// sale order line reference
StockMoveLine nonConsolidatedStockMoveLine = null;
StockMove stockMove = stockMoveLine.getStockMove();
if (saleOrderLine != null) {
nonConsolidatedStockMoveLine = stockMoveLineRepository.all().filter("self.saleOrderLine.id = :saleOrderLineId " + "AND self.stockMove.id = :stockMoveId " + "AND self.id != :stockMoveLineId").bind("saleOrderLineId", saleOrderLine.getId()).bind("stockMoveId", stockMove.getId()).bind("stockMoveLineId", stockMoveLine.getId()).order("id").fetchOne();
} else if (purchaseOrderLine != null) {
nonConsolidatedStockMoveLine = stockMoveLineRepository.all().filter("self.purchaseOrderLine.id = :purchaseOrderLineId " + "AND self.stockMove.id = :stockMoveId " + "AND self.id != :stockMoveLineId").bind("purchaseOrderLineId", purchaseOrderLine.getId()).bind("stockMoveId", stockMove.getId()).bind("stockMoveLineId", stockMoveLine.getId()).order("id").fetchOne();
}
invoiceLine.setStockMoveLine(nonConsolidatedStockMoveLine);
deleteConsolidatedStockMoveLine(stockMoveLine);
}
}
return invoiceLine;
}
use of com.axelor.apps.stock.db.StockMove in project axelor-open-suite by axelor.
the class StockMoveInvoiceServiceImpl method createInvoiceFromOrderlessStockMove.
@Override
@Transactional(rollbackOn = { Exception.class })
public Invoice createInvoiceFromOrderlessStockMove(StockMove stockMove, Map<Long, BigDecimal> qtyToInvoiceMap) throws AxelorException {
int stockMoveType = stockMove.getTypeSelect();
int invoiceOperationType;
if (stockMove.getIsReversion()) {
if (stockMoveType == StockMoveRepository.TYPE_INCOMING) {
invoiceOperationType = InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND;
} else if (stockMoveType == StockMoveRepository.TYPE_OUTGOING) {
invoiceOperationType = InvoiceRepository.OPERATION_TYPE_SUPPLIER_REFUND;
} else {
return null;
}
} else {
if (stockMoveType == StockMoveRepository.TYPE_INCOMING) {
invoiceOperationType = InvoiceRepository.OPERATION_TYPE_SUPPLIER_PURCHASE;
} else if (stockMoveType == StockMoveRepository.TYPE_OUTGOING) {
invoiceOperationType = InvoiceRepository.OPERATION_TYPE_CLIENT_SALE;
} else {
return null;
}
}
// do not use invoiced partner if the option is disabled
if (!appSupplychainService.getAppSupplychain().getActivatePartnerRelations()) {
stockMove.setInvoicedPartner(null);
}
InvoiceGenerator invoiceGenerator = new InvoiceGeneratorSupplyChain(stockMove, invoiceOperationType) {
@Override
public Invoice generate() throws AxelorException {
return super.createInvoiceHeader();
}
};
Invoice invoice = invoiceGenerator.generate();
invoiceGenerator.populate(invoice, this.createInvoiceLines(invoice, stockMove, stockMove.getStockMoveLineList(), qtyToInvoiceMap));
if (invoice != null) {
this.extendInternalReference(stockMove, invoice);
invoice.setAddressStr(Beans.get(AddressService.class).computeAddressStr(invoice.getAddress()));
if (stockMoveType == StockMoveRepository.TYPE_OUTGOING) {
invoice.setHeadOfficeAddress(stockMove.getPartner().getHeadOfficeAddress());
}
invoiceRepository.save(invoice);
if (invoice != null) {
Set<StockMove> stockMoveSet = invoice.getStockMoveSet();
if (stockMoveSet == null) {
stockMoveSet = new HashSet<>();
invoice.setStockMoveSet(stockMoveSet);
}
stockMoveSet.add(stockMove);
}
invoiceRepository.save(invoice);
}
return invoice;
}
Aggregations