mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 04:10:32 +00:00
Merge pull request #332 from bigcapitalhq/big-105-convert-invoice-status-after-sending-mail-notification
feat: convert invoice status after sending mail notification
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -132,4 +132,10 @@ export interface SaleEstimateMailOptions extends CommonMailOptions {
|
||||
|
||||
export interface SaleEstimateMailOptionsDTO extends CommonMailOptionsDTO {
|
||||
attachEstimate?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISaleEstimateMailPresendEvent {
|
||||
tenantId: number;
|
||||
saleEstimateId: number;
|
||||
messageOptions: SaleEstimateMailOptionsDTO;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,9 @@ 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';
|
||||
import { SaleReceiptMarkClosedOnMailSentSubcriber } from '@/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber';
|
||||
import { SaleEstimateMarkApprovedOnMailSent } from '@/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent';
|
||||
|
||||
export default () => {
|
||||
return new EventPublisher();
|
||||
@@ -104,8 +107,12 @@ export const susbcribers = () => {
|
||||
InventorySubscriber,
|
||||
CustomerWriteGLOpeningBalanceSubscriber,
|
||||
VendorsWriteGLOpeningSubscriber,
|
||||
|
||||
// # Estimate
|
||||
SaleEstimateAutoSerialSubscriber,
|
||||
SaleEstimateSmsNotificationSubscriber,
|
||||
SaleEstimateMarkApprovedOnMailSent,
|
||||
|
||||
ExpensesWriteGLSubscriber,
|
||||
SaleReceiptAutoSerialSubscriber,
|
||||
SaleInvoiceAutoIncrementSubscriber,
|
||||
@@ -152,11 +159,13 @@ export const susbcribers = () => {
|
||||
// #Invoices
|
||||
InvoicePaymentGLRewriteSubscriber,
|
||||
InvoiceCostGLEntriesSubscriber,
|
||||
InvoiceChangeStatusOnMailSentSubscriber,
|
||||
|
||||
BillPaymentsGLEntriesRewriteSubscriber,
|
||||
|
||||
// # Receipts
|
||||
SaleReceiptCostGLEntriesSubscriber,
|
||||
SaleReceiptMarkClosedOnMailSentSubcriber,
|
||||
|
||||
// Transaction locking.
|
||||
SalesTransactionLockingGuardSubscriber,
|
||||
@@ -199,6 +208,6 @@ export const susbcribers = () => {
|
||||
BillTaxRateValidateSubscriber,
|
||||
WriteBillTaxTransactionsSubscriber,
|
||||
|
||||
SyncItemTaxRateOnEditTaxSubscriber
|
||||
SyncItemTaxRateOnEditTaxSubscriber,
|
||||
];
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { IAccountTransaction } from '@/interfaces';
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
import { transaction } from 'objection';
|
||||
|
||||
export default class AccountTransactionTransformer extends Transformer {
|
||||
/**
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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<void> {
|
||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<void>}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ import { SaleReceiptCostGLEntries } from '../SaleReceiptCostGLEntries';
|
||||
@Service()
|
||||
export class SaleReceiptCostGLEntriesSubscriber {
|
||||
@Inject()
|
||||
saleReceiptCostEntries: SaleReceiptCostGLEntries;
|
||||
private saleReceiptCostEntries: SaleReceiptCostGLEntries;
|
||||
|
||||
/**
|
||||
* Attaches events.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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,11 @@ export default {
|
||||
onRejecting: 'onSaleEstimateRejecting',
|
||||
onRejected: 'onSaleEstimateRejected',
|
||||
|
||||
onNotifyMail: 'onSaleEstimateNotifyMail'
|
||||
onNotifyMail: 'onSaleEstimateNotifyMail',
|
||||
|
||||
onPreMailSend: 'onSaleEstimatePreMailSend',
|
||||
onMailSend: 'onSaleEstimateMailSend',
|
||||
onMailSent: 'onSaleEstimateMailSend',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -188,6 +199,10 @@ export default {
|
||||
|
||||
onNotifySms: 'onSaleReceiptNotifySms',
|
||||
onNotifiedSms: 'onSaleReceiptNotifiedSms',
|
||||
|
||||
onPreMailSend: 'onSaleReceiptPreMailSend',
|
||||
onMailSend: 'onSaleReceiptMailSend',
|
||||
onMailSent: 'onSaleReceiptMailSent',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -208,6 +223,10 @@ export default {
|
||||
|
||||
onNotifySms: 'onPaymentReceiveNotifySms',
|
||||
onNotifiedSms: 'onPaymentReceiveNotifiedSms',
|
||||
|
||||
onPreMailSend: 'onPaymentReceivePreMailSend',
|
||||
onMailSend: 'onPaymentReceiveMailSend',
|
||||
onMailSent: 'onPaymentReceiveMailSent',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -580,6 +599,6 @@ export default {
|
||||
onActivated: 'onTaxRateActivated',
|
||||
|
||||
onInactivating: 'onTaxRateInactivating',
|
||||
onInactivated: 'onTaxRateInactivated'
|
||||
onInactivated: 'onTaxRateInactivated',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -53,6 +53,9 @@ export enum DialogsName {
|
||||
EstimateMail = 'estimate-mail',
|
||||
ReceiptMail = 'receipt-mail',
|
||||
PaymentMail = 'payment-mail',
|
||||
InvoiceFormMailDeliver = 'InvoiceFormMailDeliver',
|
||||
EstimateFormMailDeliver = 'EstimateFormMailDeliver',
|
||||
ReceiptFormMailDeliver = 'ReceiptFormMailDeliver',
|
||||
BalanceSheetPdfPreview = 'BalanceSheetPdfPreview',
|
||||
TrialBalanceSheetPdfPreview = 'TrialBalanceSheetPdfPreview',
|
||||
CashflowSheetPdfPreview = 'CashflowSheetPdfPreview',
|
||||
|
||||
@@ -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 (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={'Estimate Mail'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={false}
|
||||
isCloseButtonShown={false}
|
||||
autoFocus={true}
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<EstimateFormMailDeliverDialogContent
|
||||
dialogName={dialogName}
|
||||
estimateId={estimateId}
|
||||
/>
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogRedux())(EstimateFormMailDeliverDialog);
|
||||
@@ -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 (
|
||||
<EstimateMailDialogContent
|
||||
estimateId={estimateId}
|
||||
onFormSubmit={handleSubmit}
|
||||
onCancelClick={handleCancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(
|
||||
EstimateFormDeliverDialogContentRoot,
|
||||
);
|
||||
@@ -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}
|
||||
/>
|
||||
<EstimateFormMailDeliverDialog
|
||||
dialogName={DialogsName.EstimateFormMailDeliver}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ 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,
|
||||
@@ -26,10 +26,7 @@ function EstimateMailDialog({
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<EstimateMailDialogContent
|
||||
dialogName={dialogName}
|
||||
estimateId={estimateId}
|
||||
/>
|
||||
<EstimateMailDialogBody estimateId={estimateId} />
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<EstimateMailDialogContent
|
||||
estimateId={estimateId}
|
||||
onFormSubmit={handleSubmit}
|
||||
onCancelClick={handleCancelClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(EstimateMailDialogBodyRoot);
|
||||
@@ -6,12 +6,14 @@ import { DialogContent } from '@/components';
|
||||
interface EstimateMailDialogBootValues {
|
||||
estimateId: number;
|
||||
mailOptions: any;
|
||||
redirectToEstimatesList: boolean;
|
||||
}
|
||||
|
||||
const EstimateMailDialagBoot = createContext<EstimateMailDialogBootValues>();
|
||||
|
||||
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 (
|
||||
|
||||
@@ -2,16 +2,21 @@ import { EstimateMailDialogBoot } from './EstimateMailDialogBoot';
|
||||
import { EstimateMailDialogForm } from './EstimateMailDialogForm';
|
||||
|
||||
interface EstimateMailDialogContentProps {
|
||||
dialogName: string;
|
||||
estimateId: number;
|
||||
onFormSubmit?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
}
|
||||
export default function EstimateMailDialogContent({
|
||||
dialogName,
|
||||
estimateId,
|
||||
onFormSubmit,
|
||||
onCancelClick,
|
||||
}: EstimateMailDialogContentProps) {
|
||||
return (
|
||||
<EstimateMailDialogBoot estimateId={estimateId}>
|
||||
<EstimateMailDialogForm />
|
||||
<EstimateMailDialogForm
|
||||
onFormSubmit={onFormSubmit}
|
||||
onCancelClick={onCancelClick}
|
||||
/>
|
||||
</EstimateMailDialogBoot>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { Formik } from 'formik';
|
||||
import * as R from 'ramda';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { useEstimateMailDialogBoot } from './EstimateMailDialogBoot';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
@@ -12,7 +13,6 @@ import {
|
||||
transformMailFormToInitialValues,
|
||||
transformMailFormToRequest,
|
||||
} from '@/containers/SendMailNotification/utils';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { AppToaster } from '@/components';
|
||||
|
||||
const initialFormValues = {
|
||||
@@ -25,11 +25,15 @@ interface EstimateMailFormValues extends MailNotificationFormValues {
|
||||
}
|
||||
|
||||
function EstimateMailDialogFormRoot({
|
||||
onFormSubmit,
|
||||
onCancelClick,
|
||||
|
||||
// #withDialogClose
|
||||
closeDialog,
|
||||
}) {
|
||||
const { mutateAsync: sendEstimateMail } = useSendSaleEstimateMail();
|
||||
const { mailOptions, saleEstimateId } = useEstimateMailDialogBoot();
|
||||
const { mailOptions, saleEstimateId, redirectToEstimatesList } =
|
||||
useEstimateMailDialogBoot();
|
||||
|
||||
const initialValues = transformMailFormToInitialValues(
|
||||
mailOptions,
|
||||
@@ -48,14 +52,16 @@ function EstimateMailDialogFormRoot({
|
||||
});
|
||||
closeDialog(DialogsName.EstimateMail);
|
||||
setSubmitting(false);
|
||||
onFormSubmit && onFormSubmit();
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(() => {
|
||||
setSubmitting(false);
|
||||
closeDialog(DialogsName.EstimateMail);
|
||||
AppToaster.show({
|
||||
message: 'Something went wrong.',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
onCancelClick && onCancelClick();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={'Invoice Mail'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={false}
|
||||
isCloseButtonShown={false}
|
||||
autoFocus={true}
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<InvoiceFormMailDeliverDialogContent
|
||||
dialogName={dialogName}
|
||||
invoiceId={invoiceId}
|
||||
/>
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogRedux())(InvoiceFormMailDeliverDialog);
|
||||
@@ -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 (
|
||||
<InvoiceMailDialogContent
|
||||
invoiceId={invoiceId}
|
||||
onFormSubmit={handleSubmit}
|
||||
onCancelClick={handleCancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(
|
||||
InvoiceFormDeliverDialogContentRoot,
|
||||
);
|
||||
@@ -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 (
|
||||
<InvoiceNumberDialog
|
||||
dialogName={DialogsName.InvoiceNumberSettings}
|
||||
onConfirm={handleInvoiceNumberFormConfirm}
|
||||
/>
|
||||
<>
|
||||
<InvoiceNumberDialog
|
||||
dialogName={DialogsName.InvoiceNumberSettings}
|
||||
onConfirm={handleInvoiceNumberFormConfirm}
|
||||
/>
|
||||
<InvoiceFormMailDeliverDialog
|
||||
dialogName={DialogsName.InvoiceFormMailDeliver}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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'),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -21,15 +21,13 @@ function InvoiceMailDialog({
|
||||
name={dialogName}
|
||||
title={'Invoice Mail'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={true}
|
||||
canEscapeJeyClose={false}
|
||||
isCloseButtonShown={false}
|
||||
autoFocus={true}
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<InvoiceMailDialogContent
|
||||
dialogName={dialogName}
|
||||
invoiceId={invoiceId}
|
||||
/>
|
||||
<InvoiceMailDialogBody invoiceId={invoiceId} />
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<InvoiceMailDialogContent
|
||||
invoiceId={invoiceId}
|
||||
onCancelClick={handleCancelClick}
|
||||
onFormSubmit={handleSubmitClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(InvoiceMailDialogBodyRoot);
|
||||
@@ -6,12 +6,14 @@ import { DialogContent } from '@/components';
|
||||
interface InvoiceMailDialogBootValues {
|
||||
invoiceId: number;
|
||||
mailOptions: any;
|
||||
redirectToInvoicesList: boolean;
|
||||
}
|
||||
|
||||
const InvoiceMailDialagBoot = createContext<InvoiceMailDialogBootValues>();
|
||||
|
||||
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 (
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
import { InvoiceMailDialogBoot } from './InvoiceMailDialogBoot';
|
||||
import { InvoiceMailDialogForm } from './InvoiceMailDialogForm';
|
||||
|
||||
interface InvoiceMailDialogContentProps {
|
||||
dialogName: string;
|
||||
export interface InvoiceMailDialogContentProps {
|
||||
invoiceId: number;
|
||||
onFormSubmit?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
}
|
||||
export default function InvoiceMailDialogContent({
|
||||
dialogName,
|
||||
invoiceId,
|
||||
onFormSubmit,
|
||||
onCancelClick,
|
||||
}: InvoiceMailDialogContentProps) {
|
||||
return (
|
||||
<InvoiceMailDialogBoot invoiceId={invoiceId}>
|
||||
<InvoiceMailDialogForm />
|
||||
<InvoiceMailDialogForm
|
||||
onFormSubmit={onFormSubmit}
|
||||
onCancelClick={onCancelClick}
|
||||
/>
|
||||
</InvoiceMailDialogBoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -25,10 +22,7 @@ interface InvoiceMailFormValues extends MailNotificationFormValues {
|
||||
attachInvoice: boolean;
|
||||
}
|
||||
|
||||
function InvoiceMailDialogFormRoot({
|
||||
// #withDialogActions
|
||||
closeDialog,
|
||||
}) {
|
||||
export function InvoiceMailDialogForm({ onFormSubmit, onCancelClick }) {
|
||||
const { mailOptions, saleInvoiceId } = useInvoiceMailDialogBoot();
|
||||
const { mutateAsync: sendInvoiceMail } = useSendSaleInvoiceMail();
|
||||
|
||||
@@ -47,8 +41,8 @@ function InvoiceMailDialogFormRoot({
|
||||
message: 'The mail notification has been sent successfully.',
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeDialog(DialogsName.InvoiceMail);
|
||||
setSubmitting(false);
|
||||
onFormSubmit && onFormSubmit(values);
|
||||
})
|
||||
.catch(() => {
|
||||
AppToaster.show({
|
||||
@@ -60,7 +54,7 @@ function InvoiceMailDialogFormRoot({
|
||||
};
|
||||
// Handle the close button click.
|
||||
const handleClose = () => {
|
||||
closeDialog(DialogsName.InvoiceMail);
|
||||
onCancelClick && onCancelClick();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -73,7 +67,3 @@ function InvoiceMailDialogFormRoot({
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export const InvoiceMailDialogForm = R.compose(withDialogActions)(
|
||||
InvoiceMailDialogFormRoot,
|
||||
);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './InvoiceMailDialog';
|
||||
export * from './InvoiceMailDialog';
|
||||
export * from './InvoiceMailDialogContent';
|
||||
@@ -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({
|
||||
<PaymentMailDialogContent
|
||||
dialogName={dialogName}
|
||||
paymentReceiveId={paymentReceiveId}
|
||||
redirectToPaymentsList={redirectToPaymentsList}
|
||||
/>
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 (
|
||||
<PaymentMailDialogBoot paymentReceiveId={paymentReceiveId}>
|
||||
<PaymentMailDialogBoot
|
||||
paymentReceiveId={paymentReceiveId}
|
||||
redirectToPaymentsList={redirectToPaymentsList}
|
||||
>
|
||||
<PaymentMailDialogForm />
|
||||
</PaymentMailDialogBoot>
|
||||
);
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={'Receipt Mail'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={false}
|
||||
isCloseButtonShown={false}
|
||||
autoFocus={true}
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<ReceiptFormMailDeliverDialogContent
|
||||
dialogName={dialogName}
|
||||
receiptId={receiptId}
|
||||
/>
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogRedux())(ReceiptFormMailDeliverDialog);
|
||||
@@ -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 (
|
||||
<ReceiptMailDialogContent
|
||||
receiptId={receiptId}
|
||||
onFormSubmit={handleSubmit}
|
||||
onCancelClick={handleCancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(
|
||||
ReceiptFormDeliverDialogContentRoot,
|
||||
);
|
||||
@@ -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}
|
||||
/>
|
||||
<ReceiptFormMailDeliverDialog
|
||||
dialogName={DialogsName.ReceiptFormMailDeliver}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ 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,
|
||||
@@ -26,10 +26,7 @@ function ReceiptMailDialog({
|
||||
style={{ width: 600 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<ReceiptMailDialogContent
|
||||
dialogName={dialogName}
|
||||
receiptId={receiptId}
|
||||
/>
|
||||
<ReceiptMailDialogBody receiptId={receiptId} />
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<ReceiptMailDialogContent
|
||||
receiptId={receiptId}
|
||||
onFormSubmit={handleSubmitClick}
|
||||
onCancelClick={handleCancelClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default R.compose(withDialogActions)(ReceiptMailDialogBodyRoot);
|
||||
@@ -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 (
|
||||
|
||||
@@ -2,17 +2,22 @@ import React from 'react';
|
||||
import { ReceiptMailDialogBoot } from './ReceiptMailDialogBoot';
|
||||
import { ReceiptMailDialogForm } from './ReceiptMailDialogForm';
|
||||
|
||||
interface ReceiptMailDialogContentProps {
|
||||
dialogName: string
|
||||
export interface ReceiptMailDialogContentProps {
|
||||
receiptId: number;
|
||||
onFormSubmit?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
}
|
||||
export default function ReceiptMailDialogContent({
|
||||
dialogName,
|
||||
receiptId,
|
||||
onFormSubmit,
|
||||
onCancelClick
|
||||
}: ReceiptMailDialogContentProps) {
|
||||
return (
|
||||
<ReceiptMailDialogBoot receiptId={receiptId}>
|
||||
<ReceiptMailDialogForm />
|
||||
<ReceiptMailDialogForm
|
||||
onFormSubmit={onFormSubmit}
|
||||
onCancelClick={onCancelClick}
|
||||
/>
|
||||
</ReceiptMailDialogBoot>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,16 @@ interface ReceiptMailFormValues extends MailNotificationFormValues {
|
||||
attachReceipt: boolean;
|
||||
}
|
||||
|
||||
function ReceiptMailDialogFormRoot({ closeDialog }) {
|
||||
interface ReceiptMailDialogFormProps {
|
||||
onFormSubmit?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
}
|
||||
|
||||
export function ReceiptMailDialogForm({
|
||||
// #props
|
||||
onFormSubmit,
|
||||
onCancelClick,
|
||||
}: ReceiptMailDialogFormProps) {
|
||||
const { mailOptions, saleReceiptId } = useReceiptMailDialogBoot();
|
||||
const { mutateAsync: sendReceiptMail } = useSendSaleReceiptMail();
|
||||
|
||||
@@ -46,8 +55,8 @@ function ReceiptMailDialogFormRoot({ closeDialog }) {
|
||||
message: 'The mail notification has been sent successfully.',
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeDialog(DialogsName.ReceiptMail);
|
||||
setSubmitting(false);
|
||||
onFormSubmit && onFormSubmit(values);
|
||||
})
|
||||
.catch(() => {
|
||||
AppToaster.show({
|
||||
@@ -59,7 +68,7 @@ function ReceiptMailDialogFormRoot({ closeDialog }) {
|
||||
};
|
||||
// Handle the close button click.
|
||||
const handleClose = () => {
|
||||
closeDialog(DialogsName.ReceiptMail);
|
||||
onCancelClick && onCancelClick();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -68,7 +77,3 @@ function ReceiptMailDialogFormRoot({ closeDialog }) {
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export const ReceiptMailDialogForm = R.compose(withDialogActions)(
|
||||
ReceiptMailDialogFormRoot,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user