feat(v2): multi-tranche DB schema + gate cumulativo 5 voci Cecilia
A1 migrations.py: - remission_practice DROP uq_application + ADD sequence_number/period_label/suggested_instructor_id - UNIQUE composita (application_id, sequence_number) - partial index idx_remission_practice_unassigned su assigned_instructor_id NULL - nuova tabella remission_custom_check_value (storage_path/mime/size/sha256 allineata adapter) A2 models.py + templates.py: - RemissionPractice: UniqueConstraint composita, campi multi-tranche, relationship custom_checks - classe RemissionCustomCheckValue - RESTART_TEMPLATE schema_version=2, max_tranches=2, custom_checks esempio (antiriciclaggio required no-doc, polizza_fidejussoria optional con-doc) - upgrade_schema_to_v2 idempotente per snapshot v1 esistenti A3 _compute_gate_check(db, practice) CUMULATIVO: - max_remission_global = min(cap_pct * erogato, cap_abs) - already_approved = func.sum(approved_remission) su tranche APPROVED precedenti dello stesso application_id con sequence_number < corrente - max_remission_this_tranche = max(0, global - already_approved) - pre_check_admissible = min(grand_total_declared, this_tranche) [voce 2 Cecilia] - remission_due = min(effective_total, this_tranche) - residuo_da_restituire = erogato - already_approved - remission_due (cumulativo) - output totals esteso: sequence_number, tranches_count, tranches_max - signature (db, practice) - aggiornati 6 call site in practices/instructor/verbale Test su NAPOLI SAS: erogato 17K, cap 8500, tranche 1 approvata 467.14EUR, tranche 2 vuota -> residuo disponibile 8032.86EUR, residuo_da_restituire 16532.86EUR.
This commit is contained in:
@@ -41,6 +41,60 @@ MIGRATIONS = [
|
||||
ADD COLUMN IF NOT EXISTS sha256 varchar(64),
|
||||
ADD COLUMN IF NOT EXISTS uploaded_by integer;
|
||||
""",
|
||||
# 2026-04-18 v2: multi-tranche su remission_practice
|
||||
# DROP UNIQUE su application_id (permette piu tranche per stessa domanda)
|
||||
# aggiunge sequence_number, period_label, suggested_instructor_id
|
||||
# nuova UNIQUE (application_id, sequence_number)
|
||||
# partial index su assigned_instructor_id IS NULL per coda "da assegnare"
|
||||
"""
|
||||
ALTER TABLE gepafin_rendic.remission_practice
|
||||
DROP CONSTRAINT IF EXISTS uq_remission_practice_application;
|
||||
ALTER TABLE gepafin_rendic.remission_practice
|
||||
ADD COLUMN IF NOT EXISTS sequence_number integer NOT NULL DEFAULT 1,
|
||||
ADD COLUMN IF NOT EXISTS period_label varchar(100),
|
||||
ADD COLUMN IF NOT EXISTS suggested_instructor_id integer;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conname = 'uq_remission_practice_app_seq'
|
||||
AND conrelid = 'gepafin_rendic.remission_practice'::regclass
|
||||
) THEN
|
||||
ALTER TABLE gepafin_rendic.remission_practice
|
||||
ADD CONSTRAINT uq_remission_practice_app_seq UNIQUE (application_id, sequence_number);
|
||||
END IF;
|
||||
END$$;
|
||||
CREATE INDEX IF NOT EXISTS idx_remission_practice_unassigned
|
||||
ON gepafin_rendic.remission_practice(assigned_instructor_id)
|
||||
WHERE assigned_instructor_id IS NULL;
|
||||
""",
|
||||
# 2026-04-18 v2: tabella custom checks
|
||||
# allineata allo storage adapter esistente (storage_path + mime + size + sha256)
|
||||
# NON segue le specs RAG p1 che usavano document_filename (v1 obsoleta)
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS gepafin_rendic.remission_custom_check_value (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
practice_id uuid NOT NULL REFERENCES gepafin_rendic.remission_practice(id) ON DELETE CASCADE,
|
||||
check_code varchar(64) NOT NULL,
|
||||
beneficiary_declared boolean NOT NULL DEFAULT false,
|
||||
declared_at timestamptz,
|
||||
storage_path varchar(1024),
|
||||
mime varchar(128),
|
||||
size_bytes bigint,
|
||||
sha256 varchar(64),
|
||||
document_uploaded_at timestamptz,
|
||||
uploaded_by integer,
|
||||
verification_status varchar(20) NOT NULL DEFAULT 'PENDING',
|
||||
verification_notes text,
|
||||
verified_by integer,
|
||||
verified_at timestamptz,
|
||||
created_at timestamptz NOT NULL DEFAULT NOW(),
|
||||
updated_at timestamptz NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_custom_check_practice_code UNIQUE (practice_id, check_code)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_custom_check_practice
|
||||
ON gepafin_rendic.remission_custom_check_value(practice_id);
|
||||
""",
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user