diff --git a/package-lock.json b/package-lock.json index eb61f2b..4fcec39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,8 @@ "supertest": "^7.0.0", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.0", - "ts-node": "^10.9.2" + "ts-node": "^10.9.2", + "uuid": "^9.0.1" }, "devDependencies": { "@types/bcrypt": "^5.0.2", @@ -8724,6 +8725,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/sequelize/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -9581,9 +9590,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } diff --git a/package.json b/package.json index 99fb976..41713e0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "supertest": "^7.0.0", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.0", - "ts-node": "^10.9.2" + "ts-node": "^10.9.2", + "uuid": "^9.0.1" }, "devDependencies": { "@types/bcrypt": "^5.0.2", diff --git a/src/database/migrations/20240520101722-create-user.js b/src/database/migrations/20240520101722-create-user.js index fd58e0c..a0b134e 100644 --- a/src/database/migrations/20240520101722-create-user.js +++ b/src/database/migrations/20240520101722-create-user.js @@ -15,7 +15,8 @@ module.exports = { }, email:{ type: Sequelize.STRING, - allowNull: false + allowNull: false, + unique: true }, password:{ type: Sequelize.STRING, @@ -52,4 +53,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('Users'); } -}; \ No newline at end of file +}; diff --git a/src/database/migrations/20240520134354-create-vendor.js b/src/database/migrations/20240520134354-create-vendor.js index cf3bb22..06bd66d 100644 --- a/src/database/migrations/20240520134354-create-vendor.js +++ b/src/database/migrations/20240520134354-create-vendor.js @@ -26,11 +26,13 @@ module.exports = { allowNull: false }, TIN:{ - type: Sequelize.INTEGER, - allowNull: false + type: Sequelize.BIGINT, + allowNull: false, + unique: true }, bankAccount:{ - type: Sequelize.INTEGER, + type: Sequelize.BIGINT, + unique: true }, paymentDetails: { type: Sequelize.JSONB @@ -52,4 +54,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('Vendors'); } -}; \ No newline at end of file +}; diff --git a/src/database/migrations/20240520140651-create-product.js b/src/database/migrations/20240520140651-create-product.js index 4ca9545..1ea4ec6 100644 --- a/src/database/migrations/20240520140651-create-product.js +++ b/src/database/migrations/20240520140651-create-product.js @@ -29,7 +29,7 @@ module.exports = { allowNull: false }, discount:{ - type: Sequelize.STRING, + type: Sequelize.DOUBLE, allowNull: false }, price:{ @@ -55,4 +55,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('Products'); } -}; \ No newline at end of file +}; diff --git a/src/database/migrations/20240520141938-create-cart-item.js b/src/database/migrations/20240520141938-create-cart-item.js index a81b65a..e07a285 100644 --- a/src/database/migrations/20240520141938-create-cart-item.js +++ b/src/database/migrations/20240520141938-create-cart-item.js @@ -11,24 +11,23 @@ module.exports = { }, cartId: { type: Sequelize.STRING, - references:{ + references: { model: 'Carts', key: 'cartId' } }, - productId:{ + productId: { type: Sequelize.STRING, - references:{ + references: { model: 'Products', key: 'productId' } }, - quantinty:{ + quantity: { type: Sequelize.INTEGER, allowNull: false, defaultValue: 1 - }, price: { type: Sequelize.INTEGER, @@ -47,4 +46,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('CartItems'); } -}; \ No newline at end of file +}; diff --git a/src/database/migrations/20240520143222-create-admin.js b/src/database/migrations/20240520143222-create-admin.js index 699f054..2214d73 100644 --- a/src/database/migrations/20240520143222-create-admin.js +++ b/src/database/migrations/20240520143222-create-admin.js @@ -10,7 +10,8 @@ module.exports = { defaultValue: Sequelize.UUIDV4 }, email: { - type: Sequelize.STRING + type: Sequelize.STRING, + unique: true }, password: { type: Sequelize.STRING @@ -28,4 +29,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('Admins'); } -}; \ No newline at end of file +}; diff --git a/src/database/migrations/20240520143257-create-subscription.js b/src/database/migrations/20240520143257-create-subscription.js index 4f64265..e3c1b8f 100644 --- a/src/database/migrations/20240520143257-create-subscription.js +++ b/src/database/migrations/20240520143257-create-subscription.js @@ -10,7 +10,8 @@ module.exports = { defaultValue: Sequelize.UUIDV4 }, email: { - type: Sequelize.STRING + type: Sequelize.STRING, + unique: true }, createdAt: { allowNull: false, @@ -25,4 +26,4 @@ module.exports = { async down(queryInterface, Sequelize) { await queryInterface.dropTable('Subscriptions'); } -}; \ No newline at end of file +}; diff --git a/src/database/seeders/20240521193841-seed-users.js b/src/database/seeders/20240521193841-seed-users.js new file mode 100644 index 0000000..3bfbb41 --- /dev/null +++ b/src/database/seeders/20240521193841-seed-users.js @@ -0,0 +1,94 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const profileUrl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXhCG6nff2emBYOKGHb6jU2zQ4C2m0LBg4Mj-eydwZyg&s' + await queryInterface.bulkInsert('Users', [ + { + userId: uuidv4(), + name: 'User1', + email: 'user1@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + }, + { + userId: uuidv4(), + name: 'User2', + email: 'user2@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + }, { + userId: uuidv4(), + name: 'User3', + email: 'user3@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + }, + { + userId: uuidv4(), + name: 'User4', + email: 'user4@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + }, + { + userId: uuidv4(), + name: 'User5', + email: 'user5@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + }, { + + userId: uuidv4(), + name: 'User6', + email: 'user6@email.com', + password: 'password1', + status: 'active', + wishlistId: null, + cartId: null, + role: 'buyer', + profile: profileUrl, + createdAt: new Date(), + updatedAt: new Date() + } + ], {}); + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Users', null, {}); + } +}; diff --git a/src/database/seeders/20240521201427-seed-carts.js b/src/database/seeders/20240521201427-seed-carts.js new file mode 100644 index 0000000..cb4bf31 --- /dev/null +++ b/src/database/seeders/20240521201427-seed-carts.js @@ -0,0 +1,38 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + console.log('Getting the users') + const [users] = await queryInterface.sequelize.query(`SELECT "userId" FROM "Users"`); + + users.map(user => ( + console.log('The users ', user) + )) + + const carts = users.map(user => ({ + cartId: uuidv4(), + // @ts-ignore + userId: user.userId, + createdAt: new Date(), + updatedAt: new Date() + })); + + await queryInterface.bulkInsert('Carts', carts, {}); + + for (const cart of carts) { + await queryInterface.bulkUpdate('Users', + { cartId: cart.cartId }, + { userId: cart.userId } + ); + } + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Carts', null, {}); + await queryInterface.bulkUpdate('Users', { cartId: null }, { cartId: { [Sequelize.Op.ne]: null } }); + } +}; diff --git a/src/database/seeders/20240521204207-seed-vendors.js b/src/database/seeders/20240521204207-seed-vendors.js new file mode 100644 index 0000000..a8623d0 --- /dev/null +++ b/src/database/seeders/20240521204207-seed-vendors.js @@ -0,0 +1,50 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const [users] = await queryInterface.sequelize.query(` + SELECT "userId" + FROM "Users" + ORDER BY "createdAt" DESC + LIMIT 3; + `); + + const vendors = users.map(user => ({ + vendorId: uuidv4(), + // @ts-ignore + userId: user.userId, + storeName: `Store ${Math.floor(Math.random() * (11))}`, + address: JSON.stringify({ + street: 'KG 111 ST', + city: 'Kigali' + }), + TIN: Math.floor(Math.random() * 100000000), + bankAccount: Math.floor(Math.random() * 1000000000), + paymentDetails: JSON.stringify({ + method: 'Bank Transfer', + bankName: 'Bank Of Kigali' + }), + status: 'pending', + createdAt: new Date(), + updatedAt: new Date() + })) + + await queryInterface.bulkInsert('Vendors', vendors, {}); + + await queryInterface.bulkUpdate('Users', + { role: 'vendor' }, + // @ts-ignore + { userId: users.map(user => user.userId) } + ); + }, + + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Vendors', null, {}); + await queryInterface.bulkUpdate('Users', { role: 'buyer' }, { role: 'vendor' }); + } +}; diff --git a/src/database/seeders/20240522064825-seed-products.js b/src/database/seeders/20240522064825-seed-products.js new file mode 100644 index 0000000..cf5a0fa --- /dev/null +++ b/src/database/seeders/20240522064825-seed-products.js @@ -0,0 +1,40 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const imageUrl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXhCG6nff2emBYOKGHb6jU2zQ4C2m0LBg4Mj-eydwZyg&s' + + const [vendors] = await queryInterface.sequelize.query(` + SELECT "vendorId" + FROM "Vendors" + ORDER BY "createdAt" DESC + LIMIT 3; + `); + + const products = vendors.map(vendor => ({ + productId: uuidv4(), + // @ts-ignore + vendorId: vendor.vendorId, + name: 'nike shoes', + image: imageUrl, + description: 'These are nike shoes.', + discount: 2, + price: 12000, + quantity: 100, + category: 'Shoes', + createdAt: new Date(), + updatedAt: new Date() + })) + + await queryInterface.bulkInsert('Products', products, {}); + }, + + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Products', null, {}); + } +}; diff --git a/src/database/seeders/20240522070922-seed-wishlists.js b/src/database/seeders/20240522070922-seed-wishlists.js new file mode 100644 index 0000000..ecad181 --- /dev/null +++ b/src/database/seeders/20240522070922-seed-wishlists.js @@ -0,0 +1,50 @@ +'use strict'; + +// @ts-ignore +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + // @ts-ignore + async up(queryInterface, Sequelize) { + const [users] = await queryInterface.sequelize.query(` + SELECT "userId" + FROM "Users" + ORDER BY "createdAt" DESC + LIMIT 3; + `); + + const [products] = await queryInterface.sequelize.query(` + SELECT "productId" + FROM "Products" + LIMIT 3; + `); + + const wishlists = users.flatMap(user => + products.map(product => ({ + wishlistId: uuidv4(), + // @ts-ignore + userId: user.userId, + // @ts-ignore + productId: product.productId, + createdAt: new Date(), + updatedAt: new Date() + })) + ); + + await queryInterface.bulkInsert('Wishlists', wishlists, {}); + + for (const wishlist of wishlists) { + await queryInterface.bulkUpdate('Users', + { wishlistId: wishlist.wishlistId }, + { userId: wishlist.userId } + ); + } + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Carts', null, {}); + await queryInterface.bulkUpdate('Users', { wishlistId: null }, { wishlistId: { [Sequelize.Op.ne]: null } }); + } +}; diff --git a/src/database/seeders/20240522073044-seed-cartitems.js b/src/database/seeders/20240522073044-seed-cartitems.js new file mode 100644 index 0000000..9ae691a --- /dev/null +++ b/src/database/seeders/20240522073044-seed-cartitems.js @@ -0,0 +1,44 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const [carts] = await queryInterface.sequelize.query(` + SELECT "cartId" + FROM "Carts" + ORDER BY "createdAt" DESC + LIMIT 3; + `); + + const [products] = await queryInterface.sequelize.query(` + SELECT "productId", "price" + FROM "Products" + LIMIT 3; + `); + + const quantity = 10 + + const cartItems = carts.flatMap(cart => + products.map(product => ({ + cartitemsid: uuidv4(), + // @ts-ignore + cartId: cart.cartId, + // @ts-ignore + productId: product.productId, + quantity: quantity, + // @ts-ignore + price: product.price * quantity, + createdAt: new Date(), + updatedAt: new Date() + }))) + + await queryInterface.bulkInsert('CartItems', cartItems, {}); + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('CartItems', null, {}) + } +}; diff --git a/src/database/seeders/20240522075149-seed-orders.js b/src/database/seeders/20240522075149-seed-orders.js new file mode 100644 index 0000000..e8acd39 --- /dev/null +++ b/src/database/seeders/20240522075149-seed-orders.js @@ -0,0 +1,49 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const [users] = await queryInterface.sequelize.query(` + SELECT "userId" + FROM "Users" + LIMIT 3; + `); + + const [products] = await queryInterface.sequelize.query(` + SELECT "productId", "name" + FROM "Products" + LIMIT 3; + `); + + const orders = users.flatMap(user => + products.map(product => ({ + orderId: uuidv4(), + deliveryAddress: JSON.stringify({ + street: 'KG 111 ST', + city: 'Kigali' + }), + // @ts-ignore + userId: user.userId, + paymentMethod: 'Bank Transfer', + status: 'pending', + products: JSON.stringify({ + // @ts-ignore + productId: product.productId, + // @ts-ignore + productName: product.name + }), + createdAt: new Date(), + updatedAt: new Date() + }))) + + await queryInterface.bulkInsert('Orders', orders, {}); + + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Orders', null, {}) + } +}; diff --git a/src/database/seeders/20240522080345-seed-admins.js b/src/database/seeders/20240522080345-seed-admins.js new file mode 100644 index 0000000..605b8e0 --- /dev/null +++ b/src/database/seeders/20240522080345-seed-admins.js @@ -0,0 +1,31 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert('Admins', [ + { + adminId: uuidv4(), + email: 'admin1@email.com', + password: 'password1', + createdAt: new Date(), + updatedAt: new Date() + }, + { + adminId: uuidv4(), + email: 'admin2@email.com', + password: 'password1', + createdAt: new Date(), + updatedAt: new Date() + } + ], {}); + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Admins', null, {}); + + } +}; diff --git a/src/database/seeders/20240522081008-seed-messages.js b/src/database/seeders/20240522081008-seed-messages.js new file mode 100644 index 0000000..a937d70 --- /dev/null +++ b/src/database/seeders/20240522081008-seed-messages.js @@ -0,0 +1,32 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert('Messages', [ + { + contactId: uuidv4(), + name: 'Testing', + email: 'test@email.com', + content: 'Hello thank you', + createdAt: new Date(), + updatedAt: new Date() + }, + { + contactId: uuidv4(), + name: 'Testing', + email: 'test@email.com', + content: 'Hello thanks', + createdAt: new Date(), + updatedAt: new Date() + } + ], {}); + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Messages', null, {}); + } +}; diff --git a/src/database/seeders/20240522081616-seed-subscriptions.js b/src/database/seeders/20240522081616-seed-subscriptions.js new file mode 100644 index 0000000..bedf08c --- /dev/null +++ b/src/database/seeders/20240522081616-seed-subscriptions.js @@ -0,0 +1,33 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert('Subscriptions', [ + { + subscriptionId: uuidv4(), + email: 'subscriber1@gmail.com', + createdAt: new Date(), + updatedAt: new Date() + }, + { + subscriptionId: uuidv4(), + email: 'subscriber2@gmail.com', + createdAt: new Date(), + updatedAt: new Date() + }, + { + subscriptionId: uuidv4(), + email: 'subscriber3@gmail.com', + createdAt: new Date(), + updatedAt: new Date() + }], {}) + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Subscriptions', null, {}); + } +}; diff --git a/src/database/seeders/20240522082250-seed-ratings.js b/src/database/seeders/20240522082250-seed-ratings.js new file mode 100644 index 0000000..a9bd727 --- /dev/null +++ b/src/database/seeders/20240522082250-seed-ratings.js @@ -0,0 +1,40 @@ +'use strict'; + +const { v4: uuidv4 } = require('uuid'); + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const [users] = await queryInterface.sequelize.query(` + SELECT "userId" + FROM "Users" + LIMIT 3; + `); + + const [vendors] = await queryInterface.sequelize.query(` + SELECT "vendorId" + FROM "Vendors" + LIMIT 3; + `); + + const ratings = users.flatMap(user => + vendors.map(vendor => ({ + ratingId: uuidv4(), + ratingScore: 5, + // @ts-ignore + userId: user.userId, + // @ts-ignore + vendorId: vendor.vendorId, + createdAt: new Date(), + updatedAt: new Date() + }))) + + await queryInterface.bulkInsert('Ratings', ratings, {}); + + }, + + async down(queryInterface, Sequelize) { + // @ts-ignore + await queryInterface.bulkDelete('Ratings', null, {}) + } +}; diff --git a/src/database/seeders/users.ts b/src/database/seeders/users.ts deleted file mode 100644 index 4716b2e..0000000 --- a/src/database/seeders/users.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const userss = [ - { - username: "Imanishimwe" - }, - { - username: "Rukundo" - }, -] \ No newline at end of file