feat: configuring import services on more resources

This commit is contained in:
Ahmed Bouhuolia
2024-04-06 04:06:15 +02:00
parent dd9098bdc1
commit bbafdcd8bd
24 changed files with 805 additions and 106 deletions

View File

@@ -77,4 +77,75 @@ export default {
fieldType: 'date', 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',
},
},
},
},
}; };

View File

@@ -1,5 +1,8 @@
export default { export default {
importable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'paymentReceiveNo',
fields: { fields: {
customer: { customer: {
name: 'payment_receive.field.customer', name: 'payment_receive.field.customer',
@@ -54,4 +57,62 @@ export default {
fieldDate: 'date', 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,
},
},
},
},
}; };

View File

@@ -4,13 +4,17 @@ export default {
sortOrder: 'DESC', sortOrder: 'DESC',
sortField: 'created_at', sortField: 'created_at',
}, },
importable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'receiptNumber',
fields: { fields: {
'amount': { amount: {
name: 'receipt.field.amount', name: 'receipt.field.amount',
column: 'amount', column: 'amount',
fieldType: 'number', fieldType: 'number',
}, },
'deposit_account': { deposit_account: {
column: 'deposit_account_id', column: 'deposit_account_id',
name: 'receipt.field.deposit_account', name: 'receipt.field.deposit_account',
fieldType: 'relation', fieldType: 'relation',
@@ -21,7 +25,7 @@ export default {
relationEntityLabel: 'name', relationEntityLabel: 'name',
relationEntityKey: 'slug', relationEntityKey: 'slug',
}, },
'customer': { customer: {
name: 'receipt.field.customer', name: 'receipt.field.customer',
column: 'customer_id', column: 'customer_id',
fieldType: 'relation', fieldType: 'relation',
@@ -32,38 +36,37 @@ export default {
relationEntityLabel: 'display_name', relationEntityLabel: 'display_name',
relationEntityKey: 'id', relationEntityKey: 'id',
}, },
'receipt_date': { receipt_date: {
name: 'receipt.field.receipt_date', name: 'receipt.field.receipt_date',
column: 'receipt_date', column: 'receipt_date',
fieldType: 'date', fieldType: 'date',
}, },
'receipt_number': { receipt_number: {
name: 'receipt.field.receipt_number', name: 'receipt.field.receipt_number',
column: 'receipt_number', column: 'receipt_number',
fieldType: 'text', fieldType: 'text',
}, },
'reference_no': { reference_no: {
name: 'receipt.field.reference_no', name: 'receipt.field.reference_no',
column: 'reference_no', column: 'reference_no',
fieldType: 'text', fieldType: 'text',
}, },
'receipt_message': { receipt_message: {
name: 'receipt.field.receipt_message', name: 'receipt.field.receipt_message',
column: 'receipt_message', column: 'receipt_message',
fieldType: 'text', fieldType: 'text',
}, },
'statement': { statement: {
name: 'receipt.field.statement', name: 'receipt.field.statement',
column: 'statement', column: 'statement',
fieldType: 'text', fieldType: 'text',
}, },
'created_at': { created_at: {
name: 'receipt.field.created_at', name: 'receipt.field.created_at',
column: 'created_at', column: 'created_at',
fieldType: 'date', fieldType: 'date',
}, },
'status': { status: {
name: 'receipt.field.status', name: 'receipt.field.status',
fieldType: 'enumeration', fieldType: 'enumeration',
options: [ options: [
@@ -74,6 +77,81 @@ export default {
sortCustomQuery: StatusFieldSortQuery, 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) { function StatusFieldFilterQuery(query, role) {

View File

@@ -12,6 +12,10 @@ export default {
sortOrder: 'DESC', sortOrder: 'DESC',
sortField: 'name', sortField: 'name',
}, },
importable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'vendorCreditNumber',
fields: { fields: {
vendor: { vendor: {
name: 'vendor_credit.field.vendor', name: 'vendor_credit.field.vendor',
@@ -72,4 +76,68 @@ export default {
fieldType: 'date', 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',
},
},
},
},
}; };

View File

@@ -34,7 +34,7 @@ export default class CreateCreditNote extends BaseCreditNotes {
public newCreditNote = async ( public newCreditNote = async (
tenantId: number, tenantId: number,
creditNoteDTO: ICreditNoteNewDTO, creditNoteDTO: ICreditNoteNewDTO,
authorizedUser: ISystemUser trx?: Knex.Transaction
) => { ) => {
const { CreditNote, Contact } = this.tenancy.models(tenantId); const { CreditNote, Contact } = this.tenancy.models(tenantId);
@@ -66,28 +66,32 @@ export default class CreateCreditNote extends BaseCreditNotes {
customer.currencyCode customer.currencyCode
); );
// Creates a new credit card transactions under unit-of-work envirement. // Creates a new credit card transactions under unit-of-work envirement.
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(
// Triggers `onCreditNoteCreating` event. tenantId,
await this.eventPublisher.emitAsync(events.creditNote.onCreating, { async (trx: Knex.Transaction) => {
tenantId, // Triggers `onCreditNoteCreating` event.
creditNoteDTO, await this.eventPublisher.emitAsync(events.creditNote.onCreating, {
trx, tenantId,
} as ICreditNoteCreatingPayload); creditNoteDTO,
trx,
} as ICreditNoteCreatingPayload);
// Upsert the credit note graph. // Upsert the credit note graph.
const creditNote = await CreditNote.query(trx).upsertGraph({ const creditNote = await CreditNote.query(trx).upsertGraph({
...creditNoteModel, ...creditNoteModel,
}); });
// Triggers `onCreditNoteCreated` event. // Triggers `onCreditNoteCreated` event.
await this.eventPublisher.emitAsync(events.creditNote.onCreated, { await this.eventPublisher.emitAsync(events.creditNote.onCreated, {
tenantId, tenantId,
creditNoteDTO, creditNoteDTO,
creditNote, creditNote,
creditNoteId: creditNote.id, creditNoteId: creditNote.id,
trx, trx,
} as ICreditNoteCreatedPayload); } as ICreditNoteCreatedPayload);
return creditNote; return creditNote;
}); },
trx
);
}; };
} }

View File

@@ -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 [];
}
}

View File

@@ -12,6 +12,10 @@ import { ExpensesImportable } from '../Expenses/ExpensesImportable';
import { SaleInvoicesImportable } from '../Sales/Invoices/SaleInvoicesImportable'; import { SaleInvoicesImportable } from '../Sales/Invoices/SaleInvoicesImportable';
import { SaleEstimatesImportable } from '../Sales/Estimates/SaleEstimatesImportable'; import { SaleEstimatesImportable } from '../Sales/Estimates/SaleEstimatesImportable';
import { BillPaymentsImportable } from '../Purchases/BillPayments/BillPaymentsImportable'; 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() @Service()
export class ImportableResources { export class ImportableResources {
@@ -40,6 +44,10 @@ export class ImportableResources {
{ resource: 'SaleInvoice', importable: SaleInvoicesImportable }, { resource: 'SaleInvoice', importable: SaleInvoicesImportable },
{ resource: 'SaleEstimate', importable: SaleEstimatesImportable }, { resource: 'SaleEstimate', importable: SaleEstimatesImportable },
{ resource: 'BillPayment', importable: BillPaymentsImportable }, { resource: 'BillPayment', importable: BillPaymentsImportable },
{ resource: 'PaymentReceive', importable: PaymentReceivesImportable },
{ resource: 'VendorCredit', importable: VendorCreditsImportable },
{ resource: 'CreditNote', importable: CreditNotesImportable },
{ resource: 'SaleReceipt', importable: SaleReceiptsImportable }
]; ];
public get registry() { public get registry() {

View File

@@ -33,7 +33,8 @@ export default class CreateVendorCredit extends BaseVendorCredit {
*/ */
public newVendorCredit = async ( public newVendorCredit = async (
tenantId: number, tenantId: number,
vendorCreditCreateDTO: IVendorCreditCreateDTO vendorCreditCreateDTO: IVendorCreditCreateDTO,
trx?: Knex.Transaction
) => { ) => {
const { VendorCredit, Vendor } = this.tenancy.models(tenantId); const { VendorCredit, Vendor } = this.tenancy.models(tenantId);
@@ -59,27 +60,31 @@ export default class CreateVendorCredit extends BaseVendorCredit {
vendor.currencyCode vendor.currencyCode
); );
// Saves the vendor credit transactions under UOW envirement. // Saves the vendor credit transactions under UOW envirement.
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(
// Triggers `onVendorCreditCreating` event. tenantId,
await this.eventPublisher.emitAsync(events.vendorCredit.onCreating, { async (trx: Knex.Transaction) => {
tenantId, // Triggers `onVendorCreditCreating` event.
vendorCreditCreateDTO, await this.eventPublisher.emitAsync(events.vendorCredit.onCreating, {
trx, tenantId,
} as IVendorCreditCreatingPayload); vendorCreditCreateDTO,
trx,
} as IVendorCreditCreatingPayload);
// Saves the vendor credit graph. // Saves the vendor credit graph.
const vendorCredit = await VendorCredit.query(trx).upsertGraphAndFetch({ const vendorCredit = await VendorCredit.query(trx).upsertGraphAndFetch({
...vendorCreditModel, ...vendorCreditModel,
}); });
// Triggers `onVendorCreditCreated` event. // Triggers `onVendorCreditCreated` event.
await this.eventPublisher.emitAsync(events.vendorCredit.onCreated, { await this.eventPublisher.emitAsync(events.vendorCredit.onCreated, {
tenantId, tenantId,
vendorCredit, vendorCredit,
vendorCreditCreateDTO, vendorCreditCreateDTO,
trx, trx,
} as IVendorCreditCreatedPayload); } as IVendorCreditCreatedPayload);
return vendorCredit; return vendorCredit;
}); },
trx
);
}; };
} }

View File

@@ -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;
}
}

