Back

What is the Sales scope?

The Sales scope is where your team captures every customer commitment, from the first price quote to the final signed order. It keeps your pricing consistent, your promotions running on schedule, and every salesperson looking at the same live pipeline.

Use it to send quotations, confirm orders, lock in long-term contracts with blanket agreements, and watch how your sales are tracking against targets β€” all without leaving HMX.

How a sale moves through the system

Quotation
Sent to Customer
Sales Order
Delivery & Invoice
Done

A quotation is just a price offer. It only becomes a Sales Order β€” and a real commitment β€” the moment the customer agrees and you confirm it.

What you can do in Sales

πŸ“

Quotations & Orders

Draft a price offer, send it to the customer, and confirm it as a Sales Order once they agree.

πŸ“…

Blanket Orders

Lock in a yearly contract with a customer β€” release individual orders against it as they need stock.

πŸ’²

Pricelists

Different prices for different customers, regions, or date windows β€” managed centrally.

🎁

Promotions

Time-limited discounts or bundled offers, applied automatically when rules match.

πŸ“ˆ

Sales Analytics

See how sales are performing by customer, product, or rep β€” powered by HMX's OLAP engine.

Before you begin

Make sure these are in place β€” the Sales scope depends on them:

  • Your customers exist in the Partners module (at least one).
  • Your products or services are set up with selling prices.
  • Your company's currency and tax settings are configured.
  • The user creating orders has the Sales role assigned.

Your first sale β€” step by step

Step 1: Define at least one Order Type

Order Types let you separate regular orders from special ones (samples, consignment, service-only, etc.). You need at least one before you can confirm any sales order.

Sales β†’ Configuration β†’ Order Types β†’ New
New Order Type
Standard Sale
STD
β˜‘ Yes
A simple "Standard Sale" type is enough to begin β€” add more later for sample orders, consignment, etc.

Step 2: Set up a default Pricelist

Even if you only sell in one currency with no discounts, every order needs a pricelist attached. Create one called "Public" to start.

Sales β†’ Configuration β†’ Pricelists β†’ New
New Pricelist
Public
USD
Product Price
"Base on Product Price" means the pricelist uses whatever price is set on the product itself β€” no adjustments yet.

Step 3: Create your first quotation

Open the Sales Orders screen and click New. Pick a customer, an order type, and the pricelist you just made. Add a product line and save as a draft quotation.

Sales β†’ Orders β†’ Sales Orders β†’ New
New Quotation β€” Draft
ACME Corp
Standard Sale
Public
1Γ— Widget @ 100.00
The order stays in Draft until you click Confirm β€” customers can't see it yet.

Step 4: (Optional) Set a credit limit for the customer

If you sell on credit, open the customer record and set a limit. HMX will warn you before confirming orders that push the customer past it.

Partners β†’ Customers β†’ [select] β†’ Accounting tab
ACME Corp β€” Accounting
50,000.00 USD
12,340.00 USD
β˜‘ Yes
When "Block when exceeded" is on, orders above the limit require a manager override to confirm.

What is a quotation?

A quotation is a formal price offer you send to a customer, listing the products or services they asked about, the quantities, the unit price, and any taxes or discounts. It has a validity date β€” after that date, the offer expires.

The customer can accept, ask for changes, or walk away. Nothing is booked in your books until you confirm the quotation and it becomes a Sales Order.

How to create and send a quotation

Step 1: Open the Sales Orders list

Quotations and confirmed orders live in the same list, separated by status. Click New to start a fresh quotation.

Sales β†’ Orders β†’ Sales Orders
Sales Orders
ReferenceCustomerDateStatusTotal
SO00123ACME Corp2026-04-18Draft1,250.00
SO00122Globex Ltd2026-04-17Sent3,420.00
SO00121Initech2026-04-15Confirmed8,900.00
Draft = not yet sent. Sent = customer has received it. Confirmed = now a real Sales Order.

Step 2: Pick customer and order type

Choose which customer you're quoting to, and which Order Type applies. The order type controls downstream rules like delivery method and approval workflow.

[New] β†’ Customer field + Order Type field
New Quotation
ACME Corp
Standard Sale
Jane Doe
The salesperson defaults to you, but you can reassign before sending.

Step 3: Set dates and pricelist

Enter the quotation date, a validity date (how long the offer stays open), and confirm the pricelist. The pricelist decides which unit prices appear when you add lines.

