Hello Emad,
Please see the implementation of
"createAcctgTransForSalesShipmentIssuance", this service is simply doing
AccountingTransaction entries for Sales_Shipment.
Here glAccountTypeId is hard coded for credit and debit entries.
Few other services can be of our interest:
- getGlAccountFromAccountType(If you have glAccountId then glAccountTypeId
is present in the GlAccount entity)
The description in above service definition also provides the
necessary information:
<service name="getGlAccountFromAccountType" engine="simple"
location="component://accounting/minilang/ledger/GeneralLedgerServices.xml"
invoke="getGlAccountFromAccountType" auth="true">
<description>Look up a GlAccountId first in ProductGlAccount by
productId and productGlAccountTypeId, if not found,
then in organizationPartyId and glAccountTypeId </description>
<attribute name="organizationPartyId" type="String" mode="IN"
optional="false"/>
<attribute name="glAccountTypeId" type="String" mode="IN"
optional="true"/>
<attribute name="acctgTransTypeId" type="String" mode="IN"
optional="true"/>
<attribute name="debitCreditFlag" type="String" mode="IN"
optional="true"/>
<attribute name="partyId" type="String" mode="IN" optional="true"/>
<attribute name="roleTypeId" type="String" mode="IN"
optional="true"/>
<attribute name="productId" type="String" mode="IN"
optional="true"/>
<attribute name="paymentId" type="String" mode="IN"
optional="true"/>
<attribute name="invoiceId" type="String" mode="IN"
optional="true"/>
<attribute name="fixedAssetId" type="String" mode="IN"
optional="true"/>
<attribute name="glAccountId" type="String" mode="OUT"
optional="true"/>
</service>
- createAcctgTransForSalesInvoice
AcctgTrans and AcctgTransEntry are the two entities which keep the Credit
and Debit transaction entries.
Hope this helps.
--
Kind Regards,
Ashish Vijaywargiya
Vice President of Operations
*HotWax Systems*
*Enterprise open source experts*
http://www.hotwaxsystems.com
On Wed, Oct 5, 2022 at 9:08 PM Emad Radwan <[email protected]> wrote:
> 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
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>