Files
shanxia2.0/backend/tests/test_pl_vehicle_recharge_mine_vehicles.py
T
zlwuandCursor 0d2c5a2048 feat(pl): enforce mineVehicles write rules on recharge apply
Reject foreign plates on create and require own applicant for update/submit/cancel when mineVehicles is enabled.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-27 18:33:25 +08:00

230 lines
7.1 KiB
Python

"""mineVehicles:车辆人员归属过滤与写校验。"""
from __future__ import annotations
from datetime import date, datetime
from types import SimpleNamespace
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.models.pl_models import (
PlPersonnel,
PlVehicle,
PlVehiclePersonnel,
PlVehicleRechargeApply,
)
def _make_session():
engine = create_engine("sqlite://")
for table in (
PlVehicle.__table__,
PlPersonnel.__table__,
PlVehiclePersonnel.__table__,
PlVehicleRechargeApply.__table__,
):
table.create(engine)
return sessionmaker(bind=engine)()
def _user(uid: str = "u-driver") -> SimpleNamespace:
return SimpleNamespace(id=uid, name="司机甲", dept_id="d1", role="driver", tenant_no="t1")
def _seed_person_vehicle(db, *, user_id="u-driver", plate="鄂A11111", vehicle_id="veh-a"):
db.add(
PlVehicle(
id=vehicle_id,
vehicle_type="self",
license_plate=plate,
tenant_no="t1",
create_dept_id="d1",
del_flag=0,
)
)
db.add(
PlPersonnel(
id="p-1",
personnel_name="司机甲",
personnel_type="driver",
personnel_affiliation="self",
status="1",
sys_user_id=user_id,
tenant_no="t1",
create_dept_id="d1",
del_flag=0,
)
)
db.add(
PlVehiclePersonnel(
id="vp-1",
vehicle_id=vehicle_id,
personnel_id="p-1",
role="driver",
is_default=1,
tenant_no="t1",
create_dept_id="d1",
del_flag=0,
)
)
def test_license_plates_for_user_personnel():
from app.services.pl_vehicle_mine_vehicles import license_plates_for_user_personnel
db = _make_session()
_seed_person_vehicle(db)
db.add(
PlVehicle(
id="veh-b",
vehicle_type="self",
license_plate="鄂A22222",
tenant_no="t1",
create_dept_id="d1",
del_flag=0,
)
)
db.commit()
plates = license_plates_for_user_personnel(db, "t1", "u-driver")
assert plates == {"鄂A11111"}
def test_license_plates_empty_when_no_personnel():
from app.services.pl_vehicle_mine_vehicles import license_plates_for_user_personnel
db = _make_session()
db.commit()
assert license_plates_for_user_personnel(db, "t1", "u-nobody") == set()
def _seed_apply(db, *, apply_id, plate, applicant_id, status="draft"):
db.add(
PlVehicleRechargeApply(
id=apply_id,
apply_no=f"SXSQ{apply_id}",
license_plate=plate,
recharge_type="etc",
apply_date=date.today(),
applicant_id=applicant_id,
status=status,
tenant_no="t1",
create_by=applicant_id,
create_dept_id="d1",
create_time=datetime.now(),
update_time=datetime.now(),
del_flag=0,
)
)
def test_list_applies_mine_vehicles_includes_others_on_my_plate(monkeypatch):
from app.services import pl_vehicle_recharge_service as svc
db = _make_session()
_seed_person_vehicle(db)
_seed_apply(db, apply_id="a1", plate="鄂A11111", applicant_id="u-office")
_seed_apply(db, apply_id="a2", plate="鄂A99999", applicant_id="u-office")
db.commit()
monkeypatch.setattr(svc, "apply_pl_scope", lambda query, *_a, **_k: query)
monkeypatch.setattr(svc, "assert_pl_row_in_scope", lambda *_a, **_k: None)
monkeypatch.setattr(svc, "_resolve_user_name", lambda *_a, **_k: "X")
monkeypatch.setattr(
svc,
"apply_to_read",
lambda row, db, **kw: SimpleNamespace(
id=row.id, licensePlate=row.license_plate, applicantId=row.applicant_id
),
)
items, total = svc.list_applies(
db, "t1", _user(), mine_vehicles=True, page=1, page_size=20
)
assert total == 1
assert items[0].id == "a1"
def test_get_apply_mine_vehicles_allows_others_on_my_plate(monkeypatch):
from app.services import pl_vehicle_recharge_service as svc
db = _make_session()
_seed_person_vehicle(db)
_seed_apply(db, apply_id="a1", plate="鄂A11111", applicant_id="u-office")
db.commit()
monkeypatch.setattr(
svc,
"assert_pl_row_in_scope",
lambda *_a, **_k: (_ for _ in ()).throw(
AssertionError("should not use data scope when mine_vehicles")
),
)
monkeypatch.setattr(svc, "_resolve_user_name", lambda *_a, **_k: "X")
monkeypatch.setattr(
svc,
"apply_to_read",
lambda row, db, **kw: SimpleNamespace(id=row.id),
)
result = svc.get_apply(db, "t1", _user(), "a1", mine_vehicles=True)
assert result.id == "a1" or getattr(result, "id", None) == "a1"
def test_get_apply_mine_vehicles_rejects_foreign_plate(monkeypatch):
from fastapi import HTTPException
from app.services import pl_vehicle_recharge_service as svc
db = _make_session()
_seed_person_vehicle(db)
_seed_apply(db, apply_id="a2", plate="鄂A99999", applicant_id="u-office")
db.commit()
monkeypatch.setattr(svc, "_resolve_user_name", lambda *_a, **_k: "X")
with pytest.raises(HTTPException) as exc:
svc.get_apply(db, "t1", _user(), "a2", mine_vehicles=True)
assert exc.value.status_code == 403
assert "无权" in exc.value.detail
def test_create_apply_mine_vehicles_rejects_foreign_plate(monkeypatch):
from fastapi import HTTPException
from app.schemas.pl.vehicle_recharge import VehicleRechargeApplyCreate
from app.services import pl_vehicle_recharge_service as svc
db = _make_session()
_seed_person_vehicle(db)
db.commit()
monkeypatch.setattr(svc, "apply_pl_scope", lambda query, *_a, **_k: query)
monkeypatch.setattr(svc, "assert_pl_row_in_scope", lambda *_a, **_k: None)
monkeypatch.setattr(svc, "_resolve_user_name", lambda *_a, **_k: "X")
monkeypatch.setattr(svc, "_resolve_applicant_id", lambda *_a, **_k: "u-driver")
monkeypatch.setattr(svc, "_assert_vehicle_exists", lambda *_a, **_k: None)
monkeypatch.setattr(svc, "generate_apply_no", lambda *_a, **_k: "SXSQTEST1")
payload = VehicleRechargeApplyCreate(
licensePlate="鄂A99999",
rechargeType="etc",
applyDate=date.today(),
)
with pytest.raises(HTTPException) as ei:
svc.create_apply(db, "t1", _user(), payload, mine_vehicles=True)
assert ei.value.status_code in (400, 403)
def test_update_cancel_submit_require_own_applicant(monkeypatch):
from fastapi import HTTPException
from app.services import pl_vehicle_recharge_service as svc
db = _make_session()
_seed_person_vehicle(db)
_seed_apply(db, apply_id="a1", plate="鄂A11111", applicant_id="u-office", status="draft")
db.commit()
monkeypatch.setattr(svc, "assert_pl_row_in_scope", lambda *_a, **_k: None)
monkeypatch.setattr(svc, "_resolve_user_name", lambda *_a, **_k: "X")
with pytest.raises(HTTPException) as ei:
svc.cancel_apply(db, "t1", _user(), "a1", mine_vehicles=True)
assert ei.value.status_code == 403