import { Model, DataTypes, Sequelize, Op } from 'sequelize'; import { CONSTITUTIONAL_CHANGE_TYPES, CONSTITUTIONAL_STAGES } from '../../../../common/config/constants.js'; export interface ConstitutionalChangeAttributes { id: string; requestId: string; outletId: string | null; dealerId: string; changeType: typeof CONSTITUTIONAL_CHANGE_TYPES[keyof typeof CONSTITUTIONAL_CHANGE_TYPES]; description: string; currentConstitution: string | null; oldValue: string | null; newValue: string | null; currentStage: typeof CONSTITUTIONAL_STAGES[keyof typeof CONSTITUTIONAL_STAGES]; status: string; progressPercentage: number; metadata: any; documents: any[]; timeline: any[]; } export interface ConstitutionalChangeInstance extends Model, ConstitutionalChangeAttributes { } export default (sequelize: Sequelize) => { const ConstitutionalChange = sequelize.define('ConstitutionalChange', { id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true }, requestId: { type: DataTypes.STRING, unique: true, allowNull: false }, outletId: { type: DataTypes.UUID, allowNull: true, references: { model: 'outlets', key: 'id' } }, dealerId: { type: DataTypes.UUID, allowNull: false, references: { model: 'users', key: 'id' } }, changeType: { type: DataTypes.ENUM(...Object.values(CONSTITUTIONAL_CHANGE_TYPES)), allowNull: false }, description: { type: DataTypes.TEXT, allowNull: false }, currentConstitution: { type: DataTypes.STRING, allowNull: true }, oldValue: { type: DataTypes.STRING, allowNull: true }, newValue: { type: DataTypes.STRING, allowNull: true }, currentStage: { type: DataTypes.ENUM(...Object.values(CONSTITUTIONAL_STAGES)), defaultValue: CONSTITUTIONAL_STAGES.ASM_REVIEW }, status: { type: DataTypes.STRING, defaultValue: 'Pending' }, progressPercentage: { type: DataTypes.INTEGER, defaultValue: 0 }, metadata: { type: DataTypes.JSON, defaultValue: {} }, documents: { type: DataTypes.JSON, defaultValue: [] }, timeline: { type: DataTypes.JSON, defaultValue: [] } }, { tableName: 'constitutional_changes', timestamps: true, indexes: [ { fields: ['requestId'] }, { fields: ['outletId'] }, { fields: ['dealerId'] }, { fields: ['currentStage'] }, /** SRS §12.2 — at most one non-terminal request per dealer (PostgreSQL partial unique index). */ { name: 'uq_constitutional_open_per_dealer', unique: true, fields: ['dealerId'], where: { status: { [Op.notIn]: ['Completed', 'Closed', 'Rejected', 'Revoked'] } } } ] }); (ConstitutionalChange as any).associate = (models: any) => { ConstitutionalChange.belongsTo(models.Outlet, { foreignKey: 'outletId', as: 'outlet' }); ConstitutionalChange.belongsTo(models.User, { foreignKey: 'dealerId', as: 'dealer' }); ConstitutionalChange.hasMany(models.ConstitutionalDocument, { foreignKey: 'constitutionalChangeId', as: 'uploadedDocuments' }); ConstitutionalChange.hasMany(models.Worknote, { foreignKey: 'requestId', as: 'worknotes', scope: { requestType: 'constitutional' }, constraints: false }); ConstitutionalChange.hasMany(models.RequestParticipant, { foreignKey: 'requestId', as: 'participants', scope: { requestType: 'constitutional' }, constraints: false }); }; return ConstitutionalChange; };