diff --git a/src/database/migrations/20240926095920-create-user.js b/src/database/migrations/20240926095920-create-user.js deleted file mode 100644 index 9e99769..0000000 --- a/src/database/migrations/20240926095920-create-user.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable('Users', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - name: { - type: Sequelize.STRING, - }, - email: { - type: Sequelize.STRING, - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE, - defaultValue: Sequelize.NOW, - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE, - defaultValue: Sequelize.NOW, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable('Users'); - }, -}; diff --git a/src/database/migrations/20240926100622-create-project.js b/src/database/migrations/20240926100622-create-project.js deleted file mode 100644 index 65f68ec..0000000 --- a/src/database/migrations/20240926100622-create-project.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable('article', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - name: { - type: Sequelize.STRING, - }, - description: { - type: Sequelize.TEXT, - }, - userId: { - type: Sequelize.INTEGER, - allowNull: false, - references: { - model: 'User', - key: 'id', - }, - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE, - defaultValue: Sequelize.NOW, - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE, - defaultValue: Sequelize.NOW, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable('article'); - }, -}; diff --git a/src/database/migrations/20251127000000-initial-schema.js b/src/database/migrations/20251127000000-initial-schema.js new file mode 100644 index 0000000..93f8c4d --- /dev/null +++ b/src/database/migrations/20251127000000-initial-schema.js @@ -0,0 +1,624 @@ +'use strict'; + +module.exports = { + async up(queryInterface, Sequelize) { + const transaction = await queryInterface.sequelize.transaction(); + + try { + // Create User table + await queryInterface.createTable('user', { + id: { + type: Sequelize.STRING(24), + allowNull: false, + primaryKey: true + }, + email: { + type: Sequelize.STRING(255), + allowNull: false, + unique: true + }, + username: { + type: Sequelize.STRING(255), + allowNull: false, + unique: true + }, + firstname: { + type: Sequelize.STRING(255), + allowNull: true + }, + lastname: { + type: Sequelize.STRING(255), + allowNull: true + }, + phone: { + type: Sequelize.STRING(20), + allowNull: true + }, + image: { + type: Sequelize.STRING(128), + allowNull: true + }, + role: { + type: Sequelize.STRING(20), + allowNull: true + }, + salt: { + type: Sequelize.STRING(255), + allowNull: false + }, + hash: { + type: Sequelize.TEXT, + allowNull: false + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Tag table + await queryInterface.createTable('tag', { + name: { + type: Sequelize.STRING(255), + allowNull: false, + primaryKey: true + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Role table + await queryInterface.createTable('role', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + name: { + type: Sequelize.STRING(255), + allowNull: true + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Brand table + await queryInterface.createTable('brand', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + name: { + type: Sequelize.STRING(255), + allowNull: true + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Category table + await queryInterface.createTable('category', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + name: { + type: Sequelize.STRING(255), + allowNull: true + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Packaging table + await queryInterface.createTable('packaging', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + name: { + type: Sequelize.STRING(255), + allowNull: true + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Article table + await queryInterface.createTable('article', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + slug: { + type: Sequelize.STRING(255), + allowNull: false + }, + title: { + type: Sequelize.STRING(255), + allowNull: false + }, + description: { + type: Sequelize.TEXT, + allowNull: true + }, + body: { + type: Sequelize.TEXT, + allowNull: false + }, + authorId: { + type: Sequelize.STRING(24), + allowNull: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Comment table + await queryInterface.createTable('comment', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + body: { + type: Sequelize.TEXT, + allowNull: false + }, + authorId: { + type: Sequelize.STRING(24), + allowNull: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + articleId: { + type: Sequelize.INTEGER, + allowNull: true, + references: { + model: 'article', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create TagList table (junction table for Article-Tag) + await queryInterface.createTable('tagList', { + articleId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'article', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + tagName: { + type: Sequelize.STRING(255), + allowNull: false, + primaryKey: true, + references: { + model: 'tag', + key: 'name' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Favorite table (junction table for User-Article) + await queryInterface.createTable('favorite', { + userId: { + type: Sequelize.STRING(24), + allowNull: false, + primaryKey: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + articleId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'article', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Follower table (junction table for User-User) + await queryInterface.createTable('follower', { + userId: { + type: Sequelize.STRING(24), + allowNull: false, + primaryKey: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + followerId: { + type: Sequelize.STRING(24), + allowNull: false, + primaryKey: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create Product table + await queryInterface.createTable('product', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + eancode: { + type: Sequelize.STRING(13), + allowNull: false, + unique: true + }, + name: { + type: Sequelize.STRING(255), + allowNull: false + }, + description: { + type: Sequelize.TEXT, + allowNull: true + }, + stock: { + type: Sequelize.INTEGER, + allowNull: true, + defaultValue: 0 + }, + weightGross: { + type: Sequelize.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00 + }, + weightNet: { + type: Sequelize.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00 + }, + priceBuy: { + type: Sequelize.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00 + }, + priceRetail: { + type: Sequelize.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00 + }, + priceTaxe: { + type: Sequelize.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00 + }, + brandId: { + type: Sequelize.INTEGER, + allowNull: true, + references: { + model: 'brand', + key: 'id' + }, + onDelete: 'SET NULL', + onUpdate: 'CASCADE' + }, + ownerId: { + type: Sequelize.STRING(24), + allowNull: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'SET NULL', + onUpdate: 'CASCADE' + }, + packagingId: { + type: Sequelize.INTEGER, + allowNull: true, + references: { + model: 'packaging', + key: 'id' + }, + onDelete: 'SET NULL', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create UserRoleXref table (junction table for User-Role) + await queryInterface.createTable('userRoleXref', { + userId: { + type: Sequelize.STRING(24), + allowNull: false, + primaryKey: true, + references: { + model: 'user', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + roleId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'role', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create ProductCategoryXref table + await queryInterface.createTable('productCategoryXref', { + productId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'product', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + categoryId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'category', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create ProductTagXref table + await queryInterface.createTable('productTagXref', { + productId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { + model: 'product', + key: 'id' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + tagName: { + type: Sequelize.STRING(255), + allowNull: false, + primaryKey: true, + references: { + model: 'tag', + key: 'name' + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE' + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }, { transaction }); + + // Create indexes + await queryInterface.addIndex('article', ['authorId'], { transaction }); + await queryInterface.addIndex('article', ['slug'], { transaction }); + await queryInterface.addIndex('comment', ['authorId'], { transaction }); + await queryInterface.addIndex('comment', ['articleId'], { transaction }); + await queryInterface.addIndex('product', ['eancode'], { transaction }); + await queryInterface.addIndex('product', ['brandId'], { transaction }); + await queryInterface.addIndex('product', ['ownerId'], { transaction }); + await queryInterface.addIndex('product', ['packagingId'], { transaction }); + await queryInterface.addIndex('follower', ['followerId'], { transaction }); + + await transaction.commit(); + } catch (err) { + await transaction.rollback(); + throw err; + } + }, + + async down(queryInterface, Sequelize) { + const transaction = await queryInterface.sequelize.transaction(); + + try { + // Drop tables in reverse order of creation (due to foreign key constraints) + await queryInterface.dropTable('productTagXref', { transaction }); + await queryInterface.dropTable('productCategoryXref', { transaction }); + await queryInterface.dropTable('userRoleXref', { transaction }); + await queryInterface.dropTable('product', { transaction }); + await queryInterface.dropTable('follower', { transaction }); + await queryInterface.dropTable('favorite', { transaction }); + await queryInterface.dropTable('tagList', { transaction }); + await queryInterface.dropTable('comment', { transaction }); + await queryInterface.dropTable('article', { transaction }); + await queryInterface.dropTable('packaging', { transaction }); + await queryInterface.dropTable('category', { transaction }); + await queryInterface.dropTable('brand', { transaction }); + await queryInterface.dropTable('role', { transaction }); + await queryInterface.dropTable('tag', { transaction }); + await queryInterface.dropTable('user', { transaction }); + + await transaction.commit(); + } catch (err) { + await transaction.rollback(); + throw err; + } + } +};