From 033d2363dfe8eb201be67582a497f448353e3ba1 Mon Sep 17 00:00:00 2001 From: David Arranz Date: Mon, 26 Aug 2024 20:29:41 +0200 Subject: [PATCH] . --- .../src/app/quotes/components/QuoteResume.tsx | 236 ++++++++++++++++++ .../app/quotes/components/QuotesDataTable.tsx | 12 +- .../components/editors/QuoteStatusEditor.tsx | 50 ++++ .../app/quotes/components/editors/index.ts | 1 + client/src/app/quotes/components/index.ts | 1 + client/src/app/quotes/edit.tsx | 2 +- client/src/app/quotes/list.tsx | 2 +- .../Quote/SetStatusQuote.useCase.ts | 96 +++++++ .../contexts/sales/application/Quote/index.ts | 1 + .../repository/QuoteRepository.interface.ts | 4 +- .../sales/infrastructure/Quote.repository.ts | 33 ++- .../express/controllers/quotes/index.ts | 1 + .../SetStatusQuote.controller.ts | 103 ++++++++ .../quotes/setStatusQuote/index.ts | 21 ++ .../express/api/routes/quote.routes.ts | 7 + .../ISetStatusQuote_Request.dto.ts | 20 ++ .../dto/Quote/SetStatusQuote.dto/index.ts | 1 + .../sales/application/dto/Quote/index.ts | 1 + 18 files changed, 574 insertions(+), 18 deletions(-) create mode 100644 client/src/app/quotes/components/QuoteResume.tsx create mode 100644 client/src/app/quotes/components/editors/QuoteStatusEditor.tsx create mode 100644 server/src/contexts/sales/application/Quote/SetStatusQuote.useCase.ts create mode 100644 server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/SetStatusQuote.controller.ts create mode 100644 server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/index.ts create mode 100644 shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/ISetStatusQuote_Request.dto.ts create mode 100644 shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/index.ts diff --git a/client/src/app/quotes/components/QuoteResume.tsx b/client/src/app/quotes/components/QuoteResume.tsx new file mode 100644 index 0000000..4fd100f --- /dev/null +++ b/client/src/app/quotes/components/QuoteResume.tsx @@ -0,0 +1,236 @@ +import { + ChevronLeft, + ChevronRight, + CreditCard, + DownloadIcon, + FilePenLineIcon, + MoreVertical, +} from "lucide-react"; + +import { cn } from "@/lib/utils"; +import { + Button, + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, + Pagination, + PaginationContent, + PaginationItem, + Separator, + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/ui"; +import { t } from "i18next"; +import { useNavigate } from "react-router-dom"; +import { useQuotes } from "../hooks"; +import { QuoteStatusEditor } from "./editors"; + +type QuoteResumeProps = { + quoteId: string; + className: string; +}; + +export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { + const { useOne, useUpdate } = useQuotes(); + const { data, status, error: queryError } = useOne(quoteId); + const navigate = useNavigate(); + + if (status === "error") { + return null; + } + + if (status !== "success") { + return null; + } + + if (!data) { + return ( + + +

Select a quote

+
+
+ ); + } + + return ( + + + +
+ + {`${t("quotes.list.preview.quote")} #${data.reference}`} + + assaasassa +
+
+ + + + + + + + Edit + Export + + Trash + + +
+
+ + null} /> + + + + Resume + Preview + + +
+
+
Customer Information
+ Date: {new Date(data.date).toLocaleDateString()} +
{data.customer_information}
+
+
+
Customer
+
Liam Johnson
+
+
+
Email
+
+ liam@acme.com +
+
+
+
Phone
+
+ +1 234 567 890 +
+
+
+
+ +
Order Details
+
    +
  • + + Glimmer Lamps x 2 + + $250.00 +
  • +
  • + + Aqua Filters x 1 + + $49.00 +
  • +
+ +
    +
  • + Subtotal + $299.00 +
  • +
  • + Shipping + $5.00 +
  • +
  • + Tax + $25.00 +
  • +
  • + Total + $329.00 +
  • +
