feat: implement business pricing service and money utilities
- Added `businessPricing.service.js` to handle business customer pricing logic. - Introduced `money.js` for money parsing, formatting, and calculations. - Created `pricing.service.js` to manage variant quoting and promotion application. - Updated validation schemas in `catalogue.schemas.js` and `inventoryMerchandising.schemas.js` for new pricing and inventory features. - Implemented cron job for inventory reservation expiry in `inventoryReservationExpiry.cron.js`. - Created database migrations for catalogue and inventory structures. - Added unit tests for catalogue localization, validation, and inventory merchandising functionalities.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("Brand",{id:{type:D.STRING,primaryKey:true},name:{type:D.STRING(160),allowNull:false},slug:{type:D.STRING(180),allowNull:false,unique:true},description:D.TEXT,logo_upload_id:D.INTEGER,website:D.STRING,status:{type:D.ENUM("ACTIVE","INACTIVE"),allowNull:false,defaultValue:"INACTIVE"},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"brands",timestamps:true});M.associate=m=>{M.hasMany(m.Product,{foreignKey:"brand_id",as:"products"});M.belongsTo(m.Upload,{foreignKey:"logo_upload_id",as:"logo",constraints:false});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("Category",{id:{type:D.STRING,primaryKey:true},parent_id:D.STRING,code:{type:D.STRING(80),allowNull:false,unique:true},slug:{type:D.STRING(180),allowNull:false,unique:true},status:{type:D.ENUM("ACTIVE","INACTIVE"),allowNull:false,defaultValue:"INACTIVE"},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0},image_upload_id:D.INTEGER},{tableName:"categories",timestamps:true});M.associate=m=>{M.belongsTo(M,{foreignKey:"parent_id",as:"parent"});M.hasMany(M,{foreignKey:"parent_id",as:"children"});M.hasMany(m.CategoryTranslation,{foreignKey:"category_id",as:"translations"});M.belongsToMany(m.Product,{through:m.ProductCategory,foreignKey:"category_id",otherKey:"product_id",as:"products"});M.belongsTo(m.Upload,{foreignKey:"image_upload_id",as:"image",constraints:false});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("CategoryTranslation",{id:{type:D.STRING,primaryKey:true},category_id:{type:D.STRING,allowNull:false},locale:{type:D.ENUM("en","si","ta"),allowNull:false},name:{type:D.STRING(180),allowNull:false},description:D.TEXT,meta_title:D.STRING(180),meta_description:D.STRING(320)},{tableName:"category_translations",timestamps:true,indexes:[{unique:true,fields:["category_id","locale"]}]});M.associate=m=>M.belongsTo(m.Category,{foreignKey:"category_id",as:"category"});return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("Collection",{id:{type:D.STRING,primaryKey:true},slug:{type:D.STRING(180),allowNull:false,unique:true},type:{type:D.STRING(80),allowNull:false,defaultValue:"EDITORIAL"},status:{type:D.ENUM("DRAFT","ACTIVE","INACTIVE"),allowNull:false,defaultValue:"DRAFT"},starts_at:D.DATE,ends_at:D.DATE,hero_upload_id:D.INTEGER,sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"collections",timestamps:true});M.associate=m=>{M.hasMany(m.CollectionTranslation,{foreignKey:"collection_id",as:"translations"});M.belongsToMany(m.Product,{through:m.CollectionProduct,foreignKey:"collection_id",otherKey:"product_id",as:"products"});M.belongsTo(m.Upload,{foreignKey:"hero_upload_id",as:"hero",constraints:false});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>s.define("CollectionProduct",{id:{type:D.STRING,primaryKey:true},collection_id:{type:D.STRING,allowNull:false},product_id:{type:D.STRING,allowNull:false},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0},featured:{type:D.BOOLEAN,allowNull:false,defaultValue:false}},{tableName:"collection_products",timestamps:true,indexes:[{unique:true,fields:["collection_id","product_id"]}]});
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("CollectionTranslation",{id:{type:D.STRING,primaryKey:true},collection_id:{type:D.STRING,allowNull:false},locale:{type:D.ENUM("en","si","ta"),allowNull:false},name:{type:D.STRING(180),allowNull:false},description:D.TEXT,headline:D.STRING(250),subheadline:D.STRING(300)},{tableName:"collection_translations",timestamps:true,indexes:[{unique:true,fields:["collection_id","locale"]}]});M.associate=m=>M.belongsTo(m.Collection,{foreignKey:"collection_id",as:"collection"});return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("Product",{id:{type:D.STRING,primaryKey:true},brand_id:{type:D.STRING,allowNull:false},default_category_id:D.STRING,slug:{type:D.STRING(200),allowNull:false,unique:true},product_code:{type:D.STRING(100),allowNull:false,unique:true},status:{type:D.ENUM("DRAFT","ACTIVE","INACTIVE","ARCHIVED"),allowNull:false,defaultValue:"DRAFT"},visibility:{type:D.ENUM("PUBLIC","HIDDEN"),allowNull:false,defaultValue:"HIDDEN"},product_type:{type:D.STRING(80),allowNull:false,defaultValue:"STANDARD"},featured:{type:D.BOOLEAN,allowNull:false,defaultValue:false},new_arrival_until:D.DATE,published_at:D.DATE,created_by:{type:D.STRING,allowNull:false},updated_by:D.STRING,size_guide_id:D.STRING},{tableName:"products",timestamps:true});M.associate=m=>{M.belongsTo(m.Brand,{foreignKey:"brand_id",as:"brand"});M.belongsTo(m.Category,{foreignKey:"default_category_id",as:"defaultCategory"});M.hasMany(m.ProductTranslation,{foreignKey:"product_id",as:"translations"});M.hasMany(m.ProductVariant,{foreignKey:"product_id",as:"variants"});M.hasMany(m.ProductOption,{foreignKey:"product_id",as:"options"});M.hasMany(m.ProductAttribute,{foreignKey:"product_id",as:"attributes"});M.hasMany(m.ProductMedia,{foreignKey:"product_id",as:"media"});M.belongsToMany(m.Category,{through:m.ProductCategory,foreignKey:"product_id",otherKey:"category_id",as:"categories"});M.belongsTo(m.SizeGuide,{foreignKey:"size_guide_id",as:"sizeGuide"});M.hasMany(m.ProductReview,{foreignKey:"product_id",as:"reviews"});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductAttribute",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},name:{type:D.STRING(100),allowNull:false},value:{type:D.STRING(500),allowNull:false},locale:{type:D.ENUM("en","si","ta"),allowNull:false,defaultValue:"en"},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"product_attributes",timestamps:true});M.associate=m=>M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductCategory",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},category_id:{type:D.STRING,allowNull:false}},{tableName:"product_categories",timestamps:true,indexes:[{unique:true,fields:["product_id","category_id"]}]});return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductMedia",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},variant_id:D.STRING,upload_id:{type:D.INTEGER,allowNull:false},type:{type:D.ENUM("IMAGE"),allowNull:false,defaultValue:"IMAGE"},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0},alt_text:D.STRING(250),is_primary:{type:D.BOOLEAN,allowNull:false,defaultValue:false}},{tableName:"product_media",timestamps:true,indexes:[{unique:true,fields:["product_id","upload_id"]}]});M.associate=m=>{M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});M.belongsTo(m.ProductVariant,{foreignKey:"variant_id",as:"variant"});M.belongsTo(m.Upload,{foreignKey:"upload_id",as:"upload",constraints:false});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductOption",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},name:{type:D.STRING(100),allowNull:false},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"product_options",timestamps:true,indexes:[{unique:true,fields:["product_id","name"]}]});M.associate=m=>{M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});M.hasMany(m.ProductOptionValue,{foreignKey:"option_id",as:"values"});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductOptionValue",{id:{type:D.STRING,primaryKey:true},option_id:{type:D.STRING,allowNull:false},value:{type:D.STRING(100),allowNull:false},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"product_option_values",timestamps:true,indexes:[{unique:true,fields:["option_id","value"]}]});M.associate=m=>{M.belongsTo(m.ProductOption,{foreignKey:"option_id",as:"option"});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>s.define("ProductRelation",{id:{type:D.STRING,primaryKey:true},source_product_id:{type:D.STRING,allowNull:false},target_product_id:{type:D.STRING,allowNull:false},relation_type:{type:D.ENUM("RELATED","SIMILAR","COMPLETE_THE_LOOK"),allowNull:false},sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"product_relations",timestamps:true,indexes:[{unique:true,fields:["source_product_id","target_product_id","relation_type"]}]});
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductReview",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},user_id:{type:D.STRING,allowNull:false},rating:{type:D.INTEGER,allowNull:false,validate:{min:1,max:5}},title:{type:D.STRING(160),allowNull:false},body:{type:D.TEXT,allowNull:false},status:{type:D.ENUM("PENDING","APPROVED","REJECTED"),allowNull:false,defaultValue:"PENDING"},verified_purchase:{type:D.BOOLEAN,allowNull:false,defaultValue:false},moderated_by:D.STRING,moderated_at:D.DATE},{tableName:"product_reviews",timestamps:true,indexes:[{unique:true,fields:["user_id","product_id"]}]});M.associate=m=>{M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});M.belongsTo(m.User,{foreignKey:"user_id",as:"author"});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductTranslation",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},locale:{type:D.ENUM("en","si","ta"),allowNull:false},name:{type:D.STRING(220),allowNull:false},short_description:D.STRING(500),description:D.TEXT,care_instructions:D.TEXT,materials:D.TEXT,origin:D.STRING(120),meta_title:D.STRING(180),meta_description:D.STRING(320)},{tableName:"product_translations",timestamps:true,indexes:[{unique:true,fields:["product_id","locale"]}]});M.associate=m=>M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>{const M=s.define("ProductVariant",{id:{type:D.STRING,primaryKey:true},product_id:{type:D.STRING,allowNull:false},sku:{type:D.STRING(100),allowNull:false,unique:true},barcode:{type:D.STRING(100),unique:true},status:{type:D.ENUM("ACTIVE","INACTIVE"),allowNull:false,defaultValue:"ACTIVE"},base_price:{type:D.DECIMAL(15,2),allowNull:false},compare_at_price:D.DECIMAL(15,2),currency:{type:D.STRING(3),allowNull:false,defaultValue:"LKR"},weight:D.DECIMAL(10,3),sort_order:{type:D.INTEGER,allowNull:false,defaultValue:0}},{tableName:"product_variants",timestamps:true});M.associate=m=>{M.belongsTo(m.Product,{foreignKey:"product_id",as:"product"});M.belongsToMany(m.ProductOptionValue,{through:m.VariantOptionValue,foreignKey:"variant_id",otherKey:"option_value_id",as:"optionValues"});M.hasMany(m.ProductMedia,{foreignKey:"variant_id",as:"media"});};return M;};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>s.define("SizeGuide",{id:{type:D.STRING,primaryKey:true},code:{type:D.STRING(80),allowNull:false,unique:true},name:{type:D.STRING(160),allowNull:false},locale:{type:D.ENUM("en","si","ta"),allowNull:false,defaultValue:"en"},data:{type:D.JSON,allowNull:false},category_id:D.STRING,status:{type:D.ENUM("ACTIVE","INACTIVE"),allowNull:false,defaultValue:"ACTIVE"}},{tableName:"size_guides",timestamps:true});
|
||||
@@ -0,0 +1 @@
|
||||
module.exports=(s,D)=>s.define("VariantOptionValue",{id:{type:D.STRING,primaryKey:true},variant_id:{type:D.STRING,allowNull:false},option_value_id:{type:D.STRING,allowNull:false}},{tableName:"variant_option_values",timestamps:true,indexes:[{unique:true,fields:["variant_id","option_value_id"]}]});
|
||||
Reference in New Issue
Block a user