148 lines
4.4 KiB
TypeScript
148 lines
4.4 KiB
TypeScript
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>, ConstitutionalChangeAttributes { }
|
|
|
|
export default (sequelize: Sequelize) => {
|
|
const ConstitutionalChange = sequelize.define<ConstitutionalChangeInstance>('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;
|
|
};
|