订单管理
概述
订单管理是指通过从内容库中选择内容,并生成订单,然后进行翻译,最后交付给客户。 一个订单关联以下元素
- 能够从内容库中筛选出内容的查询构建器
- 关联的用于报价语言资产(非必要)
- 用于锁定原文内容的Tag Rules(非必要)
- 服务项目
- 供应商
- 报价单
- 报价协商历史
- 生产过程协商
- 验收协商历史
- 上下文策略
流程
PM在Repository中通过查询构建器筛选出内容,点击创建订单,在预览订单页中选择目标语言,附加的服务项目,报价用语言资产,设置锁定器,然后生成订单。用户进入订单,选择开始报价,弹出符合条件的供应商,选择供应商,开始首轮机器报价,报价需要异步进行,报价完成后,触发通知。PM如果对机器报价无异议,选择认可的供应商,进入本地化生产阶段,如果没有满意的机器报价,则选择需要进一步沟通的供应商,进入协商流程,当前支持一次和一家供应商协商,如果需要和多家供应商协商,则需要退出当前协商阶段,重新选择其他供应商(相当于流程回退,本期暂不实现),在与供应商协商过程中,供应商会根据客户需求,多轮次的生成报价,直至客户对最终报价满意,如果协商一致无法达成一致,用户关闭订单,注意当有进行中的订单时,关联的内容库无法修改,如果通过了协商,则进入生产阶段,生产阶段PM主要的工作是监控进度,生产过程中会有持续的协商过程,直至生产完成,进入验收阶段,验收阶段PM主要的工作是对成果物的预览,相当于在Repository中产生一个预览版本,如果预览无异议,完成验收,预览版本变成正式版本,订单完成,如果验收有异议,则进入协商流程,供应商认可后重新进入生成流程,重复此工作,知道验收完成,进入付款阶段,完成付款后,订单关闭。 补充说明关于上下文策略,用户选择内容进行翻译,但是因为内容库是长期迭代的,如果将整个内容库完全暴露给译员,可能对译员造成困扰,或者参数信息泄露等问题,但是如果仅仅提供部分内容,则可能无法满足翻译需求,所以需要提供一个上下文策略,用于指导译员进行翻译,上下文策略包括:
- 整个库
- 指定翻译的上下各N条
- 仅选定内容(不允许手动获取上下文)
- 仅选定内容(允许手动获取上下文)
手动获取上下文的意思是指,在翻译过程中,译员可以根据需求手动获取上下文。
订单状态与动作
订单状态
- 初始化
订单实体已创建,可以编辑订单信息。
- 报价中
订单信息已确认,正在执行自动报价流程。
- 协商中
报价信息已出,正在等待用户确认最终报价。
- 生产中
订单已确认,正在执行生产流程。
- 验收中
生产成果已提交,正在等待用户验收。
- 付款中
验收通过,正在等待用户付款。
- 已完成
订单已完成。
- 已关闭
订单在未进入生产阶段前,可以随时关闭。
客户视角动作动作
- 生成订单
- 编辑订单
- 开始报价
- 确认报价
- 发起协商
- 确认协商报价
- 发起生产
- 确认验收
- 执行付款
- 关闭订单
供应商视角动作
- 生成协商报价
- 确认生产
- 发起验收
- 发起付款(上传/生成 Invoice)
- 确认付款(上传/生成 Receipt)
完整订单生命周期
报价流程
当订单进入报价阶段,首选通过Snapshot ID, 获取报价对应到的唯一内容服务,内容返回原文,标签化的原文,词数,字数,将内容数据存储在订单服务报价模块中,调用语言资产服务获取每一句话的匹配率区间,调用TMS服务获取供应商的费率配置,折扣配置,通过区间字数 X 区间费率(区间费率 = 区间价 或 基础费率 X 区间折扣)然后计算出总价,得到详细的报价单,报价流程是一个异步任务,任务完成后,将报价单写入数据库,并通知Producer报价完成。
报价流程图
协商(议价)流程
当客户看到报价单后,可以在多家报价中选择一个供应商进行议价,用户点击Request New按钮后,订单状态变为"协商中",并推送消息给供应商,供应商点击订单的报价按钮,可以看到要求重新报价的原因以及可能相关的附件,在此基础上,供应商可以调整订单的TM关联,附加Tag Rules,并生成新的报价单,报价单生成后,供应商可以查看报价详情,如果仍有问题,可以继续调整和生成,觉得无误后,点击Push,客户将收到新的报价,如果客户对此报价满意,则接受报价进入生成阶段,如果仍有异议可以继续点击Request New按钮,此时供应商需要重复刚才的步骤继续生成报价,这个过程可以一直重复,直到客户接受报价或关闭订单。
协商流程图
API 接口设计
1. 订单创建相关接口
1.1 创建订单接口
- 说明:基于内容库筛选结果创建新订单
- 方法:POST
- URL:
/api/v1/orders - 请求示例:
{
"repository_id": "repo_uuid",
"name": "项目名称-20240301",
"query_builder_id": "query_uuid",
"target_languages": ["zh-CN", "ja-JP"],
"service_items": [
{
"type": "translation",
"unit_type": "word",
"currency": "EUR"
},
{
"type": "expedited service",
"currency": "EUR"
}
],
"guidance": "需要尽快完成",
"attachment": [{
"file_id": "file_uuid",
"description": "参考文件-01"
}],
"language_assets": ["asset_uuid1", "asset_uuid2"],
"content_locker_ids": ["locker_uuid1", "locker_uuid2"]
}- 响应示例:
{
"code": 200,
"message": "订单创建成功",
"data": {
"order_id": "order_uuid",
"status": "draft",
"created_at": "2024-03-01T00:00:00Z"
}
}1.2 编辑订单接口
- 说明:编辑草稿状态的订单信息
- 方法:PUT
- URL:
/api/v1/orders/{orderId} - 请求示例:
{
"name": "项目名称-20240301-修改",
"target_languages": ["zh-CN", "ja-JP", "ko-KR"],
"service_items": [
{
"type": "translation",
"unit_type": "word",
"currency": "EUR"
},
{
"type": "expedited service",
"currency": "EUR"
},
{
"type": "desktop publishing",
"currency": "EUR"
}
],
"guidance": "需要尽快完成,并且注意排版要求",
"attachment": [
{
"file_id": "file_uuid1",
"description": "参考文件-01"
},
{
"file_id": "file_uuid2",
"description": "排版规范"
}
],
"language_assets": ["asset_uuid1", "asset_uuid2", "asset_uuid3"],
"content_locker_ids": ["locker_uuid1", "locker_uuid2"]
}- 响应示例:
{
"code": 200,
"message": "订单更新成功",
"data": {
"order_id": "order_uuid",
"status": "draft",
"updated_at": "2024-03-01T00:10:00Z"
}
}2. 报价相关接口
2.1 开始自动报价流程
- 方法:POST
- URL:
/api/v1/orders/{orderId}/quotation/start - 响应示例:
{
"code": 200,
"message": "报价流程已启动",
"data": {
"qualified_vendors": [
{
"vendor_id": ["vendor_uuid1", "vendor_uuid2"]
}
]
}
}2.2 查询机器报价结果
- 方法:GET
- URL:
/api/v1/orders/{orderId}/quotation/machine-quote/{taskId} - 响应示例:
{
"code": 200,
"message": "查询成功",
"data": {
"status": "completed",
"quote_details": {
"total_amount": 1000.00,
"currency": "CNY",
"word_count": {
"source": 5000,
"new": 3000,
"fuzzy": 1500,
"exact": 500
},
"service_breakdown": [
{
"service_type": "translation",
"unit_price": 0.15,
"quantity": 5000,
"amount": 750.00
},
{
"service_type": "review",
"unit_price": 0.05,
"quantity": 5000,
"amount": 250.00
}
]
}
}
}3. 协商相关接口
3.1 发起报价协商
- 方法:POST
- URL:
/api/v1/orders/{orderId}/negotiation/start - 请求示例:
{
"vendor_id": "vendor_uuid",
"message": "期望单价调整",
"expected_price": {
"translation": 0.12,
"review": 0.04
}
}3.2 供应商更新报价
- 方法:POST
- URL:
/api/v1/orders/{orderId}/negotiation/update-quote - 请求示例:
{
"quote_details": {
"service_breakdown": [
{
"service_type": "translation",
"unit_price": 0.13,
"quantity": 5000,
"amount": 650.00
}
]
},
"message": "已调整翻译单价"
}4. 生产阶段接口
4.1 更新生产进度
- 方法:POST
- URL:
/api/v1/orders/{orderId}/production/progress - 请求示例:
{
"progress": 45,
"completed_items": ["content_uuid1", "content_uuid2"],
"message": "已完成45%的翻译工作"
}5. 验收阶段接口
5.1 提交验收
- 方法:POST
- URL:
/api/v1/orders/{orderId}/acceptance/submit - 请求示例:
{
"preview_version": "version_uuid",
"message": "翻译工作已完成,请验收"
}5.2 验收确认
- 方法:POST
- URL:
/api/v1/orders/{orderId}/acceptance/confirm - 请求示例:
{
"status": "accepted",
"message": "验收通过"
}数据库设计
1. 订单主表 (orders)
CREATE TABLE orders (
id VARCHAR(36) PRIMARY KEY,
number VARCHAR(100) NOT NULL COMMENT '订单号',
repository_id VARCHAR(36) NOT NULL COMMENT '关联的内容库ID',
repository_version VARCHAR(36) NOT NULL COMMENT '关联的内容库版本号',
source_language VARCHAR(10) NOT NULL COMMENT '源语言代码',
query_builder_id VARCHAR(36) NOT NULL COMMENT '使用的查询构建器ID',
content_locker_id VARCHAR(255) COMMENT '内容锁定器ID',
status VARCHAR(20) NOT NULL COMMENT '订单状态:draft,quoting,negotiating,producing,reviewing,completed,closed',
workspace_id VARCHAR(36) COMMENT '选定的供应商的Workspace ID',
total_amount DECIMAL(10,2) COMMENT '最终订单应付总金额',
currency VARCHAR(10) DEFAULT 'CNY' COMMENT '币种',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT '创建者ID',
updated_by VARCHAR(36) NOT NULL COMMENT '更新者ID',
INDEX idx_status (status),
INDEX idx_repository (repository_id),
INDEX idx_vendor (workspace_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单主表';2. 订单目标语言表 (order_target_languages)
CREATE TABLE order_target_languages (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
language VARCHAR(10) NOT NULL COMMENT '目标语言代码',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_order_lang (order_id, language),
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单目标语言表';3. 订单服务项目表 (order_service_items)
CREATE TABLE order_service_items (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
service_id VARCHAR(20) NOT NULL COMMENT '服务类型ID',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单服务项目表';4. 订单语言资产关联表 (order_language_assets)
CREATE TABLE order_language_assets (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
asset_id VARCHAR(36) NOT NULL COMMENT '语言资产ID',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_order_asset (order_id, asset_id),
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单语言资产关联表';5. 订单报价历史表 (order_quotation_history)
CREATE TABLE order_quotation_history (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
workspace_id VARCHAR(36) NOT NULL COMMENT '供应商 Workspace ID',
quote_type VARCHAR(20) NOT NULL COMMENT '报价类型:machine,negotiation',
total_amount DECIMAL(10,2) NOT NULL COMMENT '报价总金额',
quote_details JSON COMMENT '报价详情',
message TEXT COMMENT '报价说明',
status VARCHAR(20) NOT NULL COMMENT '报价状态:pending,accepted,rejected',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT '报价发起人ID',
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单报价历史表';6. 订单生产进度表 (order_production_progress)
CREATE TABLE order_production_progress (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
progress INT NOT NULL COMMENT '进度百分比',
completed_items JSON COMMENT '已完成的内容ID列表',
message TEXT COMMENT '进度说明',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT '更新人ID',
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单生产进度表';7. 订单验收记录表 (order_acceptance_records)
CREATE TABLE order_acceptance_records (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
preview_version VARCHAR(36) COMMENT '预览版本ID',
status VARCHAR(20) NOT NULL COMMENT '验收状态:submitted,accepted,rejected',
message TEXT COMMENT '验收说明',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT '操作人ID',
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单验收记录表';8. 订单附加信息表 (order_additional_info)
CREATE TABLE order_additional_info (
id VARCHAR(36) PRIMARY KEY,
order_id VARCHAR(36) NOT NULL,
info_key VARCHAR(255) NOT NULL COMMENT '信息键',
info_value TEXT COMMENT '信息值',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(36) NOT NULL COMMENT '创建者ID',
FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单附加信息表';9. 汇率字典表 (exchange_rates)
用于存储汇率信息。
CREATE TABLE exchange_rates (
exchange_rate_id UUID PRIMARY KEY,
currency_from VARCHAR(10) NOT NULL,
currency_to VARCHAR(10) NOT NULL,
rate DECIMAL(10, 4) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_currency_from FOREIGN KEY (currency_from) REFERENCES currencies(code),
CONSTRAINT fk_currency_to FOREIGN KEY (currency_to) REFERENCES currencies(code)
);