Add Phase 19 bank accounting and reconciliation workflow
This commit is contained in:
@@ -162,7 +162,7 @@ def pending_count_for_user(user_id: int) -> int:
|
||||
db.close()
|
||||
|
||||
|
||||
def enqueue_job(*, user, roles: Iterable[str], job_id: str, paths: list[Path], job_dir: Path, bank_selection: str, financial_year: str, customer_override: str, account_override: str, classification_enabled: bool, client_id: int | None = None, engagement_id: int | None = None, ownership_confirmation: bool = False) -> BankStatementAnalysisJob:
|
||||
def enqueue_job(*, user, roles: Iterable[str], job_id: str, paths: list[Path], job_dir: Path, bank_selection: str, financial_year: str, customer_override: str, account_override: str, classification_enabled: bool, client_id: int | None = None, engagement_id: int | None = None, ownership_confirmation: bool = False, purpose: str = "analyze_only") -> BankStatementAnalysisJob:
|
||||
if pending_count_for_user(int(user.id)) >= MAX_PENDING_PER_USER:
|
||||
shutil.rmtree(job_dir, ignore_errors=True)
|
||||
raise ValueError("You already have three queued or processing analyses. Please wait for one to complete before submitting another.")
|
||||
@@ -186,6 +186,12 @@ def enqueue_job(*, user, roles: Iterable[str], job_id: str, paths: list[Path], j
|
||||
customer_override=(customer_override or "").strip() or None,
|
||||
account_override=(account_override or "").strip() or None,
|
||||
classification_enabled=bool(classification_enabled),
|
||||
purpose=(purpose if purpose in {"analyze_only", "accounting_entries", "bank_reconciliation"} else "analyze_only"),
|
||||
accounting_import_status=(
|
||||
"pending"
|
||||
if purpose in {"accounting_entries", "bank_reconciliation"}
|
||||
else "not_requested"
|
||||
),
|
||||
status="queued",
|
||||
progress_percent=0,
|
||||
file_count=len(paths),
|
||||
@@ -333,6 +339,46 @@ def _process_job(job_id: str) -> None:
|
||||
job.completed_at_utc = _now()
|
||||
job.expires_at_utc = _now() + timedelta(hours=COMPLETED_RETENTION_HOURS)
|
||||
db.commit()
|
||||
|
||||
# Phase 19 reuses the existing AccountingBankTransaction import path.
|
||||
# Analyze-only remains unchanged. Accounting/Reconciliation jobs import
|
||||
# only after ownership has passed and the workbook has completed.
|
||||
if job.purpose in {"accounting_entries", "bank_reconciliation"}:
|
||||
try:
|
||||
if not job.client_id:
|
||||
raise ValueError(
|
||||
"Accounting / Bank Reconciliation purpose requires an ERP client."
|
||||
)
|
||||
from app.modules.accounting.bank_service import import_completed_job
|
||||
|
||||
added, skipped = import_completed_job(
|
||||
db,
|
||||
tenant_id=int(job.tenant_id or 0),
|
||||
client_id=int(job.client_id),
|
||||
job_id=job.id,
|
||||
user_id=int(job.user_id),
|
||||
)
|
||||
job = db.get(BankStatementAnalysisJob, job.id)
|
||||
job.accounting_import_status = "completed"
|
||||
job.accounting_import_json = json.dumps(
|
||||
{
|
||||
"added": int(added),
|
||||
"skipped_duplicate_fingerprints": int(skipped),
|
||||
"purpose": job.purpose,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
db.commit()
|
||||
except Exception as import_exc:
|
||||
db.rollback()
|
||||
job = db.get(BankStatementAnalysisJob, job_id)
|
||||
if job:
|
||||
job.accounting_import_status = "failed"
|
||||
job.accounting_import_json = json.dumps(
|
||||
{"error": str(import_exc)[:2000]},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
db.commit()
|
||||
except Exception as exc:
|
||||
db.rollback()
|
||||
job = db.get(BankStatementAnalysisJob, job_id)
|
||||
@@ -481,6 +527,9 @@ def job_view(job: BankStatementAnalysisJob) -> dict:
|
||||
"file_count": job.file_count,
|
||||
"selected_bank": job.selected_bank,
|
||||
"financial_year": job.financial_year or "",
|
||||
"purpose": getattr(job, "purpose", "analyze_only"),
|
||||
"accounting_import_status": getattr(job, "accounting_import_status", "not_requested"),
|
||||
"accounting_import": json.loads(job.accounting_import_json) if getattr(job, "accounting_import_json", None) else {},
|
||||
"submitted_at": job.submitted_at_utc,
|
||||
"completed_at": job.completed_at_utc,
|
||||
"expires_at": job.expires_at_utc,
|
||||
|
||||
Reference in New Issue
Block a user