Appearance
TMS v2 — feature list
What TMS v2 can do today, what is only designed, and what was dropped on purpose. One table per area of the system. Screens and other UI features are left out; the backend side of an admin feature stays in.
Read this first
- Built = the code exists on
main-v2-prototype(commit 3d70475a) and an HTTP endpoint, Kafka consumer or worker reaches it. - Partly built = some of it is in the code, but the design asks for more, or the endpoint exists and does nothing yet.
- Designed = written in a module design, no code yet. "Parked" in the text means the design itself put it on hold.
- Cut = dropped on purpose; the reason is in the last column.
- Code paths are relative to
/Users/thanosorn/Works/Software/tms/wt-v2-prototype-core/. Design paths are relative to/Users/thanosorn/Works/Software/tms/agent-task/.work/tms-v2-discovery/and name the section heading to open. - DO = delivery order (one customer order to deliver). OMS = BigC's order system, which sends orders over Kafka. Task = one driver's trip with its ordered stops.
Summary
| area | Built | Partly built | Designed | Cut | total |
|---|---|---|---|---|---|
| Intake / DO | 4 | 4 | 9 | 1 | 18 |
| Planning | 4 | 4 | 9 | 3 | 20 |
| Execution | 0 | 2 | 24 | 2 | 28 |
| COD | 0 | 0 | 11 | 2 | 13 |
| Workforce | 1 | 1 | 15 | 2 | 19 |
| Master data | 5 | 2 | 7 | 3 | 17 |
| Admin / reporting | 3 | 2 | 3 | 3 | 11 |
| Platform | 14 | 3 | 7 | 4 | 28 |
| all | 31 | 18 | 85 | 20 | 154 |
The short picture: the platform base (jobs, Kafka in and out, history, settings, logs, files) is mostly built. DO intake and planning have a working prototype that does not yet follow the design's states and rules. Execution, COD and workforce are designed only. The driver app for v2 has not been started.
Intake / DO
How orders get into TMS and change before delivery.
| feature | status | what it does | where |
|---|---|---|---|
| DO create, read, update over REST | Built | Admin or another system creates a DO, lists it, reads it by DO number and updates it | src/delivery_order/delivery_order.controller.ts |
| DO lines (items) over REST | Built | List, read, create, update and delete the lines of a DO | src/delivery_order_item/delivery_order_item.controller.ts |
| DO number generation | Built | A new DO gets "DO" plus 8 running digits when no number is sent | src/delivery_order/delivery_order.service.ts (createDeliveryOrder) |
| Kafka order intake, each message applied once | Built | Messages on bigc.lastmiles.do-post create or update a DO; a repeated message id is a no-op; a message that keeps failing is dead-lettered | src/delivery_order/delivery_order.kafka_consumer.ts, src/kafka/kafka.consumer.ts |
| Enrich a new DO | Partly built | Built: copies the source store's name and location onto the DO. Designed: geocode a missing customer location through an address cache, sum weight and volume from the lines | code: delivery_order.service.ts (_resolveSourceStore); design: modules/intake/srs.md § "Enrich a new DO once" |
| History event for every DO change | Partly built | Built: create and update write one history row in the same transaction. Designed: status, cancel, hold, assign and redeliver rows, because those commands do not exist yet | code: delivery_order.service.ts; design: modules/intake/srs.md § "Record every DO change as an event" |
| Durable consume with retry | Partly built | Built: a failed message is retried and a crash redelivers it. Designed: pause the partition and back off 1 s to 60 s while MongoDB is down, alert on lag over 60 s | code: src/kafka/kafka.consumer.ts; design: modules/intake/srs.md § "Consume durably and replay without duplicates" |
| Accept only newer updates | Partly built | Built: the same message cannot be applied twice. Designed: an update older than the stored source version is skipped and logged as stale | design: modules/intake/srs.md § "Apply an update only when it is newer" |
| Route every message to one outcome | Designed | Each message is matched against a fixed rule list (create, update, cancel, redeliver, park) and the first match decides | modules/intake/srs.md § "Route every order message to one outcome" |
| Park orders with unknown store or channel, and replay | Designed | An order for a store or channel TMS does not know is kept with its raw payload and a reason, never dropped, and can be replayed. Today such a message fails and is dead-lettered | modules/intake/srs.md § "Park an order whose master data is unknown" |
| Cancel through one command | Designed | OMS, REST and the admin button cancel through the same checks; once the DO is on a task the cancel is refused and goes to ops | modules/intake/srs.md § "Cancel through one command" |
| Redelivery from OMS opens a new DO | Designed | A newer message for a cancelled or failed order creates a new DO linked to the old one | modules/intake/srs.md § "Open the next attempt when OMS redelivers" |
| Partial re-delivery by the admin | Designed | The admin re-sends missing items of a finished order as a new linked DO, choosing a quantity per item | modules/intake/srs.md § "Partial re-delivery opened by the admin" |
| Excel import of DOs | Designed | Each Excel row goes through the same create rules as Kafka and records its source | modules/intake/srs.md § "Create by hand and by Excel with the same rules" |
| Kafka-to-DO field mapping as checked data | Designed | The mapping is declarative rules from a fixed list of transforms, refused on save if invalid; nothing is evaluated as code | modules/intake/srs.md § "Refuse an invalid Kafka mapping on save" |
| Preview a mapping on a sample payload | Designed | The admin sees the DO a draft mapping would build from a real stored message before activating it | modules/intake/srs.md § "Preview a mapping against a sample payload" |
| Mapping versions and rollback | Designed | Every mapping save is a version; one is active; each DO records the version that built it | modules/intake/srs.md § "Version the mapping, roll it back" |
Run the Kafka mapping through eval (v1 way) | Cut | Running admin-typed code on every message had no check and no history; replaced by the declarative mapping above | modules/intake/design.md § "Rejected options" |
Planning
Turning one store's waiting orders into vehicle routes for one day, then into driver tasks.
| feature | status | what it does | where |
|---|---|---|---|
| Create a plan for a store and date | Built | Builds the plan's vehicle slots (shifts) from the store's plan template and the store's opening hours | src/plan/plan.service.ts (createPlan), POST /plan |
| Route optimisation with Google | Partly built | Built: sends the orders and vehicles to Google Route Optimization and saves routes and the unassigned list. Designed: run it as a background job that answers at once and checks the plan revision | code: src/plan/plan_optimize.service.ts, POST /plan/:code/re_plan; design: modules/planning/srs.md § "Route optimisation runs as a job" |
| Move, assign and unassign a stop by hand | Built | The admin moves a stop between routes, adds an unassigned order to a route or takes one out; changed routes are recalculated with the new order kept | src/plan/plan_operation.service.ts, POST /plan/:code/move_stop, assign_stop, unassign_stop |
| Pinned stops | Built | A pinned stop keeps its route and round through the next optimisation | src/plan/plan_optimize.service.ts (_collectPins) |
| Planning history | Built | Every optimise, edit and failure writes one history event with counts; readable per plan | src/plan_history/, GET /plan_history, GET /plan_history/plan/:code |
| Order selection for a plan | Partly built | Built: picks the store's orders of that date in status PENDING. Designed: only approved orders, not on hold, claimed by no other plan, using the v2 status names | code: plan_optimize.service.ts (_findCandidateOrders); design: modules/planning/srs.md § "Order selection" |
| Plan states | Partly built | Built: three states (pending, planned, generated). Designed: seven states with fixed moves (adds optimising, failed, generating, cancelled) | code: src/common/enums/plan.enum.ts; design: modules/planning/srs.md § "Plan states" |
| Generate tasks from routes | Partly built | The endpoint exists but returns a success message without doing anything. Designed: one task per route with its stops and totals, orders set ASSIGNED, all in one transaction, resumable | code: plan.service.ts (generateTask), POST /plan/:code/generate_task; design: modules/planning/srs.md § "Generate tasks once per route" |
| Plan variants, one chosen per store and date | Designed | Several plans for the same store and date can be compared; the first one generated becomes the chosen one | modules/planning/srs.md § "Plan variants" |
| Cancel a plan | Designed | Cancels a plan with no route holding a task and releases its orders in the same write | modules/planning/srs.md § "Cancel a plan" |
| Claim orders at generate | Designed | An order is reserved for a plan only when its task is created, with a write that fails if another plan took it first | modules/planning/srs.md § "Claim at generate" |
| Attach drivers to vehicle slots | Designed | A driver goes on a slot only if active, not on approved leave and within working hours; ties go to the driver with fewest booked hours | modules/planning/srs.md § "Vehicle slots and driver attachment" |
| Manual route | Designed | The admin adds a route by picking a slot, a driver and a vehicle, even on a generated plan | modules/planning/srs.md § "Manual route" |
| On-demand insert | Designed | An order that becomes ready late is put into the day's plan automatically | modules/planning/srs.md § "On-demand insert" |
| Add an order to a route not yet started | Designed | The admin adds waiting orders of the same store to a route that has not left, after a preview | modules/planning/srs.md § "Add an order to a route not yet started" |
| Re-plan a started route | Designed | Re-optimises a route on the road; started and finished stops stay fixed | modules/planning/srs.md § "Re-plan a started route" |
| Partner assign rules | Designed | A store's ordered rule list (for example by order weight) picks each new order's partner and hand-over type | modules/planning/srs.md § "1.3 Definitions" (assign rules) |
| Load and load item records | Cut | In v1 a load only wrapped a task (7,089 loads for 7,083 tasks); capacity becomes a planning limit plus totals on the task | modules/planning/design.md § "Data model" |
| Legacy pre-built pipeline and load-based task generation | Cut | Not used on PROD | modules/planning/srs.md § "Retired v1 features" |
| Postal-code zones | Cut | Retired in the planning design as unused on PROD. A later decision reopened it: zones move into a v2 zoning design that is not written yet | modules/planning/srs.md § "Retired v1 features" |
Execution
The driver's run from accepting a task to closing it at the store, and ops corrections on the way. Nothing here runs yet: the task record exists but holds only its number.
| feature | status | what it does | where |
|---|---|---|---|
| Task record | Partly built | Built: a task collection with a running number (TK + 8 digits), no endpoints. Designed: driver, vehicle, ordered stops, capacity totals, status | code: src/task/; design: modules/execution/design.md § "Data model" |
| Reschedule trail per DO | Partly built | Built: a revision record per DO with a counter, readable per DO or per task, not yet called by anything. Designed: written when a failed DO is rescheduled | code: src/delivery_order_revision/; design: modules/execution/design.md § "Reschedule record, ad-hoc into a task, and who owns a DO" |
| Every status change is a guarded move | Designed | Task, stop and DO change status only through a fixed table and only if still in the expected status | modules/execution/srs.md § "Every status change is a guarded transition" |
| Accept a task | Designed | The assigned driver accepts a pending task | modules/execution/srs.md § "Accept a task" |
| Check in at the pickup store | Designed | Refused when the driver is farther than the store radius (default 300 m) | modules/execution/srs.md § "Check in at the pickup store" |
| Scan goods into the vehicle | Designed | Parked: stays as v1 for now; the scan count moves to the visit record | modules/execution/srs.md § "Scan goods into the vehicle" |
| Depart with a short load | Designed | Parked: v1 behaviour kept (staff PIN, short DOs held, their items cancelled) | modules/execution/srs.md § "Depart with a short load" |
| Depart | Designed | One transaction moves the task, its stops and its DOs, with optional staff PIN and load photos | modules/execution/srs.md § "Depart" |
| Start delivering, open the next stop | Designed | Opening a stop moves the task on the road and closes the previous stop | modules/execution/srs.md § "Start delivering and open the next stop" |
| Arrive at the customer | Designed | Stores the position and flags an arrival too far from the customer | modules/execution/srs.md § "Arrive at the customer" |
| Proof of delivery | Designed | Photo or signature upload checked against the DO and stop status, stored once per client upload id | modules/execution/srs.md § "Proof of delivery" |
| Confirm delivered | Designed | Safe to send twice; for a COD order the cash collection is written in the same transaction | modules/execution/srs.md § "Confirm delivered" |
| Report and retry a failed attempt | Designed | Reason, photo, position and call attempts; the attempt counts toward a cap (default 3) when its reason says so | modules/execution/srs.md § "Report and retry a failed attempt" |
| Hold and release a DO | Designed | Ops opens and releases a hold with a reason; each hold is its own record | modules/execution/srs.md § "Hold and release a DO" |
| Change a redelivery after close-out | Designed | Ops changes the date of a failed DO waiting for redelivery, or ends it as failed | modules/execution/srs.md § "Change a redelivery after close-out" |
| Return to store and close out | Designed | The driver scans back undelivered goods; staff decide redeliver or fail per DO | modules/execution/srs.md § "Return to store and close out" |
| Stop and task completion | Designed | Fixed rules for when a stop and a task are final | modules/execution/srs.md § "Stop and task completion" |
| Ops changes to a running task | Designed | Move stops between tasks that have not left, or add an order, after a preview | modules/execution/srs.md § "Ops changes to a running task" |
| Driver task list and ride history | Designed | Today's and upcoming tasks, plus a paged history by status group (backend endpoint) | modules/execution/srs.md § "Driver home and ride history" |
| Driver GPS trail | Designed | Positions sampled only during an active task, uploaded in batches, kept 90 days | modules/execution/srs.md § "Driver GPS trail" |
| Driven route | Designed | Built once from the GPS points when a task closes and kept on the task | modules/execution/srs.md § "Driven route" |
| Read lists for stops, proofs, attempts and holds | Designed | Ops can read every stop, proof, attempt, hold and GPS trail; none can be edited directly | modules/execution/srs.md § "Reason master and admin read lists" |
| Auto-cancel tasks never started | Designed | A scheduled job cancels tasks still not started a set number of hours after their date; their orders go back to the pool | modules/execution/srs.md § "Cancel tasks that were never started" |
| Ops close-out of overdue tasks | Designed | A list of tasks left on the road past their date, which ops close out | modules/execution/srs.md § "Ops close-out of an overdue task" |
| Visit record per task and DO | Designed | One record per task and DO keeps each visit as it happened, so a second attempt never overwrites the first | modules/execution/srs.md § "The visit record keeps each delivery visit" |
| An order on a task always has its task | Designed | Assigning a DO writes its task and stop in the same transaction; a daily check counts any orphans | modules/execution/srs.md § "An order on a task always has its task" |
| Generic stop-status rewrite, DO copies inside stops, manual loads, separate time-stamp endpoint | Cut | They let any client set a status outside the rules, go stale, or have no PROD use | modules/execution/srs.md § "Retired v1 features" |
| Stop proof photos and the old start-unload steps | Cut | Replaced by proof per DO and the single close-out step | modules/execution/srs.md § "Retired v1 features" |
COD (cash on delivery)
Collecting cash at the door and handing it to the store.
| feature | status | what it does | where |
|---|---|---|---|
| Collect COD inside confirm delivered | Designed | The server copies the amount due; the payment method, collector and time are written with the delivery | modules/cod-payment/srs.md § "Collect COD inside delivery confirmation" |
| Payment photo | Designed | Stores the photo and its time on the order only; still required before a COD order is confirmed | modules/cod-payment/srs.md § "Payment photo stores the photo only" |
| Exact amount only | Designed | No amount in the request and no part payment at the door; a customer who does not pay is a failed attempt | modules/cod-payment/srs.md § "The driver collects exactly the amount due" |
| Payment method stored as sent | Designed | Any method value OMS or the app sends is kept as is | modules/cod-payment/srs.md § "Payment method stored as sent" |
| Driver COD day view and balance | Designed | Per day: orders collected, total, cash in hand and shortfall owed | modules/cod-payment/srs.md § "Driver COD day view and balance" |
| Cash handover per task | Designed | After close-out the cashier enters the cash received; one handover record per task with expected, received and difference | modules/cod-payment/srs.md § "Cash handover per task" |
| Cashier PIN of the task's own store | Designed | The handover is refused unless the PIN belongs to staff of that store | modules/cod-payment/srs.md § "The cashier is identified by a PIN" |
| Short handover needs a reason | Designed | Less than expected needs a reason from the store's list; more than expected is refused | modules/cod-payment/srs.md § "A short handover needs a reason" |
| Correct a handover by adjustment | Designed | A store supervisor adds a signed adjustment with a reason; the original stays | modules/cod-payment/srs.md § "Correct a handover by adjustment" |
| Open-cash list per store | Designed | Tasks with cash collected and no handover, and tasks settled short | modules/cod-payment/srs.md § "Open-cash list per store" |
| Block dispatch while a driver holds cash | Designed | Store setting, off by default: planning refuses a driver who has an unsettled task | modules/cod-payment/srs.md § "Optional block on dispatch" |
| Whole-day COD confirm, standalone collect and method edit endpoints | Cut | Handover is per task and collection happens only inside confirm delivered | modules/cod-payment/srs.md § "Whole-day confirm and unused COD endpoints" |
| Partner contract and partner billing | Cut | 0 rows on PROD and no screen; partner costs may come back as rate cards later | modules/cod-payment/srs.md § "Partner contract and partner billing" |
Workforce
Drivers, their login and their working day.
| feature | status | what it does | where |
|---|---|---|---|
| Device registration and heartbeat | Built | The app registers its device for the logged-in user and sends a heartbeat; admin lists devices | src/device/device.controller.ts |
| Driver login | Partly built | Built: one login for every user type with an optional OTP step. Designed: active drivers by phone or driver number, the code sent by SMS | code: src/auth/auth.controller.ts; design: modules/workforce/srs.md § "Driver login" |
| Forgot password | Designed | Code by phone, then a new password with a confirmation token; the code never travels in the URL | modules/workforce/srs.md § "Forgot password" |
| Change own password | Designed | The driver changes the password by giving the current one | modules/workforce/srs.md § "Change own password" |
| Admin password reset | Designed | Ops sets a temporary password that must be changed at next login | modules/workforce/srs.md § "Admin password reset" |
| Driver profile | Designed | Name, photo, phone, partner, home vehicle and totals; only name and photo editable | modules/workforce/srs.md § "Driver profile" |
| Minimum app version | Designed | Below the minimum version the app may make no call except the update screen | modules/workforce/srs.md § "Minimum app version" |
| Partner portal scope | Designed | A partner user sees and edits only their own drivers, vehicles and bookings; filtered on the server | modules/workforce/srs.md § "Partner portal" |
| Create booking | Designed | Ops books a driver, vehicle, store and time window by form or import | modules/workforce/srs.md § "Create booking" |
| Clock-in | Designed | With photo and a fresh, accurate position; once per day | modules/workforce/srs.md § "Clock-in" |
| Clock-out | Designed | With photo and position, only with no task in progress | modules/workforce/srs.md § "Clock-out" |
| Clock-in history | Designed | The driver's last 15 days of duty records | modules/workforce/srs.md § "Clock-in history" |
| Hold and unhold a driver | Designed | Holding a driver unassigns their not-started tasks for that date in the same step | modules/workforce/srs.md § "Hold and unhold" |
| Break | Designed | Start and end a break with a reason from a list | modules/workforce/srs.md § "Break" |
| Leave | Designed | Ops enters and approves leave; only approved leave keeps a driver out of planning | modules/workforce/srs.md § "Leave" |
| Day close | Designed | Every 15 minutes, duty days still open 2 hours after their last window end are closed (or marked absent) | modules/workforce/srs.md § "Day close" |
| Driver master | Designed | Creating a driver also creates the login user; phone and driver number unique. Today a driver is only a user with the driver role | modules/workforce/srs.md § "Driver master" |
| Cognito and social login | Cut | Not used on PROD; password login only | workscope.md § "Out of scope" |
| Shift extension | Cut | Hidden in the v1 app | workscope.md § "Out of scope" |
Master data
Reference records other modules read. Each gets plain create, read, update and list.
| feature | status | what it does | where |
|---|---|---|---|
| Store | Built | Code, name, opening hours, location, loading bays | src/store/store.controller.ts |
| Vehicle type | Built | Default capacity and load and unload minutes per type | src/vehicle_type/vehicle_type.controller.ts |
| Plan template | Built | A store's vehicle slots: vehicle type, window, amount | src/plan_template/plan_template.controller.ts |
| User | Built | Create, list, read users; read and update own profile; roles admin, store operator, driver | src/user/user.controller.ts |
| API client (application) | Built | App key and secret for systems that call TMS; create, update, revoke, delete | src/application/application.controller.ts |
| Vehicle | Partly built | Built: create, list, read, update by code. Designed: unique plate number, partner, own capacity overriding its type, status model | code: src/vehicle/; design: modules/workforce/srs.md § "Vehicle master" |
| Shared base service for master records | Partly built | Built: one base service gives each entity create, read, update, delete and list. Designed: write access only for master records (transactional records change only through their commands); fix of read and write by id ignoring the caller's filter | code: src/common/base/base.service.ts; design: modules/platform/srs.md § "Base CRUD for master and config entities" |
| Channel | Designed | Sales channels by code (31 on PROD); intake parks orders of an unknown channel | modules/intake/design.md § "Data model" |
| Partner | Designed | Code, type, service scope, zones, supported vehicle types, priority | modules/workforce/srs.md § "Partner master" |
| Roles and permissions as data | Designed | Roles become editable records; permission keys are declared in code and collected by the system; a user may hold several roles | /Users/thanosorn/Works/Software/tms/_docs/bigc-tms-core-v2/tms-v2-auth.md § 3 |
| Store staff and staff PIN | Designed | Store staff get a 6-digit PIN, stored only as a keyed hash, used to sign departure and cash handover. Moved out of the first phase to the phase that first needs a signature | modules/platform/srs.md § "Staff PIN signature" |
| Failed-attempt reason master | Designed | Reason, category, and whether it counts toward the attempt cap | modules/execution/srs.md § "Reason master and admin read lists" |
| Break reason list | Designed | Reasons a driver can pick when starting a break | modules/workforce/srs.md § "Break" |
| Short-handover reason list | Designed | Reasons a cashier picks when less cash than expected is handed over, kept per store | modules/cod-payment/srs.md § "A short handover needs a reason" |
| Product, package and unit masters | Cut | Unused on PROD; DO lines keep the unit text as sent | workscope.md § "Out of scope" |
| Vehicle brand master | Cut | Unused on PROD | workscope.md § "Out of scope" |
| Partner rate cards in place of contracts | Cut | Partner contracts had 0 rows; rate cards only if asked for later | modules/cod-payment/design.md § "Partner contract and billing" |
Admin / reporting
Backend behaviour behind the admin: reports, export, import, permissions.
| feature | status | what it does | where |
|---|---|---|---|
| Print, email and SMS templates | Built | Templates stored per code and rendered with LiquidJS, optionally fed by a sandboxed data script | src/template/template.controller.ts (POST /template/render), src/template_engine/ |
| Field catalog | Built | Lists the fields of each entity that templates and exports may use | src/field_catalog/field_catalog.controller.ts |
| Export configs | Built | Create, list, read and update the column setup of an export | src/export_config/export_config.controller.ts |
| Export to Excel as a job | Partly built | Built: the export setup, field catalog and batched data script. Designed: running the export as a job with a visible status and the xlsx file kept for the user | code: src/export_config/, src/script_runner/batch_mapper.ts; design: modules/platform/srs.md § "Export runs as a job with a visible status" |
| Role check per endpoint | Partly built | Built: login check on every endpoint and a role list per endpoint. Designed: a permission key per endpoint and store filtering on the server; any other role gets 403 | code: src/common/guards/auth.guard.ts; design: modules/admin-reporting/srs.md § "Role check per endpoint" |
| Reports read live data | Designed | POD, Order Information and DO Transaction reports read current data, up to 31 days per request, first page in 2 s or less | modules/admin-reporting/srs.md § "Reports read live data" |
| Import from Excel | Designed | Two steps (verify, then execute) with partial commit, only for the configs ops still use | modules/admin-reporting/srs.md § "Import from Excel" |
| Partner scope and password login | Designed | A partner user logs in with a password and every read or write is limited to their partner | modules/admin-reporting/srs.md § "Partner scope and password login" |
| Scheduled report refresh | Cut | Reports read live data, so v1's scheduled report rebuild is not needed; BigC still has to accept this | workscope.md § "Rules BigC must confirm" |
| Disabled v1 report (delivery_order_report) | Cut | Already switched off in v1 | modules/admin-reporting/srs.md § "1.2 Scope" |
| Import/export configs no one uses | Cut | Only the configs ops name as in use (out of 26 on PROD) are ported | modules/admin-reporting/srs.md § "Import from Excel" |
Platform
The shared base every module writes through.
| feature | status | what it does | where |
|---|---|---|---|
| Background jobs that are never dropped | Built | A job is saved with its business change; a fast lane (64 partitions, each leased by one pod) and a long lane pick it up and retry; admin can list, retry and skip | src/jobs/, GET /jobs, POST /jobs/:id/retry, POST /jobs/:id/skip |
| Lossy lane | Built | Jobs that may be lost go straight to a Redis (Bull) queue after commit | src/jobs/lossy.processor.ts |
| Schedule engine | Built | Crons declared in code run once per slot across all pods; admin can enable, disable and override a cron | src/schedules/, GET /schedules, POST /schedules/:code/enable and related |
| Kafka outbound through an outbox | Built | A DO change saves its event in the same transaction; a worker sends it to lastmiles.oms.do-update or lastmiles.staffapp.do-update by channel, with an event id and version | src/kafka/kafka.target.ts, src/delivery_order/delivery_order.service.ts (_enqueueDoUpdate) |
| Kafka status and connection test | Built | Shows each pod's Kafka state and tests a connection before saving it | src/kafka/kafka.controller.ts |
| Record history in the business transaction | Built | One helper writes history rows in the same transaction as the change | src/activity_log/activity_log.service.ts |
| Read the history of a record | Built | Newest-first history of any record by entity and id | src/activity_log/activity_log.controller.ts, GET /activity_logs/:entity/:entity_id |
| Typed settings declared in code | Built | Each module declares its setting keys with type, default and secret flag; admin reads, edits and resets them | src/settings/, GET/PUT /settings/:code, POST /settings/:code/reset |
| Log lifecycle and retention | Built | Each log collection is declared once; the base creates its expiry index and retention is a setting; writes are transactional or buffered | src/log/ |
| External call log | Built | One helper logs outgoing calls (Google, Kafka) with a body size cap | src/common/utils/external_call.ts, src/google/google_log.schema.ts, src/kafka/kafka_log.schema.ts |
| Trace id end to end | Built | One trace id per HTTP request, Kafka message, schedule tick and job, added to every log line and outbound Kafka message | src/common/context/ |
| File upload straight to S3 | Built | The client gets a presigned upload URL, uploads, then confirms; unconfirmed files are swept | src/attachment/, POST /attachment, POST /attachment/:id/confirm |
| Storage setting | Built | S3 bucket and keys kept as an encrypted setting | src/storage_setting/ |
| Health check and public map key | Built | GET /health_check; GET /settings/public gives the Google Maps key to the admin | src/app.controller.ts, src/google/google_public.controller.ts |
| Sign in, session and sign out | Partly built | Built: token login, OTP check, Redis session, revoke. Designed: access plus rotating refresh token, account lockout | code: src/auth/; design: modules/platform/srs.md § "Sign in, session and sign out" |
| Fix auth as built | Partly built | Still open in code: tokens live 1 year, revoke accepts any token in the body, passwords use a SHA-256 hash salted with the creation date | code: src/common/constants/auth.constant.ts, src/auth/auth.service.ts; design: modules/platform/srs.md § "Fix v2 auth as built" |
| Business schedules | Partly built | The engine runs, but no business cron is declared yet. Designed: booking shift generation daily, on-demand assign every minute, Kafka inbox retry and reconcile, plus the day-close and auto-cancel jobs | design: modules/platform/srs.md § "Run scheduled jobs once per slot" |
| Send email | Designed | An email is a row written with the business change; a worker renders and sends it over SMTP with retries | modules/platform/srs.md § "Send email" |
| Search lists by indexed fields | Designed | One keyword box with exact or prefix match on indexed fields, separate filters | modules/platform/srs.md § "Search lists by indexed fields" |
| Versioned admin config | Designed | Admin-editable config saved as immutable versions with validate, preview and activate; first user is the Kafka mapping | modules/platform/srs.md § "Versioned admin config" |
| Master-data cache | Designed | Master records cached so pods stay stateless and fast | modules/platform/design.md § "Master-data cache and stateless pods" |
| Kafka channel list as configuration | Designed | Which channels go to which outbound topic is configuration. Today the lists are fixed in code | modules/platform/srs.md § "Publish a business event to Kafka" |
| Grouped exception log | Designed | Parked until ops confirm New Relic on PROD; if New Relic is on, this is dropped | modules/platform/srs.md § "Exception log, grouped" |
| Internal MCP for support | Designed | Draft only: read-only tools for support staff to inspect v2 data | modules/platform/design.md § "Internal MCP (draft)" |
| Kafka direct-produce path | Cut | Removed in the foundation simplify review: every outbound event goes through the outbox | /Users/thanosorn/Works/Software/tms/_docs/bigc-tms-core-v2/tms-v2-foundation-simplify-cut-list.md |
| Load, task and driver Kafka topics | Cut | PROD never had them; their event names are still listed in code but nothing sends them | modules/platform/srs.md § "Publish a business event to Kafka" |
| Job statistics counters | Cut | Nothing read them; removed in the simplify review | /Users/thanosorn/Works/Software/tms/_docs/bigc-tms-core-v2/tms-v2-foundation-simplify-cut-list.md |
| Push notifications to drivers | Cut | Out of scope until a real requirement exists | workscope.md § "Out of scope" |