vr-migrations 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +60 -0
- package/dist/create-migration.d.ts +1 -0
- package/dist/create-migration.js +26 -0
- package/dist/create-seeder.d.ts +1 -0
- package/dist/create-seeder.js +26 -0
- package/dist/db.d.ts +12 -0
- package/dist/db.js +54 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +29 -0
- package/dist/migrate.d.ts +1 -0
- package/dist/migrate.js +36 -0
- package/dist/migrations/001-create-security-clearances.js +62 -0
- package/dist/migrations/002-create-users.js +141 -0
- package/dist/migrations/003-create-products.js +52 -0
- package/dist/migrations/004-create-pricing.js +82 -0
- package/dist/migrations/005-create-devices.js +63 -0
- package/dist/migrations/006-create-device-payment-plans.js +115 -0
- package/dist/migrations/007-create-idempotency-records.js +61 -0
- package/dist/migrations/008-create-payments.js +106 -0
- package/dist/migrations/009-create-transactions.js +80 -0
- package/dist/migrations/010-create-eventLogs.js +117 -0
- package/dist/migrations/index.d.ts +0 -0
- package/dist/migrations/index.js +1 -0
- package/dist/migrations/index.ts +1 -0
- package/dist/reset.d.ts +1 -0
- package/dist/reset.js +9 -0
- package/dist/rollback.d.ts +1 -0
- package/dist/rollback.js +40 -0
- package/dist/seed.d.ts +1 -0
- package/dist/seed.js +38 -0
- package/dist/seeders/001-security-clearance-demo.js +116 -0
- package/dist/seeders/002-users-demo.js +94 -0
- package/dist/seeders/index.d.ts +0 -0
- package/dist/seeders/index.js +1 -0
- package/dist/seeders/index.ts +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.js +2 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.program = void 0;
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const migrate_1 = require("./migrate");
|
|
10
|
+
const rollback_1 = require("./rollback");
|
|
11
|
+
const seed_1 = require("./seed");
|
|
12
|
+
const reset_1 = require("./reset");
|
|
13
|
+
const create_migration_1 = require("./create-migration");
|
|
14
|
+
const create_seeder_1 = require("./create-seeder");
|
|
15
|
+
const db_1 = require("./db");
|
|
16
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
17
|
+
dotenv_1.default.config();
|
|
18
|
+
exports.program = new commander_1.Command();
|
|
19
|
+
exports.program
|
|
20
|
+
.name("vr-migrate") //
|
|
21
|
+
.description("CENTRALIZED VR Migration Tool") //
|
|
22
|
+
.version("1.0.0")
|
|
23
|
+
.hook("preAction", async () => {
|
|
24
|
+
const sequelize = await (0, db_1.initializeDatabase)({
|
|
25
|
+
DB_HOST: process.env.DB_HOST,
|
|
26
|
+
DB_PORT: parseInt(process.env.DB_PORT || "5432"),
|
|
27
|
+
DB_USER: process.env.DB_USER,
|
|
28
|
+
DB_PASSWORD: process.env.DB_PASSWORD,
|
|
29
|
+
DB_NAME: process.env.DB_NAME,
|
|
30
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
31
|
+
});
|
|
32
|
+
await sequelize.authenticate();
|
|
33
|
+
});
|
|
34
|
+
// Centralized Commands (No path overrides allowed)
|
|
35
|
+
exports.program
|
|
36
|
+
.command("migrate")
|
|
37
|
+
.description("Run CENTRALIZED migrations from vr-migrations package") //
|
|
38
|
+
.action(async () => await (0, migrate_1.migrate)());
|
|
39
|
+
exports.program
|
|
40
|
+
.command("rollback")
|
|
41
|
+
.description("Rollback CENTRALIZED migrations")
|
|
42
|
+
.option("--all", "Rollback all migrations")
|
|
43
|
+
.action(async (options) => await (0, rollback_1.rollback)(options.all ? "all" : 1));
|
|
44
|
+
exports.program
|
|
45
|
+
.command("seed")
|
|
46
|
+
.description("Run CENTRALIZED seeders")
|
|
47
|
+
.action(async () => await (0, seed_1.seed)());
|
|
48
|
+
exports.program
|
|
49
|
+
.command("reset")
|
|
50
|
+
.description("Reset database (DANGER!)")
|
|
51
|
+
.action(async () => await (0, reset_1.reset)());
|
|
52
|
+
exports.program
|
|
53
|
+
.command("create:migration <name>")
|
|
54
|
+
.description("Create new migration in vr-migrations package") //
|
|
55
|
+
.action((name) => (0, create_migration_1.createMigration)(name));
|
|
56
|
+
exports.program
|
|
57
|
+
.command("create:seeder <name>")
|
|
58
|
+
.description("Create new seeder in vr-migrations package") //
|
|
59
|
+
.action((name) => (0, create_seeder_1.createSeeder)(name));
|
|
60
|
+
exports.program.parse(process.argv);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createMigration(name: string): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createMigration = createMigration;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
// const migrationsDir = path.join(__dirname, "../migrations");
|
|
10
|
+
const migrationsDir = path_1.default.join(__dirname, "migrations");
|
|
11
|
+
const template = `module.exports = {
|
|
12
|
+
async up(queryInterface, Sequelize) {
|
|
13
|
+
// Migration code here
|
|
14
|
+
},
|
|
15
|
+
async down(queryInterface) {
|
|
16
|
+
// Rollback code here
|
|
17
|
+
}
|
|
18
|
+
};`;
|
|
19
|
+
function createMigration(name) {
|
|
20
|
+
const timestamp = new Date().toISOString().replace(/\D/g, "").slice(0, 14);
|
|
21
|
+
const fileName = `${timestamp}-${name}.js`;
|
|
22
|
+
const filePath = path_1.default.join(migrationsDir, fileName);
|
|
23
|
+
fs_1.default.mkdirSync(migrationsDir, { recursive: true });
|
|
24
|
+
fs_1.default.writeFileSync(filePath, template);
|
|
25
|
+
console.log(`✅ Created migration: ${fileName}`);
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createSeeder(name: string): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createSeeder = createSeeder;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
// const seedersDir = path.join(__dirname, "../seeders");
|
|
10
|
+
const seedersDir = path_1.default.join(__dirname, "seeders");
|
|
11
|
+
const template = `module.exports = {
|
|
12
|
+
async up(queryInterface, Sequelize) {
|
|
13
|
+
// Migration code here
|
|
14
|
+
},
|
|
15
|
+
async down(queryInterface) {
|
|
16
|
+
// Rollback code here
|
|
17
|
+
}
|
|
18
|
+
};`;
|
|
19
|
+
function createSeeder(name) {
|
|
20
|
+
const timestamp = new Date().toISOString().replace(/\D/g, "").slice(0, 14);
|
|
21
|
+
const fileName = `${timestamp}-${name}.js`;
|
|
22
|
+
const filePath = path_1.default.join(seedersDir, fileName);
|
|
23
|
+
fs_1.default.mkdirSync(seedersDir, { recursive: true });
|
|
24
|
+
fs_1.default.writeFileSync(filePath, template);
|
|
25
|
+
console.log(`✅ Created CENTRALIZED seeder: ${fileName}`);
|
|
26
|
+
}
|
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Sequelize } from "sequelize";
|
|
2
|
+
export declare function getSequelize(): Sequelize;
|
|
3
|
+
export declare function initializeDatabase(config: {
|
|
4
|
+
DB_HOST: string;
|
|
5
|
+
DB_PORT: number;
|
|
6
|
+
DB_USER: string;
|
|
7
|
+
DB_PASSWORD: string;
|
|
8
|
+
DB_NAME: string;
|
|
9
|
+
NODE_ENV?: string;
|
|
10
|
+
}): Promise<Sequelize>;
|
|
11
|
+
export declare function closeDatabase(): Promise<void>;
|
|
12
|
+
export { Model, InferAttributes, InferCreationAttributes, DataTypes, CreationOptional, ModelStatic, ModelAttributes, NonAttribute, Op, } from "sequelize";
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Op = exports.DataTypes = exports.Model = void 0;
|
|
4
|
+
exports.getSequelize = getSequelize;
|
|
5
|
+
exports.initializeDatabase = initializeDatabase;
|
|
6
|
+
exports.closeDatabase = closeDatabase;
|
|
7
|
+
const sequelize_1 = require("sequelize");
|
|
8
|
+
let _sequelize = null;
|
|
9
|
+
let _isInitialized = false;
|
|
10
|
+
function getSequelize() {
|
|
11
|
+
if (!_isInitialized) {
|
|
12
|
+
throw new Error("Database not initialized. Call initializeDatabase() first");
|
|
13
|
+
}
|
|
14
|
+
return _sequelize;
|
|
15
|
+
}
|
|
16
|
+
async function initializeDatabase(config) {
|
|
17
|
+
if (_isInitialized)
|
|
18
|
+
return _sequelize;
|
|
19
|
+
_sequelize = new sequelize_1.Sequelize({
|
|
20
|
+
dialect: "postgres",
|
|
21
|
+
host: config.DB_HOST,
|
|
22
|
+
port: config.DB_PORT,
|
|
23
|
+
username: config.DB_USER,
|
|
24
|
+
password: config.DB_PASSWORD,
|
|
25
|
+
database: config.DB_NAME,
|
|
26
|
+
logging: false,
|
|
27
|
+
pool: {
|
|
28
|
+
max: 20,
|
|
29
|
+
min: 2,
|
|
30
|
+
acquire: 120000,
|
|
31
|
+
idle: 10000,
|
|
32
|
+
},
|
|
33
|
+
dialectOptions: config.NODE_ENV === "production"
|
|
34
|
+
? {
|
|
35
|
+
ssl: { require: true, rejectUnauthorized: false },
|
|
36
|
+
}
|
|
37
|
+
: {},
|
|
38
|
+
});
|
|
39
|
+
await _sequelize.authenticate();
|
|
40
|
+
_isInitialized = true;
|
|
41
|
+
return _sequelize;
|
|
42
|
+
}
|
|
43
|
+
async function closeDatabase() {
|
|
44
|
+
if (_sequelize) {
|
|
45
|
+
await _sequelize.close();
|
|
46
|
+
_sequelize = null;
|
|
47
|
+
_isInitialized = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Export types for models
|
|
51
|
+
var sequelize_2 = require("sequelize");
|
|
52
|
+
Object.defineProperty(exports, "Model", { enumerable: true, get: function () { return sequelize_2.Model; } });
|
|
53
|
+
Object.defineProperty(exports, "DataTypes", { enumerable: true, get: function () { return sequelize_2.DataTypes; } });
|
|
54
|
+
Object.defineProperty(exports, "Op", { enumerable: true, get: function () { return sequelize_2.Op; } });
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Export types first
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
// Then export functionality
|
|
20
|
+
__exportStar(require("./db"), exports);
|
|
21
|
+
__exportStar(require("./migrate"), exports);
|
|
22
|
+
__exportStar(require("./rollback"), exports);
|
|
23
|
+
__exportStar(require("./seed"), exports);
|
|
24
|
+
__exportStar(require("./reset"), exports);
|
|
25
|
+
__exportStar(require("./create-migration"), exports);
|
|
26
|
+
__exportStar(require("./create-seeder"), exports);
|
|
27
|
+
// // CLI export
|
|
28
|
+
// import { program } from "./cli";
|
|
29
|
+
// export default program;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function migrate(): Promise<void>;
|
package/dist/migrate.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.migrate = migrate;
|
|
7
|
+
const umzug_1 = require("umzug");
|
|
8
|
+
const db_1 = require("./db");
|
|
9
|
+
const sequelize_1 = require("sequelize");
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
// const migrationsPath = path.join(__dirname, "../migrations/[0-9]*-*.js");
|
|
12
|
+
const migrationsPath = path_1.default.join(__dirname, "migrations/[0-9]*-*.js");
|
|
13
|
+
async function migrate() {
|
|
14
|
+
console.log("looking for migrations at:", migrationsPath);
|
|
15
|
+
const sequelize = (0, db_1.getSequelize)();
|
|
16
|
+
const migrator = new umzug_1.Umzug({
|
|
17
|
+
migrations: {
|
|
18
|
+
glob: migrationsPath,
|
|
19
|
+
resolve: ({ name, path: filePath }) => ({
|
|
20
|
+
name,
|
|
21
|
+
up: async () => {
|
|
22
|
+
const migration = require(filePath);
|
|
23
|
+
return migration.up(sequelize.getQueryInterface(), sequelize_1.Sequelize);
|
|
24
|
+
},
|
|
25
|
+
down: async () => {
|
|
26
|
+
const migration = require(filePath);
|
|
27
|
+
return migration.down(sequelize.getQueryInterface());
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
storage: new umzug_1.SequelizeStorage({ sequelize }),
|
|
32
|
+
logger: console,
|
|
33
|
+
});
|
|
34
|
+
await migrator.up();
|
|
35
|
+
console.log("✅ Migrations completed");
|
|
36
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/** @type {import('sequelize-cli').Migration} */
|
|
4
|
+
module.exports = {
|
|
5
|
+
async up(queryInterface, Sequelize) {
|
|
6
|
+
await queryInterface.createTable("security_clearances", {
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.UUID,
|
|
9
|
+
defaultValue: Sequelize.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
11
|
+
allowNull: false
|
|
12
|
+
},
|
|
13
|
+
role: {
|
|
14
|
+
type: Sequelize.ENUM(
|
|
15
|
+
"RIDER",
|
|
16
|
+
"PASSENGER",
|
|
17
|
+
"ADMIN",
|
|
18
|
+
"AGENT",
|
|
19
|
+
"SUPER_ADMIN"
|
|
20
|
+
),
|
|
21
|
+
allowNull: false,
|
|
22
|
+
unique: true
|
|
23
|
+
},
|
|
24
|
+
description: {
|
|
25
|
+
type: Sequelize.TEXT,
|
|
26
|
+
allowNull: true
|
|
27
|
+
},
|
|
28
|
+
level: {
|
|
29
|
+
type: Sequelize.INTEGER,
|
|
30
|
+
allowNull: false,
|
|
31
|
+
defaultValue: 0
|
|
32
|
+
},
|
|
33
|
+
permissions: {
|
|
34
|
+
type: Sequelize.ARRAY(Sequelize.STRING),
|
|
35
|
+
allowNull: false,
|
|
36
|
+
defaultValue: []
|
|
37
|
+
},
|
|
38
|
+
isDefault: {
|
|
39
|
+
type: Sequelize.BOOLEAN,
|
|
40
|
+
allowNull: false,
|
|
41
|
+
defaultValue: false
|
|
42
|
+
},
|
|
43
|
+
createdAt: {
|
|
44
|
+
type: Sequelize.DATE,
|
|
45
|
+
allowNull: false,
|
|
46
|
+
defaultValue: Sequelize.fn("NOW")
|
|
47
|
+
},
|
|
48
|
+
updatedAt: {
|
|
49
|
+
type: Sequelize.DATE,
|
|
50
|
+
allowNull: false,
|
|
51
|
+
defaultValue: Sequelize.fn("NOW")
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
async down(queryInterface) {
|
|
57
|
+
await queryInterface.dropTable("security_clearances");
|
|
58
|
+
await queryInterface.sequelize.query(
|
|
59
|
+
'DROP TYPE IF EXISTS "enum_security_clearances_role";'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/** @type {import('sequelize').Migration} */
|
|
4
|
+
module.exports = {
|
|
5
|
+
async up(queryInterface, Sequelize) {
|
|
6
|
+
await queryInterface.createTable("users", {
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.UUID,
|
|
9
|
+
defaultValue: Sequelize.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
11
|
+
allowNull: false
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
firstName: {
|
|
15
|
+
type: Sequelize.STRING(50),
|
|
16
|
+
allowNull: false
|
|
17
|
+
},
|
|
18
|
+
securityClearanceId: {
|
|
19
|
+
type: Sequelize.UUID,
|
|
20
|
+
allowNull: false,
|
|
21
|
+
references: {
|
|
22
|
+
model: "security_clearances",
|
|
23
|
+
key: "id"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
lastName: {
|
|
27
|
+
type: Sequelize.STRING(50),
|
|
28
|
+
allowNull: false
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
phoneNumber: {
|
|
32
|
+
type: Sequelize.STRING(20),
|
|
33
|
+
allowNull: false,
|
|
34
|
+
unique: true
|
|
35
|
+
},
|
|
36
|
+
email: {
|
|
37
|
+
type: Sequelize.STRING(100),
|
|
38
|
+
allowNull: true,
|
|
39
|
+
unique: true
|
|
40
|
+
},
|
|
41
|
+
password: {
|
|
42
|
+
type: Sequelize.STRING,
|
|
43
|
+
allowNull: true
|
|
44
|
+
},
|
|
45
|
+
jacketId: {
|
|
46
|
+
type: Sequelize.STRING(50),
|
|
47
|
+
allowNull: true,
|
|
48
|
+
unique: true
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
nationalId: {
|
|
52
|
+
type: Sequelize.STRING(60),
|
|
53
|
+
allowNull: true,
|
|
54
|
+
unique: true
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
role: {
|
|
58
|
+
type: Sequelize.ENUM("RIDER", "ADMIN", "AGENT"),
|
|
59
|
+
allowNull: false,
|
|
60
|
+
defaultValue: "RIDER"
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
plateNumber: {
|
|
64
|
+
type: Sequelize.STRING(20),
|
|
65
|
+
allowNull: true
|
|
66
|
+
},
|
|
67
|
+
isActive: {
|
|
68
|
+
type: Sequelize.BOOLEAN,
|
|
69
|
+
allowNull: false,
|
|
70
|
+
defaultValue: true
|
|
71
|
+
},
|
|
72
|
+
tokenVersion: {
|
|
73
|
+
type: Sequelize.INTEGER,
|
|
74
|
+
allowNull: false,
|
|
75
|
+
defaultValue: 1
|
|
76
|
+
},
|
|
77
|
+
forgotPassword: {
|
|
78
|
+
type: Sequelize.BOOLEAN,
|
|
79
|
+
defaultValue: false
|
|
80
|
+
},
|
|
81
|
+
otp: {
|
|
82
|
+
type: Sequelize.STRING(6),
|
|
83
|
+
allowNull: true
|
|
84
|
+
},
|
|
85
|
+
otpExpiresAt: {
|
|
86
|
+
type: Sequelize.DATE,
|
|
87
|
+
allowNull: true
|
|
88
|
+
},
|
|
89
|
+
isSuspended: {
|
|
90
|
+
type: Sequelize.BOOLEAN,
|
|
91
|
+
allowNull: false,
|
|
92
|
+
defaultValue: false
|
|
93
|
+
},
|
|
94
|
+
bannedAt: {
|
|
95
|
+
type: Sequelize.DATE,
|
|
96
|
+
allowNull: true
|
|
97
|
+
},
|
|
98
|
+
banReason: {
|
|
99
|
+
type: Sequelize.TEXT,
|
|
100
|
+
allowNull: true
|
|
101
|
+
},
|
|
102
|
+
suspendedAt: {
|
|
103
|
+
type: Sequelize.DATE,
|
|
104
|
+
allowNull: true
|
|
105
|
+
},
|
|
106
|
+
suspensionReason: {
|
|
107
|
+
type: Sequelize.TEXT,
|
|
108
|
+
allowNull: true
|
|
109
|
+
},
|
|
110
|
+
lastLoginAt: {
|
|
111
|
+
type: Sequelize.DATE,
|
|
112
|
+
allowNull: true
|
|
113
|
+
},
|
|
114
|
+
isDeactivated: {
|
|
115
|
+
type: Sequelize.BOOLEAN,
|
|
116
|
+
defaultValue: false
|
|
117
|
+
},
|
|
118
|
+
deactivatedAt: {
|
|
119
|
+
type: Sequelize.DATE,
|
|
120
|
+
allowNull: true
|
|
121
|
+
},
|
|
122
|
+
createdAt: {
|
|
123
|
+
type: Sequelize.DATE,
|
|
124
|
+
allowNull: false,
|
|
125
|
+
defaultValue: Sequelize.fn("NOW")
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Optional: explicit indexes (Postgres already enforces uniques, but this is clarity)
|
|
130
|
+
await queryInterface.addIndex("users", ["phoneNumber"]);
|
|
131
|
+
await queryInterface.addIndex("users", ["jacketId"]);
|
|
132
|
+
await queryInterface.addIndex("users", ["nationalId"]);
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
async down(queryInterface) {
|
|
136
|
+
await queryInterface.dropTable("users");
|
|
137
|
+
await queryInterface.sequelize.query(
|
|
138
|
+
'DROP TYPE IF EXISTS "enum_users_role";'
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
async up(queryInterface, Sequelize) {
|
|
5
|
+
await queryInterface.createTable("products", {
|
|
6
|
+
id: {
|
|
7
|
+
type: Sequelize.UUID,
|
|
8
|
+
defaultValue: Sequelize.UUIDV4,
|
|
9
|
+
primaryKey: true,
|
|
10
|
+
allowNull: false
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
name: {
|
|
14
|
+
type: Sequelize.STRING(100),
|
|
15
|
+
allowNull: false
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
description: {
|
|
19
|
+
type: Sequelize.TEXT,
|
|
20
|
+
allowNull: true
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
stock: {
|
|
24
|
+
type: Sequelize.INTEGER,
|
|
25
|
+
allowNull: false,
|
|
26
|
+
defaultValue: 0
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
isActive: {
|
|
30
|
+
type: Sequelize.BOOLEAN,
|
|
31
|
+
allowNull: false,
|
|
32
|
+
defaultValue: true
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
createdAt: {
|
|
36
|
+
type: Sequelize.DATE,
|
|
37
|
+
allowNull: false,
|
|
38
|
+
defaultValue: Sequelize.fn("NOW")
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
updatedAt: {
|
|
42
|
+
type: Sequelize.DATE,
|
|
43
|
+
allowNull: false,
|
|
44
|
+
defaultValue: Sequelize.fn("NOW")
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
async down(queryInterface) {
|
|
50
|
+
await queryInterface.dropTable("products");
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
async up(queryInterface, Sequelize) {
|
|
5
|
+
await queryInterface.createTable("pricings", {
|
|
6
|
+
id: {
|
|
7
|
+
type: Sequelize.UUID,
|
|
8
|
+
defaultValue: Sequelize.UUIDV4,
|
|
9
|
+
primaryKey: true,
|
|
10
|
+
allowNull: false
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
productId: {
|
|
14
|
+
type: Sequelize.UUID,
|
|
15
|
+
allowNull: false,
|
|
16
|
+
references: {
|
|
17
|
+
model: "products",
|
|
18
|
+
key: "id"
|
|
19
|
+
},
|
|
20
|
+
onUpdate: "CASCADE",
|
|
21
|
+
onDelete: "CASCADE"
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
name: {
|
|
25
|
+
type: Sequelize.STRING(100),
|
|
26
|
+
allowNull: false
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
upfrontPrice: {
|
|
30
|
+
type: Sequelize.DECIMAL(10, 2),
|
|
31
|
+
allowNull: false
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
downPayment: {
|
|
35
|
+
type: Sequelize.DECIMAL(10, 2),
|
|
36
|
+
allowNull: false,
|
|
37
|
+
defaultValue: 0
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
installmentAmount: {
|
|
41
|
+
type: Sequelize.DECIMAL(10, 2),
|
|
42
|
+
allowNull: true
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
installmentIntervalDays: {
|
|
46
|
+
type: Sequelize.INTEGER,
|
|
47
|
+
allowNull: true
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
totalAmount: {
|
|
51
|
+
type: Sequelize.DECIMAL(10, 2),
|
|
52
|
+
allowNull: false
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
isActive: {
|
|
56
|
+
type: Sequelize.BOOLEAN,
|
|
57
|
+
allowNull: false,
|
|
58
|
+
defaultValue: true
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
createdAt: {
|
|
62
|
+
type: Sequelize.DATE,
|
|
63
|
+
allowNull: false,
|
|
64
|
+
defaultValue: Sequelize.fn("NOW")
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
updatedAt: {
|
|
68
|
+
type: Sequelize.DATE,
|
|
69
|
+
allowNull: false,
|
|
70
|
+
defaultValue: Sequelize.fn("NOW")
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Optional but recommended indexes
|
|
75
|
+
await queryInterface.addIndex("pricings", ["productId"]);
|
|
76
|
+
await queryInterface.addIndex("pricings", ["isActive"]);
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
async down(queryInterface) {
|
|
80
|
+
await queryInterface.dropTable("pricings");
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/** @type {import('sequelize').QueryInterface} */
|
|
4
|
+
module.exports = {
|
|
5
|
+
async up(queryInterface, Sequelize) {
|
|
6
|
+
await queryInterface.createTable("devices", {
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.UUID,
|
|
9
|
+
defaultValue: Sequelize.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
11
|
+
allowNull: false
|
|
12
|
+
},
|
|
13
|
+
serialNumber: {
|
|
14
|
+
type: Sequelize.STRING(64),
|
|
15
|
+
allowNull: false,
|
|
16
|
+
unique: true
|
|
17
|
+
},
|
|
18
|
+
productId: {
|
|
19
|
+
type: Sequelize.UUID,
|
|
20
|
+
allowNull: false,
|
|
21
|
+
references: {
|
|
22
|
+
model: "products",
|
|
23
|
+
key: "id"
|
|
24
|
+
},
|
|
25
|
+
onUpdate: "CASCADE",
|
|
26
|
+
onDelete: "RESTRICT"
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
status: {
|
|
30
|
+
type: Sequelize.ENUM("locked", "unlocked", "disabled"),
|
|
31
|
+
allowNull: false,
|
|
32
|
+
defaultValue: "locked"
|
|
33
|
+
},
|
|
34
|
+
isPermanentlyUnlocked: {
|
|
35
|
+
type: Sequelize.BOOLEAN,
|
|
36
|
+
allowNull: false,
|
|
37
|
+
defaultValue: false
|
|
38
|
+
},
|
|
39
|
+
activatedAt: {
|
|
40
|
+
type: Sequelize.DATE,
|
|
41
|
+
allowNull: true
|
|
42
|
+
},
|
|
43
|
+
createdAt: {
|
|
44
|
+
type: Sequelize.DATE,
|
|
45
|
+
allowNull: false,
|
|
46
|
+
defaultValue: Sequelize.fn("NOW")
|
|
47
|
+
},
|
|
48
|
+
updatedAt: {
|
|
49
|
+
type: Sequelize.DATE,
|
|
50
|
+
allowNull: false,
|
|
51
|
+
defaultValue: Sequelize.fn("NOW")
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
async down(queryInterface) {
|
|
57
|
+
await queryInterface.dropTable("devices");
|
|
58
|
+
|
|
59
|
+
await queryInterface.sequelize.query(
|
|
60
|
+
'DROP TYPE IF EXISTS "enum_devices_status"'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|