This is an automated email from the ASF dual-hosted git repository. nmalin pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
commit 7230aa804664cbeb1a70efdea3940b7e559fe72d Author: Nicolas Malin <nicolas.ma...@nereide.fr> AuthorDate: Wed Sep 15 17:34:58 2021 +0200 Improved: Convert createMatchingPaymentApplication service from mini-lang to groovy DSL (OFBIZ-11500) Thanks to Rohit Koushal to submit the patch --- .../groovyScripts/payment/PaymentServices.groovy | 117 ++++++++++++++++++ .../minilang/payment/PaymentServices.xml | 135 --------------------- .../accounting/servicedef/services_payment.xml | 4 +- 3 files changed, 119 insertions(+), 137 deletions(-) diff --git a/applications/accounting/groovyScripts/payment/PaymentServices.groovy b/applications/accounting/groovyScripts/payment/PaymentServices.groovy index fbc0edd..cfa29b8 100644 --- a/applications/accounting/groovyScripts/payment/PaymentServices.groovy +++ b/applications/accounting/groovyScripts/payment/PaymentServices.groovy @@ -26,6 +26,8 @@ import org.apache.ofbiz.entity.condition.EntityCondition import org.apache.ofbiz.entity.condition.EntityConditionBuilder import org.apache.ofbiz.entity.condition.EntityOperator import org.apache.ofbiz.entity.GenericValue +import org.apache.ofbiz.entity.util.EntityTypeUtil +import org.apache.ofbiz.entity.util.EntityUtilProperties import org.apache.ofbiz.service.ServiceUtil import java.sql.Timestamp @@ -713,3 +715,118 @@ def setPaymentStatus() { payment.store() return success(oldStatusId: oldStatusId) } + +def createMatchingPaymentApplication() { + String autoCreate = EntityUtilProperties.getPropertyValue("accounting", "accounting.payment.application.autocreate", "Y", delegator) + if ("Y" != autoCreate) { + logInfo("payment application not automatically created because config is not set to Y") + return success() + } + + Map createPaymentApplicationCtx = [:] + if (parameters.invoiceId) { + GenericValue invoice = from("Invoice").where("invoiceId", parameters.invoiceId).queryOne() + if (invoice) { + BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice) + + Map isInvoiceInForeignCurrencyResp = run service: 'isInvoiceInForeignCurrency', with: [invoiceId: invoice.invoiceId] + if (ServiceUtil.isError(isInvoiceInForeignCurrencyResp)) return isInvoiceInForeignCurrencyResp + + EntityConditionBuilder exprBldr = new EntityConditionBuilder() + EntityCondition expr = exprBldr.AND() { + NOT_EQUAL(statusId: 'PMNT_CONFIRMED') + EQUALS(partyIdFrom: invoice.partyId) + EQUALS(partyIdTo: invoice.partyIdFrom) + } + if (isInvoiceInForeignCurrencyResp.isForeign) { + expr = exprBldr.AND(expr) { + EQUALS(actualCurrencyAmount: invoiceTotal) + EQUALS(actualCurrencyUomId: invoice.currencyUomId) + } + } else { + expr = exprBldr.AND(expr) { + EQUALS(amount: invoiceTotal) + EQUALS(currencyUomId: invoice.currencyUomId) + } + } + + GenericValue payment = from('Payment') + .where(expr) + .orderBy('effectiveDate') + .queryFirst() + + if (payment && from('PaymentApplication') + .where('paymentId', payment.paymentId) + .queryCount() == 0) { + createPaymentApplicationCtx.paymentId = payment.paymentId + createPaymentApplicationCtx.invoiceId = parameters.invoiceId + createPaymentApplicationCtx.amountApplied = isInvoiceInForeignCurrencyResp.isForeign + ? payment.actualCurrencyAmount + : payment.amount + } + } + } + + if (parameters.paymentId) { + GenericValue payment = from("Payment").where(paymentId: parameters.paymentId).queryOne() + + if (payment) { + EntityCondition expr = new EntityConditionBuilder().AND() { + NOT_IN(statusId: ['INVOICE_READY','INVOICE_PAID','INVOICE_CANCELLED','INVOICE_WRITEOFF']) + EQUALS(partyIdFrom: payment.partyIdTo) + EQUALS(partyId: payment.partyIdFrom) + } + + List invoices = from('Invoice') + .where(expr) + .orderBy('invoiceDate') + .queryList() + String invoiceId + BigDecimal amountApplied + for (GenericValue invoice: invoices) { + boolean isPurchaseInvoice = EntityTypeUtil.hasParentType(delegator, 'InvoiceType', 'invoiceTypeId', invoice.invoiceTypeId, 'parentTypeId', 'PURCHASE_INVOICE') + boolean isSalesInvoice = EntityTypeUtil.hasParentType(delegator, 'InvoiceType', 'invoiceTypeId', invoice.invoiceTypeId, 'parentTypeId', 'SALES_INVOICE') + + if (isPurchaseInvoice || isSalesInvoice) { + BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice) + + Map isInvoiceInForeignCurrencyResp = run service: 'isInvoiceInForeignCurrency', with: [invoiceId: invoice.invoiceId] + if (ServiceUtil.isError(isInvoiceInForeignCurrencyResp)) return isInvoiceInForeignCurrencyResp + + if (isInvoiceInForeignCurrencyResp.isForeign + && invoiceTotal.compareTo(payment.actualCurrencyAmount) == 0 + && invoice.currencyUomId == payment.actualCurrencyUomId) { + invoiceId = invoice.invoiceId + amountApplied = payment.actualCurrencyAmount + } else if (invoiceTotal.compareTo(payment.amount) == 0 && invoice.currencyUomId == payment.currencyUomId) { + invoiceId = invoice.invoiceId + amountApplied = payment.amount + } + + } + } + + if (invoiceId) { + if (from('PaymentApplication') + .where(invoiceId: invoiceId) + .queryCount()) { + createPaymentApplicationCtx.paymentId = parameters.paymentId + createPaymentApplicationCtx.invoiceId = invoiceId + createPaymentApplicationCtx.amountApplied = amountApplied + } + } + } + } + + if (createPaymentApplicationCtx.paymentId && + createPaymentApplicationCtx.invoiceId) { + Map createPaymentApplicationResp = run service: 'createPaymentApplication', with: createPaymentApplicationCtx + if (ServiceUtil.isError(createPaymentApplicationResp)) return createPaymentApplicationResp + + logInfo("payment application automatically created between invoiceId: $createPaymentApplicationCtx.invoiceId}" + + " and paymentId: ${createPaymentApplicationCtx.paymentId} for" + + " the amount: ${createPaymentApplicationCtx.amountApplied} (can be disabled in accounting.properties)") + } + return success() + +} \ No newline at end of file diff --git a/applications/accounting/minilang/payment/PaymentServices.xml b/applications/accounting/minilang/payment/PaymentServices.xml index a878bc9..d7f112b 100644 --- a/applications/accounting/minilang/payment/PaymentServices.xml +++ b/applications/accounting/minilang/payment/PaymentServices.xml @@ -190,139 +190,4 @@ under the License. </else> </if-not-empty> </simple-method> - <simple-method method-name="createMatchingPaymentApplication" short-description="Create a payment application if either the invoice of payment could be found"> - <property-to-field resource="accounting" property="accounting.payment.application.autocreate" field="autoCreate" default="Y"/> - <if-compare operator="not-equals" value="Y" field="autoCreate"> - <log level="info" message="payment application not automatically created because config is not set to Y"/> - <return/> - </if-compare> - - <if-not-empty field="parameters.invoiceId"> - <entity-one entity-name="Invoice" value-field="invoice"/> - <if-not-empty field="invoice"> - <call-class-method method-name="getInvoiceTotal" class-name="org.apache.ofbiz.accounting.invoice.InvoiceWorker" ret-field="invoiceTotal"> - <field field="invoice" type="GenericValue"/> - </call-class-method> - - <set field="checkInvoice.invoiceId" from="invoice.invoiceId"/> - <call-service service-name="isInvoiceInForeignCurrency" in-map-name="checkInvoice"> - <result-to-field result-name="isForeign"/> - </call-service> - <if-compare operator="equals" value="true" field="isForeign"> - <entity-condition entity-name="Payment" list="payments"> - <condition-list combine="and"> - <condition-expr field-name="statusId" value="PMNT_CONFIRMED" operator="not-equals"/> - <condition-expr field-name="partyIdFrom" operator="equals" from-field="invoice.partyId"/> - <condition-expr field-name="partyIdTo" operator="equals" from-field="invoice.partyIdFrom"/> - <condition-expr field-name="actualCurrencyAmount" operator="equals" from-field="invoiceTotal"/> - <condition-expr field-name="actualCurrencyUomId" operator="equals" from-field="invoice.currencyUomId"/> - </condition-list> - <order-by field-name="effectiveDate"/> - </entity-condition> - <else> - <entity-condition entity-name="Payment" list="payments"> - <condition-list combine="and"> - <condition-expr field-name="statusId" value="PMNT_CONFIRMED" operator="not-equals"/> - <condition-expr field-name="partyIdFrom" operator="equals" from-field="invoice.partyId"/> - <condition-expr field-name="partyIdTo" operator="equals" from-field="invoice.partyIdFrom"/> - <condition-expr field-name="amount" operator="equals" from-field="invoiceTotal"/> - <condition-expr field-name="currencyUomId" operator="equals" from-field="invoice.currencyUomId"/> - </condition-list> - <order-by field-name="effectiveDate"/> - </entity-condition> - </else> - </if-compare> - - <if-not-empty field="payments"> - <!-- check if already applied --> - <entity-and entity-name="PaymentApplication" list="paymentAppls"> - <field-map field-name="paymentId" from-field="payments[0].paymentId"/> - </entity-and> - <if-empty field="paymentAppls"> - <set field="createAppl.paymentId" from-field="payments[0].paymentId"/> - <set field="createAppl.invoiceId" from-field="parameters.invoiceId"/> - <if-compare operator="equals" value="true" field="isForeign"> - <set field="createAppl.amountApplied" from-field="payments[0].actualCurrencyAmount"/> - <else> - <set field="createAppl.amountApplied" from-field="payments[0].amount"/> - </else> - </if-compare> - </if-empty> - </if-not-empty> - </if-not-empty> - </if-not-empty> - - <if-not-empty field="parameters.paymentId"> - <entity-one entity-name="Payment" value-field="payment"/> - <if-not-empty field="payment"> - - <entity-condition entity-name="Invoice" list="invoices"> - <condition-list combine="and"> - <condition-expr field-name="statusId" value="INVOICE_READY" operator="not-equals"/> - <condition-expr field-name="statusId" value="INVOICE_PAID" operator="not-equals"/> - <condition-expr field-name="statusId" value="INVOICE_CANCELLED" operator="not-equals"/> - <condition-expr field-name="statusId" value="INVOICE_WRITEOFF" operator="not-equals"/> - <condition-expr field-name="partyIdFrom" from-field="payment.partyIdTo"/> - <condition-expr field-name="partyId" from-field="payment.partyIdFrom"/> - </condition-list> - <order-by field-name="invoiceDate"/> - </entity-condition> - <iterate list="invoices" entry="invoice"> - <set field="isPurchaseInvoice" value="${groovy: org.apache.ofbiz.entity.util.EntityTypeUtil.hasParentType(delegator, 'InvoiceType', 'invoiceTypeId', invoice.getString('invoiceTypeId'), 'parentTypeId', 'PURCHASE_INVOICE')}" type="Boolean"/> - <set field="isSalesInvoice" value="${groovy: org.apache.ofbiz.entity.util.EntityTypeUtil.hasParentType(delegator, 'InvoiceType', 'invoiceTypeId', invoice.getString('invoiceTypeId'), 'parentTypeId', 'SALES_INVOICE')}" type="Boolean"/> - <if> - <condition> - <or> - <if-compare field="isPurchaseInvoice" operator="equals" value="true" type="Boolean"/> - <if-compare field="isSalesInvoice" operator="equals" value="true" type="Boolean"/> - </or> - </condition> - <then> - <call-class-method method-name="getInvoiceTotal" class-name="org.apache.ofbiz.accounting.invoice.InvoiceWorker" ret-field="invoiceTotal"> - <field field="invoice" type="GenericValue"/> - </call-class-method> - - <set field="checkInvoice.invoiceId" from="invoice.invoiceId"/> - <call-service service-name="isInvoiceInForeignCurrency" in-map-name="checkInvoice"> - <result-to-field result-name="isForeign"/> - </call-service> - <if-compare operator="equals" value="true" field="isForeign"> - <if-compare-field field="invoiceTotal" operator="equals" to-field="payment.actualCurrencyAmount"> - <if-compare-field field="invoice.currencyUomId" operator="equals" to-field="payment.actualCurrencyUomId"> - <set field="invoiceId" from-field="invoice.invoiceId"/> - <set field="amountApplied" from-field="payment.actualCurrencyAmount"/> - </if-compare-field> - </if-compare-field> - <else> - <if-compare-field field="invoiceTotal" operator="equals" to-field="payment.amount"> - <if-compare-field field="invoice.currencyUomId" operator="equals" to-field="payment.currencyUomId"> - <set field="invoiceId" from-field="invoice.invoiceId"/> - <set field="amountApplied" from-field="payment.amount"/> - </if-compare-field> - </if-compare-field> - </else> - </if-compare> - </then> - </if> - </iterate> - <if-not-empty field="invoiceId"> - <entity-and entity-name="PaymentApplication" list="paymentAppls"> - <field-map field-name="invoiceId" from-field="invoiceId"/> - </entity-and> - <if-empty field="paymentAppls"> - <set field="createAppl.paymentId" from-field="parameters.paymentId"/> - <set field="createAppl.invoiceId" from-field="invoiceId"/> - <set field="createAppl.amountApplied" from-field="amountApplied"/> - </if-empty> - </if-not-empty> - </if-not-empty> - </if-not-empty> - - <if-not-empty field="createAppl.paymentId"> - <if-not-empty field="createAppl.invoiceId"> - <call-service service-name="createPaymentApplication" in-map-name="createAppl"/> - <log level="info" message="payment application automatically created between invoiceId: ${createAppl.invoiceId} and paymentId: ${createAppl.paymentId} for the amount: ${createAppl.appliedAmount} (can be disabled in accounting.properties)"/> - </if-not-empty> - </if-not-empty> - </simple-method> </simple-methods> diff --git a/applications/accounting/servicedef/services_payment.xml b/applications/accounting/servicedef/services_payment.xml index 8a667e0..c244812 100644 --- a/applications/accounting/servicedef/services_payment.xml +++ b/applications/accounting/servicedef/services_payment.xml @@ -244,8 +244,8 @@ under the License. <attribute name="comments" type="String" mode="IN" optional="true"/> </service> - <service name="createMatchingPaymentApplication" engine="simple" - location="component://accounting/minilang/payment/PaymentServices.xml" invoke="createMatchingPaymentApplication" auth="true"> + <service name="createMatchingPaymentApplication" engine="groovy" + location="component://accounting/groovyScripts/payment/PaymentServices.groovy" invoke="createMatchingPaymentApplication" auth="true"> <description>Create a payment application if either the invoice of payment could be found</description> <attribute name="paymentId" type="String" mode="IN" optional="true"/> <attribute name="invoiceId" type="String" mode="IN" optional="true"/>