Re_Backend/src/migrations/20251211-create-claim-budget-tracking-table.ts

198 lines
5.6 KiB
TypeScript

import { QueryInterface, DataTypes } from 'sequelize';
export async function up(queryInterface: QueryInterface): Promise<void> {
// Create claim_budget_tracking table for comprehensive budget management
await queryInterface.createTable('claim_budget_tracking', {
budget_id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4
},
request_id: {
type: DataTypes.UUID,
allowNull: false,
unique: true,
references: {
model: 'workflow_requests',
key: 'request_id'
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE'
},
// Initial Budget (from claim creation)
initial_estimated_budget: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Initial estimated budget when claim was created'
},
// Proposal Budget (from Step 1 - Dealer Proposal)
proposal_estimated_budget: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Total estimated budget from dealer proposal'
},
proposal_submitted_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When dealer submitted proposal'
},
// Approved Budget (from Step 2 - Requestor Evaluation)
approved_budget: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Budget approved by requestor in Step 2'
},
approved_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When budget was approved by requestor'
},
approved_by: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'users',
key: 'user_id'
},
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
comment: 'User who approved the budget'
},
// IO Blocked Budget (from Step 3 - Department Lead)
io_blocked_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Amount blocked in IO (from internal_orders table)'
},
io_blocked_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When budget was blocked in IO'
},
// Closed Expenses (from Step 5 - Dealer Completion)
closed_expenses: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Total closed expenses from completion documents'
},
closed_expenses_submitted_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When completion expenses were submitted'
},
// Final Claim Amount (from Step 6 - Requestor Claim Approval)
final_claim_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Final claim amount approved/modified by requestor in Step 6'
},
final_claim_amount_approved_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When final claim amount was approved'
},
final_claim_amount_approved_by: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'users',
key: 'user_id'
},
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
comment: 'User who approved final claim amount'
},
// Credit Note (from Step 8 - Finance)
credit_note_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Credit note amount issued by finance'
},
credit_note_issued_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When credit note was issued'
},
// Budget Status
budget_status: {
type: DataTypes.ENUM('DRAFT', 'PROPOSED', 'APPROVED', 'BLOCKED', 'CLOSED', 'SETTLED'),
defaultValue: 'DRAFT',
allowNull: false,
comment: 'Current status of budget lifecycle'
},
// Currency
currency: {
type: DataTypes.STRING(3),
defaultValue: 'INR',
allowNull: false,
comment: 'Currency code (INR, USD, etc.)'
},
// Budget Variance
variance_amount: {
type: DataTypes.DECIMAL(15, 2),
allowNull: true,
comment: 'Difference between approved and closed expenses (closed - approved)'
},
variance_percentage: {
type: DataTypes.DECIMAL(5, 2),
allowNull: true,
comment: 'Variance as percentage of approved budget'
},
// Audit fields
last_modified_by: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'users',
key: 'user_id'
},
onDelete: 'SET NULL',
onUpdate: 'CASCADE',
comment: 'Last user who modified budget'
},
last_modified_at: {
type: DataTypes.DATE,
allowNull: true,
comment: 'When budget was last modified'
},
modification_reason: {
type: DataTypes.TEXT,
allowNull: true,
comment: 'Reason for budget modification'
},
created_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
},
updated_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
}
});
// Create indexes
await queryInterface.addIndex('claim_budget_tracking', ['request_id'], {
name: 'idx_claim_budget_tracking_request_id',
unique: true
});
await queryInterface.addIndex('claim_budget_tracking', ['budget_status'], {
name: 'idx_claim_budget_tracking_status'
});
await queryInterface.addIndex('claim_budget_tracking', ['approved_by'], {
name: 'idx_claim_budget_tracking_approved_by'
});
await queryInterface.addIndex('claim_budget_tracking', ['final_claim_amount_approved_by'], {
name: 'idx_claim_budget_tracking_final_approved_by'
});
}
export async function down(queryInterface: QueryInterface): Promise<void> {
await queryInterface.dropTable('claim_budget_tracking');
}