Data model for physical sales(POS)

Hi all! I was wondering if somebody else implemented a POS system in Moqui. More specifically I’m wondering if there is some data model available already for POS sales, something like a POSLine or similar.

Because when we talk about physical in store sales, the Invoice or OrderHeader don’t really apply so well since most of the time we don’t have any information about the customer, like the name or contact mechanisms.

Did somebody else implemented a POS system with Moqui, and if yes, did you do it with the standard data model in the udm, or did you customized and added new entities?

1 Like

This isn’t a full explanation of the model, but there has been pos stuff done with Moqui before.

Off the top of my head there is a terminalId on OrderHeader

        <field name="terminalId" type="text-short"><description>ID for the terminal, such as a POS system, where the order was recorded</description></field>

Yea, I just realized a bit after posting that we don’t actually need a separate POSLine, because a POS sale is basically an Order, so we can customize the OrderHeader and OrderLine for the POS specific case. I didn’t yet tested this approach, but probably I will use the following settings:

  • Register a simple in-store Sale as an Order with no customer(or placeholder customer like _NA_)
  • If shipment or Invoice is needed, then register the customer and shipment/billing as usual
  • The payment is the specific part. So I guess I should create some new payment methods for in-store cash, in-store credit card or cash on delivery and either add a terminalId to the payment or link the terminal to the terminalId from the OrderHeader(as it already has this field, as you mentioned above). I just hope I can receive a payment for an Order, instead of just for invoices…
  • Then at the end of the day I need the total cash per terminal, which I can get from the payments, since they are linked to the terminalId
  • Or instead of using a terminalId I could use the FinancialAccount??, as a terminal is similar to a BankAccount(as in it stores money, but inside the store, not inside the bank)… not sure about this one…

Note
As I was writting this I thought a bit more about where the terminalId should be stored, and I think it should be on the Payment, not OrderHeader, as the terminal is just the place where you store cash, and you receive cash through payments, not orders.
I’m thinking about my case, where we have 2 stores in the same city(one terminal per store), and we could register an order in any of the 2 stores, and then receive the payment(or multiple partial payments) for the order in any of the 2 stores(aka terminals), so I know how much cash we have in each terminal at a given time.

1 Like

To receive a payment for an order, you just set it to a sales order instead of a purchase order. That’s done by making the vendor of the OrderPart the internal organization.

I’d probably use a FinancialAccount associated to the terminalId, because then I wouldn’t have to write custom summary and transaction reports based on a custom data structure.

Because typically a POS System is a way to place a n order and a payment is downstream of that, I would consider that if you want to associate the terminalId with the payment, the payment is already associated with the OrderPart which is associated with the OrderHeader. So you could create a view entity for grabbing a OrderPartWithPayment based on a terminalId in the OrderHeader.

1 Like

Okay, I came back to this. So, the data model seems to miss some crucial fields for in store sales. Let’s forget about the terminalId for a moment. What I need to know for in store sales are 2 things: the products sold and the cash received.

For products sold everything seems ok. The order registers the products and the product store/facility where the inventory should be updated.

But for cash there are 2 problems. First, there is no facility id or store id on the payment, so for cash payments I don’t know in which store we received the payment. Note that the order might be created and shipped from store 1, but the payment received in store 2.

The second problem is that for in store sales we very rarely create invoices, and the payment application can only be applied to invoices, not orders. So for orders we have no way of knowing which are paid and which are unpaid.

IMO, you always need an invoice in exchange for a payment. Cash register tickets are a type of invoice, just smaller. :wink: The issue with the facility ID or store ID sounds good if we fix it, though.

Yea, I agree. Even in my country in accounting terms the cash register ticket is called a simplified invoice, because it’s both an invoice and a receipt(proof of payment). So I guess for cash payments I will just create an Invoice with a new invoiceTypeEnumId of type Simplified for example, and a payment of type cash connected to it.

