Store multiple bank receipts on biz_attachment keyed by instance id. Co-authored-by: Cursor <cursoragent@cursor.com>
236 lines
7.7 KiB
Python
236 lines
7.7 KiB
Python
"""OA 银行回执单:biz_attachment 挂载 instance。"""
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from app.models.base import Base
|
|
from app.models.models import BizAttachment, OaApp, OaAppVersion, OaInstance
|
|
from app.services import oa_bank_receipt as svc
|
|
|
|
|
|
class TestOaBankReceipt(unittest.TestCase):
|
|
def setUp(self):
|
|
self.engine = create_engine("sqlite:///:memory:")
|
|
Base.metadata.create_all(
|
|
self.engine,
|
|
tables=[
|
|
OaApp.__table__,
|
|
OaAppVersion.__table__,
|
|
OaInstance.__table__,
|
|
BizAttachment.__table__,
|
|
],
|
|
)
|
|
Session = sessionmaker(bind=self.engine, autoflush=False, autocommit=False)
|
|
self.db = Session()
|
|
t0 = datetime(2026, 10, 16, 10, 0, 0)
|
|
self.db.add_all(
|
|
[
|
|
OaApp(
|
|
id="app1",
|
|
app_name="付款申请",
|
|
initiator_scope="all",
|
|
admin_scope="all_oa_admin",
|
|
status="1",
|
|
tenant_no="zkxw",
|
|
create_dept_id="",
|
|
create_time=t0,
|
|
update_time=t0,
|
|
del_flag=0,
|
|
),
|
|
OaAppVersion(
|
|
id="v1",
|
|
app_id="app1",
|
|
version_no=1,
|
|
status="published",
|
|
is_latest_published="1",
|
|
form_schema_json="{}",
|
|
flow_tree_json="{}",
|
|
advanced_settings_json="{}",
|
|
tenant_no="zkxw",
|
|
create_dept_id="",
|
|
create_time=t0,
|
|
update_time=t0,
|
|
del_flag=0,
|
|
),
|
|
OaInstance(
|
|
id="inst-1",
|
|
app_id="app1",
|
|
app_version_id="v1",
|
|
title="付款-1",
|
|
initiator_user_id="u1",
|
|
status="completed",
|
|
current_round=1,
|
|
tenant_no="zkxw",
|
|
create_dept_id="",
|
|
create_time=t0,
|
|
update_time=t0,
|
|
del_flag=0,
|
|
),
|
|
OaInstance(
|
|
id="inst-other-tenant",
|
|
app_id="app1",
|
|
app_version_id="v1",
|
|
title="付款-x",
|
|
initiator_user_id="u1",
|
|
status="completed",
|
|
current_round=1,
|
|
tenant_no="other",
|
|
create_dept_id="",
|
|
create_time=t0,
|
|
update_time=t0,
|
|
del_flag=0,
|
|
),
|
|
]
|
|
)
|
|
self.db.commit()
|
|
|
|
def tearDown(self):
|
|
self.db.close()
|
|
self.engine.dispose()
|
|
|
|
def test_list_empty(self):
|
|
items = svc.list_bank_receipts(self.db, instance_id="inst-1", tenant_no="zkxw")
|
|
self.assertEqual(items, [])
|
|
|
|
def test_replace_then_list(self):
|
|
out = svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[
|
|
{
|
|
"fileUrl": "oa-bank-receipt/a.pdf",
|
|
"fileName": "回单A.pdf",
|
|
"fileType": "application/pdf",
|
|
"fileSize": 100,
|
|
},
|
|
{
|
|
"fileUrl": "oa-bank-receipt/b.jpg",
|
|
"fileName": "回单B.jpg",
|
|
"fileType": "image/jpeg",
|
|
"fileSize": 200,
|
|
},
|
|
],
|
|
user_id="u1",
|
|
dept_id="d1",
|
|
)
|
|
self.db.commit()
|
|
self.assertEqual(len(out), 2)
|
|
listed = svc.list_bank_receipts(self.db, instance_id="inst-1", tenant_no="zkxw")
|
|
self.assertEqual([x["fileUrl"] for x in listed], [
|
|
"oa-bank-receipt/a.pdf",
|
|
"oa-bank-receipt/b.jpg",
|
|
])
|
|
self.assertEqual(listed[0]["fileName"], "回单A.pdf")
|
|
|
|
def test_replace_removes_missing(self):
|
|
svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[
|
|
{"fileUrl": "oa-bank-receipt/a.pdf", "fileName": "A.pdf"},
|
|
{"fileUrl": "oa-bank-receipt/b.pdf", "fileName": "B.pdf"},
|
|
],
|
|
user_id="u1",
|
|
dept_id="",
|
|
)
|
|
self.db.commit()
|
|
svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[{"fileUrl": "oa-bank-receipt/b.pdf", "fileName": "B.pdf"}],
|
|
user_id="u1",
|
|
dept_id="",
|
|
)
|
|
self.db.commit()
|
|
listed = svc.list_bank_receipts(self.db, instance_id="inst-1", tenant_no="zkxw")
|
|
self.assertEqual([x["fileUrl"] for x in listed], ["oa-bank-receipt/b.pdf"])
|
|
gone = (
|
|
self.db.query(BizAttachment)
|
|
.filter(BizAttachment.file_url == "oa-bank-receipt/a.pdf")
|
|
.first()
|
|
)
|
|
self.assertEqual(gone.del_flag, 1)
|
|
|
|
def test_replace_empty_clears_all(self):
|
|
svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[{"fileUrl": "oa-bank-receipt/a.pdf", "fileName": "A.pdf"}],
|
|
user_id="u1",
|
|
dept_id="",
|
|
)
|
|
self.db.commit()
|
|
svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[],
|
|
user_id="u1",
|
|
dept_id="",
|
|
)
|
|
self.db.commit()
|
|
self.assertEqual(
|
|
svc.list_bank_receipts(self.db, instance_id="inst-1", tenant_no="zkxw"),
|
|
[],
|
|
)
|
|
|
|
def test_bind_orphan_upload_row(self):
|
|
"""通用上传已写入无 business_type 的行时,PUT 应绑定而非再插一行。"""
|
|
t0 = datetime(2026, 10, 16, 11, 0, 0)
|
|
orphan = BizAttachment(
|
|
id="att-orphan",
|
|
business_type=None,
|
|
business_id=None,
|
|
original_name="orphan.pdf",
|
|
file_ext="pdf",
|
|
file_url="oa-bank-receipt/orphan.pdf",
|
|
file_size=10,
|
|
file_type="application/pdf",
|
|
tenant_no="zkxw",
|
|
create_dept_id="",
|
|
create_time=t0,
|
|
update_time=t0,
|
|
del_flag=0,
|
|
)
|
|
self.db.add(orphan)
|
|
self.db.commit()
|
|
svc.replace_bank_receipts(
|
|
self.db,
|
|
instance_id="inst-1",
|
|
tenant_no="zkxw",
|
|
items=[{"fileUrl": "oa-bank-receipt/orphan.pdf", "fileName": "orphan.pdf"}],
|
|
user_id="u1",
|
|
dept_id="",
|
|
)
|
|
self.db.commit()
|
|
rows = (
|
|
self.db.query(BizAttachment)
|
|
.filter(BizAttachment.file_url == "oa-bank-receipt/orphan.pdf", BizAttachment.del_flag == 0)
|
|
.all()
|
|
)
|
|
self.assertEqual(len(rows), 1)
|
|
self.assertEqual(rows[0].business_type, svc.BUSINESS_TYPE)
|
|
self.assertEqual(rows[0].business_id, "inst-1")
|
|
|
|
def test_missing_instance_raises(self):
|
|
with self.assertRaises(svc.OaBankReceiptError):
|
|
svc.list_bank_receipts(self.db, instance_id="nope", tenant_no="zkxw")
|
|
|
|
def test_cross_tenant_raises(self):
|
|
with self.assertRaises(svc.OaBankReceiptError):
|
|
svc.list_bank_receipts(
|
|
self.db, instance_id="inst-other-tenant", tenant_no="zkxw"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|