Merge pull request 'new feautres implemnted' (#2) from ali into dev
Reviewed-on: https://gitea.maskantech.in/gitea_admin/productcatalogue_backend/pulls/2
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "logs\\.3fa4d5e91883ce1217f62a49f94203b42caa131d-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1782885016196,
|
||||
"name": "logs\\combined-2026-07-01.log",
|
||||
"hash": "62273be471fbf03240935eebb5eaf8487e7a3002b6cced421c983245646bc21a"
|
||||
},
|
||||
{
|
||||
"date": 1782968983048,
|
||||
"name": "logs\\combined-2026-07-02.log",
|
||||
"hash": "10138c0f35436a800870f14a317b542645e7976bcd44030300d436a715a20c36"
|
||||
},
|
||||
{
|
||||
"date": 1783058300242,
|
||||
"name": "logs\\combined-2026-07-03.log",
|
||||
"hash": "a0e79e7be8f5ef13f7e6e8483c8bb663b1c7ddeb1eaa188152cda3f015df5203"
|
||||
},
|
||||
{
|
||||
"date": 1783142857411,
|
||||
"name": "logs\\combined-2026-07-04.log",
|
||||
"hash": "df5726dddf64ecbb358dc871efc7f6fa558f95b33fec683e6eef801c4d9f7e4a"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "logs\\.944c2a6e38c8046075bb4cb64c11b1f8d919853c-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1782885016194,
|
||||
"name": "logs\\error-2026-07-01.log",
|
||||
"hash": "3dc68d8ca2e67e313b2363c163e011da72b07deaf5d0f5736607ec0850b50e9b"
|
||||
},
|
||||
{
|
||||
"date": 1782968983045,
|
||||
"name": "logs\\error-2026-07-02.log",
|
||||
"hash": "bf64fe21cbfba23af08772bef924ee896b52bcbf80bb4e87b6f7c5fb125e38aa"
|
||||
},
|
||||
{
|
||||
"date": 1783058300224,
|
||||
"name": "logs\\error-2026-07-03.log",
|
||||
"hash": "9d7b2b6bae80886841b6c099d2312d2fe37fd6e58d4eb934668e9c62e4e38bc1"
|
||||
},
|
||||
{
|
||||
"date": 1783142857406,
|
||||
"name": "logs\\error-2026-07-04.log",
|
||||
"hash": "7d2caa5cd525a8a119155e3c48baeded2d8741b61d934b266de04b9140095740"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
Generated
-7
@@ -2346,13 +2346,6 @@
|
||||
"fn.name": "1.x.x"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-types": {
|
||||
"version": "12.1.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
"scripts": {
|
||||
"start": "cross-env NODE_ENV=production node index.js",
|
||||
"dev": "cross-env NODE_ENV=development nodemon index.js",
|
||||
"test": "cross-env NODE_ENV=test nodemon index.js",
|
||||
"local": "cross-env NODE_ENV=local nodemon index.js",
|
||||
"start:local": "cross-env NODE_ENV=local nodemon index.js",
|
||||
"db:migrate:local": "cross-env NODE_ENV=local sequelize-cli db:migrate --config src/shared/config/database.config.cjs --migrations-path src/migrations --models-path src/shared/database",
|
||||
"db:seed:local": "cross-env NODE_ENV=local sequelize-cli db:seed:all --config src/shared/config/database.config.cjs --seeders-path src/seeders --models-path src/shared/database",
|
||||
|
||||
@@ -5,6 +5,20 @@ import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles:
|
||||
* get:
|
||||
* summary: Retrieve all roles
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -12,6 +26,24 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles/by-tenant/{tenantId}:
|
||||
* get:
|
||||
* summary: Retrieve roles by tenant
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: tenantId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/by-tenant/:tenantId',
|
||||
authenticate,
|
||||
@@ -19,6 +51,18 @@ router.get(
|
||||
controller.getByTenant
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles/permissions:
|
||||
* get:
|
||||
* summary: Retrieve all permission nodes
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/permissions',
|
||||
authenticate,
|
||||
@@ -26,6 +70,26 @@ router.get(
|
||||
controller.getPermissions
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single role
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -33,6 +97,32 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles:
|
||||
* post:
|
||||
* summary: Create a new role
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [name]
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* permissions:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Created
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -40,6 +130,24 @@ router.post(
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles/{id}:
|
||||
* put:
|
||||
* summary: Update a role
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -47,6 +155,24 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/roles/{id}:
|
||||
* delete:
|
||||
* summary: Delete a role
|
||||
* tags: [Roles]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -5,6 +5,20 @@ import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/users:
|
||||
* get:
|
||||
* summary: Retrieve all users
|
||||
* tags: [Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -12,6 +26,26 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/users/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single user
|
||||
* tags: [Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -19,6 +53,32 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/users/invite:
|
||||
* post:
|
||||
* summary: Invite a new user
|
||||
* tags: [Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [email, role_id]
|
||||
* properties:
|
||||
* email:
|
||||
* type: string
|
||||
* role_id:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Invitation sent
|
||||
* 400:
|
||||
* description: Validation Error
|
||||
*/
|
||||
router.post(
|
||||
'/invite',
|
||||
authenticate,
|
||||
@@ -26,6 +86,24 @@ router.post(
|
||||
controller.invite
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/users/{id}:
|
||||
* put:
|
||||
* summary: Update a user
|
||||
* tags: [Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -33,6 +111,24 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/users/{id}:
|
||||
* delete:
|
||||
* summary: Delete a user
|
||||
* tags: [Users]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -7,20 +7,11 @@ import categoriesRouter from './categories/index.js';
|
||||
import brandsRouter from './brands/index.js';
|
||||
import attributesRouter from './attributes/index.js';
|
||||
import mediaRouter from './media/index.js';
|
||||
import pricingRouter from './pricing/index.js';
|
||||
import inventoryRouter from './inventory/index.js';
|
||||
import suppliersRouter from './suppliers/index.js';
|
||||
import localizationRouter from './localization/index.js';
|
||||
import workflowsRouter from './workflows/index.js';
|
||||
import integrationsRouter from './integrations/index.js';
|
||||
import channelsRouter from './channels/index.js';
|
||||
import importsRouter from './imports/index.js';
|
||||
import exportsRouter from './exports/index.js';
|
||||
import notificationsRouter from './notifications/index.js';
|
||||
import reportsRouter from './reports/index.js';
|
||||
import settingsRouter from './settings/index.js';
|
||||
import auditLogsRouter from './auditLogs/index.js';
|
||||
import unitsRouter from './units/index.js';
|
||||
|
||||
export default function registerRoutes(app) {
|
||||
app.use('/api/v1', authenticationRouter);
|
||||
@@ -32,18 +23,9 @@ export default function registerRoutes(app) {
|
||||
app.use('/api/v1', brandsRouter);
|
||||
app.use('/api/v1', attributesRouter);
|
||||
app.use('/api/v1', mediaRouter);
|
||||
app.use('/api/v1', pricingRouter);
|
||||
app.use('/api/v1', inventoryRouter);
|
||||
app.use('/api/v1', suppliersRouter);
|
||||
app.use('/api/v1', localizationRouter);
|
||||
app.use('/api/v1', workflowsRouter);
|
||||
app.use('/api/v1', integrationsRouter);
|
||||
app.use('/api/v1', channelsRouter);
|
||||
app.use('/api/v1', importsRouter);
|
||||
app.use('/api/v1', exportsRouter);
|
||||
app.use('/api/v1', notificationsRouter);
|
||||
app.use('/api/v1', reportsRouter);
|
||||
app.use('/api/v1', settingsRouter);
|
||||
app.use('/api/v1', auditLogsRouter);
|
||||
app.use('/api/v1', unitsRouter);
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import integrationsRouter from './integrations/integration.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/integrations', integrationsRouter);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as integrationRoutes } from './integration.routes.js';
|
||||
export { default as integrationController } from './integration.controller.js';
|
||||
export { default as integrationService } from './integration.service.js';
|
||||
export { default as integrationRepository } from './integration.repository.js';
|
||||
export { default as integrationModel } from './integration.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './integration.service.js';
|
||||
|
||||
export class IntegrationController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Integration deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new IntegrationController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Integration extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Integration.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Integration',
|
||||
tableName: 'integrations',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Integration;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class IntegrationRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Integration.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Integration.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Integration.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new IntegrationRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './integration.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './integration.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/integrations:
|
||||
* get:
|
||||
* summary: Retrieve all integrations
|
||||
* tags: [Integrations]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:integrations']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/integrations/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single integration
|
||||
* tags: [Integrations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:integrations']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/integrations:
|
||||
* post:
|
||||
* summary: Create a integration
|
||||
* tags: [Integrations]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:integrations']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_INTEGRATION'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/integrations/{id}:
|
||||
* put:
|
||||
* summary: Update a integration
|
||||
* tags: [Integrations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:integrations']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_INTEGRATION'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/integrations/{id}:
|
||||
* delete:
|
||||
* summary: Delete a integration
|
||||
* tags: [Integrations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:integrations']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_INTEGRATION'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './integration.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class IntegrationService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Integration not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('integration:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Integration',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Integration not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('integration:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Integration',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Integration not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('integration:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Integration',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new IntegrationService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import inventoryRouter from './inventory/inventory.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/inventory', inventoryRouter);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as inventoryRoutes } from './inventory.routes.js';
|
||||
export { default as inventoryController } from './inventory.controller.js';
|
||||
export { default as inventoryService } from './inventory.service.js';
|
||||
export { default as inventoryRepository } from './inventory.repository.js';
|
||||
export { default as inventoryModel } from './inventory.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './inventory.service.js';
|
||||
|
||||
export class InventoryController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Inventory deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new InventoryController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Inventory extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Inventory.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Inventory',
|
||||
tableName: 'inventorys',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Inventory;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class InventoryRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Inventory.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Inventory.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Inventory.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new InventoryRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './inventory.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './inventory.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/inventorys:
|
||||
* get:
|
||||
* summary: Retrieve all inventorys
|
||||
* tags: [Inventorys]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:inventorys']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/inventorys/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single inventory
|
||||
* tags: [Inventorys]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:inventorys']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/inventorys:
|
||||
* post:
|
||||
* summary: Create a inventory
|
||||
* tags: [Inventorys]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:inventorys']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_INVENTORY'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/inventorys/{id}:
|
||||
* put:
|
||||
* summary: Update a inventory
|
||||
* tags: [Inventorys]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:inventorys']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_INVENTORY'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/inventorys/{id}:
|
||||
* delete:
|
||||
* summary: Delete a inventory
|
||||
* tags: [Inventorys]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:inventorys']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_INVENTORY'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,76 +0,0 @@
|
||||
import repository from './inventory.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
import { ApiError } from '../../../utils/helpers/ApiError.utils.js';
|
||||
|
||||
export class InventoryService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new ApiError(404, 'Inventory not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('inventory:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Inventory',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new ApiError(404, 'Inventory not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('inventory:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Inventory',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new ApiError(404, 'Inventory not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('inventory:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Inventory',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new InventoryService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import localizationRouter from './localization/localization.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/localization', localizationRouter);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as localizationRoutes } from './localization.routes.js';
|
||||
export { default as localizationController } from './localization.controller.js';
|
||||
export { default as localizationService } from './localization.service.js';
|
||||
export { default as localizationRepository } from './localization.repository.js';
|
||||
export { default as localizationModel } from './localization.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './localization.service.js';
|
||||
|
||||
export class LocalizationController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Localization deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new LocalizationController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Localization extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Localization.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Localization',
|
||||
tableName: 'localizations',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Localization;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class LocalizationRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Localization.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Localization.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Localization.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new LocalizationRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './localization.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './localization.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/localizations:
|
||||
* get:
|
||||
* summary: Retrieve all localizations
|
||||
* tags: [Localizations]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:localizations']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/localizations/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single localization
|
||||
* tags: [Localizations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:localizations']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/localizations:
|
||||
* post:
|
||||
* summary: Create a localization
|
||||
* tags: [Localizations]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:localizations']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_LOCALIZATION'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/localizations/{id}:
|
||||
* put:
|
||||
* summary: Update a localization
|
||||
* tags: [Localizations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:localizations']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_LOCALIZATION'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/localizations/{id}:
|
||||
* delete:
|
||||
* summary: Delete a localization
|
||||
* tags: [Localizations]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:localizations']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_LOCALIZATION'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './localization.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class LocalizationService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Localization not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('localization:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Localization',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Localization not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('localization:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Localization',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Localization not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('localization:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Localization',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new LocalizationService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -13,6 +13,20 @@ import {
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-families:
|
||||
* get:
|
||||
* summary: Retrieve all asset families
|
||||
* tags: [Asset Families]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -20,6 +34,26 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-families/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single asset family
|
||||
* tags: [Asset Families]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -29,6 +63,30 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-families:
|
||||
* post:
|
||||
* summary: Create a new asset family
|
||||
* tags: [Asset Families]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [name]
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Created
|
||||
* 400:
|
||||
* description: Validation Error
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -39,6 +97,35 @@ router.post(
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-families/{id}:
|
||||
* put:
|
||||
* summary: Update an asset family
|
||||
* tags: [Asset Families]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -49,6 +136,26 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-families/{id}:
|
||||
* delete:
|
||||
* summary: Delete an asset family
|
||||
* tags: [Asset Families]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -13,6 +13,20 @@ import {
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-types:
|
||||
* get:
|
||||
* summary: Retrieve all asset types
|
||||
* tags: [Asset Types]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -20,6 +34,26 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-types/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single asset type
|
||||
* tags: [Asset Types]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -29,6 +63,30 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-types:
|
||||
* post:
|
||||
* summary: Create a new asset type
|
||||
* tags: [Asset Types]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [name]
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Created
|
||||
* 400:
|
||||
* description: Validation Error
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -39,6 +97,35 @@ router.post(
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-types/{id}:
|
||||
* put:
|
||||
* summary: Update an asset type
|
||||
* tags: [Asset Types]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -49,6 +136,26 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/asset-types/{id}:
|
||||
* delete:
|
||||
* summary: Delete an asset type
|
||||
* tags: [Asset Types]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -13,6 +13,20 @@ import {
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/assets:
|
||||
* get:
|
||||
* summary: Retrieve all assets
|
||||
* tags: [Assets]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -20,6 +34,26 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/assets/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single asset
|
||||
* tags: [Assets]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -29,6 +63,30 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/assets:
|
||||
* post:
|
||||
* summary: Create a new asset
|
||||
* tags: [Assets]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [name]
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Created
|
||||
* 400:
|
||||
* description: Validation Error
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -39,6 +97,35 @@ router.post(
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/assets/{id}:
|
||||
* put:
|
||||
* summary: Update an asset
|
||||
* tags: [Assets]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -49,6 +136,26 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/assets/{id}:
|
||||
* delete:
|
||||
* summary: Delete an asset
|
||||
* tags: [Assets]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import notificationsRouter from './notifications/notification.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/notifications', notificationsRouter);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as notificationRoutes } from './notification.routes.js';
|
||||
export { default as notificationController } from './notification.controller.js';
|
||||
export { default as notificationService } from './notification.service.js';
|
||||
export { default as notificationRepository } from './notification.repository.js';
|
||||
export { default as notificationModel } from './notification.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './notification.service.js';
|
||||
|
||||
export class NotificationController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Notification deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Notification extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Notification.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Notification',
|
||||
tableName: 'notifications',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Notification;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class NotificationRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Notification.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Notification.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Notification.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './notification.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './notification.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/notifications:
|
||||
* get:
|
||||
* summary: Retrieve all notifications
|
||||
* tags: [Notifications]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:notifications']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/notifications/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single notification
|
||||
* tags: [Notifications]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:notifications']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/notifications:
|
||||
* post:
|
||||
* summary: Create a notification
|
||||
* tags: [Notifications]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:notifications']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_NOTIFICATION'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/notifications/{id}:
|
||||
* put:
|
||||
* summary: Update a notification
|
||||
* tags: [Notifications]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:notifications']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_NOTIFICATION'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/notifications/{id}:
|
||||
* delete:
|
||||
* summary: Delete a notification
|
||||
* tags: [Notifications]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:notifications']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_NOTIFICATION'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './notification.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class NotificationService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Notification not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('notification:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Notification',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Notification not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('notification:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Notification',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Notification not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('notification:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Notification',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -5,6 +5,20 @@ import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/tenants:
|
||||
* get:
|
||||
* summary: Retrieve all tenants
|
||||
* tags: [Tenants]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -12,6 +26,26 @@ router.get(
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/tenants/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single tenant
|
||||
* tags: [Tenants]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* 404:
|
||||
* description: Not Found
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -19,6 +53,32 @@ router.get(
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/tenants:
|
||||
* post:
|
||||
* summary: Create a new tenant
|
||||
* tags: [Tenants]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required: [name, domain]
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* domain:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Created
|
||||
* 400:
|
||||
* description: Validation Error
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
@@ -26,6 +86,24 @@ router.post(
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/tenants/{id}:
|
||||
* put:
|
||||
* summary: Update a tenant
|
||||
* tags: [Tenants]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
@@ -33,6 +111,24 @@ router.put(
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/tenants/{id}:
|
||||
* delete:
|
||||
* summary: Delete a tenant
|
||||
* tags: [Tenants]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Deleted
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import pricingRouter from './pricing/pricing.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/pricing', pricingRouter);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as pricingRoutes } from './pricing.routes.js';
|
||||
export { default as pricingController } from './pricing.controller.js';
|
||||
export { default as pricingService } from './pricing.service.js';
|
||||
export { default as pricingRepository } from './pricing.repository.js';
|
||||
export { default as pricingModel } from './pricing.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './pricing.service.js';
|
||||
|
||||
export class PricingController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Pricing deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new PricingController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Pricing extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Pricing.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Pricing',
|
||||
tableName: 'pricings',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Pricing;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class PricingRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Pricing.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Pricing.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Pricing.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new PricingRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './pricing.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './pricing.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/pricings:
|
||||
* get:
|
||||
* summary: Retrieve all pricings
|
||||
* tags: [Pricings]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:pricings']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/pricings/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single pricing
|
||||
* tags: [Pricings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:pricings']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/pricings:
|
||||
* post:
|
||||
* summary: Create a pricing
|
||||
* tags: [Pricings]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:pricings']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_PRICING'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/pricings/{id}:
|
||||
* put:
|
||||
* summary: Update a pricing
|
||||
* tags: [Pricings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:pricings']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_PRICING'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/pricings/{id}:
|
||||
* delete:
|
||||
* summary: Delete a pricing
|
||||
* tags: [Pricings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:pricings']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_PRICING'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './pricing.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class PricingService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Pricing not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('pricing:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Pricing',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Pricing not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('pricing:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Pricing',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Pricing not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('pricing:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Pricing',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new PricingService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './approval.service.js';
|
||||
|
||||
export class ApprovalController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Approval deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApprovalController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Approval extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Approval.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Approval',
|
||||
tableName: 'approvals',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Approval;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class ApprovalRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Approval.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Approval.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Approval.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApprovalRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './approval.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './approval.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/approvals:
|
||||
* get:
|
||||
* summary: Retrieve all approvals
|
||||
* tags: [Approvals]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:approvals']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/approvals/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single approval
|
||||
* tags: [Approvals]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:approvals']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/approvals:
|
||||
* post:
|
||||
* summary: Create a approval
|
||||
* tags: [Approvals]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:approvals']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_APPROVAL'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/approvals/{id}:
|
||||
* put:
|
||||
* summary: Update a approval
|
||||
* tags: [Approvals]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:approvals']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_APPROVAL'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/approvals/{id}:
|
||||
* delete:
|
||||
* summary: Delete a approval
|
||||
* tags: [Approvals]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:approvals']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_APPROVAL'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './approval.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class ApprovalService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Approval not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('approval:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Approval',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Approval not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('approval:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Approval',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Approval not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('approval:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Approval',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApprovalService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as approvalRoutes } from './approval.routes.js';
|
||||
export { default as approvalController } from './approval.controller.js';
|
||||
export { default as approvalService } from './approval.service.js';
|
||||
export { default as approvalRepository } from './approval.repository.js';
|
||||
export { default as approvalModel } from './approval.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './bundle.service.js';
|
||||
|
||||
export class BundleController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Bundle deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new BundleController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Bundle extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Bundle.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Bundle',
|
||||
tableName: 'bundles',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Bundle;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class BundleRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Bundle.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Bundle.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Bundle.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new BundleRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './bundle.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './bundle.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/bundles:
|
||||
* get:
|
||||
* summary: Retrieve all bundles
|
||||
* tags: [Bundles]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:bundles']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/bundles/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single bundle
|
||||
* tags: [Bundles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:bundles']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/bundles:
|
||||
* post:
|
||||
* summary: Create a bundle
|
||||
* tags: [Bundles]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:bundles']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_BUNDLE'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/bundles/{id}:
|
||||
* put:
|
||||
* summary: Update a bundle
|
||||
* tags: [Bundles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:bundles']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_BUNDLE'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/bundles/{id}:
|
||||
* delete:
|
||||
* summary: Delete a bundle
|
||||
* tags: [Bundles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:bundles']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_BUNDLE'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './bundle.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class BundleService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Bundle not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('bundle:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Bundle',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Bundle not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('bundle:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Bundle',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Bundle not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('bundle:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Bundle',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new BundleService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as bundleRoutes } from './bundle.routes.js';
|
||||
export { default as bundleController } from './bundle.controller.js';
|
||||
export { default as bundleService } from './bundle.service.js';
|
||||
export { default as bundleRepository } from './bundle.repository.js';
|
||||
export { default as bundleModel } from './bundle.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './configurableProduct.service.js';
|
||||
|
||||
export class ConfigurableProductController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'ConfigurableProduct deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConfigurableProductController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class ConfigurableProduct extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
ConfigurableProduct.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'ConfigurableProduct',
|
||||
tableName: 'configurableproducts',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return ConfigurableProduct;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class ConfigurableProductRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.ConfigurableProduct.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.ConfigurableProduct.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.ConfigurableProduct.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConfigurableProductRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './configurableProduct.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './configurableProduct.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/configurableProducts:
|
||||
* get:
|
||||
* summary: Retrieve all configurableProducts
|
||||
* tags: [ConfigurableProducts]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:configurableProducts']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/configurableProducts/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single configurableProduct
|
||||
* tags: [ConfigurableProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:configurableProducts']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/configurableProducts:
|
||||
* post:
|
||||
* summary: Create a configurableProduct
|
||||
* tags: [ConfigurableProducts]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:configurableProducts']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_CONFIGURABLEPRODUCT'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/configurableProducts/{id}:
|
||||
* put:
|
||||
* summary: Update a configurableProduct
|
||||
* tags: [ConfigurableProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:configurableProducts']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_CONFIGURABLEPRODUCT'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/configurableProducts/{id}:
|
||||
* delete:
|
||||
* summary: Delete a configurableProduct
|
||||
* tags: [ConfigurableProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:configurableProducts']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_CONFIGURABLEPRODUCT'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './configurableProduct.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class ConfigurableProductService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('ConfigurableProduct not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('configurableProduct:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'ConfigurableProduct',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('ConfigurableProduct not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('configurableProduct:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'ConfigurableProduct',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('ConfigurableProduct not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('configurableProduct:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'ConfigurableProduct',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new ConfigurableProductService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as configurableProductRoutes } from './configurableProduct.routes.js';
|
||||
export { default as configurableProductController } from './configurableProduct.controller.js';
|
||||
export { default as configurableProductService } from './configurableProduct.service.js';
|
||||
export { default as configurableProductRepository } from './configurableProduct.repository.js';
|
||||
export { default as configurableProductModel } from './configurableProduct.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './digitalProduct.service.js';
|
||||
|
||||
export class DigitalProductController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'DigitalProduct deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new DigitalProductController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class DigitalProduct extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
DigitalProduct.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'DigitalProduct',
|
||||
tableName: 'digitalproducts',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return DigitalProduct;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class DigitalProductRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.DigitalProduct.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.DigitalProduct.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.DigitalProduct.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new DigitalProductRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './digitalProduct.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './digitalProduct.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/digitalProducts:
|
||||
* get:
|
||||
* summary: Retrieve all digitalProducts
|
||||
* tags: [DigitalProducts]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:digitalProducts']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/digitalProducts/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single digitalProduct
|
||||
* tags: [DigitalProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:digitalProducts']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/digitalProducts:
|
||||
* post:
|
||||
* summary: Create a digitalProduct
|
||||
* tags: [DigitalProducts]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:digitalProducts']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_DIGITALPRODUCT'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/digitalProducts/{id}:
|
||||
* put:
|
||||
* summary: Update a digitalProduct
|
||||
* tags: [DigitalProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:digitalProducts']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_DIGITALPRODUCT'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/digitalProducts/{id}:
|
||||
* delete:
|
||||
* summary: Delete a digitalProduct
|
||||
* tags: [DigitalProducts]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:digitalProducts']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_DIGITALPRODUCT'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './digitalProduct.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class DigitalProductService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('DigitalProduct not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('digitalProduct:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'DigitalProduct',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('DigitalProduct not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('digitalProduct:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'DigitalProduct',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('DigitalProduct not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('digitalProduct:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'DigitalProduct',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new DigitalProductService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as digitalProductRoutes } from './digitalProduct.routes.js';
|
||||
export { default as digitalProductController } from './digitalProduct.controller.js';
|
||||
export { default as digitalProductService } from './digitalProduct.service.js';
|
||||
export { default as digitalProductRepository } from './digitalProduct.repository.js';
|
||||
export { default as digitalProductModel } from './digitalProduct.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './family.service.js';
|
||||
|
||||
export class FamilyController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Family deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new FamilyController();
|
||||
@@ -1,55 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Family extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here if any
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Family.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
code: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
description: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true
|
||||
},
|
||||
category: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
attributes: {
|
||||
type: DataTypes.JSONB,
|
||||
defaultValue: []
|
||||
},
|
||||
variant_axes: {
|
||||
type: DataTypes.JSONB,
|
||||
defaultValue: []
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Family',
|
||||
tableName: 'families',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Family;
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class FamilyRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Family.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Family.findByPk(id, options);
|
||||
}
|
||||
|
||||
async findByCode(code, options = {}) {
|
||||
return await models.Family.findOne({ where: { code }, ...options });
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Family.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new FamilyRepository();
|
||||
@@ -1,62 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './family.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './family.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:products']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:products']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:products']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_FAMILY'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:products']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_FAMILY'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:products']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_FAMILY'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,72 +0,0 @@
|
||||
import repository from './family.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class FamilyService {
|
||||
async getAll(query = {}) {
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Family not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
SocketService.broadcast('family:created', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Family',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Family not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('family:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Family',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Family not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('family:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Family',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new FamilyService();
|
||||
@@ -1,36 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('code')
|
||||
.isString()
|
||||
.trim()
|
||||
.notEmpty()
|
||||
.withMessage('Code is required'),
|
||||
body('name')
|
||||
.isString()
|
||||
.trim()
|
||||
.notEmpty()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,24 +1,8 @@
|
||||
import { Router } from 'express';
|
||||
import productsRouter from './products/product.routes.js';
|
||||
import variantsRouter from './variants/variant.routes.js';
|
||||
import bundlesRouter from './bundles/bundle.routes.js';
|
||||
import configurableProductsRouter from './configurableProducts/configurableProduct.routes.js';
|
||||
import digitalProductsRouter from './digitalProducts/digitalProduct.routes.js';
|
||||
import lifecycleRouter from './lifecycle/lifecycle.routes.js';
|
||||
import approvalsRouter from './approvals/approval.routes.js';
|
||||
import publishingRouter from './publishing/publishing.routes.js';
|
||||
import familiesRouter from './families/family.routes.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/products', productsRouter);
|
||||
router.use('/variants', variantsRouter);
|
||||
router.use('/bundles', bundlesRouter);
|
||||
router.use('/configurableproducts', configurableProductsRouter);
|
||||
router.use('/digitalproducts', digitalProductsRouter);
|
||||
router.use('/lifecycle', lifecycleRouter);
|
||||
router.use('/approvals', approvalsRouter);
|
||||
router.use('/publishing', publishingRouter);
|
||||
router.use('/families', familiesRouter);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as lifecycleRoutes } from './lifecycle.routes.js';
|
||||
export { default as lifecycleController } from './lifecycle.controller.js';
|
||||
export { default as lifecycleService } from './lifecycle.service.js';
|
||||
export { default as lifecycleRepository } from './lifecycle.repository.js';
|
||||
export { default as lifecycleModel } from './lifecycle.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './lifecycle.service.js';
|
||||
|
||||
export class LifecycleController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Lifecycle deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new LifecycleController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Lifecycle extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Lifecycle.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Lifecycle',
|
||||
tableName: 'lifecycles',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Lifecycle;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class LifecycleRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Lifecycle.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Lifecycle.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Lifecycle.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new LifecycleRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './lifecycle.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './lifecycle.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/lifecycles:
|
||||
* get:
|
||||
* summary: Retrieve all lifecycles
|
||||
* tags: [Lifecycles]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:lifecycles']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/lifecycles/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single lifecycle
|
||||
* tags: [Lifecycles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:lifecycles']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/lifecycles:
|
||||
* post:
|
||||
* summary: Create a lifecycle
|
||||
* tags: [Lifecycles]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:lifecycles']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_LIFECYCLE'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/lifecycles/{id}:
|
||||
* put:
|
||||
* summary: Update a lifecycle
|
||||
* tags: [Lifecycles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:lifecycles']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_LIFECYCLE'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/lifecycles/{id}:
|
||||
* delete:
|
||||
* summary: Delete a lifecycle
|
||||
* tags: [Lifecycles]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:lifecycles']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_LIFECYCLE'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './lifecycle.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class LifecycleService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Lifecycle not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('lifecycle:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Lifecycle',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Lifecycle not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('lifecycle:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Lifecycle',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Lifecycle not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('lifecycle:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Lifecycle',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new LifecycleService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as publishingRoutes } from './publishing.routes.js';
|
||||
export { default as publishingController } from './publishing.controller.js';
|
||||
export { default as publishingService } from './publishing.service.js';
|
||||
export { default as publishingRepository } from './publishing.repository.js';
|
||||
export { default as publishingModel } from './publishing.model.js';
|
||||
@@ -1,50 +0,0 @@
|
||||
import service from './publishing.service.js';
|
||||
|
||||
export class PublishingController {
|
||||
async getAll(req, res, next) {
|
||||
try {
|
||||
const records = await service.getAll(req.query);
|
||||
return res.status(200).json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getById(req, res, next) {
|
||||
try {
|
||||
const record = await service.getById(req.params.id);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async create(req, res, next) {
|
||||
try {
|
||||
const record = await service.create(req.body, req.user);
|
||||
return res.status(201).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async update(req, res, next) {
|
||||
try {
|
||||
const record = await service.update(req.params.id, req.body, req.user);
|
||||
return res.status(200).json({ success: true, data: record });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(req, res, next) {
|
||||
try {
|
||||
await service.delete(req.params.id, req.user);
|
||||
return res.status(200).json({ success: true, message: 'Publishing deleted successfully' });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new PublishingController();
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
|
||||
export class Publishing extends Model {
|
||||
static associate(models) {
|
||||
// Define associations here
|
||||
}
|
||||
}
|
||||
|
||||
export default (sequelize) => {
|
||||
Publishing.init({
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'active'
|
||||
},
|
||||
metadata: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
modelName: 'Publishing',
|
||||
tableName: 'publishings',
|
||||
timestamps: true,
|
||||
underscored: true
|
||||
});
|
||||
|
||||
return Publishing;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { models } from '../../../shared/database/models.js';
|
||||
|
||||
export class PublishingRepository {
|
||||
async findAll(options = {}) {
|
||||
return await models.Publishing.findAll(options);
|
||||
}
|
||||
|
||||
async findById(id, options = {}) {
|
||||
return await models.Publishing.findByPk(id, options);
|
||||
}
|
||||
|
||||
async create(data, options = {}) {
|
||||
return await models.Publishing.create(data, options);
|
||||
}
|
||||
|
||||
async update(id, data, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return null;
|
||||
return await record.update(data, options);
|
||||
}
|
||||
|
||||
async delete(id, options = {}) {
|
||||
const record = await this.findById(id, options);
|
||||
if (!record) return false;
|
||||
await record.destroy(options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new PublishingRepository();
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import controller from './publishing.controller.js';
|
||||
import { authenticate } from '../../../shared/middleware/auth.middleware.js';
|
||||
import { validate } from '../../../shared/middleware/validation.middleware.js';
|
||||
import { authorize } from '../../../shared/middleware/permission.middleware.js';
|
||||
import { audit } from '../../../shared/middleware/audit.middleware.js';
|
||||
import {
|
||||
createValidation,
|
||||
updateValidation,
|
||||
deleteValidation,
|
||||
getByIdValidation
|
||||
} from './publishing.validation.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/publishings:
|
||||
* get:
|
||||
* summary: Retrieve all publishings
|
||||
* tags: [Publishings]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['read:publishings']),
|
||||
controller.getAll
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/publishings/{id}:
|
||||
* get:
|
||||
* summary: Retrieve a single publishing
|
||||
* tags: [Publishings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.get(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['read:publishings']),
|
||||
getByIdValidation,
|
||||
validate,
|
||||
controller.getById
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/publishings:
|
||||
* post:
|
||||
* summary: Create a publishing
|
||||
* tags: [Publishings]
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Success
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
authenticate,
|
||||
authorize(['write:publishings']),
|
||||
createValidation,
|
||||
validate,
|
||||
audit('CREATE_PUBLISHING'),
|
||||
controller.create
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/publishings/{id}:
|
||||
* put:
|
||||
* summary: Update a publishing
|
||||
* tags: [Publishings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.put(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:publishings']),
|
||||
updateValidation,
|
||||
validate,
|
||||
audit('UPDATE_PUBLISHING'),
|
||||
controller.update
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/publishings/{id}:
|
||||
* delete:
|
||||
* summary: Delete a publishing
|
||||
* tags: [Publishings]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
*/
|
||||
router.delete(
|
||||
'/:id',
|
||||
authenticate,
|
||||
authorize(['write:publishings']),
|
||||
deleteValidation,
|
||||
validate,
|
||||
audit('DELETE_PUBLISHING'),
|
||||
controller.delete
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,75 +0,0 @@
|
||||
import repository from './publishing.repository.js';
|
||||
import { SocketService } from '../../../shared/services/socket.service.js';
|
||||
import { AuditService } from '../../../shared/services/audit.service.js';
|
||||
|
||||
export class PublishingService {
|
||||
async getAll(query = {}) {
|
||||
// Add business logic filtering, pagination, etc.
|
||||
return await repository.findAll();
|
||||
}
|
||||
|
||||
async getById(id) {
|
||||
const record = await repository.findById(id);
|
||||
if (!record) {
|
||||
throw new Error('Publishing not found');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
async create(data, userContext = {}) {
|
||||
const record = await repository.create(data);
|
||||
|
||||
// Broadcast event
|
||||
SocketService.broadcast('publishing:created', record);
|
||||
|
||||
// Log audit
|
||||
await AuditService.log({
|
||||
action: 'CREATE',
|
||||
resource: 'Publishing',
|
||||
resourceId: record.id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async update(id, data, userContext = {}) {
|
||||
const record = await repository.update(id, data);
|
||||
if (!record) {
|
||||
throw new Error('Publishing not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('publishing:updated', record);
|
||||
|
||||
await AuditService.log({
|
||||
action: 'UPDATE',
|
||||
resource: 'Publishing',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system',
|
||||
details: data
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
async delete(id, userContext = {}) {
|
||||
const deleted = await repository.delete(id);
|
||||
if (!deleted) {
|
||||
throw new Error('Publishing not found');
|
||||
}
|
||||
|
||||
SocketService.broadcast('publishing:deleted', { id });
|
||||
|
||||
await AuditService.log({
|
||||
action: 'DELETE',
|
||||
resource: 'Publishing',
|
||||
resourceId: id,
|
||||
userId: userContext.id || 'system'
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new PublishingService();
|
||||
@@ -1,32 +0,0 @@
|
||||
import { body, param } from 'express-validator';
|
||||
|
||||
export const createValidation = [
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const updateValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required'),
|
||||
body('name')
|
||||
.optional()
|
||||
.isString()
|
||||
.trim()
|
||||
.withMessage('Name must be a string')
|
||||
];
|
||||
|
||||
export const deleteValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
|
||||
export const getByIdValidation = [
|
||||
param('id')
|
||||
.isUUID()
|
||||
.withMessage('Valid UUID is required')
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user