This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new 0f0202c7ef Fixed: Mini-lang to Groovy regressions in
InvoiceServicesScript (OFBIZ-13575)
0f0202c7ef is described below
commit 0f0202c7ef4cd46b2610cd3853754faf8389524b
Author: Mridul Pathak <[email protected]>
AuthorDate: Fri Sep 11 23:44:05 2026 +0530
Fixed: Mini-lang to Groovy regressions in InvoiceServicesScript
(OFBIZ-13575)
- getInvoicesFilterByAssocType: invert filter condition so only invoices
without the specified association are returned, restoring commission run
behavior.
- addTaxOnInvoice: align parallel input lists for calcTax by only adding
amounts and quantities when productId is present, preventing misalignment on
non-product line items.
- updateInvoiceItem: guard calculateProductPrice to only run when productId
exists, and enforce mandatory amount check on all item updates.
- autoGenerateInvoiceFromExistingInvoice: use map subscript access for
switchType and ensure recurrenceInfoId is cleared on all generated invoices.
- copyInvoice: handle getInvoice failure gracefully to avoid NPE, reset
invoiceDate to nowTimestamp, and clear paidDate on the new invoice.
- createInvoiceFromOrder: return error if orderHeader is not found instead
of throwing NPE.
- getInvoiceRunningTotal: use safe navigation when accessing
partyAccountingPreference baseCurrencyUomId.
- getNextInvoiceId & invoiceSequenceRestart: explicitly declare local
variables to prevent leaking into the script binding.
---
.../invoice/InvoiceServicesScript.groovy | 46 ++++++++++++----------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git
a/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/invoice/InvoiceServicesScript.groovy
b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/invoice/InvoiceServicesScript.groovy
index d40b1f0887..d72fb637d9 100644
---
a/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/invoice/InvoiceServicesScript.groovy
+++
b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/invoice/InvoiceServicesScript.groovy
@@ -69,7 +69,7 @@ Map getNextInvoiceId() {
invoiceIdTemp = parameters.invoiceId
if (invoiceIdTemp) {
//check the provided ID
- errorMsg = UtilValidate.checkValidDatabaseId(invoiceIdTemp)
+ String errorMsg = UtilValidate.checkValidDatabaseId(invoiceIdTemp)
if (errorMsg != null) {
return error("In getNextInvoiceId ${errorMsg}")
}
@@ -109,7 +109,7 @@ Map invoiceSequenceRestart() {
Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
if (partyAcctgPreference.lastInvoiceRestartDate) {
//first figure out if we need to reset the lastInvoiceNumber; is the
lastInvoiceRestartDate after the fiscalYearStartMonth/Day for this year?
- curYearFiscalStartDate = UtilDateTime.getYearStart(nowTimestamp,
+ Timestamp curYearFiscalStartDate =
UtilDateTime.getYearStart(nowTimestamp,
partyAcctgPreference.fiscalYearStartDay,
partyAcctgPreference.fiscalYearStartMonth, 0L)
if (partyAcctgPreference.lastInvoiceRestartDate <
curYearFiscalStartDate && nowTimestamp >= curYearFiscalStartDate) {
//less than fiscal year start, we need to reset it
@@ -199,12 +199,17 @@ Map updateInvoice() {
*/
Map copyInvoice() {
Map serviceResult = run service: 'getInvoice', with: [invoiceId:
parameters.invoiceIdToCopyFrom]
+ if (ServiceUtil.isError(serviceResult) ||
ServiceUtil.isFailure(serviceResult) || !serviceResult.invoice) {
+ return serviceResult ?: error(label('AccountingUiLabels',
'AccountingInvoiceNotFound', [invoiceId: parameters.invoiceIdToCopyFrom]))
+ }
GenericValue invoice = serviceResult.invoice
List<GenericValue> invoiceItems = serviceResult.invoiceItems
invoice.invoiceTypeId = parameters.invoiceTypeId ?: invoice.invoiceTypeId
serviceResult = run service: 'createInvoice', with: [*:
invoice.getAllFields(),
statusId:
'INVOICE_IN_PROCESS',
- invoiceId: null]
+ invoiceId: null,
+ invoiceDate:
UtilDateTime.nowTimestamp(),
+ paidDate: null]
String newInvoiceId = serviceResult.invoiceId
invoiceItems.each {
run service: 'createInvoiceItem', with: [*: it.getAllFields(),
@@ -386,14 +391,14 @@ Map updateInvoiceItem() {
invoiceItem.setNonPKFields(parameters, true)
// check if the productNumber is updated, when yes retrieve product
description and price
- if (lookedInvoiceItem.productId != invoiceItem.productId) {
+ if (invoiceItem.productId && lookedInvoiceItem.productId !=
invoiceItem.productId) {
GenericValue product = from('Product').where(productId:
invoiceItem.productId).cache().queryOne()
invoiceItem.description = product?.description
Map serviceResult = run service: 'calculateProductPrice', with:
[product: product]
invoiceItem.amount = serviceResult.price
- if (invoiceItem.amount == null) {
- return error(label('AccountingUiLabels',
'AccountingInvoiceAmountIsMandatory'))
- }
+ }
+ if (invoiceItem.amount == null) {
+ return error(label('AccountingUiLabels',
'AccountingInvoiceAmountIsMandatory'))
}
if (lookedInvoiceItem != invoiceItem) {
invoiceItem.store()
@@ -429,12 +434,10 @@ Map autoGenerateInvoiceFromExistingInvoice() {
.each {
Map serviceResult = run service: 'copyInvoice', with: [*:
it.getAllFields(),
invoiceIdToCopyFrom: it.invoiceId]
- if (switchType.containsKey(it.invoiceTypeId)) {
- String invoiceId = serviceResult.invoiceId
- run service: 'updateInvoice', with: [invoiceId: invoiceId,
- recurrenceInfoId:
null,
- invoiceTypeId:
switchType(it.invoiceTypeId)]
- }
+ String invoiceId = serviceResult.invoiceId
+ run service: 'updateInvoice', with: [invoiceId: invoiceId,
+ recurrenceInfoId: null,
+ invoiceTypeId:
switchType[it.invoiceTypeId] ?: it.invoiceTypeId]
}
return success()
}
@@ -453,7 +456,7 @@ Map getInvoiceRunningTotal() {
}
Map serviceResult = run service: 'getPartyAccountingPreferences', with:
parameters
Map partyAccountingPreference = serviceResult.partyAccountingPreference
- String currencyUomId = partyAccountingPreference.baseCurrencyUomId ?:
+ String currencyUomId = partyAccountingPreference?.baseCurrencyUomId ?:
EntityUtilProperties.getPropertyValue('general',
'currency.uom.id.default', 'USD', delegator)
return success([invoiceRunningTotal:
UtilFormatOut.formatCurrency(runningTotal, currencyUomId, parameters.locale)])
}
@@ -472,7 +475,7 @@ Map getInvoicesFilterByAssocType() {
.distinct()
.filterByDate()
.getFieldList('invoiceIdFrom')
- return success([filteredInvoiceList: parameters.invoiceList.findAll {
invoiceIds.contains(it.invoiceId) }])
+ return success([filteredInvoiceList: parameters.invoiceList.findAll {
!invoiceIds.contains(it.invoiceId) }])
}
/**
@@ -567,11 +570,11 @@ Map addTaxOnInvoice() {
if (promoAdjs) {
totalAmount -= it.amount
}
+ addTaxMap.itemAmountList << totalAmount
+ addTaxMap.itemPriceList << it.amount
+ addTaxMap.itemQuantityList << it.quantity
+ addTaxMap.itemShippingList << BigDecimal.ZERO
}
- addTaxMap.itemAmountList << totalAmount
- addTaxMap.itemPriceList << it.amount
- addTaxMap.itemQuantityList << it.quantity
- addTaxMap.itemShippingList << BigDecimal.ZERO
}
if (!addTaxMap.itemProductList) {
return error(label('AccountingUiLabels',
'AccountingTaxProductIdCannotCalculate'))
@@ -624,7 +627,10 @@ Map addTaxOnInvoice() {
*/
Map createInvoiceFromOrder() {
GenericValue order = from('OrderHeader').where(parameters).queryOne()
- String invoicePerShipment = order?.invoicePerShipment ?:
+ if (!order) {
+ return error(label('OrderUiLabels', 'OrderOrderNotFound', parameters))
+ }
+ String invoicePerShipment = order.invoicePerShipment ?:
EntityUtilProperties.getPropertyValue('accounting',
'create.invoice.per.shipment', 'N', delegator)
if (invoicePerShipment == 'N') {
List orderItemBillingItemsSeqIds =
from('OrderItemBilling').where(orderId:
order.orderId).getFieldList('orderItemSeqId')