From c8e7a2c7d905d5b5dce2f5c3ff9e56340b59280e Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 24 Jan 2024 00:00:15 +0200 Subject: [PATCH 1/5] feat(server): convert invoice status after sending mail notification --- packages/server/src/interfaces/SaleInvoice.ts | 12 +++++ packages/server/src/loaders/eventEmitter.ts | 2 + .../Sales/Invoices/DeliverSaleInvoice.ts | 4 +- .../Sales/Invoices/SendSaleInvoiceMail.ts | 36 ++++++++++++-- .../Sales/Invoices/SendSaleInvoiceMailJob.ts | 4 +- .../Invoices/SendSaleInvoiceMailReminder.ts | 23 ++++++++- ...InvoiceChangeStatusOnMailSentSubscriber.ts | 49 +++++++++++++++++++ packages/server/src/subscribers/events.ts | 13 +++-- 8 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts diff --git a/packages/server/src/interfaces/SaleInvoice.ts b/packages/server/src/interfaces/SaleInvoice.ts index 394319e86..61594306a 100644 --- a/packages/server/src/interfaces/SaleInvoice.ts +++ b/packages/server/src/interfaces/SaleInvoice.ts @@ -201,3 +201,15 @@ export interface ISaleInvoiceNotifyPayload { saleInvoiceId: number; messageDTO: SendInvoiceMailDTO; } + +export interface ISaleInvoiceMailSend { + tenantId: number; + saleInvoiceId: number; + messageOptions: SendInvoiceMailDTO; +} + +export interface ISaleInvoiceMailSent { + tenantId: number; + saleInvoiceId: number; + messageOptions: SendInvoiceMailDTO; +} diff --git a/packages/server/src/loaders/eventEmitter.ts b/packages/server/src/loaders/eventEmitter.ts index fa1942b72..5e052f376 100644 --- a/packages/server/src/loaders/eventEmitter.ts +++ b/packages/server/src/loaders/eventEmitter.ts @@ -84,6 +84,7 @@ import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subsc import { BillTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/BillTaxRateValidateSubscriber'; import { WriteBillTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteBillTaxTransactionsSubscriber'; import { SyncItemTaxRateOnEditTaxSubscriber } from '@/services/TaxRates/SyncItemTaxRateOnEditTaxSubscriber'; +import { InvoiceChangeStatusOnMailSentSubscriber } from '@/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber'; export default () => { return new EventPublisher(); @@ -152,6 +153,7 @@ export const susbcribers = () => { // #Invoices InvoicePaymentGLRewriteSubscriber, InvoiceCostGLEntriesSubscriber, + InvoiceChangeStatusOnMailSentSubscriber, BillPaymentsGLEntriesRewriteSubscriber, diff --git a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts index 30ba635a6..f5500a03a 100644 --- a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts +++ b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts @@ -4,7 +4,6 @@ import { ServiceError } from '@/exceptions'; import { ISaleInvoiceDeliveringPayload, ISaleInvoiceEventDeliveredPayload, - ISystemUser, } from '@/interfaces'; import { ERRORS } from './constants'; import { Inject, Service } from 'typedi'; @@ -36,8 +35,7 @@ export class DeliverSaleInvoice { */ public async deliverSaleInvoice( tenantId: number, - saleInvoiceId: number, - authorizedUser: ISystemUser + saleInvoiceId: number ): Promise { const { SaleInvoice } = this.tenancy.models(tenantId); diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts index 05db4f73e..eff8b2603 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts @@ -1,6 +1,6 @@ import { Inject, Service } from 'typedi'; import Mail from '@/lib/Mail'; -import { SendInvoiceMailDTO } from '@/interfaces'; +import { ISaleInvoiceMailSend, SendInvoiceMailDTO } from '@/interfaces'; import { SaleInvoicePdf } from './SaleInvoicePdf'; import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon'; import { @@ -8,6 +8,8 @@ import { DEFAULT_INVOICE_MAIL_SUBJECT, } from './constants'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import events from '@/subscribers/events'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; @Service() export class SendSaleInvoiceMail { @@ -20,6 +22,9 @@ export class SendSaleInvoiceMail { @Inject('agenda') private agenda: any; + @Inject() + private eventPublisher: EventPublisher; + /** * Sends the invoice mail of the given sale invoice. * @param {number} tenantId @@ -29,14 +34,21 @@ export class SendSaleInvoiceMail { public async triggerMail( tenantId: number, saleInvoiceId: number, - messageDTO: SendInvoiceMailDTO + messageOptions: SendInvoiceMailDTO ) { const payload = { tenantId, saleInvoiceId, - messageDTO, + messageOptions, }; await this.agenda.now('sale-invoice-mail-send', payload); + + // Triggers the event `onSaleInvoicePreMailSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onPreMailSend, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); } /** @@ -64,7 +76,7 @@ export class SendSaleInvoiceMail { public async sendMail( tenantId: number, saleInvoiceId: number, - messageDTO: SendInvoiceMailDTO + messageOptions: SendInvoiceMailDTO ) { const defaultMessageOpts = await this.getMailOption( tenantId, @@ -73,7 +85,7 @@ export class SendSaleInvoiceMail { // Merge message opts with default options and validate the incoming options. const messageOpts = parseAndValidateMailOptions( defaultMessageOpts, - messageDTO + messageOptions ); const mail = new Mail() .setSubject(messageOpts.subject) @@ -90,6 +102,20 @@ export class SendSaleInvoiceMail { { filename: 'invoice.pdf', content: invoicePdfBuffer }, ]); } + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailSend, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); + await mail.send(); + + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailSent, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); } } diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts index 3c1e49a6c..9de941f5f 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts @@ -19,11 +19,11 @@ export class SendSaleInvoiceMailJob { * Triggers sending invoice mail. */ private handler = async (job, done: Function) => { - const { tenantId, saleInvoiceId, messageDTO } = job.attrs.data; + const { tenantId, saleInvoiceId, messageOptions } = job.attrs.data; const sendInvoiceMail = Container.get(SendSaleInvoiceMail); try { - await sendInvoiceMail.sendMail(tenantId, saleInvoiceId, messageDTO); + await sendInvoiceMail.sendMail(tenantId, saleInvoiceId, messageOptions); done(); } catch (error) { console.log(error); diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts index f16db0172..7829a3bf2 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts @@ -1,5 +1,9 @@ import { Inject, Service } from 'typedi'; -import { SendInvoiceMailDTO } from '@/interfaces'; +import { + ISaleInvoiceMailSend, + ISaleInvoiceMailSent, + SendInvoiceMailDTO, +} from '@/interfaces'; import Mail from '@/lib/Mail'; import { SaleInvoicePdf } from './SaleInvoicePdf'; import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon'; @@ -8,6 +12,8 @@ import { DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT, } from './constants'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; @Service() export class SendInvoiceMailReminder { @@ -20,6 +26,9 @@ export class SendInvoiceMailReminder { @Inject() private invoiceCommonMail: SendSaleInvoiceMailCommon; + @Inject() + private eventPublisher: EventPublisher; + /** * Triggers the reminder mail of the given sale invoice. * @param {number} tenantId @@ -86,6 +95,18 @@ export class SendInvoiceMailReminder { { filename: 'invoice.pdf', content: invoicePdfBuffer }, ]); } + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSend, { + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); + await mail.send(); + + // Triggers the event `onSaleInvoiceSent`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSent, { + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSent); } } diff --git a/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts b/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts new file mode 100644 index 000000000..fc4392777 --- /dev/null +++ b/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts @@ -0,0 +1,49 @@ +import { Inject, Service } from 'typedi'; +import events from '@/subscribers/events'; +import { ISaleInvoiceMailSent } from '@/interfaces'; +import { DeliverSaleInvoice } from '../DeliverSaleInvoice'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from '../constants'; + +@Service() +export class InvoiceChangeStatusOnMailSentSubscriber { + @Inject() + private markInvoiceDelivedService: DeliverSaleInvoice; + + /** + * Attaches events. + */ + public attach(bus) { + bus.subscribe(events.saleInvoice.onPreMailSend, this.markInvoiceDelivered); + bus.subscribe( + events.saleInvoice.onMailReminderSent, + this.markInvoiceDelivered + ); + } + + /** + * Marks the invoice delivered once the invoice mail sent. + * @param {ISaleInvoiceMailSent} + * @returns {Promise} + */ + private markInvoiceDelivered = async ({ + tenantId, + saleInvoiceId, + messageOptions, + }: ISaleInvoiceMailSent) => { + try { + await this.markInvoiceDelivedService.deliverSaleInvoice( + tenantId, + saleInvoiceId + ); + } catch (error) { + if ( + error instanceof ServiceError && + error.errorType === ERRORS.SALE_INVOICE_ALREADY_DELIVERED + ) { + } else { + throw error; + } + } + }; +} diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index e54f48152..a46c32696 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -131,7 +131,14 @@ export default { onNotifiedSms: 'onSaleInvoiceNotifiedSms', onNotifyMail: 'onSaleInvoiceNotifyMail', - onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail' + onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail', + + onPreMailSend: 'onSaleInvoicePreMailSend', + onMailSend: 'onSaleInvoiceMailSend', + onMailSent: 'onSaleInvoiceMailSent', + + onMailReminderSend: 'onSaleInvoiceMailReminderSend', + onMailReminderSent: 'onSaleInvoiceMailReminderSent', }, /** @@ -164,7 +171,7 @@ export default { onRejecting: 'onSaleEstimateRejecting', onRejected: 'onSaleEstimateRejected', - onNotifyMail: 'onSaleEstimateNotifyMail' + onNotifyMail: 'onSaleEstimateNotifyMail', }, /** @@ -580,6 +587,6 @@ export default { onActivated: 'onTaxRateActivated', onInactivating: 'onTaxRateInactivating', - onInactivated: 'onTaxRateInactivated' + onInactivated: 'onTaxRateInactivated', }, }; From 9d4e7cec9e8d2c627890d1b82ad9130df67ac7ff Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 24 Jan 2024 20:03:04 +0200 Subject: [PATCH 2/5] feat(webapp): add ability to redirect to list to mail dialogs --- .../EstimateMailDialog/EstimateMailDialog.tsx | 8 +++++++- .../EstimateMailDialog/EstimateMailDialogBoot.tsx | 4 ++++ .../EstimateMailDialogContent.tsx | 11 ++++++++--- .../EstimateMailDialog/EstimateMailDialogForm.tsx | 14 +++++++++++--- .../InvoiceMailDialog/InvoiceMailDialog.tsx | 8 +++++++- .../InvoiceMailDialog/InvoiceMailDialogBoot.tsx | 4 ++++ .../InvoiceMailDialog/InvoiceMailDialogContent.tsx | 9 ++++++++- .../InvoiceMailDialog/InvoiceMailDialogForm.tsx | 10 +++++++++- .../PaymentMailDialog/PaymentMailDialog.tsx | 8 +++++++- .../PaymentMailDialog/PaymentMailDialogBoot.tsx | 4 +++- .../PaymentMailDialog/PaymentMailDialogContent.tsx | 7 ++++++- .../PaymentMailDialog/PaymentMailDialogForm.tsx | 13 +++++++++++-- .../ReceiptMailDialog/ReceiptMailDialog.tsx | 8 +++++++- .../ReceiptMailDialog/ReceiptMailDialogBoot.tsx | 4 ++++ .../ReceiptMailDialog/ReceiptMailDialogContent.tsx | 9 +++++++-- .../ReceiptMailDialog/ReceiptMailDialogForm.tsx | 10 +++++++++- 16 files changed, 112 insertions(+), 19 deletions(-) diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx index 9965db833..a90f0e94a 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx @@ -13,7 +13,12 @@ const EstimateMailDialogContent = React.lazy( */ function EstimateMailDialog({ dialogName, - payload: { estimateId = null }, + payload: { + estimateId = null, + + // Redirect to the estimates list after mail submitting. + redirectToEstimatesList = false, + }, isOpen, }) { return ( @@ -29,6 +34,7 @@ function EstimateMailDialog({ diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBoot.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBoot.tsx index d68afb4c5..65b05a9c1 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBoot.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBoot.tsx @@ -6,12 +6,14 @@ import { DialogContent } from '@/components'; interface EstimateMailDialogBootValues { estimateId: number; mailOptions: any; + redirectToEstimatesList: boolean; } const EstimateMailDialagBoot = createContext(); interface EstimateMailDialogBootProps { estimateId: number; + redirectToEstimatesList?: boolean; children: React.ReactNode; } @@ -20,6 +22,7 @@ interface EstimateMailDialogBootProps { */ function EstimateMailDialogBoot({ estimateId, + redirectToEstimatesList, ...props }: EstimateMailDialogBootProps) { const { data: mailOptions, isLoading: isMailOptionsLoading } = @@ -29,6 +32,7 @@ function EstimateMailDialogBoot({ saleEstimateId: estimateId, mailOptions, isMailOptionsLoading, + redirectToEstimatesList, }; return ( diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx index ad67bb048..3eb0af76d 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx @@ -4,14 +4,19 @@ import { EstimateMailDialogForm } from './EstimateMailDialogForm'; interface EstimateMailDialogContentProps { dialogName: string; estimateId: number; + redirectToEstimatesList?: boolean; } export default function EstimateMailDialogContent({ dialogName, estimateId, + redirectToEstimatesList, }: EstimateMailDialogContentProps) { return ( - - + + - ) + ); } diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx index f8811cdbb..4c6e7e943 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx @@ -1,6 +1,8 @@ // @ts-nocheck import { Formik } from 'formik'; import * as R from 'ramda'; +import { Intent } from '@blueprintjs/core'; +import { useHistory } from 'react-router-dom'; import { useEstimateMailDialogBoot } from './EstimateMailDialogBoot'; import { DialogsName } from '@/constants/dialogs'; import withDialogActions from '@/containers/Dialog/withDialogActions'; @@ -12,7 +14,6 @@ import { transformMailFormToInitialValues, transformMailFormToRequest, } from '@/containers/SendMailNotification/utils'; -import { Intent } from '@blueprintjs/core'; import { AppToaster } from '@/components'; const initialFormValues = { @@ -29,7 +30,10 @@ function EstimateMailDialogFormRoot({ closeDialog, }) { const { mutateAsync: sendEstimateMail } = useSendSaleEstimateMail(); - const { mailOptions, saleEstimateId } = useEstimateMailDialogBoot(); + const { mailOptions, saleEstimateId, redirectToEstimatesList } = + useEstimateMailDialogBoot(); + + const history = useHistory(); const initialValues = transformMailFormToInitialValues( mailOptions, @@ -48,8 +52,12 @@ function EstimateMailDialogFormRoot({ }); closeDialog(DialogsName.EstimateMail); setSubmitting(false); + + if (redirectToEstimatesList) { + history.push('/estimates'); + } }) - .catch((error) => { + .catch(() => { setSubmitting(false); closeDialog(DialogsName.EstimateMail); AppToaster.show({ diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx index 63430ce10..1b385b83f 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx @@ -13,7 +13,12 @@ const InvoiceMailDialogContent = React.lazy( */ function InvoiceMailDialog({ dialogName, - payload: { invoiceId = null }, + payload: { + invoiceId = null, + + // Redirects to the invoices list. + redirectToInvoicesList = false, + }, isOpen, }) { return ( @@ -29,6 +34,7 @@ function InvoiceMailDialog({ diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBoot.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBoot.tsx index ae16a0cf2..8c7d5f7e2 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBoot.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBoot.tsx @@ -6,12 +6,14 @@ import { DialogContent } from '@/components'; interface InvoiceMailDialogBootValues { invoiceId: number; mailOptions: any; + redirectToInvoicesList: boolean; } const InvoiceMailDialagBoot = createContext(); interface InvoiceMailDialogBootProps { invoiceId: number; + redirectToInvoicesList?: boolean; children: React.ReactNode; } @@ -20,6 +22,7 @@ interface InvoiceMailDialogBootProps { */ function InvoiceMailDialogBoot({ invoiceId, + redirectToInvoicesList, ...props }: InvoiceMailDialogBootProps) { const { data: mailOptions, isLoading: isMailOptionsLoading } = @@ -29,6 +32,7 @@ function InvoiceMailDialogBoot({ saleInvoiceId: invoiceId, mailOptions, isMailOptionsLoading, + redirectToInvoicesList, }; return ( diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx index 37f3f091f..769a722b6 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx @@ -4,13 +4,20 @@ import { InvoiceMailDialogForm } from './InvoiceMailDialogForm'; interface InvoiceMailDialogContentProps { dialogName: string; invoiceId: number; + + // Redirect to invoices list after submitting the message. + redirectToInvoicesList?: boolean; } export default function InvoiceMailDialogContent({ dialogName, invoiceId, + redirectToInvoicesList, }: InvoiceMailDialogContentProps) { return ( - + ); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx index 794ed890d..697e8e9a1 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx @@ -15,6 +15,7 @@ import { transformMailFormToRequest, transformMailFormToInitialValues, } from '@/containers/SendMailNotification/utils'; +import { useHistory } from 'react-router-dom'; const initialFormValues = { ...initialMailNotificationValues, @@ -29,7 +30,9 @@ function InvoiceMailDialogFormRoot({ // #withDialogActions closeDialog, }) { - const { mailOptions, saleInvoiceId } = useInvoiceMailDialogBoot(); + const history = useHistory(); + const { mailOptions, saleInvoiceId, redirectToInvoicesList } = + useInvoiceMailDialogBoot(); const { mutateAsync: sendInvoiceMail } = useSendSaleInvoiceMail(); const initialValues = transformMailFormToInitialValues( @@ -49,6 +52,11 @@ function InvoiceMailDialogFormRoot({ }); closeDialog(DialogsName.InvoiceMail); setSubmitting(false); + + // Redirect to the dashboard if the option was enabled. + if (redirectToInvoicesList) { + history.push('/invoices'); + } }) .catch(() => { AppToaster.show({ diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog.tsx index 6da51d03e..32c175ed9 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog.tsx @@ -13,7 +13,12 @@ const PaymentMailDialogContent = React.lazy( */ function PaymentMailDialog({ dialogName, - payload: { paymentReceiveId = null }, + payload: { + paymentReceiveId = null, + + // Redirects to the payments list on mail submitting. + redirectToPaymentsList = false, + }, isOpen, }) { return ( @@ -29,6 +34,7 @@ function PaymentMailDialog({ diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogBoot.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogBoot.tsx index aa08bd2e1..5fcbd4afa 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogBoot.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogBoot.tsx @@ -13,6 +13,7 @@ const PaymentMailDialogBootContext = interface PaymentMailDialogBootProps { paymentReceiveId: number; + redirectToPaymentsList: boolean; children: React.ReactNode; } @@ -29,7 +30,8 @@ function PaymentMailDialogBoot({ const provider = { mailOptions, isMailOptionsLoading, - paymentReceiveId + paymentReceiveId, + redirectToPaymentsList }; return ( diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogContent.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogContent.tsx index 12fa57e05..33597cfa9 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogContent.tsx @@ -4,13 +4,18 @@ import { PaymentMailDialogForm } from './PaymentMailDialogForm'; interface PaymentMailDialogContentProps { dialogName: string; paymentReceiveId: number; + redirectToPaymentsList: boolean; } export default function PaymentMailDialogContent({ dialogName, paymentReceiveId, + redirectToPaymentsList, }: PaymentMailDialogContentProps) { return ( - + ); diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogForm.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogForm.tsx index bf0aa578b..f397a8740 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialogForm.tsx @@ -3,7 +3,6 @@ import { Formik, FormikBag } from 'formik'; import * as R from 'ramda'; import { Intent } from '@blueprintjs/core'; import { usePaymentMailDialogBoot } from './PaymentMailDialogBoot'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; import { DialogsName } from '@/constants/dialogs'; import { useSendPaymentReceiveMail } from '@/hooks/query'; import { PaymentMailDialogFormContent } from './PaymentMailDialogFormContent'; @@ -14,6 +13,8 @@ import { transformMailFormToInitialValues, } from '@/containers/SendMailNotification/utils'; import { AppToaster } from '@/components'; +import { useHistory } from 'react-router-dom'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; const initialFormValues = { ...initialMailNotificationValues, @@ -28,9 +29,12 @@ export function PaymentMailDialogFormRoot({ // #withDialogActions closeDialog, }) { - const { mailOptions, paymentReceiveId } = usePaymentMailDialogBoot(); + const { mailOptions, paymentReceiveId, redirectToPaymentsList } = + usePaymentMailDialogBoot(); const { mutateAsync: sendPaymentMail } = useSendPaymentReceiveMail(); + const history = useHistory(); + const initialValues = transformMailFormToInitialValues( mailOptions, initialFormValues, @@ -51,6 +55,11 @@ export function PaymentMailDialogFormRoot({ }); setSubmitting(false); closeDialog(DialogsName.PaymentMail); + + // Redirects to payments list if the option is enabled. + if (redirectToPaymentsList) { + history.push('/payment-receives'); + } }) .catch(() => { AppToaster.show({ diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx index a64ad5531..eb68d7d37 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx @@ -13,7 +13,12 @@ const ReceiptMailDialogContent = React.lazy( */ function ReceiptMailDialog({ dialogName, - payload: { receiptId = null }, + payload: { + receiptId = null, + + // Redirects to receipts list after mail submitting. + redirectToReceiptsList = false, + }, isOpen, }) { return ( @@ -29,6 +34,7 @@ function ReceiptMailDialog({ diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBoot.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBoot.tsx index 09eeb55f1..54f7200db 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBoot.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBoot.tsx @@ -6,6 +6,7 @@ import { DialogContent } from '@/components'; interface ReceiptMailDialogBootValues { receiptId: number; mailOptions: any; + redirectToReceiptsList: boolean; } const ReceiptMailDialogBootContext = @@ -14,6 +15,7 @@ const ReceiptMailDialogBootContext = interface ReceiptMailDialogBootProps { receiptId: number; children: React.ReactNode; + redirectToReceiptsList?: boolean; } /** @@ -21,6 +23,7 @@ interface ReceiptMailDialogBootProps { */ function ReceiptMailDialogBoot({ receiptId, + redirectToReceiptsList = false, ...props }: ReceiptMailDialogBootProps) { const { data: mailOptions, isLoading: isMailOptionsLoading } = @@ -30,6 +33,7 @@ function ReceiptMailDialogBoot({ saleReceiptId: receiptId, mailOptions, isMailOptionsLoading, + redirectToReceiptsList, }; return ( diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx index 955620f86..586de745c 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx @@ -3,15 +3,20 @@ import { ReceiptMailDialogBoot } from './ReceiptMailDialogBoot'; import { ReceiptMailDialogForm } from './ReceiptMailDialogForm'; interface ReceiptMailDialogContentProps { - dialogName: string + dialogName: string; receiptId: number; + redirectToReceiptsList?: boolean; } export default function ReceiptMailDialogContent({ dialogName, receiptId, + redirectToReceiptsList = false, }: ReceiptMailDialogContentProps) { return ( - + ); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx index fb9b845af..d46ea7eb0 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx @@ -2,6 +2,7 @@ import { Formik, FormikBag } from 'formik'; import * as R from 'ramda'; import { Intent } from '@blueprintjs/core'; +import { useHistory } from 'react-router-dom'; import { useReceiptMailDialogBoot } from './ReceiptMailDialogBoot'; import withDialogActions from '@/containers/Dialog/withDialogActions'; import { DialogsName } from '@/constants/dialogs'; @@ -24,9 +25,12 @@ interface ReceiptMailFormValues extends MailNotificationFormValues { } function ReceiptMailDialogFormRoot({ closeDialog }) { - const { mailOptions, saleReceiptId } = useReceiptMailDialogBoot(); + const { mailOptions, saleReceiptId, redirectToReceiptsList } = + useReceiptMailDialogBoot(); const { mutateAsync: sendReceiptMail } = useSendSaleReceiptMail(); + const history = useHistory(); + // Transformes mail options to initial form values. const initialValues = transformMailFormToInitialValues( mailOptions, @@ -48,6 +52,10 @@ function ReceiptMailDialogFormRoot({ closeDialog }) { }); closeDialog(DialogsName.ReceiptMail); setSubmitting(false); + + if (redirectToReceiptsList) { + history.push('/receipts'); + } }) .catch(() => { AppToaster.show({ From 760dbc6cfc7d890f99c08a73cf76cb5e72801db1 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Thu, 25 Jan 2024 21:52:07 +0200 Subject: [PATCH 3/5] feat(server): change estimate and receipts status once delivering mail --- .../server/src/interfaces/PaymentReceive.ts | 6 +++ .../server/src/interfaces/SaleEstimate.ts | 8 +++- packages/server/src/interfaces/SaleReceipt.ts | 6 +++ packages/server/src/loaders/eventEmitter.ts | 9 +++- .../Accounts/AccountTransactionTransformer.ts | 1 - .../src/services/Accounts/AccountTransform.ts | 2 +- .../src/services/Accounts/ActivateAccount.ts | 4 -- .../Sales/Estimates/SendSaleEstimateMail.ts | 15 ++++++- .../SaleEstimateMarkApprovedOnMailSent.ts | 43 +++++++++++++++++++ .../PaymentReceiveMailNotification.ts | 13 ++++++ .../Receipts/SaleReceiptMailNotification.ts | 22 ++++++++-- .../SaleReceiptCostGLEntriesSubscriber.ts | 2 +- ...aleReceiptMarkClosedOnMailSentSubcriber.ts | 41 ++++++++++++++++++ packages/server/src/subscribers/events.ts | 12 ++++++ 14 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 packages/server/src/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent.ts create mode 100644 packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber.ts diff --git a/packages/server/src/interfaces/PaymentReceive.ts b/packages/server/src/interfaces/PaymentReceive.ts index 2926d923c..329d0d944 100644 --- a/packages/server/src/interfaces/PaymentReceive.ts +++ b/packages/server/src/interfaces/PaymentReceive.ts @@ -173,3 +173,9 @@ export type IPaymentReceiveGLCommonEntry = Pick< export interface PaymentReceiveMailOpts extends CommonMailOptions {} export interface PaymentReceiveMailOptsDTO extends CommonMailOptionsDTO {} + +export interface PaymentReceiveMailPresendEvent { + tenantId: number; + paymentReceiveId: number; + messageOptions: PaymentReceiveMailOptsDTO; +} diff --git a/packages/server/src/interfaces/SaleEstimate.ts b/packages/server/src/interfaces/SaleEstimate.ts index 171c8a0d1..9ac17295c 100644 --- a/packages/server/src/interfaces/SaleEstimate.ts +++ b/packages/server/src/interfaces/SaleEstimate.ts @@ -132,4 +132,10 @@ export interface SaleEstimateMailOptions extends CommonMailOptions { export interface SaleEstimateMailOptionsDTO extends CommonMailOptionsDTO { attachEstimate?: boolean; -} \ No newline at end of file +} + +export interface ISaleEstimateMailPresendEvent { + tenantId: number; + saleEstimateId: number; + messageOptions: SaleEstimateMailOptionsDTO; +} diff --git a/packages/server/src/interfaces/SaleReceipt.ts b/packages/server/src/interfaces/SaleReceipt.ts index 1e8ffa98e..8904767c6 100644 --- a/packages/server/src/interfaces/SaleReceipt.ts +++ b/packages/server/src/interfaces/SaleReceipt.ts @@ -143,3 +143,9 @@ export interface SaleReceiptMailOpts extends CommonMailOptions { export interface SaleReceiptMailOptsDTO extends CommonMailOptionsDTO { attachReceipt?: boolean; } + +export interface ISaleReceiptMailPresend { + tenantId: number; + saleReceiptId: number; + messageOptions: SaleReceiptMailOptsDTO; +} diff --git a/packages/server/src/loaders/eventEmitter.ts b/packages/server/src/loaders/eventEmitter.ts index 5e052f376..5d3269646 100644 --- a/packages/server/src/loaders/eventEmitter.ts +++ b/packages/server/src/loaders/eventEmitter.ts @@ -85,6 +85,8 @@ import { BillTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/B import { WriteBillTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteBillTaxTransactionsSubscriber'; import { SyncItemTaxRateOnEditTaxSubscriber } from '@/services/TaxRates/SyncItemTaxRateOnEditTaxSubscriber'; import { InvoiceChangeStatusOnMailSentSubscriber } from '@/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber'; +import { SaleReceiptMarkClosedOnMailSentSubcriber } from '@/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber'; +import { SaleEstimateMarkApprovedOnMailSent } from '@/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent'; export default () => { return new EventPublisher(); @@ -105,8 +107,12 @@ export const susbcribers = () => { InventorySubscriber, CustomerWriteGLOpeningBalanceSubscriber, VendorsWriteGLOpeningSubscriber, + + // # Estimate SaleEstimateAutoSerialSubscriber, SaleEstimateSmsNotificationSubscriber, + SaleEstimateMarkApprovedOnMailSent, + ExpensesWriteGLSubscriber, SaleReceiptAutoSerialSubscriber, SaleInvoiceAutoIncrementSubscriber, @@ -159,6 +165,7 @@ export const susbcribers = () => { // # Receipts SaleReceiptCostGLEntriesSubscriber, + SaleReceiptMarkClosedOnMailSentSubcriber, // Transaction locking. SalesTransactionLockingGuardSubscriber, @@ -201,6 +208,6 @@ export const susbcribers = () => { BillTaxRateValidateSubscriber, WriteBillTaxTransactionsSubscriber, - SyncItemTaxRateOnEditTaxSubscriber + SyncItemTaxRateOnEditTaxSubscriber, ]; }; diff --git a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts index 857fe5ccc..d0e3e487f 100644 --- a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts +++ b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts @@ -1,6 +1,5 @@ import { IAccountTransaction } from '@/interfaces'; import { Transformer } from '@/lib/Transformer/Transformer'; -import { transaction } from 'objection'; export default class AccountTransactionTransformer extends Transformer { /** diff --git a/packages/server/src/services/Accounts/AccountTransform.ts b/packages/server/src/services/Accounts/AccountTransform.ts index 9297994be..98e19553e 100644 --- a/packages/server/src/services/Accounts/AccountTransform.ts +++ b/packages/server/src/services/Accounts/AccountTransform.ts @@ -34,7 +34,7 @@ export class AccountTransformer extends Transformer { /** * Retrieve formatted account amount. - * @param {IAccount} invoice + * @param {IAccount} invoice * @returns {string} */ protected formattedAmount = (account: IAccount): string => { diff --git a/packages/server/src/services/Accounts/ActivateAccount.ts b/packages/server/src/services/Accounts/ActivateAccount.ts index 1fcd104f6..26afd836d 100644 --- a/packages/server/src/services/Accounts/ActivateAccount.ts +++ b/packages/server/src/services/Accounts/ActivateAccount.ts @@ -5,7 +5,6 @@ import { IAccountEventActivatedPayload } from '@/interfaces'; import events from '@/subscribers/events'; import UnitOfWork from '@/services/UnitOfWork'; import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; -import { CommandAccountValidators } from './CommandAccountValidators'; @Service() export class ActivateAccount { @@ -18,9 +17,6 @@ export class ActivateAccount { @Inject() private uow: UnitOfWork; - @Inject() - private validator: CommandAccountValidators; - /** * Activates/Inactivates the given account. * @param {number} tenantId diff --git a/packages/server/src/services/Sales/Estimates/SendSaleEstimateMail.ts b/packages/server/src/services/Sales/Estimates/SendSaleEstimateMail.ts index 258496306..0ac580b90 100644 --- a/packages/server/src/services/Sales/Estimates/SendSaleEstimateMail.ts +++ b/packages/server/src/services/Sales/Estimates/SendSaleEstimateMail.ts @@ -8,11 +8,14 @@ import { import { SaleEstimatesPdf } from './SaleEstimatesPdf'; import { GetSaleEstimate } from './GetSaleEstimate'; import { + ISaleEstimateMailPresendEvent, SaleEstimateMailOptions, SaleEstimateMailOptionsDTO, } from '@/interfaces'; import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; @Service() export class SendSaleEstimateMail { @@ -31,6 +34,9 @@ export class SendSaleEstimateMail { @Inject('agenda') private agenda: any; + @Inject() + private eventPublisher: EventPublisher; + /** * Triggers the reminder mail of the given sale estimate. * @param {number} tenantId - @@ -49,6 +55,13 @@ export class SendSaleEstimateMail { messageOptions, }; await this.agenda.now('sale-estimate-mail-send', payload); + + // Triggers `onSaleEstimatePreMailSend` event. + await this.eventPublisher.emitAsync(events.saleEstimate.onPreMailSend, { + tenantId, + saleEstimateId, + messageOptions, + } as ISaleEstimateMailPresendEvent); } /** @@ -99,7 +112,7 @@ export class SendSaleEstimateMail { return { ...mailOptions, data: formatterData, - attachEstimate: true + attachEstimate: true, }; }; diff --git a/packages/server/src/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent.ts b/packages/server/src/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent.ts new file mode 100644 index 000000000..99caa3952 --- /dev/null +++ b/packages/server/src/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent.ts @@ -0,0 +1,43 @@ +import { Inject, Service } from 'typedi'; +import events from '@/subscribers/events'; +import { ISaleEstimateMailPresendEvent } from '@/interfaces'; +import { DeliverSaleEstimate } from '../DeliverSaleEstimate'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from '../constants'; + +@Service() +export class SaleEstimateMarkApprovedOnMailSent { + @Inject() + private deliverEstimateService: DeliverSaleEstimate; + + /** + * Attaches events. + */ + public attach(bus) { + bus.subscribe(events.saleEstimate.onPreMailSend, this.markEstimateApproved); + } + + /** + * Marks the given estimate approved on submitting mail. + * @param {ISaleEstimateMailPresendEvent} + */ + private markEstimateApproved = async ({ + tenantId, + saleEstimateId, + }: ISaleEstimateMailPresendEvent) => { + try { + await this.deliverEstimateService.deliverSaleEstimate( + tenantId, + saleEstimateId + ); + } catch (error) { + if ( + error instanceof ServiceError && + error.errorType === ERRORS.SALE_ESTIMATE_ALREADY_DELIVERED + ) { + } else { + throw error; + } + } + }; +} diff --git a/packages/server/src/services/Sales/PaymentReceives/PaymentReceiveMailNotification.ts b/packages/server/src/services/Sales/PaymentReceives/PaymentReceiveMailNotification.ts index acb1ea7a1..bd8d4fa64 100644 --- a/packages/server/src/services/Sales/PaymentReceives/PaymentReceiveMailNotification.ts +++ b/packages/server/src/services/Sales/PaymentReceives/PaymentReceiveMailNotification.ts @@ -2,6 +2,7 @@ import { Inject, Service } from 'typedi'; import { PaymentReceiveMailOpts, PaymentReceiveMailOptsDTO, + PaymentReceiveMailPresendEvent, SendInvoiceMailDTO, } from '@/interfaces'; import Mail from '@/lib/Mail'; @@ -13,6 +14,8 @@ import { import { GetPaymentReceive } from './GetPaymentReceive'; import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; @Service() export class SendPaymentReceiveMailNotification { @@ -28,6 +31,9 @@ export class SendPaymentReceiveMailNotification { @Inject('agenda') private agenda: any; + @Inject() + private eventPublisher: EventPublisher; + /** * Sends the mail of the given payment receive. * @param {number} tenantId @@ -46,6 +52,13 @@ export class SendPaymentReceiveMailNotification { messageDTO, }; await this.agenda.now('payment-receive-mail-send', payload); + + // Triggers `onPaymentReceivePreMailSend` event. + await this.eventPublisher.emitAsync(events.paymentReceive.onPreMailSend, { + tenantId, + paymentReceiveId, + messageOptions: messageDTO, + } as PaymentReceiveMailPresendEvent); } /** diff --git a/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts b/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts index 572bed2f8..24add40cc 100644 --- a/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts +++ b/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts @@ -7,9 +7,15 @@ import { DEFAULT_RECEIPT_MAIL_CONTENT, DEFAULT_RECEIPT_MAIL_SUBJECT, } from './constants'; -import { SaleReceiptMailOpts, SaleReceiptMailOptsDTO } from '@/interfaces'; +import { + ISaleReceiptMailPresend, + SaleReceiptMailOpts, + SaleReceiptMailOptsDTO, +} from '@/interfaces'; import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; @Service() export class SaleReceiptMailNotification { @@ -25,6 +31,9 @@ export class SaleReceiptMailNotification { @Inject() private contactMailNotification: ContactMailNotification; + @Inject() + private eventPublisher: EventPublisher; + @Inject('agenda') private agenda: any; @@ -37,14 +46,21 @@ export class SaleReceiptMailNotification { public async triggerMail( tenantId: number, saleReceiptId: number, - messageOpts: SaleReceiptMailOptsDTO + messageOptions: SaleReceiptMailOptsDTO ) { const payload = { tenantId, saleReceiptId, - messageOpts, + messageOpts: messageOptions, }; await this.agenda.now('sale-receipt-mail-send', payload); + + // Triggers the event `onSaleReceiptPreMailSend`. + await this.eventPublisher.emitAsync(events.saleReceipt.onPreMailSend, { + tenantId, + saleReceiptId, + messageOptions, + } as ISaleReceiptMailPresend); } /** diff --git a/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptCostGLEntriesSubscriber.ts b/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptCostGLEntriesSubscriber.ts index 5e6311005..39590198b 100644 --- a/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptCostGLEntriesSubscriber.ts +++ b/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptCostGLEntriesSubscriber.ts @@ -6,7 +6,7 @@ import { SaleReceiptCostGLEntries } from '../SaleReceiptCostGLEntries'; @Service() export class SaleReceiptCostGLEntriesSubscriber { @Inject() - saleReceiptCostEntries: SaleReceiptCostGLEntries; + private saleReceiptCostEntries: SaleReceiptCostGLEntries; /** * Attaches events. diff --git a/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber.ts b/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber.ts new file mode 100644 index 000000000..3a8d26394 --- /dev/null +++ b/packages/server/src/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber.ts @@ -0,0 +1,41 @@ +import { ISaleReceiptMailPresend } from '@/interfaces'; +import events from '@/subscribers/events'; +import { CloseSaleReceipt } from '../CloseSaleReceipt'; +import { Inject, Service } from 'typedi'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from '../constants'; + +@Service() +export class SaleReceiptMarkClosedOnMailSentSubcriber { + @Inject() + private closeReceiptService: CloseSaleReceipt; + + /** + * Attaches events. + */ + public attach(bus) { + bus.subscribe(events.saleReceipt.onPreMailSend, this.markReceiptClosed); + } + + /** + * Marks the sale receipt closed on submitting mail. + * @param {ISaleReceiptMailPresend} + */ + private markReceiptClosed = async ({ + tenantId, + saleReceiptId, + messageOptions, + }: ISaleReceiptMailPresend) => { + try { + await this.closeReceiptService.closeSaleReceipt(tenantId, saleReceiptId); + } catch (error) { + if ( + error instanceof ServiceError && + error.errorType === ERRORS.SALE_RECEIPT_IS_ALREADY_CLOSED + ) { + } else { + throw error; + } + } + }; +} diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index a46c32696..882027f98 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -172,6 +172,10 @@ export default { onRejected: 'onSaleEstimateRejected', onNotifyMail: 'onSaleEstimateNotifyMail', + + onPreMailSend: 'onSaleEstimatePreMailSend', + onMailSend: 'onSaleEstimateMailSend', + onMailSent: 'onSaleEstimateMailSend', }, /** @@ -195,6 +199,10 @@ export default { onNotifySms: 'onSaleReceiptNotifySms', onNotifiedSms: 'onSaleReceiptNotifiedSms', + + onPreMailSend: 'onSaleReceiptPreMailSend', + onMailSend: 'onSaleReceiptMailSend', + onMailSent: 'onSaleReceiptMailSent', }, /** @@ -215,6 +223,10 @@ export default { onNotifySms: 'onPaymentReceiveNotifySms', onNotifiedSms: 'onPaymentReceiveNotifiedSms', + + onPreMailSend: 'onPaymentReceivePreMailSend', + onMailSend: 'onPaymentReceiveMailSend', + onMailSent: 'onPaymentReceiveMailSent', }, /** From 63708ae839b91b2c802c171d91c1bae9df9c710b Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Thu, 25 Jan 2024 21:56:18 +0200 Subject: [PATCH 4/5] feat(webapp): showing up mail popup once saving invoice, receipt and estimate --- packages/webapp/src/constants/dialogs.ts | 4 ++ .../Dialogs/EstimateFormMailDeliverDialog.tsx | 39 ++++++++++++++++++ .../EstimateFormMailDeliverDialogContent.tsx | 40 +++++++++++++++++++ .../EstimateForm/EstimateFloatingActions.tsx | 2 +- .../Estimates/EstimateForm/EstimateForm.tsx | 13 +++++- .../EstimateForm/EstimateFormDialogs.tsx | 5 +++ .../EstimateMailDialog/EstimateMailDialog.tsx | 19 +++------ .../EstimateMailDialogBody.tsx | 33 +++++++++++++++ .../EstimateMailDialogContent.tsx | 18 ++++----- .../EstimateMailDialogForm.tsx | 12 +++--- .../InvoiceFormMailDeliverDialog.tsx | 39 ++++++++++++++++++ .../InvoiceFormMailDeliverDialogContent.tsx | 40 +++++++++++++++++++ .../InvoiceForm/InvoiceFloatingActions.tsx | 8 ++-- .../Invoices/InvoiceForm/InvoiceForm.tsx | 18 ++++++++- .../InvoiceForm/InvoiceFormDialogs.tsx | 15 ++++--- .../InvoiceMailDialog/InvoiceMailDialog.tsx | 20 +++------- .../InvoiceMailDialogBody.tsx | 36 +++++++++++++++++ .../InvoiceMailDialogContent.tsx | 22 +++++----- .../InvoiceMailDialogForm.tsx | 26 ++---------- .../Sales/Invoices/InvoiceMailDialog/index.ts | 3 +- .../Dialogs/ReceiptFormMailDeliverDialog.tsx | 39 ++++++++++++++++++ .../ReceiptFormMailDeliverDialogContent.tsx | 40 +++++++++++++++++++ .../Receipts/ReceiptForm/ReceiptForm.tsx | 21 +++++++--- .../ReceiptForm/ReceiptFormDialogs.tsx | 5 +++ .../ReceiptFormFloatingActions.tsx | 2 +- .../ReceiptMailDialog/ReceiptMailDialog.tsx | 19 +++------ .../ReceiptMailDialogBody.tsx | 33 +++++++++++++++ .../ReceiptMailDialogContent.tsx | 20 +++++----- .../ReceiptMailDialogForm.tsx | 29 ++++++-------- 29 files changed, 482 insertions(+), 138 deletions(-) create mode 100644 packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialog.tsx create mode 100644 packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialogContent.tsx create mode 100644 packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBody.tsx create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialog.tsx create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialogContent.tsx create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBody.tsx create mode 100644 packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialog.tsx create mode 100644 packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialogContent.tsx create mode 100644 packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBody.tsx diff --git a/packages/webapp/src/constants/dialogs.ts b/packages/webapp/src/constants/dialogs.ts index c9bb52a0e..e7aa4d324 100644 --- a/packages/webapp/src/constants/dialogs.ts +++ b/packages/webapp/src/constants/dialogs.ts @@ -53,4 +53,8 @@ export enum DialogsName { EstimateMail = 'estimate-mail', ReceiptMail = 'receipt-mail', PaymentMail = 'payment-mail', + + InvoiceFormMailDeliver = 'InvoiceFormMailDeliver', + EstimateFormMailDeliver = 'EstimateFormMailDeliver', + ReceiptFormMailDeliver = 'ReceiptFormMailDeliver', } diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialog.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialog.tsx new file mode 100644 index 000000000..6a0b832c3 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialog.tsx @@ -0,0 +1,39 @@ +// @ts-nocheck +import React from 'react'; +import { Dialog, DialogSuspense } from '@/components'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import { compose } from '@/utils'; + +const EstimateFormMailDeliverDialogContent = React.lazy( + () => import('./EstimateFormMailDeliverDialogContent'), +); + +/** + * Estimate mail dialog. + */ +function EstimateFormMailDeliverDialog({ + dialogName, + payload: { estimateId = null }, + isOpen, +}) { + return ( + + + + + + ); +} + +export default compose(withDialogRedux())(EstimateFormMailDeliverDialog); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialogContent.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialogContent.tsx new file mode 100644 index 000000000..e77e3ee99 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/Dialogs/EstimateFormMailDeliverDialogContent.tsx @@ -0,0 +1,40 @@ +// @ts-nocheck +import * as R from 'ramda'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import { useHistory } from 'react-router-dom'; +import EstimateMailDialogContent from '../../EstimateMailDialog/EstimateMailDialogContent'; +import { DialogsName } from '@/constants/dialogs'; + +interface EstimateFormDeliverDialogContent { + estimateId: number; +} + +function EstimateFormDeliverDialogContentRoot({ + estimateId, + + // #withDialogActions + closeDialog, +}: EstimateFormDeliverDialogContent) { + const history = useHistory(); + + const handleSubmit = () => { + closeDialog(DialogsName.EstimateFormMailDeliver); + history.push('/estimates'); + }; + const handleCancel = () => { + closeDialog(DialogsName.EstimateFormMailDeliver); + history.push('/estimates'); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)( + EstimateFormDeliverDialogContentRoot, +); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx index df212c38c..474730d93 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx @@ -29,7 +29,7 @@ export default function EstimateFloatingActions() { // Handle submit & deliver button click. const handleSubmitDeliverBtnClick = (event) => { - setSubmitPayload({ redirect: true, deliver: true }); + setSubmitPayload({ redirect: false, deliverViaMail: true }); submitForm(); }; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx index aff0888d6..b1e665d3d 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx @@ -36,11 +36,16 @@ import { handleErrors, resetFormState, } from './utils'; +import { DialogsName } from '@/constants/dialogs'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; /** * Estimate form. */ function EstimateForm({ + // #withDialogActions + openDialog, + // #withSettings estimateNextNumber, estimateNumberPrefix, @@ -108,7 +113,7 @@ function EstimateForm({ delivered: submitPayload.deliver, }; // Handle the request success. - const onSuccess = (response) => { + const onSuccess = (res) => { AppToaster.show({ message: intl.get( isNewMode @@ -126,6 +131,11 @@ function EstimateForm({ if (submitPayload.resetForm) { resetFormState({ resetForm, initialValues, values }); } + if (submitPayload.deliverViaMail) { + openDialog(DialogsName.EstimateFormMailDeliver, { + estimateId: res.data.id, + }); + } }; // Handle the request error. const onError = ({ @@ -180,6 +190,7 @@ function EstimateForm({ } export default compose( + withDialogActions, withSettings(({ estimatesSettings }) => ({ estimateNextNumber: estimatesSettings?.nextNumber, estimateNumberPrefix: estimatesSettings?.numberPrefix, diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormDialogs.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormDialogs.tsx index aa1c165a1..a50326486 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormDialogs.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormDialogs.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { useFormikContext } from 'formik'; import EstimateNumberDialog from '@/containers/Dialogs/EstimateNumberDialog'; +import EstimateFormMailDeliverDialog from './Dialogs/EstimateFormMailDeliverDialog'; +import { DialogsName } from '@/constants/dialogs'; /** * Estimate form dialogs. @@ -25,6 +27,9 @@ export default function EstimateFormDialogs() { dialogName={'estimate-number-form'} onConfirm={handleEstimateNumberFormConfirm} /> + ); } diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx index a90f0e94a..0d13e07fb 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog.tsx @@ -4,21 +4,16 @@ import { Dialog, DialogSuspense } from '@/components'; import withDialogRedux from '@/components/DialogReduxConnect'; import { compose } from '@/utils'; -const EstimateMailDialogContent = React.lazy( - () => import('./EstimateMailDialogContent'), +const EstimateMailDialogBody = React.lazy( + () => import('./EstimateMailDialogBody'), ); /** - * Invoice mail dialog. + * Estimate mail dialog. */ function EstimateMailDialog({ dialogName, - payload: { - estimateId = null, - - // Redirect to the estimates list after mail submitting. - redirectToEstimatesList = false, - }, + payload: { estimateId = null }, isOpen, }) { return ( @@ -31,11 +26,7 @@ function EstimateMailDialog({ style={{ width: 600 }} > - + ); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBody.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBody.tsx new file mode 100644 index 000000000..2fa1c0472 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogBody.tsx @@ -0,0 +1,33 @@ +// @ts-nocheck +import * as R from 'ramda'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import EstimateMailDialogContent from './EstimateMailDialogContent'; +import { DialogsName } from '@/constants/dialogs'; + +interface EstimateMailDialogBodyProps { + estimateId: number; +} + +function EstimateMailDialogBodyRoot({ + estimateId, + + // #withDialogActions + closeDialog, +}: EstimateMailDialogBodyProps) { + const handleSubmit = () => { + closeDialog(DialogsName.EstimateMail); + }; + const handleCancelClick = () => { + closeDialog(DialogsName.EstimateMail); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)(EstimateMailDialogBodyRoot); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx index 3eb0af76d..c673f71c6 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogContent.tsx @@ -2,21 +2,21 @@ import { EstimateMailDialogBoot } from './EstimateMailDialogBoot'; import { EstimateMailDialogForm } from './EstimateMailDialogForm'; interface EstimateMailDialogContentProps { - dialogName: string; estimateId: number; - redirectToEstimatesList?: boolean; + onFormSubmit?: () => void; + onCancelClick?: () => void; } export default function EstimateMailDialogContent({ - dialogName, estimateId, - redirectToEstimatesList, + onFormSubmit, + onCancelClick, }: EstimateMailDialogContentProps) { return ( - - + + ); } diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx index 4c6e7e943..8f51add43 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx @@ -2,7 +2,6 @@ import { Formik } from 'formik'; import * as R from 'ramda'; import { Intent } from '@blueprintjs/core'; -import { useHistory } from 'react-router-dom'; import { useEstimateMailDialogBoot } from './EstimateMailDialogBoot'; import { DialogsName } from '@/constants/dialogs'; import withDialogActions from '@/containers/Dialog/withDialogActions'; @@ -26,6 +25,9 @@ interface EstimateMailFormValues extends MailNotificationFormValues { } function EstimateMailDialogFormRoot({ + onFormSubmit, + onCancelClick, + // #withDialogClose closeDialog, }) { @@ -33,8 +35,6 @@ function EstimateMailDialogFormRoot({ const { mailOptions, saleEstimateId, redirectToEstimatesList } = useEstimateMailDialogBoot(); - const history = useHistory(); - const initialValues = transformMailFormToInitialValues( mailOptions, initialFormValues, @@ -52,10 +52,7 @@ function EstimateMailDialogFormRoot({ }); closeDialog(DialogsName.EstimateMail); setSubmitting(false); - - if (redirectToEstimatesList) { - history.push('/estimates'); - } + onFormSubmit && onFormSubmit(); }) .catch(() => { setSubmitting(false); @@ -64,6 +61,7 @@ function EstimateMailDialogFormRoot({ message: 'Something went wrong.', intent: Intent.DANGER, }); + onCancelClick && onCancelClick(); }); }; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialog.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialog.tsx new file mode 100644 index 000000000..f6ceb38f8 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialog.tsx @@ -0,0 +1,39 @@ +// @ts-nocheck +import React from 'react'; +import { Dialog, DialogSuspense } from '@/components'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import { compose } from '@/utils'; + +const InvoiceFormMailDeliverDialogContent = React.lazy( + () => import('./InvoiceFormMailDeliverDialogContent'), +); + +/** + * Invoice mail dialog. + */ +function InvoiceFormMailDeliverDialog({ + dialogName, + payload: { invoiceId = null }, + isOpen, +}) { + return ( + + + + + + ); +} + +export default compose(withDialogRedux())(InvoiceFormMailDeliverDialog); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialogContent.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialogContent.tsx new file mode 100644 index 000000000..8ce5e7c12 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialogContent.tsx @@ -0,0 +1,40 @@ +// @ts-nocheck +import * as R from 'ramda'; +import { useHistory } from 'react-router-dom'; +import InvoiceMailDialogContent from '../../../InvoiceMailDialog/InvoiceMailDialogContent'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import { DialogsName } from '@/constants/dialogs'; + +interface InvoiceFormDeliverDialogContent { + invoiceId: number; +} + +function InvoiceFormDeliverDialogContentRoot({ + invoiceId, + + // #withDialogActions + closeDialog, +}: InvoiceFormDeliverDialogContent) { + const history = useHistory(); + + const handleSubmit = () => { + history.push('/invoices'); + closeDialog(DialogsName.InvoiceFormMailDeliver); + }; + const handleCancel = () => { + history.push('/invoices'); + closeDialog(DialogsName.InvoiceFormMailDeliver); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)( + InvoiceFormDeliverDialogContentRoot, +); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx index e212c8b7d..0a9a72913 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx @@ -30,19 +30,19 @@ export default function InvoiceFloatingActions() { const { setSubmitPayload, invoice } = useInvoiceFormContext(); // Handle submit & deliver button click. - const handleSubmitDeliverBtnClick = (event) => { - setSubmitPayload({ redirect: true, deliver: true }); + const handleSubmitDeliverBtnClick = () => { + setSubmitPayload({ redirectToEdit: true, deliverViaMail: true }); submitForm(); }; // Handle submit, deliver & new button click. - const handleSubmitDeliverAndNewBtnClick = (event) => { + const handleSubmitDeliverAndNewBtnClick = () => { setSubmitPayload({ redirect: false, deliver: true, resetForm: true }); submitForm(); }; // Handle submit, deliver & continue editing button click. - const handleSubmitDeliverContinueEditingBtnClick = (event) => { + const handleSubmitDeliverContinueEditingBtnClick = () => { setSubmitPayload({ redirect: false, deliver: true }); submitForm(); }; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx index 6b9f234ac..c47f7bc53 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx @@ -34,12 +34,20 @@ import { transformValueToRequest, resetFormState, } from './utils'; -import { InvoiceExchangeRateSync, InvoiceNoSyncSettingsToForm } from './components'; +import { + InvoiceExchangeRateSync, + InvoiceNoSyncSettingsToForm, +} from './components'; +import { DialogsName } from '@/constants/dialogs'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; /** * Invoice form. */ function InvoiceForm({ + // #withDialogActions + openDialog, + // #withSettings invoiceNextNumber, invoiceNumberPrefix, @@ -111,7 +119,7 @@ function InvoiceForm({ from_estimate_id: estimateId, }; // Handle the request success. - const onSuccess = () => { + const onSuccess = (res) => { AppToaster.show({ message: intl.get( isNewMode @@ -123,6 +131,11 @@ function InvoiceForm({ }); setSubmitting(false); + if (submitPayload.deliverViaMail) { + openDialog(DialogsName.InvoiceFormMailDeliver, { + invoiceId: res.data.id, + }); + } if (submitPayload.redirect) { history.push('/invoices'); } @@ -201,4 +214,5 @@ export default compose( invoiceTermsConditions: invoiceSettings?.termsConditions, })), withCurrentOrganization(), + withDialogActions, )(InvoiceForm); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormDialogs.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormDialogs.tsx index eb0e3e0ba..fca6a8bcb 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormDialogs.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormDialogs.tsx @@ -1,8 +1,8 @@ // @ts-nocheck -import React from 'react'; import { useFormikContext } from 'formik'; import InvoiceNumberDialog from '@/containers/Dialogs/InvoiceNumberDialog'; import { DialogsName } from '@/constants/dialogs'; +import InvoiceFormMailDeliverDialog from './Dialogs/InvoiceFormMailDeliverDialog/InvoiceFormMailDeliverDialog'; /** * Invoice form dialogs. @@ -23,9 +23,14 @@ export default function InvoiceFormDialogs() { }; return ( - + <> + + + ); } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx index 1b385b83f..02c629e7c 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog.tsx @@ -4,8 +4,8 @@ import { Dialog, DialogSuspense } from '@/components'; import withDialogRedux from '@/components/DialogReduxConnect'; import { compose } from '@/utils'; -const InvoiceMailDialogContent = React.lazy( - () => import('./InvoiceMailDialogContent'), +const InvoiceMailDialogBody = React.lazy( + () => import('./InvoiceMailDialogBody'), ); /** @@ -13,12 +13,7 @@ const InvoiceMailDialogContent = React.lazy( */ function InvoiceMailDialog({ dialogName, - payload: { - invoiceId = null, - - // Redirects to the invoices list. - redirectToInvoicesList = false, - }, + payload: { invoiceId = null }, isOpen, }) { return ( @@ -26,16 +21,13 @@ function InvoiceMailDialog({ name={dialogName} title={'Invoice Mail'} isOpen={isOpen} - canEscapeJeyClose={true} + canEscapeJeyClose={false} + isCloseButtonShown={false} autoFocus={true} style={{ width: 600 }} > - + ); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBody.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBody.tsx new file mode 100644 index 000000000..3728c60ce --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogBody.tsx @@ -0,0 +1,36 @@ +// @ts-nocheck +import * as R from 'ramda'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import InvoiceMailDialogContent, { + InvoiceMailDialogContentProps, +} from './InvoiceMailDialogContent'; +import { DialogsName } from '@/constants/dialogs'; + +export interface InvoiceMailDialogBodyProps + extends InvoiceMailDialogContentProps {} + +function InvoiceMailDialogBodyRoot({ + invoiceId, + onCancelClick, + onFormSubmit, + + // #withDialogActions + closeDialog, +}: InvoiceMailDialogBodyProps) { + const handleCancelClick = () => { + closeDialog(DialogsName.InvoiceMail); + }; + const handleSubmitClick = () => { + closeDialog(DialogsName.InvoiceMail); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)(InvoiceMailDialogBodyRoot); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx index 769a722b6..dbecb34fc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogContent.tsx @@ -1,24 +1,22 @@ import { InvoiceMailDialogBoot } from './InvoiceMailDialogBoot'; import { InvoiceMailDialogForm } from './InvoiceMailDialogForm'; -interface InvoiceMailDialogContentProps { - dialogName: string; +export interface InvoiceMailDialogContentProps { invoiceId: number; - - // Redirect to invoices list after submitting the message. - redirectToInvoicesList?: boolean; + onFormSubmit?: () => void; + onCancelClick?: () => void; } export default function InvoiceMailDialogContent({ - dialogName, invoiceId, - redirectToInvoicesList, + onFormSubmit, + onCancelClick, }: InvoiceMailDialogContentProps) { return ( - - + + ); } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx index 697e8e9a1..a91c03466 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialogForm.tsx @@ -1,12 +1,9 @@ // @ts-nocheck import { Formik } from 'formik'; -import * as R from 'ramda'; import { Intent } from '@blueprintjs/core'; import { useInvoiceMailDialogBoot } from './InvoiceMailDialogBoot'; -import { DialogsName } from '@/constants/dialogs'; import { AppToaster } from '@/components'; import { useSendSaleInvoiceMail } from '@/hooks/query'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; import { InvoiceMailDialogFormContent } from './InvoiceMailDialogFormContent'; import { InvoiceMailFormSchema } from './InvoiceMailDialogForm.schema'; import { @@ -15,7 +12,6 @@ import { transformMailFormToRequest, transformMailFormToInitialValues, } from '@/containers/SendMailNotification/utils'; -import { useHistory } from 'react-router-dom'; const initialFormValues = { ...initialMailNotificationValues, @@ -26,13 +22,8 @@ interface InvoiceMailFormValues extends MailNotificationFormValues { attachInvoice: boolean; } -function InvoiceMailDialogFormRoot({ - // #withDialogActions - closeDialog, -}) { - const history = useHistory(); - const { mailOptions, saleInvoiceId, redirectToInvoicesList } = - useInvoiceMailDialogBoot(); +export function InvoiceMailDialogForm({ onFormSubmit, onCancelClick }) { + const { mailOptions, saleInvoiceId } = useInvoiceMailDialogBoot(); const { mutateAsync: sendInvoiceMail } = useSendSaleInvoiceMail(); const initialValues = transformMailFormToInitialValues( @@ -50,13 +41,8 @@ function InvoiceMailDialogFormRoot({ message: 'The mail notification has been sent successfully.', intent: Intent.SUCCESS, }); - closeDialog(DialogsName.InvoiceMail); setSubmitting(false); - - // Redirect to the dashboard if the option was enabled. - if (redirectToInvoicesList) { - history.push('/invoices'); - } + onFormSubmit && onFormSubmit(values); }) .catch(() => { AppToaster.show({ @@ -68,7 +54,7 @@ function InvoiceMailDialogFormRoot({ }; // Handle the close button click. const handleClose = () => { - closeDialog(DialogsName.InvoiceMail); + onCancelClick && onCancelClick(); }; return ( @@ -81,7 +67,3 @@ function InvoiceMailDialogFormRoot({ ); } - -export const InvoiceMailDialogForm = R.compose(withDialogActions)( - InvoiceMailDialogFormRoot, -); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/index.ts b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/index.ts index b64dcaaf3..b40bce27b 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/index.ts +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceMailDialog/index.ts @@ -1 +1,2 @@ -export * from './InvoiceMailDialog'; \ No newline at end of file +export * from './InvoiceMailDialog'; +export * from './InvoiceMailDialogContent'; \ No newline at end of file diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialog.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialog.tsx new file mode 100644 index 000000000..60f2758ff --- /dev/null +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialog.tsx @@ -0,0 +1,39 @@ +// @ts-nocheck +import React from 'react'; +import { Dialog, DialogSuspense } from '@/components'; +import withDialogRedux from '@/components/DialogReduxConnect'; +import { compose } from '@/utils'; + +const ReceiptFormMailDeliverDialogContent = React.lazy( + () => import('./ReceiptFormMailDeliverDialogContent'), +); + +/** + * Receipt mail dialog. + */ +function ReceiptFormMailDeliverDialog({ + dialogName, + payload: { receiptId = null }, + isOpen, +}) { + return ( + + + + + + ); +} + +export default compose(withDialogRedux())(ReceiptFormMailDeliverDialog); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialogContent.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialogContent.tsx new file mode 100644 index 000000000..4b5d31e40 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/Dialogs/ReceiptFormMailDeliverDialogContent.tsx @@ -0,0 +1,40 @@ +// @ts-nocheck +import * as R from 'ramda'; +import { useHistory } from 'react-router-dom'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import ReceiptMailDialogContent from '../../ReceiptMailDialog/ReceiptMailDialogContent'; +import { DialogsName } from '@/constants/dialogs'; + +interface ReceiptFormDeliverDialogContent { + receiptId: number; +} + +function ReceiptFormDeliverDialogContentRoot({ + receiptId, + + // #withDialogActions + closeDialog, +}: ReceiptFormDeliverDialogContent) { + const history = useHistory(); + + const handleSubmit = () => { + history.push('/receipts'); + closeDialog(DialogsName.ReceiptFormMailDeliver); + }; + const handleCancel = () => { + history.push('/receipts'); + closeDialog(DialogsName.ReceiptFormMailDeliver); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)( + ReceiptFormDeliverDialogContentRoot, +); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx index 62206bdbf..d7010d2ae 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx @@ -34,12 +34,20 @@ import { transformFormValuesToRequest, resetFormState, } from './utils'; -import { ReceiptSyncAutoExRateToForm, ReceiptSyncIncrementSettingsToForm } from './components'; +import { + ReceiptSyncAutoExRateToForm, + ReceiptSyncIncrementSettingsToForm, +} from './components'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import { DialogsName } from '@/constants/dialogs'; /** * Receipt form. */ function ReceiptForm({ + // #withDialogActions + openDialog, + // #withSettings receiptNextNumber, receiptNumberPrefix, @@ -84,10 +92,7 @@ function ReceiptForm({ }), }; // Handle the form submit. - const handleFormSubmit = ( - values, - { setErrors, setSubmitting, resetForm }, - ) => { + const handleFormSubmit = (values, { setErrors, setSubmitting }) => { const entries = values.entries.filter( (item) => item.item_id && item.quantity, ); @@ -124,6 +129,11 @@ function ReceiptForm({ if (submitPayload.resetForm) { resetFormState(); } + if (submitPayload.deliverMail) { + openDialog(DialogsName.ReceiptFormMailDeliver, { + receiptId: response.data.id, + }); + } }; // Handle the request error. @@ -179,6 +189,7 @@ function ReceiptForm({ } export default compose( + withDialogActions, withDashboardActions, withSettings(({ receiptSettings }) => ({ receiptNextNumber: receiptSettings?.nextNumber, diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormDialogs.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormDialogs.tsx index 4fe2cb947..30477aee6 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormDialogs.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormDialogs.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { useFormikContext } from 'formik'; import ReceiptNumberDialog from '@/containers/Dialogs/ReceiptNumberDialog'; +import ReceiptFormMailDeliverDialog from './Dialogs/ReceiptFormMailDeliverDialog'; +import { DialogsName } from '@/constants/dialogs'; /** * Receipt form dialogs. @@ -27,6 +29,9 @@ export default function ReceiptFormDialogs() { dialogName={'receipt-number-form'} onConfirm={handleReceiptNumberFormConfirm} /> + ); } diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx index d8d83dfb5..4db00c3ae 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx @@ -33,7 +33,7 @@ export default function ReceiptFormFloatingActions() { // Handle submit & close button click. const handleSubmitCloseBtnClick = (event) => { - setSubmitPayload({ redirect: true, status: true }); + setSubmitPayload({ redirect: false, deliverMail: true, status: true }); submitForm(); }; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx index eb68d7d37..69a0e64a9 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog.tsx @@ -4,21 +4,16 @@ import { Dialog, DialogSuspense } from '@/components'; import withDialogRedux from '@/components/DialogReduxConnect'; import { compose } from '@/utils'; -const ReceiptMailDialogContent = React.lazy( - () => import('./ReceiptMailDialogContent'), +const ReceiptMailDialogBody = React.lazy( + () => import('./ReceiptMailDialogBody'), ); /** - * Invoice mail dialog. + * Receipt mail dialog. */ function ReceiptMailDialog({ dialogName, - payload: { - receiptId = null, - - // Redirects to receipts list after mail submitting. - redirectToReceiptsList = false, - }, + payload: { receiptId = null }, isOpen, }) { return ( @@ -31,11 +26,7 @@ function ReceiptMailDialog({ style={{ width: 600 }} > - + ); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBody.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBody.tsx new file mode 100644 index 000000000..fbd379b84 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogBody.tsx @@ -0,0 +1,33 @@ +// @ts-nocheck +import * as R from 'ramda'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import ReceiptMailDialogContent, { + ReceiptMailDialogContentProps, +} from './ReceiptMailDialogContent'; +import { DialogsName } from '@/constants/dialogs'; + +interface ReceiptMailDialogBodyProps extends ReceiptMailDialogContentProps {} + +function ReceiptMailDialogBodyRoot({ + receiptId, + + // #withDialogActions + closeDialog, +}: ReceiptMailDialogBodyProps) { + const handleCancelClick = () => { + closeDialog(DialogsName.ReceiptMail); + }; + const handleSubmitClick = () => { + closeDialog(DialogsName.ReceiptMail); + }; + + return ( + + ); +} + +export default R.compose(withDialogActions)(ReceiptMailDialogBodyRoot); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx index 586de745c..a02966a1c 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogContent.tsx @@ -2,22 +2,22 @@ import React from 'react'; import { ReceiptMailDialogBoot } from './ReceiptMailDialogBoot'; import { ReceiptMailDialogForm } from './ReceiptMailDialogForm'; -interface ReceiptMailDialogContentProps { - dialogName: string; +export interface ReceiptMailDialogContentProps { receiptId: number; - redirectToReceiptsList?: boolean; + onFormSubmit?: () => void; + onCancelClick?: () => void; } export default function ReceiptMailDialogContent({ - dialogName, receiptId, - redirectToReceiptsList = false, + onFormSubmit, + onCancelClick }: ReceiptMailDialogContentProps) { return ( - - + + ); } diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx index d46ea7eb0..db2808f4c 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogForm.tsx @@ -2,7 +2,6 @@ import { Formik, FormikBag } from 'formik'; import * as R from 'ramda'; import { Intent } from '@blueprintjs/core'; -import { useHistory } from 'react-router-dom'; import { useReceiptMailDialogBoot } from './ReceiptMailDialogBoot'; import withDialogActions from '@/containers/Dialog/withDialogActions'; import { DialogsName } from '@/constants/dialogs'; @@ -24,12 +23,18 @@ interface ReceiptMailFormValues extends MailNotificationFormValues { attachReceipt: boolean; } -function ReceiptMailDialogFormRoot({ closeDialog }) { - const { mailOptions, saleReceiptId, redirectToReceiptsList } = - useReceiptMailDialogBoot(); - const { mutateAsync: sendReceiptMail } = useSendSaleReceiptMail(); +interface ReceiptMailDialogFormProps { + onFormSubmit?: () => void; + onCancelClick?: () => void; +} - const history = useHistory(); +export function ReceiptMailDialogForm({ + // #props + onFormSubmit, + onCancelClick, +}: ReceiptMailDialogFormProps) { + const { mailOptions, saleReceiptId } = useReceiptMailDialogBoot(); + const { mutateAsync: sendReceiptMail } = useSendSaleReceiptMail(); // Transformes mail options to initial form values. const initialValues = transformMailFormToInitialValues( @@ -50,12 +55,8 @@ function ReceiptMailDialogFormRoot({ closeDialog }) { message: 'The mail notification has been sent successfully.', intent: Intent.SUCCESS, }); - closeDialog(DialogsName.ReceiptMail); setSubmitting(false); - - if (redirectToReceiptsList) { - history.push('/receipts'); - } + onFormSubmit && onFormSubmit(values); }) .catch(() => { AppToaster.show({ @@ -67,7 +68,7 @@ function ReceiptMailDialogFormRoot({ closeDialog }) { }; // Handle the close button click. const handleClose = () => { - closeDialog(DialogsName.ReceiptMail); + onCancelClick && onCancelClick(); }; return ( @@ -76,7 +77,3 @@ function ReceiptMailDialogFormRoot({ closeDialog }) { ); } - -export const ReceiptMailDialogForm = R.compose(withDialogActions)( - ReceiptMailDialogFormRoot, -); From 4e40009ba01bf2204e502b4c4c4e03c6eee123ac Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 21 Feb 2024 20:16:57 +0200 Subject: [PATCH 5/5] revert: form changes --- .../EstimateForm/EstimateFloatingActions.tsx | 2 +- .../Estimates/EstimateForm/EstimateForm.tsx | 13 +----------- .../InvoiceForm/InvoiceFloatingActions.tsx | 8 +++---- .../Invoices/InvoiceForm/InvoiceForm.tsx | 18 ++-------------- .../Receipts/ReceiptForm/ReceiptForm.tsx | 21 +++++-------------- .../ReceiptFormFloatingActions.tsx | 2 +- 6 files changed, 14 insertions(+), 50 deletions(-) diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx index 474730d93..df212c38c 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFloatingActions.tsx @@ -29,7 +29,7 @@ export default function EstimateFloatingActions() { // Handle submit & deliver button click. const handleSubmitDeliverBtnClick = (event) => { - setSubmitPayload({ redirect: false, deliverViaMail: true }); + setSubmitPayload({ redirect: true, deliver: true }); submitForm(); }; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx index b1e665d3d..aff0888d6 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateForm.tsx @@ -36,16 +36,11 @@ import { handleErrors, resetFormState, } from './utils'; -import { DialogsName } from '@/constants/dialogs'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; /** * Estimate form. */ function EstimateForm({ - // #withDialogActions - openDialog, - // #withSettings estimateNextNumber, estimateNumberPrefix, @@ -113,7 +108,7 @@ function EstimateForm({ delivered: submitPayload.deliver, }; // Handle the request success. - const onSuccess = (res) => { + const onSuccess = (response) => { AppToaster.show({ message: intl.get( isNewMode @@ -131,11 +126,6 @@ function EstimateForm({ if (submitPayload.resetForm) { resetFormState({ resetForm, initialValues, values }); } - if (submitPayload.deliverViaMail) { - openDialog(DialogsName.EstimateFormMailDeliver, { - estimateId: res.data.id, - }); - } }; // Handle the request error. const onError = ({ @@ -190,7 +180,6 @@ function EstimateForm({ } export default compose( - withDialogActions, withSettings(({ estimatesSettings }) => ({ estimateNextNumber: estimatesSettings?.nextNumber, estimateNumberPrefix: estimatesSettings?.numberPrefix, diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx index 0a9a72913..e212c8b7d 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFloatingActions.tsx @@ -30,19 +30,19 @@ export default function InvoiceFloatingActions() { const { setSubmitPayload, invoice } = useInvoiceFormContext(); // Handle submit & deliver button click. - const handleSubmitDeliverBtnClick = () => { - setSubmitPayload({ redirectToEdit: true, deliverViaMail: true }); + const handleSubmitDeliverBtnClick = (event) => { + setSubmitPayload({ redirect: true, deliver: true }); submitForm(); }; // Handle submit, deliver & new button click. - const handleSubmitDeliverAndNewBtnClick = () => { + const handleSubmitDeliverAndNewBtnClick = (event) => { setSubmitPayload({ redirect: false, deliver: true, resetForm: true }); submitForm(); }; // Handle submit, deliver & continue editing button click. - const handleSubmitDeliverContinueEditingBtnClick = () => { + const handleSubmitDeliverContinueEditingBtnClick = (event) => { setSubmitPayload({ redirect: false, deliver: true }); submitForm(); }; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx index c47f7bc53..6b9f234ac 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx @@ -34,20 +34,12 @@ import { transformValueToRequest, resetFormState, } from './utils'; -import { - InvoiceExchangeRateSync, - InvoiceNoSyncSettingsToForm, -} from './components'; -import { DialogsName } from '@/constants/dialogs'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; +import { InvoiceExchangeRateSync, InvoiceNoSyncSettingsToForm } from './components'; /** * Invoice form. */ function InvoiceForm({ - // #withDialogActions - openDialog, - // #withSettings invoiceNextNumber, invoiceNumberPrefix, @@ -119,7 +111,7 @@ function InvoiceForm({ from_estimate_id: estimateId, }; // Handle the request success. - const onSuccess = (res) => { + const onSuccess = () => { AppToaster.show({ message: intl.get( isNewMode @@ -131,11 +123,6 @@ function InvoiceForm({ }); setSubmitting(false); - if (submitPayload.deliverViaMail) { - openDialog(DialogsName.InvoiceFormMailDeliver, { - invoiceId: res.data.id, - }); - } if (submitPayload.redirect) { history.push('/invoices'); } @@ -214,5 +201,4 @@ export default compose( invoiceTermsConditions: invoiceSettings?.termsConditions, })), withCurrentOrganization(), - withDialogActions, )(InvoiceForm); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx index d7010d2ae..62206bdbf 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptForm.tsx @@ -34,20 +34,12 @@ import { transformFormValuesToRequest, resetFormState, } from './utils'; -import { - ReceiptSyncAutoExRateToForm, - ReceiptSyncIncrementSettingsToForm, -} from './components'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; -import { DialogsName } from '@/constants/dialogs'; +import { ReceiptSyncAutoExRateToForm, ReceiptSyncIncrementSettingsToForm } from './components'; /** * Receipt form. */ function ReceiptForm({ - // #withDialogActions - openDialog, - // #withSettings receiptNextNumber, receiptNumberPrefix, @@ -92,7 +84,10 @@ function ReceiptForm({ }), }; // Handle the form submit. - const handleFormSubmit = (values, { setErrors, setSubmitting }) => { + const handleFormSubmit = ( + values, + { setErrors, setSubmitting, resetForm }, + ) => { const entries = values.entries.filter( (item) => item.item_id && item.quantity, ); @@ -129,11 +124,6 @@ function ReceiptForm({ if (submitPayload.resetForm) { resetFormState(); } - if (submitPayload.deliverMail) { - openDialog(DialogsName.ReceiptFormMailDeliver, { - receiptId: response.data.id, - }); - } }; // Handle the request error. @@ -189,7 +179,6 @@ function ReceiptForm({ } export default compose( - withDialogActions, withDashboardActions, withSettings(({ receiptSettings }) => ({ receiptNextNumber: receiptSettings?.nextNumber, diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx index 4db00c3ae..d8d83dfb5 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFloatingActions.tsx @@ -33,7 +33,7 @@ export default function ReceiptFormFloatingActions() { // Handle submit & close button click. const handleSubmitCloseBtnClick = (event) => { - setSubmitPayload({ redirect: false, deliverMail: true, status: true }); + setSubmitPayload({ redirect: true, status: true }); submitForm(); };