From a32ba80bb6039c79b88d844c6e21393519c97925 Mon Sep 17 00:00:00 2001 From: David Arranz Date: Wed, 3 Jul 2024 12:27:58 +0200 Subject: [PATCH] . --- .../express/passport/authMiddleware.ts | 2 + .../common/infrastructure/ContextFactory.ts | 42 +++++++-- .../Dealer/CreateDealer.useCase.ts | 2 +- .../Dealer/UpdateDealer.useCase.ts | 2 +- .../application/Quote/CreateQuote.useCase.ts | 39 ++++++-- .../application/Quote/ListQuotes.useCase.ts | 24 +++-- .../application/Quote/UpdateQuote.useCase.ts | 2 +- .../sales/domain/entities/Quotes/Quote.ts | 2 +- .../contexts/sales/domain/entities/index.ts | 2 +- .../sales/infrastructure/Sales.context.ts | 33 +------ .../express/middlewares/dealerMiddleware.ts | 35 +++++++- .../infrastructure/mappers/dealer.mapper.ts | 39 ++++---- .../infrastructure/sequelize/dealer.model.ts | 34 ++++--- .../infrastructure/sequelize/quote.model.ts | 2 +- .../express/api/context.middleware.ts | 8 +- .../express/api/routes/quote.routes.ts | 5 +- .../QueryCriteria/Filters/FilterCriteria.ts | 89 ++++++++++--------- .../GetDealer.dto/IGetDealer_Response.dto.ts | 1 + 18 files changed, 225 insertions(+), 138 deletions(-) diff --git a/server/src/contexts/auth/infrastructure/express/passport/authMiddleware.ts b/server/src/contexts/auth/infrastructure/express/passport/authMiddleware.ts index af82e61..39de7c9 100644 --- a/server/src/contexts/auth/infrastructure/express/passport/authMiddleware.ts +++ b/server/src/contexts/auth/infrastructure/express/passport/authMiddleware.ts @@ -10,6 +10,7 @@ export const checkUser = composeMiddleware([ session: false, }), (req: Express.Request, res: Express.Response, next: Express.NextFunction) => { + const user = req.user; if (req.isAuthenticated()) { return next(); } @@ -33,6 +34,7 @@ export const checkAdminOrSelf = composeMiddleware([ checkUser, (req: Express.Request, res: Express.Response, next: Express.NextFunction) => { const user = req.user; + const { userId } = req.params; if (user.isAdmin) { diff --git a/server/src/contexts/common/infrastructure/ContextFactory.ts b/server/src/contexts/common/infrastructure/ContextFactory.ts index 0830b61..09e04c0 100644 --- a/server/src/contexts/common/infrastructure/ContextFactory.ts +++ b/server/src/contexts/common/infrastructure/ContextFactory.ts @@ -1,26 +1,52 @@ import { IRepositoryManager, RepositoryManager } from "../domain"; import { ISequelizeAdapter, createSequelizeAdapter } from "./sequelize"; +export interface IContext { + adapter: ISequelizeAdapter; + repositoryManager: IRepositoryManager; +} + +export class ContextFactory { + private static instance: ContextFactory | null = null; + + public static getInstance(): IContext { + if (!ContextFactory.instance) { + ContextFactory.instance = new ContextFactory({ + adapter: createSequelizeAdapter(), + repositoryManager: RepositoryManager.getInstance(), + }); + } + + return ContextFactory.instance.context; + } + + private context: IContext; + + private constructor(context: IContext) { + this.context = context; + } +} + // ContextFactory.ts -export interface IContext { +/*export interface IContext { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager; services: T; } -export class ContextFactory { +export class ContextFactory { private static instances: Map> = new Map(); - public static getInstance(constructor: new () => T): ContextFactory { + public static getInstance(constructor: new () => T): ContextFactory { const key = constructor.name; if (!ContextFactory.instances.has(key)) { - ContextFactory.instances.set(key, new ContextFactory(constructor)); + ContextFactory.instances.set(key, new ContextFactory(constructor)); } - return ContextFactory.instances.get(key)! as ContextFactory; + return ContextFactory.instances.get(key)! as ContextFactory; } - private context: IContext; + private context: IContext; private constructor(constructor: new () => T) { this.context = { @@ -30,7 +56,7 @@ export class ContextFactory { }; } - public getContext(): IContext { + public getContext(): IContext { return this.context; } -} +}*/ diff --git a/server/src/contexts/sales/application/Dealer/CreateDealer.useCase.ts b/server/src/contexts/sales/application/Dealer/CreateDealer.useCase.ts index 7a21347..cd4d0d6 100644 --- a/server/src/contexts/sales/application/Dealer/CreateDealer.useCase.ts +++ b/server/src/contexts/sales/application/Dealer/CreateDealer.useCase.ts @@ -73,7 +73,7 @@ export class CreateDealerUseCase switch (domainError.code) { case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = "El usuario tiene algún dato erróneo."; + message = "El distribuidor tiene algún dato erróneo."; break; default: diff --git a/server/src/contexts/sales/application/Dealer/UpdateDealer.useCase.ts b/server/src/contexts/sales/application/Dealer/UpdateDealer.useCase.ts index 601d315..a93f784 100644 --- a/server/src/contexts/sales/application/Dealer/UpdateDealer.useCase.ts +++ b/server/src/contexts/sales/application/Dealer/UpdateDealer.useCase.ts @@ -66,7 +66,7 @@ export class UpdateDealerUseCase // Errores manuales case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = "El usuario tiene algún dato erróneo."; + message = "El distribuidor tiene algún dato erróneo."; break; default: diff --git a/server/src/contexts/sales/application/Quote/CreateQuote.useCase.ts b/server/src/contexts/sales/application/Quote/CreateQuote.useCase.ts index 2949b54..67e01de 100644 --- a/server/src/contexts/sales/application/Quote/CreateQuote.useCase.ts +++ b/server/src/contexts/sales/application/Quote/CreateQuote.useCase.ts @@ -18,7 +18,16 @@ import { UnitPrice, ensureIdIsValid, } from "@shared/contexts"; -import { IQuoteRepository, Quote, QuoteCustomer, QuoteItem, QuoteStatus } from "../../domain"; +import { + Dealer, + IQuoteRepository, + Quote, + QuoteCustomer, + QuoteItem, + QuoteReference, + QuoteStatus, +} from "../../domain"; +import { ISalesContext } from "../../infrastructure"; export type CreateQuoteResponseOrError = | Result // Misc errors (value objects) @@ -29,16 +38,25 @@ export class CreateQuoteUseCase { private _adapter: ISequelizeAdapter; private _repositoryManager: IRepositoryManager; + private _dealer?: Dealer; - constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) { - this._adapter = props.adapter; - this._repositoryManager = props.repositoryManager; + constructor(context: ISalesContext) { + this._adapter = context.adapter; + this._repositoryManager = context.repositoryManager; + this._dealer = context.dealer; } async execute(request: ICreateQuote_Request_DTO) { const { id } = request; // Validaciones de datos + if (!this._dealer) { + const message = "Error. Missing Dealer"; + return Result.fail(UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message)); + } + + const dealerId = this._dealer.id; + const idOrError = ensureIdIsValid(id); if (idOrError.isFailure) { const message = idOrError.error.message; //`Quote ID ${quoteDTO.id} is not valid`; @@ -47,7 +65,7 @@ export class CreateQuoteUseCase ); } - // Comprobar que no existe un usuario previo con esos datos + // Comprobar que no existe un quote previo con esos datos const quoteRepository = this._getQuoteRepository(); const idExists = await quoteRepository().exists(idOrError.object); @@ -61,7 +79,7 @@ export class CreateQuoteUseCase } // Crear quote - const quoteOrError = this._tryCreateQuoteInstance(request, idOrError.object); + const quoteOrError = this._tryCreateQuoteInstance(request, idOrError.object, dealerId); if (quoteOrError.isFailure) { const { error: domainError } = quoteOrError; @@ -71,7 +89,7 @@ export class CreateQuoteUseCase switch (domainError.code) { case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = "El usuario tiene algún dato erróneo."; + message = "El presupuesto tiene algún dato erróneo."; break; default: @@ -107,7 +125,8 @@ export class CreateQuoteUseCase private _tryCreateQuoteInstance( quoteDTO: ICreateQuote_Request_DTO, - quoteId: UniqueID + quoteId: UniqueID, + dealerId: UniqueID ): Result { const statusOrError = QuoteStatus.create(quoteDTO.status); if (statusOrError.isFailure) { @@ -119,7 +138,7 @@ export class CreateQuoteUseCase return Result.fail(dateOrError.error); } - const referenceOrError = QuoteStatus.create(quoteDTO.reference); + const referenceOrError = QuoteReference.create(quoteDTO.reference); if (referenceOrError.isFailure) { return Result.fail(referenceOrError.error); } @@ -182,6 +201,8 @@ export class CreateQuoteUseCase validity: validityOrError.object, items, + + dealerId, }, quoteId ); diff --git a/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts b/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts index b7fe7fa..e8fe123 100644 --- a/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts +++ b/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts @@ -1,11 +1,12 @@ import { IUseCase, IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases"; import { IRepositoryManager } from "@/contexts/common/domain"; -import { Collection, ICollection, IQueryCriteria, Result } from "@shared/contexts"; +import { Collection, Filter, ICollection, IQueryCriteria, Result } from "@shared/contexts"; import { IInfrastructureError } from "@/contexts/common/infrastructure"; import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; -import { Quote } from "../../domain"; +import { Dealer, Quote } from "../../domain"; import { IQuoteRepository } from "../../domain/repository"; +import { ISalesContext } from "../../infrastructure"; export interface IListQuotesParams { queryCriteria: IQueryCriteria; @@ -18,15 +19,28 @@ export type ListQuotesResult = export class ListQuotesUseCase implements IUseCase> { private _adapter: ISequelizeAdapter; private _repositoryManager: IRepositoryManager; + private _dealer?: Dealer; - constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) { - this._adapter = props.adapter; - this._repositoryManager = props.repositoryManager; + constructor(context: ISalesContext) { + this._adapter = context.adapter; + this._repositoryManager = context.repositoryManager; + this._dealer = context.dealer; } async execute(params: Partial): Promise { const { queryCriteria } = params; + if (this._dealer) { + queryCriteria?.filters.add( + Filter.create({ + operator: "eq", + field: "dealer_id", + value: this._dealer.id, + }).object, + "AND" + ); + } + return this.findQuotes(queryCriteria); } diff --git a/server/src/contexts/sales/application/Quote/UpdateQuote.useCase.ts b/server/src/contexts/sales/application/Quote/UpdateQuote.useCase.ts index 7978c7f..c06d5ea 100644 --- a/server/src/contexts/sales/application/Quote/UpdateQuote.useCase.ts +++ b/server/src/contexts/sales/application/Quote/UpdateQuote.useCase.ts @@ -72,7 +72,7 @@ export class UpdateQuoteUseCase // Errores manuales case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = "El usuario tiene algún dato erróneo."; + message = "El presupuesto tiene algún dato erróneo."; break; default: diff --git a/server/src/contexts/sales/domain/entities/Quotes/Quote.ts b/server/src/contexts/sales/domain/entities/Quotes/Quote.ts index 7ca6d51..99c2a91 100644 --- a/server/src/contexts/sales/domain/entities/Quotes/Quote.ts +++ b/server/src/contexts/sales/domain/entities/Quotes/Quote.ts @@ -111,6 +111,6 @@ export class Quote extends AggregateRoot implements IQuote { } get dealerId() { - return this.dealerId; + return this.props.dealerId; } } diff --git a/server/src/contexts/sales/domain/entities/index.ts b/server/src/contexts/sales/domain/entities/index.ts index 5b5cfef..9033586 100644 --- a/server/src/contexts/sales/domain/entities/index.ts +++ b/server/src/contexts/sales/domain/entities/index.ts @@ -1,2 +1,2 @@ -export * from "./Dealer/Dealer"; +export * from "./Dealer"; export * from "./Quotes"; diff --git a/server/src/contexts/sales/infrastructure/Sales.context.ts b/server/src/contexts/sales/infrastructure/Sales.context.ts index b013360..dd63cea 100644 --- a/server/src/contexts/sales/infrastructure/Sales.context.ts +++ b/server/src/contexts/sales/infrastructure/Sales.context.ts @@ -1,32 +1,7 @@ -import { IRepositoryManager, RepositoryManager } from "@/contexts/common/domain"; -import { - ISequelizeAdapter, - createSequelizeAdapter, -} from "@/contexts/common/infrastructure/sequelize"; +import { IContext } from "@/contexts/common/infrastructure"; +import { Dealer } from "../domain"; -export interface ISalesContext { - adapter: ISequelizeAdapter; - repositoryManager: IRepositoryManager; +export interface ISalesContext extends IContext { //services: IApplicationService; -} - -export class SalesContext { - private static instance: SalesContext | null = null; - - public static getInstance(): ISalesContext { - if (!SalesContext.instance) { - SalesContext.instance = new SalesContext({ - adapter: createSequelizeAdapter(), - repositoryManager: RepositoryManager.getInstance(), - }); - } - - return SalesContext.instance.context; - } - - private context: ISalesContext; - - private constructor(context: ISalesContext) { - this.context = context; - } + dealer?: Dealer; } diff --git a/server/src/contexts/sales/infrastructure/express/middlewares/dealerMiddleware.ts b/server/src/contexts/sales/infrastructure/express/middlewares/dealerMiddleware.ts index 4e6e572..775a1c1 100644 --- a/server/src/contexts/sales/infrastructure/express/middlewares/dealerMiddleware.ts +++ b/server/src/contexts/sales/infrastructure/express/middlewares/dealerMiddleware.ts @@ -1,3 +1,34 @@ -import { getDealerByUserController } from "../controllers/dealers/getDealerByUser"; +import { AuthUser } from "@/contexts/auth/domain"; +import { GetDealerByUserUseCase } from "@/contexts/sales/application"; +import Express from "express"; +import { registerDealerRepository } from "../../Dealer.repository"; +import { ISalesContext } from "../../Sales.context"; -export const getDealerMiddleware = getDealerByUserController; +export const getDealerMiddleware = async ( + req: Express.Request, + res: Express.Response, + next: Express.NextFunction +) => { + const user = req.user; + const context: ISalesContext = res.locals.context; + + registerDealerRepository(context); + + try { + const dealerOrError = await new GetDealerByUserUseCase(context).execute({ + userId: user.id, + }); + + if (dealerOrError.isFailure) { + return res.status(500).json().send(); + //return this._handleExecuteError(result.error); + } + + context.dealer = dealerOrError.object; + + return next(); + } catch (e: unknown) { + //return this.fail(e as IServerError); + return res.status(500).json().send(); + } +}; diff --git a/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts b/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts index a8d0ca4..864ed3e 100644 --- a/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts +++ b/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts @@ -20,29 +20,36 @@ class DealerMapper } protected toDomainMappingImpl(source: Dealer_Model, params: any): Dealer { + const name = this.mapsValue(source, "name", Name.create); + const user_id = this.mapsValue(source, "user_id", UniqueID.create); + const status = this.mapsValue(source, "status", DealerStatus.create); + const language = this.mapsValue(source, "lang_code", Language.createFromCode); + + const additionalInfoOrError = KeyValueMap.create([ + ["contact_information", source.contact_information], + ["default_payment_method", source.default_payment_method], + ["default_notes", source.default_notes], + ["default_legal_terms", source.default_legal_terms], + ["default_quote_validity", source.default_quote_validity], + ]); + const props: IDealerProps = { - user_id: this.mapsValue(source, "user_id", UniqueID.create), + user_id, logo: "", - name: this.mapsValue(source, "name", Name.create), - status: this.mapsValue(source, "status", DealerStatus.create), - language: this.mapsValue(source, "language", Language.createFromCode), - additionalInfo: KeyValueMap.create([ - ["contact_information", source.contact_information], - ["default_payment_method", source.default_payment_method], - ["default_notes", source.default_notes], - ["default_legal_terms", source.default_legal_terms], - ["default_quote_validity", source.default_quote_validity], - ]).object, + name, + status, + language, + additionalInfo: additionalInfoOrError.object, }; const id = this.mapsValue(source, "id", UniqueID.create); - const userOrError = Dealer.create(props, id); + const dealerOrError = Dealer.create(props, id); - if (userOrError.isFailure) { - throw userOrError.error; + if (dealerOrError.isFailure) { + throw dealerOrError.error; } - return userOrError.object; + return dealerOrError.object; } protected toPersistenceMappingImpl(source: Dealer, params?: MapperParamsType | undefined) { @@ -53,7 +60,7 @@ class DealerMapper logo: "", name: source.name.toPrimitive(), status: source.status.toPrimitive(), - language: source.language.toPrimitive(), + lang_code: source.language.toPrimitive(), contact_information: source.additionalInfo.get("contact_information")?.toString() ?? "", default_payment_method: source.additionalInfo.get("default_payment_method")?.toString() ?? "", default_notes: source.additionalInfo.get("default_notes")?.toString() ?? "", diff --git a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts index f974e30..f8a7bcf 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts @@ -1,5 +1,6 @@ -import { UserCreationAttributes, User_Model } from "@/contexts/users"; +import { User_Model } from "@/contexts/users"; import { + CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, @@ -8,14 +9,14 @@ import { Op, Sequelize, } from "sequelize"; -import { QuoteCreationAttributes, Quote_Model } from "./quote.model"; +import { Quote_Model } from "./quote.model"; export type DealerCreationAttributes = InferCreationAttributes< Dealer_Model, { omit: "user" | "quotes" } > & { - user: UserCreationAttributes; - quotes: QuoteCreationAttributes[]; + user_id: string; + //quotes?: QuoteCreationAttributes[]; }; export class Dealer_Model extends Model< @@ -45,15 +46,15 @@ export class Dealer_Model extends Model< } declare id: string; - declare contact_id?: string; // number ?? - declare name: string; - declare contact_information: string; - declare default_payment_method: string; - declare default_notes: string; - declare default_legal_terms: string; - declare default_quote_validity: string; - declare status: string; - declare language: string; + declare contact_id?: CreationOptional; + declare name: CreationOptional; + declare contact_information: CreationOptional; + declare default_payment_method: CreationOptional; + declare default_notes: CreationOptional; + declare default_legal_terms: CreationOptional; + declare default_quote_validity: CreationOptional; + declare status: CreationOptional; + declare lang_code: CreationOptional; declare user: NonAttribute; declare quotes: NonAttribute; @@ -82,7 +83,12 @@ export default (sequelize: Sequelize) => { default_notes: DataTypes.TEXT, default_legal_terms: DataTypes.TEXT, default_quote_validity: DataTypes.TEXT, - language: DataTypes.STRING, + + lang_code: { + type: DataTypes.STRING(2), + allowNull: false, + defaultValue: "es", + }, status: { type: DataTypes.STRING, diff --git a/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts b/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts index 2a55d36..ad48b04 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts @@ -33,8 +33,8 @@ export class Quote_Model extends Model< }); Quote_Model.belongsTo(Dealer_Model, { - as: "dealer", foreignKey: "dealer_id", + as: "dealer", onDelete: "RESTRICT", }); } diff --git a/server/src/infrastructure/express/api/context.middleware.ts b/server/src/infrastructure/express/api/context.middleware.ts index 0eacbb6..9573ba0 100644 --- a/server/src/infrastructure/express/api/context.middleware.ts +++ b/server/src/infrastructure/express/api/context.middleware.ts @@ -1,7 +1,3 @@ -import { RepositoryManager } from "@/contexts/common/domain"; -import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; +import { ContextFactory } from "@/contexts/common/infrastructure"; -export const createContextMiddleware = () => ({ - adapter: createSequelizeAdapter(), - repositoryManager: RepositoryManager.getInstance(), -}); +export const createContextMiddleware = () => ContextFactory.getInstance(); diff --git a/server/src/infrastructure/express/api/routes/quote.routes.ts b/server/src/infrastructure/express/api/routes/quote.routes.ts index bc72aab..b02bf55 100644 --- a/server/src/infrastructure/express/api/routes/quote.routes.ts +++ b/server/src/infrastructure/express/api/routes/quote.routes.ts @@ -3,13 +3,14 @@ import { createQuoteController, listQuotesController, } from "@/contexts/sales/infrastructure/express/controllers"; +import { getDealerMiddleware } from "@/contexts/sales/infrastructure/express/middlewares/dealerMiddleware"; import Express from "express"; export const QuoteRouter = (appRouter: Express.Router) => { const quoteRoutes: Express.Router = Express.Router({ mergeParams: true }); - quoteRoutes.get("/", checkUser, listQuotesController); - quoteRoutes.post("/", checkUser, createQuoteController); + quoteRoutes.get("/", checkUser, getDealerMiddleware, listQuotesController); + quoteRoutes.post("/", checkUser, getDealerMiddleware, createQuoteController); //quoteRoutes.put("/:quoteId", checkUser, updateQuoteController); diff --git a/shared/lib/contexts/common/domain/entities/QueryCriteria/Filters/FilterCriteria.ts b/shared/lib/contexts/common/domain/entities/QueryCriteria/Filters/FilterCriteria.ts index e58ac33..47c6e95 100644 --- a/shared/lib/contexts/common/domain/entities/QueryCriteria/Filters/FilterCriteria.ts +++ b/shared/lib/contexts/common/domain/entities/QueryCriteria/Filters/FilterCriteria.ts @@ -12,11 +12,17 @@ export interface IFilterCriteria { toObject(): Record; } -export class FilterCriteria - extends StringValueObject - implements IFilterCriteria -{ +interface IFilterNode { + connection: string | undefined; + filter: Filter; +} + +export class FilterCriteria extends StringValueObject implements IFilterCriteria { + protected _root: IFilterNode; + protected static parseFilterString = (filterString: string): string[][] => { + // Ejemplo: lang_code[eq]pt|AND|dealer_id[eq]2222222|and|pepe[eq]assaas + // eslint-disable-next-line no-useless-escape const regex = /(?:\|([^\]]+)(?:\|))*([^\[|]+)\[([^\]]+)\]([^\[|]+)/gi; const result: any[] = []; @@ -40,14 +46,8 @@ export class FilterCriteria } protected static validate(value: UndefinedOr) { - if ( - RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, value) - .isSuccess - ) { - const stringOrError = RuleValidator.validate( - RuleValidator.RULE_IS_TYPE_STRING, - value - ); + if (RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, value).isSuccess) { + const stringOrError = RuleValidator.validate(RuleValidator.RULE_IS_TYPE_STRING, value); if (stringOrError.isFailure) { return stringOrError; @@ -75,8 +75,13 @@ export class FilterCriteria return Result.ok(filterString); } + constructor(value: string) { + super(value); + this._root = this.buildFilterRoot(value); + } + public getFilterRoot(): any { - return this.buildFilterRoot(); + return this._root; } public toJSON(): string { @@ -91,7 +96,7 @@ export class FilterCriteria return this.getFilterRoot(); } - protected buildFilterRoot(): any { + protected buildFilterRoot(filterString: string): IFilterNode { const __processNodes: any = (nodes: any[], prevFilter?: IFilter) => { const _node: any = nodes.shift(); @@ -109,37 +114,39 @@ export class FilterCriteria }; }; - const filterString = String(this.props); + const filterNodes = FilterCriteria.parseFilterString(filterString).map((token: string[]) => { + /** TOKEN + * [1] => and / or (optional) + * [2] => field + * [3] => operator + * [4] => value + */ + const connection = token[1] ? String(token[1]).toUpperCase() : undefined; - const filterNodes = FilterCriteria.parseFilterString(filterString).map( - (token: string[]) => { - /** TOKEN - * [1] => and / or (opcional) - * [2] => field - * [3] => operator - * [4] => value - */ - const connection = token[1] - ? String(token[1]).toUpperCase() - : undefined; + const filterOrError = Filter.create({ + field: token[2], + operator: String(token[3]).toUpperCase(), + value: token[4], + }); - const filterOrError = Filter.create({ - field: token[2], - operator: String(token[3]).toUpperCase(), - value: token[4], - }); - - if (filterOrError.isFailure) { - throw new Error(`Filter '${token.join()}' is not valid`); - } - - return { - connection, - filter: filterOrError.object, - }; + if (filterOrError.isFailure) { + throw new Error(`Filter '${token.join()}' is not valid`); } - ); + + return { + connection, + filter: filterOrError.object, + }; + }); return __processNodes(filterNodes, null); } + + public add(filter: Filter, connection: string = "AND"): void { + const newFilterString = `${connection.toLowerCase()}|${ + filter.field + }[${filter.operator.toLowerCase()}]${filter.value}`; + + this._root = this.buildFilterRoot(`${this.props}|${newFilterString}`); + } } diff --git a/shared/lib/contexts/sales/application/dto/Dealer/GetDealer.dto/IGetDealer_Response.dto.ts b/shared/lib/contexts/sales/application/dto/Dealer/GetDealer.dto/IGetDealer_Response.dto.ts index 8229b63..e2bf6df 100644 --- a/shared/lib/contexts/sales/application/dto/Dealer/GetDealer.dto/IGetDealer_Response.dto.ts +++ b/shared/lib/contexts/sales/application/dto/Dealer/GetDealer.dto/IGetDealer_Response.dto.ts @@ -1,4 +1,5 @@ export interface IGetDealerResponse_DTO { id: string; name: string; + lang_code: string; }