1
0
forked from erp-dev/erp
Files
erpnew/docs/mdy_plate_order_sync.md

170 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MDY明道云PlateOrder 同步:任务 / Command / 数据查询说明
## 这份文档解决什么问题
当你忘记:
- PlateOrder开版数据表是否有定时同步
- 手动怎么跑同步?
- 同步的数据落到哪里、怎么查?
直接看本文档即可。
---
## 一、同步“是什么”:从明道云到哪里?
### 1) 同步目标表(本地暂存)
同步会把明道云“开版数据表”的行写入本地暂存表:
- 模型:`api_v1.models.MDYPlateOrderStaging`
- 字段:
- `mdy_rowid`:明道云 rowid唯一
- `raw`整行原始数据JSON
- `related`可选跨表关联数据list[dict],已做碾平)
- `ctime/utime`:明道云系统时间字段(用于排序/增量)
### 2) 增量游标checkpoint
同步进度记录在:
- 模型:`api_v1.models.DataSync`
- 表名枚举:`DataSync.TableName.PLATE_ORDER`
Command 默认会读取/写入 checkpoint可以通过参数关闭。
---
## 二、有没有“定时任务”Celery Beat
结论:**当前没有把 PlateOrder 同步加入 `CELERY_BEAT_SCHEDULE`**。
目前 `flower/settings.py` 里看到的 mdy 定时任务只有:
- `mdy_product_sync`:每 10 分钟(`api_v1.tasks.sync_mdy_products`
- `mdy_customer_sync`:每 5 分钟(`api_v1.tasks.sync_mdy_customers`
但代码里确实存在 PlateOrder 的 Celery task见下文只是 **未配置到 beat schedule**
---
## 三、如何手动运行推荐management command
### Command`sync_mdy_plate_orders`
入口文件:
- `api_v1/management/commands/sync_mdy_plate_orders.py`
最常用用法:
- 默认增量同步(使用 DataSync checkpoint默认抓关联表数据
- `uv run python manage.py sync_mdy_plate_orders`
常用参数:
- `--page-size 100`:每页拉取条数(默认 100
- `--max-pages 2`:本次最多处理多少页(不是最大页码)
- `--max-records 200`:本次最多处理多少条
- `--with-related / --without-related`:是否抓取跨表关联数据(默认 with-related
- `--max-related-per-type 5`:每种关联表最多拉多少条 rowid
- `--request-interval-seconds 0.02`每次明道云请求之间最小间隔限流0.02≈50qps
- `--use-checkpoint / --skip-checkpoint`:是否读取 DataSync 游标(默认 use
- `--update-checkpoint / --skip-checkpoint-write`:是否写入 DataSync 记录(默认写)
- `--sort-direction asc|desc`:按 ctime 升/降序抓取(默认 asc
示例:
- 只拉主表、不拉关联(更快):
- `uv run python manage.py sync_mdy_plate_orders --without-related`
- 从头全量跑一段(不读 checkpoint且跑完不写 checkpoint
- `uv run python manage.py sync_mdy_plate_orders --skip-checkpoint --skip-checkpoint-write`
- 控制单次任务规模(避免跑太久):
- `uv run python manage.py sync_mdy_plate_orders --page-size 100 --max-pages 3 --max-records 250`
---
## 四、如何通过 Celery 运行(可选)
### Celery Task`api_v1.tasks.sync_mdy_plate_orders`
位置:
- `api_v1/tasks.py`task 名:`sync_mdy_plate_orders`
说明:
- 该 task 内部调用 `api_v1.mdy_plate_order_sync.sync_mdy_plate_orders_to_staging`
- 该 task **目前不在 beat schedule**,但可以手动触发
两种触发方式(任选其一):
1) 通过 celery call适合已有 worker 环境):
- `uv run celery -A flower call api_v1.tasks.sync_mdy_plate_orders --kwargs='{"page_size":100,"max_pages":2,"with_related":true,"request_interval_seconds":0.02}'`
2) 通过 Django shell适合本地临时验证
- `uv run python manage.py shell -c "from api_v1.tasks import sync_mdy_plate_orders; r=sync_mdy_plate_orders.delay(page_size=100,max_pages=2); print(r.id)"`
> 如果你确实需要“定时同步 PlateOrder”可以把该 task 加进 `CELERY_BEAT_SCHEDULE`;但这属于策略选择(数据量/频率/接口限流),当前项目默认没开。
---
## 五、同步后如何查询API
### 暂存查询接口(只读)
文档:
- `docs/api_v1_mdy_plate_order_staging.md`
接口:
- List`GET /api/v1/mdy-plate-order-staging/?limit=20&offset=0`
- Detail`GET /api/v1/mdy-plate-order-staging/{id}/`
说明:
- 支持 LimitOffset 分页
- 支持按“内部字段名”的 query param 过滤(对前端隐藏 JSONField 细节)
---
## 六、相关实现入口(定位用)
- 同步逻辑(写入暂存+checkpoint`api_v1/mdy_plate_order_sync.py`
- 拉取明道云 rows`flower/utils/mingdaoyun/fetch.py``fetch_plate_orders_from_mingdaoyun`
- 明道云客户端:`flower/utils/mingdaoyun/client.py`(当前 appKey/sign 仍是硬编码)
- 暂存查询 API`api_v1/views/mingdaoyun/plate_order_staging.py`
---
## 七、常见报错:`duplicate key value violates ... api_mdy_plate_order_staging_pkey`
### 这到底是哪种“唯一性冲突”?
`api_mdy_plate_order_staging_pkey`**主键id** 的约束名,不是 `mdy_rowid` 的 unique。
这类报错通常意味着:**PostgreSQL 自增序列sequence落后于当前表内的最大 id**(常见于 restore/copy/import 后)。
### 当前代码如何处理
`sync_mdy_plate_orders_to_staging` 在写入暂存表时,如果遇到该主键冲突,会:
- 自动重置该表的 id sequence 到 `MAX(id)`(使下一次插入从 `MAX(id)+1` 开始)
- 然后对当前 row 再重试一次写入
对应实现:`api_v1/mdy_plate_order_sync.py``_reset_mdy_plate_order_staging_id_sequence()`
### 手动修复(可选)
如果你想一次性手动修复,可在 PostgreSQL 执行(把 sequence 名替换为实际值):
```sql
SELECT setval(
pg_get_serial_sequence('api_mdy_plate_order_staging', 'id'),
COALESCE((SELECT MAX(id) FROM api_mdy_plate_order_staging), 1),
true
);
```