Hello Ashish,
Thanks for the great tip. I feel I'm getting closer to understanding the
logic.
A question please for an issue that I can't understand. Following your
example and until we reach service
'createAcctgTransForSalesShipmentIssuance' I don't understand how the
glAccountType is determined here.
Service 'getGlAccountFromAccountType' is handling a number of cases but I
think it's not determining the glAccountId for this specific case. Am I
correct? Is it determined in a later called service?
I'm including the transaction entries here.
Regards,
Emad
[
{
"ACCTG_TRANS_ID": "10000",
"ACCTG_TRANS_ENTRY_SEQ_ID": "00001",
"ACCTG_TRANS_ENTRY_TYPE_ID": "_NA_",
"DESCRIPTION": null,
"VOUCHER_REF": null,
"PARTY_ID": "DemoCustomer",
"ROLE_TYPE_ID": "BILL_TO_CUSTOMER",
"THEIR_PARTY_ID": null,
"PRODUCT_ID": "GZ-1000",
"THEIR_PRODUCT_ID": null,
"INVENTORY_ITEM_ID": "9026",
"GL_ACCOUNT_TYPE_ID": "INVENTORY_ACCOUNT",
"GL_ACCOUNT_ID": "140000",
"ORGANIZATION_PARTY_ID": "Company",
"AMOUNT": 4.80,
"CURRENCY_UOM_ID": "USD",
"ORIG_AMOUNT": 4.80,
"ORIG_CURRENCY_UOM_ID": "USD",
"DEBIT_CREDIT_FLAG": "C",
"DUE_DATE": null,
"GROUP_ID": null,
"TAX_ID": null,
"RECONCILE_STATUS_ID": "AES_NOT_RECONCILED",
"SETTLEMENT_TERM_ID": null,
"IS_SUMMARY": null,
"LAST_UPDATED_STAMP": "2022-06-19 12:55:05.220",
"LAST_UPDATED_TX_STAMP": "2022-06-19 12:55:03.257",
"CREATED_STAMP": "2022-06-19 12:55:05.220",
"CREATED_TX_STAMP": "2022-06-19 12:55:03.257"
},
{
"ACCTG_TRANS_ID": "10000",
"ACCTG_TRANS_ENTRY_SEQ_ID": "00002",
"ACCTG_TRANS_ENTRY_TYPE_ID": "_NA_",
"DESCRIPTION": null,
"VOUCHER_REF": null,
"PARTY_ID": "DemoCustomer",
"ROLE_TYPE_ID": "BILL_TO_CUSTOMER",
"THEIR_PARTY_ID": null,
"PRODUCT_ID": "GZ-1000",
"THEIR_PRODUCT_ID": null,
"INVENTORY_ITEM_ID": null,
"GL_ACCOUNT_TYPE_ID": "COGS_ACCOUNT",
"GL_ACCOUNT_ID": "500000",
"ORGANIZATION_PARTY_ID": "Company",
"AMOUNT": 4.80,
"CURRENCY_UOM_ID": "USD",
"ORIG_AMOUNT": 4.80,
"ORIG_CURRENCY_UOM_ID": "USD",
"DEBIT_CREDIT_FLAG": "D",
"DUE_DATE": null,
"GROUP_ID": null,
"TAX_ID": null,
"RECONCILE_STATUS_ID": "AES_NOT_RECONCILED",
"SETTLEMENT_TERM_ID": null,
"IS_SUMMARY": null,
"LAST_UPDATED_STAMP": "2022-06-19 12:55:05.267",
"LAST_UPDATED_TX_STAMP": "2022-06-19 12:55:03.257",
"CREATED_STAMP": "2022-06-19 12:55:05.267",
"CREATED_TX_STAMP": "2022-06-19 12:55:03.257"
}
]
On Mon, Oct 3, 2022 at 3:02 PM Ashish Vijaywargiya <
[email protected]> wrote:
> Hello Emad,
>
> I am not 100% sure what you are trying to achieve here. So I am providing
> the details based on presumptions that the below details might be helpful
> to you:
>
> 1) First of all, create a Sales Order in your system from the
> backend/ecommerce for a "DemoCustomer" party.
>
> 2) Then come to OrderView page, like this -
> https://localhost:8443/ordermgr/control/orderview?orderId=WSCO10010
>
> 3) Click on the "Quick Ship Entire Order". You will see this link in the
> mid right corner of the page.
>
> 4) Trace the request "quickShipOrder" controller request from the Order
> component.
>
> 5) This is how my console log looks like when I performed quickShipOrder
> operation:
>
> https://drive.google.com/file/d/15whseNPGGDUGs5xbIvl0aPtKon8DEF4r/view?usp=sharing
>
> 6) Here in the console log you can see the reference of
> "createInvoiceForOrder" as well.
>
> You need to trace the code and understand the overall flow.
>
> You will find that there are many triggers(EECA, SECA) written in OFBiz
> which get triggered based on some conditions.
>
> Hope this helps.
>
> --
> Kind Regards,
> Ashish Vijaywargiya
> Vice President of Operations
> *HotWax Systems*
> *Enterprise open source experts*
> http://www.hotwaxsystems.com
>
>
>
> On Mon, Oct 3, 2022 at 4:32 PM Emad Radwan <[email protected]> wrote:
>
> > Hello Ashish,
> >
> > As usual, your help is so much valuable and to the point. Two more things
> > please that will make it clearer for me.
> >
> > - In createInvoiceForOrder, I noticed that 'ServiceItems' that will be
> > converted to 'billItems' are based on order items that are linked to
> > products. Sorry for my ignorance but what are the other options here?
> >
> > - Part of my suffering with logic tracing is getting to know what
> services
> > are being called especially since they are not called from each other all
> > the time with the existence of events for example. I tried to depend on
> > 'Service Logs', however, I noticed that 'createInvoiceForOrder' was not
> > listed before 'createInvoiceForOrder' while I did find it in the normal
> > logs. For sure this is not the best way to trace code, so if you have a
> > piece of advice here I'd highly appreciate it.
> >
> > Best Regards,
> > Emad
> >
> > On Sat, Oct 1, 2022 at 4:48 PM Ashish Vijaywargiya <
> > [email protected]> wrote:
> >
> > > Hello Emad,
> > >
> > > We are simply getting "billItems"(List) value from the service context
> > map.
> > >
> > > Here is the service definition of createInvoiceForOrder(Please refer
> > file:
> > > services_invoice.xml):
> > >
> > > <service name="createInvoiceForOrder" engine="java"
> > > location="org.apache.ofbiz.accounting.invoice.InvoiceServices"
> > > invoke="createInvoiceForOrder">
> > > <description>
> > > Create an invoice from existing order
> > > orderId = The orderId to associate the invoice with
> > > billItems = List of ItemIssuance records to use for
> creating
> > > the invoice
> > > </description>
> > > <attribute name="orderId" type="String" mode="IN"
> > > optional="false"/>
> > > <attribute name="billItems" type="List" mode="IN"
> > > optional="false"/>
> > > <attribute name="eventDate" type="Timestamp" mode="IN"
> > > optional="true"/>
> > > <attribute name="invoiceId" type="String" mode="INOUT"
> > > optional="true"/>
> > > <attribute name="invoiceTypeId" type="String" mode="OUT"
> > > optional="true"/>
> > > </service>
> > >
> > > Now you can check from where this service is being called:
> > > One example from where "createInvoiceForOrder" is being called is from
> > > OrderServices.java(There can be other references as well)-
> > > Please refer following service implementation:
> > > public static Map<String, Object> invoiceServiceItems(
> > >
> > > And then read the code of this service and see the following code
> > snippet:
> > > // find any service items
> > > List<GenericValue> serviceItems = new LinkedList<>();
> > > if (UtilValidate.isNotEmpty(orderItems)) {
> > > for (GenericValue item : orderItems) {
> > > GenericValue product = null;
> > > try {
> > > product = item.getRelatedOne("Product", false);
> > > } catch (GenericEntityException e) {
> > > Debug.logError(e, "ERROR: Unable to get Product
> from
> > > OrderItem", module);
> > > }
> > > if (product != null) {
> > > // check for service goods
> > > if
> ("SERVICE".equals(product.get("productTypeId"))) {
> > > serviceItems.add(item);
> > > }
> > > }
> > > }
> > > }
> > >
> > > // now process the service items
> > > if (UtilValidate.isNotEmpty(serviceItems)) {
> > > // Make sure there is actually something needing invoicing
> > > because createInvoiceForOrder doesn't check
> > > List<GenericValue> billItems = new LinkedList<>();
> > > for (GenericValue item : serviceItems) {
> > > BigDecimal orderQuantity =
> > > OrderReadHelper.getOrderItemQuantity(item);
> > > BigDecimal invoiceQuantity =
> > > OrderReadHelper.getOrderItemInvoicedQuantity(item);
> > > BigDecimal outstandingQuantity =
> > > orderQuantity.subtract(invoiceQuantity);
> > > if (outstandingQuantity.compareTo(ZERO) > 0) {
> > > billItems.add(item);
> > > }
> > > }
> > > // do something tricky here: run as a different user that
> can
> > > actually create an invoice, post transaction, etc
> > > Map<String, Object> invoiceResult = null;
> > > try {
> > > GenericValue permUserLogin =
> > ServiceUtil.getUserLogin(dctx,
> > > context, "system");
> > > Map<String, Object> invoiceContext =
> > > UtilMisc.toMap("orderId", orderId, "billItems", billItems, "userLogin",
> > > permUserLogin);
> > > invoiceResult =
> > dispatcher.runSync("createInvoiceForOrder",
> > > invoiceContext);
> > > if (ServiceUtil.isError(invoiceResult)) {
> > > return
> > > ServiceUtil.returnError(ServiceUtil.getErrorMessage(invoiceResult));
> > > }
> > > } catch (GenericServiceException e) {
> > > Debug.logError(e, "ERROR: Unable to invoice service
> > items",
> > > module);
> > > return
> > > ServiceUtil.returnError(UtilProperties.getMessage(resource_error,
> > > "OrderProblemWithInvoiceCreationServiceItems",
> > > locale));
> > > }
> > >
> > >
> > > If you find it difficult to understand the control flow and learn how
> to
> > do
> > > application development in Apache OFBiz framework then you can refer to
> > the
> > > following document:
> > > https://cwiki.apache.org/confluence/x/1gsBCw
> > >
> > > Above document will help you to understand the following topics from
> > Apache
> > > OFBiz:
> > > - Control Flow
> > > - Form/Screen Widget
> > > - Events
> > > - Services
> > > - Groovy
> > > - FTL
> > >
> > > And many more things that we can't learn from a random exploration
> > > Please let me know if you need further help from my side.
> > >
> > > --
> > > Kind Regards,
> > > Ashish Vijaywargiya
> > > Vice President of Operations
> > > *HotWax Systems*
> > > *Enterprise open source experts*
> > > http://www.hotwaxsystems.com
> > >
> > >
> > >
> > > On Sat, Oct 1, 2022 at 6:22 PM Emad Radwan <[email protected]>
> > wrote:
> > >
> > > > Hello Ashish,
> > > >
> > > > One more thing please on the 'createInvoiceForOrder' service, how
> > > > 'billItems'
> > > > in line 163 are being retrieved and identified?
> > > >
> > > > Regards,
> > > > Emad
> > > >
> > > > On Thu, Sep 1, 2022 at 8:58 AM Ashish Vijaywargiya <
> > > > [email protected]> wrote:
> > > >
> > > > > Hello Emad,
> > > > >
> > > > > Please read the code of the service/method:
> > > > > File: InvoiceServices.java
> > > > >
> > > > >
> > > >
> > >
> >
> https://github.com/apache/ofbiz-framework/blob/trunk/applications/accounting/src/main/java/org/apache/ofbiz/accounting/invoice/InvoiceServices.java
> > > > > Method: createInvoiceForOrder
> > > > >
> > > > > See the line #461
> > > > > createInvoiceItemContext.put("invoiceItemTypeId",
> > > > > getInvoiceItemType(delegator,
> orderItem.getString("orderItemTypeId"),
> > > > > product == null ? null :
> > > > > product.getString("productTypeId"), invoiceType,
> "INV_FPROD_ITEM"));
> > > > >
> > > > > Then see the method present inside line # 1941:
> > > > > private static String getInvoiceItemType(Delegator delegator,
> String
> > > > key1,
> > > > > String key2, String invoiceTypeId, String defaultValue) {
> > > > > }
> > > > >
> > > > > Hopefully it's self explanatory, Please let me know if you need
> > > > > further assistance on this.
> > > > >
> > > > > --
> > > > > Kind Regards,
> > > > > Ashish Vijaywargiya
> > > > > Vice President of Operations
> > > > > *HotWax Systems*
> > > > > *Enterprise open source experts*
> > > > > http://www.hotwaxsystems.com
> > > > >
> > > > >
> > > > >
> > > > > On Wed, Aug 31, 2022 at 5:31 PM Emad Radwan <[email protected]
> >
> > > > wrote:
> > > > >
> > > > > > Hello Ashis,
> > > > > >
> > > > > > Many thanks for the usual help! One issue please that I don't
> > > > understand
> > > > > in
> > > > > > the data itself, I noticed that for products - finished good - an
> > > > > > invoice_item_type_id is 'INV_FPROD_ITEM' while order_item_type_id
> > is
> > > '
> > > > > > PRODUCT_ORDER_ITEM'
> > > > > > but the key for 'INV_FPROD_ITEM' is 'FINISHED_GOOD' however, so
> how
> > > the
> > > > > > mapping is happening? What am I missing here?
> > > > > >
> > > > > > For other mappings like adjustments, mappings looks fine.
> > > > > >
> > > > > > Please shed some light on this.
> > > > > >
> > > > > > Regards,
> > > > > > Emad
> > > > > >
> > > > > > On Wed, Aug 31, 2022 at 6:53 AM Ashish Vijaywargiya <
> > > > > > [email protected]> wrote:
> > > > > >
> > > > > > > Hello Emad,
> > > > > > >
> > > > > > > A very good question. Please refer to the records present
> inside
> > > > > > > InvoiceItemTypeMap entity:
> > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
> https://demo-stable.ofbiz.apache.org/webtools/control/FindGeneric?entityName=InvoiceItemTypeMap
> > > > > > >
> > > > > > > Hopefully it's self explanatory.
> > > > > > >
> > > > > > > --
> > > > > > > Kind Regards,
> > > > > > > Ashish Vijaywargiya
> > > > > > > Vice President of Operations
> > > > > > > *HotWax Systems*
> > > > > > > *Enterprise open source experts*
> > > > > > > http://www.hotwaxsystems.com
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On Wed, Aug 31, 2022 at 1:16 AM Emad Radwan <
> > [email protected]
> > > >
> > > > > > wrote:
> > > > > > >
> > > > > > > > Hello Community,
> > > > > > > >
> > > > > > > > Let me explain my query with this when I create an order with
> > > items
> > > > > and
> > > > > > > > possible adjustments, the auto-created invoice when the order
> > > gets
> > > > > > > > completed we get a list of invoice items that is almost a
> match
> > > > with
> > > > > > both
> > > > > > > > order items plus adjustments. My question what decides the
> > > > > > > > invoice_item_type for each invoice item?
> > > > > > > >
> > > > > > > > I understand that an invoice can be not only for order; e.g.
> > work
> > > > > > effort,
> > > > > > > > but I used order item vs invoice item as an example.
> > > > > > > >
> > > > > > > > Is it mapped somehow and is configurable, or pre-determined
> and
> > > > > > > hard-coded?
> > > > > > > >
> > > > > > > >
> > > > > > > > Regards,
> > > > > > > > Emad
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>