I did some changes for what I described earlier and I think this would
be the correct way to generate invoice for shipment. Changes are
copied below for reference.
Vikas
Index: applications/product/src/org/ofbiz/shipment/verify/
VerifyPickSession.java
===================================================================
--- applications/product/src/org/ofbiz/shipment/verify/
VerifyPickSession.java (revision 793812)
+++ applications/product/src/org/ofbiz/shipment/verify/
VerifyPickSession.java (working copy)
@@ -303,12 +303,10 @@
// check reserved quantity, it should be equal to verified
quantity
this.checkReservedQty(orderId, locale);
String shipmentId =
this.createShipment((this.getPickRows(orderId)).get(0));
+
this.issueItemsToShipment(shipmentId, locale);
- invoiceId = this.createInvoice(orderId);
- for (VerifyPickSessionRow line: this.getPickRows(orderId)) {
- invoiceItemSeqId = this.createInvoiceItem(line,
invoiceId, shipmentId);
- line.setInvoiceItemSeqId(invoiceItemSeqId);
- }
+ Map context = UtilMisc.toMap("shipmentId", shipmentId,
"userLogin", this.getUserLogin());
+ this.getDispatcher().runSync("createInvoicesFromShipment",
context);
return shipmentId;
}
@@ -419,45 +417,4 @@
String shipmentId = (String) newShipResp.get("shipmentId");
return shipmentId;
}
-
- protected String createInvoice(String orderId) throws
GeneralException {
- GenericDelegator delegator = this.getDelegator();
- Map createInvoiceContext = FastMap.newInstance();
- GenericValue orderHeader = delegator.findOne("OrderHeader",
UtilMisc.toMap("orderId", orderId), false);
- GenericValue billingAccount =
orderHeader.getRelatedOne("BillingAccount");
- String billingAccountId = billingAccount != null ?
billingAccount.getString("billingAccountId") : null;
- createInvoiceContext.put("partyId",
(EntityUtil.getFirst(delegator.findByAnd("OrderRole",
UtilMisc.toMap("orderId", orderId, "roleTypeId",
"BILL_TO_CUSTOMER")))).getString("partyId"));
- createInvoiceContext.put("partyIdFrom",
(EntityUtil.getFirst(delegator.findByAnd("OrderRole",
UtilMisc.toMap("orderId", orderId, "roleTypeId",
"BILL_FROM_VENDOR")))).getString("partyId"));
- createInvoiceContext.put("billingAccountId", billingAccountId);
- createInvoiceContext.put("invoiceTypeId", "SALES_INVOICE");
- createInvoiceContext.put("statusId", "INVOICE_IN_PROCESS");
- createInvoiceContext.put("currencyUomId",
orderHeader.getString("currencyUom"));
- createInvoiceContext.put("userLogin", this.getUserLogin());
- Map createInvoiceResult =
this.getDispatcher().runSync("createInvoice", createInvoiceContext);
- if (ServiceUtil.isError(createInvoiceResult)) {
- throw new
GeneralException(ServiceUtil.getErrorMessage(createInvoiceResult));
- }
- String invoiceId = (String)
createInvoiceResult.get("invoiceId");
- return invoiceId;
- }
-
- protected String createInvoiceItem(VerifyPickSessionRow line,
String invoiceId, String shipmentId) throws GeneralException {
- Map createInvoiceItemContext = FastMap.newInstance();
- createInvoiceItemContext.put("invoiceId", invoiceId);
- createInvoiceItemContext.put("orderId", line.getOrderId());
- createInvoiceItemContext.put("invoiceItemTypeId",
"INV_FPROD_ITEM");
- createInvoiceItemContext.put("productId", line.getProductId());
- createInvoiceItemContext.put("quantity",
line.getReadyToVerifyQty());
- createInvoiceItemContext.put("userLogin", this.getUserLogin());
- Map createInvoiceItemResult =
this.getDispatcher().runSync("createInvoiceItem",
createInvoiceItemContext);
- if (ServiceUtil.isError(createInvoiceItemResult)) {
- throw new
GeneralException(ServiceUtil.getErrorMessage(createInvoiceItemResult));
- }
- String invoiceItemSeqId = (String)
createInvoiceItemResult.get("invoiceItemSeqId");
- GenericValue shipmentItemBilling =
this.getDelegator().makeValue("ShipmentItemBilling",
UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId",
invoiceItemSeqId));
- shipmentItemBilling.put("shipmentId", shipmentId);
- shipmentItemBilling.put("shipmentItemSeqId",
line.getShipmentItemSeqId());
- shipmentItemBilling.create();
- return invoiceItemSeqId;
- }
}
\ No newline at end of file
On Jul 15, 2009, at 4:05 PM, Vikas Mayur wrote:
Hi,
I have introduced a feature called Verify Pick in Facility component
few months back based on a requirement. I was reviewing the code
more closely and found some issues.
The pre-condition to run this process is that order is in approved
status.
Steps to do Verify Pick are:
1) Create a Sales Order without split shipment option. Order should
be in approved status.
2) Go to Facility and select the WebStoreWarehouse facility.
3) Lets first check whether the order is ready to pick or need stock
move. To do this go to Picking tab.
4) If the order is ready to pick then click on Verify Pick tab.
5) Enter the order Id and click Verify Order. This will show the
list of the items that need to be verified, by default all of the
items are selected.
6) Click on Verify Items.
7) This will display the summary in another list at the bottom. User
have the option to either cancel or complete the verify order process.
8) Click on Complete button to verify the order.
If step 8 is a success then it will create a shipment in Picked
status and as well as generate an invoice with In-Process status.
The existing code was working fine but not implemented correctly as
it end up creating just an Invoice and Invoice Items at max but
there are certain other processes (entities where data is stored as
well) when an invoice is created as implemented in
createInvoiceForOrder service in InvoiceService class.
There is also an eca on updateShipment service which look for
shipment in PACKED status and then create the invoice. The service
triggered on eca is createInvoicesFromShipment. This service then
finally call createInvoiceForOrder and which create Invoice with In-
Process status, Invoice Items as well few other things as well.
Depending on the ProductStore.autoApproveInvoice flag, the status of
invoice is changed to INVOICE_READY and finally payment is captured
by capturePaymentsByInvoice triggered on eca rule defined on
createInvoiceForOrder. Finally, the invoice goes to PAID status,
Payments are captured and applied.
Coming back to my question a little bit, in the Verify Order step 8,
I do not want to capture payment and which is logical because
Invoice status is In-Process status.
My question is why payment is captured when the invoice status is In-
Process? Shouldn't the system look for Invoice Ready status to
capture the payments.
If what I said above is true, I could use the existing artifacts and
do some changes so that system validate against the invoice status
before doing a capture.
Any suggestions are most welcome and appreciated.
Thanks,
Vikas