Reject foreign plates on create and require own applicant for update/submit/cancel when mineVehicles is enabled. Co-authored-by: Cursor <cursoragent@cursor.com>
230 lines
7.1 KiB
Python
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
|