494 lines
15 KiB
JSON
494 lines
15 KiB
JSON
{
|
||
"$schema": "https://local.lwltapi/schemas/ltjt_form_mapping.schema.json",
|
||
"mapping_version": "2026-07-07.team_order_create.orders_add.v0.1",
|
||
"status": "draft_dry_run",
|
||
"source": {
|
||
"schema": "schemas/standard_system_operation.schema.json",
|
||
"action": "team_order_create"
|
||
},
|
||
"target": {
|
||
"form_schema": "schemas/orders_add_form_schema.json",
|
||
"page": "/System/Business/orders_add.asp",
|
||
"form_id": "ListForm",
|
||
"submit_endpoint": "/System/DAT/orders.asp",
|
||
"submit_action": "DoInfoJH",
|
||
"payload_prefix": "Act=DoInfoJH&",
|
||
"response_type": "script"
|
||
},
|
||
"limits": {
|
||
"departure_dates": {
|
||
"min": 1,
|
||
"max": 1
|
||
},
|
||
"receivable_rows": {
|
||
"max": 10
|
||
},
|
||
"attachments": {
|
||
"max": 2
|
||
},
|
||
"transport_rows": {
|
||
"max": 4
|
||
},
|
||
"itinerary_days": {
|
||
"max": 15
|
||
}
|
||
},
|
||
"required_target_fields": [
|
||
"chufa_ri",
|
||
"zhuanxianming",
|
||
"TianShu",
|
||
"zutuanshe",
|
||
"chanpinming",
|
||
"gendanren",
|
||
"tuanxuhao1",
|
||
"tuanxuhao2",
|
||
"darenshu",
|
||
"xiaorenshu",
|
||
"ertrenshu",
|
||
"yingrenshu",
|
||
"quanrenshu",
|
||
"xiaoshouren"
|
||
],
|
||
"direct_fields": [
|
||
{
|
||
"target": "chufa_ri",
|
||
"source": "data.departure_dates[0]",
|
||
"transform": "date_yyyy_m_d",
|
||
"required": true,
|
||
"description": "出发日期"
|
||
},
|
||
{
|
||
"target": "zhuanxianming",
|
||
"source": "data.route.name",
|
||
"required": true,
|
||
"description": "专线名称"
|
||
},
|
||
{
|
||
"target": "TianShu",
|
||
"source": "data.trip.label",
|
||
"fallback": "derive_trip_label(data.trip.days, data.trip.nights)",
|
||
"required": true,
|
||
"description": "行程天数,例如 4D3N"
|
||
},
|
||
{
|
||
"target": "zutuanshe",
|
||
"source": "data.customer.name",
|
||
"required": true,
|
||
"description": "预订客户"
|
||
},
|
||
{
|
||
"target": "chanpinming",
|
||
"source": "data.product.name",
|
||
"required": true,
|
||
"description": "产品名称"
|
||
},
|
||
{
|
||
"target": "gendanren",
|
||
"source": "data.op_user.name",
|
||
"required": true,
|
||
"description": "跟单人"
|
||
},
|
||
{
|
||
"target": "xiaoshouren",
|
||
"source": "data.sales_user.name",
|
||
"required": true,
|
||
"description": "销售人"
|
||
},
|
||
{
|
||
"target": "tuanxuhao1",
|
||
"source": "data.order_number.prefix",
|
||
"required": true,
|
||
"description": "团号前缀,通常由专线 lookup 回填"
|
||
},
|
||
{
|
||
"target": "tuanxuhao2",
|
||
"source": "data.order_number.suffix",
|
||
"required": true,
|
||
"description": "团号后缀"
|
||
},
|
||
{
|
||
"target": "darenshu",
|
||
"source": "data.passenger_counts.adult",
|
||
"transform": "integer_string",
|
||
"required": true,
|
||
"description": "成人数"
|
||
},
|
||
{
|
||
"target": "xiaorenshu",
|
||
"source": "data.passenger_counts.child_bed",
|
||
"transform": "integer_string",
|
||
"required": true,
|
||
"description": "小童占床"
|
||
},
|
||
{
|
||
"target": "ertrenshu",
|
||
"source": "data.passenger_counts.child_no_bed",
|
||
"transform": "integer_string",
|
||
"required": true,
|
||
"description": "小童不占床"
|
||
},
|
||
{
|
||
"target": "yingrenshu",
|
||
"source": "data.passenger_counts.infant",
|
||
"transform": "integer_string",
|
||
"required": true,
|
||
"description": "婴儿"
|
||
},
|
||
{
|
||
"target": "quanrenshu",
|
||
"source": "data.passenger_counts.leader",
|
||
"transform": "integer_string",
|
||
"required": true,
|
||
"description": "领队"
|
||
},
|
||
{
|
||
"target": "danzhuangtai",
|
||
"source": "data.system_defaults.business_status",
|
||
"default": "预订",
|
||
"description": "订单状态 radio"
|
||
},
|
||
{
|
||
"target": "yaobeian",
|
||
"source": "data.system_defaults.filing_required",
|
||
"default": true,
|
||
"transform": "checkbox_yaobeian",
|
||
"description": "备案 checkbox;真实页面默认序列化为 yaobeian=要备案"
|
||
},
|
||
{
|
||
"target": "fabudanwei",
|
||
"source": "data.system_defaults.fabudanwei",
|
||
"description": "发布单位,由页面入口和 session 决定;本地 dry-run 可预填"
|
||
},
|
||
{
|
||
"target": "bizhong",
|
||
"source": "data.prices.currency",
|
||
"fallback": "data.system_defaults.currency",
|
||
"description": "客户/价格币种"
|
||
},
|
||
{
|
||
"target": "xiadanbeizhu",
|
||
"source": "data.special_requests",
|
||
"description": "下单备注"
|
||
}
|
||
],
|
||
"lookup_fields": [
|
||
{
|
||
"name": "customer",
|
||
"source": "data.customer",
|
||
"display_target": "zutuanshe",
|
||
"id_target": "zutuansheid",
|
||
"optional_targets": {
|
||
"contact_target": "zutuanshegzr",
|
||
"currency_target": "bizhong"
|
||
},
|
||
"endpoint_hint": "../dat/AjaxPublicFun.asp?Act=ProTravel&fabudanwei=${fabudanwei}",
|
||
"match_rule": "exact_name_or_configured_alias",
|
||
"submit_blocker_if_unresolved": true
|
||
},
|
||
{
|
||
"name": "route",
|
||
"source": "data.route",
|
||
"display_target": "zhuanxianming",
|
||
"endpoint_hint": "../dat/AjaxPublicFun.asp?Act=GetInformation&fl=3&fls=1&fabudanwei=${fabudanwei}",
|
||
"match_rule": "exact_name_or_configured_alias",
|
||
"notes": "The LTJT page uses this lookup to set zhuanxianming and tuanxuhao1.",
|
||
"submit_blocker_if_unresolved": true
|
||
},
|
||
{
|
||
"name": "product",
|
||
"source": "data.product",
|
||
"display_target": "chanpinming",
|
||
"optional_targets": {
|
||
"pricing_metadata_target": "baojia"
|
||
},
|
||
"endpoint_hint": "../dat/AjaxPublicFun.asp?Act=ProGetProductname&fls=1&fabudanwei=${fabudanwei}; ../dat/AjaxPublicFun.asp?Act=GetProduct&cpm=${chanpinming}",
|
||
"match_rule": "exact_name_or_configured_alias",
|
||
"submit_blocker_if_unresolved": true
|
||
},
|
||
{
|
||
"name": "op_user",
|
||
"source": "data.op_user",
|
||
"display_target": "gendanren",
|
||
"endpoint_hint": "../dat/AjaxPublicFun.asp?Act=ProDanwei_Yuangong&fabudanwei=${fabudanwei}",
|
||
"match_rule": "exact_staff_name",
|
||
"submit_blocker_if_unresolved": true
|
||
},
|
||
{
|
||
"name": "sales_user",
|
||
"source": "data.sales_user",
|
||
"display_target": "xiaoshouren",
|
||
"endpoint_hint": "../dat/AjaxPublicFun.asp?Act=ProDanwei_Yuangong&fabudanwei=${fabudanwei}",
|
||
"match_rule": "exact_staff_name",
|
||
"submit_blocker_if_unresolved": true
|
||
}
|
||
],
|
||
"selectbox_contract": {
|
||
"row_delimiter": "◇",
|
||
"column_delimiter": "◆",
|
||
"strict_rule": "For SelectBox-bound fields, direct text assignment is not sufficient for production. Runtime must resolve exactly one existing row and apply the page's SetVal mapping.",
|
||
"critical_selectboxes": [
|
||
{
|
||
"name": "trip_days",
|
||
"target": "TianShu",
|
||
"data_source": "static options",
|
||
"match_column": 0,
|
||
"set_values": {
|
||
"TianShu": 0
|
||
}
|
||
},
|
||
{
|
||
"name": "route",
|
||
"target": "zhuanxianming",
|
||
"endpoint": "../dat/AjaxPublicFun.asp?Act=GetInformation&fl=3&fls=1&fabudanwei=${fabudanwei}",
|
||
"observed_row_count": 16,
|
||
"observed_column_count": 11,
|
||
"match_column": 1,
|
||
"set_values": {
|
||
"zhuanxianming": 1,
|
||
"tuanxuhao1": 3
|
||
}
|
||
},
|
||
{
|
||
"name": "product",
|
||
"target": "chanpinming",
|
||
"endpoint": "../dat/AjaxPublicFun.asp?Act=ProGetProductname&fls=1&fabudanwei=${fabudanwei}",
|
||
"observed_row_count": 160,
|
||
"observed_column_count": 2,
|
||
"match_column": 1,
|
||
"set_values": {
|
||
"chanpinming": 1
|
||
},
|
||
"side_effect": "../dat/AjaxPublicFun.asp?Act=GetProduct&cpm=${chanpinming}"
|
||
},
|
||
{
|
||
"name": "customer",
|
||
"target": "zutuanshe",
|
||
"endpoint": "../dat/AjaxPublicFun.asp?Act=ProTravel&fabudanwei=${fabudanwei}",
|
||
"observed_row_count": 93,
|
||
"observed_column_count": 6,
|
||
"match_column": 2,
|
||
"set_values": {
|
||
"bizhong": 0,
|
||
"zutuansheid": 1,
|
||
"zutuanshe": 2,
|
||
"lianxiren": 3,
|
||
"zutuanshegzr": 4
|
||
}
|
||
},
|
||
{
|
||
"name": "staff",
|
||
"targets": ["gendanren", "xiaoshouren"],
|
||
"endpoint": "../dat/AjaxPublicFun.asp?Act=ProDanwei_Yuangong&fabudanwei=${fabudanwei}",
|
||
"observed_row_count": 33,
|
||
"observed_column_count": 2,
|
||
"match_column": 0,
|
||
"set_values": {
|
||
"gendanren": 0,
|
||
"xiaoshouren": 0
|
||
}
|
||
}
|
||
],
|
||
"resource_selectboxes": [
|
||
{
|
||
"name": "flight",
|
||
"target_pattern": "banhao{n}",
|
||
"set_values": {
|
||
"banhao{n}": 1,
|
||
"bancheng{n}": 4,
|
||
"banchengs{n}": 5,
|
||
"banchang{n}": 6,
|
||
"banchangs{n}": 7,
|
||
"banshi{n}": 8,
|
||
"banshis{n}": 9,
|
||
"guankou{n}": 10
|
||
}
|
||
},
|
||
{
|
||
"name": "hotel",
|
||
"target_pattern": "zhusus{day}",
|
||
"observed_row_count": 572,
|
||
"observed_column_count": 5,
|
||
"set_values": {
|
||
"zhusus{day}": 1,
|
||
"zhususs{day}": 2
|
||
}
|
||
},
|
||
{
|
||
"name": "restaurant",
|
||
"target_patterns": ["zaos{day}", "zhongs{day}", "wans{day}"],
|
||
"observed_row_count": 199,
|
||
"observed_column_count": 5,
|
||
"set_values": {
|
||
"selected_restaurant_field": 1,
|
||
"meal_standard_field": 2,
|
||
"settlement_field": 3
|
||
}
|
||
},
|
||
{
|
||
"name": "attraction",
|
||
"target_pattern": "jingdian{day}_{slot}",
|
||
"observed_row_count": 190,
|
||
"observed_column_count": 5,
|
||
"set_values": {
|
||
"jingdian{day}_{slot}": 1,
|
||
"jingdians{day}_{slot}": 2,
|
||
"jingdianss{day}_{slot}": 3
|
||
}
|
||
},
|
||
{
|
||
"name": "receivable_item",
|
||
"target_pattern": "ys_xiangmu{n}",
|
||
"observed_row_count": 20,
|
||
"observed_column_count": 1
|
||
},
|
||
{
|
||
"name": "receivable_detail_or_reserved_resource",
|
||
"target_pattern": "ys_shuoming{n}",
|
||
"observed_row_count": 54,
|
||
"observed_column_count": 3,
|
||
"set_values": {
|
||
"ys_shuoming{n}": 2
|
||
}
|
||
}
|
||
],
|
||
"product_side_effect_contract": {
|
||
"trigger_function": "Find_product()",
|
||
"endpoint": "../dat/AjaxPublicFun.asp?Act=GetProduct&cpm=${chanpinming}",
|
||
"response_type": "script",
|
||
"observed_redacted_sample": {
|
||
"changed_field_count": 135,
|
||
"changed_field_groups": {
|
||
"itinerary_text": 9,
|
||
"core": 7,
|
||
"pricing_receivable": 21,
|
||
"resources": 96,
|
||
"other": 2
|
||
}
|
||
},
|
||
"must_run_before_final_serialize": true,
|
||
"must_block_on_mismatch_fields": [
|
||
"chanpinming",
|
||
"TianShu",
|
||
"zhuanxianming",
|
||
"tuanxuhao1",
|
||
"zutuanshe",
|
||
"zutuansheid"
|
||
],
|
||
"post_effect_overwrite_policy": {
|
||
"preserve_product_template_groups": [
|
||
"itinerary_text",
|
||
"resources"
|
||
],
|
||
"clear_and_rebuild_from_standard_operation": [
|
||
"receivable_rows"
|
||
],
|
||
"overwrite_after_product_effect": [
|
||
"departure date",
|
||
"passenger counts",
|
||
"room counts",
|
||
"staff fields",
|
||
"order suffix",
|
||
"notes",
|
||
"attachments"
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"room_count_fields": {
|
||
"frenshu0": "data.room_counts.SGL",
|
||
"frenshu1": "data.room_counts.TWN",
|
||
"frenshu2": "data.room_counts.TRP",
|
||
"frenshu3": "data.room_counts.DBL",
|
||
"frenshu4": "data.room_counts.HNM",
|
||
"frenshu5": "data.room_counts.TL",
|
||
"frenshu6": "derive_room_total(data.room_counts)"
|
||
},
|
||
"receivable_rows": {
|
||
"source": "data.prices.items",
|
||
"fallback_strategy": "derive_rows_from_passenger_counts_and_category_prices",
|
||
"max_rows": 10,
|
||
"targets": {
|
||
"unit_name": "ys_danwei{n}",
|
||
"unit_id": "ys_danweiid{n}",
|
||
"placeholder": "ys_zhanwei{n}",
|
||
"item_name": "ys_xiangmu{n}",
|
||
"item_detail": "ys_shuoming{n}",
|
||
"settlement_method": "ys_fangshi{n}",
|
||
"currency": "ys_bizhong{n}",
|
||
"quantity": "ys_shuliang{n}",
|
||
"unit_price": "ys_danjia{n}",
|
||
"amount": "ys_jine{n}",
|
||
"paid_amount": "ys_yishoufu{n}",
|
||
"remark": "ys_beizhu{n}",
|
||
"row_id": "ys_id{n}",
|
||
"payment_type": "ys_shoufulei{n}",
|
||
"operator": "ys_caozuoren{n}",
|
||
"reviewer": "ys_shenheren{n}"
|
||
},
|
||
"defaults": {
|
||
"unit_name": "data.customer.name",
|
||
"unit_id": "data.customer.ltjt_id",
|
||
"settlement_method": "",
|
||
"paid_amount": "0",
|
||
"row_id": "",
|
||
"payment_type": "0",
|
||
"operator": "data.source.operator",
|
||
"reviewer": ""
|
||
},
|
||
"amount_formula": "quantity * unit_price"
|
||
},
|
||
"attachments": {
|
||
"source": "data.attachments",
|
||
"target_pattern": "PicFile{n}",
|
||
"requires": "ltjt_file_ref",
|
||
"max": 2,
|
||
"notes": "Local path attachments must be uploaded through LTJT's upload helper before this form payload can reference them."
|
||
},
|
||
"passenger_list": {
|
||
"text_target": "youkexinxis",
|
||
"supported_operations_in_this_mapping": [
|
||
"none"
|
||
],
|
||
"notes": "The real passenger-list import/edit workflow has not been captured yet. Do not treat PicFile0/PicFile1 as passenger-list import."
|
||
},
|
||
"unmapped_or_page_generated_fields": [
|
||
"baojia",
|
||
"zutuanshegzr",
|
||
"caozuoren",
|
||
"ddid",
|
||
"tdid",
|
||
"quanxian",
|
||
"session_id",
|
||
"ys_shenhe",
|
||
"yingfu_jing",
|
||
"yingfu_can",
|
||
"zhusuanpai",
|
||
"daoyoujiesuan",
|
||
"youyingshoukuan",
|
||
"itinerary day/service rows",
|
||
"transport lookup hidden metadata"
|
||
],
|
||
"validation_rules": [
|
||
"submit_mode must be dry_run for this local serializer.",
|
||
"action must be team_order_create.",
|
||
"departure_dates must contain exactly one date.",
|
||
"adult + child_bed + child_no_bed + infant + leader must be greater than zero.",
|
||
"expected_total, when provided, must equal the computed passenger total.",
|
||
"customer, route, product, op_user, and sales_user must be marked resolved by deterministic lookup before submit.",
|
||
"customer, route, product, op_user, and sales_user must each match exactly one existing LTJT SelectBox row at runtime; upstream resolved=true is not enough by itself.",
|
||
"Product Find_product/GetProduct side effects must run in the browser before final serialization.",
|
||
"Product template output must match the standard operation for product, trip, route, route prefix, customer, and customer id.",
|
||
"Product-generated receivable rows must be deliberately preserved or cleared/rebuilt from standard operation prices; this mapping currently clears and rebuilds them.",
|
||
"customer.ltjt_id is required before submit because it maps to zutuansheid and receivable unit ids.",
|
||
"receivable rows must not exceed 10.",
|
||
"attachments must already have ltjt_file_ref values.",
|
||
"passenger_list.operation must be none for this mapping version."
|
||
],
|
||
"next_browser_context_work": [
|
||
"Run browser_order_add_preflight.mjs against a real standard operation whose customer/product/route/staff names exist in LTJT.",
|
||
"Compare product-template output with standard operation and block mismatches instead of overwriting them.",
|
||
"Decide whether resource defaults from product templates are always preserved or whether upstream resource rows must become explicit standard data.",
|
||
"Classify DoInfoJH response scripts on an approved test order before enabling submit mode."
|
||
]
|
||
}
|