Files
arrr-erp/alembic/versions/20260822_sales_customer_learning_phase15.py
T
2026-08-22 22:43:44 +05:30

96 lines
6.4 KiB
Python

"""Phase 15 customer and sales ledger intelligence.
Revision ID: 20260822_sales_customer_learning_p15
Revises: 20260822_sales_income_foundation_p14
"""
from alembic import op
import sqlalchemy as sa
revision = "20260822_sales_customer_learning_p15"
down_revision = "20260822_sales_income_foundation_p14"
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
"accounting_sales_historical_runs",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False),
sa.Column("client_id", sa.Integer(), sa.ForeignKey("clients.id", ondelete="CASCADE"), nullable=False),
sa.Column("tally_guid", sa.String(120), nullable=False, server_default=""),
sa.Column("company_name", sa.String(255), nullable=False, server_default=""),
sa.Column("workstation_agent_id", sa.Integer(), sa.ForeignKey("erp_workstation_agents.id", ondelete="SET NULL"), nullable=True),
sa.Column("agent_job_id", sa.Integer(), sa.ForeignKey("erp_agent_jobs.id", ondelete="SET NULL"), nullable=True),
sa.Column("date_from", sa.String(20), nullable=False, server_default=""),
sa.Column("date_to", sa.String(20), nullable=False, server_default=""),
sa.Column("status", sa.String(30), nullable=False, server_default="queued"),
sa.Column("evidence_rows", sa.Integer(), nullable=False, server_default="0"),
sa.Column("error_message", sa.Text(), nullable=True),
sa.Column("requested_by_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True),
sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.Column("completed_at_utc", sa.DateTime(timezone=True), nullable=True),
)
for name in ("tenant_id","client_id","tally_guid","workstation_agent_id","agent_job_id","status","created_at_utc"):
op.create_index(f"ix_accounting_sales_historical_runs_{name}", "accounting_sales_historical_runs", [name])
op.create_table(
"accounting_sales_historical_evidence",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False),
sa.Column("client_id", sa.Integer(), sa.ForeignKey("clients.id", ondelete="CASCADE"), nullable=False),
sa.Column("tally_guid", sa.String(120), nullable=False, server_default=""),
sa.Column("company_name", sa.String(255), nullable=False, server_default=""),
sa.Column("party_ledger_name", sa.String(255), nullable=False),
sa.Column("party_parent_group", sa.String(255), nullable=False, server_default=""),
sa.Column("counter_ledger_name", sa.String(255), nullable=False),
sa.Column("counter_parent_group", sa.String(255), nullable=False, server_default=""),
sa.Column("voucher_type_name", sa.String(160), nullable=False, server_default="Sales"),
sa.Column("voucher_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("absolute_amount_total", sa.Float(), nullable=False, server_default="0"),
sa.Column("first_voucher_date", sa.String(20), nullable=True),
sa.Column("last_voucher_date", sa.String(20), nullable=True),
sa.Column("sample_narration", sa.Text(), nullable=True),
sa.Column("refreshed_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.UniqueConstraint(
"tenant_id","client_id","tally_guid","party_ledger_name","counter_ledger_name","voucher_type_name",
name="uq_sales_hist_evidence",
),
)
for name in ("tenant_id","client_id","tally_guid","party_ledger_name","counter_ledger_name","voucher_type_name","refreshed_at_utc"):
op.create_index(f"ix_accounting_sales_historical_evidence_{name}", "accounting_sales_historical_evidence", [name])
op.create_table(
"accounting_sales_customer_mappings",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False),
sa.Column("client_id", sa.Integer(), sa.ForeignKey("clients.id", ondelete="CASCADE"), nullable=False),
sa.Column("customer_name", sa.String(255), nullable=False, server_default=""),
sa.Column("normalized_customer_name", sa.String(255), nullable=False, server_default=""),
sa.Column("customer_gstin", sa.String(20), nullable=False, server_default=""),
sa.Column("identity_key", sa.String(300), nullable=False),
sa.Column("tally_guid", sa.String(120), nullable=False, server_default=""),
sa.Column("tally_customer_ledger_name", sa.String(255), nullable=False, server_default=""),
sa.Column("nature_id", sa.Integer(), sa.ForeignKey("accounting_natures.id", ondelete="SET NULL"), nullable=True),
sa.Column("sales_ledger_name", sa.String(255), nullable=False, server_default=""),
sa.Column("source", sa.String(30), nullable=False, server_default="review"),
sa.Column("evidence_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("confidence_percent", sa.Integer(), nullable=False, server_default="0"),
sa.Column("total_amount", sa.Float(), nullable=False, server_default="0"),
sa.Column("last_seen_date", sa.String(20), nullable=False, server_default=""),
sa.Column("confirmed_by_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True),
sa.Column("confirmed_at_utc", sa.DateTime(timezone=True), nullable=True),
sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.Column("updated_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.UniqueConstraint("tenant_id","client_id","identity_key", name="uq_sales_customer_mapping_identity"),
)
for name in ("tenant_id","client_id","normalized_customer_name","customer_gstin","identity_key","tally_guid","nature_id","source","created_at_utc"):
op.create_index(f"ix_accounting_sales_customer_mappings_{name}", "accounting_sales_customer_mappings", [name])
def downgrade():
op.drop_table("accounting_sales_customer_mappings")
op.drop_table("accounting_sales_historical_evidence")
op.drop_table("accounting_sales_historical_runs")