Now for the store problem I think there are 3 solutions:

  1. Add a store or facility ID to the payment. Honestly I don’t think this is a good fix. First because you already have the to and fromPartyId, and you can just create a party for each store or facility and you know that those payments are made throught that store. Secondly, connecting the payment only to the store still leaves the problem of having only the total cash per store. There are cases, for example supermarkets, that have multiple cash drawers in each store and they might want to have the totals per each drawer, not only per store, so they can reconcile the physical cash with the cash in the ERP.
  2. Use overrideGlAccountId and create subaccounts for each cash drawer or store. This leaves the ability to map the accounts however you want. However I still don’t like this solution, because it’s tied to the accounting module, and I might not need the accounting module otherwise. For example in our country, the majority of companies outsource accounting posting to another specialized company.
  3. Use financial accounts for each cash drawer and connect it to payments. I like this solution the best so far, because it’s not dependent on the accounting module. And I guess a bank account is very similar to a cash drawer, so most of the implemented functionality in the financial account should work out of the box. And I can also make transfers from one financial account to another financial account, aka move money from the cash drawer to a bank account an vice versa. Or just use money directly from the financial account, without a payment, to decrease the cash in the drawer.
1 Like

Okay, I got quite confused about how payments actually work in Moqui and after about 2 days of investigation I got to the conclusion that FinancialAccounts are NOT good for tracking money. I believe with the current functionality FinancialAccounts are useful to track virtual money(such as credit store, gift cards…), but tracking real money would mean duplicating a transaction both in the Payment entity and FinancialAccount entity. So actually cash can be tracked with existing payment entity with some minor adjustments. I got the following data statements:

A POS sale is an OrderHeader with salesChannelEnumId = POS and Customer = NA and CarrierShipmentMethod.shipmentMethodEnumId = ShMthPickUp.

A POS cash payment is represented by an Invoice of type InvoiceSimplified(NEW) with an attached payment of type PtInvoicePayment and paymentInstrumentEnumId = PiCash OR PiCod and toPaymentMethodId is a PaymentMethod with paymentMethodTypeEnumId = PmtCash(NEW) and ownerPartyId = facility/store party id.

A POS card payment is represented by an Invoice of type InvoiceSimplified(NEW) with an attached payment of type PtInvoicePayment and paymentInstrumentEnumId = PiDebitCard and toPaymentMethodId is a PaymentMethod with paymentMethodTypeEnumId = PmtBankAccount and ownerPartyId = facility/store party id, and an attached BankAccount(subtype of PaymentMethod).

NOTE: we use BankAccount for pos card payments because the money goes directly to our BankAccount and we don’t store card details. The CreditCard payment method subtype with the type PmtCreditCard is only used for online card payments, where we need the card details.

In this way multiple payment methods can be created per store if you want to track different cash registers. And to get payments summary by bank account or stores(cash) use the PaymentSummary view entity, which needs to be enriched with toPaymentMethodId filter. The next step would be to find out how the payment gateway works and the configuration needed.

1 Like

IMO, I agree that FinancialAccounts are useful for tracking virtual money, like bank deposits. Real money is cash. I don’t want to add to the confusion, but if we think of banknotes (fiat money, cash) as the only money you have, along with gold, bitcoin, etc., then bank deposits are basically debt that the bank owes you. Just saying…

Yea, I agree. And with the current Moqui functionality the FinancialAccounts work pretty much like a debt. For example the gift card or customer credit is a debt you have to a customer, cause he gave you money and now you owe him. The bank deposits, like you said, is debt that the bank owes you. I saw in the code that there was actually a FinancialAccount type of BankAccount, but it was commented out, not sure why.

But still, I feel like there is some overlapping functionalty with the payments and payment methods in Moqui. For example, I request payment from a customer by creating an invoice. Then the customer pays the invoice so I need to record a Payment. Now if the payment is cash, that’s it. But if the payment is by credit card or a wire transfer, do I also record a FinancialAccountTransaction? Isn’t that a duplication? What if I need to move cash money to the bank account, I record both a Payment and a FinAcctTransaction?

In my opinion, for the BankAccount case the FinAccts just adds unnecesary complexity. It’s easier to store just a Payment with paymentInstrumentEnumId PiCash or PiWireTransfer and if you have multiple bank accounts or cash registers create a separate payment method for each and set it to the toPaymentMethodId field.

Just a suggestion, POS was built out pretty well in OFBiz so it might be worth comparing and using that as a model to enhance anything that might be missing in Moqui.