Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
wangxiaolu-link-python-clean-data
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
sfa
wangxiaolu-link-python-clean-data
Commits
407f7bc5
提交
407f7bc5
authored
3月 28, 2026
作者:
lidongxu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
完成重构版本:实现清洗售点稽查低价数据的清洗增加入库以及编辑和删除等查询操作
上级
49e50691
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
33 行增加
和
3 行删除
+33
-3
schemas.py
code/api/audit/point_sale/schemas.py
+8
-1
low_price.py
code/py_/audit/point_sale/low_price.py
+18
-1
api.md
docs/api.md
+1
-1
changelog.md
docs/changelog.md
+6
-0
没有找到文件。
code/api/audit/point_sale/schemas.py
浏览文件 @
407f7bc5
...
...
@@ -3,7 +3,7 @@
from
datetime
import
date
from
decimal
import
Decimal
from
pydantic
import
BaseModel
,
Field
from
pydantic
import
BaseModel
,
Field
,
field_validator
class
CleanRequestBody
(
BaseModel
):
...
...
@@ -49,3 +49,10 @@ class RiskAuditVisitReplaceBody(BaseModel):
fresh_status
:
str
|
None
=
Field
(
...
,
max_length
=
20
)
large_date_status
:
str
|
None
=
Field
(
...
,
max_length
=
20
)
large_date_rectify
:
str
|
None
=
Field
(
...
,
max_length
=
100
)
@field_validator
(
"price"
,
"low_price_diff"
,
mode
=
"before"
)
@classmethod
def
_blank_decimal_to_none
(
cls
,
v
):
if
v
is
None
or
v
==
""
:
return
None
return
v
code/py_/audit/point_sale/low_price.py
浏览文件 @
407f7bc5
...
...
@@ -80,6 +80,10 @@ _RAV_EXCEL_SPECS: list[tuple[str, str, Any]] = [
# 与表 uk_biz 列一致:audit_date,source,store_name,channel_type,series,taste,weight,dealer_name
_RAV_UK_BIZ_INDICES
=
(
0
,
1
,
7
,
13
,
14
,
15
,
16
,
5
)
# MySQL 唯一索引中 NULL 互不相等,会导致 ON DUPLICATE KEY 无法合并;空源数据先填占位再入库
_RAV_UK_BIZ_DEFAULT_DATE
=
date
(
1900
,
1
,
1
)
_RAV_UK_BIZ_DEFAULT_STR
=
"-"
_RAV_UK_BIZ_STR_INDICES
=
(
1
,
7
,
13
,
14
,
15
,
16
,
5
)
# uk 中 varchar 列下标(与 _RAV_DB_COLS 对齐)
_RAV_INSERT_SQL
=
(
f
"INSERT INTO risk_audit_visit ({','.join(_RAV_DB_COLS)}) VALUES "
...
...
@@ -131,6 +135,19 @@ def _rav_int(val: Any) -> int | None:
return
int
(
x
)
def
_fill_uk_biz_defaults
(
tup
:
tuple
[
Any
,
...
])
->
tuple
[
Any
,
...
]:
lst
=
list
(
tup
)
if
lst
[
0
]
is
None
:
lst
[
0
]
=
_RAV_UK_BIZ_DEFAULT_DATE
for
i
in
_RAV_UK_BIZ_STR_INDICES
:
if
lst
[
i
]
is
None
:
spec
=
_RAV_EXCEL_SPECS
[
i
][
2
]
mx
=
spec
if
isinstance
(
spec
,
int
)
else
20
s
=
_RAV_UK_BIZ_DEFAULT_STR
[:
mx
]
lst
[
i
]
=
s
return
tuple
(
lst
)
def
_row_to_rav_tuple
(
row
:
pd
.
Series
)
->
tuple
[
Any
,
...
]:
out
:
list
[
Any
]
=
[]
for
_
,
zh
,
spec
in
_RAV_EXCEL_SPECS
:
...
...
@@ -143,7 +160,7 @@ def _row_to_rav_tuple(row: pd.Series) -> tuple[Any, ...]:
out
.
append
(
_rav_int
(
raw
))
else
:
out
.
append
(
_rav_str
(
raw
,
spec
))
return
tuple
(
out
)
return
_fill_uk_biz_defaults
(
tuple
(
out
)
)
def
_uk_biz_from_rav_tuple
(
tup
:
tuple
[
Any
,
...
])
->
tuple
[
Any
,
...
]:
...
...
docs/api.md
浏览文件 @
407f7bc5
...
...
@@ -29,7 +29,7 @@
-
**GET `/api/v1/risk-audit-visit`**
:分页列表。查询参数
`page`
(默认 1)、
`page_size`
(默认 20,最大 200)。成功时
`data`
:
`items`
(行字典数组,含
`rav_id`
与全部业务列)、
`total`
、
`page`
、
`page_size`
;按
`rav_id`
降序。
-
**GET `/api/v1/risk-audit-visit/{rav_id}`**
:单条详情,返回该主键下
**全部字段**
(
`ApiEnvelope.data`
为一条完整记录)。不存在 →
**404**
。
-
**PUT `/api/v1/risk-audit-visit/{rav_id}`**
:按主键
**整行覆盖**
更新。请求体为
**`RiskAuditVisitReplaceBody`**
(与表业务列一致,
**不含**
`rav_id`
;须提交全部字段键,值为 JSON
`null`
表示写入 NULL)。不存在 →
**404**
;违反唯一键
`uk_biz`
→
**409**
;库连接等失败 →
**502**
。
-
**PUT `/api/v1/risk-audit-visit/{rav_id}`**
:按主键
**整行覆盖**
更新。请求体为
**`RiskAuditVisitReplaceBody`**
(与表业务列一致,
**不含**
`rav_id`
;须提交全部字段键,值为 JSON
`null`
表示写入 NULL)。
`price`
、
`low_price_diff`
若前端传空字符串
`""`
,与
`null`
同等视为写入 NULL。
不存在 →
**404**
;违反唯一键
`uk_biz`
→
**409**
;库连接等失败 →
**502**
。
-
**DELETE `/api/v1/risk-audit-visit/{rav_id}`**
:按主键删除。不存在 →
**404**
。
连接参数同清洗写库:
`Settings.mysql_connect_kwargs()`
(见
[
database.md
](
database.md
)
)。
...
...
docs/changelog.md
浏览文件 @
407f7bc5
...
...
@@ -2,8 +2,14 @@
按时间倒序记录重要约定与行为变化,便于以后查阅;细节仍以各模块文档与代码为准。
## 2026-03-28
-
**`PUT /api/v1/risk-audit-visit/{rav_id}`**
:
`RiskAuditVisitReplaceBody`
中
`price`
、
`low_price_diff`
在 Pydantic 层将 JSON 空字符串
`""`
规范为
`None`
,避免前端用空串占位时触发
`decimal_parsing`
422;语义与
`null`
一致(写入 NULL)。
## 2026-03-27
-
**`risk_audit_visit` 写入**
:
`code/py_/audit/point_sale/low_price.py`
在组行入库前,对唯一键
`uk_biz`
八列中空值填占位(日期
`1900-01-01`
、字符串
`-`
),避免 MySQL 唯一索引对
`NULL`
不判等导致重复插入。
-
**`POST /api/v1/clean` 统计语义**
:
`merged_rows`
仍为
**合并后物理总行数**
;
`risk_audit_visit_rows`
表示按
`uk_biz`
去重后的有效入库行数(同键多行仅最后一行留在库);
`risk_audit_visit_collapsed_duplicate_rows`
为「合并待写总行数 − 去重键数」。
-
**脚本清理**
:删除一次性 Navicat 备份转换脚本
**`scripts/transform_rav_backup_sql.py`**
(仓库内无其它引用)。
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论