Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,5 @@ typings/

# DynamoDB Local files
.dynamodb/

.vscode/
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"printWidth": 160,
"printWidth": 140,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
Expand Down
29 changes: 18 additions & 11 deletions src/app/operations/product/createProductOperation.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
module.exports = ({ createProductUsecase, createWarehouseUsecase, bindingProductWarehouse }) => ({
module.exports = ({ createProductUsecase, createWarehouseUsecase, bindingProductWarehouse, removeProductByIdUsecase }) => ({
execute: async (data) => {
const { warehouse } = data;
const product = await createProductUsecase.execute(data);
if (!product) {
return;
let productId;
try {
const { warehouse } = data;
const product = await createProductUsecase.execute(data);
if (!product) {
return;
}
productId = product.id;

if (warehouse) {
const warehouseCretead = await Promise.all(warehouse.map((element) => createWarehouseUsecase.execute(element)));
await bindingProductWarehouse.execute(productId, warehouseCretead);
}
return product;
} catch (error) {
await removeProductByIdUsecase.execute(productId);
return error;
}
if (warehouse) {
const warehouseCretead = await Promise.all(warehouse.map((element) => createWarehouseUsecase.execute(element)));
// TODO: validate warehouseCreated
await bindingProductWarehouse.execute(product.id, warehouseCretead);
}
return product;
}
});
36 changes: 36 additions & 0 deletions src/app/operations/product/removeProductOperation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = ({
removeProductBySkuUsecase,
findProductBySkuUsecase,
removeWarehouseByIdUsecase,
findProductWarehouseByProductIdUsecase,
removeProductWareseByProductIdUsecase,
exceptions
}) => ({
execute: async (data) => {
const product = await findProductBySkuUsecase.execute(data);
if (!product) {
throw exceptions.notFoundError('[findProductBySkuUsecase] product is not found');
}
const { id, sku } = product;
const productWarehouse = await findProductWarehouseByProductIdUsecase.execute(id);
if (!productWarehouse || productWarehouse.length === 0) {
throw exceptions.notFoundError('[findProductWarehouseByProductIdUsecase] bind product and warehouse not found');
}
const productWarehouseIsRemoved = await removeProductWareseByProductIdUsecase.execute(id);
if (!productWarehouseIsRemoved) {
throw exceptions.internalError('[removeProductWareseByProductIdUsecase]');
}

const productIsRemoved = await removeProductBySkuUsecase.execute(sku);
if (!productIsRemoved) {
throw exceptions.internalError('[removeProductBySkuUsecase]');
}

const warehouseIsRemoved = await Promise.all(productWarehouse.map((item) => removeWarehouseByIdUsecase.execute(item.warehouseId)));
if (!warehouseIsRemoved) {
throw exceptions.internalError('[removeWarehouseByIdUsecase]');
}

return productIsRemoved;
}
});
10 changes: 7 additions & 3 deletions src/app/usecases/createProductUsecase.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
module.exports = ({ productRepository }) => ({
module.exports = ({ productRepository, exceptions }) => ({
execute: async (data) => {
const response = await productRepository.create(data);
return response;
try {
const response = await productRepository.create(data);
return response;
} catch (error) {
throw exceptions.internalError(JSON.stringify(error.errors));
}
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/findProductBySkuUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ productRepository }) => ({
execute: async (data) => {
const response = await productRepository.findBySku(data);
return response;
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/findProductWarehouseByProductIdUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ productWarehouseRepository }) => ({
execute: async (data) => {
const response = await productWarehouseRepository.findAllByProductId(data);
return response;
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/removeProductByIdUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ productRepository }) => ({
execute: async (data) => {
const response = await productRepository.removeById(data);
return response;
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/removeProductBySkuUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ productRepository }) => ({
execute: async (data) => {
const response = await productRepository.removeBySku(data);
return response;
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/removeProductWareseByProductIdUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ productWarehouseRepository }) => ({
execute: async (data) => {
const response = await productWarehouseRepository.removeByProductId(data);
return response;
}
});
6 changes: 6 additions & 0 deletions src/app/usecases/removeWarehouseByIdUsecase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = ({ warehouseRepository }) => ({
execute: async (data) => {
const response = await warehouseRepository.removeById(data);
return response;
}
});
7 changes: 7 additions & 0 deletions src/infra/errors/BadRequestError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class BadRequestError extends Error {
constructor(details) {
super(`Bad Request ${details}`);
this.name = 'BadRequestError';
}
}
module.exports = () => BadRequestError;
18 changes: 17 additions & 1 deletion src/infra/errors/Exceptions.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
module.exports = ({ internalServerError: InternalServerError }) => ({
module.exports = ({ internalServerError: InternalServerError, notFoundError: NotFoundError, badRequestError: BadRequestError }) => ({
internalError: (details) => {
const error = new InternalServerError(details);
return {
status: 500,
body: error.name
};
},

notFound: (details) => {
const error = new NotFoundError(details);
return {
status: 500,
body: error.name
};
},

badRequest: (details) => {
const error = new BadRequestError(details);
return {
status: 500,
body: error.name
};
}
});
7 changes: 7 additions & 0 deletions src/infra/errors/NotFoundError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class NotFoundError extends Error {
constructor(details) {
super(`Not found ${details}`);
this.name = 'NotFoundError';
}
}
module.exports = () => NotFoundError;
21 changes: 16 additions & 5 deletions src/infra/repositories/Repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,26 @@ class Repository {
}

async create(domainEntity) {
const model = await new this.ResourceModel(this.ResourceMapper.toInputDatabase(domainEntity));
const dbCreatedResource = await model.save();
const resource = await new this.ResourceModel(this.ResourceMapper.toInputDatabase(domainEntity));
const dbCreatedResource = await resource.save();
return this.ResourceMapper.toOutputDabase(dbCreatedResource);
}

async findOne(query) {
const resource = await this.ResourceModel.findOne(query);
if (!resource) return resource;
return this.ResourceMapper.toOutputDabase(resource);
}

async findAll(query) {
const model = await this.ResourceModel.findAll(query);
if (!model) return model;
return model.map(this.ResourceMapper.toOutputDabase);
const resource = await this.ResourceModel.findAll(query);
if (!resource) return resource;
return resource.map(this.ResourceMapper.toOutputDabase);
}

async remove(query) {
const resource = await this.ResourceModel.destroy(query);
return resource > 0;
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/infra/repositories/product/ProductRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ class ProductRepository extends Repository {
Exceptions: exceptions
});
}

async findBySku(sku) {
const resource = await this.findOne({ where: { sku } });
return resource;
}

async removeById(productId) {
const resource = await this.remove({ where: { id: productId } });
return resource;
}

async removeBySku(sku) {
const resource = await this.remove({ where: { sku } });
return resource;
}
}

module.exports = ProductRepository;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const ProductWarehouseMapper = {
toInputDatabase(entry) {
console.log(entry);
return entry;
},
toOutputDabase({ dataValues }) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Repository = require('../Repository');

class WarehouseRepository extends Repository {
class ProductWarehouseRepository extends Repository {
constructor({ sequelize, productWarehouseMapper, exceptions }) {
const { ProductWarehouse } = sequelize.models;
super({
Expand All @@ -9,6 +9,16 @@ class WarehouseRepository extends Repository {
Exceptions: exceptions
});
}

async findAllByProductId(productId) {
const resource = await this.findAll({ where: { productId } });
return resource;
}

async removeByProductId(productId) {
const resource = await this.remove({ where: { productId } });
return resource;
}
}

module.exports = WarehouseRepository;
module.exports = ProductWarehouseRepository;
5 changes: 5 additions & 0 deletions src/infra/repositories/warehouse/WarehouseRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class WarehouseRepository extends Repository {
Exceptions: exceptions
});
}

async removeById(id) {
const resource = await this.remove({ where: { id } });
return resource;
}
}

module.exports = WarehouseRepository;
17 changes: 13 additions & 4 deletions src/interfaces/http/controllers/productController.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
const { Router } = require('express');
const Status = require('http-status');

module.exports = ({ createProductOperation }) => ({
module.exports = ({ createProductOperation, removeProductOperation }) => ({
create: async (req, res, next) => {
try {
const { body } = req;
const product = await createProductOperation.execute(body);
return res.status(Status.OK).json(product);
await createProductOperation.execute(body);
return res.status(Status.CREATED).end();
} catch (error) {
next(error);
}
},

removeBySku: async (req, res, next) => {
try {
const { sku } = req.params;
const responseOperation = await removeProductOperation.execute(typeof sku === 'string' ? Number(sku) : sku);
return res.status(Status.OK).json(responseOperation);
} catch (error) {
next(error);
}
},
get router() {
return Router().post('/', this.create);
return Router().post('/', this.create).delete('/sku/:sku', this.removeBySku);
}
});