This commit is contained in:
David Arranz 2024-07-02 22:15:59 +02:00
parent 0b00b84289
commit 985111af5f
16 changed files with 153 additions and 39 deletions

View File

@ -0,0 +1,32 @@
import { IRepositoryManager, RepositoryManager } from "@/contexts/common/domain";
import {
ISequelizeAdapter,
createSequelizeAdapter,
} from "@/contexts/common/infrastructure/sequelize";
export interface ICatalogContext {
adapter: ISequelizeAdapter;
repositoryManager: IRepositoryManager;
//services: IApplicationService;
}
export class CatalogContext {
private static instance: CatalogContext | null = null;
public static getInstance(): ICatalogContext {
if (!CatalogContext.instance) {
CatalogContext.instance = new CatalogContext({
adapter: createSequelizeAdapter(),
repositoryManager: RepositoryManager.getInstance(),
});
}
return CatalogContext.instance.context;
}
private context: ICatalogContext;
private constructor(context: ICatalogContext) {
this.context = context;
}
}

View File

@ -45,7 +45,7 @@ export class Article_Model extends Model<
declare points: CreationOptional<number>;
declare retail_price: CreationOptional<number>;
declare translations?: NonAttribute<ArticleTranslation_Model[]>;
declare translations: NonAttribute<ArticleTranslation_Model[]>;
}
export default (sequelize: Sequelize) => {

View File

@ -43,6 +43,7 @@ export class ListQuotesUseCase implements IUseCase<IListQuotesParams, Promise<Li
return Result.ok(Quotes);
} catch (error: unknown) {
const _error = error as IInfrastructureError;
console.trace(_error.message);
return Result.fail(
UseCaseError.create(
UseCaseError.REPOSITORY_ERROR,

View File

@ -14,6 +14,7 @@ import {
DomainError,
IDomainError,
Language,
Note,
Quantity,
Result,
UTCDateValue,
@ -22,7 +23,7 @@ import {
} from "@shared/contexts";
import { IUpdateQuote_Request_DTO } from "@shared/contexts";
import { IQuoteRepository, Quote, QuoteItem, QuoteStatus } from "../../domain";
import { IQuoteRepository, Quote, QuoteCustomer, QuoteItem, QuoteStatus } from "../../domain";
export interface IUpdateQuoteUseCaseRequest extends IUseCaseRequest {
id: UniqueID;
@ -119,22 +120,47 @@ export class UpdateQuoteUseCase
return Result.fail(dateOrError.error);
}
const languageOrError = Language.createFromCode(quoteDTO.language_code);
const referenceOrError = QuoteStatus.create(quoteDTO.reference);
if (referenceOrError.isFailure) {
return Result.fail(referenceOrError.error);
}
const languageOrError = Language.createFromCode(quoteDTO.lang_code);
if (languageOrError.isFailure) {
return Result.fail(languageOrError.error);
}
const customerOrError = QuoteCustomer.create(quoteDTO.customer_information);
if (customerOrError.isFailure) {
return Result.fail(customerOrError.error);
}
const currencyOrError = Currency.createFromCode(quoteDTO.currency_code);
if (currencyOrError.isFailure) {
return Result.fail(currencyOrError.error);
}
const paymentOrError = Note.create(quoteDTO.payment_method);
if (paymentOrError.isFailure) {
return Result.fail(paymentOrError.error);
}
const notesOrError = Note.create(quoteDTO.notes);
if (notesOrError.isFailure) {
return Result.fail(notesOrError.error);
}
const validityOrError = Note.create(quoteDTO.validity);
if (validityOrError.isFailure) {
return Result.fail(validityOrError.error);
}
const items = new Collection<QuoteItem>(
quoteDTO.items?.map(
(item) =>
QuoteItem.create({
description: Description.create(item.description).object,
quantity: Quantity.create(item.quantity).object,
quantity: Quantity.create({ amount: item.quantity, precision: 4 }).object,
unitPrice: UnitPrice.create({
amount: item.unit_price.amount,
currencyCode: item.unit_price.currency,
@ -148,8 +174,14 @@ export class UpdateQuoteUseCase
{
status: statusOrError.object,
date: dateOrError.object,
reference: referenceOrError.object,
language: languageOrError.object,
customer: customerOrError.object,
currency: currencyOrError.object,
paymentMethod: paymentOrError.object,
notes: notesOrError.object,
validity: validityOrError.object,
items,
},
quoteId

View File

@ -26,6 +26,8 @@ export interface IQuoteProps {
validity: Note;
items: ICollection<QuoteItem>;
dealerId: UniqueID;
}
export interface IQuote {
@ -41,6 +43,8 @@ export interface IQuote {
notes: Note;
validity: Note;
items: ICollection<QuoteItem>;
dealerId: UniqueID;
}
export class Quote extends AggregateRoot<IQuoteProps> implements IQuote {
@ -105,4 +109,8 @@ export class Quote extends AggregateRoot<IQuoteProps> implements IQuote {
get items() {
return this._items;
}
get dealerId() {
return this.dealerId;
}
}

View File

@ -1,10 +1,16 @@
import { ListQuotesUseCase } from "@/contexts/sales/application";
import { registerQuoteRepository } from "@/contexts/sales/infrastructure/Quote.repository";
import { ISalesContext } from "../../../../Sales.context";
import Express from "express";
import { ListQuotesController } from "./ListQuotes.controller";
import { ListQuotesPresenter } from "./presenter";
export const listQuotesController = (context: ISalesContext) => {
export const listQuotesController = (
req: Express.Request,
res: Express.Response,
next: Express.NextFunction
) => {
const context = res.locals.context;
registerQuoteRepository(context);
return new ListQuotesController(
@ -13,5 +19,5 @@ export const listQuotesController = (context: ISalesContext) => {
presenter: ListQuotesPresenter,
},
context
);
).execute(req, res, next);
};

View File

@ -21,8 +21,11 @@ export const ListQuotesPresenter: IListQuotesPresenter = {
id: quote.id.toString(),
status: quote.status.toString(),
date: quote.date.toString(),
language_code: quote.date.toISO8601(),
reference: quote.reference.toString(),
customer_information: quote.customer.toString(),
lang_code: quote.date.toISO8601(),
currency_code: quote.currency.toString(),
subtotal: {
amount: 0,
precision: 2,

View File

@ -1,7 +1,7 @@
import { Currency, Language, UTCDateValue, UniqueID } from "@shared/contexts";
import { Currency, Language, Note, UTCDateValue, UniqueID } from "@shared/contexts";
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
import { IQuoteProps, Quote } from "../../domain";
import { IQuoteProps, Quote, QuoteCustomer, QuoteReference } from "../../domain";
import { QuoteStatus } from "../../domain/entities/Quotes/QuoteStatus";
import { ISalesContext } from "../Sales.context";
import { QuoteCreationAttributes, Quote_Model } from "../sequelize";
@ -34,11 +34,18 @@ class QuoteMapper
const props: IQuoteProps = {
status: this.mapsValue(source, "status", QuoteStatus.create),
date: this.mapsValue(source, "issue_date", UTCDateValue.create),
reference: this.mapsValue(source, "reference", QuoteReference.create),
currency: this.mapsValue(source, "quote_currency", Currency.createFromCode),
language: this.mapsValue(source, "quote_language", Language.createFromCode),
customer: source.customer_information,
customer: this.mapsValue(source, "customer", QuoteCustomer.create),
validity: this.mapsValue(source, "validity", Note.create),
paymentMethod: this.mapsValue(source, "paymentMethod", Note.create),
notes: this.mapsValue(source, "notes", Note.create),
items,
dealerId: this.mapsValue(source, "dealer_id", UniqueID.create),
};
const quoteOrError = Quote.create(props, id);
@ -60,12 +67,20 @@ class QuoteMapper
id: source.id.toPrimitive(),
status: source.status.toPrimitive(),
date: source.date.toPrimitive(),
reference: source.reference.toPrimitive(),
currency_code: source.currency.toPrimitive(),
lang_code: source.language.toPrimitive(),
customer_information: source.customer,
customer_information: source.customer.toPrimitive(),
validity: source.validity.toPrimitive(),
payment_method: source.paymentMethod.toPrimitive(),
notes: source.notes.toPrimitive(),
discount: 0,
subtotal: 0,
total: 0,
items,
dealer_id: source.dealerId.toPrimitive(),
};
return quote;

View File

@ -1,4 +1,4 @@
import { User_Model } from "@/contexts/users";
import { UserCreationAttributes, User_Model } from "@/contexts/users";
import {
DataTypes,
InferAttributes,
@ -8,12 +8,15 @@ import {
Op,
Sequelize,
} from "sequelize";
import { Quote_Model } from "./quote.model";
import { QuoteCreationAttributes, Quote_Model } from "./quote.model";
export type DealerCreationAttributes = InferCreationAttributes<
Dealer_Model,
{ omit: "user" | "quotes" }
>;
> & {
user: UserCreationAttributes;
quotes: QuoteCreationAttributes[];
};
export class Dealer_Model extends Model<
InferAttributes<Dealer_Model, { omit: "user" | "quotes" }>,
@ -52,8 +55,8 @@ export class Dealer_Model extends Model<
declare status: string;
declare language: string;
declare user?: NonAttribute<User_Model>;
declare quotes?: NonAttribute<Quote_Model>;
declare user: NonAttribute<User_Model>;
declare quotes: NonAttribute<Quote_Model>;
}
export default (sequelize: Sequelize) => {

View File

@ -9,12 +9,15 @@ import {
Sequelize,
} from "sequelize";
import { Dealer_Model } from "./dealer.model";
import { QuoteItem_Model } from "./quoteItem.model";
import { QuoteItemCreationAttributes, QuoteItem_Model } from "./quoteItem.model";
export type QuoteCreationAttributes = InferCreationAttributes<
Quote_Model,
{ omit: "items" | "dealer" }
>;
> & {
items: QuoteItemCreationAttributes[];
dealer_id: string;
};
export class Quote_Model extends Model<
InferAttributes<Quote_Model, { omit: "items" | "dealer" }>,
@ -51,8 +54,8 @@ export class Quote_Model extends Model<
declare discount: CreationOptional<number>;
declare total: CreationOptional<number>;
declare items?: NonAttribute<QuoteItem_Model[]>;
declare dealer?: NonAttribute<Dealer_Model>;
declare items: NonAttribute<QuoteItem_Model[]>;
declare dealer: NonAttribute<Dealer_Model>;
}
export default (sequelize: Sequelize) => {

View File

@ -37,7 +37,7 @@ export class QuoteItem_Model extends Model<
declare subtotal: CreationOptional<number>;
declare total: CreationOptional<number>;
declare quote?: NonAttribute<Quote_Model>;
declare quote: NonAttribute<Quote_Model>;
}
export default (sequelize: Sequelize) => {

View File

@ -1,3 +1,7 @@
import { UserContext } from "@/contexts/users/infrastructure/User.context";
import { RepositoryManager } from "@/contexts/common/domain";
import { createSequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
export const createContextMiddleware = () => UserContext.getInstance();
export const createContextMiddleware = () => ({
adapter: createSequelizeAdapter(),
repositoryManager: RepositoryManager.getInstance(),
});

View File

@ -8,13 +8,7 @@ import Express from "express";
export const QuoteRouter = (appRouter: Express.Router) => {
const quoteRoutes: Express.Router = Express.Router({ mergeParams: true });
quoteRoutes.get(
"/",
checkUser,
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
listQuotesController(res.locals["context"]).execute(req, res, next)
);
quoteRoutes.get("/", checkUser, listQuotesController);
quoteRoutes.post("/", checkUser, createQuoteController);
//quoteRoutes.put("/:quoteId", checkUser, updateQuoteController);

View File

@ -2,10 +2,10 @@ import Express from "express";
import { createContextMiddleware } from "./context.middleware";
import {
DealerRouter,
QuoteRouter,
authRouter,
catalogRouter,
profileRouter,
quoteRoutes,
usersRouter,
} from "./routes";
@ -22,6 +22,7 @@ export const v1Routes = () => {
return next();
});
routes.use((req, res, next) => {
console.log(`[${new Date().toLocaleTimeString()}] Incoming request to ${req.path}`);
next();
@ -32,7 +33,7 @@ export const v1Routes = () => {
usersRouter(routes);
catalogRouter(routes);
DealerRouter(routes);
quoteRoutes(routes);
QuoteRouter(routes);
return routes;
};

View File

@ -1,11 +1,12 @@
import { IMoney_Response_DTO } from "shared/lib/contexts/common";
import { IMoney_Response_DTO } from "../../../../../common";
export interface IListQuotes_Response_DTO {
id: string;
status: string;
date: string;
language_code: string;
reference: string;
customer_information: string;
lang_code: string;
currency_code: string;
subtotal: IMoney_Response_DTO;

View File

@ -4,8 +4,13 @@ import { IMoney_Request_DTO, Result, RuleValidator } from "../../../../../common
export interface IUpdateQuote_Request_DTO {
status: string;
date: string;
language_code: string;
reference: string;
customer_information: string;
lang_code: string;
currency_code: string;
payment_method: string;
notes: string;
validity: string;
items: IUpdateQuoteItem_Request_DTO[];
}
@ -20,8 +25,14 @@ export interface IUpdateQuoteItem_Request_DTO {
export function ensureUpdateQuote_Request_DTOIsValid(quoteDTO: IUpdateQuote_Request_DTO) {
const schema = Joi.object({
date: Joi.string(),
language: Joi.string(),
currency: Joi.string(),
reference: Joi.string(),
lang_code: Joi.string(),
customer_information: Joi.string(),
currency_code: Joi.string(),
payment_method: Joi.string(),
notes: Joi.string(),
validity: Joi.string(),
items: Joi.array().items(
Joi.object({
description: Joi.string(),