View File

@@ -1,11 +1,14 @@
export const ERRORS = { export const ERRORS = {
VENDOR_CREDIT_NOT_FOUND: 'VENDOR_CREDIT_NOT_FOUND', VENDOR_CREDIT_NOT_FOUND: 'VENDOR_CREDIT_NOT_FOUND',
VENDOR_CREDIT_ALREADY_OPENED: 'VENDOR_CREDIT_ALREADY_OPENED', VENDOR_CREDIT_ALREADY_OPENED: 'VENDOR_CREDIT_ALREADY_OPENED',
VENDOR_CREDIT_HAS_NO_REMAINING_AMOUNT: '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_APPLY_TO_BILLS_NOT_FOUND:
'VENDOR_CREDIT_APPLY_TO_BILLS_NOT_FOUND',
BILLS_HAS_NO_REMAINING_AMOUNT: 'BILLS_HAS_NO_REMAINING_AMOUNT', BILLS_HAS_NO_REMAINING_AMOUNT: 'BILLS_HAS_NO_REMAINING_AMOUNT',
VENDOR_CREDIT_HAS_REFUND_TRANSACTIONS: '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_APPLIED_BILLS: 'VENDOR_CREDIT_HAS_APPLIED_BILLS',
}; };
export const DEFAULT_VIEW_COLUMNS = []; export const DEFAULT_VIEW_COLUMNS = [];
@@ -62,3 +65,18 @@ export const DEFAULT_VIEWS = [
columns: DEFAULT_VIEW_COLUMNS, 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,
},
];