Order Date, Expiration, Pricelist fields
Dates & Pricing
2026-04-21
2026-05-05
Enterprise Tier
If the customer doesn't accept by the expiration date, the quotation auto-expires.

Step 4: Add product lines

Add each item the customer is buying, with quantity. The unit price fills in from the pricelist, and you can override it or apply a line-level discount.

Order Lines tab β†’ Add line
Order Lines
ProductQtyUnit PriceDisc %Subtotal
Widget Pro10100.005950.00
Install Service1300.000300.00
Discounts entered here are per-line, on top of any pricelist rules.

Step 5: Send to customer

Save the quotation, then click "Send". HMX generates a PDF and emails it to the customer contact. The status moves from Draft to Sent.

[Save] β†’ [Send by Email]
Send Quotation
purchasing@acme.com
Quotation SO00123 β€” ACME Corp
β˜‘ Yes
The email is logged on the quotation, so you always know when it was sent and to whom.

Step 6: Confirm the order

When the customer says yes, click "Confirm". The quotation becomes a Sales Order, a reference number is locked in, and downstream workflows (delivery, invoicing) can start.

[Confirm] button on the quotation
SO00123 β€” Confirmed
Sales Order
2026-04-22 09:14
Pending creation
Once confirmed, pricing and quantities are locked unless you use the official Revise flow.

What is a Sales Order?

A Sales Order is a confirmed quotation β€” a locked-in agreement to deliver specific products at specific prices. Once confirmed, the order drives deliveries and invoices, and its totals show up in your sales reports.

Order statuses

StatusWhat it meansWhat can change
DraftQuotation in progress, not sent.Anything.
SentQuotation emailed; waiting on the customer.Still editable β€” resend after changes.
Sales OrderCustomer accepted, order confirmed.Locked. Use Revise to change pricing or qty.
DoneFully delivered & invoiced.Read-only.
CancelledOrder pulled back before fulfilment.Archived β€” reference only.

How to revise a confirmed order

Step 1: Open the confirmed order

Find the Sales Order in the list. Its status should show "Sales Order" (green). You can't change lines directly β€” use Revise.

Sales β†’ Orders β†’ Sales Orders β†’ [open order]
SO00123 β€” Sales Order
ACME Corp
Sales Order
[Revise] [Cancel] [Print]
The Revise button replaces edit mode for confirmed orders.

Step 2: Click Revise β€” a new revision opens

HMX creates a copy of the order in Draft, with a revision tag (e.g. SO00123/R1). The original is preserved so you can always see the history.

[Revise] button
SO00123/R1 β€” Draft
SO00123 (locked)
R1
Draft
The revision number auto-increments each time the customer requests another change.

Step 3: Edit lines & resend

Adjust quantities, prices, or products. Save, then Send to push the revised PDF to the customer for approval.

Order Lines tab β†’ edit β†’ [Save] β†’ [Send]
Revised Lines
ProductOld QtyNew QtyΞ”
Widget Pro1012+2
Install Service11–
HMX highlights what changed so the customer sees the diff at a glance.

Step 4: Confirm the revision

Once the customer signs off, click Confirm. The revised order replaces the previous one as the active Sales Order, and downstream deliveries / invoices re-sync to it.

[Confirm] on the revised order
SO00123/R1 β€” Confirmed
Sales Order
SO00123 (R0)
Updated (+2 units)
Previously confirmed quantities that were already delivered stay delivered β€” only the unfulfilled portion updates.

What is a Blanket Order?

A Blanket Order is a framework contract: a customer agrees to buy, say, 10,000 units across the next 12 months at a fixed price. Instead of confirming one big delivery, you release smaller Sales Orders against the blanket whenever the customer calls for stock β€” and HMX tracks the remaining balance.

How to set up and use a Blanket Order

Step 1: Create the blanket agreement

Open the Blanket Orders screen and create a new agreement. Pick the customer, the total committed quantity, and the validity window.

Sales β†’ Agreements β†’ Blanket Orders β†’ New
New Blanket Order
ACME Corp
Widget Pro
10,000
2026-01-01 β†’ 2026-12-31
Pricing on the agreement applies to every release β€” the customer can't be upsold mid-contract.

Step 2: Raise a Sales Order against it

When the customer calls for a release, create a normal Sales Order and link it to the Blanket Order. Quantities are drawn from the remaining balance.

New Sales Order β†’ Source Agreement field
SO00200 β€” draft from BL00012
BL00012
500
9,500 / 10,000
HMX shows how much is left on the contract so you can't over-commit.

Step 3: Confirm β€” HMX validates against the contract

