115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import {
|
|
DataTypes,
|
|
Model,
|
|
type CreationOptional,
|
|
type InferAttributes,
|
|
type InferCreationAttributes,
|
|
type Sequelize,
|
|
} from 'sequelize';
|
|
import type { Db } from '@/db/types';
|
|
import type {
|
|
BelongsToGetAssociationMixin,
|
|
BelongsToSetAssociationMixin,
|
|
HasManyGetAssociationsMixin,
|
|
HasManySetAssociationsMixin,
|
|
} from 'sequelize';
|
|
import type { Campuses } from './campuses';
|
|
import type { Organizations } from './organizations';
|
|
import type { Users } from './users';
|
|
|
|
/**
|
|
* School tier (American Organization → School → Campus hierarchy). A school
|
|
* belongs to one organization and owns one or more campuses. The school head is
|
|
* the Principal (school scope); campuses keep their own per-campus `timezone`
|
|
* (a school may span timezones), so timezone is intentionally NOT on this model.
|
|
*/
|
|
export class Schools extends Model<
|
|
InferAttributes<Schools>,
|
|
InferCreationAttributes<Schools>
|
|
> {
|
|
declare id: CreationOptional<string>;
|
|
declare name: string;
|
|
declare code: string;
|
|
declare address: string | null;
|
|
declare phone: string | null;
|
|
declare email: string | null;
|
|
declare description: string | null;
|
|
declare active: CreationOptional<boolean>;
|
|
declare importHash: CreationOptional<string | null>;
|
|
declare organizationId: CreationOptional<string | null>;
|
|
declare createdById: CreationOptional<string | null>;
|
|
declare updatedById: CreationOptional<string | null>;
|
|
declare createdAt: CreationOptional<Date>;
|
|
declare updatedAt: CreationOptional<Date>;
|
|
declare deletedAt: CreationOptional<Date | null>;
|
|
|
|
declare getCampuses_school: HasManyGetAssociationsMixin<Campuses>;
|
|
declare setCampuses_school: HasManySetAssociationsMixin<Campuses, string>;
|
|
declare getOrganization: BelongsToGetAssociationMixin<Organizations>;
|
|
declare setOrganization: BelongsToSetAssociationMixin<Organizations, string>;
|
|
declare getCreatedBy: BelongsToGetAssociationMixin<Users>;
|
|
declare setCreatedBy: BelongsToSetAssociationMixin<Users, string>;
|
|
declare getUpdatedBy: BelongsToGetAssociationMixin<Users>;
|
|
declare setUpdatedBy: BelongsToSetAssociationMixin<Users, string>;
|
|
|
|
static associate(db: Db): void {
|
|
db.schools.hasMany(db.campuses, {
|
|
as: 'campuses_school',
|
|
foreignKey: { name: 'schoolId' },
|
|
constraints: false,
|
|
});
|
|
|
|
db.schools.belongsTo(db.organizations, {
|
|
as: 'organization',
|
|
foreignKey: { name: 'organizationId' },
|
|
constraints: false,
|
|
});
|
|
|
|
db.schools.belongsTo(db.users, { as: 'createdBy' });
|
|
db.schools.belongsTo(db.users, { as: 'updatedBy' });
|
|
}
|
|
}
|
|
|
|
export default function (sequelize: Sequelize): typeof Schools {
|
|
Schools.init(
|
|
{
|
|
id: {
|
|
type: DataTypes.UUID,
|
|
defaultValue: DataTypes.UUIDV4,
|
|
primaryKey: true,
|
|
},
|
|
name: { type: DataTypes.TEXT, allowNull: false },
|
|
code: { type: DataTypes.TEXT, allowNull: false },
|
|
address: { type: DataTypes.TEXT },
|
|
phone: { type: DataTypes.TEXT },
|
|
email: { type: DataTypes.TEXT },
|
|
description: { type: DataTypes.TEXT },
|
|
active: {
|
|
type: DataTypes.BOOLEAN,
|
|
allowNull: false,
|
|
defaultValue: false,
|
|
},
|
|
importHash: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true,
|
|
unique: true,
|
|
},
|
|
organizationId: { type: DataTypes.UUID, allowNull: true },
|
|
createdById: { type: DataTypes.UUID, allowNull: true },
|
|
updatedById: { type: DataTypes.UUID, allowNull: true },
|
|
createdAt: { type: DataTypes.DATE },
|
|
updatedAt: { type: DataTypes.DATE },
|
|
deletedAt: { type: DataTypes.DATE },
|
|
},
|
|
{
|
|
sequelize,
|
|
modelName: 'schools',
|
|
timestamps: true,
|
|
paranoid: true,
|
|
freezeTableName: true,
|
|
},
|
|
);
|
|
|
|
return Schools;
|
|
}
|