移除特殊费用模块

This commit is contained in:
Cheng Zhou
2026-05-12 10:15:18 +08:00
parent cd7e12ce1f
commit 6e90370a5f
30 changed files with 117 additions and 2819 deletions
-77
View File
@@ -1,77 +0,0 @@
import uuid
from typing import Sequence
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.finance_special import FinanceSpecial
from app.schemas.finance_special import FinanceSpecialCreate, FinanceSpecialUpdate
async def create_special(
db: AsyncSession,
study_id: uuid.UUID,
special_in: FinanceSpecialCreate,
created_by: uuid.UUID | None,
) -> FinanceSpecial:
special = FinanceSpecial(
study_id=study_id,
site_name=special_in.site_name,
fee_type=special_in.fee_type,
amount=special_in.amount,
occur_date=special_in.occur_date,
staff_name=special_in.staff_name,
remark=special_in.remark,
created_by=created_by,
)
db.add(special)
await db.commit()
await db.refresh(special)
return special
async def get_special(db: AsyncSession, special_id: uuid.UUID) -> FinanceSpecial | None:
result = await db.execute(select(FinanceSpecial).where(FinanceSpecial.id == special_id))
return result.scalar_one_or_none()
async def list_specials(
db: AsyncSession,
study_id: uuid.UUID,
site_name: str | None = None,
site_names: set[str] | None = None,
fee_type: str | None = None,
skip: int = 0,
limit: int = 100,
) -> Sequence[FinanceSpecial]:
stmt = (
select(FinanceSpecial)
.where(FinanceSpecial.study_id == study_id)
)
if site_names is not None:
if not site_names:
return []
stmt = stmt.where(FinanceSpecial.site_name.in_(site_names))
if site_name:
stmt = stmt.where(FinanceSpecial.site_name.ilike(f"%{site_name}%"))
if fee_type:
stmt = stmt.where(FinanceSpecial.fee_type == fee_type)
stmt = stmt.order_by(FinanceSpecial.created_at.desc()).offset(skip).limit(limit)
result = await db.execute(stmt)
return result.scalars().all()
async def update_special(
db: AsyncSession, special: FinanceSpecial, special_in: FinanceSpecialUpdate
) -> FinanceSpecial:
update_data = special_in.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(special, key, value)
await db.commit()
await db.refresh(special)
return special
async def delete_special(db: AsyncSession, special: FinanceSpecial) -> None:
await db.delete(special)
await db.commit()
-38
View File
@@ -17,13 +17,11 @@ from app.models.drug_shipment import DrugShipment
from app.models.fee_attachment import FeeAttachment
from app.models.finance import FinanceItem
from app.models.finance_contract import FinanceContract
from app.models.finance_special import FinanceSpecial
from app.models.kickoff_meeting import KickoffMeeting
from app.models.knowledge_note import KnowledgeNote
from app.models.milestone import Milestone
from app.models.monitoring_visit_issue import MonitoringVisitIssue
from app.models.site import Site
from app.models.special_expense import SpecialExpense
from app.models.startup_ethics import StartupEthics
from app.models.startup_feasibility import StartupFeasibility
from app.models.study_center_confirm import StudyCenterConfirm
@@ -158,9 +156,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
contract_fee_ids = (
await db.execute(select(ContractFee.id).where(ContractFee.center_id == site_id))
).scalars().all()
special_expense_ids = (
await db.execute(select(SpecialExpense.id).where(SpecialExpense.center_id == site_id))
).scalars().all()
drug_shipment_ids = (
await db.execute(select(DrugShipment.id).where(DrugShipment.center_id == site_id))
).scalars().all()
@@ -189,14 +184,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
)
)
).scalars().all()
finance_special_ids = (
await db.execute(
select(FinanceSpecial.id).where(
FinanceSpecial.study_id == study_id,
FinanceSpecial.site_name == site_name,
)
)
).scalars().all()
knowledge_note_ids = (
await db.execute(
select(KnowledgeNote.id).where(
@@ -233,7 +220,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
"startup_kickoff_ppt": kickoff_ids,
"training_authorization": training_ids,
"finance_contract": finance_contract_ids,
"finance_special": finance_special_ids,
"knowledge_note": knowledge_note_ids,
"drug_shipment": drug_shipment_ids,
}
@@ -279,23 +265,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
)
)
await db.execute(delete(ContractFeePayment).where(ContractFeePayment.contract_fee_id.in_(contract_fee_ids)))
if special_expense_ids:
fee_attachment_paths.extend(
(
await db.execute(
select(FeeAttachment.storage_key).where(
FeeAttachment.entity_type == "special_expense",
FeeAttachment.entity_id.in_(special_expense_ids),
)
)
).scalars().all()
)
await db.execute(
delete(FeeAttachment).where(
FeeAttachment.entity_type == "special_expense",
FeeAttachment.entity_id.in_(special_expense_ids),
)
)
if distribution_ids:
await db.execute(delete(Acknowledgement).where(Acknowledgement.distribution_id.in_(distribution_ids)))
@@ -327,7 +296,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
await db.execute(delete(StartupEthics).where(StartupEthics.site_id == site_id))
await db.execute(delete(ContractFee).where(ContractFee.center_id == site_id))
await db.execute(delete(SpecialExpense).where(SpecialExpense.center_id == site_id))
await db.execute(delete(DrugShipment).where(DrugShipment.center_id == site_id))
await db.execute(
update(MonitoringVisitIssue)
@@ -347,12 +315,6 @@ async def delete_site_and_related(db: AsyncSession, site: Site) -> None:
FinanceContract.site_name == site_name,
)
)
await db.execute(
delete(FinanceSpecial).where(
FinanceSpecial.study_id == study_id,
FinanceSpecial.site_name == site_name,
)
)
await db.execute(
delete(KnowledgeNote).where(
KnowledgeNote.study_id == study_id,
-104
View File
@@ -1,104 +0,0 @@
import uuid
from datetime import date
from typing import Sequence
from sqlalchemy import and_, func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.attachment import Attachment
from app.models.special_expense import SpecialExpense
from app.models.site import Site
from app.schemas.special_expense import SpecialExpenseCreate, SpecialExpenseUpdate
async def create_special_expense(
db: AsyncSession,
expense_in: SpecialExpenseCreate,
created_by: uuid.UUID | None,
) -> SpecialExpense:
expense = SpecialExpense(
project_id=expense_in.project_id,
center_id=expense_in.center_id,
category=expense_in.category,
amount=expense_in.amount,
happen_date=expense_in.happen_date,
description=expense_in.description,
is_paid=expense_in.is_paid,
paid_date=expense_in.paid_date,
is_verified=expense_in.is_verified,
verified_date=expense_in.verified_date,
created_by=created_by,
)
db.add(expense)
await db.commit()
await db.refresh(expense)
return expense
async def get_special_expense(db: AsyncSession, expense_id: uuid.UUID) -> SpecialExpense | None:
result = await db.execute(select(SpecialExpense).where(SpecialExpense.id == expense_id))
return result.scalar_one_or_none()
async def list_special_expenses(
db: AsyncSession,
project_id: uuid.UUID,
center_id: uuid.UUID | None = None,
center_ids: set[uuid.UUID] | None = None,
category: str | None = None,
date_from: date | None = None,
date_to: date | None = None,
) -> Sequence[tuple[SpecialExpense, str | None, int]]:
attachment_count = func.count(Attachment.id).label("attachments_count")
attachment_types = ["special_expense_voucher", "special_expense_invoice", "special_expense_other"]
stmt = (
select(
SpecialExpense,
Site.name.label("center_name"),
attachment_count,
)
.outerjoin(Site, Site.id == SpecialExpense.center_id)
.outerjoin(
Attachment,
and_(
Attachment.entity_type.in_(attachment_types),
Attachment.entity_id == SpecialExpense.id,
Attachment.is_deleted.is_(False),
),
)
.where(SpecialExpense.project_id == project_id)
.group_by(SpecialExpense.id, Site.name)
.order_by(SpecialExpense.happen_date.desc().nullslast(), SpecialExpense.created_at.desc())
)
if center_id:
stmt = stmt.where(SpecialExpense.center_id == center_id)
if center_ids is not None:
if not center_ids:
return []
stmt = stmt.where(SpecialExpense.center_id.in_(center_ids))
if category:
stmt = stmt.where(SpecialExpense.category == category)
if date_from:
stmt = stmt.where(SpecialExpense.happen_date >= date_from)
if date_to:
stmt = stmt.where(SpecialExpense.happen_date <= date_to)
result = await db.execute(stmt)
return result.all()
async def update_special_expense(
db: AsyncSession, expense: SpecialExpense, expense_in: SpecialExpenseUpdate
) -> SpecialExpense:
update_data = expense_in.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(expense, key, value)
await db.commit()
await db.refresh(expense)
return expense
async def delete_special_expense(db: AsyncSession, expense: SpecialExpense) -> None:
await db.delete(expense)
await db.commit()
-4
View File
@@ -100,10 +100,8 @@ async def delete(db: AsyncSession, study_id: uuid.UUID) -> None:
from app.models.ae import AdverseEvent
from app.models.finance import FinanceItem
from app.models.finance_contract import FinanceContract
from app.models.finance_special import FinanceSpecial
from app.models.contract_fee import ContractFee
from app.models.contract_fee_payment import ContractFeePayment
from app.models.special_expense import SpecialExpense
from app.models.milestone import Milestone
from app.models.document import Document
from app.models.attachment import Attachment
@@ -152,7 +150,6 @@ async def delete(db: AsyncSession, study_id: uuid.UUID) -> None:
await db.execute(sa_delete(Milestone).where(Milestone.study_id == study_id))
# 9. 删除财务相关
await db.execute(sa_delete(SpecialExpense).where(SpecialExpense.project_id == study_id))
await db.execute(
sa_delete(ContractFeePayment).where(
ContractFeePayment.contract_fee_id.in_(
@@ -161,7 +158,6 @@ async def delete(db: AsyncSession, study_id: uuid.UUID) -> None:
)
)
await db.execute(sa_delete(ContractFee).where(ContractFee.project_id == study_id))
await db.execute(sa_delete(FinanceSpecial).where(FinanceSpecial.study_id == study_id))
await db.execute(sa_delete(FinanceContract).where(FinanceContract.study_id == study_id))
await db.execute(sa_delete(FinanceItem).where(FinanceItem.study_id == study_id))