Move AQMM controls to assurance engagement workflow

This commit is contained in:
A R R R Associates
2026-07-07 10:29:27 +05:30
parent cd355d6fc5
commit 05c882304b
10 changed files with 943 additions and 82 deletions
+132
View File
@@ -386,6 +386,21 @@ class ClientServiceSubscription(CommonBase):
end_date: Mapped[date | None] = mapped_column(Date, nullable=True)
status: Mapped[str] = mapped_column(String(30), nullable=False, default="active", index=True)
remarks: Mapped[str | None] = mapped_column(Text, nullable=True)
# AQMM / engagement-level quality workflow. This is intentionally attached
# to the engagement/subscription, not to the client master, because one
# client can have both assurance and non-assurance services in the same FY.
quality_workflow_required: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, index=True)
quality_workflow_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_acceptance_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_independence_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_conflict_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_kyc_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_engagement_letter_status: Mapped[str] = mapped_column(String(40), nullable=False, default="not_required", index=True)
quality_approved_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True, index=True)
quality_approved_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
quality_block_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, index=True)
is_locked: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, index=True)
locked_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
@@ -405,6 +420,123 @@ class ClientServiceSubscription(CommonBase):
assigned_staff = relationship("User", foreign_keys=[assigned_staff_user_id])
review_partner = relationship("User", foreign_keys=[review_partner_user_id])
locked_by = relationship("User", foreign_keys=[locked_by_user_id])
quality_approved_by = relationship("User", foreign_keys=[quality_approved_by_user_id])
class EngagementQualityDeclaration(CommonBase):
"""Digital AQMM declaration attached to an assurance engagement.
Used for independence and conflict confirmations from the assigned partner,
review partner, manager, staff and any other engagement team member.
"""
__tablename__ = "engagement_quality_declarations"
__table_args__ = (
UniqueConstraint(
"subscription_id",
"declaration_type",
"requested_user_id",
name="uq_engagement_quality_declaration_user_type",
),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
subscription_id: Mapped[int] = mapped_column(ForeignKey("client_service_subscriptions.id", ondelete="CASCADE"), nullable=False, index=True)
declaration_type: Mapped[str] = mapped_column(String(40), nullable=False, index=True) # independence / conflict
requested_user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
requested_role: Mapped[str | None] = mapped_column(String(80), nullable=True)
status: Mapped[str] = mapped_column(String(40), nullable=False, default="pending", index=True)
declaration_text: Mapped[str | None] = mapped_column(Text, nullable=True)
response_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
responded_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
ip_address: Mapped[str | None] = mapped_column(String(80), nullable=True)
user_agent: Mapped[str | None] = mapped_column(String(500), nullable=True)
created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)
subscription = relationship("ClientServiceSubscription")
client = relationship("Client")
requested_user = relationship("User", foreign_keys=[requested_user_id])
created_by = relationship("User", foreign_keys=[created_by_user_id])
class EngagementKycVerification(CommonBase):
"""KYC verification for an assurance engagement using existing permanent documents."""
__tablename__ = "engagement_kyc_verifications"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
subscription_id: Mapped[int] = mapped_column(ForeignKey("client_service_subscriptions.id", ondelete="CASCADE"), nullable=False, index=True)
status: Mapped[str] = mapped_column(String(40), nullable=False, default="pending_verification", index=True)
source: Mapped[str] = mapped_column(String(80), nullable=False, default="permanent_documents")
verification_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
verified_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
verified_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)
subscription = relationship("ClientServiceSubscription")
client = relationship("Client")
verified_by = relationship("User", foreign_keys=[verified_by_user_id])
created_by = relationship("User", foreign_keys=[created_by_user_id])
class EngagementLetter(CommonBase):
"""Engagement-specific letter acceptance evidence.
Supports both client OTP acceptance and manual signed PDF upload/verification.
File upload storage can be extended without changing the AQMM gate fields.
"""
__tablename__ = "engagement_letters"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
subscription_id: Mapped[int] = mapped_column(ForeignKey("client_service_subscriptions.id", ondelete="CASCADE"), nullable=False, index=True)
title: Mapped[str] = mapped_column(String(255), nullable=False, default="Engagement Letter")
version_no: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
status: Mapped[str] = mapped_column(String(50), nullable=False, default="draft_pending", index=True)
acceptance_mode: Mapped[str | None] = mapped_column(String(40), nullable=True) # digital_otp / manual_signed_upload
body_text: Mapped[str | None] = mapped_column(Text, nullable=True)
pdf_sha256: Mapped[str | None] = mapped_column(String(128), nullable=True)
manual_upload_filename: Mapped[str | None] = mapped_column(String(255), nullable=True)
manual_upload_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
client_acceptance_declaration: Mapped[str | None] = mapped_column(Text, nullable=True)
partner_approved_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
partner_approved_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
client_accepted_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
client_accepted_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
manual_verified_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
manual_verified_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
ip_address: Mapped[str | None] = mapped_column(String(80), nullable=True)
user_agent: Mapped[str | None] = mapped_column(String(500), nullable=True)
created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)
subscription = relationship("ClientServiceSubscription")
client = relationship("Client")
partner_approved_by = relationship("User", foreign_keys=[partner_approved_by_user_id])
client_accepted_by = relationship("User", foreign_keys=[client_accepted_by_user_id])
manual_verified_by = relationship("User", foreign_keys=[manual_verified_by_user_id])
created_by = relationship("User", foreign_keys=[created_by_user_id])
class ClientServiceTaskInstance(CommonBase):