On Confirm, HMX checks the release quantity against the remaining blanket balance and validity dates. If you exceed the balance or the contract is expired, confirmation is blocked.

[Confirm] on the Sales Order
Validation
βœ“ 500 ≀ 9,500
βœ“ 2026-04-22 in range
Confirmed
If either check fails, HMX shows which rule was violated and blocks confirmation.

Step 4: Watch the remaining balance

Open the Blanket Order any time to see committed, released, and remaining quantities β€” plus every linked Sales Order on the "Releases" tab.

Blanket Order β†’ Releases tab
BL00012 β€” Releases
Sales OrderDateQtyStatus
SO002002026-04-22500Confirmed
SO002152026-05-10800Done
8,700 / 10,000
The Releases tab is your single source of truth for how much of the contract is still outstanding.

Why pricelists?

Most businesses don't sell at one fixed price. You might give Gold-tier customers 10% off, offer different prices in Europe vs. Asia, or run a quarterly promotion. Pricelists let you manage all of that in one place, then attach the right pricelist to each customer or order β€” prices flow in automatically.

How to set up a pricelist

Step 1: Open Pricelists and click New

Go to Sales β†’ Configuration β†’ Pricelists. You'll see every pricelist already on the system. Click New to begin.

Sales β†’ Configuration β†’ Pricelists β†’ New
Pricelists
NameCurrencyScopeValid
PublicUSDAll customersAlways
Gold TierUSDGold customersAlways
EU RetailEURRegion: EU2026-01-01 β†’
Typical setups have one "Public" pricelist plus 2–5 specialized ones.

Step 2: Name the pricelist and pick its scope

Give it a clear name. Decide who it applies to: all customers, a specific customer group, or a region. Scope decides which orders automatically pick this pricelist.

Name, Currency, Customer Group fields
New Pricelist β€” Header
Gold Tier 2026
USD
Gold
β˜‘ Yes
Setting the Customer Group means every Gold-tier customer gets this pricelist by default.

Step 3: Choose a base pricing method

Decide how prices are calculated: straight from the product's list price, from cost + markup, or from another pricelist with an adjustment. Most users pick "Product Price" and add discount rules on top.

Base Method field
Base Pricing
Product Price
βˆ’ 10 %
Nearest 0.01
A 10% global discount is a common "Gold tier" pattern β€” simpler than per-product rules.

Step 4: (Optional) Add per-product or per-category rules

Need a different discount on some products? Add rules on the Rules tab. Each rule can target a product, a category, or a quantity breakpoint.

Rules tab β†’ Add rule
Rules
Applies ToMin QtyRuleValue
Category: Software1% off15
Product: Widget Pro50Fixed price85.00
More specific rules win β€” a product-level rule beats a category rule automatically.

Step 5: Set validity dates and save

Leave dates blank for "always active", or set a start/end to limit the pricelist to a window (like a quarterly promo). Save, and the pricelist is live.

Valid From / Valid To fields β†’ [Save]
Validity
2026-04-01
2026-06-30
Active
After the end date, the pricelist auto-archives β€” any new orders fall back to the customer's default.

Promotions vs. Pricelists

Pricelists set long-term pricing for a segment (Gold tier, EU region). Promotions are short bursts β€” "Free shipping this weekend", "20% off first order", "Buy 2 get 1". A pricelist quietly adjusts every quote; a promotion fires only when its rules match and usually shows up as a named line on the order.

How to set up a promotion

Step 1: Open Promotions and click New

Each promotion is a record with rules, dates, and rewards. You can have many running at once.

Sales β†’ Marketing β†’ Promotions β†’ New
Promotions
NameWindowStatus
Spring Sale 20%Apr 1 β†’ Apr 30Active
Free Ship > 500AlwaysActive
Summer BOGOJul 1 β†’ Aug 31Scheduled
Status moves from Scheduled β†’ Active β†’ Expired based on the window.

Step 2: Name it and set the window

Give the promotion a name your team will recognise on a quote. Set the start and end dates β€” HMX will only apply the promo within that window.

Name, Start Date, End Date
New Promotion
Spring Sale 20%
2026-04-01
2026-04-30
The promo name appears on the customer-facing invoice, so keep it presentable.

Step 3: Decide who & what it targets

Limit the promo by customer segment (e.g. new customers only), by product category, or by minimum order value. Leave a field empty to mean "any".

Conditions tab
Conditions
Any
Category: Apparel
100.00 USD
Conditions are AND-combined β€” every active condition must match.

