Add task category master for service task templates

This commit is contained in:
A R R R Associates
2026-08-30 21:42:32 +05:30
parent 31b576b363
commit ad0815c807
9 changed files with 328 additions and 11 deletions
@@ -0,0 +1,48 @@
"""add service task category master
Revision ID: 20260830_task_category_master
Revises: 20260825_opening_balance_p21a
"""
from alembic import op
import sqlalchemy as sa
revision = "20260830_task_category_master"
down_revision = "20260825_opening_balance_p21a"
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
"service_task_categories",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=True),
sa.Column("service_catalogue_id", sa.Integer(), sa.ForeignKey("service_catalogues.id", ondelete="CASCADE"), nullable=False),
sa.Column("code", sa.String(50), nullable=False),
sa.Column("name", sa.String(100), nullable=False),
sa.Column("sort_order", sa.Integer(), nullable=False, server_default="100"),
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.true()),
sa.Column("created_by_user_id", sa.Integer(), sa.ForeignKey("users.id"), nullable=True),
sa.Column("updated_by_user_id", sa.Integer(), sa.ForeignKey("users.id"), 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", "service_catalogue_id", "code", name="uq_service_task_categories_scope_code"),
)
for col in ("tenant_id", "service_catalogue_id", "code", "name"):
op.create_index(f"ix_service_task_categories_{col}", "service_task_categories", [col])
for table in ("service_default_task_templates", "firm_service_task_templates"):
op.add_column(table, sa.Column("task_category_id", sa.Integer(), sa.ForeignKey("service_task_categories.id", ondelete="SET NULL"), nullable=True))
op.create_index(f"ix_{table}_task_category_id", table, ["task_category_id"])
# Preserve all existing free-text categories by materialising them into the new master.
op.execute("""INSERT INTO service_task_categories (tenant_id, service_catalogue_id, code, name, sort_order, is_active, created_at_utc, updated_at_utc) SELECT DISTINCT ON (d.service_catalogue_id, lower(trim(d.task_category))) NULL, d.service_catalogue_id, substr(regexp_replace(upper(trim(d.task_category)), '[^A-Z0-9]+', '-', 'g'),1,40) || '-' || substr(md5(lower(trim(d.task_category))),1,8), trim(d.task_category), 100, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP FROM service_default_task_templates d WHERE d.task_category IS NOT NULL AND trim(d.task_category) <> '' ORDER BY d.service_catalogue_id, lower(trim(d.task_category)), trim(d.task_category)""")
op.execute("""INSERT INTO service_task_categories (tenant_id, service_catalogue_id, code, name, sort_order, is_active, created_at_utc, updated_at_utc) SELECT DISTINCT ON (f.tenant_id, f.service_catalogue_id, lower(trim(f.task_category))) f.tenant_id, f.service_catalogue_id, substr(regexp_replace(upper(trim(f.task_category)), '[^A-Z0-9]+', '-', 'g'),1,40) || '-' || substr(md5(lower(trim(f.task_category))),1,8), trim(f.task_category), 100, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP FROM firm_service_task_templates f WHERE f.task_category IS NOT NULL AND trim(f.task_category) <> '' ORDER BY f.tenant_id, f.service_catalogue_id, lower(trim(f.task_category)), trim(f.task_category)""")
op.execute("""UPDATE service_default_task_templates d SET task_category_id = c.id FROM service_task_categories c WHERE c.tenant_id IS NULL AND c.service_catalogue_id=d.service_catalogue_id AND lower(c.name)=lower(trim(d.task_category))""")
op.execute("""UPDATE firm_service_task_templates f SET task_category_id = c.id FROM service_task_categories c WHERE c.tenant_id=f.tenant_id AND c.service_catalogue_id=f.service_catalogue_id AND lower(c.name)=lower(trim(f.task_category))""")
def downgrade():
for table in ("firm_service_task_templates", "service_default_task_templates"):
op.drop_index(f"ix_{table}_task_category_id", table_name=table)
op.drop_column(table, "task_category_id")
for col in ("name", "code", "service_catalogue_id", "tenant_id"):
op.drop_index(f"ix_service_task_categories_{col}", table_name="service_task_categories")
op.drop_table("service_task_categories")