572 lines
17 KiB
JSON
572 lines
17 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://local.lwltapi/schemas/standard_system_operation.schema.json",
|
|
"title": "Standard LTJT System Operation",
|
|
"description": "Deterministic task operation contract for LTJT. Team create/batch may defer ERP-derived fields through data.resolution; browser-form mapping remains responsible for ERP readiness.",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["action", "order_nature", "submit_mode", "data"],
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"enum": [
|
|
"team_order_create",
|
|
"team_order_batch_create",
|
|
"shared_plan_create",
|
|
"shared_child_order_create",
|
|
"order_update",
|
|
"passenger_list_import",
|
|
"confirmation_export"
|
|
]
|
|
},
|
|
"order_nature": {
|
|
"type": "string",
|
|
"enum": ["test", "formal"]
|
|
},
|
|
"submit_mode": {
|
|
"type": "string",
|
|
"description": "Production should start with dry_run. submit must be explicitly enabled by the owner.",
|
|
"enum": ["dry_run", "submit"]
|
|
},
|
|
"source": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"instruction_id": { "type": "string" },
|
|
"operator": { "type": "string" },
|
|
"received_at": { "type": "string", "format": "date-time" },
|
|
"notes": { "type": "string" }
|
|
}
|
|
},
|
|
"data": {
|
|
"$ref": "#/$defs/operationData"
|
|
}
|
|
},
|
|
"allOf": [
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "team_order_create" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": [
|
|
"product",
|
|
"departure_dates",
|
|
"passenger_counts",
|
|
"room_counts",
|
|
"prices",
|
|
"op_user",
|
|
"sales_user"
|
|
],
|
|
"properties": {
|
|
"departure_dates": {
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "team_order_batch_create" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": [
|
|
"product",
|
|
"departure_dates",
|
|
"passenger_counts",
|
|
"room_counts",
|
|
"prices",
|
|
"op_user",
|
|
"sales_user"
|
|
],
|
|
"properties": {
|
|
"departure_dates": {
|
|
"minItems": 2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "shared_plan_create" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": [
|
|
"product",
|
|
"departure_dates",
|
|
"planned_capacity",
|
|
"op_user"
|
|
],
|
|
"properties": {
|
|
"departure_dates": {
|
|
"minItems": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "shared_child_order_create" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": [
|
|
"customer",
|
|
"passenger_counts",
|
|
"prices",
|
|
"op_user",
|
|
"sales_user"
|
|
],
|
|
"anyOf": [
|
|
{ "required": ["existing_refs"] },
|
|
{ "required": ["product", "departure_dates"] }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "order_update" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": ["existing_refs", "updates"]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "passenger_list_import" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": ["existing_refs"],
|
|
"anyOf": [
|
|
{ "required": ["passenger_list"] },
|
|
{ "required": ["attachments"] },
|
|
{ "required": ["updates"] }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": {
|
|
"properties": { "action": { "const": "confirmation_export" } },
|
|
"required": ["action"]
|
|
},
|
|
"then": {
|
|
"properties": {
|
|
"data": {
|
|
"required": ["existing_refs"],
|
|
"anyOf": [
|
|
{ "required": ["confirmation"] },
|
|
{ "required": ["export_types"] }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"$defs": {
|
|
"operationData": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"order_mode": { "type": "string" },
|
|
"test_marker": { "type": "string" },
|
|
"customer": { "$ref": "#/$defs/namedRef" },
|
|
"product": { "$ref": "#/$defs/namedRef" },
|
|
"route": { "$ref": "#/$defs/namedRef" },
|
|
"departure_dates": {
|
|
"type": "array",
|
|
"items": { "type": "string", "format": "date" },
|
|
"uniqueItems": true
|
|
},
|
|
"trip": { "$ref": "#/$defs/trip" },
|
|
"order_number": { "$ref": "#/$defs/orderNumber" },
|
|
"recurrence": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"start_date": { "type": "string", "format": "date" },
|
|
"end_date": { "type": "string", "format": "date" },
|
|
"pattern": {
|
|
"type": "string",
|
|
"enum": ["daily", "weekly", "odd_days", "even_days", "specified_dates"]
|
|
},
|
|
"weekday": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 7
|
|
},
|
|
"uniqueItems": true
|
|
}
|
|
}
|
|
},
|
|
"planned_capacity": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"cycle": { "type": "string" },
|
|
"groups_per_date": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 1
|
|
},
|
|
"plans_per_date": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 1
|
|
},
|
|
"parent_group_no": { "type": "string" },
|
|
"child_order_no": { "type": "string" },
|
|
"passenger_counts": { "$ref": "#/$defs/passengerCounts" },
|
|
"room_counts": { "$ref": "#/$defs/roomCounts" },
|
|
"prices": { "$ref": "#/$defs/prices" },
|
|
"op_user": { "$ref": "#/$defs/namedRef" },
|
|
"sales_user": { "$ref": "#/$defs/namedRef" },
|
|
"logistics": { "$ref": "#/$defs/logistics" },
|
|
"special_requests": { "type": "string" },
|
|
"passenger_list": { "$ref": "#/$defs/passengerList" },
|
|
"attachments": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/attachment" }
|
|
},
|
|
"existing_refs": { "$ref": "#/$defs/existingRefs" },
|
|
"updates": {
|
|
"type": "object",
|
|
"description": "Structured update actions. The browser adapter narrows targets again before any write.",
|
|
"properties": {
|
|
"status": { "type": "string" },
|
|
"actions": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/updateAction" }
|
|
}
|
|
},
|
|
"additionalProperties": true
|
|
},
|
|
"export_types": {
|
|
"type": "array",
|
|
"uniqueItems": true,
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["xingyou-confirm", "liantai-confirm", "job-order"]
|
|
}
|
|
},
|
|
"recovery": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"export_only": { "type": "boolean" },
|
|
"never_resave": { "type": "boolean" }
|
|
}
|
|
},
|
|
"confirmation": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["type"],
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["default", "confirmation", "xingyou", "xingyou-confirm", "liantai", "liantai-confirm", "job", "job-order"]
|
|
},
|
|
"language": { "type": "string" },
|
|
"format": {
|
|
"type": "string",
|
|
"enum": ["pdf", "doc", "docx", "xls", "xlsx", "html"]
|
|
}
|
|
}
|
|
},
|
|
"system_defaults": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"fabudanwei": { "type": "string" },
|
|
"currency": { "type": "string" },
|
|
"business_status": { "type": "string" },
|
|
"filing_required": {
|
|
"type": "boolean",
|
|
"description": "Maps to LTJT yaobeian checkbox. The current add form serializes checked value as 要备案."
|
|
}
|
|
}
|
|
},
|
|
"validation_notes": {
|
|
"type": "array",
|
|
"items": { "type": "string" }
|
|
},
|
|
"resolution": {
|
|
"$ref": "#/$defs/fieldResolution"
|
|
}
|
|
}
|
|
},
|
|
"fieldResolution": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"mode": {
|
|
"type": "string",
|
|
"enum": ["task_ready", "erp_ready"]
|
|
},
|
|
"deferred_fields": {
|
|
"type": "array",
|
|
"uniqueItems": true,
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["customer", "route", "trip", "order_number"]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"namedRef": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"id": { "type": "string" },
|
|
"cpid": { "type": "string" },
|
|
"keyword": { "type": "string" },
|
|
"ltjt_id": { "type": "string" },
|
|
"contact": { "type": "string" },
|
|
"origin": { "type": "string" },
|
|
"resolved": {
|
|
"type": "boolean",
|
|
"description": "true only after deterministic lookup found exactly one accepted LTJT record."
|
|
}
|
|
}
|
|
},
|
|
"trip": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["days"],
|
|
"properties": {
|
|
"days": { "type": "integer", "minimum": 1, "maximum": 15 },
|
|
"nights": { "type": "integer", "minimum": 0, "maximum": 14 },
|
|
"label": {
|
|
"type": "string",
|
|
"description": "LTJT TianShu display value such as 1D, 2D1N, or 4D3N."
|
|
}
|
|
}
|
|
},
|
|
"orderNumber": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"prefix": {
|
|
"type": "string",
|
|
"description": "LTJT tuanxuhao1 value, normally resolved from route lookup."
|
|
},
|
|
"suffix": {
|
|
"type": "string",
|
|
"description": "LTJT tuanxuhao2 value maintained by the user's business system/database."
|
|
},
|
|
"full": {
|
|
"type": "string",
|
|
"description": "Optional complete order number when the upstream system stores it as one value."
|
|
}
|
|
},
|
|
"anyOf": [
|
|
{ "required": ["prefix", "suffix"] },
|
|
{ "required": ["full"] }
|
|
]
|
|
},
|
|
"passengerCounts": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["adult", "child_bed", "child_no_bed", "infant", "leader"],
|
|
"properties": {
|
|
"adult": { "type": "integer", "minimum": 0 },
|
|
"child_bed": { "type": "integer", "minimum": 0 },
|
|
"child_no_bed": { "type": "integer", "minimum": 0 },
|
|
"infant": { "type": "integer", "minimum": 0 },
|
|
"leader": { "type": "integer", "minimum": 0 },
|
|
"expected_total": { "type": "integer", "minimum": 1 }
|
|
}
|
|
},
|
|
"roomCounts": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"SGL": { "type": "integer", "minimum": 0 },
|
|
"TWN": { "type": "integer", "minimum": 0 },
|
|
"TRP": { "type": "integer", "minimum": 0 },
|
|
"DBL": { "type": "integer", "minimum": 0 },
|
|
"HNM": { "type": "integer", "minimum": 0 },
|
|
"TL": { "type": "integer", "minimum": 0 },
|
|
"notes": { "type": "string" }
|
|
}
|
|
},
|
|
"prices": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"currency": { "type": "string" },
|
|
"adult": { "type": "number", "minimum": 0 },
|
|
"child_bed": { "type": "number", "minimum": 0 },
|
|
"child_no_bed": { "type": "number", "minimum": 0 },
|
|
"infant": { "type": "number", "minimum": 0 },
|
|
"leader": { "type": "number", "minimum": 0 },
|
|
"items": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name", "quantity", "unit_price"],
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"unit": { "type": "string" },
|
|
"quantity": { "type": "number", "minimum": 0 },
|
|
"unit_price": { "type": "number", "minimum": 0 },
|
|
"currency": { "type": "string" },
|
|
"remark": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"logistics": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"flights": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/textBlock" }
|
|
},
|
|
"hotels": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/textBlock" }
|
|
},
|
|
"transfers": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/textBlock" }
|
|
},
|
|
"itinerary_notes": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/textBlock" }
|
|
}
|
|
}
|
|
},
|
|
"textBlock": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["text"],
|
|
"properties": {
|
|
"date": { "type": "string", "format": "date" },
|
|
"day_no": { "type": "integer", "minimum": 1 },
|
|
"text": { "type": "string" }
|
|
}
|
|
},
|
|
"passengerList": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["operation"],
|
|
"properties": {
|
|
"operation": {
|
|
"type": "string",
|
|
"enum": [
|
|
"none",
|
|
"first_import",
|
|
"append",
|
|
"modify",
|
|
"delete",
|
|
"replace",
|
|
"full_replace",
|
|
"reduce"
|
|
]
|
|
},
|
|
"confirmed": {
|
|
"type": "boolean",
|
|
"description": "Required true for modify/delete/replace/full_replace/reduce before submit."
|
|
},
|
|
"passenger_count": { "type": "integer", "minimum": 0 },
|
|
"file_count": { "type": "integer", "minimum": 0 },
|
|
"file_refs": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/attachment" }
|
|
},
|
|
"notes": { "type": "string" }
|
|
}
|
|
},
|
|
"attachment": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"path": { "type": "string" },
|
|
"mime_type": { "type": "string" },
|
|
"ltjt_file_ref": { "type": "string" }
|
|
}
|
|
},
|
|
"existingRefs": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"identifier": { "type": "string" },
|
|
"order_no": { "type": "string" },
|
|
"plan_no": { "type": "string" },
|
|
"parent_group_no": { "type": "string" },
|
|
"parent_plan_no": { "type": "string" },
|
|
"child_order_no": { "type": "string" },
|
|
"ltjt_ddid": { "type": "string" },
|
|
"ltjt_tdid": { "type": "string" },
|
|
"ltjt_child_id": { "type": "string" },
|
|
"ddid": { "type": "string" },
|
|
"tid": { "type": "string" },
|
|
"parent_tid": { "type": "string" },
|
|
"child_did": { "type": "string" }
|
|
}
|
|
}
|
|
,
|
|
"updateAction": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["target", "operation"],
|
|
"properties": {
|
|
"target": { "type": "string", "minLength": 1 },
|
|
"operation": {
|
|
"type": "string",
|
|
"enum": ["set", "delta", "append", "traveler_upsert"]
|
|
},
|
|
"value": {}
|
|
}
|
|
}
|
|
},
|
|
"x-runtime_validation": [
|
|
"For all write operations, passenger_counts adult + child_bed + child_no_bed + infant + leader must be greater than zero.",
|
|
"For order create/update with passenger_list, passenger_list.passenger_count must not exceed passenger_counts.expected_total or computed passenger total.",
|
|
"For passenger-list modify/delete/replace/full_replace/reduce, passenger_list.confirmed must be true.",
|
|
"All namedRef values used in LTJT hidden fields must be resolved exactly once before submit.",
|
|
"Dry-run serialization must match the versioned LTJT form mapping before any submit."
|
|
]
|
|
}
|