|
|
@@ -11,20 +11,49 @@ from app.core.logger import log
|
|
|
from app.plugin.module_payment.expense.institution.crud import InstitutionCRUD
|
|
|
|
|
|
|
|
|
+def _compute_quota_status(inst) -> tuple:
|
|
|
+ """根据制度配置和当前时间,计算额度记录的状态和金额
|
|
|
+
|
|
|
+ 返回: (total_amount, available_amount, status)
|
|
|
+ """
|
|
|
+ from datetime import datetime
|
|
|
+ from app.plugin.module_payment.expense.quota.enums import QuotaStatusEnum
|
|
|
+ from decimal import Decimal
|
|
|
+
|
|
|
+ grant_mode = getattr(inst, "grant_mode", None)
|
|
|
+ amount_val = float(getattr(inst, "amount", 0) or 0)
|
|
|
+
|
|
|
+ # 判断是否在有效期内
|
|
|
+ now = datetime.now()
|
|
|
+ in_period = True
|
|
|
+ start_date = getattr(inst, "effective_start_date", None)
|
|
|
+ end_date = getattr(inst, "effective_end_date", None)
|
|
|
+ if start_date and now < start_date:
|
|
|
+ in_period = False
|
|
|
+ if end_date and in_period and now > end_date:
|
|
|
+ in_period = False
|
|
|
+
|
|
|
+ # 定额+有效期内 → ACTIVE + 全额
|
|
|
+ if grant_mode == "period" and amount_val > 0 and in_period:
|
|
|
+ return (Decimal(str(amount_val)), Decimal(str(amount_val)), QuotaStatusEnum.QUOTA_ACTIVE.value)
|
|
|
+
|
|
|
+ # 否则 → PENDING + 0
|
|
|
+ return (Decimal("0"), Decimal("0"), QuotaStatusEnum.QUOTA_PENDING.value)
|
|
|
+
|
|
|
+
|
|
|
async def _sync_employee_quota(
|
|
|
auth: AuthSchema, enterprise_id: str, employee_id: str, department_ids: list[str], is_add: bool
|
|
|
) -> None:
|
|
|
"""根据员工所属部门,同步本地额度记录
|
|
|
|
|
|
扫描所有按部门模式的制度:
|
|
|
- - 匹配的部门 → 确保员工有额度记录(创建缺失的)
|
|
|
+ - 匹配的部门 → 确保员工有额度记录(检查有效期内状态)
|
|
|
- 不匹配的部门 → 删除该员工的额度记录(处理离部门场景)
|
|
|
"""
|
|
|
if not employee_id:
|
|
|
return
|
|
|
|
|
|
from app.plugin.module_payment.expense.quota.model import QuotaModel
|
|
|
- from app.plugin.module_payment.expense.quota.enums import QuotaStatusEnum
|
|
|
from sqlalchemy import insert, delete as sa_delete, select
|
|
|
|
|
|
try:
|
|
|
@@ -61,27 +90,27 @@ async def _sync_employee_quota(
|
|
|
matched = bool(scope_ids and dept_id_set.intersection(scope_ids))
|
|
|
|
|
|
if matched:
|
|
|
- # 匹配 → 确保有额度记录
|
|
|
+ # 检查是否已有记录
|
|
|
check = select(QuotaModel).where(
|
|
|
QuotaModel.employee_id == employee_id,
|
|
|
QuotaModel.institution_id == inst_id,
|
|
|
)
|
|
|
existing = await auth.db.execute(check)
|
|
|
if not existing.scalar_one_or_none():
|
|
|
+ total, available, status = _compute_quota_status(inst)
|
|
|
stmt = insert(QuotaModel).values(
|
|
|
employee_id=employee_id,
|
|
|
institution_id=inst_id,
|
|
|
out_biz_no=f"scope_{inst_id}_{employee_id}",
|
|
|
- total_amount=0,
|
|
|
- available_amount=0,
|
|
|
- status=QuotaStatusEnum.QUOTA_PENDING.value,
|
|
|
+ total_amount=total,
|
|
|
+ available_amount=available,
|
|
|
+ status=status,
|
|
|
enterprise_id=enterprise_id,
|
|
|
tenant_id=tenant_id,
|
|
|
)
|
|
|
await auth.db.execute(stmt)
|
|
|
- log.info(f"部门联动 - 新增员工额度: employee_id={employee_id}, institution_id={inst_id}")
|
|
|
+ log.info(f"部门联动 - 新增员工额度: employee_id={employee_id}, institution_id={inst_id}, status={status}, amount={total}")
|
|
|
else:
|
|
|
- # 不匹配 → 删除该员工的额度记录
|
|
|
if not is_add:
|
|
|
continue
|
|
|
del_stmt = sa_delete(QuotaModel).where(
|
|
|
@@ -159,7 +188,10 @@ async def remove_department_from_institution_scopes(
|
|
|
async def sync_employee_to_all_institution(
|
|
|
auth: AuthSchema, enterprise_id: str, employee_id: str
|
|
|
) -> None:
|
|
|
- """员工激活时,为全体员工(applicable_scope=all)的制度创建本地额度记录"""
|
|
|
+ """员工激活时,为全体员工(applicable_scope=all)的制度创建本地额度记录
|
|
|
+
|
|
|
+ 根据制度有效期和发放模式判断状态:有效期内定额→ACTIVE,否则→PENDING
|
|
|
+ """
|
|
|
if not employee_id or not enterprise_id:
|
|
|
return
|
|
|
try:
|
|
|
@@ -171,7 +203,6 @@ async def sync_employee_to_all_institution(
|
|
|
if not institutions:
|
|
|
return
|
|
|
from app.plugin.module_payment.expense.quota.model import QuotaModel
|
|
|
- from app.plugin.module_payment.expense.quota.enums import QuotaStatusEnum
|
|
|
from sqlalchemy import insert, select
|
|
|
tenant_id = auth.user.tenant_id if auth.user else 1
|
|
|
for inst in institutions:
|
|
|
@@ -182,14 +213,16 @@ async def sync_employee_to_all_institution(
|
|
|
existing = await auth.db.execute(check)
|
|
|
if existing.scalar_one_or_none():
|
|
|
continue
|
|
|
+ total, available, status = _compute_quota_status(inst)
|
|
|
stmt = insert(QuotaModel).values(
|
|
|
employee_id=employee_id, institution_id=inst_id,
|
|
|
out_biz_no=f"all_{inst_id}_{employee_id}",
|
|
|
- total_amount=0, available_amount=0,
|
|
|
- status=QuotaStatusEnum.QUOTA_PENDING.value,
|
|
|
+ total_amount=total, available_amount=available,
|
|
|
+ status=status,
|
|
|
enterprise_id=enterprise_id, tenant_id=tenant_id,
|
|
|
)
|
|
|
await auth.db.execute(stmt)
|
|
|
+ log.info(f"全员联动 - 新增员工额度: employee_id={employee_id}, institution_id={inst_id}, status={status}, amount={total}")
|
|
|
await auth.db.flush()
|
|
|
except Exception as e:
|
|
|
log.error(f"全员制度联动失败: {e}")
|