135 lines
5.2 KiB
TypeScript
135 lines
5.2 KiB
TypeScript
import { QueryInterface, DataTypes } from 'sequelize';
|
|
|
|
export const up = async (queryInterface: QueryInterface) => {
|
|
// 1. Drop and recreate the enum type for snapshot_type to ensure all values are included
|
|
// This ensures APPROVE is always present when table is recreated
|
|
// Note: Table should be dropped manually before running this migration
|
|
try {
|
|
await queryInterface.sequelize.query(`
|
|
DO $$
|
|
BEGIN
|
|
-- Drop enum if it exists (cascade will handle any dependencies)
|
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'enum_dealer_claim_history_snapshot_type') THEN
|
|
DROP TYPE IF EXISTS enum_dealer_claim_history_snapshot_type CASCADE;
|
|
END IF;
|
|
|
|
-- Create enum with all values including APPROVE
|
|
CREATE TYPE enum_dealer_claim_history_snapshot_type AS ENUM ('PROPOSAL', 'COMPLETION', 'INTERNAL_ORDER', 'WORKFLOW', 'APPROVE');
|
|
END $$;
|
|
`);
|
|
} catch (error) {
|
|
// If enum creation fails, log error but continue
|
|
console.error('Enum creation error:', error);
|
|
throw error;
|
|
}
|
|
|
|
// 2. Create new simplified level-based dealer_claim_history table
|
|
await queryInterface.createTable('dealer_claim_history', {
|
|
history_id: {
|
|
type: DataTypes.UUID,
|
|
defaultValue: DataTypes.UUIDV4,
|
|
primaryKey: true
|
|
},
|
|
request_id: {
|
|
type: DataTypes.UUID,
|
|
allowNull: false,
|
|
references: {
|
|
model: 'workflow_requests',
|
|
key: 'request_id'
|
|
},
|
|
onUpdate: 'CASCADE',
|
|
onDelete: 'CASCADE'
|
|
},
|
|
approval_level_id: {
|
|
type: DataTypes.UUID,
|
|
allowNull: true, // Nullable for workflow-level snapshots
|
|
references: {
|
|
model: 'approval_levels',
|
|
key: 'level_id'
|
|
},
|
|
onUpdate: 'CASCADE',
|
|
onDelete: 'SET NULL'
|
|
},
|
|
level_number: {
|
|
type: DataTypes.INTEGER,
|
|
allowNull: true, // Nullable for workflow-level snapshots
|
|
comment: 'Level number for easier querying (e.g., 1=Dealer, 3=Dept Lead, 4/5=Completion)'
|
|
},
|
|
level_name: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true, // Nullable for workflow-level snapshots
|
|
comment: 'Level name for consistent matching (e.g., "Dealer Proposal Submission", "Department Lead Approval")'
|
|
},
|
|
version: {
|
|
type: DataTypes.INTEGER,
|
|
allowNull: false,
|
|
comment: 'Version number for this specific level (starts at 1 per level)'
|
|
},
|
|
snapshot_type: {
|
|
type: DataTypes.ENUM('PROPOSAL', 'COMPLETION', 'INTERNAL_ORDER', 'WORKFLOW', 'APPROVE'),
|
|
allowNull: false,
|
|
comment: 'Type of snapshot: PROPOSAL (Step 1), COMPLETION (Step 4/5), INTERNAL_ORDER (Step 3), WORKFLOW (general), APPROVE (approver actions with comments)'
|
|
},
|
|
snapshot_data: {
|
|
type: DataTypes.JSONB,
|
|
allowNull: false,
|
|
comment: 'JSON object containing all snapshot data specific to this level and type. Structure varies by snapshot_type.'
|
|
},
|
|
change_reason: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: true,
|
|
comment: 'Reason for this version change (e.g., "Revision Requested: ...")'
|
|
},
|
|
changed_by: {
|
|
type: DataTypes.UUID,
|
|
allowNull: false,
|
|
references: {
|
|
model: 'users',
|
|
key: 'user_id'
|
|
}
|
|
},
|
|
created_at: {
|
|
type: DataTypes.DATE,
|
|
allowNull: false,
|
|
defaultValue: DataTypes.NOW
|
|
}
|
|
});
|
|
|
|
// Add indexes for efficient querying
|
|
await queryInterface.addIndex('dealer_claim_history', ['request_id', 'level_number', 'version'], {
|
|
name: 'idx_history_request_level_version'
|
|
});
|
|
await queryInterface.addIndex('dealer_claim_history', ['approval_level_id', 'version'], {
|
|
name: 'idx_history_level_version'
|
|
});
|
|
await queryInterface.addIndex('dealer_claim_history', ['request_id', 'snapshot_type'], {
|
|
name: 'idx_history_request_type'
|
|
});
|
|
await queryInterface.addIndex('dealer_claim_history', ['snapshot_type', 'level_number'], {
|
|
name: 'idx_history_type_level'
|
|
});
|
|
await queryInterface.addIndex('dealer_claim_history', ['request_id', 'level_name'], {
|
|
name: 'idx_history_request_level_name'
|
|
});
|
|
await queryInterface.addIndex('dealer_claim_history', ['level_name', 'snapshot_type'], {
|
|
name: 'idx_history_level_name_type'
|
|
});
|
|
// Index for JSONB queries on snapshot_data
|
|
await queryInterface.addIndex('dealer_claim_history', ['snapshot_type'], {
|
|
name: 'idx_history_snapshot_type',
|
|
using: 'BTREE'
|
|
});
|
|
};
|
|
|
|
export const down = async (queryInterface: QueryInterface) => {
|
|
// Note: Table should be dropped manually
|
|
// Drop the enum type
|
|
try {
|
|
await queryInterface.sequelize.query(`
|
|
DROP TYPE IF EXISTS enum_dealer_claim_history_snapshot_type CASCADE;
|
|
`);
|
|
} catch (error) {
|
|
console.warn('Enum drop warning:', error);
|
|
}
|
|
};
|