Sign in

    ot

    Read-only MoonBit client for the OrderTime inventory REST API: serial-number movement history, document-number search, latest Ship Doc and Customer Return lookups, and full-document detail lookups. Credentials are read from environment variables.

    ordertime
    inventory
    api-client
    Download zip
    Author
    Version
    0.5.0
    License
    Apache-2.0
    Last updated
    11 hours ago
    Downloads
    13

    #vilakku/ot

    A read-only MoonBit client for the OrderTime inventory REST API. It answers the everyday inventory questions:

    • What is the movement history of this serial number?
    • What was the latest Ship Doc for this serial number?
    • What was the latest Customer Return for this serial number?

    The client is read-only by design: it only queries. It never creates, updates, or deletes anything in OrderTime.

    #Install

    moon add vilakku/ot

    #Setup

    The client reads its OrderTime credentials from environment variables and sends them as request headers on every query:

    VariableSent as
    ORDERTIME_API_KEYapiKey header
    ORDERTIME_EMAILemail header
    ORDERTIME_PASSWORDpassword header

    Ask your OrderTime Master Admin for an API key. If a variable is missing, the client aborts with a message naming the variable instead of sending an empty credential.

    #Usage

    All query functions are async and raise on failure (see Errors).

    ///|
    async fn print_latest_ship_doc(serial : String) -> Unit {
    let client = @http.Client::Client("https://services.ordertime.com")
    try {
    match @ordertime_client.get_latest_ship_doc_for_sn(client, serial) {
    Some(tx) =>
    println("Latest ship doc \{tx.doc_no()} for item \{tx.item()}")
    None => println("No ship doc for this serial number")
    }
    } catch {
    err => println("OrderTime query failed: \{err}")
    }
    }

    The query functions:

    FunctionReturns
    get_transactions_for_snEvery recorded movement for a serial number
    get_transactions_for_sn_of_typeThe same, filtered server-side to one TranType
    get_transactions_by_doc_noEvery movement row for one document number
    get_latest_ship_doc_for_snThe most recent Ship Doc for a serial number, or None
    get_latest_customer_return_for_snThe most recent Customer Return for a serial number, or None

    Results are Transaction values. Transaction::common gives the shared fields (document number, item, date, counterparty, status) as a TransactionCommon; Transaction::tran_type gives the kind as a payload-free TranType tag.

    List results are summaries. When you need a transaction's full document (customer PO, tracking number, line items and the serial numbers filled on them), fetch it by document number:

    FunctionReturns
    get_ship_doc_detailsA full Ship Doc (ShipDocDetails)
    get_customer_return_detailsA full Customer Return (CustomerReturnDetails)

    Receiver and Transfer documents are not fetched; those transactions appear in a serial number's movement history through the list queries above, like any other movement.

    Each returns a details struct with a common field (DocumentCommon: document number, date, status, tracking number, memo, and line_items). A LineItem carries its bin and serial fills as units; DocumentCommon::serial_numbers() collects every serial number filled anywhere in the document.

    #Behavior worth knowing

    • "Latest" means the highest DocNo. OrderTime assigns document numbers in sequence, so the maximum is the most recently recorded transaction. The rule does not depend on the order rows come back in, and ties keep the earlier row. latest_transaction implements the rule and is public, so you can apply it to any list of transactions you already have.
    • Unmodeled transaction types are skipped. Rows whose TranType is not Receiver (2), Ship Doc (4), Transfer (5), or Customer Return (10) are logged and dropped while parsing.
    • The counterparty falls back to RelatedToEntityRef. Movement list rows carry no CustomerRef; the customer field reads CustomerRef when present and the related entity (customer, vendor, ...) otherwise.
    • Detail fields are not in list responses. Memo, internal notes, customer PO, and tracking numbers live on the full document only, so the matching fields on list results are always empty. The full-document lookups above return them populated.
    • The record cap is explicit, and hitting it is an error. Every list query asks for up to 1000 records (the endpoint maximum) instead of accepting the silent 100-record default. A response that comes back with 1000 rows may have more behind it, so the client raises OrderTimeQueryFailed::TooManyRecords rather than returning a truncated result that looks complete. A serial number normally has a handful of movements, so in practice this never fires; it exists so a truncated answer can never pass silently.
    • The API is slow. A single list call can take on the order of 20 seconds. Size any timeouts accordingly.

    #Errors

    The query functions raise instead of returning Result:

    • a non-200 response raises an error carrying the HTTP status code (the API uses 400 for a bad request, 403 when the API user's role lacks rights, and 409 when data validation fails);
    • a 200 response whose body is not valid JSON, or is valid JSON but not an array of rows, raises an error describing the problem;
    • a list response that returns the full 1000-record cap raises OrderTimeQueryFailed::TooManyRecords, because it may be truncated (see the record cap note above);
    • network failures raise the HTTP layer's own errors.

    All of these are suberrors of MoonBit's general Error type, so one try ... catch around a call handles every failure mode, as in the usage example above.

    #The payloads underneath

    Every query is a POST to https://services.ordertime.com/api/list with a { "Type": ..., "Filters": [...] } body. Type 1141 is the movement list; filters combine with AND, and TranType narrows the rows server-side before the client parses them.

    All transactions for a serial number:

    { "Type": 1141, "NumberOfRecords": 1000, "Filters": [ { "PropertyName": "LotOrSerialNo", "FilterValueArray": "EXAMPLESN00000000001" } ] }

    The latest lookups add a second filter, "TranType": "4" for the latest Ship Doc and "TranType": "10" for the latest Customer Return, then pick the highest DocNo among the returned rows. A document-number search swaps the serial filter for "DocNo": "12345" and returns that document's movement rows.

    #TranType reference

    ValueKindModeled by this client
    1Adjustmentno
    2Receiveryes
    3Work Orderno
    4Ship Docyes
    5Transferyes
    6Purchase Orderno
    7Sales Orderno
    8Vendor Returnno
    9Disassemblyno
    10Customer Returnyes
    13Quoteno

    #Not implemented yet

    • Inventory queries (record type 1110: stock levels, for example all units of a model in a location).
    • Write operations of any kind.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io