267e80e2ec
- Refactor server initialization to separate concerns and improve error handling. - Implement centralized environment validation using Zod. - Introduce database, Redis, and queue lifecycle management. - Add health check endpoints for liveness and readiness. - Enhance error handling middleware for better response structure. - Implement rate limiting for API endpoints. - Add request ID middleware for traceability. - Create Sequelize CLI configuration and baseline migration for schema management. - Establish CI workflow with Gitea for testing and syntax checks. - Document foundational changes and migration strategy in PHASE_0_FOUNDATION_STABILIZATION.md. - Add Docker Compose configuration for local development and testing. - Implement unit and integration tests for critical functionality.
104 lines
7.5 KiB
JavaScript
104 lines
7.5 KiB
JavaScript
"use strict";
|
|
|
|
const tableName = (value) => typeof value === "string" ? value : value.tableName;
|
|
|
|
module.exports = {
|
|
async up(queryInterface, Sequelize) {
|
|
const existing = new Set((await queryInterface.showAllTables()).map(tableName));
|
|
const create = async (name, columns, options = {}) => {
|
|
if (!existing.has(name)) await queryInterface.createTable(name, columns, options);
|
|
};
|
|
const timestamps = {
|
|
createdAt: { type: Sequelize.DATE, allowNull: false },
|
|
updatedAt: { type: Sequelize.DATE, allowNull: false },
|
|
};
|
|
|
|
await create("users", {
|
|
id: { type: Sequelize.STRING, primaryKey: true }, firstName: { type: Sequelize.STRING, allowNull: false },
|
|
lastName: { type: Sequelize.STRING, allowNull: false }, email: { type: Sequelize.STRING, allowNull: false, unique: true },
|
|
password: { type: Sequelize.STRING, allowNull: false },
|
|
accountType: { type: Sequelize.ENUM("admin", "superadmin", "manager", "business_customer", "rider", "customer", "support_agent"), defaultValue: "customer" },
|
|
accountStatus: { type: Sequelize.ENUM("PENDING_VERIFICATION", "ACTIVE", "SUSPENDED", "DEACTIVATED"), allowNull: false, defaultValue: "PENDING_VERIFICATION" },
|
|
emailVerifiedAt: { type: Sequelize.DATE, allowNull: true, defaultValue: null }, ...timestamps,
|
|
});
|
|
await create("profiles", {
|
|
profile_id: { type: Sequelize.STRING, primaryKey: true },
|
|
user_id: { type: Sequelize.STRING, allowNull: false, unique: true, references: { model: "users", key: "id" } },
|
|
theme: { type: Sequelize.STRING, allowNull: false, defaultValue: "light" }, notificationsEnabled: { type: Sequelize.BOOLEAN, defaultValue: true },
|
|
profilePicture_id: { type: Sequelize.STRING, allowNull: true }, backgroundImage_id: { type: Sequelize.STRING, allowNull: true },
|
|
dob: { type: Sequelize.DATE, allowNull: true }, phone_number: { type: Sequelize.STRING, allowNull: true }, ...timestamps,
|
|
});
|
|
await create("customers", {
|
|
customer_id: { type: Sequelize.STRING, primaryKey: true },
|
|
user_id: { type: Sequelize.STRING, allowNull: false, unique: true, references: { model: "users", key: "id" } },
|
|
address: { type: Sequelize.STRING, allowNull: false }, phoneNumber: { type: Sequelize.STRING, allowNull: false }, ...timestamps,
|
|
});
|
|
await create("business_customers", {
|
|
business_customer_id: { type: Sequelize.STRING, primaryKey: true },
|
|
user_id: { type: Sequelize.STRING, allowNull: false, unique: true, references: { model: "users", key: "id" } },
|
|
businessName: { type: Sequelize.STRING, allowNull: false }, businessRegistrationNumber: { type: Sequelize.STRING, allowNull: false },
|
|
businessType: { type: Sequelize.STRING, allowNull: false }, contactName: { type: Sequelize.STRING, allowNull: false },
|
|
phoneNumber: { type: Sequelize.STRING, allowNull: false }, businessEmail: { type: Sequelize.STRING, allowNull: false },
|
|
expectedMonthlyVolume: { type: Sequelize.STRING, allowNull: false }, note: { type: Sequelize.STRING, allowNull: true }, ...timestamps,
|
|
});
|
|
await create("roles", {
|
|
role_id: { type: Sequelize.STRING, primaryKey: true }, roleName: { type: Sequelize.STRING, allowNull: false },
|
|
roleDescription: { type: Sequelize.TEXT, allowNull: true }, ...timestamps,
|
|
});
|
|
await create("permission", {
|
|
permission_id: { type: Sequelize.STRING, primaryKey: true }, permissionName: { type: Sequelize.STRING, allowNull: false },
|
|
permissionDescription: { type: Sequelize.TEXT, allowNull: true }, page: { type: Sequelize.STRING, allowNull: false },
|
|
module: { type: Sequelize.STRING, allowNull: false }, action: { type: Sequelize.STRING, allowNull: false }, ...timestamps,
|
|
});
|
|
await create("rolePermission", {
|
|
rp_id: { type: Sequelize.STRING, primaryKey: true }, role_id: { type: Sequelize.STRING, allowNull: false, references: { model: "roles", key: "role_id" } },
|
|
permission_id: { type: Sequelize.STRING, allowNull: false, references: { model: "permission", key: "permission_id" } }, ...timestamps,
|
|
});
|
|
await create("userPermission", {
|
|
up_id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
|
|
user_id: { type: Sequelize.STRING, allowNull: false, references: { model: "users", key: "id" } },
|
|
permission_id: { type: Sequelize.STRING, allowNull: false, references: { model: "permission", key: "permission_id" } }, ...timestamps,
|
|
});
|
|
await create("uploads", {
|
|
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, file_path: { type: Sequelize.STRING, allowNull: false },
|
|
file_type: { type: Sequelize.STRING, allowNull: false }, file_size: { type: Sequelize.INTEGER, allowNull: false },
|
|
original_name: { type: Sequelize.STRING, allowNull: false }, use_for: { type: Sequelize.STRING, allowNull: false },
|
|
uploaded_by: { type: Sequelize.STRING, allowNull: false }, ...timestamps,
|
|
});
|
|
await create("UserActivity", {
|
|
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, user_id: { type: Sequelize.STRING, allowNull: false },
|
|
username: { type: Sequelize.STRING, allowNull: false }, activity_description: { type: Sequelize.STRING, allowNull: false },
|
|
activity_type: { type: Sequelize.STRING, allowNull: true }, module: { type: Sequelize.STRING, allowNull: true },
|
|
activity_time: { type: Sequelize.DATE, allowNull: false }, activity_date: { type: Sequelize.DATEONLY, allowNull: false }, ...timestamps,
|
|
});
|
|
await create("Document", {
|
|
doc_id: { type: Sequelize.STRING, primaryKey: true }, reference_no: { type: Sequelize.STRING, allowNull: false },
|
|
doc_type: { type: Sequelize.STRING, allowNull: true, defaultValue: "N/A" }, data: { type: Sequelize.JSON, allowNull: false },
|
|
status: { type: Sequelize.STRING, allowNull: false, defaultValue: "DRAFT" }, ...timestamps,
|
|
});
|
|
await create("DocumentType", {
|
|
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
|
|
doc_type_name: { type: Sequelize.STRING, allowNull: true, defaultValue: "N/A" }, description: { type: Sequelize.JSON, allowNull: false }, ...timestamps,
|
|
});
|
|
await create("referenceNumbers", {
|
|
id: { type: Sequelize.STRING, primaryKey: true }, sequence_key: { type: Sequelize.STRING, allowNull: false, unique: true },
|
|
current_number: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }, last_ref_number: { type: Sequelize.STRING }, ...timestamps,
|
|
});
|
|
await create("notification", {
|
|
notification_id: { type: Sequelize.STRING, primaryKey: true }, notificationHeadline: { type: Sequelize.STRING, allowNull: false },
|
|
notificationDescription: { type: Sequelize.TEXT, allowNull: true }, notificationType: { type: Sequelize.ENUM("USER", "ANNOUNCEMENT"), allowNull: false },
|
|
isActive: { type: Sequelize.BOOLEAN, defaultValue: true }, dateCreated: { type: Sequelize.DATE, defaultValue: Sequelize.fn("NOW") }, ...timestamps,
|
|
});
|
|
await create("user_notification", {
|
|
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, user_id: { type: Sequelize.STRING(255), allowNull: false },
|
|
notification_id: { type: Sequelize.STRING, allowNull: false }, isRead: { type: Sequelize.BOOLEAN, defaultValue: false }, ...timestamps,
|
|
});
|
|
},
|
|
|
|
async down(queryInterface) {
|
|
for (const name of ["user_notification", "notification", "referenceNumbers", "DocumentType", "Document", "UserActivity", "uploads", "userPermission", "rolePermission", "permission", "roles", "business_customers", "customers", "profiles", "users"]) {
|
|
await queryInterface.dropTable(name);
|
|
}
|
|
},
|
|
};
|