feat: implement customer profile management and business application features
- Added customer profile controller with endpoints for retrieving, updating, and deactivating user profiles. - Introduced address model and routes for managing user addresses. - Created business application model and service for handling business applications, including approval and rejection processes. - Developed business contact and credit account models to support business customer functionalities. - Implemented settlement term model for managing payment terms. - Added email templates for business application notifications (approved, rejected, received, and status changes). - Enhanced validation schemas for customer and business inputs to ensure data integrity. - Created unit tests for business application service and validation schemas to ensure functionality and correctness. - Added migration scripts to set up new database tables and columns for customer and business features.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const Address = sequelize.define("Address", {
|
||||
id: { type: DataTypes.STRING, primaryKey: true },
|
||||
user_id: { type: DataTypes.STRING, allowNull: true },
|
||||
business_profile_id: { type: DataTypes.STRING, allowNull: true },
|
||||
label: { type: DataTypes.STRING(50), allowNull: false }, recipient_name: { type: DataTypes.STRING(150), allowNull: false }, phone_number: { type: DataTypes.STRING(30), allowNull: false },
|
||||
address_line_1: { type: DataTypes.STRING(255), allowNull: false }, address_line_2: DataTypes.STRING(255), city: { type: DataTypes.STRING(100), allowNull: false }, district: DataTypes.STRING(100), province: DataTypes.STRING(100), postal_code: DataTypes.STRING(20),
|
||||
country_code: { type: DataTypes.STRING(2), allowNull: false }, address_type: { type: DataTypes.ENUM("CUSTOMER", "REGISTERED", "BILLING", "DELIVERY"), allowNull: false, defaultValue: "CUSTOMER" },
|
||||
is_default_shipping: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, is_default_billing: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false },
|
||||
}, { tableName: "addresses", timestamps: true });
|
||||
Address.associate = (models) => { Address.belongsTo(models.User, { foreignKey: "user_id", as: "user" }); Address.belongsTo(models.BusinessCustomer, { foreignKey: "business_profile_id", as: "businessProfile" }); };
|
||||
return Address;
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const Model = sequelize.define("BusinessApplication", {
|
||||
id: { type: DataTypes.STRING, primaryKey: true }, user_id: { type: DataTypes.STRING, allowNull: false },
|
||||
business_name: { type: DataTypes.STRING(180), allowNull: false }, legal_name: { type: DataTypes.STRING(180), allowNull: false }, registration_number: { type: DataTypes.STRING(100), allowNull: false }, tax_number: DataTypes.STRING(100), business_type: { type: DataTypes.STRING(80), allowNull: false }, contact_email: { type: DataTypes.STRING, allowNull: false }, contact_phone: { type: DataTypes.STRING(30), allowNull: false }, website: DataTypes.STRING,
|
||||
status: { type: DataTypes.ENUM("PENDING", "UNDER_REVIEW", "APPROVED", "REJECTED", "CANCELLED"), allowNull: false, defaultValue: "PENDING" }, reviewed_by: DataTypes.STRING, reviewed_at: DataTypes.DATE, rejection_reason: DataTypes.STRING(500),
|
||||
}, { tableName: "business_applications", timestamps: true });
|
||||
Model.associate = (models) => { Model.belongsTo(models.User, { foreignKey: "user_id", as: "applicant" }); Model.belongsTo(models.User, { foreignKey: "reviewed_by", as: "reviewer", constraints: false }); };
|
||||
return Model;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const Model = sequelize.define("BusinessContact", { id: { type: DataTypes.STRING, primaryKey: true }, business_profile_id: { type: DataTypes.STRING, allowNull: false }, name: { type: DataTypes.STRING(150), allowNull: false }, title: DataTypes.STRING(100), email: DataTypes.STRING, phone: DataTypes.STRING(30), is_primary: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false } }, { tableName: "business_contacts", timestamps: true });
|
||||
Model.associate = (models) => Model.belongsTo(models.BusinessCustomer, { foreignKey: "business_profile_id", as: "businessProfile" }); return Model;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const Model = sequelize.define("BusinessCreditAccount", { id: { type: DataTypes.STRING, primaryKey: true }, business_profile_id: { type: DataTypes.STRING, allowNull: false, unique: true }, currency: { type: DataTypes.STRING(3), allowNull: false, defaultValue: "LKR" }, credit_limit: { type: DataTypes.DECIMAL(15,2), allowNull: false, defaultValue: 0 }, status: { type: DataTypes.ENUM("DISABLED", "ACTIVE", "SUSPENDED"), allowNull: false, defaultValue: "DISABLED" } }, { tableName: "business_credit_accounts", timestamps: true });
|
||||
Model.associate = (models) => Model.belongsTo(models.BusinessCustomer, { foreignKey: "business_profile_id", as: "businessProfile" }); return Model;
|
||||
};
|
||||
@@ -21,7 +21,7 @@ module.exports = (sequelize, DataTypes) => {
|
||||
},
|
||||
businessRegistrationNumber: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
allowNull: false, unique: true,
|
||||
},
|
||||
businessType: {
|
||||
type: DataTypes.STRING,
|
||||
@@ -47,6 +47,14 @@ module.exports = (sequelize, DataTypes) => {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
legalName: DataTypes.STRING,
|
||||
taxNumber: DataTypes.STRING,
|
||||
website: DataTypes.STRING,
|
||||
partnerId: { type: DataTypes.STRING, allowNull: false, unique: true },
|
||||
status: { type: DataTypes.ENUM("ACTIVE", "SUSPENDED", "CLOSED"), allowNull: false, defaultValue: "ACTIVE" },
|
||||
approvedAt: { type: DataTypes.DATE, allowNull: false },
|
||||
approvedBy: { type: DataTypes.STRING, allowNull: false },
|
||||
settlement_term_id: { type: DataTypes.STRING, allowNull: true },
|
||||
},
|
||||
{
|
||||
tableName: "business_customers",
|
||||
@@ -59,6 +67,10 @@ module.exports = (sequelize, DataTypes) => {
|
||||
foreignKey: "user_id",
|
||||
as: "user",
|
||||
});
|
||||
BusinessCustomer.hasMany(db.BusinessContact, { foreignKey: "business_profile_id", as: "contacts" });
|
||||
BusinessCustomer.hasMany(db.Address, { foreignKey: "business_profile_id", as: "addresses" });
|
||||
BusinessCustomer.hasOne(db.BusinessCreditAccount, { foreignKey: "business_profile_id", as: "creditAccount" });
|
||||
BusinessCustomer.belongsTo(db.SettlementTerm, { foreignKey: "settlement_term_id", as: "settlementTerm" });
|
||||
};
|
||||
|
||||
return BusinessCustomer;
|
||||
|
||||
@@ -47,7 +47,11 @@ module.exports = (sequelize, DataTypes) => {
|
||||
phone_number:{
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
}
|
||||
},
|
||||
preferred_language: { type: DataTypes.ENUM("en", "si", "ta"), allowNull: false, defaultValue: "en" },
|
||||
marketing_email_enabled: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
|
||||
marketing_push_enabled: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false },
|
||||
in_app_notifications_enabled: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
|
||||
},
|
||||
{
|
||||
tableName: "profiles",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = (sequelize, DataTypes) => sequelize.define("SettlementTerm", { id: { type: DataTypes.STRING, primaryKey: true }, code: { type: DataTypes.STRING(30), allowNull: false, unique: true }, name: { type: DataTypes.STRING(100), allowNull: false }, days: { type: DataTypes.INTEGER, allowNull: false }, is_active: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true } }, { tableName: "settlement_terms", timestamps: true });
|
||||
@@ -88,6 +88,8 @@ module.exports = (sequelize, DataTypes) => {
|
||||
User.hasMany(db.AuthSession, { foreignKey: "user_id", as: "authSessions" });
|
||||
User.hasMany(db.UserIdentity, { foreignKey: "user_id", as: "identities" });
|
||||
User.hasMany(db.UserRole, { foreignKey: "user_id", as: "userRoles" });
|
||||
User.hasMany(db.Address, { foreignKey: "user_id", as: "addresses" });
|
||||
User.hasMany(db.BusinessApplication, { foreignKey: "user_id", as: "businessApplications" });
|
||||
};
|
||||
|
||||
return User;
|
||||
|
||||
Reference in New Issue
Block a user