feat/m3-increments #1

Merged
liuwenxin merged 100 commits from feat/m3-increments into main 2026-10-19 04:59:57 -04:00
7 changed files with 13 additions and 23 deletions
Showing only changes of commit 9a70264b51 - Show all commits

View File

@ -50,9 +50,7 @@ def create_shipment(
)
@router.get(
"/{shipment_id}", response_model=ApiResponse[ShipmentDetailOut], summary="发货单详情"
)
@router.get("/{shipment_id}", response_model=ApiResponse[ShipmentDetailOut], summary="发货单详情")
def get_shipment(
session: DbSession,
_: CurrentUser,

View File

@ -29,9 +29,7 @@ def count_business_refs(session: Session, customer_id: int) -> int:
return int(
session.execute(
select(func.count())
.select_from(Business)
.where(Business.customer_id == customer_id)
select(func.count()).select_from(Business).where(Business.customer_id == customer_id)
).scalar_one()
)

View File

@ -88,9 +88,7 @@ def list_receipts(
is_barter=is_barter,
settlement_status=settlement_status,
)
return list(
session.execute(stmt.order_by(Receipt.id.desc()).offset(offset).limit(limit)).all()
)
return list(session.execute(stmt.order_by(Receipt.id.desc()).offset(offset).limit(limit)).all())
def count_receipts(

View File

@ -59,9 +59,7 @@ def list_shipments(
) -> list[tuple[Shipment, str]]:
"""分页查询发货单(附业务号),按 id 倒序。"""
stmt = _apply_filters(
select(Shipment, Business.business_no).join(
Business, Business.id == Shipment.business_id
),
select(Shipment, Business.business_no).join(Business, Business.id == Shipment.business_id),
business_id=business_id,
ship_date_from=ship_date_from,
ship_date_to=ship_date_to,

View File

@ -30,9 +30,7 @@ class ReceiptCreateIn(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
business_id: int = Field(ge=1, description="业务ID")
shipment_id: int | None = Field(
default=None, ge=1, description="发货单ID,可空=暂未指定"
)
shipment_id: int | None = Field(default=None, ge=1, description="发货单ID,可空=暂未指定")
receipt_date: date = Field(description="回款到账日(M3 按此日匹配参数版本)")
amount: str = Field(description="回款金额(元),≥0,最多两位小数")
is_barter: int = Field(default=0, ge=0, le=1, description="以物抵顶标记:1是 0否")

View File

@ -151,9 +151,7 @@ class TestCrudFlow:
assert dup.status_code == 400, dup.text
assert "该公司名称与负责人的客户已存在" in dup.json()["message"]
def test_删除被业务引用的客户_400引导处理单据(
self, client: TestClient, normal: dict
) -> None:
def test_删除被业务引用的客户_400引导处理单据(self, client: TestClient, normal: dict) -> None:
"""业务表就位后删除保护补齐:FK RESTRICT 不能以 500 暴露。"""
headers = normal["headers"]
customer = _create_customer(client, headers)

View File

@ -235,7 +235,9 @@ class TestDeleteProtection:
member = _create(client, headers, manager_id=manager["id"]) # 团队成员占用
blocked = client.delete(f"{_PERSONNEL}/{manager['id']}", headers=headers)
assert blocked.status_code == 400, blocked.text
assert "存在团队成员、客户归属或业务归属引用,请改为离职而非删除" in blocked.json()["message"]
assert (
"存在团队成员、客户归属或业务归属引用,请改为离职而非删除" in blocked.json()["message"]
)
client.delete(f"{_PERSONNEL}/{member['id']}", headers=headers)
freed = client.delete(f"{_PERSONNEL}/{manager['id']}", headers=headers)
@ -261,7 +263,9 @@ class TestDeleteProtection:
blocked = client.delete(f"{_PERSONNEL}/{owner['id']}", headers=headers)
assert blocked.status_code == 400, blocked.text
assert "存在团队成员、客户归属或业务归属引用,请改为离职而非删除" in blocked.json()["message"]
assert (
"存在团队成员、客户归属或业务归属引用,请改为离职而非删除" in blocked.json()["message"]
)
# 保护与在职状态无关:离职并不能让物理删除放行
client.put(f"{_PERSONNEL}/{owner['id']}/status", json={"status": 0}, headers=headers)
@ -273,9 +277,7 @@ class TestDeleteProtection:
freed = client.delete(f"{_PERSONNEL}/{owner['id']}", headers=headers)
assert freed.status_code == 200, freed.text
def test_被业务归属引用禁删_负责或协助任一即拦(
self, client: TestClient, normal: dict
) -> None:
def test_被业务归属引用禁删_负责或协助任一即拦(self, client: TestClient, normal: dict) -> None:
"""业务表就位后删除保护补齐:负责/协助引用任一即拦,FK 不以 500 暴露。"""
headers = normal["headers"]
owner = _create(client, headers)