Domain model

The domain model of the ERP-API consists of the core object types Product, Invoice and CreditMemo. Other objects such as Customer and Staff are part of different APIs. In essence, Staff sells Products to Customers and each sale is recorded as an Invoice. Voids or sales returns are recorded as CreditMemo.

Product

A Product represents an item that is being sold by the business.

Each product has a name and various identifiers. The id is the technical identifier by which the enfore platform addresses the product. The external_id is an identifier that can be set via the ERP-API and that allows integrators to address the product directly without the need for a lookup. The article_id is the identifier by which the business communicates with the customer (aside from he product's name), it is shown on invoice documents, for example. Further identifiers can be stored as part of the product_identifiers structure, for example EAN and GTIN numbers.

Each product must have a management_unit. This unit, combined with the numeric value one, defines the minimum quantity of the product that can be addressed. For example, a product using MASS_KILOGRAMS as management unit can only be addressed in integer multiples of 1kg. It would not be possible to have a sale, purchase or stock change of 1.5kg or 500g of the product.

As products are to be sold, they also need a sales_quantity and a sales_price. The sales_quantity specifies the default quantity for a sale and the sales_price specifies the price for that default quantity of the product. For example, given product with the sales quantity of 5kg and the sales price of 10€, a customer purchasing 20kg of said product would need to pay 40€. The flag sales_price_is_gross indicates whether the sales_price is a net amount (when sales_price_is_gross == false) or a gross amount (when sales_price_is_gross == true).

For computing VAT/sales tax, each product must define its tax_category. Additionally it may define a reason for it to be exempt from taxation via its tax_exemption_reason field.

Product relationships

NOTE: The ERP-API currently does not provide a way to declare or query product relationships. This functionality will be added in the future. But as the enforePOS client allows creation of such relationships, the ERP-API must be able to represent the resulting invoice item dependencies and for understandng those, the following documentation was added.

The enfore platform allows modelling of relationships between products. Different types of relationships exist, and they influence the behavior of the platform in different ways.

A very simple form of product relationship is the "related product". When a product B is configured as a "related product" to product A, the register UI will suggest a sale of product B whenever product A is placed into the basket.

The "related product" relationship allows specifying a quantity and price for the linked product that differ from its regular sales quantity and price. This enables easy cross-selling products at a discount.

Options and option groups

When a product is configurable for a specific sale, it is often convenient to not model all possible configurations as separate products but to model the "core product" and its "options". When options are mutually exclusive, they can be wrapped in an "option group". Selection from a group may then also be set to mandatory.

For example, a product "Flat White" represents a coffee that does contain milk but may provide the choice between regular and soy milk. This would ideally be modeled as three products "Flat White", "Regular Milk" and "Say Milk" with the "Flat White" product having an option group "Milk" that referenced the other two products as "options" and whose "selection is mandatory" flag would be set.

If the "Flat White" additionally allowed the choice of having chocolate sprinkles on top, a fourth product "Chocolate Sprinkles" could be defined and the "Flat White" would reference that as an "option".

An "option" always references a product and may have a quantity/price that overrride that products regular sales quantity/price. It also has a flag controlling whether the option can be selected multiple times.

An "option group" bundles multiple "options" under a user-defined label. It has flags that control whether selection from the group is mandatory or optional and whether multiple or only one option from the group can be choosen.

Deposits

Deposit relationships represent "bottle deposit" that the customer has to pay when purchasing an item. For example, a when selling a drink in a disposable bottle in Germany, the merchant is required to collect a deposit of 0.25€. The customer can get the deposit refunded when she returns the empty bottle to the merchant later.

This usually is modeled by defining two products. One for the drink and another one for the deposit. The drink product would then reference the deposit product via a "deposit" relationship.

Custom workflows

The enfore platform provides extension points where the regular behavior of the platform can be extended and/or overridden by custom logic. This feature is known as "custom workflows". The API allows setting the start URLs for the product-related custom workflows via the field custom_workflow_config.

For more information regading custom workflows, please see CUWO architecture and interfaces (internal link).

Invoice

An Invoice represents the financial result of a sale.

It consists of various context information such as the store where the sale took place (via store_id), what register was used (via register_id) and which staff member handled the sale (via operator_id). The date and time of the sale is recorded as transaction_date_and_time.

Each invoice has a sequence of items that hold information about the products that were sold. Each item specifies the product that was sold, the sold quantity, the net/gross amounts, and any applied taxes and item-level discounts.

An invoice also has sequences of discounts and payments. The former hold information about basket-level discounts and the latter hold information about the payments made by the customer.

Edge cases

While ERP-API is focussed on the "retail" vertical and tries to provide a domain-specific view on the business data, the enfore platform provides some advanced features that cannot easily be mapped to this domain-specific view.

Invoices resulting from split/merged orders

The enfore platform uses "order" objects to represent sales. In the retail vertical, an "order" can be seen as to be equivalent to the list of items shown on the cash register. An order itself does not represent a sale yet, as it can be still be changed and/or aborted. Usually, once the merchant and customer agree on the sale, the order is converted into an invoice.

Nevertheless, the enfore platform allows invoices to be created for only part of an order, for a combination of multiple orders, or for a combination of both. For example, in the "gastro" vertical, it is common to use "one order per table" as this allows dishes to be served together and easy hand-over between waiters on shift changes. When creating invoices, it then often happens that each person/couple at the table requests a separate invoice. Or that a larger group of people is split accross multiple tables but then requsts a single, combined invoice.

When an invoice does not represent a single, complete order anymore, some additional definitions are needed to reason about the fields in the ERP-API:

  • The values for store_id, register_id, transaction_date_and_time, and operator_id, are where, when and by whom the combined/split invoice was created.
  • The values for transaction_start and transaction_end are the earliest start/lastest end of all orders that have at least one item included in the invoice.
  • When combining/splitting orders, discounts may be recomputed. Whether discounts are computed on the invoice- or order-level depends on the sale process. For example, "gastro" orders may be merged and then discounts are recomputed based on the combined invoice. For "online" orders, there may be partial invoices caused by partial shipments but discounts are still computed based on the original order.

Late payments

The ERP-API allows clients to be notified about new invoices and when fetched, those invoices include information about the payment(s) made by the customer.

The enfore platform provides a feature called "pay later" where an invoice is created and booked but payment is deferred to a later point in time. In such cases, the ERP-API will send a notification about the new invoice, but when the invoice is fetched before the payment took place, the returned Invoice object will not include the payment information.

The ERP-API currently does not provide "payments" as a separate object type or notifications about "payments".

InvoiceItem

An InvoiceItem represents a single position in an invoice.

It references a product via its product_id and product_external_id. The quantity of product that was sold is recorded in the item's quantity field. The total amount of the item is available via gross_amount and net_amount.

Information about item-level discounts is available as discounts sequence and the undiscounted amounts of the item are stored in undiscounted_gross_amount and undiscounted_net_amount.

Information about taxes is available as taxes sequence. A sequence is used here as multiple taxes might be applied to a single item, for example US sales tax usually consists of a general state sales tax and local or city sales taxes. In those cases, a single InvoiceItem may have multiple TaxInformation elements.

Dependencies between items

An invoice item can depend on other invoice items. Dependencies on invoice items are caused by relations between products. For example, when a product A that has a related deposit product B, the invoice item for A will also have a dependant invoice item for B.

See the section about product relationships for more information.

CreditMemo

A CreditMemo represents the financial result of a sales void or sales return.

It is structurally almost equal to an Invoice with the exception that there are no discounts.

CreditMemoItem

A CreditMemoItem represents a single position in a credit memo.

It is structurally almost equal to an InvoiceItem with the exception that there are no discounts or item dependencies.

Customer

See the contacts API.

Staff

See the staff members & access rights API.