Production plan
Production planning
INFO
Every response arrives in the shared envelope — code, message, messages, status_code, time — with the payload in data. The tables below describe what is inside data.
POST /production-plan/create
Create a production plan for a given year and organization. This is a year-keyed upsert — if a plan already exists for the given (year, organization_id) it is updated rather than duplicated. Items carry per-product monthly targets.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
year | number | Yes | The production plan year (e.g. 2025). Together with organization_id this is the upsert key — submitting a plan for the same year + organization updates the existing plan. |
organization_id | string | Yes | Organization ObjectId this plan belongs to |
note | string | No | Optional free-text note |
items | object[] | Yes | Per-product monthly production targets (at least one item required) |
items[].product_id | string | Yes | Product ObjectId |
items[].months | object[] | Yes | Monthly target entries for this product (at least one month required) |
items[].months[].amount | number | Yes | Planned production quantity for this month |
items[].months[].month_number | number | Yes | Calendar month (1 = January … 12 = December). Each month_number must be unique within an item. |
{
"year": 2025,
"organization_id": "string",
"note": "string",
"items": [
{
"product_id": "string",
"months": []
}
]
}Response
| Field | Type | Description |
|---|---|---|
_id | string | Production plan ObjectId |
number | string | Auto-generated plan number |
year | number | Plan year |
note | string | Free-text note |
organization_id | string | Organization ObjectId |
organization | object | |
organization._id | string | |
organization.name | string | |
created_by | object | |
created_by._id | string | |
created_by.number | string | |
created_by.full_name | string | |
updated_by | object | |
updated_by._id | string | |
updated_by.number | string | |
updated_by.full_name | string | |
created_at | string (date-time) | |
updated_at | string (date-time) | |
items | object[] | |
items[].product_id | string | Product ObjectId |
items[].product | object | |
items[].product._id | string | |
items[].product.name | string | |
items[].product.sku | string | |
items[].product.barcode | string | |
items[].months | object[] | |
items[].months[].amount | number | Planned quantity |
items[].months[].month_number | number | Calendar month (1–12) |
items[].months[].produced | number | Actual produced quantity so far |
{
"code": 0,
"message": "Success",
"status_code": 200,
"data": {
"_id": "string",
"number": "string",
"year": 0,
"note": "string",
"organization_id": "string",
"organization": {
"_id": "string",
"name": "string"
},
"created_by": {
"_id": "string",
"number": "string",
"full_name": "string"
},
"updated_by": {
"_id": "string",
"number": "string",
"full_name": "string"
},
"created_at": "2025-05-01T12:00:00Z",
"updated_at": "2025-05-01T12:00:00Z",
"items": [
{
"product_id": "string",
"product": {
"_id": null,
"name": null,
"sku": null,
"barcode": null
},
"months": []
}
]
},
"time": "2025-05-01T12:00:00Z"
}PUT /production-plan/update/{id}
Update a production plan. Internally performs the same year-keyed upsert as create — the {id} path parameter is standard-shape only; the real dedup key is body year + organization_id. Send the full plan payload including items.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Production plan ObjectId (standard-shape; upsert key is year + organization_id in body) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
year | number | Yes | The production plan year (e.g. 2025). Together with organization_id this is the upsert key — submitting a plan for the same year + organization updates the existing plan. |
organization_id | string | Yes | Organization ObjectId this plan belongs to |
note | string | No | Optional free-text note |
items | object[] | Yes | Per-product monthly production targets (at least one item required) |
items[].product_id | string | Yes | Product ObjectId |
items[].months | object[] | Yes | Monthly target entries for this product (at least one month required) |
items[].months[].amount | number | Yes | Planned production quantity for this month |
items[].months[].month_number | number | Yes | Calendar month (1 = January … 12 = December). Each month_number must be unique within an item. |
{
"year": 2025,
"organization_id": "string",
"note": "string",
"items": [
{
"product_id": "string",
"months": []
}
]
}Response
Same response shape as POST /production-plan/create.
GET /production-plan/get-by-id/{id}
Fetch a single production plan by ObjectId, with aggregated items and per-product monthly targets.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Production plan ObjectId |
Request body
No request body.
Response
Same response shape as POST /production-plan/create.
POST /production-plan/get-paging
Paginated list of production plans. The search field matches against the plan number.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
page | number | Yes | Default: 1 |
limit | number | Yes | Default: 20 |
search | string | No | Search string matched against plan number |
{
"page": 1,
"limit": 20,
"search": "string"
}Response
| Field | Type | Description |
|---|---|---|
total | number | |
list | object[] | |
list[]._id | string | |
list[].number | string | |
list[].year | number | |
list[].note | string | |
list[].organization_id | string | |
list[].organization | object | |
list[].organization._id | string | |
list[].organization.name | string | |
list[].created_by | object | |
list[].created_by._id | string | |
list[].created_by.number | string | |
list[].created_by.full_name | string | |
list[].updated_by | object | |
list[].updated_by._id | string | |
list[].updated_by.number | string | |
list[].updated_by.full_name | string | |
list[].created_at | string (date-time) | |
list[].updated_at | string (date-time) |
{
"code": 0,
"message": "Success",
"status_code": 200,
"data": {
"total": 0,
"list": [
{
"_id": "string",
"number": "string",
"year": 0,
"note": "string",
"organization_id": "string",
"organization": {
"_id": null,
"name": null
},
"created_by": {
"_id": null,
"number": null,
"full_name": null
},
"updated_by": {
"_id": null,
"number": null,
"full_name": null
},
"created_at": "2025-05-01T12:00:00Z",
"updated_at": "2025-05-01T12:00:00Z"
}
]
},
"time": "2025-05-01T12:00:00Z"
}POST /production-plan/delete-many
Soft-delete one or more production plans by their ObjectIds. Sets is_deleted=true; no physical deletion.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
ids | string[] | Yes | Production plan ObjectIds to soft-delete (at least one required) |
{
"ids": [
"string"
]
}Response
{
"code": 0,
"message": "Success",
"status_code": 200,
"data": "ok",
"time": "2025-05-01T12:00:00Z"
}POST /production-plan/get-by-year
Fetch the production plan for a year + organization. Together these are the plan's natural key — the same pair create/update upsert on — so this is the lookup to use when you hold the business key rather than the ObjectId. Returns an empty object when no plan exists for that pair.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
year | number | Yes | Calendar year of the plan, e.g. 2026 |
organization_id | string | Yes | Organization ObjectId the plan belongs to |
{
"year": 2026,
"organization_id": "string"
}Response
Same response shape as POST /production-plan/create.
This page is generated from the OpenAPI spec.