blob: 166b166d2416cee523051200f28d39f45d6abaf3 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
<simple-method method-name="createInvoice" short-description="Create a new Invoice">
<now-timestamp field="nowTimestamp"/>
<make-value entity-name="Invoice" value-field="newEntity"/>
<!-- call getNextInvoiceId service with the parameters.partyIdFrom when invoice Id is not suplied
else use it from the input -->
<if-empty field="parameters.invoiceId">
<set-service-fields service-name="getNextInvoiceId" map="parameters" to-map="getNextInvoiceIdMap"/>
<set field="getNextInvoiceIdMap.partyId" from-field="parameters.partyIdFrom"/>
<call-service service-name="getNextInvoiceId" in-map-name="getNextInvoiceIdMap">
<result-to-field result-name="invoiceId" field="parameters.invoiceId"/>
</call-service>
</if-empty>
<field-to-result field="parameters.invoiceId" result-name="invoiceId"/>
<!-- set the invoice date if not provided -->
<if-empty field="parameters.invoiceDate">
<set from-field="nowTimestamp" field="parameters.invoiceDate"/>
</if-empty>
<!-- set the invoice status if not provided -->
<if-empty field="parameters.statusId">
<set field="parameters.statusId" value="INVOICE_IN_PROCESS"/>
</if-empty>
<!-- use currency of receiving company -->
<entity-one entity-name="Party" value-field="party"/>
<if-not-empty field="party.preferredCurrencyUomId">
<set field="parameters.currencyUomId" from-field="party.preferredCurrencyUomId"/>
</if-not-empty>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<set-pk-fields map="parameters" value-field="newEntity"/>
<create-value value-field="newEntity"/>
<!-- create new status entry, and set lastStatusUpdate date -->
<set field="createInvoiceStatusMap.invoiceId" from-field="newEntity.invoiceId" />
<set field="createInvoiceStatusMap.statusId" from-field="newEntity.statusId" />
<call-service service-name="createInvoiceStatus" in-map-name="createInvoiceStatusMap"/>
</simple-method>
<simple-method method-name="copyInvoice" short-description="Create a new Invoice from an existing invoice">
<set field="invoiceLookup.invoiceId" from-field="parameters.invoiceIdToCopyFrom"/>
<call-service service-name="getInvoice" in-map-name="invoiceLookup">
<result-to-field result-name="invoice" field="invoice"/>
<result-to-field result-name="invoiceItems" field="invoiceItems"/>
</call-service>
<set field="invoice.invoiceId" from-field="parameters.invoiceId"/>
<now-timestamp field="nowTimestamp"/>
<set field="invoice.invoiceDate" from-field="nowTimestamp"/>
<set field="invoice.statusId" value="INVOICE_IN_PROCESS"/>
<if-not-empty field="parameters.invoiceTypeId">
<set field="invoice.invoiceTypeId" from-field="parameters.invoiceTypeId"/>
</if-not-empty>
<set-service-fields service-name="createInvoice" map="invoice" to-map="newInvoice"/>
<clear-field field="newInvoice.invoiceId"/>
<call-service service-name="createInvoice" in-map-name="newInvoice">
<result-to-field result-name="invoiceId" field="invoiceId"/>
</call-service>
<field-to-result field="invoiceId" result-name="invoiceId"/>
<field-to-request field="invoiceId" request-name="invoiceId"/>
<iterate list="invoiceItems" entry="invoiceItem">
<set-service-fields service-name="createInvoiceItem" map="invoiceItem" to-map="createInvoiceItem"/>
<set field="createInvoiceItem.invoiceId" from-field="invoiceId"/>
<call-service service-name="createInvoiceItem" in-map-name="createInvoiceItem"/>
</iterate>
</simple-method>
<simple-method method-name="getInvoice" short-description="Retrieve an invoice and the items">
<!-- find the invoice record -->
<make-value entity-name="Invoice" value-field="lookupPKMap"/>
<set-pk-fields map="parameters" value-field="lookupPKMap"/>
<find-by-primary-key entity-name="Invoice" map="lookupPKMap" value-field="invoiceValue"/>
<field-to-result field="invoiceValue" result-name="invoice"/>
<!-- and the items -->
<get-related value-field="invoiceValue" relation-name="InvoiceItem" list="invoiceItemValues"/>
<field-to-result field="invoiceItemValues" result-name="invoiceItems"/>
</simple-method>
<simple-method method-name="updateInvoice" short-description="Update the header of an existing Invoice">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<!-- find the current record -->
<make-value entity-name="Invoice" value-field="lookupPKMap"/>
<set-pk-fields map="parameters" value-field="lookupPKMap"/>
<find-by-primary-key entity-name="Invoice" map="lookupPKMap" value-field="lookedUpValue"/>
<!-- only try to update content if the status is in process.... -->
<if-compare field="lookedUpValue.statusId" operator="equals" value="INVOICE_IN_PROCESS">
<clone-value value-field="lookedUpValue" new-value-field="savedValue"/>
<set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
<!-- only save if something has changed, do not update status here -->
<set from-field="savedValue.statusId" field="lookedUpValue.statusId"/> <!-- get old status back -->
<if-compare-field field="lookedUpValue" to-field="savedValue" operator="not-equals" type="Object">
<store-value value-field="lookedUpValue"/> <!-- update all non status and key fields -->
</if-compare-field>
<else>
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceUpdateOnlyWithInProcessStatus"/>
</add-error>
<log level="error" message="Can only update Invoice, when status is in-process...current Status: ${lookedUpValue.statusId}"/>
<check-errors/>
</else>
</if-compare>
<!-- check if there is a requested status change if yes call invoice status update service -->
<if-not-empty field="parameters.statusId">
<if-compare-field field="parameters.statusId" to-field="savedValue.statusId" operator="not-equals">
<set from-field="parameters.invoiceId" field="inputMap.invoiceId"/>
<set from-field="parameters.statusId" field="inputMap.statusId"/>
<now-timestamp field="inputMap.statusDate"/>
<call-service service-name="setInvoiceStatus" in-map-name="inputMap"/>
</if-compare-field>
</if-not-empty>
</simple-method>
<simple-method method-name="sendInvoicePerEmail" short-description="Send an invoice per Email">
<set-service-fields service-name="sendMailFromScreen" map="parameters" to-map="emailParams"/>
<set field="emailParams.xslfoAttachScreenLocation" value="component://accounting/widget/AccountingPrintScreens.xml#InvoicePDF"/>
<set field="emailParams.bodyParameters.invoiceId" from-field="parameters.invoiceId"/>
<set field="emailParams.bodyParameters.userLogin" from-field="parameters.userLogin"/>
<set field="emailParams.bodyParameters.other" from-field="parameters.other"/><!-- to to print in 'other currency' -->
<call-service-asynch service-name="sendMailFromScreen" in-map-name="emailParams"/>
<property-to-field resource="AccountingUiLabels" property="AccountingEmailScheduledToSend" field="successMessage"/>
</simple-method>
<simple-method method-name="createInvoiceItem" short-description="Create a new Invoice Item">
<set field="invoiceId" from-field="parameters.invoiceId"/>
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<make-value entity-name="InvoiceItem" value-field="newEntity"/>
<set-pk-fields map="parameters" value-field="newEntity"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<if-empty field="newEntity.invoiceItemSeqId">
<make-next-seq-id value-field="newEntity" seq-field-name="invoiceItemSeqId"/> <!-- this finds the next sub-sequence ID -->
<field-to-result field="newEntity.invoiceItemSeqId" result-name="invoiceItemSeqId"/>
</if-empty>
<!-- if there is no amount and a productItem is supplied fill the amount(price) and description from the product record
TODO: there are return adjustments now that make this code very broken. The check for price was added as a quick fix. -->
<if-empty field="parameters.amount">
<if-not-empty field="parameters.productId">
<entity-one entity-name="Product" value-field="product"/>
<set from-field="product.description" field="newEntity.description"/>
<set from-field="product" field="calculateProductPriceMap.product"/>
<call-service service-name="calculateProductPrice" in-map-name="calculateProductPriceMap">
<result-to-field result-name="price" field="newEntity.amount"/>
</call-service>
</if-not-empty>
</if-empty>
<if-not-empty field="parameters.productId">
<if-empty field="parameters.quantity">
<set field="newEntity.quantity" value="1.0" type="BigDecimal"/>
</if-empty>
</if-not-empty>
<if-empty field="newEntity.amount">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceAmountIsMandatory"/>
</add-error>
</if-empty>
<create-value value-field="newEntity"/>
</simple-method>
<simple-method method-name="updateInvoiceItem"
short-description="Update an existing Invoice Item">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<make-value entity-name="InvoiceItem" value-field="lookupPKMap"/>
<set-pk-fields map="parameters" value-field="lookupPKMap"/>
<find-by-primary-key entity-name="InvoiceItem" map="lookupPKMap" value-field="lookedUpValue"/>
<clone-value value-field="lookedUpValue" new-value-field="savedValue"/>
<!-- set all parameters -->
<set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
<!-- check if the productNumber is updated, when yes retrieve product description and price -->
<if-not-empty field="productId">
<if-compare-field to-field="lookedUpValue.productId" field="savedValue.productId" operator="not-equals">
<entity-one entity-name="Product" value-field="product"/>
<set from-field="product.description" field="lookedUpValue.description"/>
<set from-field="product" field="calculateProductPriceMap.product"/>
<call-service service-name="calculateProductPrice" in-map-name="calculateProductPriceMap">
<result-to-field result-name="price" field="lookedUpValue.amount"/>
</call-service>
</if-compare-field>
</if-not-empty>
<if-empty field="newEntity.amount">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceAmountIsMandatory"/>
</add-error>
</if-empty>
<if-compare-field field="lookedUpValue" to-field="savedValue" operator="not-equals" type="Object">
<store-value value-field="lookedUpValue"/>
</if-compare-field>
<field-to-result field="lookedUpValue.invoiceItemSeqId" result-name="invoiceItemSeqId"/>
<field-to-result field="lookedUpValue.invoiceId" result-name="invoiceId"/>
</simple-method>
<simple-method method-name="removeInvoiceItem" short-description="Remove an existing Invoice Item">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<set field="invoiceId" from-field="parameters.invoiceId"/>
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<set field="paymentApplicationMap.invoiceId" from-field="parameters.invoiceId"/>
<set field="paymentApplicationMap.invoiceItemSeqId" from-field="parameters.invoiceItemSeqId"/>
<if-not-empty field="parameters.invoiceItemSeqId">
<!-- check if there are specific item paymentApplications when yes remove those -->
<remove-by-and entity-name="PaymentApplication" map="paymentApplicationMap"/>
<else><!-- update global application with a null sequence number -->
<!-- TODO: reduce amount on global paymentApplication record -->
</else>
</if-not-empty>
<entity-one entity-name="InvoiceItem" value-field="lookedUpValue"/>
<remove-value value-field="lookedUpValue"/>
</simple-method>
<simple-method method-name="removePaymentApplication" short-description="Remove an existing payment application">
<entity-one entity-name="PaymentApplication" value-field="paymentApplication">
<field-map field-name="paymentApplicationId" value="${parameters.paymentApplicationId}"/>
</entity-one>
<if-empty field="paymentApplication">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingPaymentApplicationNotFound"/>
</add-error>
<check-errors/>
</if-empty>
<!-- payment -->
<set field="currencyUomId" value=""/><!-- currency of the paymentApplication -->
<if-not-empty field="paymentApplication.paymentId">
<entity-one entity-name="Payment" value-field="payment">
<field-map field-name="paymentId" value="${paymentApplication.paymentId}"/>
</entity-one>
<if-not-empty field="payment">
<if-compare field="payment.statusId" operator="equals" value="PMNT_CONFIRMED">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingPaymentApplicationCannotRemovedWithConfirmedStatus"/>
</add-error>
</if-compare>
<check-errors/>
</if-not-empty>
<field-to-result field="paymentApplication.paymentId" result-name="paymentId"/>
<set field="currencyUomId" from-field="paymentId.currencyUomId"/>
</if-not-empty>
<!-- check invoice -->
<if-not-empty field="paymentApplication.invoiceId">
<entity-one entity-name="Invoice" value-field="invoice">
<field-map field-name="invoiceId" value="${paymentApplication.invoiceId}"/>
</entity-one>
<if-empty field="invoice">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceNotFound"/>
</add-error>
<log level="info" message="Invoice not found, invoice Id: ${invoiceId}"/>
<check-errors/>
</if-empty>
<set field="currencyUomId" from-field="invoice.currencyUomId"/>
<!-- if the invoice is already PAID, then set it back to READY and clear out the paidDate -->
<if-compare field="invoice.statusId" operator="equals" value="INVOICE_PAID">
<set field="invoiceStatusMap.invoiceId" value="${paymentApplication.invoiceId}"/>
<set field="invoiceStatusMap.statusId" value="INVOICE_READY"/>
<call-service service-name="setInvoiceStatus" in-map-name="invoiceStatusMap"/>
</if-compare>
<check-errors/>
<field-to-result field="paymentApplication.invoiceId" result-name="invoiceId"/>
<property-to-field resource="AccountingUiLabels" property="AccountingPaymentApplToInvoice" field="toMessage"/>
</if-not-empty>
<!-- invoice item -->
<if-not-empty field="paymentApplication.invoiceItemSeqId">
<field-to-result field="paymentApplication.invoiceItemSeqId" result-name="invoiceItemSeqId"/>
<property-to-field resource="AccountingUiLabels" property="AccountingApplicationToInvoiceItem" field="toMessage"/>
</if-not-empty>
<!-- toPayment -->
<if-not-empty field="paymentApplication.toPaymentId">
<entity-one entity-name="Payment" value-field="toPayment">
<field-map field-name="paymentId" value="${paymentApplication.toPaymentId}"/>
</entity-one>
<if-not-empty field="toPayment">
<if-compare field="toPayment.statusId" operator="equals" value="PMNT_CONFIRMED">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingPaymentApplicationCannotRemovedWithConfirmedStatus"/>
</add-error>
</if-compare>
<check-errors/>
</if-not-empty>
<property-to-field resource="AccountingUiLabels" property="AccountingPaymentApplToPayment" field="toMessage"/>
<field-to-result field="paymentApplication.toPaymentId" result-name="toPaymentId"/>
</if-not-empty>
<!-- billing account -->
<if-not-empty field="paymentApplication.billingAccountId">
<field-to-result field="paymentApplication.billingAccountId" result-name="billingAccountId"/>
<property-to-field resource="AccountingUiLabels" property="AccountingPaymentApplToBillingAccount" field="toMessage"/>
<entity-one entity-name="BillingAccount" value-field="billingAccount">
<field-map field-name="billingAccountId" from-field="paymentApplication.billingAccountId"/>
</entity-one>
<set field="currencyUomId" from-field="billingAccount.accountCurrencyUomId"/>
</if-not-empty>
<!-- tax authority -->
<if-not-empty field="paymentApplication.taxAuthGeoId">
<field-to-result field="paymentApplication.taxAuthGeoId" result-name="taxAuthGeoId"/>
<property-to-field resource="AccountingUiLabels" property="AccountingPaymentApplToTaxAuth" field="toMessage"/>
</if-not-empty>
<!-- finally delete application -->
<property-to-field resource="AccountingUiLabels" property="AccountingPaymentApplRemoved" field="successMessage"/>
<string-append field="successMessage" string=" ${toMessage}"/>
<remove-value value-field="paymentApplication"/>
</simple-method>
<simple-method method-name="createInvoiceRole" short-description="Create a Invoice Role">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<make-value entity-name="InvoiceRole" value-field="newEntity"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<set-pk-fields map="parameters" value-field="newEntity"/>
<if-empty field="newEntity.datetimePerformed"><now-timestamp field="newEntity.datetimePerformed"/></if-empty>
<create-value value-field="newEntity"/>
</simple-method>
<simple-method method-name="removeInvoiceRole" short-description="Remove existing Invoice Role">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<entity-one entity-name="InvoiceRole" value-field="lookedUpValue"/>
<remove-value value-field="lookedUpValue"/>
</simple-method>
<simple-method method-name="setInvoiceStatus" short-description="Set The Invoice Status">
<entity-one entity-name="Invoice" value-field="invoice"/>
<field-to-result field="invoice.statusId" result-name="oldStatusId"/>
<field-to-result field="invoice.invoiceTypeId" result-name="invoiceTypeId"/>
<if-compare-field field="invoice.statusId" to-field="parameters.statusId" operator="not-equals">
<entity-one entity-name="StatusValidChange" value-field="statusChange" auto-field-map="false">
<field-map field-name="statusId" from-field="invoice.statusId"/>
<field-map field-name="statusIdTo" from-field="parameters.statusId"/>
</entity-one>
<if-empty field="statusChange">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingPSInvalidStatusChange"/>
</add-error>
<log level="error" message="Cannot change from ${invoice.statusId} to ${parameters.statusId}"/>
<check-errors/>
<else>
<!-- if new status is paid check if the complete invoice is applied. -->
<if-compare field="parameters.statusId" operator="equals" value="INVOICE_PAID">
<set field="notApplied" type="BigDecimal" value="${groovy:org.apache.ofbiz.accounting.invoice.InvoiceWorker.getInvoiceNotApplied(invoice)}"/>
<if-compare field="notApplied" operator="not-equals" value="0.00" type="BigDecimal">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceCannotChangeStatusToPaid"/>
</add-error>
<check-errors/>
</if-compare>
<!-- if it's OK to mark invoice paid, use parameter for paidDate -->
<if-empty field="parameters.paidDate">
<now-timestamp field="nowTimestamp"/>
<set from-field="nowTimestamp" field="invoice.paidDate"/>
<else>
<set from-field="parameters.paidDate" field="invoice.paidDate"/>
</else>
</if-empty>
</if-compare>
<if-not-empty field="invoice.paidDate">
<if-compare field="parameters.statusId" operator="equals" value="INVOICE_READY">
<clear-field field="invoice.paidDate"/>
</if-compare>
</if-not-empty>
<set from-field="parameters.statusId" field="invoice.statusId"/>
<store-value value-field="invoice"/>
<set field="createInvoiceStatusMap.invoiceId" from-field="invoice.invoiceId"/>
<set field="createInvoiceStatusMap.statusId" from-field="invoice.statusId"/>
<set field="createInvoiceStatusMap.statusDate" from-field="parameters.statusDate"/>
<call-service service-name="createInvoiceStatus" in-map-name="createInvoiceStatusMap"/>
<!-- if the invoice is a payrol invoice, create the payment in the not-paid status -->
<if-compare field="invoice.invoiceTypeId" operator="equals" value="PAYROL_INVOICE">
<if>
<condition>
<or>
<if-compare field="parameters.statusId" operator="equals" value="INVOICE_APPROVED"/>
<if-compare field="parameters.statusId" operator="equals" value="INVOICE_READY"/>
</or>
</condition>
<then>
<!-- only generate payment if no application exist yet -->
<entity-and entity-name="PaymentApplication" list="paymentApplications">
<field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
</entity-and>
<if-empty field="paymentApplications">
<set field="newp.partyIdFrom" from-field="invoice.partyId"/>
<set field="newp.partyIdTo" from-field="invoice.partyIdFrom"/>
<set field="newp.paymentMethodTypeId" value="COMPANY_CHECK"/>
<set field="newp.paymentTypeId" value="PAYROL_PAYMENT"/>
<set field="newp.statusId" value="PMNT_NOT_PAID"/>
<set field="newp.currencyUomId" from-field="invoice.currencyUomId"/>
<call-class-method class-name="org.apache.ofbiz.accounting.invoice.InvoiceWorker" method-name="getInvoiceTotal" ret-field="newp.amount">
<field field="invoice" type="GenericValue"/>
</call-class-method>
<call-service service-name="createPayment" in-map-name="newp">
<result-to-field result-name="paymentId" field="payment.paymentId"/>
</call-service>
<set field="payAppl.invoiceId" from-field="invoice.invoiceId"/>
<set field="payAppl.paymentId" from-field="payment.paymentId"/>
<set field="payAppl.amountApplied" from-field="newp.amount"/>
<call-service service-name="createPaymentApplication" in-map-name="payAppl"/>
</if-empty>
</then>
</if>
</if-compare>
</else>
</if-empty>
</if-compare-field>
</simple-method>
<simple-method method-name="createInvoiceTerm" short-description="Create a Invoice Term">
<call-simple-method method-name="checkInvoiceStatusInProgress"/>
<make-value entity-name="InvoiceTerm" value-field="newEntity"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<sequenced-id sequence-name="InvoiceTerm" field="newEntity.invoiceTermId"/>
<field-to-result field="newEntity.invoiceTermId" result-name="invoiceTermId"/>
<create-value value-field="newEntity"/>
</simple-method>
<simple-method method-name="copyInvoiceToTemplate" short-description="copy a invoice to a InvoiceType starting with 'template'">
<set field="parameters.invoiceIdToCopyFrom" from-field="parameters.invoiceId"/>
<if-compare field="parameters.invoiceTypeId" operator="equals" value="SALES_INVOICE">
<set field="parameters.invoiceTypeId" value="SALES_INV_TEMPLATE"/>
</if-compare>
<if-compare field="parameters.invoiceTypeId" operator="equals" value="PURCHASE_INVOICE">
<set field="parameters.invoiceTypeId" value="PUR_INV_TEMPLATE"/>
</if-compare>
<call-simple-method method-name="copyInvoice"/>
</simple-method>
<!-- ===============subroutine services =================-->
<simple-method method-name="checkInvoiceStatusInProgress" short-description="Check if the invoiceStatus is in progress">
<!-- find the current header record -->
<entity-one entity-name="Invoice" value-field="headerValue"/>
<if-empty field="headerValue">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceNotFound"/>
</add-error>
<log level="info" message="Invoice not found, invoice Id: ${invoiceId}"/>
<check-errors/>
</if-empty>
<!-- check if the status is in progress... -->
<if-compare field="headerValue.statusId" operator="not-equals" value="INVOICE_IN_PROCESS">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceUpdateOnlyWithInProcessStatus"/>
</add-error>
<log level="info" message="Can only update Invoice, when status is in-process...is now: ${headerValue.statusId}"/>
</if-compare>
<check-errors/>
</simple-method>
<simple-method method-name="autoGenerateInvoiceFromExistingInvoice" short-description="Scheduled service to generate Invoice from an existing Invoice">
<entity-and entity-name="Invoice" list="invoices">
<field-map field-name="recurrenceInfoId" from-field="parameters.recurrenceInfoId"/>
</entity-and>
<iterate list="invoices" entry="invoice">
<set-service-fields service-name="copyInvoice" map="invoice" to-map="copyInvoiceCtx"/>
<set field="copyInvoiceCtx.invoiceIdToCopyFrom" from-field="invoice.invoiceId"/>
<call-service service-name="copyInvoice" in-map-name="copyInvoiceCtx">
<result-to-field result-name="invoiceId" field="invoiceId"/>
</call-service>
<set-service-fields service-name="updateInvoice" map="invoice" to-map="updateInvoiceCtx"/>
<set field="updateInvoiceCtx.invoiceId" from-field="invoiceId"/>
<if-compare field="updateInvoiceCtx.invoiceTypeId" operator="equals" value="SALES_INV_TEMPLATE">
<set field="updateInvoiceCtx.invoiceTypeId" value="SALES_INVOICE"/>
</if-compare>
<if-compare field="updateInvoiceCtx.invoiceTypeId" operator="equals" value="PUR_INV_TEMPLATE">
<set field="updateInvoiceCtx.invoiceTypeId" value="PURCHASE_INVOICE"/>
</if-compare>
<clear-field field="invoice"/>
<clear-field field="parameters.invoiceIdToCopyFrom"/>
<clear-field field="updateInvoiceCtx.recurrenceInfoId"/>
<call-service service-name="updateInvoice" in-map-name="updateInvoiceCtx"/>
</iterate>
</simple-method>
<simple-method method-name="cancelInvoice" short-description="Service to cancel the Invoices">
<entity-one entity-name="Invoice" value-field="invoice"/>
<if-empty field="invoice">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingInvoiceNotFound"/>
</add-error>
<check-errors/>
</if-empty>
<get-related relation-name="PaymentApplication" value-field="invoice" list="paymentApplications"/>
<iterate list="paymentApplications" entry="paymentApplication">
<get-related-one relation-name="Payment" value-field="paymentApplication" to-value-field="payment"/>
<if-compare field="payment.statusId" operator="equals" value="PMNT_CONFIRMED">
<set field="paymentStatusMap.paymentId" from-field="payment.paymentId"/>
<set field="isReceipt" value="${groovy:org.apache.ofbiz.accounting.util.UtilAccounting.isReceipt(payment)}" type="Boolean"/>
<set field="isDisbursement" value="${groovy:org.apache.ofbiz.accounting.util.UtilAccounting.isDisbursement(payment)}" type="Boolean"/>
<if-compare field="isReceipt" operator="equals" value="true" type="Boolean">
<set field="paymentStatusMap.statusId" value="PMNT_RECEIVED"/>
<else>
<if-compare field="isDisbursement" operator="equals" value="true" type="Boolean">
<set field="paymentStatusMap.statusId" value="PMNT_SENT"/>
</if-compare>
</else>
</if-compare>
<call-service service-name="setPaymentStatus" in-map-name="paymentStatusMap"/>
</if-compare>
<set field="removePaymentApplicationCtx.paymentApplicationId" from-field="paymentApplication.paymentApplicationId"/>
<call-service service-name="removePaymentApplication" in-map-name="removePaymentApplicationCtx"/>
</iterate>
<field-to-result field="invoice.invoiceTypeId" result-name="invoiceTypeId"/>
</simple-method>
<simple-method method-name="getInvoiceRunningTotal" short-description="calculate running total for Invoices">
<set field="invoiceIds" from-field="parameters.invoiceIds"/>
<set field="runningTotal" type="BigDecimal" value="0"/>
<entity-condition entity-name="Invoice" list="invoiceList">
<condition-expr field-name="invoiceId" operator="in" from-field="invoiceIds"/>
</entity-condition>
<iterate list="invoiceList" entry="invoice">
<set field="getInvoicePaymentInfoListCtx.invoiceId" from-field="invoice.invoiceId"/>
<call-service service-name="getInvoicePaymentInfoList" in-map-name="getInvoicePaymentInfoListCtx">
<result-to-field result-name="invoicePaymentInfoList"/>
</call-service>
<first-from-list list="invoicePaymentInfoList" entry="invoicePaymentInfo"/>
<set field="runningTotal" value="${runningTotal + invoicePaymentInfo.outstandingAmount}" type="BigDecimal"/>
</iterate>
<set-service-fields service-name="getPartyAccountingPreferences" map="parameters" to-map="getPartyAccountingPreferencesMap"/>
<call-service service-name="getPartyAccountingPreferences" in-map-name="getPartyAccountingPreferencesMap">
<result-to-field result-name="partyAccountingPreference"/>
</call-service>
<set field="currencyUomId" from-field="partyAccountingPreference.baseCurrencyUomId"/>
<if-empty field="currencyUomId">
<property-to-field resource="general" property="currency.uom.id.default" field="currencyUomId"/>
</if-empty>
<set field="invoiceRunningTotal" value="${groovy:org.apache.ofbiz.base.util.UtilFormatOut.formatCurrency(runningTotal, currencyUomId, parameters.locale)}"/>
<field-to-result field="invoiceRunningTotal"/>
</simple-method>
<simple-method method-name="getInvoicesFilterByAssocType" short-description="Filter invoices by invoiceItemAssocTypeId">
<set field="invoiceList" from-field="parameters.invoiceList"/>
<set field="invoiceItemAssocTypeId" from-field="parameters.invoiceItemAssocTypeId"/>
<iterate list="invoiceList" entry="invoice">
<entity-and entity-name="InvoiceItemAssoc" list="invoiceItemAssocList" filter-by-date="true">
<field-map field-name="invoiceIdFrom" from-field="invoice.invoiceId"/>
<field-map field-name="invoiceItemAssocTypeId"/>
</entity-and>
<if-empty field="invoiceItemAssocList">
<field-to-list field="invoice" list="filteredInvoiceList"/>
</if-empty>
</iterate>
<field-to-result field="filteredInvoiceList"/>
</simple-method>
<simple-method method-name="removeInvoiceItemAssocOnCancelInvoice" short-description="Remove invoiceItemAssoc record on cancel invoice">
<entity-and entity-name="InvoiceItemAssoc" list="invoiceItemAssocs">
<field-map field-name="invoiceIdTo" from-field="parameters.invoiceId"/>
</entity-and>
<iterate list="invoiceItemAssocs" entry="invoiceItemAssoc">
<set-service-fields service-name="deleteInvoiceItemAssoc" map="invoiceItemAssoc" to-map="deleteInvoiceItemAssocMap"/>
<call-service service-name="deleteInvoiceItemAssoc" in-map-name="deleteInvoiceItemAssocMap"/>
<log level="info" message="Removed invoiceItemAssoc: ${invoiceItemAssoc}"/>
</iterate>
</simple-method>
<simple-method method-name="resetOrderItemBillingAndOrderAdjustmentBillingOnCancelInvoice"
short-description="Reset OrderItemBilling and OrderAdjustmentBilling records on cancel invoice, so it is isn't considered invoiced any more by createInvoiceForOrder service">
<entity-and entity-name="OrderItemBilling" list="orderItemBillings">
<field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
</entity-and>
<iterate list="orderItemBillings" entry="orderItemBilling">
<set field="orderItemBilling.quantity" value="0" type="BigDecimal"/>
<store-value value-field="orderItemBilling"/>
</iterate>
<entity-and entity-name="OrderAdjustmentBilling" list="orderAdjustmentBillings">
<field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
</entity-and>
<iterate list="orderAdjustmentBillings" entry="orderAdjustmentBilling">
<set field="orderAdjustmentBilling.amount" value="0" type="BigDecimal"/>
<store-value value-field="orderAdjustmentBilling"/>
</iterate>
</simple-method>
<simple-method method-name="massChangeInvoiceStatus" short-description="Service set status of Invoices in bulk.">
<iterate list="parameters.invoiceIds" entry="invoiceId">
<set field="setInvoiceStatusMap.invoiceId" from-field="invoiceId"/>
<set field="setInvoiceStatusMap.statusId" from-field="parameters.statusId"/>
<call-service service-name="setInvoiceStatus" in-map-name="setInvoiceStatusMap"/>
<clear-field field="setInvoiceStatusMap"/>
</iterate>
</simple-method>
<simple-method method-name="addtax" short-description="Set Parameter And Call Tax Calculate Service">
<entity-one entity-name="Invoice" value-field="invoice">
<field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
</entity-one>
<entity-and entity-name="InvoiceItem" list="invoiceItems">
<field-map field-name="invoiceId" from-field="invoice.invoiceId"/>
</entity-and>
<entity-and entity-name="PartyContactMechPurpose" list="contacts">
<field-map field-name="partyId" from-field="invoice.partyId"/>
<field-map field-name="contactMechPurposeTypeId" value="SHIPPING_LOCATION"/>
</entity-and>
<if-empty field="contacts">
<entity-and entity-name="PartyContactMechPurpose" list="contacts">
<field-map field-name="partyId" from-field="invoice.partyId"/>
<field-map field-name="contactMechPurposeTypeId" value="GENERAL_LOCATION"/>
</entity-and>
</if-empty>
<if-empty field="contacts">
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingTaxCannotCalculate"/>
</add-error>
</if-empty>
<first-from-list list="contacts" entry="contactMech"/>
<entity-one entity-name="PostalAddress" value-field="postalAddress">
<field-map field-name="contactMechId" from-field="contactMech.contactMechId"/>
</entity-one>
<if-compare field="invoice.invoiceTypeId" value="SALES_INVOICE" operator="equals">
<set field="addtaxMap.billToPartyId" from-field="invoice.partyId"/>
</if-compare>
<if-compare field="invoice.invoiceTypeId" value="PURCHASE_INVOICE" operator="equals">
<set field="addtaxMap.billToPartyId" from-field="invoice.partyIdFrom"/>
</if-compare>
<set field="addtaxMap.payToPartyId" from-field="invoice.partyIdFrom"/>
<iterate list="invoiceItems" entry="invoiceItem">
<entity-and entity-name="Product" list="product">
<field-map field-name="productId" from-field="invoiceItem.productId"/>
</entity-and>
<first-from-list list="product" entry="itemProduct"/>
<if-not-empty field="invoiceItem.productId">
<entity-and entity-name="InvoiceItem" list="findinvoiceItems">
<field-map field-name="invoiceId" from-field="invoice.invoiceId"/>
<field-map field-name="productId" from-field="invoiceItem.productId"/>
<field-map field-name="invoiceItemTypeId" value="ITM_PROMOTION_ADJ"/>
</entity-and>
<if-not-empty field="findinvoiceItems">
<calculate field="total" decimal-scale="${roundingDecimals}" rounding-mode="${roundingMode}" type="BigDecimal">
<calcop operator="multiply">
<calcop operator="get" field="invoiceItem.quantity"/>
<calcop operator="get" field="invoiceItem.amount"/>
</calcop>
</calculate>
<set field="totalAmount" from-field="total" type="BigDecimal"/>
<calculate field="totalAmount" decimal-scale="${roundingDecimals}" rounding-mode="${roundingMode}" type="BigDecimal">
<calcop operator="subtract">
<calcop operator="get" field="totalAmount"/>
<calcop operator="get" field="invoiceItem.amount"/>
</calcop>
</calculate>
<else>
<calculate field="total" decimal-scale="${roundingDecimals}" rounding-mode="${roundingMode}" type="BigDecimal">
<calcop operator="multiply">
<calcop operator="get" field="invoiceItem.quantity"/>
<calcop operator="get" field="invoiceItem.amount"/>
</calcop>
</calculate>
<set field="totalAmount" from-field="total" type="BigDecimal"/>
</else>
</if-not-empty>
<else>
<set field="totalAmount" value="0" type="BigDecimal"/>
</else>
</if-not-empty>
<set field="itemAmount" from-field="totalAmount" type="BigDecimal"/>
<set field="itemPrice" from-field="invoiceItem.amount" type="BigDecimal"/>
<set field="addtaxMap.itemProductList[]" from-field="itemProduct"/>
<set field="addtaxMap.itemAmountList[]" from-field="itemAmount" type="BigDecimal"/>
<set field="addtaxMap.itemPriceList[]" from-field="itemPrice" type="BigDecimal"/>
<set field="addtaxMap.itemQuantityList[]" from-field="invoiceItem.quantity" type="BigDecimal"/>
<set field="addtaxMap.itemShippingList[]" type="BigDecimal" value="0"/>
</iterate>
<set field="addtaxMap.orderShippingAmount" type="BigDecimal" value="0"/>
<set field="addtaxMap.orderPromotionsAmount" type="BigDecimal" value="0"/>
<set field="addtaxMap.shippingAddress" from-field="postalAddress"/>
<if>
<condition>
<not><if-empty field="addtaxMap.itemProductList"></if-empty></not>
</condition>
<then>
<call-service service-name="calcTax" in-map-name="addtaxMap">
<result-to-field result-name="itemAdjustments" field="itemAdjustments"/>
<result-to-field result-name="orderAdjustments" field="orderAdjustments"/>
</call-service>
<iterate list="invoiceItems" entry="findItem">
<if>
<condition>
<not><if-empty field="findItem.productId"></if-empty></not>
</condition>
<then>
<set field="invoiceItemSeqId" from-field="findItem.invoiceItemSeqId"/>
<set field="productId" from-field="findItem.productId"/>
<set field="itemMap.itemSeqIdList[]" from-field="invoiceItemSeqId"/>
<set field="itemMap.productList[]" from-field="productId"/>
</then>
</if>
</iterate>
<set field="countItemId" value="-1" type="Long"/>
<iterate list="itemAdjustments" entry="itemAdjustment">
<calculate field="countItemId">
<calcop operator="add" field="countItemId">
<number value="1"/>
</calcop>
</calculate>
<if-not-empty field="itemAdjustment">
<iterate list="itemAdjustment" entry="orderAdjustment">
<set field="createInvoiceItemContext.invoiceId" from-field="invoice.invoiceId"/>
<if-compare field="invoice.invoiceTypeId" value="PURCHASE_INVOICE" operator="equals">
<set field="createInvoiceItemContext.invoiceItemTypeId" value="PITM_SALES_TAX"/>
<else>
<set field="createInvoiceItemContext.invoiceItemTypeId" value="ITM_SALES_TAX"/>
</else>
</if-compare>
<set field="createInvoiceItemContext.overrideGlAccountId" from-field="orderAdjustment.overrideGlAccountId"/>
<set field="createInvoiceItemContext.productId" from-field="itemMap.productList[countItemId]"/>
<set field="createInvoiceItemContext.taxAuthPartyId" from-field="orderAdjustment.taxAuthPartyId"/>
<set field="createInvoiceItemContext.taxAuthGeoId" from-field="orderAdjustment.taxAuthGeoId"/>
<set field="createInvoiceItemContext.amount" from-field="orderAdjustment.amount" type="BigDecimal"/>
<set field="createInvoiceItemContext.quantity" value="1"/>
<set field="createInvoiceItemContext.parentInvoiceItemSeqId" from-field="itemMap.itemSeqIdList[countItemId]"/>
<set field="createInvoiceItemContext.taxAuthorityRateSeqId" from-field="orderAdjustment.taxAuthorityRateSeqId"/>
<set field="createInvoiceItemContext.description" from-field="orderAdjustment.comments"/>
<!--call createInvoiceItem service for every ItemAdjustment-->
<call-service service-name="createInvoiceItem" in-map-name="createInvoiceItemContext"></call-service>
</iterate>
</if-not-empty>
</iterate>
<iterate list="orderAdjustments" entry="Adjustment">
<if-not-empty field="Adjustment">
<set field="InvoiceItemContext.invoiceId" from-field="invoice.invoiceId"/>
<if-compare field="invoice.invoiceTypeId" value="PURCHASE_INVOICE" operator="equals">
<set field="InvoiceItemContext.invoiceItemTypeId" value="PITM_SALES_TAX"/>
<else>
<set field="InvoiceItemContext.invoiceItemTypeId" value="ITM_SALES_TAX"/>
</else>
</if-compare>
<set field="InvoiceItemContext.overrideGlAccountId" from-field="Adjustment.overrideGlAccountId"/>
<set field="InvoiceItemContext.taxAuthPartyId" from-field="Adjustment.taxAuthPartyId"/>
<set field="InvoiceItemContext.taxAuthGeoId" from-field="Adjustment.taxAuthGeoId"/>
<set field="InvoiceItemContext.amount" from-field="Adjustment.amount" type="BigDecimal"/>
<set field="InvoiceItemContext.quantity" value="1"/>
<set field="InvoiceItemContext.taxAuthorityRateSeqId" from-field="Adjustment.taxAuthorityRateSeqId"/>
<!-- call createInvoiceItem service for every orderAdjustment -->
<call-service service-name="createInvoiceItem" in-map-name="InvoiceItemContext"></call-service>
</if-not-empty>
</iterate>
</then>
<else>
<add-error>
<fail-property resource="AccountingUiLabels" property="AccountingTaxProductIdCannotCalculate"/>
</add-error>
<log level="error" message="Cannot call calcTax service, when don't have productId"/>
<check-errors/>
</else>
</if>
</simple-method>
<simple-method method-name="createInvoiceFromOrder" short-description="Create an invoice from existing order when invoicePerShipment is N">
<entity-one entity-name="OrderHeader" value-field="orderHeader">
<field-map field-name="orderId" from-field="parameters.orderId"/>
</entity-one>
<set field="invoicePerShipment" from-field="orderHeader.invoicePerShipment"/>
<if-empty field="invoicePerShipment">
<property-to-field resource="accounting" property="create.invoice.per.shipment" field="invoicePerShipment"/>
</if-empty>
<if-compare operator="equals" value="N" field="invoicePerShipment">
<entity-and entity-name="OrderItemBilling" list="orderItemBilling">
<field-map field-name="orderId" from-field="parameters.orderId"/>
</entity-and>
<if-empty field="orderItemBilling">
<set field="createInvoiceContext.orderId" from-field="parameters.orderId"/>
<call-service service-name="createInvoiceForOrderAllItems" in-map-name="createInvoiceContext">
<result-to-field result-name="invoiceId" field="invoiceId"/>
</call-service>
<else>
<entity-and list="orderItems" entity-name="OrderItem">
<field-map field-name="orderId" from-field="parameters.orderId"/>
<order-by field-name="orderItemSeqId"/>
</entity-and>
<iterate list="orderItems" entry="orderItem">
<entity-and list="checkOrderItem" entity-name="OrderItemBilling">
<field-map field-name="orderId" from-field="parameters.orderId"/>
<field-map field-name="orderItemSeqId" from-field="orderItem.orderItemSeqId"/>
</entity-and>
<if-empty field="checkOrderItem">
<field-to-list list="billItems" field="orderItem"/>
</if-empty>
<set field="createInvoiceContext.orderId" from-field="parameters.orderId"/>
<set field="createInvoiceContext.billItems" from-field="billItems"/>
</iterate>
<call-service service-name="createInvoiceForOrder" in-map-name="createInvoiceContext">
<result-to-field result-name="invoiceId" field="invoiceId"/>
</call-service>
</else>
</if-empty>
<field-to-result field="invoiceId" result-name="invoiceId"/>
</if-compare>
</simple-method>
<!-- InvoiceContent -->
<simple-method method-name="createInvoiceContent" short-description="Create Content For Invoice">
<make-value entity-name="InvoiceContent" value-field="newEntity"/>
<set-pk-fields map="parameters" value-field="newEntity"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<if-empty field="newEntity.fromDate">
<now-timestamp field="nowTimestamp"/>
<set field="newEntity.fromDate" from-field="nowTimestamp"/>
</if-empty>
<create-value value-field="newEntity"/>
<set-service-fields service-name="updateContent" map="parameters" to-map="updateContent"/>
<call-service service-name="updateContent" in-map-name="updateContent"/>
<field-to-result field="newEntity.contentId" result-name="contentId"/>
<field-to-result field="newEntity.invoiceId" result-name="invoiceId"/>
<field-to-result field="newEntity.invoiceContentTypeId" result-name="invoiceContentTypeId"/>
</simple-method>
<simple-method method-name="updateInvoiceContent" short-description="Update Content For Invoice">
<make-value entity-name="InvoiceContent" value-field="lookupPKMap"/>
<set-pk-fields map="parameters" value-field="lookupPKMap"/>
<find-by-primary-key map="lookupPKMap" value-field="lookedUpValue"/>
<set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
<store-value value-field="lookedUpValue"/>
<set-service-fields service-name="updateContent" map="parameters" to-map="updateContent"/>
<call-service service-name="updateContent" in-map-name="updateContent"/>
</simple-method>
<simple-method method-name="createSimpleTextContentForInvoice" short-description="Create Simple Text Content For Invoice">
<set-service-fields service-name="createInvoiceContent" map="parameters" to-map="createInvoiceContentMap"/>
<set-service-fields service-name="createSimpleTextContent" map="parameters" to-map="createSimpleTextMap"/>
<call-service service-name="createSimpleTextContent" in-map-name="createSimpleTextMap">
<result-to-field result-name="contentId" field="createInvoiceContentMap.contentId"/>
</call-service>
<call-service service-name="createInvoiceContent" in-map-name="createInvoiceContentMap"/>
</simple-method>
<simple-method method-name="updateSimpleTextContentForInvoice" short-description="Update Simple Text Content For Invoice">
<set-service-fields service-name="updateInvoiceContent" map="parameters" to-map="updateInvoiceContent"/>
<call-service service-name="updateInvoiceContent" in-map-name="updateInvoiceContent"/>
<set-service-fields service-name="updateSimpleTextContent" map="parameters" to-map="updateSimpleText"/>
<call-service service-name="updateSimpleTextContent" in-map-name="updateSimpleText"/>
</simple-method>
<simple-method method-name="isInvoiceInForeignCurrency" short-description="check if a invoice is in a foreign currency related to the accounting company.">
<entity-one entity-name="InvoiceAndType" value-field="invoice">
<field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
</entity-one>
<if-empty field="invoice">
<log level="error" message="Invoice not found"/>
<return/>
</if-empty>
<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-compare field="isPurchaseInvoice" operator="equals" value="true" type="Boolean">
<set field="pref.organizationPartyId" from-field="invoice.partyId"/>
</if-compare>
<if-compare field="isSalesInvoice" operator="equals" value="true" type="Boolean">
<set field="pref.organizationPartyId" from-field="invoice.partyIdFrom"/>
</if-compare>
<call-service service-name="getPartyAccountingPreferences" in-map-name="pref">
<result-to-field result-name="partyAccountingPreference"/>
</call-service>
<if-compare-field field="invoice.currencyUomId" operator="equals" to-field="partyAccountingPreference.baseCurrencyUomId">
<set field="isForeign" value="false" type="Boolean"/>
<else>
<set field="isForeign" value="true" type="Boolean"/>
</else>
</if-compare-field>
<field-to-result field="isForeign"/>
</simple-method>
</simple-methods>