public IEditablePricingContext createPricingContext( I_C_InvoiceLine invoiceLine, final int priceListId, final BigDecimal priceQty) { final org.compiere.model.I_C_Invoice invoice = invoiceLine.getC_Invoice(); final boolean isSOTrx = invoice.isSOTrx(); final int productId = invoiceLine.getM_Product_ID(); int bPartnerId = invoice.getC_BPartner_ID(); final Timestamp date = invoice.getDateInvoiced(); final IEditablePricingContext pricingCtx = Services.get(IPricingBL.class) .createInitialContext( productId, bPartnerId, invoiceLine.getPrice_UOM_ID(), priceQty, isSOTrx); pricingCtx.setPriceDate(date); // 03152: setting the 'ol' to allow the subscription system to compute the right price pricingCtx.setReferencedObject(invoiceLine); pricingCtx.setM_PriceList_ID(priceListId); // PLV is only accurate if PL selected in header // metas: relay on M_PriceList_ID only, don't use M_PriceList_Version_ID // pricingCtx.setM_PriceList_Version_ID(orderLine.getM_PriceList_Version_ID()); return pricingCtx; }
@Override public IEditablePricingContext createPricingContext(final I_C_InvoiceLine invoiceLine) { final I_C_Invoice invoice = invoiceLine.getC_Invoice(); final int priceListId = invoice.getM_PriceList_ID(); final BigDecimal qtyInvoicedInPriceUOM = calculateQtyInvoicedInPriceUOM(invoiceLine); return createPricingContext(invoiceLine, priceListId, qtyInvoicedInPriceUOM); }
private boolean addInvoice0(final I_C_Invoice invoice) { // // Skip not posted invoices, but warn the user if (!invoice.isPosted()) { loggable.addLog("@Error@: @C_Invoice_ID@ @Posted@=@N@: " + invoiceBL.getSummary(invoice)); return false; } // // Tax declaration lines (one for each invoice tax record) final List<I_C_InvoiceTax> invoiceTaxes = invoiceDAO.retrieveTaxes(invoice); final Map<Integer, I_C_TaxDeclarationLine> taxId2taxDeclarationLine = new HashMap<>(invoiceTaxes.size()); for (final I_C_InvoiceTax invoiceTax : invoiceTaxes) { final int taxId = invoiceTax.getC_Tax_ID(); final I_C_TaxDeclarationLine taxDeclarationLine = createTaxDeclarationLine(invoice, invoiceTax); final I_C_TaxDeclarationLine taxDeclarationLineOld = taxId2taxDeclarationLine.put(taxId, taxDeclarationLine); Check.assumeNull( taxDeclarationLineOld, "More than one invoice tax line for {0}, taxId={1}", invoice, taxId); } // // Tax declaration accounting records final List<I_Fact_Acct> factAcctRecords = factAcctDAO .retrieveQueryForDocument(invoice) // fetch only those Fact_Acct records which are about taxes, i.e. .addNotEqualsFilter(I_Fact_Acct.COLUMN_C_Tax_ID, null) // C_Tax_ID is set .addEqualsFilter(I_Fact_Acct.COLUMN_Line_ID, null) // Line_ID is NOT set // .create() .list(); for (final I_Fact_Acct factAcctRecord : factAcctRecords) { // // Link to Tax Declaration Line only if this Fact_Acct is about tax bookings. Which means: // * it's document level booking (Line_ID <= 0) // * we have a C_TaxDeclarationLine which has the same tax as this booking I_C_TaxDeclarationLine taxDeclarationLine = null; if (factAcctRecord.getLine_ID() <= 0) { final int taxId = factAcctRecord.getC_Tax_ID(); taxDeclarationLine = taxId2taxDeclarationLine.get(taxId); } createTaxDeclarationAcct(taxDeclarationLine, factAcctRecord); } return true; }
private void calculatePriceActual(final I_C_InvoiceLine invoiceLine, final int precision) { final BigDecimal discount = invoiceLine.getDiscount(); final BigDecimal priceEntered = invoiceLine.getPriceEntered(); BigDecimal priceActual; if (priceEntered.signum() == 0) { priceActual = priceEntered; } else { final int precisionToUse; if (precision >= 0) { precisionToUse = precision; } else { final I_C_Invoice invoice = invoiceLine.getC_Invoice(); precisionToUse = invoice.getM_PriceList().getPricePrecision(); } priceActual = subtractDiscount(priceEntered, discount, precisionToUse); } invoiceLine.setPriceActual(priceActual); }
@Override public void updateLineNetAmt(final I_C_InvoiceLine line, final BigDecimal qtyEntered) { if (qtyEntered != null) { final Properties ctx = InterfaceWrapperHelper.getCtx(line); final I_C_Invoice invoice = line.getC_Invoice(); final int priceListId = invoice.getM_PriceList_ID(); // // We need to get the quantity in the pricing's UOM (if different) final BigDecimal convertedQty = calculateQtyInvoicedInPriceUOM(line); // this code has been borrowed from // org.compiere.model.CalloutOrder.amt final int stdPrecision = MPriceList.getStandardPrecision(ctx, priceListId); BigDecimal lineNetAmt = convertedQty.multiply(line.getPriceActual()); if (lineNetAmt.scale() > stdPrecision) { lineNetAmt = lineNetAmt.setScale(stdPrecision, BigDecimal.ROUND_HALF_UP); } logger.info("LineNetAmt=" + lineNetAmt); line.setLineNetAmt(lineNetAmt); } }
private final I_C_TaxDeclarationLine createTaxDeclarationLine( final I_C_Invoice invoice, final I_C_InvoiceTax invoiceTax) { final I_C_TaxDeclarationLine taxDeclarationLine = newTaxDeclarationLine(); taxDeclarationLine.setAD_Org_ID(invoice.getAD_Org_ID()); taxDeclarationLine.setIsManual(false); // taxDeclarationLine.setC_Invoice(invoice); taxDeclarationLine.setIsSOTrx(invoice.isSOTrx()); taxDeclarationLine.setC_BPartner_ID(invoice.getC_BPartner_ID()); taxDeclarationLine.setC_Currency_ID(invoice.getC_Currency_ID()); taxDeclarationLine.setDateAcct(invoice.getDateAcct()); taxDeclarationLine.setC_DocType_ID(invoice.getC_DocType_ID()); taxDeclarationLine.setDocumentNo(invoice.getDocumentNo()); // taxDeclarationLine.setC_Tax_ID(invoiceTax.getC_Tax_ID()); taxDeclarationLine.setTaxBaseAmt(invoiceTax.getTaxBaseAmt()); taxDeclarationLine.setTaxAmt(invoiceTax.getTaxAmt()); save(taxDeclarationLine); return taxDeclarationLine; }
@Override public boolean setTax( final Properties ctx, final org.compiere.model.I_C_InvoiceLine il, final String trxName) { int taxCategoryId = il.getC_TaxCategory_ID(); if (taxCategoryId <= 0 && il.getM_Product_ID() > 0) { // NOTE: we can retrieve the tax category only if we have a product taxCategoryId = getC_TaxCategory_ID(il); il.setC_TaxCategory_ID(taxCategoryId); } if (il.getM_InOutLine_ID() <= 0) { logger.debug(il + "has M_InOutLine_ID=" + il.getM_InOutLine_ID() + ": returning"); return false; } if (il.getM_Product_ID() <= 0) { // this might be the case if a descriptional il refers to an iol. logger.debug(il + "has M_Product_ID=" + il.getM_Product_ID() + ": returning"); return false; } final I_M_InOut io = il.getM_InOutLine().getM_InOut(); final I_C_Location locationFrom = Services.get(IWarehouseBL.class).getC_Location(io.getM_Warehouse()); final int countryFromId = locationFrom.getC_Country_ID(); final I_C_BPartner_Location locationTo = InterfaceWrapperHelper.create(io.getC_BPartner_Location(), I_C_BPartner_Location.class); final Timestamp shipDate = io.getMovementDate(); final int taxId = Services.get(ITaxBL.class) .retrieveTaxIdForCategory( ctx, countryFromId, io.getAD_Org_ID(), locationTo, shipDate, taxCategoryId, il.getC_Invoice().isSOTrx(), trxName, false); if (taxId <= 0) { final I_C_Invoice invoice = il.getC_Invoice(); throw new TaxNotFoundException( taxCategoryId, io.isSOTrx(), shipDate, locationFrom.getC_Location_ID(), locationTo.getC_Location_ID(), invoice.getDateInvoiced(), locationFrom.getC_Location_ID(), invoice.getC_BPartner_Location().getC_Location_ID()); } final boolean taxChange = il.getC_Tax_ID() != taxId; if (taxChange) { logger.info("Changing C_Tax_ID to " + taxId + " for " + il); il.setC_Tax_ID(taxId); final I_C_Tax tax = il.getC_Tax(); il.setC_TaxCategory_ID(tax.getC_TaxCategory_ID()); } return taxChange; }
@Override public int getC_TaxCategory_ID(final org.compiere.model.I_C_InvoiceLine invoiceLine) { // FIXME: we need to retrieve the C_TaxCategory_ID by using Pricing Engine if (invoiceLine.getC_Charge_ID() > 0) { return invoiceLine.getC_Charge().getC_TaxCategory_ID(); } final I_C_Invoice invoice = invoiceLine.getC_Invoice(); final IPriceListDAO priceListDAO = Services.get(IPriceListDAO.class); final Boolean processedPLVFiltering = null; // task 09533: the user doesn't know about PLV's processed flag, so we can't filter by // it if (invoice.getM_PriceList_ID() != 100) // FIXME use PriceList_None constant { final I_M_PriceList priceList = invoice.getM_PriceList(); final I_M_PriceList_Version priceListVersion = priceListDAO.retrievePriceListVersionOrNull( priceList, invoice.getDateInvoiced(), processedPLVFiltering); Check.errorIf( priceListVersion == null, "Missing PLV for M_PriceList and DateInvoiced of {}", invoice); final int m_Product_ID = invoiceLine.getM_Product_ID(); Check.assume(m_Product_ID > 0, "M_Product_ID > 0 for {}", invoiceLine); final I_M_ProductPrice productPrice = priceListDAO.retrieveProductPrice(priceListVersion, m_Product_ID); return productPrice.getC_TaxCategory_ID(); } // Fallback: try getting from Order Line if (invoiceLine.getC_OrderLine_ID() > 0) { return invoiceLine.getC_OrderLine().getC_TaxCategory_ID(); } // Fallback: try getting from Invoice -> Order if (invoiceLine.getC_Invoice().getC_Order_ID() > 0) { final Properties ctx = InterfaceWrapperHelper.getCtx(invoiceLine); final String trxName = InterfaceWrapperHelper.getTrxName(invoiceLine); final I_C_Order order = InterfaceWrapperHelper.create( ctx, invoiceLine.getC_Invoice().getC_Order_ID(), I_C_Order.class, trxName); final I_M_PriceList priceList = order.getM_PriceList(); final I_M_PriceList_Version priceListVersion = priceListDAO.retrievePriceListVersionOrNull( priceList, invoice.getDateInvoiced(), processedPLVFiltering); Check.errorIf( priceListVersion == null, "Missing PLV for M_PriceList and DateInvoiced of {}", invoice); final int m_Product_ID = invoiceLine.getM_Product_ID(); Check.assume(m_Product_ID > 0, "M_Product_ID > 0 for {}", invoiceLine); final I_M_ProductPrice productPrice = priceListDAO.retrieveProductPrice(priceListVersion, m_Product_ID); return productPrice.getC_TaxCategory_ID(); } throw new AdempiereException( "@NotFound@ @C_TaxCategory_ID@ (" + "@C_InvoiceLine_ID@:" + invoiceLine + ")"); }
@Override public void createBankStatementLines( final I_C_BankStatement bankStatement, final I_C_PaySelection paySelection) { Check.errorIf( bankStatement.getC_BP_BankAccount_ID() != paySelection.getC_BP_BankAccount_ID(), "C_BankStatement {} with C_BP_BankAccount_ID={} and C_PaySelection {} with C_BP_BankAccount_ID={} need to have the same C_BP_BankAccount_ID", bankStatement, bankStatement.getC_BP_BankAccount_ID(), paySelection, paySelection.getC_BP_BankAccount_ID()); // services final IPaySelectionDAO paySelectionDAO = Services.get(IPaySelectionDAO.class); final IInvoiceBL invoiceBL = Services.get(IInvoiceBL.class); final IBankStatementBL bankStatementBL = Services.get(IBankStatementBL.class); I_C_BankStatementLine bankStatementLine = null; int nextReferenceLineNo = 10; final List<I_C_PaySelectionLine> paySelectionLines = paySelectionDAO.retrievePaySelectionLines(paySelection, I_C_PaySelectionLine.class); for (final I_C_PaySelectionLine psl : paySelectionLines) { // Skip if already in a bank statement if (isInBankStatement(psl)) { continue; } // Skip if no invoice if (psl.getC_Invoice_ID() <= 0) { continue; } // // Create the bank statement line (if not already created) if (bankStatementLine == null) { bankStatementLine = InterfaceWrapperHelper.newInstance(I_C_BankStatementLine.class, paySelection); bankStatementLine.setAD_Org_ID(paySelection.getAD_Org_ID()); bankStatementLine.setC_BankStatement(bankStatement); bankStatementLine.setIsMultiplePaymentOrInvoice( true); // we have a reference line for each invoice bankStatementLine.setIsMultiplePayment(true); // each invoice shall have it's own payment bankStatementLine.setC_Currency_ID(bankStatement.getC_BP_BankAccount().getC_Currency_ID()); bankStatementLine.setValutaDate(paySelection.getPayDate()); bankStatementLine.setDateAcct(paySelection.getPayDate()); bankStatementLine.setStatementLineDate(paySelection.getPayDate()); bankStatementLine.setReferenceNo(null); // no ReferenceNo at this level bankStatementLine.setC_BPartner( null); // no partner because we will have it on "line reference" level bankStatementLine.setStmtAmt(BigDecimal.ZERO); // will be updated at the end bankStatementLine.setTrxAmt(BigDecimal.ZERO); // will be updated at the end bankStatementLine.setChargeAmt(BigDecimal.ZERO); bankStatementLine.setInterestAmt(BigDecimal.ZERO); InterfaceWrapperHelper.save(bankStatementLine); } // // Create new bank statement line reference for our current pay selection line. final I_C_BankStatementLine_Ref bankStatementLineRef = InterfaceWrapperHelper.newInstance(I_C_BankStatementLine_Ref.class, bankStatementLine); bankStatementLineRef.setAD_Org_ID(bankStatementLine.getAD_Org_ID()); bankStatementLineRef.setC_BankStatementLine(bankStatementLine); IBankStatementBL.DYNATTR_DisableBankStatementLineRecalculateFromReferences.setValue( bankStatementLineRef, true); // disable recalculation. we will do it at the end // // Set Invoice from pay selection line bankStatementLineRef.setC_BPartner_ID(psl.getC_BPartner_ID()); final I_C_Invoice invoice = psl.getC_Invoice(); bankStatementLineRef.setC_Invoice(invoice); bankStatementLineRef.setC_Currency_ID(invoice.getC_Currency_ID()); // // Get pay schedule line amounts: final boolean isReceipt; if (invoiceBL.isCreditMemo(invoice)) { // SOTrx=Y, but credit memo => receipt=N isReceipt = !invoice.isSOTrx(); } else { // SOTrx=Y => receipt=Y isReceipt = invoice.isSOTrx(); } final BigDecimal factor = isReceipt ? BigDecimal.ONE : BigDecimal.ONE.negate(); final BigDecimal linePayAmt = psl.getPayAmt().multiply(factor); final BigDecimal lineDiscountAmt = psl.getDiscountAmt().multiply(factor); // we store the psl's discount amount, because if we create a payment from this line, then we // don't want the psl's Discount to end up as a mere underpayment. bankStatementLineRef.setDiscountAmt(lineDiscountAmt); bankStatementLineRef.setTrxAmt(linePayAmt); bankStatementLineRef.setReferenceNo(psl.getReference()); bankStatementLineRef.setLine(nextReferenceLineNo); // // Set Payment from pay selection line. // NOTE: In case the pay selection line does not already have a payment generated, // we are generating it now because it's the most convenient for the user. createPaymentIfNeeded(psl); bankStatementLineRef.setC_Payment_ID(psl.getC_Payment_ID()); // // Save the bank statement line reference InterfaceWrapperHelper.save(bankStatementLineRef); nextReferenceLineNo += 10; // // Update pay selection line => mark it as reconciled linkBankStatementLine(psl, bankStatementLine, bankStatementLineRef); } // // Update Bank Statement Line's totals: if (bankStatementLine != null) { bankStatementBL.recalculateStatementLineAmounts(bankStatementLine); } }
@Override public void updateFromInvoice(final org.compiere.model.I_C_PaySelectionLine psl) { final I_C_PaySelectionLine pslExt = InterfaceWrapperHelper.create(psl, I_C_PaySelectionLine.class); if (Services.get(IPaymentRequestBL.class).isUpdatedFromPaymentRequest(pslExt)) { return; } if (psl.getC_Invoice_ID() <= 0) { return; // nothing to do yet, but as C_PaySelectionLine.C_Invoice_ID is mandatory, we only // need to make sure this method is eventually called from a model interceptor } final IBPBankAccountDAO bpBankAccountDAO = Services.get(IBPBankAccountDAO.class); final Properties ctx = InterfaceWrapperHelper.getCtx(pslExt); final int partnerID = pslExt.getC_Invoice().getC_BPartner_ID(); pslExt.setC_BPartner_ID(partnerID); final String paymentRule = pslExt.getPaymentRule(); // task 09500 get the currency from the account of the selection header // this is safe because the columns are mandatory final int currencyID = pslExt.getC_PaySelection().getC_BP_BankAccount().getC_Currency_ID(); final List<I_C_BP_BankAccount> bankAccts = bpBankAccountDAO.retrieveBankAccountsForPartnerAndCurrency(ctx, partnerID, currencyID); if (!bankAccts.isEmpty()) { int primaryAcct = 0; int secondaryAcct = 0; for (final I_C_BP_BankAccount account : bankAccts) { final int accountID = account.getC_BP_BankAccount_ID(); if (accountID > 0) { if (account.getBPBankAcctUse().equals(X_C_BP_BankAccount.BPBANKACCTUSE_Both)) { secondaryAcct = accountID; } else if (account.getBPBankAcctUse().equals(paymentRule)) { primaryAcct = accountID; break; } } } if (primaryAcct != 0) { pslExt.setC_BP_BankAccount_ID(primaryAcct); } else if (secondaryAcct != 0) { pslExt.setC_BP_BankAccount_ID(secondaryAcct); } } // 08297: After trying to set the Reference from the payment request, fallback (if still empty) // to the Invoice's POReference final boolean trimWhitespaces = true; if (Check.isEmpty(pslExt.getReference(), trimWhitespaces)) { final I_C_Invoice invoice = pslExt.getC_Invoice(); if (invoice == null) { return; } final String invoicePOReference = invoice.getPOReference(); if (Check.isEmpty(invoicePOReference, trimWhitespaces)) { return; } pslExt.setReference(invoicePOReference); } }