.
This commit is contained in:
parent
985111af5f
commit
a32ba80bb6
@ -10,6 +10,7 @@ export const checkUser = composeMiddleware([
|
|||||||
session: false,
|
session: false,
|
||||||
}),
|
}),
|
||||||
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
|
||||||
|
const user = <AuthUser>req.user;
|
||||||
if (req.isAuthenticated()) {
|
if (req.isAuthenticated()) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@ -33,6 +34,7 @@ export const checkAdminOrSelf = composeMiddleware([
|
|||||||
checkUser,
|
checkUser,
|
||||||
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
|
||||||
const user = <AuthUser>req.user;
|
const user = <AuthUser>req.user;
|
||||||
|
|
||||||
const { userId } = req.params;
|
const { userId } = req.params;
|
||||||
|
|
||||||
if (user.isAdmin) {
|
if (user.isAdmin) {
|
||||||
|
|||||||
@ -1,26 +1,52 @@
|
|||||||
import { IRepositoryManager, RepositoryManager } from "../domain";
|
import { IRepositoryManager, RepositoryManager } from "../domain";
|
||||||
import { ISequelizeAdapter, createSequelizeAdapter } from "./sequelize";
|
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
|
// ContextFactory.ts
|
||||||
export interface IContext<T> {
|
/*export interface IContext {
|
||||||
adapter: ISequelizeAdapter;
|
adapter: ISequelizeAdapter;
|
||||||
repositoryManager: IRepositoryManager;
|
repositoryManager: IRepositoryManager;
|
||||||
services: T;
|
services: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContextFactory<T> {
|
export class ContextFactory {
|
||||||
private static instances: Map<string, ContextFactory<any>> = new Map();
|
private static instances: Map<string, ContextFactory<any>> = new Map();
|
||||||
|
|
||||||
public static getInstance<T>(constructor: new () => T): ContextFactory<T> {
|
public static getInstance(constructor: new () => T): ContextFactory {
|
||||||
const key = constructor.name;
|
const key = constructor.name;
|
||||||
if (!ContextFactory.instances.has(key)) {
|
if (!ContextFactory.instances.has(key)) {
|
||||||
ContextFactory.instances.set(key, new ContextFactory<T>(constructor));
|
ContextFactory.instances.set(key, new ContextFactory(constructor));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContextFactory.instances.get(key)! as ContextFactory<T>;
|
return ContextFactory.instances.get(key)! as ContextFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private context: IContext<T>;
|
private context: IContext;
|
||||||
|
|
||||||
private constructor(constructor: new () => T) {
|
private constructor(constructor: new () => T) {
|
||||||
this.context = {
|
this.context = {
|
||||||
@ -30,7 +56,7 @@ export class ContextFactory<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContext(): IContext<T> {
|
public getContext(): IContext {
|
||||||
return this.context;
|
return this.context;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export class CreateDealerUseCase
|
|||||||
switch (domainError.code) {
|
switch (domainError.code) {
|
||||||
case DomainError.INVALID_INPUT_DATA:
|
case DomainError.INVALID_INPUT_DATA:
|
||||||
errorCode = UseCaseError.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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export class UpdateDealerUseCase
|
|||||||
// Errores manuales
|
// Errores manuales
|
||||||
case DomainError.INVALID_INPUT_DATA:
|
case DomainError.INVALID_INPUT_DATA:
|
||||||
errorCode = UseCaseError.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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -18,7 +18,16 @@ import {
|
|||||||
UnitPrice,
|
UnitPrice,
|
||||||
ensureIdIsValid,
|
ensureIdIsValid,
|
||||||
} from "@shared/contexts";
|
} 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 =
|
export type CreateQuoteResponseOrError =
|
||||||
| Result<never, IUseCaseError> // Misc errors (value objects)
|
| Result<never, IUseCaseError> // Misc errors (value objects)
|
||||||
@ -29,16 +38,25 @@ export class CreateQuoteUseCase
|
|||||||
{
|
{
|
||||||
private _adapter: ISequelizeAdapter;
|
private _adapter: ISequelizeAdapter;
|
||||||
private _repositoryManager: IRepositoryManager;
|
private _repositoryManager: IRepositoryManager;
|
||||||
|
private _dealer?: Dealer;
|
||||||
|
|
||||||
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
|
constructor(context: ISalesContext) {
|
||||||
this._adapter = props.adapter;
|
this._adapter = context.adapter;
|
||||||
this._repositoryManager = props.repositoryManager;
|
this._repositoryManager = context.repositoryManager;
|
||||||
|
this._dealer = context.dealer;
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(request: ICreateQuote_Request_DTO) {
|
async execute(request: ICreateQuote_Request_DTO) {
|
||||||
const { id } = request;
|
const { id } = request;
|
||||||
|
|
||||||
// Validaciones de datos
|
// 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);
|
const idOrError = ensureIdIsValid(id);
|
||||||
if (idOrError.isFailure) {
|
if (idOrError.isFailure) {
|
||||||
const message = idOrError.error.message; //`Quote ID ${quoteDTO.id} is not valid`;
|
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 quoteRepository = this._getQuoteRepository();
|
||||||
|
|
||||||
const idExists = await quoteRepository().exists(idOrError.object);
|
const idExists = await quoteRepository().exists(idOrError.object);
|
||||||
@ -61,7 +79,7 @@ export class CreateQuoteUseCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crear quote
|
// Crear quote
|
||||||
const quoteOrError = this._tryCreateQuoteInstance(request, idOrError.object);
|
const quoteOrError = this._tryCreateQuoteInstance(request, idOrError.object, dealerId);
|
||||||
|
|
||||||
if (quoteOrError.isFailure) {
|
if (quoteOrError.isFailure) {
|
||||||
const { error: domainError } = quoteOrError;
|
const { error: domainError } = quoteOrError;
|
||||||
@ -71,7 +89,7 @@ export class CreateQuoteUseCase
|
|||||||
switch (domainError.code) {
|
switch (domainError.code) {
|
||||||
case DomainError.INVALID_INPUT_DATA:
|
case DomainError.INVALID_INPUT_DATA:
|
||||||
errorCode = UseCaseError.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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -107,7 +125,8 @@ export class CreateQuoteUseCase
|
|||||||
|
|
||||||
private _tryCreateQuoteInstance(
|
private _tryCreateQuoteInstance(
|
||||||
quoteDTO: ICreateQuote_Request_DTO,
|
quoteDTO: ICreateQuote_Request_DTO,
|
||||||
quoteId: UniqueID
|
quoteId: UniqueID,
|
||||||
|
dealerId: UniqueID
|
||||||
): Result<Quote, IDomainError> {
|
): Result<Quote, IDomainError> {
|
||||||
const statusOrError = QuoteStatus.create(quoteDTO.status);
|
const statusOrError = QuoteStatus.create(quoteDTO.status);
|
||||||
if (statusOrError.isFailure) {
|
if (statusOrError.isFailure) {
|
||||||
@ -119,7 +138,7 @@ export class CreateQuoteUseCase
|
|||||||
return Result.fail(dateOrError.error);
|
return Result.fail(dateOrError.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const referenceOrError = QuoteStatus.create(quoteDTO.reference);
|
const referenceOrError = QuoteReference.create(quoteDTO.reference);
|
||||||
if (referenceOrError.isFailure) {
|
if (referenceOrError.isFailure) {
|
||||||
return Result.fail(referenceOrError.error);
|
return Result.fail(referenceOrError.error);
|
||||||
}
|
}
|
||||||
@ -182,6 +201,8 @@ export class CreateQuoteUseCase
|
|||||||
validity: validityOrError.object,
|
validity: validityOrError.object,
|
||||||
|
|
||||||
items,
|
items,
|
||||||
|
|
||||||
|
dealerId,
|
||||||
},
|
},
|
||||||
quoteId
|
quoteId
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { IUseCase, IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
|
import { IUseCase, IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
|
||||||
import { IRepositoryManager } from "@/contexts/common/domain";
|
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 { IInfrastructureError } from "@/contexts/common/infrastructure";
|
||||||
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { Quote } from "../../domain";
|
import { Dealer, Quote } from "../../domain";
|
||||||
import { IQuoteRepository } from "../../domain/repository";
|
import { IQuoteRepository } from "../../domain/repository";
|
||||||
|
import { ISalesContext } from "../../infrastructure";
|
||||||
|
|
||||||
export interface IListQuotesParams {
|
export interface IListQuotesParams {
|
||||||
queryCriteria: IQueryCriteria;
|
queryCriteria: IQueryCriteria;
|
||||||
@ -18,15 +19,28 @@ export type ListQuotesResult =
|
|||||||
export class ListQuotesUseCase implements IUseCase<IListQuotesParams, Promise<ListQuotesResult>> {
|
export class ListQuotesUseCase implements IUseCase<IListQuotesParams, Promise<ListQuotesResult>> {
|
||||||
private _adapter: ISequelizeAdapter;
|
private _adapter: ISequelizeAdapter;
|
||||||
private _repositoryManager: IRepositoryManager;
|
private _repositoryManager: IRepositoryManager;
|
||||||
|
private _dealer?: Dealer;
|
||||||
|
|
||||||
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
|
constructor(context: ISalesContext) {
|
||||||
this._adapter = props.adapter;
|
this._adapter = context.adapter;
|
||||||
this._repositoryManager = props.repositoryManager;
|
this._repositoryManager = context.repositoryManager;
|
||||||
|
this._dealer = context.dealer;
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(params: Partial<IListQuotesParams>): Promise<ListQuotesResult> {
|
async execute(params: Partial<IListQuotesParams>): Promise<ListQuotesResult> {
|
||||||
const { queryCriteria } = params;
|
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);
|
return this.findQuotes(queryCriteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ export class UpdateQuoteUseCase
|
|||||||
// Errores manuales
|
// Errores manuales
|
||||||
case DomainError.INVALID_INPUT_DATA:
|
case DomainError.INVALID_INPUT_DATA:
|
||||||
errorCode = UseCaseError.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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -111,6 +111,6 @@ export class Quote extends AggregateRoot<IQuoteProps> implements IQuote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get dealerId() {
|
get dealerId() {
|
||||||
return this.dealerId;
|
return this.props.dealerId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./Dealer/Dealer";
|
export * from "./Dealer";
|
||||||
export * from "./Quotes";
|
export * from "./Quotes";
|
||||||
|
|||||||
@ -1,32 +1,7 @@
|
|||||||
import { IRepositoryManager, RepositoryManager } from "@/contexts/common/domain";
|
import { IContext } from "@/contexts/common/infrastructure";
|
||||||
import {
|
import { Dealer } from "../domain";
|
||||||
ISequelizeAdapter,
|
|
||||||
createSequelizeAdapter,
|
|
||||||
} from "@/contexts/common/infrastructure/sequelize";
|
|
||||||
|
|
||||||
export interface ISalesContext {
|
export interface ISalesContext extends IContext {
|
||||||
adapter: ISequelizeAdapter;
|
|
||||||
repositoryManager: IRepositoryManager;
|
|
||||||
//services: IApplicationService;
|
//services: IApplicationService;
|
||||||
}
|
dealer?: Dealer;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 = <AuthUser>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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -20,29 +20,36 @@ class DealerMapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected toDomainMappingImpl(source: Dealer_Model, params: any): Dealer {
|
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 = {
|
const props: IDealerProps = {
|
||||||
user_id: this.mapsValue(source, "user_id", UniqueID.create),
|
user_id,
|
||||||
logo: "",
|
logo: "",
|
||||||
name: this.mapsValue(source, "name", Name.create),
|
name,
|
||||||
status: this.mapsValue(source, "status", DealerStatus.create),
|
status,
|
||||||
language: this.mapsValue(source, "language", Language.createFromCode),
|
language,
|
||||||
additionalInfo: KeyValueMap.create([
|
additionalInfo: additionalInfoOrError.object,
|
||||||
["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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = this.mapsValue(source, "id", UniqueID.create);
|
const id = this.mapsValue(source, "id", UniqueID.create);
|
||||||
const userOrError = Dealer.create(props, id);
|
const dealerOrError = Dealer.create(props, id);
|
||||||
|
|
||||||
if (userOrError.isFailure) {
|
if (dealerOrError.isFailure) {
|
||||||
throw userOrError.error;
|
throw dealerOrError.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return userOrError.object;
|
return dealerOrError.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toPersistenceMappingImpl(source: Dealer, params?: MapperParamsType | undefined) {
|
protected toPersistenceMappingImpl(source: Dealer, params?: MapperParamsType | undefined) {
|
||||||
@ -53,7 +60,7 @@ class DealerMapper
|
|||||||
logo: "",
|
logo: "",
|
||||||
name: source.name.toPrimitive(),
|
name: source.name.toPrimitive(),
|
||||||
status: source.status.toPrimitive(),
|
status: source.status.toPrimitive(),
|
||||||
language: source.language.toPrimitive(),
|
lang_code: source.language.toPrimitive(),
|
||||||
contact_information: source.additionalInfo.get("contact_information")?.toString() ?? "",
|
contact_information: source.additionalInfo.get("contact_information")?.toString() ?? "",
|
||||||
default_payment_method: source.additionalInfo.get("default_payment_method")?.toString() ?? "",
|
default_payment_method: source.additionalInfo.get("default_payment_method")?.toString() ?? "",
|
||||||
default_notes: source.additionalInfo.get("default_notes")?.toString() ?? "",
|
default_notes: source.additionalInfo.get("default_notes")?.toString() ?? "",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { UserCreationAttributes, User_Model } from "@/contexts/users";
|
import { User_Model } from "@/contexts/users";
|
||||||
import {
|
import {
|
||||||
|
CreationOptional,
|
||||||
DataTypes,
|
DataTypes,
|
||||||
InferAttributes,
|
InferAttributes,
|
||||||
InferCreationAttributes,
|
InferCreationAttributes,
|
||||||
@ -8,14 +9,14 @@ import {
|
|||||||
Op,
|
Op,
|
||||||
Sequelize,
|
Sequelize,
|
||||||
} from "sequelize";
|
} from "sequelize";
|
||||||
import { QuoteCreationAttributes, Quote_Model } from "./quote.model";
|
import { Quote_Model } from "./quote.model";
|
||||||
|
|
||||||
export type DealerCreationAttributes = InferCreationAttributes<
|
export type DealerCreationAttributes = InferCreationAttributes<
|
||||||
Dealer_Model,
|
Dealer_Model,
|
||||||
{ omit: "user" | "quotes" }
|
{ omit: "user" | "quotes" }
|
||||||
> & {
|
> & {
|
||||||
user: UserCreationAttributes;
|
user_id: string;
|
||||||
quotes: QuoteCreationAttributes[];
|
//quotes?: QuoteCreationAttributes[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Dealer_Model extends Model<
|
export class Dealer_Model extends Model<
|
||||||
@ -45,15 +46,15 @@ export class Dealer_Model extends Model<
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare id: string;
|
declare id: string;
|
||||||
declare contact_id?: string; // number ??
|
declare contact_id?: CreationOptional<string>;
|
||||||
declare name: string;
|
declare name: CreationOptional<string>;
|
||||||
declare contact_information: string;
|
declare contact_information: CreationOptional<string>;
|
||||||
declare default_payment_method: string;
|
declare default_payment_method: CreationOptional<string>;
|
||||||
declare default_notes: string;
|
declare default_notes: CreationOptional<string>;
|
||||||
declare default_legal_terms: string;
|
declare default_legal_terms: CreationOptional<string>;
|
||||||
declare default_quote_validity: string;
|
declare default_quote_validity: CreationOptional<string>;
|
||||||
declare status: string;
|
declare status: CreationOptional<string>;
|
||||||
declare language: string;
|
declare lang_code: CreationOptional<string>;
|
||||||
|
|
||||||
declare user: NonAttribute<User_Model>;
|
declare user: NonAttribute<User_Model>;
|
||||||
declare quotes: NonAttribute<Quote_Model>;
|
declare quotes: NonAttribute<Quote_Model>;
|
||||||
@ -82,7 +83,12 @@ export default (sequelize: Sequelize) => {
|
|||||||
default_notes: DataTypes.TEXT,
|
default_notes: DataTypes.TEXT,
|
||||||
default_legal_terms: DataTypes.TEXT,
|
default_legal_terms: DataTypes.TEXT,
|
||||||
default_quote_validity: DataTypes.TEXT,
|
default_quote_validity: DataTypes.TEXT,
|
||||||
language: DataTypes.STRING,
|
|
||||||
|
lang_code: {
|
||||||
|
type: DataTypes.STRING(2),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "es",
|
||||||
|
},
|
||||||
|
|
||||||
status: {
|
status: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
|
|||||||
@ -33,8 +33,8 @@ export class Quote_Model extends Model<
|
|||||||
});
|
});
|
||||||
|
|
||||||
Quote_Model.belongsTo(Dealer_Model, {
|
Quote_Model.belongsTo(Dealer_Model, {
|
||||||
as: "dealer",
|
|
||||||
foreignKey: "dealer_id",
|
foreignKey: "dealer_id",
|
||||||
|
as: "dealer",
|
||||||
onDelete: "RESTRICT",
|
onDelete: "RESTRICT",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
import { RepositoryManager } from "@/contexts/common/domain";
|
import { ContextFactory } from "@/contexts/common/infrastructure";
|
||||||
import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
|
||||||
|
|
||||||
export const createContextMiddleware = () => ({
|
export const createContextMiddleware = () => ContextFactory.getInstance();
|
||||||
adapter: createSequelizeAdapter(),
|
|
||||||
repositoryManager: RepositoryManager.getInstance(),
|
|
||||||
});
|
|
||||||
|
|||||||
@ -3,13 +3,14 @@ import {
|
|||||||
createQuoteController,
|
createQuoteController,
|
||||||
listQuotesController,
|
listQuotesController,
|
||||||
} from "@/contexts/sales/infrastructure/express/controllers";
|
} from "@/contexts/sales/infrastructure/express/controllers";
|
||||||
|
import { getDealerMiddleware } from "@/contexts/sales/infrastructure/express/middlewares/dealerMiddleware";
|
||||||
import Express from "express";
|
import Express from "express";
|
||||||
|
|
||||||
export const QuoteRouter = (appRouter: Express.Router) => {
|
export const QuoteRouter = (appRouter: Express.Router) => {
|
||||||
const quoteRoutes: Express.Router = Express.Router({ mergeParams: true });
|
const quoteRoutes: Express.Router = Express.Router({ mergeParams: true });
|
||||||
|
|
||||||
quoteRoutes.get("/", checkUser, listQuotesController);
|
quoteRoutes.get("/", checkUser, getDealerMiddleware, listQuotesController);
|
||||||
quoteRoutes.post("/", checkUser, createQuoteController);
|
quoteRoutes.post("/", checkUser, getDealerMiddleware, createQuoteController);
|
||||||
|
|
||||||
//quoteRoutes.put("/:quoteId", checkUser, updateQuoteController);
|
//quoteRoutes.put("/:quoteId", checkUser, updateQuoteController);
|
||||||
|
|
||||||
|
|||||||
@ -12,11 +12,17 @@ export interface IFilterCriteria {
|
|||||||
toObject(): Record<string, any>;
|
toObject(): Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FilterCriteria
|
interface IFilterNode {
|
||||||
extends StringValueObject
|
connection: string | undefined;
|
||||||
implements IFilterCriteria
|
filter: Filter;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
export class FilterCriteria extends StringValueObject implements IFilterCriteria {
|
||||||
|
protected _root: IFilterNode;
|
||||||
|
|
||||||
protected static parseFilterString = (filterString: string): string[][] => {
|
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
|
// eslint-disable-next-line no-useless-escape
|
||||||
const regex = /(?:\|([^\]]+)(?:\|))*([^\[|]+)\[([^\]]+)\]([^\[|]+)/gi;
|
const regex = /(?:\|([^\]]+)(?:\|))*([^\[|]+)\[([^\]]+)\]([^\[|]+)/gi;
|
||||||
const result: any[] = [];
|
const result: any[] = [];
|
||||||
@ -40,14 +46,8 @@ export class FilterCriteria
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static validate(value: UndefinedOr<string>) {
|
protected static validate(value: UndefinedOr<string>) {
|
||||||
if (
|
if (RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, value).isSuccess) {
|
||||||
RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, value)
|
const stringOrError = RuleValidator.validate(RuleValidator.RULE_IS_TYPE_STRING, value);
|
||||||
.isSuccess
|
|
||||||
) {
|
|
||||||
const stringOrError = RuleValidator.validate(
|
|
||||||
RuleValidator.RULE_IS_TYPE_STRING,
|
|
||||||
value
|
|
||||||
);
|
|
||||||
|
|
||||||
if (stringOrError.isFailure) {
|
if (stringOrError.isFailure) {
|
||||||
return stringOrError;
|
return stringOrError;
|
||||||
@ -75,8 +75,13 @@ export class FilterCriteria
|
|||||||
return Result.ok(filterString);
|
return Result.ok(filterString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(value: string) {
|
||||||
|
super(value);
|
||||||
|
this._root = this.buildFilterRoot(value);
|
||||||
|
}
|
||||||
|
|
||||||
public getFilterRoot(): any {
|
public getFilterRoot(): any {
|
||||||
return this.buildFilterRoot();
|
return this._root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): string {
|
public toJSON(): string {
|
||||||
@ -91,7 +96,7 @@ export class FilterCriteria
|
|||||||
return this.getFilterRoot();
|
return this.getFilterRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected buildFilterRoot(): any {
|
protected buildFilterRoot(filterString: string): IFilterNode {
|
||||||
const __processNodes: any = (nodes: any[], prevFilter?: IFilter) => {
|
const __processNodes: any = (nodes: any[], prevFilter?: IFilter) => {
|
||||||
const _node: any = nodes.shift();
|
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(
|
const filterOrError = Filter.create({
|
||||||
(token: string[]) => {
|
field: token[2],
|
||||||
/** TOKEN
|
operator: String(token[3]).toUpperCase(),
|
||||||
* [1] => and / or (opcional)
|
value: token[4],
|
||||||
* [2] => field
|
});
|
||||||
* [3] => operator
|
|
||||||
* [4] => value
|
|
||||||
*/
|
|
||||||
const connection = token[1]
|
|
||||||
? String(token[1]).toUpperCase()
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const filterOrError = Filter.create({
|
if (filterOrError.isFailure) {
|
||||||
field: token[2],
|
throw new Error(`Filter '${token.join()}' is not valid`);
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return {
|
||||||
|
connection,
|
||||||
|
filter: filterOrError.object,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return __processNodes(filterNodes, null);
|
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}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
export interface IGetDealerResponse_DTO {
|
export interface IGetDealerResponse_DTO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
lang_code: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user