.
This commit is contained in:
parent
ccdf2efef3
commit
af1eca6c30
13
server/jest.config.js
Normal file
13
server/jest.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
globals: {
|
||||||
|
"ts-jest": {
|
||||||
|
tsconfig: "tsconfig.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ["ts", "js"],
|
||||||
|
transform: {
|
||||||
|
"^.+\\.(ts|tsx)$": "ts-jest",
|
||||||
|
},
|
||||||
|
testMatch: ["**/*.test.(ts|js)"],
|
||||||
|
testEnvironment: "node",
|
||||||
|
};
|
||||||
@ -64,7 +64,6 @@
|
|||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"mysql2": "^3.6.0",
|
"mysql2": "^3.6.0",
|
||||||
"node-firebird": "^1.1.8",
|
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"remove": "^0.1.5",
|
"remove": "^0.1.5",
|
||||||
"response-time": "^2.3.2",
|
"response-time": "^2.3.2",
|
||||||
|
|||||||
@ -13,25 +13,25 @@ import {
|
|||||||
} from "@shared/contexts";
|
} from "@shared/contexts";
|
||||||
|
|
||||||
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
||||||
import { IFirebirdAdapter } from "@/contexts/common/infrastructure/firebird";
|
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { ICatalogRepository, Product } from "../domain";
|
import { Article, ICatalogRepository } from "../domain";
|
||||||
|
|
||||||
export interface IListProductsParams {
|
export interface IListArticlesParams {
|
||||||
queryCriteria: IQueryCriteria;
|
queryCriteria: IQueryCriteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ListProductsResult =
|
export type ListArticlesResult =
|
||||||
| Result<never, IUseCaseError> // Misc errors (value objects)
|
| Result<never, IUseCaseError> // Misc errors (value objects)
|
||||||
| Result<ICollection<Product>, never>; // Success!
|
| Result<ICollection<Article>, never>; // Success!
|
||||||
|
|
||||||
export class ListProductsUseCase
|
export class ListArticlesUseCase
|
||||||
implements IUseCase<IListProductsParams, Promise<ListProductsResult>>
|
implements IUseCase<IListArticlesParams, Promise<ListArticlesResult>>
|
||||||
{
|
{
|
||||||
private _adapter: IFirebirdAdapter;
|
private _adapter: ISequelizeAdapter;
|
||||||
private _repositoryManager: IRepositoryManager;
|
private _repositoryManager: IRepositoryManager;
|
||||||
|
|
||||||
constructor(props: {
|
constructor(props: {
|
||||||
adapter: IFirebirdAdapter;
|
adapter: ISequelizeAdapter;
|
||||||
repositoryManager: IRepositoryManager;
|
repositoryManager: IRepositoryManager;
|
||||||
}) {
|
}) {
|
||||||
this._adapter = props.adapter;
|
this._adapter = props.adapter;
|
||||||
@ -43,19 +43,19 @@ export class ListProductsUseCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
params: Partial<IListProductsParams>
|
params: Partial<IListArticlesParams>
|
||||||
): Promise<ListProductsResult> {
|
): Promise<ListArticlesResult> {
|
||||||
const { queryCriteria } = params;
|
const { queryCriteria } = params;
|
||||||
|
|
||||||
return this.findProducts(queryCriteria);
|
return this.findArticles(queryCriteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findProducts(queryCriteria) {
|
private async findArticles(queryCriteria) {
|
||||||
const transaction = this._adapter.startTransaction();
|
const transaction = this._adapter.startTransaction();
|
||||||
const productRepoBuilder =
|
const productRepoBuilder =
|
||||||
this.getRepositoryByName<ICatalogRepository>("Product");
|
this.getRepositoryByName<ICatalogRepository>("Article");
|
||||||
|
|
||||||
let products: ICollection<Product> = new Collection();
|
let products: ICollection<Article> = new Collection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
transaction.complete(async (t) => {
|
transaction.complete(async (t) => {
|
||||||
@ -1 +1 @@
|
|||||||
export * from "./ListProductsUseCase";
|
export * from "./ListArticlesUseCase";
|
||||||
|
|||||||
87
server/src/contexts/catalog/domain/entities/Article.ts
Normal file
87
server/src/contexts/catalog/domain/entities/Article.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import {
|
||||||
|
AggregateRoot,
|
||||||
|
Description,
|
||||||
|
IDomainError,
|
||||||
|
Quantity,
|
||||||
|
Result,
|
||||||
|
Slug,
|
||||||
|
UniqueID,
|
||||||
|
UnitPrice,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
|
||||||
|
export interface IArticleProps {
|
||||||
|
catalog_name: Slug;
|
||||||
|
id_article: Description;
|
||||||
|
reference: Slug;
|
||||||
|
family: Description;
|
||||||
|
subfamily: Description;
|
||||||
|
description: Description;
|
||||||
|
points: Quantity;
|
||||||
|
retail_price: UnitPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IArticle {
|
||||||
|
id: UniqueID;
|
||||||
|
catalog_name: Slug;
|
||||||
|
id_article: Description;
|
||||||
|
reference: Slug;
|
||||||
|
family: Description;
|
||||||
|
subfamily: Description;
|
||||||
|
description: Description;
|
||||||
|
points: Quantity;
|
||||||
|
retail_price: UnitPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Article extends AggregateRoot<IArticleProps> implements IArticle {
|
||||||
|
public static create(
|
||||||
|
props: IArticleProps,
|
||||||
|
id?: UniqueID
|
||||||
|
): Result<Article, IDomainError> {
|
||||||
|
//const isNew = !!id === false;
|
||||||
|
|
||||||
|
// Se hace en el constructor de la Entidad
|
||||||
|
/* if (isNew) {
|
||||||
|
id = UniqueEntityID.create();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
const product = new Article(props, id);
|
||||||
|
|
||||||
|
return Result.ok<Article>(product);
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(props: IArticleProps, id?: UniqueID) {
|
||||||
|
super(props, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
get catalog_name(): Slug {
|
||||||
|
return this.props.catalog_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id_article(): Description {
|
||||||
|
return this.props.id_article;
|
||||||
|
}
|
||||||
|
|
||||||
|
get reference(): Slug {
|
||||||
|
return this.props.reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
get family(): Description {
|
||||||
|
return this.props.family;
|
||||||
|
}
|
||||||
|
|
||||||
|
get subfamily(): Description {
|
||||||
|
return this.props.subfamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
get description(): Description {
|
||||||
|
return this.props.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
get points(): Quantity {
|
||||||
|
return this.props.points;
|
||||||
|
}
|
||||||
|
|
||||||
|
get retail_price(): UnitPrice {
|
||||||
|
return this.props.retail_price;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,75 +0,0 @@
|
|||||||
import {
|
|
||||||
AggregateRoot,
|
|
||||||
Description,
|
|
||||||
IDomainError,
|
|
||||||
MoneyValueObject,
|
|
||||||
Result,
|
|
||||||
StringValueObject,
|
|
||||||
UniqueID,
|
|
||||||
ValueObject,
|
|
||||||
} from "@shared/contexts";
|
|
||||||
|
|
||||||
export interface IProductProps {
|
|
||||||
reference: StringValueObject;
|
|
||||||
family: StringValueObject;
|
|
||||||
subfamily: StringValueObject;
|
|
||||||
description: StringValueObject;
|
|
||||||
points: ValueObject<number>;
|
|
||||||
pvp: MoneyValueObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IProduct {
|
|
||||||
id: UniqueID;
|
|
||||||
reference: Description;
|
|
||||||
family: Description;
|
|
||||||
subfamily: Description;
|
|
||||||
description: Description;
|
|
||||||
points: ValueObject<number>;
|
|
||||||
pvp: MoneyValueObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Product extends AggregateRoot<IProductProps> implements IProduct {
|
|
||||||
public static create(
|
|
||||||
props: IProductProps,
|
|
||||||
id?: UniqueID
|
|
||||||
): Result<Product, IDomainError> {
|
|
||||||
//const isNew = !!id === false;
|
|
||||||
|
|
||||||
// Se hace en el constructor de la Entidad
|
|
||||||
/* if (isNew) {
|
|
||||||
id = UniqueEntityID.create();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const product = new Product(props, id);
|
|
||||||
|
|
||||||
return Result.ok<Product>(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
private constructor(props: IProductProps, id?: UniqueID) {
|
|
||||||
super(props, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
get reference(): Description {
|
|
||||||
return this.props.reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
get family(): Description {
|
|
||||||
return this.props.family;
|
|
||||||
}
|
|
||||||
|
|
||||||
get subfamily(): Description {
|
|
||||||
return this.props.subfamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
get description(): Description {
|
|
||||||
return this.props.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
get points(): ValueObject<number> {
|
|
||||||
return this.props.points;
|
|
||||||
}
|
|
||||||
|
|
||||||
get pvp(): MoneyValueObject {
|
|
||||||
return this.props.pvp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +1 @@
|
|||||||
export * from "./Product";
|
export * from "./Article";
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { IRepository } from "@/contexts/common/domain";
|
import { IRepository } from "@/contexts/common/domain";
|
||||||
import { ICollection, IQueryCriteria } from "@shared/contexts";
|
import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
|
||||||
import { Product } from "../entities";
|
import { Article } from "../entities";
|
||||||
|
|
||||||
export interface ICatalogRepository extends IRepository<any> {
|
export interface ICatalogRepository extends IRepository<any> {
|
||||||
findAll(queryCriteria?: IQueryCriteria): Promise<ICollection<Product>>;
|
getById(id: UniqueID): Promise<Article | null>;
|
||||||
|
findAll(queryCriteria?: IQueryCriteria): Promise<ICollection<Article>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
FirebirdRepository,
|
ISequelizeAdapter,
|
||||||
IFirebirdAdapter,
|
SequelizeRepository,
|
||||||
} from "@/contexts/common/infrastructure/firebird";
|
} from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
|
import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
|
||||||
import Firebird from "node-firebird";
|
import { Transaction } from "sequelize";
|
||||||
import { Product } from "../domain/entities";
|
import { Article } from "../domain/entities";
|
||||||
import { ICatalogRepository } from "../domain/repository/CatalogRepository.interface";
|
import { ICatalogRepository } from "../domain/repository/CatalogRepository.interface";
|
||||||
import { Product_Model } from "./firebird";
|
import { IArticleMapper } from "./mappers/article.mapper";
|
||||||
import { IProductMapper } from "./mappers/product.mapper";
|
|
||||||
|
|
||||||
export type QueryParams = {
|
export type QueryParams = {
|
||||||
pagination: Record<string, any>;
|
pagination: Record<string, any>;
|
||||||
@ -15,55 +14,42 @@ export type QueryParams = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class CatalogRepository
|
export class CatalogRepository
|
||||||
extends FirebirdRepository<Product>
|
extends SequelizeRepository<Article>
|
||||||
implements ICatalogRepository
|
implements ICatalogRepository
|
||||||
{
|
{
|
||||||
protected mapper: IProductMapper;
|
protected mapper: IArticleMapper;
|
||||||
|
|
||||||
public constructor(props: {
|
public constructor(props: {
|
||||||
mapper: IProductMapper;
|
mapper: IArticleMapper;
|
||||||
adapter: IFirebirdAdapter;
|
adapter: ISequelizeAdapter;
|
||||||
transaction: Firebird.Transaction;
|
transaction: Transaction;
|
||||||
}) {
|
}) {
|
||||||
const { adapter, mapper, transaction } = props;
|
const { adapter, mapper, transaction } = props;
|
||||||
super({ adapter, transaction });
|
super({ adapter, transaction });
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getById(id: UniqueID): Promise<Product | null> {
|
public async getById(id: UniqueID): Promise<Article | null> {
|
||||||
const rawProduct: Product_Model = await this.adapter.execute(
|
const rawArticle: any = await this._getById("Article_Model", id);
|
||||||
"SELECT * FROM ARTICULOS WHERE ID=?",
|
|
||||||
[id.toString()]
|
|
||||||
);
|
|
||||||
|
|
||||||
return this.mapper.mapToDomain(rawProduct);
|
if (!rawArticle === true) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.mapper.mapToDomain(rawArticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public async count(): number {
|
|
||||||
const result = await this.adapter.execute<number>(
|
|
||||||
"SELECT count(*) FROM ARTICULOS",
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public async findAll(
|
public async findAll(
|
||||||
queryCriteria?: IQueryCriteria
|
queryCriteria?: IQueryCriteria
|
||||||
): Promise<ICollection<Product>> {
|
): Promise<ICollection<any>> {
|
||||||
let rows: Product_Model[] = [];
|
const { rows, count } = await this._findAll(
|
||||||
const count = await this.adapter.execute<number[]>(
|
"Article_Model",
|
||||||
"SELECT count(*) FROM ARTICULOS",
|
queryCriteria
|
||||||
[]
|
/*{
|
||||||
|
include: [], // esto es para quitar las asociaciones al hacer la consulta
|
||||||
|
}*/
|
||||||
);
|
);
|
||||||
if (count[0]) {
|
|
||||||
rows = await this.adapter.execute<Product_Model[]>(
|
|
||||||
"SELECT * FROM ARTICULOS",
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.mapper.mapArrayAndCountToDomain(rows, count[0]);
|
return this.mapper.mapArrayAndCountToDomain(rows, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import express, { NextFunction, Request, Response, Router } from "express";
|
import express, { NextFunction, Request, Response, Router } from "express";
|
||||||
|
|
||||||
import { RepositoryManager } from "@/contexts/common/domain";
|
import { RepositoryManager } from "@/contexts/common/domain";
|
||||||
import { createFirebirdAdapter } from "@/contexts/common/infrastructure/firebird";
|
import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { createListProductsController } from "./controllers/listProducts";
|
import { createListArticlesController } from "./controllers";
|
||||||
|
|
||||||
const catalogRouter: Router = express.Router({ mergeParams: true });
|
const catalogRouter: Router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ catalogRouter.use(logMiddleware);
|
|||||||
|
|
||||||
const contextMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
const contextMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
||||||
res.locals["context"] = {
|
res.locals["context"] = {
|
||||||
adapter: createFirebirdAdapter(),
|
adapter: createSequelizeAdapter(),
|
||||||
repositoryManager: RepositoryManager.getInstance(),
|
repositoryManager: RepositoryManager.getInstance(),
|
||||||
services: {},
|
services: {},
|
||||||
};
|
};
|
||||||
@ -28,7 +28,7 @@ const contextMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
|||||||
catalogRouter.use(contextMiddleware);
|
catalogRouter.use(contextMiddleware);
|
||||||
|
|
||||||
catalogRouter.get("/", (req: Request, res: Response, next: NextFunction) =>
|
catalogRouter.get("/", (req: Request, res: Response, next: NextFunction) =>
|
||||||
createListProductsController(res.locals["context"]).execute(req, res, next)
|
createListArticlesController(res.locals["context"]).execute(req, res, next)
|
||||||
);
|
);
|
||||||
|
|
||||||
/*catalogRouter.get(
|
/*catalogRouter.get(
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./listProducts";
|
export * from "./listArticles";
|
||||||
|
|||||||
@ -1,33 +1,33 @@
|
|||||||
import Joi from "joi";
|
import Joi from "joi";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ListProductsResult,
|
ListArticlesResult,
|
||||||
ListProductsUseCase,
|
ListArticlesUseCase,
|
||||||
} from "@/contexts/catalog/application";
|
} from "@/contexts/catalog/application";
|
||||||
import { Product } from "@/contexts/catalog/domain";
|
import { Article } from "@/contexts/catalog/domain";
|
||||||
import { QueryCriteriaService } from "@/contexts/common/application/services";
|
import { QueryCriteriaService } from "@/contexts/common/application/services";
|
||||||
import { IServerError } from "@/contexts/common/domain/errors";
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
import {
|
import {
|
||||||
ICollection,
|
ICollection,
|
||||||
IListProducts_Response_DTO,
|
IListArticles_Response_DTO,
|
||||||
IListResponse_DTO,
|
IListResponse_DTO,
|
||||||
IQueryCriteria,
|
IQueryCriteria,
|
||||||
Result,
|
Result,
|
||||||
RuleValidator,
|
RuleValidator,
|
||||||
} from "@shared/contexts";
|
} from "@shared/contexts";
|
||||||
import { ICatalogContext } from "../../..";
|
import { ICatalogContext } from "../../..";
|
||||||
import { IListProductsPresenter } from "./presenter";
|
import { IListArticlesPresenter } from "./presenter";
|
||||||
|
|
||||||
export class ListProductsController extends ExpressController {
|
export class ListArticlesController extends ExpressController {
|
||||||
private useCase: ListProductsUseCase;
|
private useCase: ListArticlesUseCase;
|
||||||
private presenter: IListProductsPresenter;
|
private presenter: IListArticlesPresenter;
|
||||||
private context: ICatalogContext;
|
private context: ICatalogContext;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
props: {
|
props: {
|
||||||
useCase: ListProductsUseCase;
|
useCase: ListArticlesUseCase;
|
||||||
presenter: IListProductsPresenter;
|
presenter: IListArticlesPresenter;
|
||||||
},
|
},
|
||||||
context: ICatalogContext
|
context: ICatalogContext
|
||||||
) {
|
) {
|
||||||
@ -65,7 +65,7 @@ export class ListProductsController extends ExpressController {
|
|||||||
|
|
||||||
console.log(queryCriteria);
|
console.log(queryCriteria);
|
||||||
|
|
||||||
const result: ListProductsResult = await this.useCase.execute({
|
const result: ListArticlesResult = await this.useCase.execute({
|
||||||
queryCriteria,
|
queryCriteria,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,9 +73,9 @@ export class ListProductsController extends ExpressController {
|
|||||||
return this.clientError(result.error.message);
|
return this.clientError(result.error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const customers = <ICollection<Product>>result.object;
|
const customers = <ICollection<Article>>result.object;
|
||||||
|
|
||||||
return this.ok<IListResponse_DTO<IListProducts_Response_DTO>>(
|
return this.ok<IListResponse_DTO<IListArticles_Response_DTO>>(
|
||||||
this.presenter.mapArray(customers, this.context, {
|
this.presenter.mapArray(customers, this.context, {
|
||||||
page: queryCriteria.pagination.offset,
|
page: queryCriteria.pagination.offset,
|
||||||
limit: queryCriteria.pagination.limit,
|
limit: queryCriteria.pagination.limit,
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { ListArticlesUseCase } from "@/contexts/catalog/application";
|
||||||
|
import { ICatalogContext } from "../../..";
|
||||||
|
import { CatalogRepository } from "../../../Catalog.repository";
|
||||||
|
import { createArticleMapper } from "../../../mappers/article.mapper";
|
||||||
|
import { ListArticlesController } from "./ListArticlesController";
|
||||||
|
import { listArticlesPresenter } from "./presenter";
|
||||||
|
|
||||||
|
export const createListArticlesController = (context: ICatalogContext) => {
|
||||||
|
const adapter = context.adapter;
|
||||||
|
const repoManager = context.repositoryManager;
|
||||||
|
|
||||||
|
repoManager.registerRepository(
|
||||||
|
"Article",
|
||||||
|
(params = { transaction: null }) => {
|
||||||
|
const { transaction } = params;
|
||||||
|
|
||||||
|
return new CatalogRepository({
|
||||||
|
transaction,
|
||||||
|
adapter,
|
||||||
|
mapper: createArticleMapper(context),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const listArticlesUseCase = new ListArticlesUseCase(context);
|
||||||
|
|
||||||
|
return new ListArticlesController(
|
||||||
|
{
|
||||||
|
useCase: listArticlesUseCase,
|
||||||
|
presenter: listArticlesPresenter,
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
import { Article } from "@/contexts/catalog/domain";
|
||||||
|
import { ICatalogContext } from "@/contexts/catalog/infrastructure";
|
||||||
|
import {
|
||||||
|
ICollection,
|
||||||
|
IListArticles_Response_DTO,
|
||||||
|
IListResponse_DTO,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
|
||||||
|
export interface IListArticlesPresenter {
|
||||||
|
map: (
|
||||||
|
article: Article,
|
||||||
|
context: ICatalogContext
|
||||||
|
) => IListArticles_Response_DTO;
|
||||||
|
|
||||||
|
mapArray: (
|
||||||
|
articles: ICollection<Article>,
|
||||||
|
context: ICatalogContext,
|
||||||
|
params: {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
) => IListResponse_DTO<IListArticles_Response_DTO>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listArticlesPresenter: IListArticlesPresenter = {
|
||||||
|
map: (
|
||||||
|
article: Article,
|
||||||
|
context: ICatalogContext
|
||||||
|
): IListArticles_Response_DTO => {
|
||||||
|
console.time("listArticlesPresenter.map");
|
||||||
|
|
||||||
|
const result: IListArticles_Response_DTO = {
|
||||||
|
id: article.id.toString(),
|
||||||
|
catalog_name: article.catalog_name.toString(),
|
||||||
|
id_article: article.id_article.toString(),
|
||||||
|
reference: article.reference.toString(),
|
||||||
|
description: article.description.toString(),
|
||||||
|
family: article.family.toString(),
|
||||||
|
subfamily: article.subfamily.toString(),
|
||||||
|
points: article.points.toNumber(),
|
||||||
|
retail_price: article.retail_price.toObject(),
|
||||||
|
};
|
||||||
|
|
||||||
|
console.timeEnd("listArticlesPresenter.map");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
mapArray: (
|
||||||
|
articles: ICollection<Article>,
|
||||||
|
context: ICatalogContext,
|
||||||
|
params: {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
): IListResponse_DTO<IListArticles_Response_DTO> => {
|
||||||
|
console.time("listArticlesPresenter.mapArray");
|
||||||
|
|
||||||
|
const { page, limit } = params;
|
||||||
|
|
||||||
|
const totalCount = articles.totalCount ?? 0;
|
||||||
|
const items = articles.items.map((article: Article) =>
|
||||||
|
listArticlesPresenter.map(article, context)
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
page,
|
||||||
|
per_page: limit,
|
||||||
|
total_pages: Math.ceil(totalCount / limit),
|
||||||
|
total_items: totalCount,
|
||||||
|
items,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.timeEnd("listArticlesPresenter.mapArray");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./ListArticles.presenter";
|
||||||
@ -1,34 +0,0 @@
|
|||||||
import { ListProductsUseCase } from "@/contexts/catalog/application";
|
|
||||||
import { ICatalogContext } from "../../..";
|
|
||||||
import { CatalogRepository } from "../../../Catalog.repository";
|
|
||||||
import { createProductMapper } from "../../../mappers/product.mapper";
|
|
||||||
import { ListProductsController } from "./ListProductsController";
|
|
||||||
import { listProductsPresenter } from "./presenter";
|
|
||||||
|
|
||||||
export const createListProductsController = (context: ICatalogContext) => {
|
|
||||||
const adapter = context.adapter;
|
|
||||||
const repoManager = context.repositoryManager;
|
|
||||||
|
|
||||||
repoManager.registerRepository(
|
|
||||||
"Product",
|
|
||||||
(params = { transaction: null }) => {
|
|
||||||
const { transaction } = params;
|
|
||||||
|
|
||||||
return new CatalogRepository({
|
|
||||||
transaction,
|
|
||||||
adapter,
|
|
||||||
mapper: createProductMapper(context),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const listProductsUseCase = new ListProductsUseCase(context);
|
|
||||||
|
|
||||||
return new ListProductsController(
|
|
||||||
{
|
|
||||||
useCase: listProductsUseCase,
|
|
||||||
presenter: listProductsPresenter,
|
|
||||||
},
|
|
||||||
context
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
import { Product } from "@/contexts/catalog/domain";
|
|
||||||
import { ICatalogContext } from "@/contexts/catalog/infrastructure";
|
|
||||||
import {
|
|
||||||
ICollection,
|
|
||||||
IListProducts_Response_DTO,
|
|
||||||
IListResponse_DTO,
|
|
||||||
} from "@shared/contexts";
|
|
||||||
|
|
||||||
export interface IListProductsPresenter {
|
|
||||||
map: (
|
|
||||||
product: Product,
|
|
||||||
context: ICatalogContext
|
|
||||||
) => IListProducts_Response_DTO;
|
|
||||||
|
|
||||||
mapArray: (
|
|
||||||
products: ICollection<Product>,
|
|
||||||
context: ICatalogContext,
|
|
||||||
params: {
|
|
||||||
page: number;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
) => IListResponse_DTO<IListProducts_Response_DTO>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const listProductsPresenter: IListProductsPresenter = {
|
|
||||||
map: (
|
|
||||||
product: Product,
|
|
||||||
context: ICatalogContext
|
|
||||||
): IListProducts_Response_DTO => {
|
|
||||||
console.time("listProductsPresenter.map");
|
|
||||||
|
|
||||||
const result: IListProducts_Response_DTO = {
|
|
||||||
id: product.id.toString(),
|
|
||||||
reference: product.reference.toString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
console.timeEnd("listProductsPresenter.map");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
mapArray: (
|
|
||||||
products: ICollection<Product>,
|
|
||||||
context: ICatalogContext,
|
|
||||||
params: {
|
|
||||||
page: number;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
): IListResponse_DTO<IListProducts_Response_DTO> => {
|
|
||||||
console.time("listProductsPresenter.mapArray");
|
|
||||||
|
|
||||||
const { page, limit } = params;
|
|
||||||
|
|
||||||
const totalCount = products.totalCount ?? 0;
|
|
||||||
const items = products.items.map((product: Product) =>
|
|
||||||
listProductsPresenter.map(product, context)
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
page,
|
|
||||||
per_page: limit,
|
|
||||||
total_pages: Math.ceil(totalCount / limit),
|
|
||||||
total_items: totalCount,
|
|
||||||
items,
|
|
||||||
};
|
|
||||||
|
|
||||||
console.timeEnd("listProductsPresenter.mapArray");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./ListProducts.presenter";
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { IApplicationService } from "@/contexts/common/application/services/ApplicationService";
|
import { IApplicationService } from "@/contexts/common/application/services/ApplicationService";
|
||||||
import { IRepositoryManager } from "@/contexts/common/domain";
|
import { IRepositoryManager } from "@/contexts/common/domain";
|
||||||
import { IFirebirdAdapter } from "@/contexts/common/infrastructure/firebird";
|
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
|
|
||||||
export interface ICatalogContext {
|
export interface ICatalogContext {
|
||||||
adapter: IFirebirdAdapter;
|
adapter: ISequelizeAdapter;
|
||||||
repositoryManager: IRepositoryManager;
|
repositoryManager: IRepositoryManager;
|
||||||
services: IApplicationService;
|
services: IApplicationService;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
import {
|
||||||
|
ISequelizeMapper,
|
||||||
|
SequelizeMapper,
|
||||||
|
} from "@/contexts/common/infrastructure";
|
||||||
|
import {
|
||||||
|
Description,
|
||||||
|
Quantity,
|
||||||
|
Slug,
|
||||||
|
UniqueID,
|
||||||
|
UnitPrice,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
import { ICatalogContext } from "..";
|
||||||
|
import { Article, IArticleProps } from "../../domain/entities";
|
||||||
|
import {
|
||||||
|
Article_Model,
|
||||||
|
TCreationArticle_Attributes,
|
||||||
|
} from "../sequelize/article.model";
|
||||||
|
|
||||||
|
export interface IArticleMapper
|
||||||
|
extends ISequelizeMapper<
|
||||||
|
Article_Model,
|
||||||
|
TCreationArticle_Attributes,
|
||||||
|
Article
|
||||||
|
> {}
|
||||||
|
|
||||||
|
class ArticleMapper
|
||||||
|
extends SequelizeMapper<Article_Model, TCreationArticle_Attributes, Article>
|
||||||
|
implements IArticleMapper
|
||||||
|
{
|
||||||
|
public constructor(props: { context: ICatalogContext }) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected toDomainMappingImpl(source: Article_Model, params: any): Article {
|
||||||
|
const props: IArticleProps = {
|
||||||
|
catalog_name: this.mapsValue(source, "catalog_name", Slug.create),
|
||||||
|
id_article: this.mapsValue(source, "id_article", Description.create),
|
||||||
|
reference: this.mapsValue(source, "reference", Slug.create),
|
||||||
|
family: this.mapsValue(source, "family", Description.create),
|
||||||
|
subfamily: this.mapsValue(source, "subfamily", Description.create),
|
||||||
|
description: this.mapsValue(source, "description", Description.create),
|
||||||
|
points: this.mapsValue(source, "points", Quantity.create),
|
||||||
|
retail_price: this.mapsValue(source, "retail_price", (value: any) =>
|
||||||
|
UnitPrice.create({ amount: value, precision: 4 })
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const id = this.mapsValue(source, "id", UniqueID.create);
|
||||||
|
const productOrError = Article.create(props, id);
|
||||||
|
|
||||||
|
if (productOrError.isFailure) {
|
||||||
|
throw productOrError.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return productOrError.object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createArticleMapper = (context: ICatalogContext): IArticleMapper =>
|
||||||
|
new ArticleMapper({
|
||||||
|
context,
|
||||||
|
});
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import {
|
|
||||||
FirebirdMapper,
|
|
||||||
IFirebirdMapper,
|
|
||||||
} from "@/contexts/common/infrastructure/mappers/FirebirdMapper";
|
|
||||||
import { Description, MoneyValue, UniqueID } from "@shared/contexts";
|
|
||||||
import { ICatalogContext } from "..";
|
|
||||||
import { IProductProps, Product } from "../../domain/entities";
|
|
||||||
import { Product_Model } from "../firebird";
|
|
||||||
|
|
||||||
export interface IProductMapper
|
|
||||||
extends IFirebirdMapper<Product_Model, Product> {}
|
|
||||||
|
|
||||||
class ProductMapper
|
|
||||||
extends FirebirdMapper<Product_Model, Product>
|
|
||||||
implements IProductMapper
|
|
||||||
{
|
|
||||||
public constructor(props: { context: ICatalogContext }) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected toDomainMappingImpl(source: Product_Model, params: any): Product {
|
|
||||||
const props: IProductProps = {
|
|
||||||
reference: this.mapsValue(source, "reference", Description.create),
|
|
||||||
family: this.mapsValue(source, "family", Description.create),
|
|
||||||
subfamily: this.mapsValue(source, "subfamily", Description.create),
|
|
||||||
description: this.mapsValue(source, "description", Description.create),
|
|
||||||
points: this.mapsValue(source, "points", Description.create),
|
|
||||||
pvp: this.mapsValue(source, "pvp", (value: any) =>
|
|
||||||
MoneyValue.create({ amount: value })
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
const id = this.mapsValue(source, "id", UniqueID.create);
|
|
||||||
const productOrError = Product.create(props, id);
|
|
||||||
|
|
||||||
if (productOrError.isFailure) {
|
|
||||||
throw productOrError.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return productOrError.object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createProductMapper = (context: ICatalogContext): IProductMapper =>
|
|
||||||
new ProductMapper({
|
|
||||||
context,
|
|
||||||
});
|
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
CreationOptional,
|
||||||
|
DataTypes,
|
||||||
|
InferAttributes,
|
||||||
|
InferCreationAttributes,
|
||||||
|
Model,
|
||||||
|
Sequelize,
|
||||||
|
} from "sequelize";
|
||||||
|
|
||||||
|
export type TCreationArticle_Attributes =
|
||||||
|
InferCreationAttributes<Article_Model>;
|
||||||
|
|
||||||
|
export class Article_Model extends Model<
|
||||||
|
InferAttributes<Article_Model>,
|
||||||
|
InferCreationAttributes<Article_Model>
|
||||||
|
> {
|
||||||
|
// To avoid table creation
|
||||||
|
/*static async sync(): Promise<any> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static associate(connection: Sequelize) {}
|
||||||
|
|
||||||
|
declare id: string;
|
||||||
|
|
||||||
|
declare catalog_name: string;
|
||||||
|
declare id_article: string; // number ??
|
||||||
|
declare reference: CreationOptional<string>;
|
||||||
|
declare family: CreationOptional<string>;
|
||||||
|
declare subfamily: CreationOptional<string>;
|
||||||
|
declare description: CreationOptional<string>;
|
||||||
|
declare points: CreationOptional<number>;
|
||||||
|
declare retail_price: CreationOptional<number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (sequelize: Sequelize) => {
|
||||||
|
Article_Model.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: new DataTypes.UUID(),
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
catalog_name: DataTypes.STRING(),
|
||||||
|
id_article: DataTypes.STRING(),
|
||||||
|
reference: DataTypes.STRING(),
|
||||||
|
family: DataTypes.STRING(),
|
||||||
|
subfamily: DataTypes.STRING(),
|
||||||
|
description: DataTypes.STRING(),
|
||||||
|
points: DataTypes.SMALLINT().UNSIGNED,
|
||||||
|
retail_price: DataTypes.BIGINT(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
tableName: "catalog",
|
||||||
|
|
||||||
|
//paranoid: true, // softs deletes
|
||||||
|
timestamps: true,
|
||||||
|
//version: true,
|
||||||
|
|
||||||
|
createdAt: "created_at",
|
||||||
|
updatedAt: "updated_at",
|
||||||
|
deletedAt: "deleted_at",
|
||||||
|
|
||||||
|
indexes: [
|
||||||
|
{ name: "catalog_name_idx", fields: ["catalog_name"] },
|
||||||
|
{ name: "id_article_idx", fields: ["id_article"] },
|
||||||
|
{ name: "family_idx", fields: ["family"] },
|
||||||
|
{ name: "family_subfamily_idx", fields: ["family", "subfamily"] },
|
||||||
|
{ name: "updated_at_idx", fields: ["updated_at"] },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Article_Model;
|
||||||
|
};
|
||||||
@ -15,7 +15,7 @@ export interface IDTOMapper<S, D> {
|
|||||||
params: {
|
params: {
|
||||||
page: number;
|
page: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
},
|
}
|
||||||
) => IListResponse_DTO<D>;
|
) => IListResponse_DTO<D>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { FirebirdModel } from "@/contexts/catalog/infrastructure/firebird/firebird.model";
|
|
||||||
import { Collection, Entity, Result } from "@shared/contexts";
|
import { Collection, Entity, Result } from "@shared/contexts";
|
||||||
import { ValidationError } from "sequelize";
|
import { ValidationError } from "sequelize";
|
||||||
import {
|
import {
|
||||||
@ -6,6 +5,7 @@ import {
|
|||||||
RequiredFieldMissingError,
|
RequiredFieldMissingError,
|
||||||
} from "../../domain/errors";
|
} from "../../domain/errors";
|
||||||
import { InfrastructureError } from "../InfrastructureError";
|
import { InfrastructureError } from "../InfrastructureError";
|
||||||
|
import { FirebirdModel } from "../firebird/firebird.model";
|
||||||
|
|
||||||
export interface IFirebirdMapper<
|
export interface IFirebirdMapper<
|
||||||
TModel extends FirebirdModel,
|
TModel extends FirebirdModel,
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { ISequelizeQueryBuilder } from "./queryBuilder/SequelizeQueryBuilder";
|
|||||||
|
|
||||||
export interface ISequelizeAdapter extends IAdapter {
|
export interface ISequelizeAdapter extends IAdapter {
|
||||||
queryBuilder: ISequelizeQueryBuilder;
|
queryBuilder: ISequelizeQueryBuilder;
|
||||||
|
startTransaction: () => SequelizeBusinessTransactionType;
|
||||||
getModel: (modelName: string) => any;
|
getModel: (modelName: string) => any;
|
||||||
hasModel: (modelName: string) => boolean;
|
hasModel: (modelName: string) => boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import http from "http";
|
|||||||
import { assign } from "lodash";
|
import { assign } from "lodash";
|
||||||
import { DateTime, Settings } from "luxon";
|
import { DateTime, Settings } from "luxon";
|
||||||
|
|
||||||
import { createFirebirdAdapter } from "@/contexts/common/infrastructure/firebird";
|
|
||||||
import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { trace } from "console";
|
import { trace } from "console";
|
||||||
import { config } from "../../config";
|
import { config } from "../../config";
|
||||||
@ -92,13 +91,13 @@ const serverConnection = (conn: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sequelizeConn = createSequelizeAdapter();
|
const sequelizeConn = createSequelizeAdapter();
|
||||||
const firebirdConn = createFirebirdAdapter();
|
//const firebirdConn = createFirebirdAdapter();
|
||||||
|
|
||||||
const server: http.Server = http
|
const server: http.Server = http
|
||||||
.createServer(app)
|
.createServer(app)
|
||||||
.once("listening", () =>
|
.once("listening", () =>
|
||||||
process.on("SIGINT", () => {
|
process.on("SIGINT", () => {
|
||||||
firebirdConn.disconnect();
|
//firebirdConn.disconnect();
|
||||||
serverStop(server);
|
serverStop(server);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -111,32 +110,32 @@ const server: http.Server = http
|
|||||||
.on("error", serverError);
|
.on("error", serverError);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
firebirdConn.sync().then(() => {
|
//firebirdConn.sync().then(() => {
|
||||||
sequelizeConn.sync({ force: false, alter: true }).then(() => {
|
sequelizeConn.sync({ force: false, alter: true }).then(() => {
|
||||||
// Launch server
|
// Launch server
|
||||||
server.listen(currentState.server.port, () => {
|
server.listen(currentState.server.port, () => {
|
||||||
const now = DateTime.now();
|
const now = DateTime.now();
|
||||||
logger.info(
|
logger.info(
|
||||||
`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`
|
`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`
|
||||||
);
|
);
|
||||||
logger.info(
|
logger.info(
|
||||||
`Launched in: ${now.diff(currentState.launchedAt).toMillis()} ms`
|
`Launched in: ${now.diff(currentState.launchedAt).toMillis()} ms`
|
||||||
);
|
);
|
||||||
logger.info(`Environment: ${currentState.environment}`);
|
logger.info(`Environment: ${currentState.environment}`);
|
||||||
logger.info(`Process PID: ${process.pid}`);
|
logger.info(`Process PID: ${process.pid}`);
|
||||||
logger.info("To shut down your server, press <CTRL> + C at any time");
|
logger.info("To shut down your server, press <CTRL> + C at any time");
|
||||||
logger.info(
|
logger.info(
|
||||||
`⚡️ Server: http://${currentState.server.hostname}:${currentState.server.port}`
|
`⚡️ Server: http://${currentState.server.hostname}:${currentState.server.port}`
|
||||||
);
|
);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
//});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
serverError(error);
|
serverError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on("uncaughtException", (error: any) => {
|
process.on("uncaughtException", (error: any) => {
|
||||||
firebirdConn.disconnect();
|
//firebirdConn.disconnect();
|
||||||
logger.error(`${new Date().toUTCString()} uncaughtException:`, error.message);
|
logger.error(`${new Date().toUTCString()} uncaughtException:`, error.message);
|
||||||
logger.error(error.stack);
|
logger.error(error.stack);
|
||||||
//process.exit(1);
|
//process.exit(1);
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { IMoney_Response_DTO } from "../../../../common";
|
import { IMoney_Response_DTO } from "../../../../common";
|
||||||
|
|
||||||
export interface IListProducts_Response_DTO {
|
export interface IListArticles_Response_DTO {
|
||||||
id: string;
|
id: string;
|
||||||
|
catalog_name: string;
|
||||||
|
id_article: string;
|
||||||
reference: string;
|
reference: string;
|
||||||
family: string;
|
family: string;
|
||||||
subfamily: string;
|
subfamily: string;
|
||||||
description: string;
|
description: string;
|
||||||
points: number;
|
points: number;
|
||||||
pvp: IMoney_Response_DTO;
|
retail_price: IMoney_Response_DTO;
|
||||||
}
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./IListArticles_Response.dto";
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./IListProducts_Response.dto";
|
|
||||||
@ -1 +1 @@
|
|||||||
export * from "./IListProducts.dto";
|
export * from "./IListArticles.dto";
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class AddressTitle extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class AddressType extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,8 @@ export class City extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class Country extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,8 @@ export class PostalCode extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class Province extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class Street extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,8 @@ export class Email extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,8 @@ export class Name extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,8 @@ export class Note extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@ export class Phone extends StringValueObject {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,8 @@ export class Filter extends ValueObject<IFilterProps> implements IFilter {
|
|||||||
return Result.ok<Filter>(
|
return Result.ok<Filter>(
|
||||||
new Filter({
|
new Filter({
|
||||||
...filterProps,
|
...filterProps,
|
||||||
operator: this.sanitizeOperator(filterProps.operator),
|
operator: Filter.sanitizeOperator(filterProps.operator),
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,9 +26,9 @@ export class Order extends ValueObject<IOrderProps> implements IOrder {
|
|||||||
|
|
||||||
return Result.ok<Order>(
|
return Result.ok<Order>(
|
||||||
new Order({
|
new Order({
|
||||||
field: this.sanitize(orderProps.field),
|
field: Order.sanitize(orderProps.field),
|
||||||
type: this.sanitize(orderProps.type),
|
type: Order.sanitize(orderProps.type),
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export class Order extends ValueObject<IOrderProps> implements IOrder {
|
|||||||
) {
|
) {
|
||||||
let typeOrError = RuleValidator.validate(
|
let typeOrError = RuleValidator.validate(
|
||||||
RuleValidator.RULE_IS_TYPE_STRING,
|
RuleValidator.RULE_IS_TYPE_STRING,
|
||||||
type,
|
type
|
||||||
);
|
);
|
||||||
|
|
||||||
if (typeOrError.isFailure) {
|
if (typeOrError.isFailure) {
|
||||||
@ -63,7 +63,7 @@ export class Order extends ValueObject<IOrderProps> implements IOrder {
|
|||||||
) {
|
) {
|
||||||
const fieldOrError = RuleValidator.validate(
|
const fieldOrError = RuleValidator.validate(
|
||||||
RuleValidator.RULE_IS_TYPE_STRING,
|
RuleValidator.RULE_IS_TYPE_STRING,
|
||||||
field,
|
field
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fieldOrError.isFailure) {
|
if (fieldOrError.isFailure) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Result, ValueObject } from "@shared/contexts";
|
|
||||||
import { DomainError } from "../../../errors";
|
import { DomainError } from "../../../errors";
|
||||||
|
import { Result } from "../../Result";
|
||||||
|
import { ValueObject } from "../../ValueObject";
|
||||||
import { Order } from "./Order";
|
import { Order } from "./Order";
|
||||||
import { OrderCollection } from "./OrderCollection";
|
import { OrderCollection } from "./OrderCollection";
|
||||||
|
|
||||||
@ -43,16 +44,14 @@ export class OrderRoot
|
|||||||
|
|
||||||
return Result.ok<IOrderRoot>(
|
return Result.ok<IOrderRoot>(
|
||||||
new OrderRoot({
|
new OrderRoot({
|
||||||
type: this.sanitizeOperator(orderRootProps.type),
|
type: OrderRoot.sanitizeOperator(orderRootProps.type),
|
||||||
items: OrderCollection.create(orderRootProps.value),
|
items: OrderCollection.create(orderRootProps.value),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static validate(OrderRootRoot: IOrderRootProps): Result<any> {
|
protected static validate(OrderRootRoot: IOrderRootProps): Result<any> {
|
||||||
throw DomainError.create("NOT IMPLEMENT", {
|
throw DomainError.create("NOT IMPLEMENT", "OrderRoot.validate()");
|
||||||
function: "OrderRoot.validate()",
|
|
||||||
});
|
|
||||||
|
|
||||||
/*return Validator.isOneOf(
|
/*return Validator.isOneOf(
|
||||||
{
|
{
|
||||||
@ -85,7 +84,7 @@ export class OrderRoot
|
|||||||
}
|
}
|
||||||
|
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
return `${this.type} ${this.value.toString()}`;
|
return `${this.type} ${this.items.toString()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toObject(): Record<string, any> {
|
public toObject(): Record<string, any> {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export class Slug extends StringValueObject {
|
|||||||
|
|
||||||
protected static validate(
|
protected static validate(
|
||||||
value: UndefinedOr<string>,
|
value: UndefinedOr<string>,
|
||||||
options: IStringValueObjectOptions,
|
options: IStringValueObjectOptions
|
||||||
) {
|
) {
|
||||||
const rule = Joi.string()
|
const rule = Joi.string()
|
||||||
.allow(null)
|
.allow(null)
|
||||||
@ -68,7 +68,7 @@ export class Slug extends StringValueObject {
|
|||||||
|
|
||||||
public static create(
|
public static create(
|
||||||
value: UndefinedOr<string>,
|
value: UndefinedOr<string>,
|
||||||
options: IStringValueObjectOptions = {},
|
options: IStringValueObjectOptions = {}
|
||||||
) {
|
) {
|
||||||
const _options = {
|
const _options = {
|
||||||
label: "slug",
|
label: "slug",
|
||||||
@ -81,7 +81,8 @@ export class Slug extends StringValueObject {
|
|||||||
return Result.fail(validationResult.error);
|
return Result.fail(validationResult.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok<Slug>(new Slug(this.sanitize(validationResult.object)));
|
const slugValue = Slug.sanitize(validationResult.object);
|
||||||
|
return Result.ok<Slug>(new Slug(slugValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,8 @@ export class UniqueID extends NullableValueObject<string> {
|
|||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(
|
||||||
DomainError.INVALID_INPUT_DATA,
|
DomainError.INVALID_INPUT_DATA,
|
||||||
validationResult.error
|
validationResult.error.message,
|
||||||
|
_options
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export function handleDomainError2(
|
|||||||
|
|
||||||
export function handleDomainError(
|
export function handleDomainError(
|
||||||
code: string,
|
code: string,
|
||||||
message?: string,
|
message: string = "",
|
||||||
payload?: Record<string, any>
|
payload?: Record<string, any>
|
||||||
): DomainError {
|
): DomainError {
|
||||||
return DomainError.create(code, message, payload);
|
return DomainError.create(code, message, payload);
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
export * from "./contexts";
|
export * from "./contexts";
|
||||||
|
export * from "./utilities";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user