Skip to content

Sales Report By Document

sales-report-by-document is the query behind the Sales Report applet’s SR By Document screen — one row per sales document line, the level of detail the applet’s advance search filters down to before the grid renders it.

Path: POST /core2/tnt/dm/erp/reports/sales/sales-report-by-document/etl-ep Request body: SalesReportByItemCodeInputDto as JSON Response envelope: StreamingPagingResponse — see the family page

See Applet Reports API for authentication and the shared envelope shapes, and Data API for hosts and headers common to every etl-ep call.


Required target

A request that omits branch_guids, company_guids and location_guids entirely is rejected before the query runs, with a 400 and the message “Need to provide at least one target guid” — send at least one of the three.


Request fields

Defaults below are the DTO’s no-arg constructor; anything you omit takes that value. Optional fields default to empty (treated as no filter); Set fields default to empty (also no filter, except server_doc_type, which defaults to a non-empty set).

FieldTypeDefaultApplied by the applet’s advance search?
branch_guidsSet<UUID>emptyYes
company_guidsSet<UUID>emptyNo — the applet never sends this; it’s implied by which branches you pick
location_guidsSet<UUID>emptyNo — not on this screen’s search panel
date_from, date_toZonedDateTimenowYes — required in practice
keywordOptional<String>emptyYes — matches item code/name/description/scan code/alt codes/remarks
item_guidsSet<UUID>emptyNo
customer_guidsSet<UUID>emptyYes
customer_category_guidsSet<UUID>emptyYes
salesman_guidsSet<UUID>emptyYes — fed by the employee dropdown
shipping_recipient_entity_hdr_guidsSet<UUID>emptyYes
sales_lead_label_guidsSet<String>emptyYes
created_by_guidsSet<UUID>emptyNo
item_typeSet<String>emptyYes — BASIC_ITEM, GROUPED_ITEM, NSTI, BUNDLE, COUPON, SERVICE, WARRANTY, GL_CODE, DOC_HEADER_ADJUSTMENT, MEMBERSHIP, MADE_TO_ORDER, DIGITAL_GOODS
item_statusSet<String>emptyYes — ACTIVE, INACTIVE, DELETED
item_category1_guids … item_category20_guidsSet<String> eachemptyYes
server_doc_typeSet<String>INTERNAL_SALES_CASHBILL, INTERNAL_SALES_INVOICE, INTERNAL_SALES_ORDERNot directly — the applet never overrides this default, so leave it unset unless you specifically need a different document mix
server_doc_1Set<String>emptyYes — invoice/document number, exact match, one or more
pricing_scheme_hdr_guidOptional<UUID>emptyNo
doc_remarksOptional<String>emptyNo
report_periodDAILY / WEEKLY / MONTHLY enumDAILYNo — irrelevant to this endpoint, used by the daily/weekly/monthly summary endpoints on the same controller
group_by, optionalSet<String>emptyNo — used by other endpoints on this controller, not this one
timeZoneStringAsia/Kuala_LumpurNo
server_doc_type has a non-empty default. Unlike every other Set field on this DTO, omitting server_doc_type does not mean “no filter” — it means “cashbills, invoices and orders only,” because that’s what the no-arg constructor fills in. If you need sales returns, credit notes, or other document types the applet’s own default doesn’t show, you must send server_doc_type explicitly.

Company is implied by which branches you pick — don’t send company_guids unless you specifically want to filter branches out that way; the applet itself never does.


Cost basis: replicate the applet’s fallback yourself

The response carries every cost-type amount regardless of what the applet’s “Calculate Base On” dropdown shows, because that control is a client-side display choice, not something sent to the backend at all. To reproduce the number the applet displays as “Cost Amt” for a line, apply this fallback in your own frontend:

cost_amt = cost_ma_amount
  ?? (nonzero) cost_fifo_amount
  ?? (nonzero) cost_wa_amount
  ?? (nonzero) cost_replacement_amount

i.e. use cost_ma_amount if it is present and non-zero; otherwise fall through the list in that order. This was reverse-engineered from the applet’s own line-construction code and confirmed by matching totals against a live export — it is not documented anywhere in the backend.


Response fields

The response is one flat object per sales document line (not per document — a multi-line invoice produces multiple rows sharing the same server_doc_1). The query joins in the full item-category tree, pricing, and customer/salesman detail, so a single row carries well over a hundred fields; below are the ones you’re likely to actually need. Field names only — no data from the verification capture is reproduced here (see this page’s sources: map).

FieldNotes
line_guidUnique per line.
server_doc_1The BigLedger document number (what server_doc_1 in the request filters on).
date_txnTransaction date.
doc_ccyDocument currency.
typeItem type, one of the item_type values.
item_code, item_name, item_descr, fi_item_guidItem identity.
category1_code … category20_code, category1_name … category20_nameItem category tree, paired code/name per level. Levels a tenant does not use come back null.
branch_code, branch_guid, location_code, loc_guidWhere the sale happened.
customer_code, customer_name, customer_phoneCustomer identity — PII, handle accordingly.
salesman_code
qty_sold
amount_std, amount_discount, amount_net, amount_txnStandard sales amount fields — see the generic document for what each means on a document line generally.
cost_ma_amount, cost_fifo_amount, cost_wa_amount, cost_replacement_amount, cost_lifo_amountCost basis by method. See Cost basis above for which one the applet actually shows.
uomUnit of measure.
serial_no{"serialNumbers": [...]} when the item is serial-tracked.
pricing_scheme_code

Filter dropdowns

Populate the applet-equivalent filters from these. See Applet Reports API → dropdowns.

POST /core2/tnt/dm/erp/drop-down/company/etl-ep
POST /core2/tnt/dm/erp/drop-down/branch/etl-ep
POST /core2/tnt/dm/erp/drop-down/location/etl-ep
POST /core2/tnt/dm/erp/drop-down/customer/etl-ep
POST /core2/tnt/dm/erp/drop-down/employee/etl-ep

Body for each: {"keyword": "", "filters": {}, "limit": 50} (DropDownInputDto — keyword, filters, filterLogical, limit default 50, orderBy, order default "ASC"). Response: {"guid": "...", "code": "...", "name": "..."} per row, in the standard StreamingPagingResponse envelope.


Example

curl -X POST "https://api-etl.akaun.com/core2/tnt/dm/erp/reports/sales/sales-report-by-document/etl-ep" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "branch_guids": ["3f2a7c10-9b4e-4d61-8a22-1c5e7f9d0b33"],
    "date_from": "2026-08-01T00:00:00+08:00",
    "date_to": "2026-08-31T23:59:59+08:00",
    "item_status": ["ACTIVE"]
  }'

server_doc_type was left unset here, so the response is cashbills, invoices and orders only — send it explicitly to widen that.


Related

Last updated on