View File

@@ -42,7 +42,8 @@ export class CreatePaymentReceive {
public async createPaymentReceive( public async createPaymentReceive(
tenantId: number, tenantId: number,
paymentReceiveDTO: IPaymentReceiveCreateDTO, paymentReceiveDTO: IPaymentReceiveCreateDTO,
authorizedUser: ISystemUser authorizedUser: ISystemUser,
trx?: Knex.Transaction
) { ) {
const { PaymentReceive, Contact } = this.tenancy.models(tenantId); const { PaymentReceive, Contact } = this.tenancy.models(tenantId);
@@ -88,31 +89,35 @@ export class CreatePaymentReceive {
tenantMeta.baseCurrency tenantMeta.baseCurrency
); );
// Creates a payment receive transaction under UOW envirment. // Creates a payment receive transaction under UOW envirment.
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(
// Triggers `onPaymentReceiveCreating` event. tenantId,
await this.eventPublisher.emitAsync(events.paymentReceive.onCreating, { async (trx: Knex.Transaction) => {
trx, // Triggers `onPaymentReceiveCreating` event.
paymentReceiveDTO, await this.eventPublisher.emitAsync(events.paymentReceive.onCreating, {
tenantId, trx,
} as IPaymentReceiveCreatingPayload); paymentReceiveDTO,
tenantId,
} as IPaymentReceiveCreatingPayload);
// Inserts the payment receive transaction. // Inserts the payment receive transaction.
const paymentReceive = await PaymentReceive.query( const paymentReceive = await PaymentReceive.query(
trx trx
).insertGraphAndFetch({ ).insertGraphAndFetch({
...paymentReceiveObj, ...paymentReceiveObj,
}); });
// Triggers `onPaymentReceiveCreated` event. // Triggers `onPaymentReceiveCreated` event.
await this.eventPublisher.emitAsync(events.paymentReceive.onCreated, { await this.eventPublisher.emitAsync(events.paymentReceive.onCreated, {
tenantId, tenantId,
paymentReceive, paymentReceive,
paymentReceiveId: paymentReceive.id, paymentReceiveId: paymentReceive.id,
authorizedUser, authorizedUser,
trx, trx,
} as IPaymentReceiveCreatedPayload); } as IPaymentReceiveCreatedPayload);
return paymentReceive; return paymentReceive;
}); },
trx
);
} }
/** /**

View File

@@ -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 [];
}
}

View File

@@ -41,7 +41,8 @@ export class CreateSaleReceipt {
*/ */
public async createSaleReceipt( public async createSaleReceipt(
tenantId: number, tenantId: number,
saleReceiptDTO: any saleReceiptDTO: any,
trx?: Knex.Transaction
): Promise<ISaleReceipt> { ): Promise<ISaleReceipt> {
const { SaleReceipt, Contact } = this.tenancy.models(tenantId); 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. // Creates a sale receipt transaction and associated transactions under UOW env.
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { return this.uow.withTransaction(
// Triggers `onSaleReceiptCreating` event. tenantId,
await this.eventPublisher.emitAsync(events.saleReceipt.onCreating, { async (trx: Knex.Transaction) => {
saleReceiptDTO, // Triggers `onSaleReceiptCreating` event.
tenantId, await this.eventPublisher.emitAsync(events.saleReceipt.onCreating, {
trx, saleReceiptDTO,
} as ISaleReceiptCreatingPayload); tenantId,
trx,
} as ISaleReceiptCreatingPayload);
// Inserts the sale receipt graph to the storage. // Inserts the sale receipt graph to the storage.
const saleReceipt = await SaleReceipt.query().upsertGraph({ const saleReceipt = await SaleReceipt.query().upsertGraph({
...saleReceiptObj, ...saleReceiptObj,
}); });
// Triggers `onSaleReceiptCreated` event. // Triggers `onSaleReceiptCreated` event.
await this.eventPublisher.emitAsync(events.saleReceipt.onCreated, { await this.eventPublisher.emitAsync(events.saleReceipt.onCreated, {
tenantId, tenantId,
saleReceipt, saleReceipt,
saleReceiptId: saleReceipt.id, saleReceiptId: saleReceipt.id,
trx, trx,
} as ISaleReceiptCreatedPayload); } as ISaleReceiptCreatedPayload);
return saleReceipt; return saleReceipt;
}); },
trx
);
} }
} }

