feat: add recharge workflow models and schema statuses
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
94dd52832b
commit
bdd67d44d9
7 files changed
+147
-26
No files matched your search
@@ -67,7 +67,16 @@ def create_workflow(
|
||||
nodes_data = data.pop("nodes", []) or []
|
||||
workflow = WorkflowService.create(db, data, user=user)
|
||||
if nodes_data:
|
||||
WorkflowService.save_nodes(db, workflow.id, nodes_data, user=user)
|
||||
try:
|
||||
WorkflowService.save_nodes(db, workflow.id, nodes_data, user=user)
|
||||
except ValueError as exc:
|
||||
db.rollback()
|
||||
code = (
|
||||
status.HTTP_400_BAD_REQUEST
|
||||
if "发放登记" in str(exc)
|
||||
else status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
raise HTTPException(status_code=code, detail=str(exc)) from exc
|
||||
db.commit()
|
||||
db.refresh(workflow)
|
||||
return ApiResponse(data=WorkflowDefOut.model_validate(workflow))
|
||||
@@ -87,7 +96,16 @@ def update_workflow(
|
||||
if not workflow:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在")
|
||||
if nodes_data is not None:
|
||||
WorkflowService.save_nodes(db, workflow_id, nodes_data, user=user)
|
||||
try:
|
||||
WorkflowService.save_nodes(db, workflow_id, nodes_data, user=user)
|
||||
except ValueError as exc:
|
||||
db.rollback()
|
||||
code = (
|
||||
status.HTTP_400_BAD_REQUEST
|
||||
if "发放登记" in str(exc)
|
||||
else status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
raise HTTPException(status_code=code, detail=str(exc)) from exc
|
||||
db.commit()
|
||||
db.refresh(workflow)
|
||||
return ApiResponse(data=WorkflowDefOut.model_validate(workflow))
|
||||
@@ -106,7 +124,12 @@ def save_workflow_nodes(
|
||||
WorkflowService.save_nodes(db, workflow_id, nodes_data, user=user)
|
||||
except ValueError as exc:
|
||||
db.rollback()
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
||||
code = (
|
||||
status.HTTP_400_BAD_REQUEST
|
||||
if "发放登记" in str(exc)
|
||||
else status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
raise HTTPException(status_code=code, detail=str(exc)) from exc
|
||||
workflow = WorkflowService.get_by_id(db, workflow_id, tenant_no, user=user)
|
||||
if not workflow:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="工作流不存在")
|
||||
|
||||
@@ -73,6 +73,12 @@ class BxWorkflowNode(Base):
|
||||
node_order = Column(Integer, nullable=False, default=0, comment="节点顺序")
|
||||
approver_id = Column(String(64), nullable=True, comment="审批人用户ID")
|
||||
approver_name = Column(String(64), nullable=True, comment="审批人姓名")
|
||||
action_type = Column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default="approve",
|
||||
comment="approve-审批 disburse-发放登记",
|
||||
)
|
||||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||||
order_num = Column(Integer, nullable=True, comment="排序号(公共)")
|
||||
remark = Column(String(512), nullable=True, comment="备注")
|
||||
|
||||
@@ -1333,7 +1333,41 @@ class PlVehicleRechargeApply(Base):
|
||||
odometer_km = Column(DECIMAL(10, 1), nullable=True, comment="期初公里数")
|
||||
attachment_urls = Column(String(2000), nullable=True, comment="附件URL")
|
||||
applicant_id = Column(String(64), nullable=False, comment="申请人ID")
|
||||
status = Column(String(20), nullable=False, default="pending", comment="申请状态")
|
||||
status = Column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default="draft",
|
||||
comment="draft/in_approval/rejected/disbursed/cancelled",
|
||||
)
|
||||
wf_id = Column(String(64), nullable=True, comment="工作流定义ID")
|
||||
current_node = Column(String(64), nullable=True, comment="当前节点ID")
|
||||
approval_round = Column(Integer, nullable=False, default=0, comment="当前审批轮次")
|
||||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||||
remark = Column(String(512), nullable=True, comment="备注")
|
||||
create_by = Column(String(64), nullable=True, comment="创建人id")
|
||||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
|
||||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||||
update_by = Column(String(64), nullable=True, comment="更新人id")
|
||||
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
|
||||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记:0-正常 1-已删除")
|
||||
|
||||
|
||||
class PlVehicleRechargeApproval(Base):
|
||||
"""车辆充值申请审批历史 pl_vehicle_recharge_approval"""
|
||||
|
||||
__tablename__ = "pl_vehicle_recharge_approval"
|
||||
|
||||
id = Column(String(64), primary_key=True, comment="主键ID")
|
||||
apply_id = Column(String(64), nullable=False, comment="申请单ID")
|
||||
approval_round = Column(Integer, nullable=False, default=1, comment="审批轮次")
|
||||
node_id = Column(String(64), nullable=True, comment="节点ID快照")
|
||||
node_name = Column(String(128), nullable=True, comment="节点名称快照")
|
||||
approver_id = Column(String(64), nullable=False, comment="审批人用户ID")
|
||||
approver_name = Column(String(64), nullable=False, comment="审批人姓名")
|
||||
approval_status = Column(String(32), nullable=False, comment="approved/rejected/disbursed")
|
||||
approval_opinion = Column(String(1024), nullable=True, comment="审批意见")
|
||||
approval_time = Column(DateTime, nullable=False, comment="审批时间")
|
||||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||||
remark = Column(String(512), nullable=True, comment="备注")
|
||||
|
||||
@@ -17,6 +17,7 @@ class WorkflowNodeCreate(BaseModel):
|
||||
node_order: int
|
||||
approver_id: Optional[str] = None
|
||||
approver_name: Optional[str] = None
|
||||
action_type: Optional[str] = "approve"
|
||||
|
||||
@field_validator("approver_id", mode="before")
|
||||
@classmethod
|
||||
@@ -32,6 +33,7 @@ class WorkflowNodeOut(BaseModel):
|
||||
node_order: int
|
||||
approver_id: Optional[str] = None
|
||||
approver_name: Optional[str] = None
|
||||
action_type: Optional[str] = "approve"
|
||||
|
||||
|
||||
class WorkflowDefCreate(BaseModel):
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
"""车辆 ETC/加油充值 Schema"""
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
RECHARGE_TYPES = {"etc", "fuel"}
|
||||
APPLY_STATUSES = {"draft", "in_approval", "rejected", "disbursed", "cancelled"}
|
||||
NODE_ACTION_TYPES = {"approve", "disburse"}
|
||||
APPROVAL_STATUSES = {"approved", "rejected", "disbursed"}
|
||||
|
||||
|
||||
class VehicleRechargeApplyCreate(BaseModel):
|
||||
@@ -31,6 +34,42 @@ class VehicleRechargeApplyUpdate(VehicleRechargeApplyCreate):
|
||||
pass
|
||||
|
||||
|
||||
class VehicleRechargeApprovalRead(BaseModel):
|
||||
id: str
|
||||
apply_id: str = Field(..., alias="applyId")
|
||||
approval_round: int = Field(..., alias="approvalRound")
|
||||
node_id: Optional[str] = Field(default=None, alias="nodeId")
|
||||
node_name: Optional[str] = Field(default=None, alias="nodeName")
|
||||
approver_id: str = Field(..., alias="approverId")
|
||||
approver_name: str = Field(..., alias="approverName")
|
||||
approval_status: str = Field(..., alias="approvalStatus")
|
||||
approval_opinion: Optional[str] = Field(default=None, alias="approvalOpinion")
|
||||
approval_time: datetime = Field(..., alias="approvalTime")
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class VehicleRechargeRecordRead(BaseModel):
|
||||
id: str
|
||||
recharge_order_no: str = Field(..., alias="rechargeOrderNo")
|
||||
recharge_date: date = Field(..., alias="rechargeDate")
|
||||
recharge_type: str = Field(..., alias="rechargeType")
|
||||
card_no: Optional[str] = Field(default=None, alias="cardNo")
|
||||
gas_station: Optional[str] = Field(default=None, alias="gasStation")
|
||||
amount: Decimal
|
||||
attachment_urls: Optional[str] = Field(default=None, alias="attachmentUrls")
|
||||
apply_id: Optional[str] = Field(default=None, alias="applyId")
|
||||
apply_no: Optional[str] = Field(default=None, alias="applyNo")
|
||||
license_plate: Optional[str] = Field(default=None, alias="licensePlate")
|
||||
remark: Optional[str] = None
|
||||
create_by: Optional[str] = Field(default=None, alias="createBy")
|
||||
create_by_name: Optional[str] = Field(default=None, alias="createByName")
|
||||
create_time: Optional[datetime] = Field(default=None, alias="createTime")
|
||||
update_time: Optional[datetime] = Field(default=None, alias="updateTime")
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class VehicleRechargeApplyRead(BaseModel):
|
||||
id: str
|
||||
apply_no: str = Field(..., alias="applyNo")
|
||||
@@ -42,6 +81,11 @@ class VehicleRechargeApplyRead(BaseModel):
|
||||
applicant_id: str = Field(..., alias="applicantId")
|
||||
applicant_name: Optional[str] = Field(default=None, alias="applicantName")
|
||||
status: str
|
||||
wf_id: Optional[str] = Field(default=None, alias="wfId")
|
||||
current_node: Optional[str] = Field(default=None, alias="currentNode")
|
||||
approval_round: int = Field(default=0, alias="approvalRound")
|
||||
approvals: List[VehicleRechargeApprovalRead] = Field(default_factory=list)
|
||||
record: Optional[VehicleRechargeRecordRead] = None
|
||||
remark: Optional[str] = None
|
||||
create_time: Optional[datetime] = Field(default=None, alias="createTime")
|
||||
update_time: Optional[datetime] = Field(default=None, alias="updateTime")
|
||||
@@ -67,6 +111,12 @@ class VehicleRechargeApplyOption(BaseModel):
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class VehicleRechargeOpinionBody(BaseModel):
|
||||
opinion: Optional[str] = None
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class VehicleRechargeRecordCreate(BaseModel):
|
||||
recharge_date: date = Field(..., alias="rechargeDate")
|
||||
recharge_type: str = Field(..., alias="rechargeType")
|
||||
@@ -99,27 +149,6 @@ class VehicleRechargeRecordUpdate(VehicleRechargeRecordCreate):
|
||||
pass
|
||||
|
||||
|
||||
class VehicleRechargeRecordRead(BaseModel):
|
||||
id: str
|
||||
recharge_order_no: str = Field(..., alias="rechargeOrderNo")
|
||||
recharge_date: date = Field(..., alias="rechargeDate")
|
||||
recharge_type: str = Field(..., alias="rechargeType")
|
||||
card_no: Optional[str] = Field(default=None, alias="cardNo")
|
||||
gas_station: Optional[str] = Field(default=None, alias="gasStation")
|
||||
amount: Decimal
|
||||
attachment_urls: Optional[str] = Field(default=None, alias="attachmentUrls")
|
||||
apply_id: Optional[str] = Field(default=None, alias="applyId")
|
||||
apply_no: Optional[str] = Field(default=None, alias="applyNo")
|
||||
license_plate: Optional[str] = Field(default=None, alias="licensePlate")
|
||||
remark: Optional[str] = None
|
||||
create_by: Optional[str] = Field(default=None, alias="createBy")
|
||||
create_by_name: Optional[str] = Field(default=None, alias="createByName")
|
||||
create_time: Optional[datetime] = Field(default=None, alias="createTime")
|
||||
update_time: Optional[datetime] = Field(default=None, alias="updateTime")
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class VehicleRechargeRecordListResponse(BaseModel):
|
||||
items: list[VehicleRechargeRecordRead]
|
||||
total: int
|
||||
|
||||
@@ -20,6 +20,10 @@ _DEFAULT_WORKFLOWS = {
|
||||
"wf_name": "报销单审批流程",
|
||||
"remark": "报销申请默认审批流程",
|
||||
},
|
||||
"vehicle_recharge": {
|
||||
"wf_name": "ETC/加油充值审批流程",
|
||||
"remark": "充值申请默认审批流程",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +166,18 @@ class WorkflowService:
|
||||
if not workflow:
|
||||
raise ValueError("工作流不存在")
|
||||
|
||||
disburse_count = 0
|
||||
for node_data in nodes:
|
||||
action = (
|
||||
node_data.get("action_type")
|
||||
or node_data.get("actionType")
|
||||
or "approve"
|
||||
)
|
||||
if action == "disburse":
|
||||
disburse_count += 1
|
||||
if disburse_count > 1:
|
||||
raise ValueError("发放登记节点至多一个")
|
||||
|
||||
db.query(BxWorkflowNode).filter(
|
||||
BxWorkflowNode.wf_id == wf_id,
|
||||
BxWorkflowNode.tenant_no == tenant_no,
|
||||
@@ -170,6 +186,7 @@ class WorkflowService:
|
||||
created: List[BxWorkflowNode] = []
|
||||
for node_data in nodes:
|
||||
data = dict(node_data)
|
||||
data.pop("actionType", None)
|
||||
data["id"] = generate_uuid()
|
||||
data["wf_id"] = wf_id
|
||||
data["tenant_no"] = tenant_no
|
||||
@@ -177,6 +194,8 @@ class WorkflowService:
|
||||
data["create_dept_id"] = user.dept_id or ""
|
||||
if data.get("approver_id") is not None:
|
||||
data["approver_id"] = str(data["approver_id"]).strip() or None
|
||||
if not data.get("action_type"):
|
||||
data["action_type"] = "approve"
|
||||
node = BxWorkflowNode(**data)
|
||||
db.add(node)
|
||||
created.append(node)
|
||||
|
||||
Reference in new issue
Block a user