diff --git a/server/src/contexts/catalog/infrastructure/Catalog.context.ts b/server/src/contexts/catalog/infrastructure/Catalog.context.ts new file mode 100644 index 0000000..63aa2e3 --- /dev/null +++ b/server/src/contexts/catalog/infrastructure/Catalog.context.ts @@ -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; + } +} diff --git a/server/src/contexts/catalog/infrastructure/sequelize/article.model.ts.bak b/server/src/contexts/catalog/infrastructure/sequelize/article.model.ts.bak index e8e2704..7dd32ee 100644 --- a/server/src/contexts/catalog/infrastructure/sequelize/article.model.ts.bak +++ b/server/src/contexts/catalog/infrastructure/sequelize/article.model.ts.bak @@ -45,7 +45,7 @@ export class Article_Model extends Model< declare points: CreationOptional; declare retail_price: CreationOptional; - declare translations?: NonAttribute; + declare translations: NonAttribute; } export default (sequelize: Sequelize) => { diff --git a/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts b/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts index 0b4a95e..b7fe7fa 100644 --- a/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts +++ b/server/src/contexts/sales/application/Quote/ListQuotes.useCase.ts @@ -43,6 +43,7 @@ export class ListQuotesUseCase implements IUseCase( 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 diff --git a/server/src/contexts/sales/domain/entities/Quotes/Quote.ts b/server/src/contexts/sales/domain/entities/Quotes/Quote.ts index ba32f39..7ca6d51 100644 --- a/server/src/contexts/sales/domain/entities/Quotes/Quote.ts +++ b/server/src/contexts/sales/domain/entities/Quotes/Quote.ts @@ -26,6 +26,8 @@ export interface IQuoteProps { validity: Note; items: ICollection; + + dealerId: UniqueID; } export interface IQuote { @@ -41,6 +43,8 @@ export interface IQuote { notes: Note; validity: Note; items: ICollection; + + dealerId: UniqueID; } export class Quote extends AggregateRoot implements IQuote { @@ -105,4 +109,8 @@ export class Quote extends AggregateRoot implements IQuote { get items() { return this._items; } + + get dealerId() { + return this.dealerId; + } } diff --git a/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/index.ts b/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/index.ts index f1b957c..bd19c2c 100644 --- a/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/index.ts +++ b/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/index.ts @@ -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); }; diff --git a/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/presenter/ListQuotes.presenter.ts b/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/presenter/ListQuotes.presenter.ts index 3aa604c..342d3e4 100644 --- a/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/presenter/ListQuotes.presenter.ts +++ b/server/src/contexts/sales/infrastructure/express/controllers/quotes/listQuotes/presenter/ListQuotes.presenter.ts @@ -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, diff --git a/server/src/contexts/sales/infrastructure/mappers/quote.mapper.ts b/server/src/contexts/sales/infrastructure/mappers/quote.mapper.ts index 9ede6ec..dedb230 100644 --- a/server/src/contexts/sales/infrastructure/mappers/quote.mapper.ts +++ b/server/src/contexts/sales/infrastructure/mappers/quote.mapper.ts @@ -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; diff --git a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts index 2b375b2..f974e30 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts @@ -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, @@ -52,8 +55,8 @@ export class Dealer_Model extends Model< declare status: string; declare language: string; - declare user?: NonAttribute; - declare quotes?: NonAttribute; + declare user: NonAttribute; + declare quotes: NonAttribute; } export default (sequelize: Sequelize) => { diff --git a/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts b/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts index f816b00..2a55d36 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/quote.model.ts @@ -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, @@ -51,8 +54,8 @@ export class Quote_Model extends Model< declare discount: CreationOptional; declare total: CreationOptional; - declare items?: NonAttribute; - declare dealer?: NonAttribute; + declare items: NonAttribute; + declare dealer: NonAttribute; } export default (sequelize: Sequelize) => { diff --git a/server/src/contexts/sales/infrastructure/sequelize/quoteItem.model.ts b/server/src/contexts/sales/infrastructure/sequelize/quoteItem.model.ts index 8f11846..297f5cc 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/quoteItem.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/quoteItem.model.ts @@ -37,7 +37,7 @@ export class QuoteItem_Model extends Model< declare subtotal: CreationOptional; declare total: CreationOptional; - declare quote?: NonAttribute; + declare quote: NonAttribute; } export default (sequelize: Sequelize) => { diff --git a/server/src/infrastructure/express/api/context.middleware.ts b/server/src/infrastructure/express/api/context.middleware.ts index a442b2c..0eacbb6 100644 --- a/server/src/infrastructure/express/api/context.middleware.ts +++ b/server/src/infrastructure/express/api/context.middleware.ts @@ -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(), +}); diff --git a/server/src/infrastructure/express/api/routes/quote.routes.ts b/server/src/infrastructure/express/api/routes/quote.routes.ts index e4a2bb6..bc72aab 100644 --- a/server/src/infrastructure/express/api/routes/quote.routes.ts +++ b/server/src/infrastructure/express/api/routes/quote.routes.ts @@ -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); diff --git a/server/src/infrastructure/express/api/v1.ts b/server/src/infrastructure/express/api/v1.ts index f7379f9..691fd6f 100644 --- a/server/src/infrastructure/express/api/v1.ts +++ b/server/src/infrastructure/express/api/v1.ts @@ -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; }; diff --git a/shared/lib/contexts/sales/application/dto/Quote/ListQuotes.dto/IListQuotes_Response.dto.ts b/shared/lib/contexts/sales/application/dto/Quote/ListQuotes.dto/IListQuotes_Response.dto.ts index fbc3d18..f0dbdd3 100644 --- a/shared/lib/contexts/sales/application/dto/Quote/ListQuotes.dto/IListQuotes_Response.dto.ts +++ b/shared/lib/contexts/sales/application/dto/Quote/ListQuotes.dto/IListQuotes_Response.dto.ts @@ -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; diff --git a/shared/lib/contexts/sales/application/dto/Quote/UpdateQuote.dto/IUpdateQuote_Request.dto.ts b/shared/lib/contexts/sales/application/dto/Quote/UpdateQuote.dto/IUpdateQuote_Request.dto.ts index 17e36b1..53b1495 100644 --- a/shared/lib/contexts/sales/application/dto/Quote/UpdateQuote.dto/IUpdateQuote_Request.dto.ts +++ b/shared/lib/contexts/sales/application/dto/Quote/UpdateQuote.dto/IUpdateQuote_Request.dto.ts @@ -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(),