feat(platform): close AI expense value loop
Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
from openpyxl import Workbook
|
||||
from sqlalchemy import create_engine, select
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
@@ -39,7 +40,7 @@ def build_workbook_bytes(rows: list[list[object]]) -> bytes:
|
||||
|
||||
def test_import_employees_rejects_invalid_row_without_writing() -> None:
|
||||
with build_session() as db:
|
||||
service = EmployeeService(db)
|
||||
service = EmployeeService(db, tenant_id="default")
|
||||
first = service.list_employees()[0]
|
||||
|
||||
content = build_workbook_bytes(
|
||||
@@ -80,7 +81,7 @@ def test_import_employees_rejects_invalid_row_without_writing() -> None:
|
||||
|
||||
def test_import_employees_updates_existing_employee() -> None:
|
||||
with build_session() as db:
|
||||
service = EmployeeService(db)
|
||||
service = EmployeeService(db, tenant_id="default")
|
||||
employee = service.list_employees()[0]
|
||||
new_name = f"{employee.name}-导入"
|
||||
|
||||
@@ -121,11 +122,14 @@ def test_import_employees_updates_existing_employee() -> None:
|
||||
assert updated.bankAccountName == "导入户名"
|
||||
assert updated.bankName == "招商银行上海分行"
|
||||
assert updated.bankAccountNo == "622588000000000002"
|
||||
persisted = db.execute(select(Employee).where(Employee.id == employee.id)).scalar_one()
|
||||
assert persisted.tenant_id == "default"
|
||||
assert persisted.manager_id is None
|
||||
|
||||
|
||||
def test_import_employees_creates_new_employee() -> None:
|
||||
with build_session() as db:
|
||||
service = EmployeeService(db)
|
||||
service = EmployeeService(db, tenant_id="default")
|
||||
service.list_employees()
|
||||
|
||||
content = build_workbook_bytes(
|
||||
@@ -158,11 +162,50 @@ def test_import_employees_creates_new_employee() -> None:
|
||||
|
||||
assert result.success is True
|
||||
assert result.summary.created == 1
|
||||
imported = db.execute(
|
||||
select(Employee).where(Employee.employee_no == "E90001")
|
||||
).scalar_one()
|
||||
imported = db.execute(select(Employee).where(Employee.employee_no == "E90001")).scalar_one()
|
||||
assert imported.name == "导入新员工"
|
||||
assert imported.email == "import.new.user@xfinance.com"
|
||||
assert imported.bank_account_name == "导入新员工"
|
||||
assert imported.bank_name
|
||||
assert imported.bank_account_no
|
||||
|
||||
|
||||
def test_import_employees_rolls_back_when_membership_sync_fails(monkeypatch) -> None:
|
||||
with build_session() as db:
|
||||
service = EmployeeService(db, tenant_id="default")
|
||||
service.list_employees()
|
||||
content = build_workbook_bytes(
|
||||
[
|
||||
[
|
||||
"E-ROLLBACK-001",
|
||||
"导入回滚员工",
|
||||
"import.rollback@xfinance.com",
|
||||
"女",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"上海",
|
||||
"业务专员",
|
||||
"P3",
|
||||
"FINANCE-DEPT",
|
||||
"",
|
||||
"",
|
||||
"CC-ROLLBACK",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"在职",
|
||||
"user",
|
||||
]
|
||||
]
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_ensure_tenant_memberships",
|
||||
lambda: (_ for _ in ()).throw(RuntimeError("membership sync failed")),
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError, match="membership sync failed"):
|
||||
service.import_employees(content)
|
||||
|
||||
assert db.scalar(select(Employee).where(Employee.employee_no == "E-ROLLBACK-001")) is None
|
||||
|
||||
Reference in New Issue
Block a user