Author: apatel
Date: Wed Jul 29 10:54:02 2009
New Revision: 798854
URL: http://svn.apache.org/viewvc?rev=798854&view=rev
Log:
Adding ability to create Commission invoice from sales invoices. Patch from
OFBIZ-2713. Thanks Rishi, Sumit, Awdesh, Amit for working on it.
Added:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
(with props)
ofbiz/trunk/applications/accounting/testdef/invoicetests.xml (with props)
Modified:
ofbiz/trunk/applications/accounting/data/PaymentsInvoices.xml
ofbiz/trunk/applications/accounting/ofbiz-component.xml
ofbiz/trunk/applications/accounting/servicedef/secas.xml
ofbiz/trunk/applications/accounting/servicedef/services_agreement.xml
ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/agreement/AgreementServices.java
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
ofbiz/trunk/applications/accounting/webapp/ap/WEB-INF/controller.xml
ofbiz/trunk/applications/accounting/webapp/ap/invoices/CommissionRun.ftl
ofbiz/trunk/applications/accounting/widget/ap/InvoiceScreens.xml
Modified: ofbiz/trunk/applications/accounting/data/PaymentsInvoices.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/data/PaymentsInvoices.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/data/PaymentsInvoices.xml (original)
+++ ofbiz/trunk/applications/accounting/data/PaymentsInvoices.xml Wed Jul 29
10:54:02 2009
@@ -158,4 +158,25 @@
<GlAccountOrganization glAccountId="140000" organizationPartyId="Company"
fromDate="2001-01-01 00:00:00.0" postedBalance="101.97"/>
<GlAccountOrganization glAccountId="210000" organizationPartyId="Company"
fromDate="2001-01-01 00:00:00.0" postedBalance="0.00"/>
<GlAccountOrganization glAccountId="516100" organizationPartyId="Company"
fromDate="2001-01-01 00:00:00.0" postedBalance="14.88"/>
+
+ <!-- Demo invoice data for sales invoice with INVOICE_PAID status -->
+ <Party partyId="DemoCustAgent"/>
+ <PartyRole partyId="DemoCustAgent" roleTypeId="SALES_REP"/>
+ <Product productId="WG-9943"/>
+ <Product productId="WG-9943-B3"/>
+
+ <Agreement agreementId="8000" partyIdFrom="Company"
partyIdTo="DemoCustAgent" agreementTypeId="COMMISSION_AGREEMENT"
description="Commission Agreement with DemoCustAgent"/>
+ <AgreementItem agreementId="8000" agreementItemSeqId="0001"
agreementItemTypeId="AGREEMENT_COMMISSION" currencyUomId="USD"
agreementText="Commission in USD"/>
+ <AgreementTerm agreementTermId="8000" termTypeId="FIN_COMM_FIXED"
agreementId="8000" agreementItemSeqId="0001" invoiceItemTypeId="INV_FPROD_ITEM"
termValue="1.000" termDays="30"/>
+ <AgreementTerm agreementTermId="8001" termTypeId="FIN_COMM_VARIABLE"
agreementId="8000" agreementItemSeqId="0001" invoiceItemTypeId="INV_FPROD_ITEM"
termValue="3.000" termDays="30"/>
+ <AgreementTerm agreementTermId="8002" termTypeId="FIN_COMM_MIN"
agreementId="8000" agreementItemSeqId="0001" invoiceItemTypeId="INV_FPROD_ITEM"
termValue="0.000" termDays="30"/>
+ <AgreementProductAppl agreementId="8000" agreementItemSeqId="0001"
productId="WG-9943"/>
+
+ <Invoice invoiceId="8100" invoiceTypeId="SALES_INVOICE"
partyIdFrom="Company" partyId="admin" statusId="INVOICE_PAID"
invoiceDate="2009-07-08 11:54:00.765" paidDate="2009-07-08 11:54:03.246"
currencyUomId="USD"/>
+ <InvoiceStatus statusId="INVOICE_IN_PROCESS" invoiceId="8100"
statusDate="2009-07-08 11:54:00.845"/>
+ <InvoiceStatus statusId="INVOICE_PAID" invoiceId="8100"
statusDate="2009-07-08 11:54:03.8"/>
+ <InvoiceStatus statusId="INVOICE_READY" invoiceId="8100"
statusDate="2009-07-08 11:54:01.863"/>
+ <InvoiceItem invoiceId="8100" invoiceItemSeqId="00002"
invoiceItemTypeId="INV_FPROD_ITEM" productId="WG-9943-B3" quantity="3.000000"
amount="440.000" description="Giant Widget B3"/>
+ <InvoiceRole invoiceId="8100" partyId="Company"
roleTypeId="BILL_FROM_VENDOR" datetimePerformed="2009-07-08 11:54:00.979"/>
+ <InvoiceRole invoiceId="8100" partyId="DemoCustAgent"
roleTypeId="SALES_REP" datetimePerformed="2009-07-08 11:54:00.979"/>
</entity-engine-xml>
Modified: ofbiz/trunk/applications/accounting/ofbiz-component.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/ofbiz-component.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/ofbiz-component.xml (original)
+++ ofbiz/trunk/applications/accounting/ofbiz-component.xml Wed Jul 29 10:54:02
2009
@@ -80,6 +80,7 @@
<test-suite loader="main" location="testdef/accountingtests.xml"/>
<test-suite loader="main" location="testdef/paymenttests.xml"/>
+ <test-suite loader="main" location="testdef/invoicetests.xml"/>
<webapp name="accounting"
title="Accounting"
Added:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml?rev=798854&view=auto
==============================================================================
---
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
(added)
+++
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
Wed Jul 29 10:54:02 2009
@@ -0,0 +1,74 @@
+<?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"
+
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/simple-methods.xsd">
+ <!-- Test case for Commission Run -->
+ <simple-method method-name="testCommissionRun" short-description="Test
case for Commission Run" login-required="false">
+
+ <!-- Precondition : For Creating Commission invoice following data
should be there :
+ 1 ) Sales invoices with paid status.(invoiceId = "8100")
+ 2 ) Sales Representative with agreement to Company on product
(DemoCustAgent and DemoRepAll). -->
+ <!-- Postcondition :
+ 1 ) Two commission will be creating for the parties
DemoCustAgent and DemoRepAll (like 10000 and 10001 invoiceId).
+ 2 ) Its amountTotal will be same as commission cost of
associated products. -->
+
+ <set field="invoiceId" value="8100"/>
+ <set field="invoiceIds[]" from-field="invoiceId"/>
+ <set field="partyIds[]" value="DemoRepAll"/>
+ <set field="partyIds[]" value="DemoCustAgent"/>
+ <set field="partyIds[]" value="DemoRepStore"/>
+ <set field="invoiceTotal" type="BigDecimal" value="0"/>
+ <entity-one entity-name="UserLogin" value-field="userLogin">
+ <field-map field-name="userLoginId" value="system"/>
+ </entity-one>
+ <entity-and entity-name="InvoiceItem" list="invoiceItems">
+ <field-map field-name="invoiceId" from-field="invoiceId"/>
+ </entity-and>
+ <iterate list="invoiceItems" entry="invoiceItem">
+ <if-compare field="invoiceItem.productId" operator="equals"
value="WG-9943-B3">
+ <set field="invoiceTotal" value="${invoiceTotal +
(invoiceItem.quantity * (invoiceItem.amount * 3 / 100 + 1))}"
type="BigDecimal"/>
+ </if-compare>
+ </iterate>
+ <set field="createCommissionInvoicesMap.invoiceIds"
from-field="invoiceIds"/>
+ <set field="createCommissionInvoicesMap.partyIds"
from-field="partyIds"/>
+ <set field="createCommissionInvoicesMap.userLogin"
from-field="userLogin"/>
+ <call-service service-name="createCommissionInvoices"
in-map-name="createCommissionInvoicesMap">
+ <result-to-field result-name="invoicesCreated"/>
+ </call-service>
+ <assert>
+ <not><if-empty field="invoicesCreated"/></not>
+ </assert>
+ <check-errors/>
+ <iterate list="invoicesCreated" entry="invoice">
+ <call-class-method method-name="getInvoiceTotal"
ret-field="amountTotal" class-name="org.ofbiz.accounting.invoice.InvoiceWorker">
+ <field field="delegator"
type="org.ofbiz.entity.GenericDelegator"/>
+ <field field="invoice" type="String"/>
+ </call-class-method>
+ <assert>
+ <or>
+ <if-compare-field field="amountTotal" operator="equals"
to-field="invoiceTotal"/>
+ </or>
+ </assert>
+ <check-errors/>
+ </iterate>
+ <log level="info" message="Commission Invoice ${invoicesCreated} is
created successfully for ${partyIds}"/>
+ </simple-method>
+</simple-methods>
Propchange:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml
Modified: ofbiz/trunk/applications/accounting/servicedef/secas.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/secas.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/servicedef/secas.xml (original)
+++ ofbiz/trunk/applications/accounting/servicedef/secas.xml Wed Jul 29
10:54:02 2009
@@ -24,7 +24,6 @@
<eca service="createPaymentApplication" event="commit">
<condition field-name="invoiceId" operator="is-not-empty"/>
<action service="checkInvoicePaymentApplications" mode="sync"/>
- <action service="createCommissionInvoices" mode="sync"
run-as-user="system"/>
</eca>
<!-- Uncomment this if you want commission invoices to be set to READY
automatically, which means they are official
Modified: ofbiz/trunk/applications/accounting/servicedef/services_agreement.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/services_agreement.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/servicedef/services_agreement.xml
(original)
+++ ofbiz/trunk/applications/accounting/servicedef/services_agreement.xml Wed
Jul 29 10:54:02 2009
@@ -227,6 +227,8 @@
</description>
<permission-service service-name="acctgCommissionPermissionCheck"
main-action="VIEW"/>
<attribute name="productId" type="String" mode="IN" optional="false"/>
+ <attribute name="invoiceId" type="String" mode="IN" optional="true"/>
+ <attribute name="invoiceItemSeqId" type="String" mode="IN"
optional="true"/>
<attribute name="invoiceItemTypeId" type="String" mode="IN"
optional="false"/>
<attribute name="amount" type="BigDecimal" mode="IN" optional="false"/>
<attribute name="quantity" type="BigDecimal" mode="IN"
optional="true"/>
Modified: ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml
(original)
+++ ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml Wed Jul
29 10:54:02 2009
@@ -168,14 +168,9 @@
</service>
<service name="createCommissionInvoices" engine="java"
location="org.ofbiz.accounting.invoice.InvoiceServices"
invoke="createCommissionInvoices">
- <description>
- Create commission invoices from an order or return invoice. It
- does not create any OrderItemBilling or ReturnItemBilling entities
for partial commissions. Therefore, correct value
- of the amountApplied needs to be supplied.
- </description>
- <attribute name="invoiceId" type="String" mode="IN" optional="false"/>
- <attribute name="invoiceItemSeqId" type="String" mode="IN"
optional="true"/>
- <attribute name="amountApplied" type="BigDecimal" mode="IN"
optional="false"/>
+ <description>Create commission invoice for the list of sales
invoices</description>
+ <attribute name="partyIds" type="List" mode="IN" optional="true"/>
+ <attribute name="invoiceIds" type="List" mode="IN" optional="false"/>
<attribute name="invoicesCreated" type="List" mode="OUT"
optional="true"/>
</service>
<service name="sampleInvoiceAffiliateCommission" engine="simple"
Modified:
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/agreement/AgreementServices.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/agreement/AgreementServices.java?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
---
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/agreement/AgreementServices.java
(original)
+++
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/agreement/AgreementServices.java
Wed Jul 29 10:54:02 2009
@@ -92,6 +92,8 @@
quantity = quantity.abs();
String productId = (String) context.get("productId");
String invoiceItemTypeId = (String)
context.get("invoiceItemTypeId");
+ String invoiceItemSeqId = (String) context.get("invoiceItemSeqId");
+ String invoiceId = (String) context.get("invoiceId");
// Collect agreementItems applicable to this orderItem/returnItem
// TODO: partyIds should be part of this query!
@@ -165,6 +167,8 @@
Map<String, Object> partyCommissionResult = UtilMisc.toMap(
"partyIdFrom",
agreementItem.getString("partyIdFrom"),
"partyIdTo", agreementItem.getString("partyIdTo"),
+ "invoiceItemSeqId", invoiceItemSeqId,
+ "invoiceId", invoiceId,
"commission", commission,
"quantity", quantity,
"currencyUomId",
agreementItem.getString("currencyUomId"),
@@ -172,7 +176,9 @@
if (days >= 0) {
partyCommissionResult.put("days", Long.valueOf(days));
}
- commissions.add(partyCommissionResult);
+ if(!commissions.contains(partyCommissionResult)) {
+ commissions.add(partyCommissionResult);
+ }
}
}
} catch (GenericEntityException e) {
Modified:
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
---
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
(original)
+++
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
Wed Jul 29 10:54:02 2009
@@ -32,6 +32,7 @@
import javolution.util.FastMap;
+import org.apache.commons.collections.CollectionUtils;
import org.ofbiz.accounting.payment.BillingAccountWorker;
import org.ofbiz.accounting.payment.PaymentWorker;
import org.ofbiz.accounting.payment.PaymentGatewayServices;
@@ -832,187 +833,225 @@
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
- List invoicesCreated = FastList.newInstance();
-
- String invoiceIdIn = (String) context.get("invoiceId");
- String invoiceItemSeqIdIn = (String) context.get("invoiceItemSeqId");
- BigDecimal amountTotal = InvoiceWorker.getInvoiceTotal(delegator,
invoiceIdIn);
- // never use equals for BigDecimal - use either signum or compareTo
- if (amountTotal.signum() == 0) {
- Debug.logWarning("Invoice [" + invoiceIdIn + "] has an amount
total of [" + amountTotal + "], so no commission invoice will be created",
module);
- return
ServiceUtil.returnSuccess(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionZeroInvoiceAmount",locale));
- }
-
- try {
- List billFromVendorInvoiceRoles =
EntityUtil.getFieldListFromEntityList(delegator.findByAnd("InvoiceRole",
UtilMisc.<String, Object>toMap("invoiceId", invoiceIdIn, "roleTypeId",
"BILL_FROM_VENDOR")), "partyId", true);
- List salesRepInvoiceRoles =
EntityUtil.getFieldListFromEntityList(delegator.findByAnd("InvoiceRole",
UtilMisc.<String, Object>toMap("invoiceId", invoiceIdIn, "roleTypeId",
"SALES_REP")), "partyId", true);
- if (UtilValidate.isEmpty(billFromVendorInvoiceRoles) ||
UtilValidate.isEmpty(salesRepInvoiceRoles)) {
- return ServiceUtil.returnSuccess();
+ List<String> salesInvoiceIds = (List) context.get("invoiceIds");
+ List<Map> invoicesCreated = FastList.newInstance();
+ Map commissionParties = FastMap.newInstance();
+ for (String salesInvoiceId : salesInvoiceIds) {
+ List<String> salesRepPartyIds = (List) context.get("partyIds");
+ BigDecimal amountTotal = InvoiceWorker.getInvoiceTotal(delegator,
salesInvoiceId);
+ if (amountTotal.signum() == 0) {
+ Debug.logWarning("Invoice [" + salesInvoiceId + "] has an
amount total of [" + amountTotal + "], so no commission invoice will be
created", module);
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionZeroInvoiceAmount",locale));
}
- // Change this when amountApplied is BigDecimal, 18 digit scale to
keep all the precision
- BigDecimal appliedFraction =
((BigDecimal)context.get("amountApplied")).divide(amountTotal, 12, rounding);
- Map inMap = UtilMisc.toMap("invoiceId", invoiceIdIn);
- GenericValue invoice = delegator.findByPrimaryKey("Invoice",
inMap);
- String invoiceTypeId = invoice.getString("invoiceTypeId");
-
- // Determine sales or return
+ BigDecimal appliedFraction = amountTotal.divide(amountTotal, 12,
rounding);
+ GenericValue invoice = null;
boolean isReturn = false;
- if ("SALES_INVOICE".equals(invoiceTypeId)) {
- isReturn = false;
- } else if ("CUST_RTN_INVOICE".equals(invoiceTypeId)) {
- isReturn = true;
- } else {
- Debug.logWarning("This type of invoice has no commission;
returning success", module);
- return
ServiceUtil.returnSuccess(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionInvalid",locale));
- }
-
- if (invoiceItemSeqIdIn != null) {
- inMap.put("invoiceItemSeqId", invoiceItemSeqIdIn);
+ List<String> billFromVendorInvoiceRoles = new ArrayList<String>();
+ List<GenericValue> invoiceItems = new ArrayList<GenericValue>();
+ try {
+ List invoiceRoleConds = UtilMisc.toList(
+ EntityCondition.makeCondition("invoiceId",
EntityOperator.EQUALS, salesInvoiceId),
+ EntityCondition.makeCondition("roleTypeId",
EntityOperator.EQUALS, "BILL_FROM_VENDOR"));
+ billFromVendorInvoiceRoles =
EntityUtil.getFieldListFromEntityList(delegator.findList("InvoiceRole",
EntityCondition.makeCondition(invoiceRoleConds, EntityOperator.AND), null,
null, null, false), "partyId", true);
+ invoiceRoleConds = UtilMisc.toList(
+ EntityCondition.makeCondition("invoiceId",
EntityOperator.EQUALS, salesInvoiceId),
+ EntityCondition.makeCondition("roleTypeId",
EntityOperator.EQUALS, "SALES_REP"));
+ // if the receiving parties is empty then we will create
commission invoices for all sales agent associated to sales invoice.
+ if (UtilValidate.isEmpty(salesRepPartyIds)) {
+ salesRepPartyIds =
EntityUtil.getFieldListFromEntityList(delegator.findList("InvoiceRole",
EntityCondition.makeCondition(invoiceRoleConds, EntityOperator.AND), null,
null, null, false), "partyId", true);
+ if (UtilValidate.isEmpty(salesRepPartyIds)) {
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"No party found with
role sales representative for sales invoice "+ salesInvoiceId,locale));
+ }
+ } else {
+ List<String> salesInvoiceRolePartyIds =
EntityUtil.getFieldListFromEntityList(delegator.findList("InvoiceRole",
EntityCondition.makeCondition(invoiceRoleConds, EntityOperator.AND), null,
null, null, false), "partyId", true);
+ if (UtilValidate.isNotEmpty(salesInvoiceRolePartyIds)) {
+ salesRepPartyIds = (List)
CollectionUtils.intersection(salesRepPartyIds, salesInvoiceRolePartyIds);
+ }
+ }
+ invoice = delegator.findOne("Invoice",
UtilMisc.toMap("invoiceId", salesInvoiceId), false);
+ String invoiceTypeId = invoice.getString("invoiceTypeId");
+ if ("CUST_RTN_INVOICE".equals(invoiceTypeId)) {
+ isReturn = true;
+ } else if (!"SALES_INVOICE".equals(invoiceTypeId)) {
+ Debug.logWarning("This type of invoice has no commission;
returning success", module);
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionInvalid",locale));
+ }
+ invoiceItems = delegator.findList("InvoiceItem",
EntityCondition.makeCondition("invoiceId", EntityOperator.EQUALS,
salesInvoiceId), null, null, null, false);
+ } catch (GenericEntityException e) {
+ return ServiceUtil.returnError(e.getMessage());
}
- List invoiceItems = delegator.findByAnd("InvoiceItem", inMap);
-
- // Map of commission Lists (of Maps) for each party
- Map commissionParties = FastMap.newInstance();
- // Determine commissions for various parties
- Iterator itemIter = invoiceItems.iterator();
- while (itemIter.hasNext()) {
- GenericValue invoiceItem = (GenericValue) itemIter.next();
+ // Map of commission Lists (of Maps) for each party.
+ // Determine commissions for various parties.
+ for (GenericValue invoiceItem : invoiceItems) {
BigDecimal amount = ZERO;
BigDecimal quantity = ZERO;
quantity = invoiceItem.getBigDecimal("quantity");
amount = invoiceItem.getBigDecimal("amount");
amount = isReturn ? amount.negate() : amount;
String productId = invoiceItem.getString("productId");
-
+ String invoiceItemSeqId =
invoiceItem.getString("invoiceItemSeqId");
+ String invoiceId = invoiceItem.getString("invoiceId");
// Determine commission parties for this invoiceItem
if (productId != null && productId.length() > 0) {
- Map outMap = dispatcher.runSync("getCommissionForProduct",
UtilMisc.<String, Object>toMap(
- "productId", productId,
- "invoiceItemTypeId",
invoiceItem.getString("invoiceItemTypeId"),
- "amount", amount,
- "quantity", quantity,
- "userLogin", userLogin));
- if (ServiceUtil.isError(outMap)) {
- return outMap;
+ Map resultMap = null;
+ try{
+ resultMap =
dispatcher.runSync("getCommissionForProduct", UtilMisc.<String, Object>toMap(
+ "productId", productId,
+ "invoiceId", invoiceId,
+ "invoiceItemSeqId", invoiceItemSeqId,
+ "invoiceItemTypeId",
invoiceItem.getString("invoiceItemTypeId"),
+ "amount", amount,
+ "quantity", quantity,
+ "userLogin", userLogin));
+ } catch (GenericServiceException e) {
+ return ServiceUtil.returnError(e.getMessage());
}
-
// build a Map of partyIds (both to and from) in a
commission and the amounts
// Note that getCommissionForProduct returns a List of
Maps with a lot values. See services.xml definition for reference.
- List itemComms = (List) outMap.get("commissions");
- if (UtilValidate.isNotEmpty(itemComms)) {
- Iterator it = itemComms.iterator();
- while (it.hasNext()) {
- Map commMap = (Map)it.next();
- if
(!billFromVendorInvoiceRoles.contains(commMap.get("partyIdFrom")) ||
!salesRepInvoiceRoles.contains(commMap.get("partyIdTo"))) {
+ List<Map> itemCommissions = (List)
resultMap.get("commissions");
+ if (UtilValidate.isNotEmpty(itemCommissions)) {
+ for (Map commissionMap : itemCommissions) {
+ commissionMap.put("invoice", invoice);
+ commissionMap.put("appliedFraction",
appliedFraction);
+ if
(!billFromVendorInvoiceRoles.contains(commissionMap.get("partyIdFrom")) ||
!salesRepPartyIds.contains(commissionMap.get("partyIdTo"))) {
continue;
}
- String partyIdFromTo = (String)
commMap.get("partyIdFrom") + (String) commMap.get("partyIdTo");
+ String partyIdFromTo = (String)
commissionMap.get("partyIdFrom") + (String) commissionMap.get("partyIdTo");
if (!commissionParties.containsKey(partyIdFromTo))
{
- commissionParties.put(partyIdFromTo,
UtilMisc.toList(commMap));
+ commissionParties.put(partyIdFromTo,
UtilMisc.toList(commissionMap));
} else {
-
((List)commissionParties.get(partyIdFromTo)).add(commMap);
+
((List)commissionParties.get(partyIdFromTo)).add(commissionMap);
}
}
}
}
}
-
- String invoiceType = "COMMISSION_INVOICE";
- Timestamp now = UtilDateTime.nowTimestamp();
-
- // Create invoice for each commission receiving party
- Iterator it = commissionParties.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry pair = (Map.Entry)it.next();
- List toStore = FastList.newInstance();
- List commList = (List)pair.getValue();
- // get the billing parties
- if (UtilValidate.isEmpty(commList)) {
- continue;
- }
-
- // From and To are reversed between commission and invoice
- String partyIdBillTo = (String)
((Map)commList.get(0)).get("partyIdFrom");
- String partyIdBillFrom = (String)
((Map)commList.get(0)).get("partyIdTo");
- Long days = (Long) ((Map)commList.get(0)).get("days");
-
- // create the invoice record
- // To and From are in commission's sense, opposite for invoice
- Map createInvoiceContext = FastMap.newInstance();
- createInvoiceContext.put("partyId", partyIdBillTo);
- createInvoiceContext.put("partyIdFrom", partyIdBillFrom);
- createInvoiceContext.put("invoiceDate", now);
- // if there were days associated with the commission
agreement, then set a dueDate for the invoice.
- if (days != null) {
- createInvoiceContext.put("dueDate",
UtilDateTime.getDayEnd(now, days));
- }
- createInvoiceContext.put("invoiceTypeId", invoiceType);
- // start with INVOICE_IN_PROCESS, in the INVOICE_READY we
can't change the invoice (or shouldn't be able to...)
- createInvoiceContext.put("statusId", "INVOICE_IN_PROCESS");
- createInvoiceContext.put("currencyUomId",
invoice.getString("currencyUomId"));
- createInvoiceContext.put("userLogin", userLogin);
-
- // store the invoice first
- Map createInvoiceResult = dispatcher.runSync("createInvoice",
createInvoiceContext);
- if (ServiceUtil.isError(createInvoiceResult)) {
- return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionError",locale),
null, null, createInvoiceResult);
- }
- String invoiceId = (String)
createInvoiceResult.get("invoiceId");
-
- // create the bill-from (or pay-to) contact mech as the
primary PAYMENT_LOCATION of the party from the store
- List contactMechs =
delegator.findByAnd("PartyContactMechPurpose", UtilMisc.toMap("partyId",
partyIdBillTo, "contactMechPurposeTypeId", "BILLING_LOCATION"));
- if (contactMechs.size() > 0) {
- GenericValue address = (GenericValue) contactMechs.get(0);
- GenericValue payToCm =
delegator.makeValue("InvoiceContactMech", UtilMisc.toMap(
- "invoiceId", invoiceId,
- "contactMechId",
address.getString("contactMechId"),
- "contactMechPurposeTypeId", "BILLING_LOCATION"));
- toStore.add(payToCm);
- }
- contactMechs = delegator.findByAnd("PartyContactMechPurpose",
UtilMisc.toMap("partyId", partyIdBillFrom, "contactMechPurposeTypeId",
"PAYMENT_LOCATION"));
- if (contactMechs.size() > 0) {
- GenericValue address = (GenericValue) contactMechs.get(0);
- GenericValue payToCm =
delegator.makeValue("InvoiceContactMech", UtilMisc.toMap(
- "invoiceId", invoiceId,
- "contactMechId",
address.getString("contactMechId"),
- "contactMechPurposeTypeId", "PAYMENT_LOCATION"));
- toStore.add(payToCm);
- }
-
- // create the item records
- Iterator itt = commList.iterator();
- while (itt.hasNext()) {
- Map elem = (Map) itt.next();
- BigDecimal elemAmount =
((BigDecimal)elem.get("commission")).multiply(appliedFraction);
- BigDecimal quantity = (BigDecimal)elem.get("quantity");
- elemAmount = elemAmount.setScale(decimals, rounding);
- Map resMap = dispatcher.runSync("createInvoiceItem",
UtilMisc.toMap(
+ }
+ Timestamp now = UtilDateTime.nowTimestamp();
+ // Create invoice for each commission receiving party
+ for (Object commissionParty : commissionParties.entrySet()) {
+ Map.Entry pair = (Map.Entry)commissionParty;
+ List toStore = FastList.newInstance();
+ List<Map> commList = (List)pair.getValue();
+ // get the billing parties
+ if (UtilValidate.isEmpty(commList)) {
+ continue;
+ }
+ // From and To are reversed between commission and invoice
+ String partyIdBillTo = (String)
(commList.get(0)).get("partyIdFrom");
+ String partyIdBillFrom = (String)
(commList.get(0)).get("partyIdTo");
+ GenericValue invoice = (GenericValue)
(commList.get(0)).get("invoice");
+ BigDecimal appliedFraction = (BigDecimal)
(commList.get(0)).get("appliedFraction");
+ Long days = (Long) (commList.get(0)).get("days");
+ // create the invoice record
+ // To and From are in commission's sense, opposite for invoice
+ Map createInvoiceMap = FastMap.newInstance();
+ createInvoiceMap.put("partyId", partyIdBillTo);
+ createInvoiceMap.put("partyIdFrom", partyIdBillFrom);
+ createInvoiceMap.put("invoiceDate", now);
+ // if there were days associated with the commission agreement,
then set a dueDate for the invoice.
+ if (days != null) {
+ createInvoiceMap.put("dueDate", UtilDateTime.getDayEnd(now,
days));
+ }
+ createInvoiceMap.put("invoiceTypeId", "COMMISSION_INVOICE");
+ // start with INVOICE_IN_PROCESS, in the INVOICE_READY we can't
change the invoice (or shouldn't be able to...)
+ createInvoiceMap.put("statusId", "INVOICE_IN_PROCESS");
+ createInvoiceMap.put("currencyUomId",
invoice.getString("currencyUomId"));
+ createInvoiceMap.put("userLogin", userLogin);
+ // store the invoice first
+ Map createInvoiceResult = null;
+ try{
+ createInvoiceResult = dispatcher.runSync("createInvoice",
createInvoiceMap);
+ } catch (GenericServiceException e) {
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionError",locale),
null, null, createInvoiceResult);
+ }
+ String invoiceId = (String) createInvoiceResult.get("invoiceId");
+ // create the bill-from (or pay-to) contact mech as the primary
PAYMENT_LOCATION of the party from the store
+ List partyContactMechPurposeConds = UtilMisc.toList(
+ EntityCondition.makeCondition("partyId",
EntityOperator.EQUALS, partyIdBillTo),
+ EntityCondition.makeCondition("contactMechPurposeTypeId",
EntityOperator.EQUALS, "BILLING_LOCATION"));
+ List<GenericValue> partyContactMechPurposes = new
ArrayList<GenericValue>();
+ try {
+ partyContactMechPurposes =
delegator.findList("PartyContactMechPurpose",
+
EntityCondition.makeCondition(partyContactMechPurposeConds,
EntityOperator.AND), null, null, null, false);
+ } catch (GenericEntityException e) {
+ return ServiceUtil.returnError(e.getMessage());
+ }
+ if (partyContactMechPurposes.size() > 0) {
+ GenericValue address = partyContactMechPurposes.get(0);
+ GenericValue invoiceContactMech =
delegator.makeValue("InvoiceContactMech", UtilMisc.toMap(
+ "invoiceId", invoiceId,
+ "contactMechId", address.getString("contactMechId"),
+ "contactMechPurposeTypeId", "BILLING_LOCATION"));
+ toStore.add(invoiceContactMech);
+ }
+ partyContactMechPurposeConds = UtilMisc.toList(
+ EntityCondition.makeCondition("partyId",
EntityOperator.EQUALS, partyIdBillTo),
+ EntityCondition.makeCondition("contactMechPurposeTypeId",
EntityOperator.EQUALS, "PAYMENT_LOCATION"));
+ try {
+ partyContactMechPurposes =
delegator.findList("PartyContactMechPurpose",
+
EntityCondition.makeCondition(partyContactMechPurposeConds,
EntityOperator.AND), null, null, null, false);
+ } catch (GenericEntityException e) {
+ return ServiceUtil.returnError(e.getMessage());
+ }
+ if (partyContactMechPurposes.size() > 0) {
+ GenericValue address = partyContactMechPurposes.get(0);
+ GenericValue invoiceContactMech =
delegator.makeValue("InvoiceContactMech", UtilMisc.toMap(
+ "invoiceId", invoiceId,
+ "contactMechId", address.getString("contactMechId"),
+ "contactMechPurposeTypeId", "PAYMENT_LOCATION"));
+ toStore.add(invoiceContactMech);
+ }
+ // create the item records
+ for (Map commissionMap : commList) {
+ BigDecimal elemAmount =
((BigDecimal)commissionMap.get("commission")).multiply(appliedFraction);
+ BigDecimal quantity =
(BigDecimal)commissionMap.get("quantity");
+ String invoiceIdFrom = (String)commissionMap.get("invoiceId");
+ String invoiceItemSeqIdFrom =
(String)commissionMap.get("invoiceItemSeqId");
+ elemAmount = elemAmount.setScale(decimals, rounding);
+ Map resMap = null;
+ Map invoiceItemAssocResultMap = null;
+ try {
+ resMap = dispatcher.runSync("createInvoiceItem",
UtilMisc.toMap(
"invoiceId", invoiceId,
- "productId", elem.get("productId"),
+ "productId", commissionMap.get("productId"),
"invoiceItemTypeId", "COMM_INV_ITEM",
"quantity",quantity,
"amount", elemAmount,
"userLogin", userLogin));
- if (ServiceUtil.isError(resMap)) {
- return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionErrorItem",locale),
null, null, resMap);
- }
+ invoiceItemAssocResultMap =
dispatcher.runSync("createInvoiceItemAssoc", UtilMisc.toMap(
+ "invoiceIdFrom", invoiceIdFrom,
+ "invoiceItemSeqIdFrom", invoiceItemSeqIdFrom,
+ "invoiceIdTo", invoiceId,
+ "invoiceItemSeqIdTo",
resMap.get("invoiceItemSeqId"),
+ "invoiceItemAssocTypeId", "COMMISSION_INVOICE",
+ "partyIdFrom", partyIdBillFrom,
+ "partyIdTo", partyIdBillTo,
+ "quantity", quantity,
+ "amount", elemAmount,
+ "userLogin", userLogin));
+ } catch (GenericServiceException e) {
+ return ServiceUtil.returnError(e.getMessage());
}
- // store value objects
+ GenericValue invoiceItemAssoc = null;
+ if (ServiceUtil.isError(resMap)) {
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingInvoiceCommissionErrorItem",locale),
null, null, resMap);
+ }
+ }
+ // store value objects
+ try {
delegator.storeAll(toStore);
- invoicesCreated.add(invoiceId);
+ } catch (GenericEntityException e) {
+ String errMsg =
UtilProperties.getMessage(resource,"AccountingInvoiceCommissionEntityDataProblem",UtilMisc.toMap("reason",e.toString()),locale);
+ Debug.logError(e, errMsg, module);
+ return ServiceUtil.returnError(errMsg);
}
- Map resp = ServiceUtil.returnSuccess();
- resp.put("invoicesCreated", invoicesCreated);
- return resp;
- } catch (GenericEntityException e) {
- String errMsg =
UtilProperties.getMessage(resource,"AccountingInvoiceCommissionEntityDataProblem",UtilMisc.toMap("reason",e.toString()),locale);
- Debug.logError(e, errMsg, module);
- return ServiceUtil.returnError(errMsg);
- } catch (GenericServiceException e) {
- String errMsg =
UtilProperties.getMessage(resource,"AccountingInvoiceCommissionEntityDataProblem",UtilMisc.toMap("reason",e.toString()),locale);
- Debug.logError(e, errMsg, module);
- return ServiceUtil.returnError(errMsg);
+
invoicesCreated.add(UtilMisc.toMap("commissionInvoiceId",invoiceId,
"salesRepresentative ",partyIdBillFrom));
}
+ Map result = ServiceUtil.returnSuccess("Created Commission invoices
for each commission receiving parties " + invoicesCreated);
+ Debug.logInfo("Created Commission invoices for each commission
receiving parties " + invoicesCreated, module);
+ result.put("invoicesCreated", invoicesCreated);
+ return result;
}
public static Map readyInvoices(DispatchContext dctx, Map context) {
Added: ofbiz/trunk/applications/accounting/testdef/invoicetests.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/testdef/invoicetests.xml?rev=798854&view=auto
==============================================================================
--- ofbiz/trunk/applications/accounting/testdef/invoicetests.xml (added)
+++ ofbiz/trunk/applications/accounting/testdef/invoicetests.xml Wed Jul 29
10:54:02 2009
@@ -0,0 +1,27 @@
+<!--
+ 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.
+ -->
+
+<test-suite suite-name="accountingtests"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/test-suite.xsd">
+ <!-- Test case for Commission Run -->
+ <test-case case-name="auto-tests-CommissionRun">
+ <simple-method-test
location="component://accounting/script/org/ofbiz/accounting/test/AutoInvoiceTests.xml"
name="testCommissionRun"/>
+ </test-case>
+</test-suite>
Propchange: ofbiz/trunk/applications/accounting/testdef/invoicetests.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/applications/accounting/testdef/invoicetests.xml
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/applications/accounting/testdef/invoicetests.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml
Modified: ofbiz/trunk/applications/accounting/webapp/ap/WEB-INF/controller.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/webapp/ap/WEB-INF/controller.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/webapp/ap/WEB-INF/controller.xml
(original)
+++ ofbiz/trunk/applications/accounting/webapp/ap/WEB-INF/controller.xml Wed
Jul 29 10:54:02 2009
@@ -54,6 +54,11 @@
<response name="success" type="request" value="PaymentGroupOverview"/>
<response name="error" type="view" value="FindPurchaseInvoices"/>
</request-map>
+ <request-map uri="processCommissionRun">
+ <security https="true" auth="true"/>
+ <event type="service" invoke="createCommissionInvoices"/>
+ <response name="success" type="view" value="CommissionRun"/>
+ </request-map>
<!-- ================ Vendor requests ================ -->
<request-map uri="findVendors">
@@ -89,4 +94,4 @@
<!-- Vendor Mappings -->
<view-map name="FindVendors" type="screen"
page="component://accounting/widget/ap/CommonScreens.xml#FindVendors"/>
<view-map name="EditVendor" type="screen"
page="component://accounting/widget/ap/CommonScreens.xml#EditVendor"/>
-</site-conf>
\ No newline at end of file
+</site-conf>
Modified:
ofbiz/trunk/applications/accounting/webapp/ap/invoices/CommissionRun.ftl
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/webapp/ap/invoices/CommissionRun.ftl?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/webapp/ap/invoices/CommissionRun.ftl
(original)
+++ ofbiz/trunk/applications/accounting/webapp/ap/invoices/CommissionRun.ftl
Wed Jul 29 10:54:02 2009
@@ -29,31 +29,49 @@
}
}
}
+function setServiceName(selection) {
+ document.listSalesInvoices.action =
'<@ofbizUrl>'+selection.value+'</@ofbizUrl>';
+}
+function runAction() {
+ var form = document.listSalesInvoices;
+ var invoices = form.elements.length;
+ for (var i = 0; i < invoices; i++) {
+ var element = form.elements[i];
+ if (element.name == "invoiceIds") {
+ element.disabled = false;
+ }
+ }
+ form.submit();
+}
-->
</script>
<#if invoices?has_content >
- <form name="listSalesInvoices" id="listSalesInvoices">
+ <form name="listSalesInvoices" id="listSalesInvoices" method="post">
+ <#if parties?has_content>
+ <input type="hidden" name="partyIds" value="${parties?if_exists}"/>
+ </#if>
<div align="right">
- <select name="serviceName" id="serviceName">
+ <select name="serviceName" id="serviceName"
onchange="javascript:setServiceName(this);">
<option value=""/>
- <option
value="commissionRun">${uiLabelMap.AccountingCommissionRun}</option>
+ <option
value="processCommissionRun">${uiLabelMap.AccountingCommissionRun}</option>
</select>
- <a href="#" id="runAction"
class="buttontext">${uiLabelMap.OrderRunAction}</a>
+ <a href="javascript:runAction();" id="runAction"
class="buttontext">${uiLabelMap.OrderRunAction}</a>
</div>
<table class="basic-table hover-bar" cellspacing="0">
<#-- Header Begins -->
<tr class="header-row-2">
- <td width="8%"><input type="checkbox" id="checkAllInvoices"
name="checkAllInvoices" onchange="javascript:toggleInvoiceId(this);"/>
${uiLabelMap.CommonSelectAll}</td>
+ <td width="10%"><input type="checkbox" id="checkAllInvoices"
name="checkAllInvoices" onchange="javascript:toggleInvoiceId(this);"/>
${uiLabelMap.CommonSelectAll}</td>
<td width="10%">${uiLabelMap.FormFieldTitle_invoiceId}</td>
- <td width="15%">${uiLabelMap.AccountingVendorParty}</td>
- <td width="10%">${uiLabelMap.CommonStatus}</td>
+ <td width="10%">${uiLabelMap.AccountingVendorParty}</td>
+ <td width="8%">${uiLabelMap.CommonStatus}</td>
<td width="10%">${uiLabelMap.AccountingReferenceNumber}</td>
+ <td width="15%">${uiLabelMap.CommonDescription}</td>
<td width="10%">${uiLabelMap.AccountingInvoiceDate}</td>
- <td width="10%">${uiLabelMap.AccountingDueDate}</td>
- <td width="9%">${uiLabelMap.AccountingAmount}</td>
- <td width="9%">${uiLabelMap.FormFieldTitle_paidAmount}</td>
- <td width="9%">${uiLabelMap.FormFieldTitle_outstandingAmount}</td>
+ <td width="8%">${uiLabelMap.AccountingDueDate}</td>
+ <td width="8%">${uiLabelMap.AccountingAmount}</td>
+ <td width="8%">${uiLabelMap.FormFieldTitle_paidAmount}</td>
+ <td width="8%">${uiLabelMap.FormFieldTitle_outstandingAmount}</td>
</tr>
<#-- Header Ends-->
<#assign alt_row = false>
@@ -67,6 +85,7 @@
<td>${Static["org.ofbiz.party.party.PartyHelper"].getPartyName(delegator,
invoice.partyIdFrom, false)?if_exists}</td>
<td>${statusItem.get("description")?if_exists}</td>
<td>${invoice.get("referenceNumber")?if_exists}</td>
+ <td>${invoice.get("description")?if_exists}</td>
<td>${invoice.get("invoiceDate")?if_exists}</td>
<td>${invoice.get("dueDate")?if_exists}</td>
<td><@ofbizCurrency amount=invoicePaymentInfo.amount
isoCode=defaultOrganizationPartyCurrencyUomId/></td>
Modified: ofbiz/trunk/applications/accounting/widget/ap/InvoiceScreens.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/widget/ap/InvoiceScreens.xml?rev=798854&r1=798853&r2=798854&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/widget/ap/InvoiceScreens.xml (original)
+++ ofbiz/trunk/applications/accounting/widget/ap/InvoiceScreens.xml Wed Jul 29
10:54:02 2009
@@ -157,6 +157,7 @@
<actions>
<set field="titleProperty"
value="AccountingFindSalesInvoicesForCommissionRun"/>
<set field="tabButtonItem" value="commissionRun"/>
+ <set field="parties" type="List"
from-field="parameters.partyIds"/>
<script
location="component://accounting/webapp/ap/WEB-INF/actions/invoices/CommissionRun.groovy"/>
<set field="parameters.partyIds" value=""/>
</actions>