certflow.services.dual_code 源代码

"""批次1 双编码:SN 短码 / KKS 长码 派生(B1-1 / B1-2)

背景与定案(reports_migration/notes/vba_replica_audit/README.md 76-86 行):
- B1-ambig(0.2):一般件 kks_code=长 V 码(含YYMM)、sn_code=剥 YYMM 短码;
  电厂件 kks_code=用户 9 位 KKS 清单、sn_code=短 V 码。
- B1-sn-elec(0.4):电厂件 kks_code 来自订单 KKS 清单逐行补录(**非 getKKS 公式生成**),
  getKKS 仅历史特殊规则参考 → 真 KKS 受保护不被编号覆盖。

本模块只负责「字段+生成规则」:
- to_sn_code:   由长 V 码剥离 4 位 YYMM → SN 短码(对齐 VBA 默认模式 sn = code[0]+code[5:])。
- sync_dual_codes: 编号后置,由 product_code 同步 sn_code / kks_code 到 SalePlan。
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from certflow.models.sale_plan import SalePlan

from certflow.utils.logger import get_logger

logger = get_logger()


[文档] def to_sn_code(long_code: str) -> str: """由长 V 码剥离 4 位 YYMM,得到 SN 短码(保留 V + 流水号 + 后缀)。 对齐 VBA 默认编码模式(certificate_print_service._derive_sn_and_kks 默认分支): KKS(长)=完整编码含年月;SN(短)=去掉中间 4 位年月。 例:``V2604520Y`` -> ``V520Y``;``V2606001-V2606005`` -> ``V001-V2606005`` (仅首段去 YYMM,与打印期推导保持一致)。 非 V 码 / 空值原样返回。 Args: long_code: 完整产品编号(如 ``V2604520Y``),一般为 product_code。 Returns: str: SN 短码;输入非法时原样返回(空串返回空串)。 """ if not long_code or not long_code.startswith("V") or len(long_code) <= 5: return long_code or "" # V + 4 位年月(YYMM) + 流水号 + 后缀 → 去掉中间 4 位年月,保留 V + 其余 return long_code[0] + long_code[5:]
def _is_real_kks(value: str) -> bool: """判断是否为用户录入的真 KKS(电厂件),而非自动默认的长 V 码。 真 KKS 来自订单 KKS 清单,不以 ``V`` 开头(KKS 为独立编码),受 :func:`sync_dual_codes` 保护不被编号覆盖。 Args: value: 当前 kks_code 值。 Returns: bool: 为真 KKS 返回 True。 """ return bool(value) and not value.startswith("V")
[文档] def sync_dual_codes(record: SalePlan) -> None: """编号后置:由 product_code 同步 sn_code / kks_code 到 SalePlan。 规则: - ``sn_code`` = 剥 YYMM 短码(:func:`to_sn_code`)。 - ``kks_code`` = 一般件默认=长 V 码(product_code);电厂件已录入的真 KKS (不以 V 开头)**受保护不被覆盖**(B1-sn-elec 0.4)。 Args: record: 已设置 product_code 的 SalePlan ORM 对象(会被就地修改)。 """ long_code = record.product_code or "" # SN 短码始终跟随 product_code 重新推导 record.sn_code = to_sn_code(long_code) # KKS 长码:真 KKS(电厂件)保护;其余(空或既往默认的 V 码)跟随 product_code if _is_real_kks(record.kks_code or ""): logger.debug( f"sync_dual_codes | 真KKS受保护 product_code={long_code!r} " f"sn_code={record.sn_code!r} kks_code={record.kks_code!r}(保留)" ) return record.kks_code = long_code logger.debug( f"sync_dual_codes | product_code={long_code!r} " f"sn_code={record.sn_code!r} kks_code={record.kks_code!r}" )