+
+ +
+
+
Shipping Information
+
+ Liam Johnson + 1234 Main St. + Anytown, CA 12345 +
+
+
+
Billing Information
+
Same as shipping address
+
+
+ + +
+
Payment Information
+
+
+
+ + Visa +
+
**** **** **** 4532
+
+
+
+
+ +
+ +
Updated...
+ + + + + + + + + + +
+
+
+ ); +}; diff --git a/client/src/app/quotes/components/QuotesDataTable.tsx b/client/src/app/quotes/components/QuotesDataTable.tsx index 8e04cef..5f980c1 100644 --- a/client/src/app/quotes/components/QuotesDataTable.tsx +++ b/client/src/app/quotes/components/QuotesDataTable.tsx @@ -25,7 +25,7 @@ import { TooltipTrigger, } from "@/ui"; import { useToast } from "@/ui/use-toast"; -import { IListQuotes_Response_DTO, MoneyValue, UTCDateValue } from "@shared/contexts"; +import { IListQuotes_Response_DTO, UTCDateValue } from "@shared/contexts"; import { ColumnDef, Row } from "@tanstack/react-table"; import { t } from "i18next"; import { FilePenLineIcon, MoreVerticalIcon } from "lucide-react"; @@ -33,7 +33,7 @@ import { useCallback, useEffect, useId, useMemo, useState } from "react"; import { useNavigate } from "react-router-dom"; import { useQuotes } from "../hooks"; import { DownloadQuoteDialog } from "./DownloadQuoteDialog"; -import { QuotePDFPreview } from "./QuotePDFPreview"; +import { QuoteResume } from "./QuoteResume"; export const QuotesDataTable = ({ status = "all", @@ -137,8 +137,7 @@ export const QuotesDataTable = ({ ), size: 600, }, - - { + /*{ id: "total_price" as const, accessor: "total_price", header: () =>
{t("quotes.list.columns.total_price")}
, @@ -148,7 +147,7 @@ export const QuotesDataTable = ({
{price.isSuccess ? price.object.toFormat() : "-"}
); }, - }, + },*/ { id: "row-actions", header: () => null, @@ -294,7 +293,8 @@ export const QuotesDataTable = ({ defaultSize={35} className='flex items-stretch flex-1' > - + + {/**/} )} diff --git a/client/src/app/quotes/components/editors/QuoteStatusEditor.tsx b/client/src/app/quotes/components/editors/QuoteStatusEditor.tsx new file mode 100644 index 0000000..f177c3b --- /dev/null +++ b/client/src/app/quotes/components/editors/QuoteStatusEditor.tsx @@ -0,0 +1,50 @@ +import { Button } from "@/ui/button"; +import { Select, SelectContent, SelectTrigger, SelectValue } from "@/ui/select"; +import { SelectItem } from "@radix-ui/react-select"; +import { useState } from "react"; + +const QUOTE_STATUS = ["draft", "ready", "delivered", "accepted", "rejected", "archived"]; + +const QUOTE_NEXT_STATUS = { + draft: ["ready", "archived"], + ready: ["delivered", "archived"], + delivered: ["accepted", "rejected", "archived"], + accepted: ["archived"], + rejected: ["archived"], + archived: [], +}; + +export const QuoteStatusEditor = ({ quote, onChangeStatus }) => { + const [status, changeStatus] = useState(quote.status); + + const handleChangeStatus = () => { + if (status !== quote.status) { + onChangeStatus(quote.id, status); + } + }; + + return ( +
+ + +
+ ); +}; diff --git a/client/src/app/quotes/components/editors/index.ts b/client/src/app/quotes/components/editors/index.ts index d8b9177..fe71ae5 100644 --- a/client/src/app/quotes/components/editors/index.ts +++ b/client/src/app/quotes/components/editors/index.ts @@ -1,3 +1,4 @@ export * from "./QuoteDetailsCardEditor"; export * from "./QuoteDocumentsCardEditor"; export * from "./QuoteGeneralCardEditor"; +export * from "./QuoteStatusEditor"; diff --git a/client/src/app/quotes/components/index.ts b/client/src/app/quotes/components/index.ts index 8af5494..1710530 100644 --- a/client/src/app/quotes/components/index.ts +++ b/client/src/app/quotes/components/index.ts @@ -1,2 +1,3 @@ export * from "./QuotePricesResume"; +export * from "./QuoteResume"; export * from "./QuotesDataTable"; diff --git a/client/src/app/quotes/edit.tsx b/client/src/app/quotes/edit.tsx index 3e44ade..1b5c1f8 100644 --- a/client/src/app/quotes/edit.tsx +++ b/client/src/app/quotes/edit.tsx @@ -255,7 +255,7 @@ export const QuoteEdit = () => {
navigate("/quotes")} diff --git a/client/src/app/quotes/list.tsx b/client/src/app/quotes/list.tsx index 5563bed..a0730c3 100644 --- a/client/src/app/quotes/list.tsx +++ b/client/src/app/quotes/list.tsx @@ -10,7 +10,7 @@ import { useNavigate } from "react-router-dom"; export const QuotesList = () => { const navigate = useNavigate(); - const [enabledPreview, toggleEnabledPreview] = useToggle(false); + const [enabledPreview, toggleEnabledPreview] = useToggle(true); return ( diff --git a/server/src/contexts/sales/application/Quote/SetStatusQuote.useCase.ts b/server/src/contexts/sales/application/Quote/SetStatusQuote.useCase.ts new file mode 100644 index 0000000..ca36116 --- /dev/null +++ b/server/src/contexts/sales/application/Quote/SetStatusQuote.useCase.ts @@ -0,0 +1,96 @@ +import { + IUseCase, + IUseCaseError, + IUseCaseRequest, + UseCaseError, +} from "@/contexts/common/application/useCases"; +import { IRepositoryManager } from "@/contexts/common/domain"; +import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; +import { DomainError, ISetStatusQuote_Request_DTO, Result, UniqueID } from "@shared/contexts"; +import { IQuoteRepository, QuoteStatus } from "../../domain"; + +export interface ISetStatusQuoteUseCaseRequest extends IUseCaseRequest { + id: UniqueID; + newStatusDTO: ISetStatusQuote_Request_DTO; +} + +export type SetStatusQuoteResponseOrError = + | Result // Misc errors (value objects) + | Result; // Success! + +export class SetStatusQuoteUseCase + implements IUseCase> +{ + private _adapter: ISequelizeAdapter; + private _repositoryManager: IRepositoryManager; + + constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) { + this._adapter = props.adapter; + this._repositoryManager = props.repositoryManager; + } + + async execute(request: ISetStatusQuoteUseCaseRequest): Promise { + const { + id, + newStatusDTO: { newStatus }, + } = request; + + const quoteRepository = this._getQuoteRepository(); + + // Comprobar que existe el Quote + const idExists = await quoteRepository().exists(id); + if (!idExists) { + const message = `Quote ID not found`; + return Result.fail( + UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, { + path: "id", + }) + ); + } + + // Comprobar el status + const statusOrError = QuoteStatus.create(newStatus); + if (statusOrError.isFailure) { + const { error: domainError } = statusOrError; + let errorCode = ""; + let message = ""; + + switch (domainError.code) { + // Errores manuales + case DomainError.INVALID_INPUT_DATA: + errorCode = UseCaseError.INVALID_INPUT_DATA; + message = "Es nuevo estado no es correcto"; + break; + + default: + errorCode = UseCaseError.UNEXCEPTED_ERROR; + message = domainError.message; + break; + } + + return Result.fail(UseCaseError.create(errorCode, message, domainError)); + } + + const transaction = this._adapter.startTransaction(); + try { + await transaction.complete(async (t) => { + const quoteRepo = quoteRepository({ transaction: t }); + await quoteRepo.updateStatusById(id, statusOrError.object); + }); + + return Result.ok(); + } catch (error: unknown) { + //const _error = error as IInfrastructureError; + return Result.fail( + UseCaseError.create( + UseCaseError.REPOSITORY_ERROR, + "Error al establecer el nuevo estado en la cotización" + ) + ); + } + } + + private _getQuoteRepository() { + return this._repositoryManager.getRepository("Quote"); + } +} diff --git a/server/src/contexts/sales/application/Quote/index.ts b/server/src/contexts/sales/application/Quote/index.ts index 9e6c161..443716a 100644 --- a/server/src/contexts/sales/application/Quote/index.ts +++ b/server/src/contexts/sales/application/Quote/index.ts @@ -2,4 +2,5 @@ export * from "./CreateQuote.useCase"; export * from "./DeleteQuote.useCase"; export * from "./GetQuote.useCase"; export * from "./ListQuotes.useCase"; +export * from "./SetStatusQuote.useCase"; export * from "./UpdateQuote.useCase"; diff --git a/server/src/contexts/sales/domain/repository/QuoteRepository.interface.ts b/server/src/contexts/sales/domain/repository/QuoteRepository.interface.ts index 26736f5..6709a6e 100644 --- a/server/src/contexts/sales/domain/repository/QuoteRepository.interface.ts +++ b/server/src/contexts/sales/domain/repository/QuoteRepository.interface.ts @@ -1,7 +1,7 @@ /* eslint-disable no-unused-vars */ import { IRepository } from "@/contexts/common/domain/repositories"; import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts"; -import { Quote, QuoteReference } from "../entities"; +import { Quote, QuoteReference, QuoteStatus } from "../entities"; export interface IQuoteRepository extends IRepository { exists(id: UniqueID): Promise; @@ -17,4 +17,6 @@ export interface IQuoteRepository extends IRepository { findLastQuoteByDealerId(dealerId: UniqueID): Promise; findLastReferenceByDealerId(dealerId: UniqueID): Promise; + + updateStatusById(quoteId: UniqueID, newStatus: QuoteStatus): Promise; } diff --git a/server/src/contexts/sales/infrastructure/Quote.repository.ts b/server/src/contexts/sales/infrastructure/Quote.repository.ts index 85e4cec..abe00de 100644 --- a/server/src/contexts/sales/infrastructure/Quote.repository.ts +++ b/server/src/contexts/sales/infrastructure/Quote.repository.ts @@ -3,7 +3,7 @@ import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts"; import { ModelDefined, Transaction } from "sequelize"; import { IQuoteRepository } from "../domain"; -import { Quote, QuoteReference } from "../domain/entities"; +import { Quote, QuoteReference, QuoteStatus } from "../domain/entities"; import { ISalesContext } from "./Sales.context"; import { IQuoteMapper, createQuoteMapper } from "./mappers/quote.mapper"; @@ -33,29 +33,29 @@ export class QuoteRepository extends SequelizeRepository implements IQuot return this._exists("Quote_Model", "reference", reference.toPrimitive()); } - public async create(user: Quote): Promise { - const userData = this.mapper.mapToPersistence(user); - await this._save("Quote_Model", user.id, userData); + public async create(quote: Quote): Promise { + const quoteData = this.mapper.mapToPersistence(quote); + await this._save("Quote_Model", quote.id, quoteData); } - public async update(user: Quote): Promise { + public async update(quote: Quote): Promise { console.time("update"); - const userData = this.mapper.mapToPersistence(user); + const quoteData = this.mapper.mapToPersistence(quote); const QuoteItem_Model: ModelDefined = this._adapter.getModel("QuoteItem_Model"); await Promise.all([ - this._save("Quote_Model", user.id, userData, {}), + this._save("Quote_Model", quote.id, quoteData, {}), QuoteItem_Model.destroy({ where: { - quote_id: userData.id, + quote_id: quoteData.id, }, transaction: this._transaction, force: true, }), ]); - await QuoteItem_Model.bulkCreate(userData.items, { + await QuoteItem_Model.bulkCreate(quoteData.items, { transaction: this._transaction, }); @@ -143,6 +143,21 @@ export class QuoteRepository extends SequelizeRepository implements IQuot const quote = await this.findLastQuoteByDealerId(dealerId); return quote ? quote.reference : null; } + + public async updateStatusById(quoteId: UniqueID, newStatus: QuoteStatus): Promise { + const quoteStatusData = newStatus.toPrimitive(); //this.mapper.mapToPersistence(quote); + const _model = this._adapter.getModel("Quote_Model"); + + await _model.update( + { + status: quoteStatusData, + }, + { + where: { id: quoteId.toPrimitive() }, + transaction: this._transaction, + } + ); + } } export const registerQuoteRepository = (context: ISalesContext) => { diff --git a/server/src/contexts/sales/infrastructure/express/controllers/quotes/index.ts b/server/src/contexts/sales/infrastructure/express/controllers/quotes/index.ts index 5adf695..cfdf99b 100644 --- a/server/src/contexts/sales/infrastructure/express/controllers/quotes/index.ts +++ b/server/src/contexts/sales/infrastructure/express/controllers/quotes/index.ts @@ -3,4 +3,5 @@ export * from "./deleteQuote"; export * from "./getQuote"; export * from "./listQuotes"; export * from "./reportQuote"; +export * from "./setStatusQuote"; export * from "./updateQuote"; diff --git a/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/SetStatusQuote.controller.ts b/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/SetStatusQuote.controller.ts new file mode 100644 index 0000000..77c1c6f --- /dev/null +++ b/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/SetStatusQuote.controller.ts @@ -0,0 +1,103 @@ +import { IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases"; +import { IServerError } from "@/contexts/common/domain/errors"; +import { IInfrastructureError, InfrastructureError } from "@/contexts/common/infrastructure"; +import { ExpressController } from "@/contexts/common/infrastructure/express"; +import { SetStatusQuoteUseCase } from "@/contexts/sales/application"; +import { + ensureIdIsValid, + ensureSetStatusQuote_Request_DTOIsValid, + ISetStatusQuote_Request_DTO, +} from "@shared/contexts"; +import { ISalesContext } from "../../../../Sales.context"; + +export class SetStatusQuoteController extends ExpressController { + private useCase: SetStatusQuoteUseCase; + private context: ISalesContext; + + constructor(props: { useCase: SetStatusQuoteUseCase }, context: ISalesContext) { + super(); + + const { useCase } = props; + this.useCase = useCase; + this.context = context; + } + + async executeImpl(): Promise { + try { + const { quoteId } = this.req.params; + const newStatusDTO: ISetStatusQuote_Request_DTO = this.req.body; + + // Validar ID + const quoteIdOrError = ensureIdIsValid(quoteId); + if (quoteIdOrError.isFailure) { + const errorMessage = "Quote ID is not valid"; + const infraError = InfrastructureError.create( + InfrastructureError.INVALID_INPUT_DATA, + errorMessage, + quoteIdOrError.error + ); + return this.invalidInputError(errorMessage, infraError); + } + + // Validar DTO de datos + const newStatusDTOOrError = ensureSetStatusQuote_Request_DTOIsValid(newStatusDTO); + + if (newStatusDTOOrError.isFailure) { + const errorMessage = "New quote status is not valid"; + const infraError = InfrastructureError.create( + InfrastructureError.INVALID_INPUT_DATA, + errorMessage, + newStatusDTOOrError.error + ); + return this.invalidInputError(errorMessage, infraError); + } + + // Llamar al caso de uso + const result = await this.useCase.execute({ + id: quoteIdOrError.object, + newStatusDTO, + }); + + if (result.isFailure) { + return this._handleExecuteError(result.error); + } + return this.noContent(); + } catch (e: unknown) { + return this.fail(e as IServerError); + } + } + + private _handleExecuteError(error: IUseCaseError) { + let errorMessage: string; + let infraError: IInfrastructureError; + + switch (error.code) { + case UseCaseError.NOT_FOUND_ERROR: + errorMessage = "Quote not found"; + + infraError = InfrastructureError.create( + InfrastructureError.RESOURCE_NOT_FOUND_ERROR, + errorMessage, + error + ); + + return this.notFoundError(errorMessage, infraError); + break; + + case UseCaseError.UNEXCEPTED_ERROR: + errorMessage = error.message; + + infraError = InfrastructureError.create( + InfrastructureError.UNEXCEPTED_ERROR, + errorMessage, + error + ); + return this.internalServerError(errorMessage, infraError); + break; + + default: + errorMessage = error.message; + return this.clientError(errorMessage); + } + } +} diff --git a/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/index.ts b/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/index.ts new file mode 100644 index 0000000..26cbdee --- /dev/null +++ b/server/src/contexts/sales/infrastructure/express/controllers/quotes/setStatusQuote/index.ts @@ -0,0 +1,21 @@ +import { SetStatusQuoteUseCase } from "@/contexts/sales/application"; +import Express from "express"; +import { registerQuoteRepository } from "../../../../Quote.repository"; +import { ISalesContext } from "../../../../Sales.context"; +import { SetStatusQuoteController } from "./SetStatusQuote.controller"; + +export const setStatusQuoteController = ( + req: Express.Request, + res: Express.Response, + next: Express.NextFunction +) => { + const context: ISalesContext = res.locals.context; + + registerQuoteRepository(context); + return new SetStatusQuoteController( + { + useCase: new SetStatusQuoteUseCase(context), + }, + context + ).execute(req, res, next); +}; diff --git a/server/src/infrastructure/express/api/routes/quote.routes.ts b/server/src/infrastructure/express/api/routes/quote.routes.ts index a31802d..eccb78c 100644 --- a/server/src/infrastructure/express/api/routes/quote.routes.ts +++ b/server/src/infrastructure/express/api/routes/quote.routes.ts @@ -4,6 +4,7 @@ import { getQuoteController, listQuotesController, reportQuoteController, + setStatusQuoteController, updateQuoteController, } from "@/contexts/sales/infrastructure/express/controllers"; import { getDealerMiddleware } from "@/contexts/sales/infrastructure/express/middlewares/dealerMiddleware"; @@ -21,6 +22,12 @@ export const QuoteRouter = (appRouter: Express.Router) => { // Reports quoteRoutes.get("/:quoteId/report", checkUser, getDealerMiddleware, reportQuoteController); + // Status + quoteRoutes.put( + "/:quoteId/setStatus", + checkUser, + /*getDealerMiddleware, */ setStatusQuoteController + ); /* quoteRoutes.post("/", isAdmin, createQuoteController); diff --git a/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/ISetStatusQuote_Request.dto.ts b/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/ISetStatusQuote_Request.dto.ts new file mode 100644 index 0000000..8bb23fe --- /dev/null +++ b/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/ISetStatusQuote_Request.dto.ts @@ -0,0 +1,20 @@ +import Joi from "joi"; +import { Result, RuleValidator } from "../../../../../common"; + +export interface ISetStatusQuote_Request_DTO { + newStatus: string; +} + +export function ensureSetStatusQuote_Request_DTOIsValid(quoteDTO: ISetStatusQuote_Request_DTO) { + const schema = Joi.object({ + newStatus: Joi.string(), + }); + + const result = RuleValidator.validate(schema, quoteDTO); + + if (result.isFailure) { + return Result.fail(result.error); + } + + return Result.ok(true); +} diff --git a/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/index.ts b/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/index.ts new file mode 100644 index 0000000..338fd44 --- /dev/null +++ b/shared/lib/contexts/sales/application/dto/Quote/SetStatusQuote.dto/index.ts @@ -0,0 +1 @@ +export * from "./ISetStatusQuote_Request.dto"; diff --git a/shared/lib/contexts/sales/application/dto/Quote/index.ts b/shared/lib/contexts/sales/application/dto/Quote/index.ts index 6cbb1f3..b8ce619 100644 --- a/shared/lib/contexts/sales/application/dto/Quote/index.ts +++ b/shared/lib/contexts/sales/application/dto/Quote/index.ts @@ -1,4 +1,5 @@ export * from "./CreateQuote.dto"; export * from "./GetQuote.dto"; export * from "./ListQuotes.dto"; +export * from "./SetStatusQuote.dto"; export * from "./UpdateQuote.dto";