fix: 批次统计修复小/大日期反向并增强除零兜底
- 三个 batch_*erp 脚本将 小日期=min、大日期=max,与中文语义一致 - get_f_l_date 改为先解析为 date 再比较,移除对字符串字典序的依赖 - 合格率/直通率兜底 except 同时捕获 decimal.InvalidOperation 与 ZeroDivisionError - 新增 batch_gxerp.md 整理计算规则与字段 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3129cc0e54
commit
13c9d8a258
|
|
@ -68,12 +68,12 @@ def main(batch: str, mgroup_obj:Mgroup=None):
|
|||
|
||||
try:
|
||||
data[f"{mgroup_name}_完全合格率"] = round((data[f"{mgroup_name}_count_ok_full"] / data[f"{mgroup_name}_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data[f"{mgroup_name}_完全合格率"] = 0
|
||||
|
||||
try:
|
||||
data[f"{mgroup_name}_合格率"] = round((data[f"{mgroup_name}_count_ok"] / data[f"{mgroup_name}_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data[f"{mgroup_name}_合格率"] = 0
|
||||
|
||||
mlogbd1_qs = MlogbDefect.objects.filter(mlogb__in=mlogb1_qs, count__gt=0).values("defect__name").annotate(total=Sum("count"))
|
||||
|
|
@ -93,8 +93,8 @@ def main(batch: str, mgroup_obj:Mgroup=None):
|
|||
data[f"{mgroup_name}_含缺陷_{item['defect__name']}_比例"] = round((item["total"] / data[f"{mgroup_name}_count_real"])*100, 2)
|
||||
|
||||
data[f"{mgroup_name}_日期"] = list(set(data[f"{mgroup_name}_日期"]))
|
||||
data[f"{mgroup_name}_小日期"] = max(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_大日期"] = min(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_小日期"] = min(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_大日期"] = max(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data[f"{mgroup_name}_日期"]])
|
||||
data[f"{mgroup_name}_操作人"] = list(set(data[f"{mgroup_name}_操作人"]))
|
||||
data[f"{mgroup_name}_操作人"] = ";".join([item.name for item in data[f"{mgroup_name}_操作人"]])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
# batch_gxerp.py 批次统计计算规则
|
||||
|
||||
`apps/wpm/scripts/batch_gxerp.py` 用于按 **批次号 (batch)** 汇总该批次在各工序组下的生产/检验数据,写入 `BatchSt.data` (JSON),同时维护 `first_time` / `last_time`。
|
||||
|
||||
---
|
||||
|
||||
## 一、入参与前置条件
|
||||
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| `batch` | 批次号 |
|
||||
| `mgroup_obj` | 工序组对象(当前实现未直接使用,仅作为入口签名) |
|
||||
|
||||
- 必须存在 `BatchSt.objects.get(batch=batch, version=1)`,否则报错并退出。
|
||||
- 遍历 `Mgroup.objects.all().order_by("sort")`,对每个工序组分别统计。
|
||||
- 仅统计已提交且已出库的报工单:`mlog.submit_time__isnull=False` 且 `material_out__isnull=False`,并要求 `need_inout=True`。
|
||||
|
||||
---
|
||||
|
||||
## 二、字段命名约定
|
||||
|
||||
输出 JSON `data` 的 key 形式如下(`<G>` 代表工序组名):
|
||||
|
||||
| Key 模式 | 含义 |
|
||||
| --- | --- |
|
||||
| `批次号` | 批次号 |
|
||||
| `<G>_日期` | 该工序组所有报工日期,去重后 `;` 拼接 |
|
||||
| `<G>_小日期` / `<G>_大日期` | 该工序组最早 / 最晚日期(`YYYY-MM-DD`) |
|
||||
| `<G>_操作人` | 操作人姓名去重后 `;` 拼接 |
|
||||
| `<G>_班次` | 班次名去重后 `;` 拼接 |
|
||||
| `<G>_count_use` | 领用数(来自上游 `mlogb_from`) |
|
||||
| `<G>_count_real` | 实际生产数 |
|
||||
| `<G>_count_ok` | 合格数 |
|
||||
| `<G>_count_notok` | 不合格数 |
|
||||
| `<G>_count_ok_full` | 完全合格数 |
|
||||
| `<G>_count_pn_jgqbl` | 加工前不良数(来自上游 `mlogb_from`) |
|
||||
| `<G>_合格率` | 合格率(%) |
|
||||
| `<G>_完全合格率` | 完全合格率(%) |
|
||||
| `<G>_缺陷_<缺陷名>` | 该工序组的缺陷数量(按缺陷名汇总) |
|
||||
| `<G>_缺陷_<缺陷名>_比例` | 缺陷数 / `count_real` × 100,单位 % |
|
||||
| `<G>_加工前_缺陷_<缺陷名>` | 上游 `mlogb_from` 上的缺陷数量 |
|
||||
| `<G>_加工前_缺陷_<缺陷名>_比例` | 加工前缺陷数 / `count_use` × 100,单位 % |
|
||||
|
||||
---
|
||||
|
||||
## 三、主流程:按工序组汇总(普通报工,`is_fix=False`)
|
||||
|
||||
数据源 `mlogb1_qs`:
|
||||
|
||||
```
|
||||
Mlogb where mlog.submit_time IS NOT NULL
|
||||
and material_out IS NOT NULL
|
||||
and mlog.mgroup = <G>
|
||||
and mlog.is_fix = False
|
||||
and batch = <batch>
|
||||
and need_inout = True
|
||||
```
|
||||
|
||||
### 1. 累加规则
|
||||
|
||||
对每条 `Mlogb`:
|
||||
|
||||
| 字段 | 累加来源 |
|
||||
| --- | --- |
|
||||
| `count_use` | `mlogb_from.count_use`(上游报工子项;若无 `mlogb_from` 则跳过) |
|
||||
| `count_pn_jgqbl` | `mlogb_from.count_pn_jgqbl` |
|
||||
| `count_real` | 当前 `item.count_real` |
|
||||
| `count_ok` | 当前 `item.count_ok` |
|
||||
| `count_ok_full` | 当前 `item.count_ok_full or 0` |
|
||||
| `count_notok` | 当前 `item.count_notok or 0` |
|
||||
| `操作人` | `mlog.handle_user`(最终去重,按 `name` 拼接) |
|
||||
| `日期` | `mlog.handle_date`(最终去重排序) |
|
||||
| `班次` | `mlog.shift.name` |
|
||||
|
||||
并记录所有上游 `mlogb_from.id` 到 `mlogb_q_ids`,用于"加工前缺陷"统计。
|
||||
|
||||
### 2. 合格率计算
|
||||
|
||||
```
|
||||
完全合格率 = round(count_ok_full / count_real * 100, 2)
|
||||
合格率 = round(count_ok / count_real * 100, 2)
|
||||
```
|
||||
|
||||
`decimal.InvalidOperation` 异常时(如分母为 0)记 `0`。
|
||||
|
||||
### 3. 缺陷统计
|
||||
|
||||
- 当前工序缺陷:`MlogbDefect.filter(mlogb__in=mlogb1_qs, count__gt=0).values('defect__name').annotate(total=Sum('count'))`
|
||||
- `<G>_缺陷_<name>` = total
|
||||
- `<G>_缺陷_<name>_比例` = `round(total / count_real * 100, 2)`
|
||||
- 加工前(上游)缺陷:`MlogbDefect.filter(mlogb__id__in=mlogb_q_ids, count__gt=0)...`
|
||||
- `<G>_加工前_缺陷_<name>` = total
|
||||
- `<G>_加工前_缺陷_<name>_比例` = `round(total / count_use * 100, 2)`
|
||||
|
||||
### 4. 日期字段
|
||||
|
||||
```python
|
||||
data[f"{G}_小日期"] = min(日期列表).strftime("%Y-%m-%d") # 最早日期
|
||||
data[f"{G}_大日期"] = max(日期列表).strftime("%Y-%m-%d") # 最晚日期
|
||||
```
|
||||
|
||||
最终 `<G>_日期` 被覆写为去重排序后的字符串(`;` 拼接)。
|
||||
|
||||
---
|
||||
|
||||
## 四、外观检验返修(`is_fix=True`)
|
||||
|
||||
数据源 `mlogb2_qs`:
|
||||
|
||||
```
|
||||
Mlogb where mlog.submit_time IS NOT NULL
|
||||
and material_out IS NOT NULL
|
||||
and mlog.mgroup.name = '外观检验'
|
||||
and mlog.is_fix = True
|
||||
and batch = <batch>
|
||||
and need_inout = True
|
||||
```
|
||||
|
||||
输出字段:
|
||||
|
||||
| Key | 计算 |
|
||||
| --- | --- |
|
||||
| `外观检验_返修_日期` | 报工日期,去重 `;` 拼接 |
|
||||
| `外观检验_返修_操作人` | 操作人姓名,去重 `;` 拼接 |
|
||||
| `外观检验_返修_count_real` | Σ `count_real` |
|
||||
| `外观检验_返修_count_ok` | Σ `count_ok` |
|
||||
| `外观检验_返修_count_ok_full` | Σ `count_ok_full or 0` |
|
||||
| `外观检验_返修_缺陷_<name>` | `MlogbDefect` 按缺陷名汇总 |
|
||||
| `外观检验_返修_缺陷_<name>_比例` | `round(total / 外观检验_返修_count_real * 100, 2)` |
|
||||
|
||||
---
|
||||
|
||||
## 五、外观检验车间库存抽检
|
||||
|
||||
数据源 `ft_qs`:
|
||||
|
||||
```
|
||||
FtestWork where type2 = TYPE2_SOME
|
||||
and wm.mgroup.name = '外观检验'
|
||||
and batch = <batch>
|
||||
and submit_time IS NOT NULL
|
||||
```
|
||||
|
||||
输出字段:
|
||||
|
||||
| Key | 计算 |
|
||||
| --- | --- |
|
||||
| `外观检验_车间库存抽检_日期` | `test_date` 去重 `;` 拼接 |
|
||||
| `外观检验_车间库存抽检_操作人` | `test_user.name` 去重 `;` 拼接 |
|
||||
| `外观检验_车间库存抽检_count_notok` | Σ `count_notok or 0` |
|
||||
| `外观检验_车间库存抽检_缺陷_<name>` | `FtestworkDefect` 按缺陷名汇总(无比例字段) |
|
||||
|
||||
---
|
||||
|
||||
## 六、外观检验汇总指标(仅当存在 `外观检验_count_ok` 时计算)
|
||||
|
||||
| Key | 公式 |
|
||||
| --- | --- |
|
||||
| `外观检验_总合格数` | `外观检验_count_ok + 外观检验_返修_count_ok(默认0)` |
|
||||
| `外观检验_总合格率` | `round(外观检验_总合格数 / 外观检验_count_real * 100, 2)` |
|
||||
| `外观检验_完全总合格数` | `外观检验_count_ok_full + 外观检验_返修_count_ok_full(默认0)` |
|
||||
| `外观检验_完全总合格率` | `round(外观检验_完全总合格数 / 外观检验_count_real * 100, 2)` |
|
||||
| `外观检验_直通合格数` | `外观检验_总合格数 - 外观检验_车间库存抽检_count_notok(默认0)` |
|
||||
|
||||
### 直通合格率(依赖尺寸检验)
|
||||
|
||||
仅当 `尺寸检验_合格率` 存在时:
|
||||
|
||||
```
|
||||
外观检验_直通合格率 = round(外观检验_总合格率 * 尺寸检验_合格率 / 100, 2)
|
||||
外观检验_直通合格率2 = round(外观检验_直通合格数 / 尺寸检验_count_use * 100, 2)
|
||||
```
|
||||
|
||||
仅当 `尺寸检验_完全合格率` 存在时:
|
||||
|
||||
```
|
||||
外观检验_完全直通合格率 = round(外观检验_完全总合格率 * 尺寸检验_完全合格率 / 100, 2)
|
||||
```
|
||||
|
||||
异常(`InvalidOperation` / `ZeroDivisionError`)回退为 `0`。
|
||||
|
||||
---
|
||||
|
||||
## 七、写回 BatchSt
|
||||
|
||||
1. `data` 经 `MyJSONEncoder` 序列化后回填 `batchst.data`。
|
||||
2. 调 `get_f_l_date(data)`:扫描所有以 `_日期` 结尾的字段,按 `;` 拆开后逐个 `datetime.strptime("%Y-%m-%d")` 解析为 `date` 对象,再取最小/最大并转成上海时区的 `00:00:00` / `23:59:59`,得到 `first_time` / `last_time`。无法解析的片段会写日志并跳过。
|
||||
3. 仅当现有 `first_time` 为空或新值更早时更新;`last_time` 反之。
|
||||
4. 调用 `batchst.save()` 持久化。
|
||||
|
||||
---
|
||||
|
||||
## 八、关键依赖与字段含义速查
|
||||
|
||||
| 模型字段 | 中文释义 | 来源 |
|
||||
| --- | --- | --- |
|
||||
| `Mlogb.count_use` | 领用数 | 报工子项(来自 `mlogb_from`) |
|
||||
| `Mlogb.count_real` | 实际生产数 | 报工子项 |
|
||||
| `Mlogb.count_ok` | 合格数 | `count_real - count_notok` |
|
||||
| `Mlogb.count_ok_full` | 完全合格数 | `count_real - count_notok_full` |
|
||||
| `Mlogb.count_notok` | 不合格数 | 缺陷 `okcate=30` 求和 |
|
||||
| `Mlogb.count_pn_jgqbl` | 加工前不良 | `MlogbDefect` 中加工前不良求和 |
|
||||
| `Mlogb.need_inout` | 是否需出入库 | 仅 `True` 参与统计 |
|
||||
| `Mlogb.mlogb_from` | 上游报工子项 | 用于追溯领用与加工前缺陷 |
|
||||
|
||||
---
|
||||
|
||||
## 九、已知潜在问题
|
||||
|
||||
1. **`mgroup_obj` 入参未使用**:当前实现忽略该参数,对所有 `Mgroup` 全量遍历。
|
||||
|
||||
## 十、修订记录
|
||||
|
||||
- 修复 `小日期 / 大日期` 命名与含义反向,`小日期` 取最早日期、`大日期` 取最晚日期;同步修正 `batch_bxerp.py`、`batch_gzerp.py` 中所有同类字段。
|
||||
- `get_f_l_date` 改为先 `datetime.strptime` 解析为 `date` 对象再比较,移除对字符串字典序的隐式依赖;非法日期片段记录日志后跳过。
|
||||
- 所有合格率/直通率计算的兜底 `except` 同时捕获 `decimal.InvalidOperation` 与 `ZeroDivisionError`,以兼容 `Decimal` 与原生数值的除零场景;`batch_bxerp.py` 与 `batch_gzerp.py` 中仅捕获 `decimal.InvalidOperation` 的合格率分支也同步扩展。
|
||||
|
|
@ -57,12 +57,12 @@ def main(batch: str, mgroup_obj):
|
|||
|
||||
try:
|
||||
data[f"{mgroup_name}_完全合格率"] = round((data[f"{mgroup_name}_count_ok_full"] / data[f"{mgroup_name}_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data[f"{mgroup_name}_完全合格率"] = 0
|
||||
|
||||
try:
|
||||
data[f"{mgroup_name}_合格率"] = round((data[f"{mgroup_name}_count_ok"] / data[f"{mgroup_name}_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data[f"{mgroup_name}_合格率"] = 0
|
||||
|
||||
mlogbd1_qs = MlogbDefect.objects.filter(mlogb__in=mlogb1_qs, count__gt=0).values("defect__name").annotate(total=Sum("count"))
|
||||
|
|
@ -78,8 +78,8 @@ def main(batch: str, mgroup_obj):
|
|||
|
||||
data[f"{mgroup_name}_日期"] = list(set(data[f"{mgroup_name}_日期"]))
|
||||
data[f"{mgroup_name}_日期"].sort()
|
||||
data[f"{mgroup_name}_小日期"] = max(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_大日期"] = min(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_小日期"] = min(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_大日期"] = max(data[f"{mgroup_name}_日期"]).strftime("%Y-%m-%d")
|
||||
data[f"{mgroup_name}_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data[f"{mgroup_name}_日期"]])
|
||||
data[f"{mgroup_name}_操作人"] = list(set(data[f"{mgroup_name}_操作人"]))
|
||||
data[f"{mgroup_name}_操作人"] = ";".join([item.name for item in data[f"{mgroup_name}_操作人"]])
|
||||
|
|
@ -144,20 +144,20 @@ def main(batch: str, mgroup_obj):
|
|||
data["外观检验_总合格数"] = data["外观检验_count_ok"] + data.get("外观检验_返修_count_ok", 0)
|
||||
try:
|
||||
data["外观检验_总合格率"] = round((data["外观检验_总合格数"] / data["外观检验_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data["外观检验_总合格率"] = 0
|
||||
|
||||
data["外观检验_完全总合格数"] = data["外观检验_count_ok_full"] + data.get("外观检验_返修_count_ok_full", 0)
|
||||
try:
|
||||
data["外观检验_完全总合格率"] = round((data["外观检验_完全总合格数"] / data["外观检验_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data["外观检验_完全总合格率"] = 0
|
||||
|
||||
data["外观检验_直通合格数"] = data["外观检验_总合格数"] - data.get("外观检验_车间库存抽检_count_notok", 0)
|
||||
if "尺寸检验_合格率" in data:
|
||||
try:
|
||||
data["外观检验_直通合格率"] = round((data["外观检验_总合格率"]* data["尺寸检验_合格率"])/100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data["外观检验_直通合格率"] = 0
|
||||
|
||||
try:
|
||||
|
|
@ -168,7 +168,7 @@ def main(batch: str, mgroup_obj):
|
|||
if "尺寸检验_完全合格率" in data:
|
||||
try:
|
||||
data["外观检验_完全直通合格率"] = round((data["外观检验_完全总合格率"]* data["尺寸检验_完全合格率"])/100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
data["外观检验_完全直通合格率"] = 0
|
||||
|
||||
res = get_f_l_date(data)
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data["棒料成型_切料人"] = ";".join([item.name for item in data["棒料成型_切料人"]])
|
||||
data["棒料成型_日期"] = list(set(data["棒料成型_日期"]))
|
||||
data["棒料成型_日期"].sort()
|
||||
data["棒料成型_小日期"] = max(data["棒料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["棒料成型_大日期"] = min(data["棒料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["棒料成型_小日期"] = min(data["棒料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["棒料成型_大日期"] = max(data["棒料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["棒料成型_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["棒料成型_日期"]])
|
||||
try:
|
||||
data["棒料成型_合格率"] = round((data["棒料成型_count_ok"] * 100/ data["棒料成型_count_real"]), 1)
|
||||
|
|
@ -95,8 +95,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data["管料成型_合格率"] = round((data["管料成型_count_ok"] * 100 / data["管料成型_count_real"]), 1)
|
||||
data["管料成型_日期"] = list(set(data["管料成型_日期"]))
|
||||
data["管料成型_日期"].sort()
|
||||
data["管料成型_小日期"] = max(data["管料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料成型_大日期"] = min(data["管料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料成型_小日期"] = min(data["管料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料成型_大日期"] = max(data["管料成型_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料成型_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["管料成型_日期"]])
|
||||
|
||||
# 7车间生产入库数据/ 8车间中检数据
|
||||
|
|
@ -127,8 +127,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data["七车间入库_合格率"] = round((data["七车间入库_count"] - data["七车间入库_count_notok"]) * 100/ data["七车间入库_count"], 1)
|
||||
data["七车间入库_日期"] = list(set(data["七车间入库_日期"]))
|
||||
data["七车间入库_日期"].sort()
|
||||
data["七车间入库_小日期"] = max(data["七车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["七车间入库_大日期"] = min(data["七车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["七车间入库_小日期"] = min(data["七车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["七车间入库_大日期"] = max(data["七车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["七车间入库_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["七车间入库_日期"]])
|
||||
data["七车间入库_车间执行人"] = list(set(data["七车间入库_车间执行人"]))
|
||||
data["七车间入库_车间执行人"] = ";".join([item.name for item in data["七车间入库_车间执行人"]])
|
||||
|
|
@ -168,8 +168,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data["十车间入库_仓库执行人"] = ";".join([item.name for item in data["十车间入库_仓库执行人"]])
|
||||
data["十车间入库_日期"] = list(set(data["十车间入库_日期"]))
|
||||
data["十车间入库_日期"].sort()
|
||||
data["十车间入库_小日期"] = max(data["十车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["十车间入库_大日期"] = min(data["十车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["十车间入库_小日期"] = min(data["十车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["十车间入库_大日期"] = max(data["十车间入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["十车间入库_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["十车间入库_日期"]])
|
||||
data["十车间入库_合格数"] = data["十车间入库_count"] - data["十车间入库_count_notok"]
|
||||
data["十车间入库_合格率"] = round((data["十车间入库_count"] - data["十车间入库_count_notok"]) * 100/ data["十车间入库_count"], 1)
|
||||
|
|
@ -222,8 +222,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data[f'管料退火_{field}'] += getattr(item, field)
|
||||
data["管料退火_日期"] = list(set(data["管料退火_日期"]))
|
||||
data["管料退火_日期"].sort()
|
||||
data["管料退火_小日期"] = max(data["管料退火_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料退火_大日期"] = min(data["管料退火_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料退火_小日期"] = min(data["管料退火_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料退火_大日期"] = max(data["管料退火_日期"]).strftime("%Y-%m-%d")
|
||||
data["管料退火_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["管料退火_日期"]])
|
||||
data["管料退火_操作人"] = list(set(data["管料退火_操作人"]))
|
||||
data["管料退火_操作人"] = ";".join([item.name for item in data["管料退火_操作人"]])
|
||||
|
|
@ -257,8 +257,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data[f'六车间领料_{field}'] += getattr(item, field)
|
||||
data["六车间领料_日期"] = list(set(data["六车间领料_日期"]))
|
||||
data["六车间领料_日期"].sort()
|
||||
data["六车间领料_小日期"] = max(data["六车间领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间领料_大日期"] = min(data["六车间领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间领料_小日期"] = min(data["六车间领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间领料_大日期"] = max(data["六车间领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间领料_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["六车间领料_日期"]])
|
||||
data["六车间领料_仓库执行人"] = list(set(data["六车间领料_仓库执行人"]))
|
||||
data["六车间领料_仓库执行人"] = ";".join([item.name for item in data["六车间领料_仓库执行人"]])
|
||||
|
|
@ -283,8 +283,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data["六车间交接领料_接料人"].append(item.recive_user)
|
||||
data["六车间交接领料_日期"] = list(set(data["六车间交接领料_日期"]))
|
||||
data["六车间交接领料_日期"].sort()
|
||||
data["六车间交接领料_小日期"] = max(data["六车间交接领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间交接领料_大日期"] = min(data["六车间交接领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间交接领料_小日期"] = min(data["六车间交接领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间交接领料_大日期"] = max(data["六车间交接领料_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间交接领料_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["六车间交接领料_日期"]])
|
||||
data["六车间交接领料_送料人"] = list(set(data["六车间交接领料_送料人"]))
|
||||
data["六车间交接领料_送料人"] = ";".join([item.name for item in data["六车间交接领料_送料人"]])
|
||||
|
|
@ -320,14 +320,14 @@ def main(batch: str, mgroup_obj=None):
|
|||
data[f'六车间_{mgroup_name}_{field}'] += getattr(item, field)
|
||||
data[f'六车间_{mgroup_name}_日期'] = list(set(data[f'六车间_{mgroup_name}_日期']))
|
||||
data[f'六车间_{mgroup_name}_日期'].sort()
|
||||
data[f'六车间_{mgroup_name}_小日期'] = max(data[f'六车间_{mgroup_name}_日期']).strftime("%Y-%m-%d")
|
||||
data[f'六车间_{mgroup_name}_大日期'] = min(data[f'六车间_{mgroup_name}_日期']).strftime("%Y-%m-%d")
|
||||
data[f'六车间_{mgroup_name}_小日期'] = min(data[f'六车间_{mgroup_name}_日期']).strftime("%Y-%m-%d")
|
||||
data[f'六车间_{mgroup_name}_大日期'] = max(data[f'六车间_{mgroup_name}_日期']).strftime("%Y-%m-%d")
|
||||
data[f'六车间_{mgroup_name}_日期'] = ";".join([item.strftime("%Y-%m-%d") for item in data[f'六车间_{mgroup_name}_日期']])
|
||||
data[f'六车间_{mgroup_name}_操作人'] = list(set(data[f'六车间_{mgroup_name}_操作人']))
|
||||
data[f'六车间_{mgroup_name}_操作人'] = ";".join([item.name for item in data[f'六车间_{mgroup_name}_操作人']])
|
||||
try:
|
||||
data[f'六车间_{mgroup_name}_合格率'] = round(data[f'六车间_{mgroup_name}_count_ok'] * 100/ data[f'六车间_{mgroup_name}_count_real'], 1)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
# myLogger.error(f"六车间_{mgroup_name}_合格率decimal.InvalidOperation-{data}")
|
||||
data[f'六车间_{mgroup_name}_合格率'] = 0
|
||||
|
||||
|
|
@ -359,8 +359,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data[f'六车间中检_{field}'] += getattr(item, field)
|
||||
data["六车间中检_日期"] = list(set(data["六车间中检_日期"]))
|
||||
data["六车间中检_日期"].sort()
|
||||
data["六车间中检_小日期"] = max(data["六车间中检_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间中检_大日期"] = min(data["六车间中检_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间中检_小日期"] = min(data["六车间中检_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间中检_大日期"] = max(data["六车间中检_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间中检_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["六车间中检_日期"]])
|
||||
data['六车间中检_检验人'] = list(set(data['六车间中检_检验人']))
|
||||
data['六车间中检_检验人'] = ";".join([item.name for item in data['六车间中检_检验人']])
|
||||
|
|
@ -395,7 +395,7 @@ def main(batch: str, mgroup_obj=None):
|
|||
data['六车间生产入库_检验人'] = ";".join([item.name for item in data['六车间生产入库_检验人']])
|
||||
try:
|
||||
data['六车间生产入库_合格率'] = round((data['六车间生产入库_count'] - data['六车间生产入库_count_notok']) * 100/ data['六车间生产入库_count'], 1)
|
||||
except decimal.InvalidOperation:
|
||||
except (decimal.InvalidOperation, ZeroDivisionError):
|
||||
# myLogger.error("六车间生产入库_合格率decimal.InvalidOperation-{data}")
|
||||
data['六车间生产入库_合格率'] = 0
|
||||
|
||||
|
|
@ -419,8 +419,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
if "六车间生产入库_日期" in data:
|
||||
data["六车间生产入库_日期"] = list(set(data["六车间生产入库_日期"]))
|
||||
data["六车间生产入库_日期"].sort()
|
||||
data["六车间生产入库_小日期"] = max(data["六车间生产入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间生产入库_大日期"] = min(data["六车间生产入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间生产入库_小日期"] = min(data["六车间生产入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间生产入库_大日期"] = max(data["六车间生产入库_日期"]).strftime("%Y-%m-%d")
|
||||
data["六车间生产入库_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["六车间生产入库_日期"]])
|
||||
|
||||
# 成品检验数据
|
||||
|
|
@ -497,8 +497,8 @@ def main(batch: str, mgroup_obj=None):
|
|||
data['销售发货_仓库执行人'] = ";".join([item.name for item in data['销售发货_仓库执行人']])
|
||||
data["销售发货_日期"] = list(set(data["销售发货_日期"]))
|
||||
data["销售发货_日期"].sort()
|
||||
data["销售发货_小日期"] = max(data["销售发货_日期"]).strftime("%Y-%m-%d")
|
||||
data["销售发货_大日期"] = min(data["销售发货_日期"]).strftime("%Y-%m-%d")
|
||||
data["销售发货_小日期"] = min(data["销售发货_日期"]).strftime("%Y-%m-%d")
|
||||
data["销售发货_大日期"] = max(data["销售发货_日期"]).strftime("%Y-%m-%d")
|
||||
data["销售发货_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["销售发货_日期"]])
|
||||
|
||||
# if data.get("六车间领料_count", 0) > 0 or data.get("六车间交接领料_count", 0) > 0:
|
||||
|
|
|
|||
|
|
@ -65,16 +65,25 @@ def get_f_l_date(data):
|
|||
if v:
|
||||
if isinstance(v, list):
|
||||
myLogger.error(f"get_f_l_date {k} {v}")
|
||||
v = v.split(";")
|
||||
if first_date is None:
|
||||
first_date = min(v)
|
||||
else:
|
||||
first_date = min(first_date, min(v))
|
||||
if last_date is None:
|
||||
last_date = max(v)
|
||||
else:
|
||||
last_date = max(last_date, max(v))
|
||||
return {"first_date": first_date,
|
||||
"last_date": last_date,
|
||||
"first_time": datetime.strptime(f"{first_date} 00:00:00", "%Y-%m-%d %H:%M:%S").replace(tzinfo=tz_shanghai) if first_date else None,
|
||||
"last_time": datetime.strptime(f"{last_date} 23:59:59", "%Y-%m-%d %H:%M:%S").replace(tzinfo=tz_shanghai) if last_date else None}
|
||||
continue
|
||||
dates = []
|
||||
for s in v.split(";"):
|
||||
s = s.strip()
|
||||
if not s:
|
||||
continue
|
||||
try:
|
||||
dates.append(datetime.strptime(s, "%Y-%m-%d").date())
|
||||
except ValueError:
|
||||
myLogger.error(f"get_f_l_date invalid date {k} {s}")
|
||||
if not dates:
|
||||
continue
|
||||
cur_min = min(dates)
|
||||
cur_max = max(dates)
|
||||
if first_date is None or cur_min < first_date:
|
||||
first_date = cur_min
|
||||
if last_date is None or cur_max > last_date:
|
||||
last_date = cur_max
|
||||
return {"first_date": first_date.strftime("%Y-%m-%d") if first_date else None,
|
||||
"last_date": last_date.strftime("%Y-%m-%d") if last_date else None,
|
||||
"first_time": datetime.combine(first_date, datetime.min.time()).replace(tzinfo=tz_shanghai) if first_date else None,
|
||||
"last_time": datetime.combine(last_date, datetime.max.time().replace(microsecond=0)).replace(tzinfo=tz_shanghai) if last_date else None}
|
||||
|
|
|
|||
Loading…
Reference in New Issue