Step 4: Pick the reward type

What do customers get? Choose from: percentage off, fixed amount off, free shipping, free product (BOGO), or tiered discount. Each reward type has its own fields.

Rewards tab
Rewards
Percentage Off
20 %
Order Subtotal
"Applies To" decides whether the discount hits the whole order or specific lines.

Step 5: Activate and save

Flip the Active toggle and save. From the start date onward, any matching order will automatically show the discount β€” with the promo name on the order line.

Active toggle β†’ [Save]
Order β€” Promotion Applied
LineDescriptionAmount
12 Γ— Spring Jacket240.00
2Promo: Spring Sale 20%βˆ’48.00
The promo line is clearly labelled β€” customers see exactly what they saved.

What's different about Sales Analytics?

Transactional screens (orders, invoices) are great for day-to-day work but slow for big questions like "which salesperson sold the most widgets last quarter?". Sales Analytics uses HMX's OLAP engine β€” a fast, column-oriented copy of your sales data β€” so those questions return in seconds, even across years of records.

What reports come out of the box

πŸ†

Top Customers

Revenue by customer, ranked β€” with drilldown to their orders.

πŸ“¦

Product Performance

Units sold and revenue by product or category.

πŸ‘€

Rep Leaderboard

Which salesperson closed the most orders this period.

πŸ“…

Sales by Period

Daily, weekly, monthly and yearly trend lines β€” compare periods.

Sample: Top Customers report

Top Customers β€” Q1 2026
2026-01-01 β†’ 2026-03-31
RankCustomerOrdersRevenueShare
1ACME Corp42184,20018 %
2Globex Ltd28121,80012 %
3Initech1993,4509 %
4Umbrella Co2481,3008 %
5Soylent Corp1767,9007 %

Click any row to drill down into the customer's orders, products, and payment status β€” all computed live from HMX's OLAP cube.

How the analytics work under the hood

The sale_olap module syncs Sales Order data into a DuckDB-backed analytical store. Reports query that store, not the live transactional tables, so there's no production-database load. Sync is incremental and runs after every order confirmation.

Modules in the Sales scope

ModulePurpose
saleTop-level Sales app β€” exposes the entry models and API endpoints.
core_saleCore sales logic: Sales Order lifecycle, Order Type, Revise flow, credit limit hooks.
master_saleMaster data for the Sales scope: customer category extensions, partner-as-customer helpers.
sale_olapSync layer that feeds Sales records into the DuckDB OLAP store for analytics.

Key data models

ModelModuleRole
saleordercore_saleHeader of a Sales Order / Quotation. Owns status, customer, totals, validity.
saleorderlinecore_saleLine-level product, quantity, unit price, line discount.
saleordertypecore_saleOrder Type master β€” controls downstream rules (delivery, workflow).
salepricelistcore_salePricelist header β€” scope, currency, base method, validity.
basepartnercore_sale / master_saleCustomer record extensions (credit limit, tier, default pricelist).
salecustomercategorymaster_saleCustomer category master (Gold, Retail, Wholesale).

Sales Order state machine

FromActionTo
draftaction_sendsent
sentaction_confirmsale
draftaction_confirmsale
saleaction_revisedraft (new revision)
saleaction_donedone
anyaction_cancelcancel

Extension hooks

  • saleorder._onchange_partner_id β€” fills pricelist, payment terms, salesperson from the customer.
  • saleorder._check_credit_limit β€” pre-confirm guard; raises if partner.outstanding + order.total > partner.credit_limit.
  • saleorder._compute_totals β€” recomputes taxed/untaxed totals; override for custom rounding or levies.
  • saleorderline._onchange_product_id β€” pulls unit price from the active pricelist, default UoM, taxes.
  • salepricelist._get_price β€” the rules engine: override to inject custom pricing logic.

API endpoints

ModuleMethodPathPurpose
saleGET/Health + scope metadata.
saleGET/checkModule availability probe (used by deploy checks).

OLAP models (sale_olap)

The sale_olap module mirrors Sales Order data into DuckDB for analytics. The fact table carries confirmed-order lines; dimension tables join customer, product, period, and salesperson.

TableRole
fact_sale_lineOne row per confirmed order line β€” qty, revenue, discount, cost.
dim_customerCustomer attributes (name, category, region) at time of sync.
dim_productProduct attributes (name, category, cost).
dim_periodCalendar dimension β€” day, week, month, quarter, year keys.
dim_salespersonSalesperson / team attributes.