View File

@@ -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;
}
}

View File

@@ -46,3 +46,23 @@ export const DEFAULT_VIEWS = [
columns: DEFAULT_VIEW_COLUMNS, 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."
}
]

View File

@@ -75,6 +75,11 @@ function VendorsCreditNoteActionsBar({
addSetting('vendorCredit', 'tableSize', size); addSetting('vendorCredit', 'tableSize', size);
}; };
// Handle import button click.
const handleImportBtnClick = () => {
history.push('/vendor-credits/import')
}
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -117,6 +122,7 @@ function VendorsCreditNoteActionsBar({
className={Classes.MINIMAL} className={Classes.MINIMAL}
icon={<Icon icon={'file-import-16'} />} icon={<Icon icon={'file-import-16'} />}
text={<T id={'import'} />} text={<T id={'import'} />}
onClick={handleImportBtnClick}
/> />
<Button <Button
className={Classes.MINIMAL} className={Classes.MINIMAL}

View File

@@ -0,0 +1,25 @@
// @ts-nocheck
import { DashboardInsider } from '@/components';
import { ImportView } from '@/containers/Import';
import { useHistory } from 'react-router-dom';
export default function VendorCreditsImport() {
const history = useHistory();
const handleCancelBtnClick = () => {
history.push('/vendor-credits');
};
const handleImportSuccess = () => {
history.push('/vendor-credits');
};
return (
<DashboardInsider name={'import-vendor-credit'}>
<ImportView
resource={'vendor_credit'}
onCancelClick={handleCancelBtnClick}
onImportSuccess={handleImportSuccess}
/>
</DashboardInsider>
);
}

View File

@@ -0,0 +1,25 @@
// @ts-nocheck
import { DashboardInsider } from '@/components';
import { ImportView } from '@/containers/Import';
import { useHistory } from 'react-router-dom';
export default function CreditNotesImport() {
const history = useHistory();
const handleCancelBtnClick = () => {
history.push('/credit-notes');
};
const handleImportSuccess = () => {
history.push('/credit-notes');
};
return (
<DashboardInsider name={'import-credit-notes'}>
<ImportView
resource={'credit_note'}
onCancelClick={handleCancelBtnClick}
onImportSuccess={handleImportSuccess}
/>
</DashboardInsider>
);
}

View File

@@ -69,6 +69,11 @@ function CreditNotesActionsBar({
addSetting('creditNote', 'tableSize', size); addSetting('creditNote', 'tableSize', size);
}; };
// Handle import button click.
const handleImportBtnClick = () => {
history.push('/credit-notes/import');
};
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -111,6 +116,7 @@ function CreditNotesActionsBar({
className={Classes.MINIMAL} className={Classes.MINIMAL}
icon={<Icon icon={'file-import-16'} />} icon={<Icon icon={'file-import-16'} />}
text={<T id={'import'} />} text={<T id={'import'} />}
onClick={handleImportBtnClick}
/> />
<Button <Button
className={Classes.MINIMAL} className={Classes.MINIMAL}

View File

@@ -0,0 +1,25 @@
// @ts-nocheck
import { useHistory } from 'react-router-dom';
import { DashboardInsider } from '@/components';
import { ImportView } from '@/containers/Import';
export default function PaymentsReceiveImport() {
const history = useHistory();
const handleCancelBtnClick = () => {
history.push('/');
};
const handleImportSuccess = () => {
history.push('/accounts');
};
return (
<DashboardInsider name={'import-accounts'}>
<ImportView
resource={'payment_receive'}
onCancelClick={handleCancelBtnClick}
onImportSuccess={handleImportSuccess}
/>
</DashboardInsider>
);
}

View File

@@ -26,7 +26,10 @@ import withPaymentReceives from './withPaymentReceives';
import withPaymentReceivesActions from './withPaymentReceivesActions'; import withPaymentReceivesActions from './withPaymentReceivesActions';
import withSettings from '@/containers/Settings/withSettings'; import withSettings from '@/containers/Settings/withSettings';
import withSettingsActions from '@/containers/Settings/withSettingsActions'; import withSettingsActions from '@/containers/Settings/withSettingsActions';
import { PaymentReceiveAction, AbilitySubject } from '@/constants/abilityOption'; import {
PaymentReceiveAction,
AbilitySubject,
} from '@/constants/abilityOption';
import { usePaymentReceivesListContext } from './PaymentReceiptsListProvider'; import { usePaymentReceivesListContext } from './PaymentReceiptsListProvider';
import { useRefreshPaymentReceive } from '@/hooks/query/paymentReceives'; import { useRefreshPaymentReceive } from '@/hooks/query/paymentReceives';
import { compose } from '@/utils'; import { compose } from '@/utils';
@@ -75,6 +78,10 @@ function PaymentReceiveActionsBar({
const handleTableRowSizeChange = (size) => { const handleTableRowSizeChange = (size) => {
addSetting('paymentReceives', 'tableSize', size); addSetting('paymentReceives', 'tableSize', size);
}; };
// Handle the import button click.
const handleImportBtnClick = () => {
history.push('/payment-receives/import');
};
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
@@ -126,6 +133,7 @@ function PaymentReceiveActionsBar({
className={Classes.MINIMAL} className={Classes.MINIMAL}
icon={<Icon icon={'file-import-16'} />} icon={<Icon icon={'file-import-16'} />}
text={<T id={'import'} />} text={<T id={'import'} />}
onClick={handleImportBtnClick}
/> />
<Button <Button
className={Classes.MINIMAL} className={Classes.MINIMAL}

View File

@@ -81,6 +81,11 @@ function ReceiptActionsBar({
addSetting('salesReceipts', 'tableSize', size); addSetting('salesReceipts', 'tableSize', size);
}; };
// Handle the import button click.
const handleImportBtnClick = () => {
history.push('/receipts/import');
};
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -134,6 +139,7 @@ function ReceiptActionsBar({
className={Classes.MINIMAL} className={Classes.MINIMAL}
icon={<Icon icon={'file-import-16'} />} icon={<Icon icon={'file-import-16'} />}
text={<T id={'import'} />} text={<T id={'import'} />}
onClick={handleImportBtnClick}
/> />
<Button <Button
className={Classes.MINIMAL} className={Classes.MINIMAL}

View File

@@ -0,0 +1,25 @@
// @ts-nocheck
import { useHistory } from 'react-router-dom';
import { ImportView } from '@/containers/Import';
import { DashboardInsider } from '@/components';
export default function ReceiptsImport() {
const history = useHistory();
const handleCancelBtnClick = () => {
history.push('/accounts');
};
const handleImportSuccess = () => {
history.push('/accounts');
};
return (
<DashboardInsider name={'import-accounts'}>
<ImportView
resource={'sale_receipt'}
onCancelClick={handleCancelBtnClick}
onImportSuccess={handleImportSuccess}
/>
</DashboardInsider>
);
}

View File

@@ -789,6 +789,19 @@ export const getDashboardRoutes = () => [
}, },
// Sales Receipts. // Sales Receipts.
{
path: `/receipts/import`,
component: lazy(
() => import('@/containers/Sales/Receipts/SaleReceiptsImport'),
),
name: 'receipt-import',
breadcrumb: 'Receipts Import',
pageTitle: 'Receipts Import',
backLink: true,
sidebarExpand: false,
defaultSearchResource: RESOURCES_TYPES.RECEIPT,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{ {
path: `/receipts/:id/edit`, path: `/receipts/:id/edit`,
component: lazy( component: lazy(
@@ -829,6 +842,19 @@ export const getDashboardRoutes = () => [
}, },
// Sales Credit notes. // Sales Credit notes.
{
path: `/credit-notes/import`,
component: lazy(
() => import('@/containers/Sales/CreditNotes/CreditNotesImport'),
),
name: 'credit-note-import',
breadcrumb: 'Credit Notes Import',
pageTitle: 'Credit Notes Import',
backLink: true,
sidebarExpand: false,
defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{ {
path: `/credit-notes/:id/edit`, path: `/credit-notes/:id/edit`,
component: lazy( component: lazy(
@@ -890,8 +916,20 @@ export const getDashboardRoutes = () => [
defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE, defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN], subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
}, },
// Payment receives // Payment receives
{
path: `/payment-receives/import`,
component: lazy(
() => import('@/containers/Sales/PaymentReceives/PaymentReceivesImport'),
),
name: 'payment-receive-import',
breadcrumb: 'Payments Receive Import',
pageTitle: 'Payments Receive Import',
backLink: true,
sidebarExpand: false,
defaultSearchResource: RESOURCES_TYPES.PAYMENT_RECEIVE,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{ {
path: `/payment-receives/:id/edit`, path: `/payment-receives/:id/edit`,
component: lazy( component: lazy(
@@ -989,6 +1027,19 @@ export const getDashboardRoutes = () => [
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN], subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
}, },
// Purchases Credit note. // Purchases Credit note.
{
path: `/vendor-credits/import`,
component: lazy(
() => import('@/containers/Purchases/CreditNotes/VendorCreditsImport'),
),
name: 'vendor-credits-edit',
breadcrumb: 'Vendor Credits Import',
pageTitle: 'Vendor Credits Import',
backLink: true,
sidebarExpand: false,
defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
},
{ {
path: `/vendor-credits/:id/edit`, path: `/vendor-credits/:id/edit`,
component: lazy( component: lazy(