# Orders, stock, status and access: 4.16-4.22

Behaviour the specs don't define (simulator choices). Back to the [index](README.md).

Card Order (4.16):
- `orderRefNo` is 6 digits counting up from `000001`, like the sample's
  `016906`. `invoiceNo` is 16 digits: the order date as `YYMMDD` followed by
  the order number, so it's unique and shows when the order was placed.
- `quantity` must be a positive whole number of up to 10 digits (`INVQTY`).
- There's no list of branches, so `branchId` is accepted if it's a non-blank
  string of up to 8 characters (`INBRID` otherwise), or `null` / missing for
  the API user's branch, as in the sample.
- A `delivery` node, when sent, must have non-blank `name`, `address1`,
  `address2`, `city`, `state`, `country` and `postalCode` (`11` otherwise).
  Field lengths aren't checked; the sample's `postalCode` is 15 characters.
- Purchase Card and Card Replacement don't check `cardDesign`; only Card
  Order does.

Card Receipt (4.17):
- The spec says each card is dispatched with a pack reference number, and its
  samples use pack numbers shaped like proxy numbers (`000000012740`). So a
  pack number is the card's proxy number, and its card number is made from it
  as for new cards. Shorter pack numbers, like the receipt sample's `12786`,
  are padded to 12 digits.
- No response says which packs an order got, so the simulator accepts any
  range that fits: `toPackNo` − `fromPackNo` + 1 must equal `quantity`
  (`INVQTY`), and no pack may already be a card, in the inventory, or
  reported damaged (`INVFNO`). The real system would only accept the order's own packs.
- Pack numbers must be 1–12 digits and not zero (`INVFNO` / `INVTNO`);
  `toPackNo` before `fromPackNo` → `INVTNO`.
- An order can be receipted in parts until its `quantity` is used up by
  receipted packs and packs damaged on arrival (4.18). One receipt takes at
  most 1,000 cards (`INVQTY`), since each is kept in memory.
- An unknown `orderRefNo` → `17` ("No records found"); the spec has no code
  for it.
- Receipted cards don't keep the order's product or design: Purchase Card
  sets the product from its `loadDetails`, as for seed inventory cards.

Update Stock Details (4.18):
- The spec says to use this for damage found on delivery and to update the
  inventory, so both cases are handled: damaged after receipt (the pack
  leaves the inventory) and on arrival (the pack is never receipted).
- Repeated pack numbers count once, so the sample (one pack sent twice with
  `quantity` `"1"`) succeeds. The number of distinct packs must equal
  `quantity` (`INVQTY`), at most 1,000 as in Card Receipt.
- `packNo` may be a list, as in the sample, or a single string. Pack numbers
  are padded to 12 digits like Card Receipt's; a malformed one or a missing
  `refNumbers` → `11`.
- A pack that's a card already sold, in the inventory for another order or
  the seed, or already damaged → `DATERR` ("Invalid Data"), the closest code
  in appendix 7.3. Damaging on arrival beyond what the order has left →
  `INVQTY`. An unknown `orderRefNo` → `17`.
- A damaged card can't be undamaged.

Get Stock Details (4.19):
- Every product in `:products` is listed, in product code order, even with
  no orders, as the sample lists a product with zeros. Products aren't
  mapped to branches.
- There's no list of branches, so any non-blank `branchId` gets an answer;
  one with no orders gets zeros. A missing or blank `branchId` → `INBRID`.
  Length isn't checked: the sample's `BRCORPID09880` is longer than the 8
  characters the table allows (Card Order does check it).
- A card counts for the product of the order it came from. A card is
  activated once it has been active, through Purchase Card with
  `cardActivationFlag` `Y` or Card Activation, even if it's locked or blocked
  since. Cards ordered but neither receipted nor damaged are only in
  `cardOrdered`.
- Seed inventory and cards created without a pack aren't counted.
- The response includes `cardDamaged` as the table says; the sample leaves it out.

Status Request (4.20):
- A request counts as received once it passes the header and body checks
  and its `txnRefNo` is recorded (steps 1–3 under "Every request"). One
  rejected before that, for a bad `apikey` or `msgHdr` for instance, →
  `TXNNRV`.
- A reused `txnRefNo` gets `TIDEXT`, but Status Request still reports the
  first request's result.
- A request that's received but not finished → `03` ("Unable to process the
  request"). The spec doesn't cover this; it only happens when the two
  requests overlap.
- The response is `txnRefNo`, `responseCode` and `responseText` only, as
  the sample shows. The original response's other fields aren't repeated.
- Only card API requests are covered, not the notification and onboarding
  calls. Results are lost on a restart or `/_sim/reset`.
- A failed original is reported with `:error_http_status`, like any other
  error.

Change Password (4.21):
- The request names no user, and the REST headers carry no password, so
  the password belongs to the API user in the `netid` header. Only Change
  Password checks that the `netid` is a configured user (`INVUSR`
  otherwise); other endpoints still accept any.
- The simulator compares hashes as sent. It can't check the 8–16 character
  rule, since the hash hides the length; any non-blank string is accepted as
  a hash (`11` otherwise). The sample's values aren't real hashes.
- `newPassword` must differ from the current password and the 12 before it
  (`PSTHIS`), so the sample, which sends the same value twice, fails.
- `PSDCNT` ("Password cannot be changed within seven days") isn't applied,
  so passwords can be changed repeatedly while testing.
- Passwords go back to the configured ones on a restart or `/_sim/reset`.

Access Rights (4.22):
- The REST spec has no way to create a web profile (Profile Creation is
  only in the SOAP spec), so profiles come from `:web_profiles` config,
  created outside the API as they would be through the web portal. Purchase
  Card doesn't create one.
- `userId` is matched exactly, case included. Length isn't checked: the
  sample's `CUSTOMER1` is longer than the 8 characters the table allows.
- `lastLogin` is returned as configured. The simulator has no logins, and
  the sample's format (`12-03-2024 09:40:12`) differs from the table's
  (`DD-MON-YYYY HH:MI:SS AM/PM`).
- `menuList` is one object for a single menu, as in the sample, and a list
  for several, as the table describes.
- An unknown or missing `userId` → `INVUSR` ("Invalid User").
