From bbafdcd8bd16e9af09d6a92d27718a1142b192cb Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sat, 6 Apr 2024 04:06:15 +0200 Subject: [PATCH] feat: configuring import services on more resources --- packages/server/src/models/CreditNote.Meta.ts | 71 +++++++++++++ .../src/models/PaymentReceive.Settings.ts | 63 ++++++++++- .../server/src/models/SaleReceipt.Settings.ts | 100 ++++++++++++++++-- .../server/src/models/VendorCredit.Meta.ts | 68 ++++++++++++ .../services/CreditNotes/CreateCreditNote.ts | 48 +++++---- .../CreditNotes/CreditNotesImportable.ts | 44 ++++++++ .../services/Import/ImportableResources.ts | 8 ++ .../VendorCredits/CreateVendorCredit.ts | 47 ++++---- .../VendorCredits/VendorCreditsImportable.ts | 45 ++++++++ .../Purchases/VendorCredits/constants.ts | 26 ++++- .../PaymentReceives/CreatePaymentReceive.ts | 53 +++++----- .../PaymentReceivesImportable.ts | 45 ++++++++ .../Sales/Receipts/CreateSaleReceipt.ts | 47 ++++---- .../Sales/Receipts/SaleReceiptsImportable.ts | 45 ++++++++ .../src/services/Sales/Receipts/constants.ts | 20 ++++ .../VendorsCreditNoteActionsBar.tsx | 6 ++ .../CreditNotes/VendorCreditsImport.tsx | 25 +++++ .../Sales/CreditNotes/CreditNotesImport.tsx | 25 +++++ .../CreditNotesActionsBar.tsx | 6 ++ .../PaymentReceives/PaymentReceivesImport.tsx | 25 +++++ .../PaymentReceiveActionsBar.tsx | 10 +- .../ReceiptsLanding/ReceiptActionsBar.tsx | 6 ++ .../Sales/Receipts/SaleReceiptsImport.tsx | 25 +++++ packages/webapp/src/routes/dashboard.tsx | 53 +++++++++- 24 files changed, 805 insertions(+), 106 deletions(-) create mode 100644 packages/server/src/services/CreditNotes/CreditNotesImportable.ts create mode 100644 packages/server/src/services/Purchases/VendorCredits/VendorCreditsImportable.ts create mode 100644 packages/server/src/services/Sales/PaymentReceives/PaymentReceivesImportable.ts create mode 100644 packages/server/src/services/Sales/Receipts/SaleReceiptsImportable.ts create mode 100644 packages/webapp/src/containers/Purchases/CreditNotes/VendorCreditsImport.tsx create mode 100644 packages/webapp/src/containers/Sales/CreditNotes/CreditNotesImport.tsx create mode 100644 packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceivesImport.tsx create mode 100644 packages/webapp/src/containers/Sales/Receipts/SaleReceiptsImport.tsx diff --git a/packages/server/src/models/CreditNote.Meta.ts b/packages/server/src/models/CreditNote.Meta.ts index 1cfc2bed9..c28081d87 100644 --- a/packages/server/src/models/CreditNote.Meta.ts +++ b/packages/server/src/models/CreditNote.Meta.ts @@ -77,4 +77,75 @@ export default { fieldType: 'date', }, }, + importable: true, + importAggregator: 'group', + importAggregateOn: 'entries', + importAggregateBy: 'creditNoteNumber', + fields2: { + customerId: { + name: 'Customer', + fieldType: 'relation', + relationModel: 'Contact', + relationImportMatch: 'displayName', + required: true, + }, + exchangeRate: { + name: 'Exchange Rate', + fieldType: 'number', + }, + creditNoteDate: { + name: 'Credit Note Date', + fieldType: 'date', + required: true, + }, + referenceNo: { + name: 'Reference No.', + fieldType: 'text', + }, + note: { + name: 'Note', + fieldType: 'text', + }, + termsConditions: { + name: 'Terms & Conditions', + fieldType: 'text', + }, + creditNoteNumber: { + name: 'Credit Note Number', + fieldType: 'text', + }, + open: { + name: 'Open', + fieldType: 'boolean', + }, + entries: { + name: 'Entries', + fieldType: 'collection', + collectionOf: 'object', + collectionMinLength: 1, + fields: { + itemId: { + name: 'Item', + fieldType: 'relation', + relationModel: 'Item', + relationImportMatch: ['name', 'code'], + required: true, + }, + rate: { + name: 'Rate', + fieldType: 'number', + required: true, + }, + quantity: { + name: 'Quantity', + fieldType: 'number', + required: true, + }, + description: { + name: 'Description', + fieldType: 'text', + }, + }, + }, + }, }; diff --git a/packages/server/src/models/PaymentReceive.Settings.ts b/packages/server/src/models/PaymentReceive.Settings.ts index 0e9012806..043ab77d1 100644 --- a/packages/server/src/models/PaymentReceive.Settings.ts +++ b/packages/server/src/models/PaymentReceive.Settings.ts @@ -1,5 +1,8 @@ - export default { + importable: true, + importAggregator: 'group', + importAggregateOn: 'entries', + importAggregateBy: 'paymentReceiveNo', fields: { customer: { name: 'payment_receive.field.customer', @@ -54,4 +57,62 @@ export default { fieldDate: 'date', }, }, + field2: { + customerId: { + name: 'payment_receive.field.customer_id', + fieldType: 'relation', + relationModel: 'Contact', + relationImportMatch: ['displayName'], + required: true, + }, + exchangeRate: { + name: 'payment_receive.field.exchange_rate', + fieldType: 'number', + }, + paymentDate: { + name: 'payment_receive.field.payment_date', + fieldType: 'date', + required: true, + }, + referenceNo: { + name: 'payment_receive.field.reference_no', + fieldType: 'text', + }, + depositAccountId: { + name: 'payment_receive.field.deposit_account_id', + fieldType: 'relation', + relationModel: 'Account', + relationImportMatch: ['name', 'code'], + required: true, + }, + paymentReceiveNo: { + name: 'payment_receive.field.payment_receive_no', + fieldType: 'text', + }, + statement: { + name: 'payment_receive.field.statement', + fieldType: 'text', + }, + entries: { + name: 'payment_receive.field.entries', + fieldType: 'collection', + collectionOf: 'object', + collectionMinLength: 1, + required: true, + fields: { + invoiceId: { + name: 'payment_receive.field.invoice', + fieldType: 'relation', + relationModel: 'SaleInvoice', + relationImportMatch: 'invoiceNo', + required: true, + }, + paymentAmount: { + name: 'payment_receive.field.entries.payment_amount', + fieldType: 'number', + required: true, + }, + }, + }, + }, }; diff --git a/packages/server/src/models/SaleReceipt.Settings.ts b/packages/server/src/models/SaleReceipt.Settings.ts index a844661ed..43fd54837 100644 --- a/packages/server/src/models/SaleReceipt.Settings.ts +++ b/packages/server/src/models/SaleReceipt.Settings.ts @@ -4,13 +4,17 @@ export default { sortOrder: 'DESC', sortField: 'created_at', }, + importable: true, + importAggregator: 'group', + importAggregateOn: 'entries', + importAggregateBy: 'receiptNumber', fields: { - 'amount': { + amount: { name: 'receipt.field.amount', column: 'amount', fieldType: 'number', }, - 'deposit_account': { + deposit_account: { column: 'deposit_account_id', name: 'receipt.field.deposit_account', fieldType: 'relation', @@ -21,7 +25,7 @@ export default { relationEntityLabel: 'name', relationEntityKey: 'slug', }, - 'customer': { + customer: { name: 'receipt.field.customer', column: 'customer_id', fieldType: 'relation', @@ -32,38 +36,37 @@ export default { relationEntityLabel: 'display_name', relationEntityKey: 'id', }, - 'receipt_date': { + receipt_date: { name: 'receipt.field.receipt_date', column: 'receipt_date', fieldType: 'date', - }, - 'receipt_number': { + receipt_number: { name: 'receipt.field.receipt_number', column: 'receipt_number', fieldType: 'text', }, - 'reference_no': { + reference_no: { name: 'receipt.field.reference_no', column: 'reference_no', fieldType: 'text', }, - 'receipt_message': { + receipt_message: { name: 'receipt.field.receipt_message', column: 'receipt_message', fieldType: 'text', }, - 'statement': { + statement: { name: 'receipt.field.statement', column: 'statement', fieldType: 'text', }, - 'created_at': { + created_at: { name: 'receipt.field.created_at', column: 'created_at', fieldType: 'date', }, - 'status': { + status: { name: 'receipt.field.status', fieldType: 'enumeration', options: [ @@ -74,6 +77,81 @@ export default { sortCustomQuery: StatusFieldSortQuery, }, }, + fields2: { + receiptDate: { + name: 'Receipt Date', + fieldType: 'date', + required: true, + }, + customerId: { + name: 'Customer', + fieldType: 'relation', + relationModel: 'Contact', + relationImportMatch: 'displayName', + required: true, + }, + depositAccountId: { + name: 'Deposit Account', + fieldType: 'relation', + relationModel: 'Account', + relationImportMatch: ['name', 'code'], + required: true, + }, + exchangeRate: { + name: 'Exchange Rate', + fieldType: 'number', + }, + receiptNumber: { + name: 'Receipt Number', + fieldType: 'text', + }, + referenceNo: { + name: 'Reference No.', + fieldType: 'text', + }, + closed: { + name: 'Closed', + fieldType: 'boolean', + }, + entries: { + name: 'Entries', + fieldType: 'collection', + collectionOf: 'object', + collectionMinLength: 1, + required: true, + fields: { + itemId: { + name: 'invoice.field.item_name', + fieldType: 'relation', + relationModel: 'Item', + relationImportMatch: ['name', 'code'], + required: true, + }, + rate: { + name: 'invoice.field.rate', + fieldType: 'number', + required: true, + }, + quantity: { + name: 'invoice.field.quantity', + fieldType: 'number', + required: true, + }, + description: { + name: 'invoice.field.description', + fieldType: 'text', + }, + }, + }, + statement: { + name: 'Statement', + fieldType: 'text', + }, + receiptMessage: { + name: 'Receipt Message', + fieldType: 'text', + }, + }, }; function StatusFieldFilterQuery(query, role) { diff --git a/packages/server/src/models/VendorCredit.Meta.ts b/packages/server/src/models/VendorCredit.Meta.ts index 27bd16c70..9ef1496dd 100644 --- a/packages/server/src/models/VendorCredit.Meta.ts +++ b/packages/server/src/models/VendorCredit.Meta.ts @@ -12,6 +12,10 @@ export default { sortOrder: 'DESC', sortField: 'name', }, + importable: true, + importAggregator: 'group', + importAggregateOn: 'entries', + importAggregateBy: 'vendorCreditNumber', fields: { vendor: { name: 'vendor_credit.field.vendor', @@ -72,4 +76,68 @@ export default { fieldType: 'date', }, }, + fields2: { + vendorId: { + name: 'Vendor', + fieldType: 'relation', + relationModel: 'Contact', + relationImportMatch: 'displayName', + required: true, + }, + exchangeRate: { + name: 'Echange Rate', + fieldType: 'text', + }, + vendorCreditNumber: { + name: 'Vendor Credit No.', + fieldType: 'text', + }, + referenceNo: { + name: 'Refernece No.', + fieldType: 'text', + }, + vendorCreditDate: { + name: 'Vendor Credit Date', + fieldType: 'date', + required: true, + }, + note: { + name: 'Note', + fieldType: 'text', + }, + open: { + name: 'Open', + fieldType: 'boolean', + }, + entries: { + name: 'Entries', + fieldType: 'collection', + collectionOf: 'object', + collectionMinLength: 1, + required: true, + fields: { + itemId: { + name: 'Item Name', + fieldType: 'relation', + relationModel: 'Item', + relationImportMatch: ['name', 'code'], + required: true, + }, + rate: { + name: 'Rate', + fieldType: 'number', + required: true, + }, + quantity: { + name: 'Quantity', + fieldType: 'number', + required: true, + }, + description: { + name: 'Description', + fieldType: 'text', + }, + }, + }, + }, }; diff --git a/packages/server/src/services/CreditNotes/CreateCreditNote.ts b/packages/server/src/services/CreditNotes/CreateCreditNote.ts index 641d1034e..2f4071c27 100644 --- a/packages/server/src/services/CreditNotes/CreateCreditNote.ts +++ b/packages/server/src/services/CreditNotes/CreateCreditNote.ts @@ -34,7 +34,7 @@ export default class CreateCreditNote extends BaseCreditNotes { public newCreditNote = async ( tenantId: number, creditNoteDTO: ICreditNoteNewDTO, - authorizedUser: ISystemUser + trx?: Knex.Transaction ) => { const { CreditNote, Contact } = this.tenancy.models(tenantId); @@ -66,28 +66,32 @@ export default class CreateCreditNote extends BaseCreditNotes { customer.currencyCode ); // Creates a new credit card transactions under unit-of-work envirement. - return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { - // Triggers `onCreditNoteCreating` event. - await this.eventPublisher.emitAsync(events.creditNote.onCreating, { - tenantId, - creditNoteDTO, - trx, - } as ICreditNoteCreatingPayload); + return this.uow.withTransaction( + tenantId, + async (trx: Knex.Transaction) => { + // Triggers `onCreditNoteCreating` event. + await this.eventPublisher.emitAsync(events.creditNote.onCreating, { + tenantId, + creditNoteDTO, + trx, + } as ICreditNoteCreatingPayload); - // Upsert the credit note graph. - const creditNote = await CreditNote.query(trx).upsertGraph({ - ...creditNoteModel, - }); - // Triggers `onCreditNoteCreated` event. - await this.eventPublisher.emitAsync(events.creditNote.onCreated, { - tenantId, - creditNoteDTO, - creditNote, - creditNoteId: creditNote.id, - trx, - } as ICreditNoteCreatedPayload); + // Upsert the credit note graph. + const creditNote = await CreditNote.query(trx).upsertGraph({ + ...creditNoteModel, + }); + // Triggers `onCreditNoteCreated` event. + await this.eventPublisher.emitAsync(events.creditNote.onCreated, { + tenantId, + creditNoteDTO, + creditNote, + creditNoteId: creditNote.id, + trx, + } as ICreditNoteCreatedPayload); - return creditNote; - }); + return creditNote; + }, + trx + ); }; } diff --git a/packages/server/src/services/CreditNotes/CreditNotesImportable.ts b/packages/server/src/services/CreditNotes/CreditNotesImportable.ts new file mode 100644 index 000000000..86388aad3 --- /dev/null +++ b/packages/server/src/services/CreditNotes/CreditNotesImportable.ts @@ -0,0 +1,44 @@ +import { Inject, Service } from 'typedi'; +import { Knex } from 'knex'; +import { ICreditNoteNewDTO } from '@/interfaces'; +import { Importable } from '../Import/Importable'; +import CreateCreditNote from './CreateCreditNote'; + +@Service() +export class CreditNotesImportable extends Importable { + @Inject() + private createCreditNoteImportable: CreateCreditNote; + + /** + * Importing to account service. + * @param {number} tenantId + * @param {IAccountCreateDTO} createAccountDTO + * @returns + */ + public importable( + tenantId: number, + createAccountDTO: ICreditNoteNewDTO, + trx?: Knex.Transaction + ) { + return this.createCreditNoteImportable.newCreditNote( + tenantId, + createAccountDTO, + trx + ); + } + + /** + * Concurrrency controlling of the importing process. + * @returns {number} + */ + public get concurrency() { + return 1; + } + + /** + * Retrieves the sample data that used to download accounts sample sheet. + */ + public sampleData(): any[] { + return []; + } +} diff --git a/packages/server/src/services/Import/ImportableResources.ts b/packages/server/src/services/Import/ImportableResources.ts index 8f51dc261..33f2f10f3 100644 --- a/packages/server/src/services/Import/ImportableResources.ts +++ b/packages/server/src/services/Import/ImportableResources.ts @@ -12,6 +12,10 @@ import { ExpensesImportable } from '../Expenses/ExpensesImportable'; import { SaleInvoicesImportable } from '../Sales/Invoices/SaleInvoicesImportable'; import { SaleEstimatesImportable } from '../Sales/Estimates/SaleEstimatesImportable'; import { BillPaymentsImportable } from '../Purchases/BillPayments/BillPaymentsImportable'; +import { VendorCreditsImportable } from '../Purchases/VendorCredits/VendorCreditsImportable'; +import { PaymentReceivesImportable } from '../Sales/PaymentReceives/PaymentReceivesImportable'; +import { CreditNotesImportable } from '../CreditNotes/CreditNotesImportable'; +import { SaleReceiptsImportable } from '../Sales/Receipts/SaleReceiptsImportable'; @Service() export class ImportableResources { @@ -40,6 +44,10 @@ export class ImportableResources { { resource: 'SaleInvoice', importable: SaleInvoicesImportable }, { resource: 'SaleEstimate', importable: SaleEstimatesImportable }, { resource: 'BillPayment', importable: BillPaymentsImportable }, + { resource: 'PaymentReceive', importable: PaymentReceivesImportable }, + { resource: 'VendorCredit', importable: VendorCreditsImportable }, + { resource: 'CreditNote', importable: CreditNotesImportable }, + { resource: 'SaleReceipt', importable: SaleReceiptsImportable } ]; public get registry() { diff --git a/packages/server/src/services/Purchases/VendorCredits/CreateVendorCredit.ts b/packages/server/src/services/Purchases/VendorCredits/CreateVendorCredit.ts index 255718fe8..32bf59386 100644 --- a/packages/server/src/services/Purchases/VendorCredits/CreateVendorCredit.ts +++ b/packages/server/src/services/Purchases/VendorCredits/CreateVendorCredit.ts @@ -33,7 +33,8 @@ export default class CreateVendorCredit extends BaseVendorCredit { */ public newVendorCredit = async ( tenantId: number, - vendorCreditCreateDTO: IVendorCreditCreateDTO + vendorCreditCreateDTO: IVendorCreditCreateDTO, + trx?: Knex.Transaction ) => { const { VendorCredit, Vendor } = this.tenancy.models(tenantId); @@ -59,27 +60,31 @@ export default class CreateVendorCredit extends BaseVendorCredit { vendor.currencyCode ); // Saves the vendor credit transactions under UOW envirement. - return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { - // Triggers `onVendorCreditCreating` event. - await this.eventPublisher.emitAsync(events.vendorCredit.onCreating, { - tenantId, - vendorCreditCreateDTO, - trx, - } as IVendorCreditCreatingPayload); + return this.uow.withTransaction( + tenantId, + async (trx: Knex.Transaction) => { + // Triggers `onVendorCreditCreating` event. + await this.eventPublisher.emitAsync(events.vendorCredit.onCreating, { + tenantId, + vendorCreditCreateDTO, + trx, + } as IVendorCreditCreatingPayload); - // Saves the vendor credit graph. - const vendorCredit = await VendorCredit.query(trx).upsertGraphAndFetch({ - ...vendorCreditModel, - }); - // Triggers `onVendorCreditCreated` event. - await this.eventPublisher.emitAsync(events.vendorCredit.onCreated, { - tenantId, - vendorCredit, - vendorCreditCreateDTO, - trx, - } as IVendorCreditCreatedPayload); + // Saves the vendor credit graph. + const vendorCredit = await VendorCredit.query(trx).upsertGraphAndFetch({ + ...vendorCreditModel, + }); + // Triggers `onVendorCreditCreated` event. + await this.eventPublisher.emitAsync(events.vendorCredit.onCreated, { + tenantId, + vendorCredit, + vendorCreditCreateDTO, + trx, + } as IVendorCreditCreatedPayload); - return vendorCredit; - }); + return vendorCredit; + }, + trx + ); }; } diff --git a/packages/server/src/services/Purchases/VendorCredits/VendorCreditsImportable.ts b/packages/server/src/services/Purchases/VendorCredits/VendorCreditsImportable.ts new file mode 100644 index 000000000..b267ef353 --- /dev/null +++ b/packages/server/src/services/Purchases/VendorCredits/VendorCreditsImportable.ts @@ -0,0 +1,45 @@ +import { Inject, Service } from 'typedi'; +import { Knex } from 'knex'; +import { Importable } from '@/services/Import/Importable'; +import CreateVendorCredit from './CreateVendorCredit'; +import { IVendorCreditCreateDTO } from '@/interfaces'; +import { VendorCreditsSampleData } from './constants'; + +@Service() +export class VendorCreditsImportable extends Importable { + @Inject() + private createVendorCreditService: CreateVendorCredit; + + /** + * Importing to account service. + * @param {number} tenantId + * @param {IAccountCreateDTO} createAccountDTO + * @returns + */ + public importable( + tenantId: number, + createPaymentDTO: IVendorCreditCreateDTO, + trx?: Knex.Transaction + ) { + return this.createVendorCreditService.newVendorCredit( + tenantId, + createPaymentDTO, + trx + ); + } + + /** + * Concurrrency controlling of the importing process. + * @returns {number} + */ + public get concurrency() { + return 1; + } + + /** + * Retrieves the sample data that used to download accounts sample sheet. + */ + public sampleData(): any[] { + return VendorCreditsSampleData; + } +} diff --git a/packages/server/src/services/Purchases/VendorCredits/constants.ts b/packages/server/src/services/Purchases/VendorCredits/constants.ts index 76a7e1b88..d686669d8 100644 --- a/packages/server/src/services/Purchases/VendorCredits/constants.ts +++ b/packages/server/src/services/Purchases/VendorCredits/constants.ts @@ -1,11 +1,14 @@ export const ERRORS = { VENDOR_CREDIT_NOT_FOUND: 'VENDOR_CREDIT_NOT_FOUND', VENDOR_CREDIT_ALREADY_OPENED: 'VENDOR_CREDIT_ALREADY_OPENED', - VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT: 'VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT', - VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND: 'VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND', + VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT: + 'VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT', + VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND: + 'VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND', BILLS_HAS_NO_REMAINING_AMOUNT: 'BILLS_HAS_NO_REMAINING_AMOUNT', - VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS: 'VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS', - VENDOR_CREDIT_HAS_APPLIED_BILLS: 'VENDOR_CREDIT_HAS_APPLIED_BILLS' + VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS: + 'VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS', + VENDOR_CREDIT_HAS_APPLIED_BILLS: 'VENDOR_CREDIT_HAS_APPLIED_BILLS', }; export const DEFAULT_VIEW_COLUMNS = []; @@ -62,3 +65,18 @@ export const DEFAULT_VIEWS = [ columns: DEFAULT_VIEW_COLUMNS, }, ]; + +export const VendorCreditsSampleData = [ + { + Vendor: 'Randall Kohler VENDOR', + 'Vendor Credit Date': '2024-01-01', + 'Vendor Credit No.': 'VC-0001', + 'Reference No.': 'REF-00001', + 'Exchange Rate': '', + Note: 'Note', + Open: 'T', + 'Item Name': 'Hettinger, Schumm and Bartoletti', + Quantity: 100, + Rate: 100, + }, +]; diff --git a/packages/server/src/services/Sales/PaymentReceives/CreatePaymentReceive.ts b/packages/server/src/services/Sales/PaymentReceives/CreatePaymentReceive.ts index 462fb6495..4e0708cbf 100644 --- a/packages/server/src/services/Sales/PaymentReceives/CreatePaymentReceive.ts +++ b/packages/server/src/services/Sales/PaymentReceives/CreatePaymentReceive.ts @@ -42,7 +42,8 @@ export class CreatePaymentReceive { public async createPaymentReceive( tenantId: number, paymentReceiveDTO: IPaymentReceiveCreateDTO, - authorizedUser: ISystemUser + authorizedUser: ISystemUser, + trx?: Knex.Transaction ) { const { PaymentReceive, Contact } = this.tenancy.models(tenantId); @@ -88,31 +89,35 @@ export class CreatePaymentReceive { tenantMeta.baseCurrency ); // Creates a payment receive transaction under UOW envirment. - return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { - // Triggers `onPaymentReceiveCreating` event. - await this.eventPublisher.emitAsync(events.paymentReceive.onCreating, { - trx, - paymentReceiveDTO, - tenantId, - } as IPaymentReceiveCreatingPayload); + return this.uow.withTransaction( + tenantId, + async (trx: Knex.Transaction) => { + // Triggers `onPaymentReceiveCreating` event. + await this.eventPublisher.emitAsync(events.paymentReceive.onCreating, { + trx, + paymentReceiveDTO, + tenantId, + } as IPaymentReceiveCreatingPayload); - // Inserts the payment receive transaction. - const paymentReceive = await PaymentReceive.query( - trx - ).insertGraphAndFetch({ - ...paymentReceiveObj, - }); - // Triggers `onPaymentReceiveCreated` event. - await this.eventPublisher.emitAsync(events.paymentReceive.onCreated, { - tenantId, - paymentReceive, - paymentReceiveId: paymentReceive.id, - authorizedUser, - trx, - } as IPaymentReceiveCreatedPayload); + // Inserts the payment receive transaction. + const paymentReceive = await PaymentReceive.query( + trx + ).insertGraphAndFetch({ + ...paymentReceiveObj, + }); + // Triggers `onPaymentReceiveCreated` event. + await this.eventPublisher.emitAsync(events.paymentReceive.onCreated, { + tenantId, + paymentReceive, + paymentReceiveId: paymentReceive.id, + authorizedUser, + trx, + } as IPaymentReceiveCreatedPayload); - return paymentReceive; - }); + return paymentReceive; + }, + trx + ); } /** diff --git a/packages/server/src/services/Sales/PaymentReceives/PaymentReceivesImportable.ts b/packages/server/src/services/Sales/PaymentReceives/PaymentReceivesImportable.ts new file mode 100644 index 000000000..2828def8a --- /dev/null +++ b/packages/server/src/services/Sales/PaymentReceives/PaymentReceivesImportable.ts @@ -0,0 +1,45 @@ +import { Inject, Service } from 'typedi'; +import { Knex } from 'knex'; +import { IPaymentReceiveCreateDTO } from '@/interfaces'; +import { Importable } from '@/services/Import/Importable'; +import { CreatePaymentReceive } from './CreatePaymentReceive'; + +@Service() +export class PaymentReceivesImportable extends Importable { + @Inject() + private createPaymentReceiveService: CreatePaymentReceive; + + /** + * Importing to account service. + * @param {number} tenantId + * @param {IAccountCreateDTO} createAccountDTO + * @returns + */ + public importable( + tenantId: number, + createPaymentDTO: IPaymentReceiveCreateDTO, + trx?: Knex.Transaction + ) { + return this.createPaymentReceiveService.createPaymentReceive( + tenantId, + createPaymentDTO, + {}, + trx + ); + } + + /** + * Concurrrency controlling of the importing process. + * @returns {number} + */ + public get concurrency() { + return 1; + } + + /** + * Retrieves the sample data that used to download accounts sample sheet. + */ + public sampleData(): any[] { + return []; + } +} diff --git a/packages/server/src/services/Sales/Receipts/CreateSaleReceipt.ts b/packages/server/src/services/Sales/Receipts/CreateSaleReceipt.ts index 0fcafff8a..2b6709e29 100644 --- a/packages/server/src/services/Sales/Receipts/CreateSaleReceipt.ts +++ b/packages/server/src/services/Sales/Receipts/CreateSaleReceipt.ts @@ -41,7 +41,8 @@ export class CreateSaleReceipt { */ public async createSaleReceipt( tenantId: number, - saleReceiptDTO: any + saleReceiptDTO: any, + trx?: Knex.Transaction ): Promise { const { SaleReceipt, Contact } = this.tenancy.models(tenantId); @@ -80,27 +81,31 @@ export class CreateSaleReceipt { ); } // Creates a sale receipt transaction and associated transactions under UOW env. - return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { - // Triggers `onSaleReceiptCreating` event. - await this.eventPublisher.emitAsync(events.saleReceipt.onCreating, { - saleReceiptDTO, - tenantId, - trx, - } as ISaleReceiptCreatingPayload); + return this.uow.withTransaction( + tenantId, + async (trx: Knex.Transaction) => { + // Triggers `onSaleReceiptCreating` event. + await this.eventPublisher.emitAsync(events.saleReceipt.onCreating, { + saleReceiptDTO, + tenantId, + trx, + } as ISaleReceiptCreatingPayload); - // Inserts the sale receipt graph to the storage. - const saleReceipt = await SaleReceipt.query().upsertGraph({ - ...saleReceiptObj, - }); - // Triggers `onSaleReceiptCreated` event. - await this.eventPublisher.emitAsync(events.saleReceipt.onCreated, { - tenantId, - saleReceipt, - saleReceiptId: saleReceipt.id, - trx, - } as ISaleReceiptCreatedPayload); + // Inserts the sale receipt graph to the storage. + const saleReceipt = await SaleReceipt.query().upsertGraph({ + ...saleReceiptObj, + }); + // Triggers `onSaleReceiptCreated` event. + await this.eventPublisher.emitAsync(events.saleReceipt.onCreated, { + tenantId, + saleReceipt, + saleReceiptId: saleReceipt.id, + trx, + } as ISaleReceiptCreatedPayload); - return saleReceipt; - }); + return saleReceipt; + }, + trx + ); } } diff --git a/packages/server/src/services/Sales/Receipts/SaleReceiptsImportable.ts b/packages/server/src/services/Sales/Receipts/SaleReceiptsImportable.ts new file mode 100644 index 000000000..c8036d894 --- /dev/null +++ b/packages/server/src/services/Sales/Receipts/SaleReceiptsImportable.ts @@ -0,0 +1,45 @@ +import { Inject, Service } from 'typedi'; +import { Knex } from 'knex'; +import { IAccountCreateDTO } from '@/interfaces'; +import { CreateSaleReceipt } from './CreateSaleReceipt'; +import { Importable } from '@/services/Import/Importable'; +import { SaleReceiptsSampleData } from './constants'; + +@Service() +export class SaleReceiptsImportable extends Importable { + @Inject() + private createReceiptService: CreateSaleReceipt; + + /** + * Importing to sale receipts service. + * @param {number} tenantId + * @param {IAccountCreateDTO} createAccountDTO + * @returns + */ + public importable( + tenantId: number, + createAccountDTO: IAccountCreateDTO, + trx?: Knex.Transaction + ) { + return this.createReceiptService.createSaleReceipt( + tenantId, + createAccountDTO, + trx + ); + } + + /** + * Concurrrency controlling of the importing process. + * @returns {number} + */ + public get concurrency() { + return 1; + } + + /** + * Retrieves the sample data that used to download accounts sample sheet. + */ + public sampleData(): any[] { + return SaleReceiptsSampleData; + } +} diff --git a/packages/server/src/services/Sales/Receipts/constants.ts b/packages/server/src/services/Sales/Receipts/constants.ts index 084af9214..06df9a615 100644 --- a/packages/server/src/services/Sales/Receipts/constants.ts +++ b/packages/server/src/services/Sales/Receipts/constants.ts @@ -46,3 +46,23 @@ export const DEFAULT_VIEWS = [ columns: DEFAULT_VIEW_COLUMNS, }, ]; + + +export const SaleReceiptsSampleData = [ + { + "Receipt Date": "2023-01-01", + "Customer": "Randall Kohler", + "Deposit Account": "Petty Cash", + "Exchange Rate": "", + "Receipt Number": "REC-00001", + "Reference No.": "REF-0001", + "Statement": "Delectus unde aut soluta et accusamus placeat.", + "Receipt Message": "Vitae asperiores dicta.", + "Closed": "T", + "Item": "Schmitt Group", + "Quantity": 100, + "Rate": 200, + "Line Description": "Distinctio distinctio sit veritatis consequatur iste quod veritatis." + } + +] \ No newline at end of file diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx index a8f8f183e..e4a7b1ff9 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.tsx @@ -75,6 +75,11 @@ function VendorsCreditNoteActionsBar({ addSetting('vendorCredit', 'tableSize', size); }; + // Handle import button click. + const handleImportBtnClick = () => { + history.push('/vendor-credits/import') + } + return ( @@ -117,6 +122,7 @@ function VendorsCreditNoteActionsBar({ className={Classes.MINIMAL} icon={} text={} + onClick={handleImportBtnClick} />