Skip to content

Work-Order Persistence

Summary of MongoDB persistence rules for:

  • POST /api/v1/inbound/work-orders (live writes)

The public format-validation endpoint POST /api/v1/inbound/work-orders/test does not use this persistence plan. See Inbound Work Orders.

API usage and examples: Inbound Work Orders.

Scope

The live endpoint validates then persists accepted projects to customer MongoDB collections:

  • projects
  • products
  • machines (read-only resolution)
  • users (read-only resolution)

The test endpoint validates JSON/XML format and contract only. It never reads or writes business collections, never writes api_idempotency_records, and never writes api_request_archive.

Live endpoint idempotency (Idempotency-Key) and raw request archive are implemented. See Idempotency and Request Archive.

Tenant fields

Every request resolves a tenant from root company_id and organization_id using the same pair-and-fallback rules as outbound GET endpoints:

Situation Result
Both request values present Use the request pair
Neither request value present Use DEFAULT_COMPANY_ID and DEFAULT_ORGANIZATION_ID when both are configured
Exactly one request value present Request rejected (TENANT_CONTEXT_INCOMPLETE)
Neither request nor configured defaults Request rejected (TENANT_CONTEXT_REQUIRED)

All lookups are scoped to the resolved tenant. The service never operates without a tenant filter.

Collection type differences

Existing schemas are preserved (no type migration in this release):

Collection company_id / organization_id
projects ObjectID
machines ObjectID
products string
users string

Natural keys

Entity Key
Project tenant + project_code
Production production_code within a project document
Stage production_stage_code within a production
Product tenant + product_code
Machine tenant + machine_code
Employee tenant + username

Product upsert

All product occurrences in the payload are upserted into products:

  • Create when missing; keep _id when updating
  • Update mutable fields: product_name, category, unit, ideal_cycle_time
  • Do not change product_code
  • Preserve existing description and image_url
  • quantity stays on embedded occurrences only
  • Same product_code may appear multiple times; master upsert can run once while occurrences keep distinct quantities

Project / production / stage merge

  • New project when code is unknown; update when code and name match
  • Same code with different name → skip project (PROJECT_NAME_CONFLICT); do not modify the document
  • Unsent existing productions and stages are preserved
  • Matched productions/stages update contract fields; operational fields (production_stage_operation, files, status when not in contract) are preserved
  • New production stages default to integer status: 0 (BSON integer). Existing stage status values are never overwritten by the request
  • If all incoming stages for a production are skipped → production skipped (ALL_STAGES_SKIPPED)
  • If all productions for a project are skipped → project skipped (ALL_PRODUCTIONS_SKIPPED)

Shared processing plan

The live endpoint builds one deterministic ProcessingPlan after validation:

  1. Decode → normalize → contract validation
  2. Tenant ObjectID and duplicate checks
  3. Integration actor validation
  4. Project / product / machine / employee lookups (reads)
  5. Product create/update/unchanged preview
  6. Production and stage merge preview, including skip rules

Then live applies the plan with MongoDB writes.

The public test endpoint stops after decode/normalize/contract validation and does not build or apply a processing plan.

Test / live difference

A successful format test does not guarantee a later live request will succeed. Live processing still depends on database state, tenant resolution, actor configuration, and business rules.

Machine resolution

Machines catalog is read-only. Missing machine_code skips the entire stage (MACHINE_NOT_FOUND). Empty machines arrays are allowed. Canonical machine_name / machine_code come from MongoDB.

Employee resolution

Users catalog is read-only. Missing username skips only that assignment (EMPLOYEE_NOT_FOUND) and does not skip the stage. Password, email, phone, and role are never embedded.

Partial processing

Projects are processed independently. Response data.status:

  • success — all received projects processed
  • partial_success — at least one processed and one or more skipped
  • HTTP 409 NO_PROJECT_PROCESSED — none processed

Integration actor

INTEGRATION_ACTOR_USER_ID supplies audit ObjectIDs / hex strings for new and updated project/product audit fields. It must be the ObjectID of an existing active user in the same Users store used at runtime. A random ObjectID is invalid even if the hex format is correct. Known actor failures return HTTP 409 (INTEGRATION_ACTOR_USER_NOT_FOUND, INTEGRATION_ACTOR_USER_INACTIVE, INTEGRATION_ACTOR_TENANT_MISMATCH) instead of INTERNAL_ERROR. Responses never include the actor ObjectID. See Configuration and Error Codes.

Standalone MongoDB

No multi-document transactions. Project document writes are single-document atomic. Product upserts are independent; products may remain if a later project write fails.

Code HTTP
NO_PROJECT_PROCESSED 409
INTEGRATION_ACTOR_USER_NOT_FOUND 409
INTEGRATION_ACTOR_USER_INACTIVE 409
INTEGRATION_ACTOR_TENANT_MISMATCH 409
DATABASE_UNAVAILABLE 503
INTERNAL_ERROR 500