Files
zkxw/backend/tests/test_protocol_operation_log.py
T
zlwuandCursor ac9db561a4 fix(web-admin): 补齐捐赠查看操作日志接线并保留审核动作语义
修复 DonationViewDialog 缺失的操作日志状态与加载调用,清理误插入的重置语句,并避免显式 audit 动作被状态映射覆盖。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-05 12:15:10 +08:00

149 lines
4.5 KiB
Python

"""Issue #24:协议操作过程日志 append-only 与动作映射。"""
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
def _session():
from app.models.models import (
BizCollectionProtocol,
BizProtocolCollectionInfo,
BizProtocolOperationLog,
BizProtocolPartyCustomer,
BizProtocolSample,
SysUser,
)
engine = create_engine("sqlite:///:memory:")
BizCollectionProtocol.__table__.create(engine)
BizProtocolPartyCustomer.__table__.create(engine)
BizProtocolCollectionInfo.__table__.create(engine)
BizProtocolSample.__table__.create(engine)
BizProtocolOperationLog.__table__.create(engine)
SysUser.__table__.create(engine)
return sessionmaker(bind=engine, autoflush=False, autocommit=False)(), engine
def test_record_cell_update_appends_before_after_and_maps_void_action():
from app.crud import protocol_operation_log as op_log
from app.models.models import BizCollectionProtocol, BizProtocolPartyCustomer, SysUser
db, engine = _session()
try:
now = datetime(2026, 11, 5, 10, 0, 0)
db.add(
SysUser(
id="u1",
user_no="u1",
nick_name="采集员甲",
tenant_no="zkxw",
create_dept_id="",
create_time=now,
update_time=now,
del_flag=0,
)
)
db.add(
BizCollectionProtocol(
id="p1",
protocol_no="XY2401",
protocol_status="sxz",
tenant_no="zkxw",
create_dept_id="",
create_time=now,
update_time=now,
del_flag=0,
)
)
db.add(
BizProtocolPartyCustomer(
id="party1",
collection_protocol_id="p1",
mother_name="旧姓名",
tenant_no="zkxw",
create_dept_id="",
create_time=now,
update_time=now,
del_flag=0,
)
)
db.commit()
before = op_log.snapshot_cell_protocol(db, protocol_id="p1", tenant_no="zkxw")
assert before is not None
assert before["protocol"]["protocolStatus"] == "sxz"
assert before["partyCustomer"]["motherName"] == "旧姓名"
row = db.query(BizCollectionProtocol).filter(BizCollectionProtocol.id == "p1").one()
row.protocol_status = "yzf"
party = (
db.query(BizProtocolPartyCustomer)
.filter(BizProtocolPartyCustomer.collection_protocol_id == "p1")
.one()
)
party.mother_name = "新姓名"
db.add(row)
db.add(party)
db.flush()
op_log.record_cell_operation(
db,
protocol_id="p1",
action=op_log.ACTION_UPDATE,
tenant_no="zkxw",
user_id="u1",
client_channel=op_log.CHANNEL_MINI,
before=before,
)
db.commit()
items = op_log.list_protocol_operation_logs(
db, biz_type=op_log.BIZ_CELL, biz_id="p1", tenant_no="zkxw"
)
assert len(items) == 1
item = items[0]
assert item["action"] == "void"
assert item["clientChannel"] == "mini"
assert item["operatorUserName"] == "采集员甲"
assert item["before"]["partyCustomer"]["motherName"] == "旧姓名"
assert item["after"]["partyCustomer"]["motherName"] == "新姓名"
assert item["after"]["protocol"]["protocolStatus"] == "yzf"
finally:
db.close()
engine.dispose()
def test_resolve_action_from_status_keeps_default_when_unchanged():
from app.crud.protocol_operation_log import (
ACTION_AUDIT,
ACTION_UPDATE,
ACTION_VOID,
resolve_action_from_status,
)
assert (
resolve_action_from_status(
default_action=ACTION_UPDATE,
before_status="sxz",
after_status="sxz",
)
== ACTION_UPDATE
)
assert (
resolve_action_from_status(
default_action=ACTION_UPDATE,
before_status="sxz",
after_status="yzf",
)
== ACTION_VOID
)
assert (
resolve_action_from_status(
default_action=ACTION_AUDIT,
before_status="dsx",
after_status="sxz",
)
== ACTION_AUDIT
)