feat: wip export resource data

This commit is contained in:
Ahmed Bouhuolia
2024-05-01 00:20:13 +02:00
parent 8a96c41258
commit 7e89966f20
34 changed files with 1259 additions and 30 deletions

View File

@@ -48,7 +48,6 @@ export class ExportController extends BaseController {
ACCEPT_TYPE.APPLICATION_CSV,
ACCEPT_TYPE.APPLICATION_PDF,
]);
const data = await this.exportResourceApp.export(
tenantId,
query.resource,

View File

@@ -127,12 +127,14 @@ export interface IModelMeta {
defaultSort: IModelMetaDefaultSort;
importable?: boolean;
exportable?: boolean;
importAggregator?: string;
importAggregateOn?: string;
importAggregateBy?: string;
fields: { [key: string]: IModelMetaField };
columns: { [key: string]: IModelMetaColumn };
}
// ----
@@ -161,3 +163,15 @@ export type IModelMetaField2 = IModelMetaFieldCommon2 &
| IModelMetaRelationField2
| IModelMetaCollectionField
);
export interface ImodelMetaColumnMeta {
name: string;
accessor?: string;
exportable?: boolean;
}
interface IModelMetaColumnText {
type: 'text;';
}
export type IModelMetaColumn = ImodelMetaColumnMeta & IModelMetaColumnText;

View File

@@ -7,6 +7,7 @@ export default {
sortField: 'name',
},
importable: true,
exportable: true,
fields: {
name: {
name: 'account.field.name',
@@ -85,6 +86,62 @@ export default {
fieldType: 'date',
},
},
columns: {
name: {
name: 'account.field.name',
type: 'text',
exportable: true,
},
code: {
name: 'account.field.code',
type: 'text',
exportable: true,
},
description: {
name: 'account.field.description',
type: 'text',
exportable: true,
},
rootType: {
name: 'account.field.root_type',
type: 'text',
exportable: true,
},
accountType: {
name: 'account.field.type',
accessor: 'accountTypeLabel',
type: 'enumeration',
exportable: true,
},
accountNormal: {
name: 'account.field.normal',
accessor: 'accountNormalFormatted',
exportable: true,
},
currencyCode: {
name: 'account.field.currency',
exportable: true,
},
bankBalance: {
name: 'account.field.bank_balance',
accessor: 'bankBalanceFormatted',
exportable: true,
},
balance: {
name: 'account.field.bank_balance',
accessor: 'amount',
exportable: true,
},
active: {
name: 'account.field.active',
type: 'boolean',
exportable: true,
},
createdAt: {
name: 'account.field.created_at',
exportable: true,
},
},
fields2: {
name: {
name: 'account.field.name',

View File

@@ -5,6 +5,7 @@ export default {
sortField: 'bill_date',
},
importable: true,
exportable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'billNumber',
@@ -80,6 +81,48 @@ export default {
fieldType: 'date',
},
},
columns: {
billNumber: {
name: 'Bill No.',
type: 'text',
exportable: true,
},
referenceNo: {
name: 'Reference No.',
type: 'text',
exportable: true,
},
billDate: {
name: 'Date',
type: 'date',
exportable: true,
},
dueDate: {
name: 'Due Date',
type: 'date',
exportable: true,
},
vendorId: {
name: 'Vendor',
type: 'text',
exportable: true,
},
exchangeRate: {
name: 'Exchange Rate',
type: 'number',
exportable: true,
},
note: {
name: 'Note',
type: 'text',
exportable: true,
},
open: {
name: 'Open',
type: 'boolean',
exportable: true,
},
},
fields2: {
billNumber: {
name: 'Bill No.',
@@ -132,7 +175,7 @@ export default {
relationModel: 'Item',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the item name or code."
importHint: 'Matches the item name or code.',
},
rate: {
name: 'Rate',

View File

@@ -4,6 +4,7 @@ export default {
sortOrder: 'DESC',
sortField: 'bill_date',
},
exportable: true,
importable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
@@ -67,6 +68,44 @@ export default {
fieldType: 'date',
},
},
columns: {
vendor: {
name: 'bill_payment.field.vendor',
type: 'relation',
exportable: true,
},
paymentDate: {
name: 'bill_payment.field.payment_date',
type: 'date',
required: true,
exportable: true,
},
paymentNumber: {
name: 'bill_payment.field.payment_number',
type: 'text',
exportable: true,
},
paymentAccountId: {
name: 'bill_payment.field.payment_account',
type: 'relation',
exportable: true,
},
exchangeRate: {
name: 'bill_payment.field.exchange_rate',
type: 'number',
exportable: true,
},
statement: {
name: 'bill_payment.field.statement',
type: 'text',
exportable: true,
},
reference: {
name: 'bill_payment.field.reference',
type: 'text',
exportable: true,
},
},
fields2: {
vendorId: {
name: 'bill_payment.field.vendor',
@@ -84,7 +123,7 @@ export default {
name: 'bill_payment.field.payment_number',
fieldType: 'text',
unique: true,
importHint: "The payment number should be unique."
importHint: 'The payment number should be unique.',
},
paymentAccountId: {
name: 'bill_payment.field.payment_account',
@@ -92,7 +131,7 @@ export default {
relationModel: 'Account',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the account name or code."
importHint: 'Matches the account name or code.',
},
exchangeRate: {
name: 'bill_payment.field.exchange_rate',
@@ -120,7 +159,7 @@ export default {
relationModel: 'Bill',
relationImportMatch: 'billNumber',
required: true,
importHint: "Matches the bill number."
importHint: 'Matches the bill number.',
},
paymentAmount: {
name: 'bill_payment.field.entries.payment_amount',

View File

@@ -1,5 +1,6 @@
export default {
importable: true,
exportable: true,
defaultFilterField: 'displayName',
defaultSort: {
sortOrder: 'DESC',
@@ -90,6 +91,135 @@ export default {
},
},
},
columns: {
firstName: {
name: 'vendor.field.first_name',
type: 'text',
},
lastName: {
name: 'vendor.field.last_name',
type: 'text',
},
displayName: {
name: 'vendor.field.display_name',
type: 'text',
},
email: {
name: 'vendor.field.email',
type: 'text',
},
workPhone: {
name: 'vendor.field.work_phone',
type: 'text',
},
personalPhone: {
name: 'vendor.field.personal_pone',
type: 'text',
},
companyName: {
name: 'vendor.field.company_name',
type: 'text',
},
website: {
name: 'vendor.field.website',
type: 'text',
},
createdAt: {
name: 'vendor.field.created_at',
type: 'date',
},
balance: {
name: 'vendor.field.balance',
type: 'number',
},
openingBalance: {
name: 'vendor.field.opening_balance',
type: 'number',
},
openingBalanceAt: {
name: 'vendor.field.opening_balance_at',
type: 'date',
},
currencyCode: {
name: 'vendor.field.currency',
type: 'text',
},
status: {
name: 'vendor.field.status',
},
// Billing Address
billingAddress1: {
name: 'Billing Address 1',
column: 'billing_address1',
type: 'text',
},
billingAddress2: {
name: 'Billing Address 2',
column: 'billing_address2',
type: 'text',
},
billingAddressCity: {
name: 'Billing Address City',
column: 'billing_address_city',
type: 'text',
},
billingAddressCountry: {
name: 'Billing Address Country',
column: 'billing_address_country',
type: 'text',
},
billingAddressPostcode: {
name: 'Billing Address Postcode',
column: 'billing_address_postcode',
type: 'text',
},
billingAddressState: {
name: 'Billing Address State',
column: 'billing_address_state',
type: 'text',
},
billingAddressPhone: {
name: 'Billing Address Phone',
column: 'billing_address_phone',
type: 'text',
},
// Shipping Address
shippingAddress1: {
name: 'Shipping Address 1',
column: 'shipping_address1',
type: 'text',
},
shippingAddress2: {
name: 'Shipping Address 2',
column: 'shipping_address2',
type: 'text',
},
shippingAddressCity: {
name: 'Shipping Address City',
column: 'shipping_address_city',
type: 'text',
},
shippingAddressCountry: {
name: 'Shipping Address Country',
column: 'shipping_address_country',
type: 'text',
},
shippingAddressPostcode: {
name: 'Shipping Address Postcode',
column: 'shipping_address_postcode',
type: 'text',
},
shippingAddressPhone: {
name: 'Shipping Address Phone',
column: 'shipping_address_phone',
type: 'text',
},
shippingAddressState: {
name: 'Shipping Address State',
column: 'shipping_address_state',
type: 'text',
},
},
fields2: {
customerType: {
name: 'Customer Type',

View File

@@ -8,6 +8,7 @@ export default {
sortField: 'name',
},
importable: true,
exportabe: true,
fields: {
payment_date: {
name: 'expense.field.payment_date',
@@ -61,6 +62,47 @@ export default {
fieldType: 'date',
},
},
columns: {
paymentReceive: {
name: 'expense.field.payment_account',
exportable: true,
},
referenceNo: {
name: 'expense.field.reference_no',
type: 'text',
exportable: true,
},
paymentDate: {
name: 'expense.field.payment_date',
type: 'date',
exportable: true,
},
currencyCode: {
name: 'expense.field.currency_code',
type: 'text',
exportable: true,
},
exchangeRate: {
name: 'expense.field.exchange_rate',
type: 'number',
exportable: true,
},
description: {
name: 'expense.field.description',
type: 'text',
exportable: true,
},
categories: {
name: 'expense.field.categories',
type: 'collection',
exportable: true,
},
publish: {
name: 'expense.field.publish',
type: 'boolean',
exportable: true,
},
},
fields2: {
paymentAccountId: {
name: 'expense.field.payment_account',
@@ -68,7 +110,7 @@ export default {
relationModel: 'Account',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the account name or code."
importHint: 'Matches the account name or code.',
},
referenceNo: {
name: 'expense.field.reference_no',
@@ -102,7 +144,7 @@ export default {
relationModel: 'Account',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the account name or code."
importHint: 'Matches the account name or code.',
},
amount: {
name: 'expense.field.amount',

View File

@@ -4,6 +4,54 @@ export default {
sortOrder: 'DESC',
sortField: 'date',
},
columns: {
date: {
name: 'inventory_adjustment.field.date',
column: 'date',
fieldType: 'date',
exportable: true,
},
type: {
name: 'inventory_adjustment.field.type',
column: 'type',
fieldType: 'enumeration',
options: [
{ key: 'increment', name: 'inventory_adjustment.field.type.increment' },
{ key: 'decrement', name: 'inventory_adjustment.field.type.decrement' },
],
exportable: true,
},
adjustmentAccount: {
name: 'inventory_adjustment.field.adjustment_account',
type: 'adjustment_account_id',
exportable: true,
},
reason: {
name: 'inventory_adjustment.field.reason',
type: 'text',
exportable: true,
},
referenceNo: {
name: 'inventory_adjustment.field.reference_no',
type: 'text',
exportable: true,
},
description: {
name: 'inventory_adjustment.field.description',
type: 'text',
exportable: true,
},
publishedAt: {
name: 'inventory_adjustment.field.published_at',
type: 'date',
exportable: true,
},
createdAt: {
name: 'inventory_adjustment.field.created_at',
type: 'date',
exportable: true,
},
},
fields: {
date: {
name: 'inventory_adjustment.field.date',

View File

@@ -1,5 +1,6 @@
export default {
importable: true,
exportable: true,
defaultFilterField: 'name',
defaultSort: {
sortField: 'name',
@@ -121,6 +122,93 @@ export default {
fieldType: 'date',
},
},
columns: {
type: {
name: 'item.field.type',
type: 'text',
exportable: true,
},
name: {
name: 'item.field.name',
type: 'text',
exportable: true,
},
code: {
name: 'item.field.code',
type: 'text',
exportable: true,
},
sellable: {
name: 'item.field.sellable',
type: 'boolean',
exportable: true,
},
purchasable: {
name: 'item.field.purchasable',
type: 'boolean',
exportable: true,
},
sellPrice: {
name: 'item.field.cost_price',
type: 'number',
exportable: true,
},
costPrice: {
name: 'item.field.cost_account',
type: 'number',
exportable: true,
},
costAccount: {
name: 'item.field.sell_account',
type: 'text',
exportable: true,
},
sellAccount: {
name: 'item.field.sell_description',
type: 'text',
exportable: true,
},
inventoryAccount: {
name: 'item.field.inventory_account',
type: 'text',
exportable: true,
},
sellDescription: {
name: 'Sell description',
type: 'text',
exportable: true,
},
purchaseDescription: {
name: 'Purchase description',
type: 'text',
exportable: true,
},
quantityOnHand: {
name: 'item.field.quantity_on_hand',
type: 'number',
exportable: true,
},
note: {
name: 'item.field.note',
type: 'text',
exportable: true,
},
category: {
name: 'item.field.category',
type: 'text',
exportable: true,
},
active: {
name: 'item.field.active',
fieldType: 'boolean',
exportable: true,
},
createdAt: {
name: 'item.field.created_at',
type: 'date',
exportable: true,
},
},
fields2: {
type: {
name: 'item.field.type',
@@ -195,7 +283,7 @@ export default {
fieldType: 'relation',
relationModel: 'ItemCategory',
relationImportMatch: ['name'],
importHint: "Matches the category name."
importHint: 'Matches the category name.',
},
active: {
name: 'item.field.active',

View File

@@ -28,6 +28,28 @@ export default {
columnType: 'date',
},
},
columns: {
name: {
name: 'item_category.field.name',
type: 'text',
exportable: true,
},
description: {
name: 'item_category.field.description',
type: 'text',
exportable: true,
},
count: {
name: 'item_category.field.count',
type: 'text',
exportable: true,
},
createdAt: {
name: 'item_category.field.created_at',
type: 'text',
exportable: true,
},
},
fields2: {
name: {
name: 'item_category.field.name',

View File

@@ -5,6 +5,7 @@ export default {
sortField: 'name',
},
importable: true,
exportable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'journalNumber',
@@ -56,6 +57,48 @@ export default {
fieldType: 'date',
},
},
columns: {
date: {
name: 'manual_journal.field.date',
type: 'date',
exportable: true,
},
journalNumber: {
name: 'manual_journal.field.journal_number',
type: 'text',
exportable: true,
},
reference: {
name: 'manual_journal.field.reference',
type: 'text',
exportable: true,
},
journalType: {
name: 'manual_journal.field.journal_type',
type: 'text',
exportable: true,
},
currencyCode: {
name: 'manual_journal.field.currency',
type: 'text',
exportable: true,
},
exchange_rate: {
name: 'manual_journal.field.exchange_rate',
type: 'number',
exportable: true,
},
description: {
name: 'manual_journal.field.description',
type: 'text',
exportable: true,
},
publish: {
name: 'Publish',
type: 'boolean',
exportable: true,
},
},
fields2: {
date: {
name: 'manual_journal.field.date',

View File

@@ -1,5 +1,6 @@
export default {
importable: true,
exportable: true,
importAggregator: 'group',
importAggregateOn: 'entries',
importAggregateBy: 'paymentReceiveNo',
@@ -57,6 +58,48 @@ export default {
fieldDate: 'date',
},
},
columns: {
customer: {
name: 'payment_receive.field.customer',
type: 'text',
importable: true,
},
paymentDate: {
name: 'payment_receive.field.payment_date',
type: 'date',
importable: true,
},
amount: {
name: 'payment_receive.field.amount',
type: 'number',
importable: true,
},
referenceNo: {
name: 'payment_receive.field.reference_no',
type: 'text',
importable: true,
},
depositAccount: {
name: 'payment_receive.field.deposit_account',
type: 'text',
importable: true,
},
paymentReceiveNo: {
name: 'payment_receive.field.payment_receive_no',
type: 'text',
importable: true,
},
statement: {
name: 'payment_receive.field.statement',
type: 'text',
importable: true,
},
created_at: {
name: 'payment_receive.field.created_at',
type: 'date',
importable: true,
},
},
fields2: {
customerId: {
name: 'payment_receive.field.customer',
@@ -84,12 +127,12 @@ export default {
relationModel: 'Account',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the account name or code."
importHint: 'Matches the account name or code.',
},
paymentReceiveNo: {
name: 'payment_receive.field.payment_receive_no',
fieldType: 'text',
importHint: "The payment number should be unique."
importHint: 'The payment number should be unique.',
},
statement: {
name: 'payment_receive.field.statement',
@@ -108,7 +151,7 @@ export default {
relationModel: 'SaleInvoice',
relationImportMatch: 'invoiceNo',
required: true,
importHint: "Matches the invoice number."
importHint: 'Matches the invoice number.',
},
paymentAmount: {
name: 'payment_receive.field.entries.payment_amount',

View File

@@ -87,6 +87,58 @@ export default {
fieldType: 'date',
},
},
columns: {
invoiceDate: {
name: 'invoice.field.invoice_date',
type: 'date',
exportable: true,
},
dueDate: {
name: 'invoice.field.due_date',
type: 'date',
exportable: true,
},
referenceNo: {
name: 'invoice.field.reference_no',
type: 'text',
exportable: true,
},
invoiceNo: {
name: 'invoice.field.invoice_no',
type: 'text',
exportable: true,
},
customer: {
name: 'invoice.field.customer',
type: 'text',
exportable: true,
},
exchangeRate: {
name: 'invoice.field.exchange_rate',
type: 'number',
exportable: true,
},
currencyCode: {
name: 'invoice.field.currency',
type: 'text',
exportable: true,
},
invoiceMessage: {
name: 'invoice.field.invoice_message',
type: 'text',
exportable: true,
},
termsConditions: {
name: 'invoice.field.terms_conditions',
type: 'text',
exportable: true,
},
delivered: {
name: 'invoice.field.delivered',
type: 'boolean',
exportable: true,
},
},
fields2: {
invoiceDate: {
name: 'invoice.field.invoice_date',
@@ -142,7 +194,7 @@ export default {
relationModel: 'Item',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the item name or code."
importHint: 'Matches the item name or code.',
},
rate: {
name: 'invoice.field.rate',

View File

@@ -77,6 +77,71 @@ export default {
sortCustomQuery: StatusFieldSortQuery,
},
},
columns: {
amount: {
name: 'receipt.field.amount',
column: 'amount',
type: 'number',
exportable: true,
},
depositAccount: {
column: 'deposit_account_id',
name: 'receipt.field.deposit_account',
type: 'relation',
exportable: true,
},
customer: {
name: 'receipt.field.customer',
column: 'customer_id',
type: 'relation',
exportable: true,
},
receiptDate: {
name: 'receipt.field.receipt_date',
column: 'receipt_date',
type: 'date',
exportable: true,
},
receiptNumber: {
name: 'receipt.field.receipt_number',
column: 'receipt_number',
type: 'text',
exportable: true,
},
referenceNo: {
name: 'receipt.field.reference_no',
column: 'reference_no',
type: 'text',
exportable: true,
},
receiptMessage: {
name: 'receipt.field.receipt_message',
column: 'receipt_message',
type: 'text',
exportable: true,
},
statement: {
name: 'receipt.field.statement',
column: 'statement',
type: 'text',
exportable: true,
},
createdAt: {
name: 'receipt.field.created_at',
column: 'created_at',
type: 'date',
exportable: true,
},
status: {
name: 'receipt.field.status',
type: 'enumeration',
options: [
{ key: 'draft', label: 'receipt.field.status.draft' },
{ key: 'closed', label: 'receipt.field.status.closed' },
],
exportable: true,
},
},
fields2: {
receiptDate: {
name: 'Receipt Date',
@@ -126,7 +191,7 @@ export default {
relationModel: 'Item',
relationImportMatch: ['name', 'code'],
required: true,
importHint: "Matches the item name or code."
importHint: 'Matches the item name or code.',
},
rate: {
name: 'invoice.field.rate',

View File

@@ -5,6 +5,7 @@ export default {
sortField: 'created_at',
},
importable: true,
exportable: true,
fields: {
first_name: {
name: 'vendor.field.first_name',
@@ -90,6 +91,135 @@ export default {
},
},
},
columns: {
firstName: {
name: 'vendor.field.first_name',
type: 'text',
},
lastName: {
name: 'vendor.field.last_name',
type: 'text',
},
displayName: {
name: 'vendor.field.display_name',
type: 'text',
},
email: {
name: 'vendor.field.email',
type: 'text',
},
workPhone: {
name: 'vendor.field.work_phone',
type: 'text',
},
personalPhone: {
name: 'vendor.field.personal_pone',
type: 'text',
},
companyName: {
name: 'vendor.field.company_name',
type: 'text',
},
website: {
name: 'vendor.field.website',
type: 'text',
},
createdAt: {
name: 'vendor.field.created_at',
type: 'date',
},
balance: {
name: 'vendor.field.balance',
type: 'number',
},
openingBalance: {
name: 'vendor.field.opening_balance',
type: 'number',
},
openingBalanceAt: {
name: 'vendor.field.opening_balance_at',
type: 'date',
},
currencyCode: {
name: 'vendor.field.currency',
type: 'text',
},
status: {
name: 'vendor.field.status',
},
// Billing Address
billingAddress1: {
name: 'Billing Address 1',
column: 'billing_address1',
type: 'text',
},
billingAddress2: {
name: 'Billing Address 2',
column: 'billing_address2',
type: 'text',
},
billingAddressCity: {
name: 'Billing Address City',
column: 'billing_address_city',
type: 'text',
},
billingAddressCountry: {
name: 'Billing Address Country',
column: 'billing_address_country',
type: 'text',
},
billingAddressPostcode: {
name: 'Billing Address Postcode',
column: 'billing_address_postcode',
type: 'text',
},
billingAddressState: {
name: 'Billing Address State',
column: 'billing_address_state',
type: 'text',
},
billingAddressPhone: {
name: 'Billing Address Phone',
column: 'billing_address_phone',
type: 'text',
},
// Shipping Address
shippingAddress1: {
name: 'Shipping Address 1',
column: 'shipping_address1',
type: 'text',
},
shippingAddress2: {
name: 'Shipping Address 2',
column: 'shipping_address2',
type: 'text',
},
shippingAddressCity: {
name: 'Shipping Address City',
column: 'shipping_address_city',
type: 'text',
},
shippingAddressCountry: {
name: 'Shipping Address Country',
column: 'shipping_address_country',
type: 'text',
},
shippingAddressPostcode: {
name: 'Shipping Address Postcode',
column: 'shipping_address_postcode',
type: 'text',
},
shippingAddressState: {
name: 'Shipping Address State',
column: 'shipping_address_state',
type: 'text',
},
shippingAddressPhone: {
name: 'Shipping Address Phone',
column: 'shipping_address_phone',
type: 'text',
}
},
fields2: {
firstName: {
name: 'vendor.field.first_name',

View File

@@ -8,6 +8,34 @@ export default {
sortField: 'name',
sortOrder: 'DESC',
},
columns: {
date: {
name: 'warehouse_transfer.field.date',
type: 'date',
exportable: true,
},
transaction_number: {
name: 'warehouse_transfer.field.transaction_number',
type: 'text',
exportable: true,
},
status: {
name: 'warehouse_transfer.field.status',
fieldType: 'enumeration',
options: [
{ key: 'draft', label: 'Draft' },
{ key: 'in-transit', label: 'In Transit' },
{ key: 'transferred', label: 'Transferred' },
],
sortable: false,
},
created_at: {
name: 'warehouse_transfer.field.created_at',
column: 'created_at',
columnType: 'date',
fieldType: 'date',
},
},
fields: {
date: {
name: 'warehouse_transfer.field.date',

View File

@@ -0,0 +1,29 @@
import { Inject, Service } from 'typedi';
import { IItemsFilter } from '@/interfaces';
import { CustomersApplication } from './CustomersApplication';
import { Exportable } from '@/services/Export/Exportable';
@Service()
export class CustomersExportable extends Exportable {
@Inject()
private customersApplication: CustomersApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IItemsFilter) {
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
page: 1,
...query,
pageSize: 12,
} as IItemsFilter;
return this.customersApplication
.getCustomers(tenantId, parsedQuery)
.then((output) => output.customers);
}
}

View File

@@ -0,0 +1,29 @@
import { Inject, Service } from 'typedi';
import { IItemsFilter } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import { VendorsApplication } from './VendorsApplication';
@Service()
export class VendorsExportable extends Exportable {
@Inject()
private vendorsApplication: VendorsApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IItemsFilter) {
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
page: 1,
...query,
pageSize: 12,
} as IItemsFilter;
return this.vendorsApplication
.getVendors(tenantId, parsedQuery)
.then((output) => output.vendors);
}
}

View File

@@ -0,0 +1,26 @@
import { Inject, Service } from 'typedi';
import { ICreditNotesQueryDTO } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import ListCreditNotes from './ListCreditNotes';
@Service()
export class CreditNotesExportable extends Exportable {
@Inject()
private getCreditNotes: ListCreditNotes;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId -
* @param {IVendorCreditsQueryDTO} query -
* @returns {}
*/
public exportable(tenantId: number, query: ICreditNotesQueryDTO) {
const parsedQuery = {
...query,
} as ICreditNotesQueryDTO;
return this.getCreditNotes
.getCreditNotesList(tenantId, parsedQuery)
.then((output) => output.creditNotes);
}
}

View File

@@ -0,0 +1,25 @@
import { Inject, Service } from 'typedi';
import { Exportable } from '../Export/Exportable';
import { IExpensesFilter } from '@/interfaces';
import { ExpensesApplication } from './ExpensesApplication';
@Service()
export class ExpensesExportable extends Exportable {
@Inject()
private expensesApplication: ExpensesApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IExpensesFilter) {
const parsedQuery = {
...query,
} as IExpensesFilter;
return this.expensesApplication
.getExpenses(tenantId, parsedQuery)
.then((output) => output.expenses);
}
}

View File

@@ -1,13 +1,27 @@
import Container, { Service } from 'typedi';
import { AccountsExportable } from '../Accounts/AccountsExportable';
import { ExportableRegistry } from './ExportRegistery';
import { ItemsImportable } from '../Items/ItemsImportable';
import { ItemsExportable } from '../Items/ItemsExportable';
import { CustomersExportable } from '../Contacts/Customers/CustomersExportable';
import { VendorsExportable } from '../Contacts/Vendors/VendorsExportable';
import { ExpensesExportable } from '../Expenses/ExpensesExportable';
import { SaleInvoicesExportable } from '../Sales/Invoices/SaleInvoicesExportable';
import { SaleEstimatesExportable } from '../Sales/Estimates/SaleEstimatesExportable';
import { SaleReceiptsExportable } from '../Sales/Receipts/SaleReceiptsExportable';
import { BillsExportable } from '../Purchases/Bills/BillsExportable';
import { PaymentsReceivedExportable } from '../Sales/PaymentReceives/PaymentsReceivedExportable';
import { BillPaymentExportable } from '../Purchases/BillPayments/BillPaymentExportable';
import { ManualJournalsExportable } from '../ManualJournals/ManualJournalExportable';
import { CreditNotesExportable } from '../CreditNotes/CreditNotesExportable';
import { VendorCreditsExportable } from '../Purchases/VendorCredits/VendorCreditsExportable';
@Service()
export class ExportableResources {
private static registry: ExportableRegistry;
/**
* Consttuctor method.
*/
constructor() {
this.boot();
}
@@ -18,6 +32,18 @@ export class ExportableResources {
private importables = [
{ resource: 'Account', exportable: AccountsExportable },
{ resource: 'Item', exportable: ItemsExportable },
{ resource: 'Customer', exportable: CustomersExportable },
{ resource: 'Vendor', exportable: VendorsExportable },
{ resource: 'Expense', exportable: ExpensesExportable },
{ resource: 'SaleInvoice', exportable: SaleInvoicesExportable },
{ resource: 'SaleEstimate', exportable: SaleEstimatesExportable },
{ resource: 'SaleReceipt', exportable: SaleReceiptsExportable },
{ resource: 'Bill', exportable: BillsExportable },
{ resource: 'PaymentReceive', exportable: PaymentsReceivedExportable },
{ resource: 'BillPayment', exportable: BillPaymentExportable },
{ resource: 'ManualJournal', exportable: ManualJournalsExportable },
{ resource: 'CreditNote', exportable: CreditNotesExportable },
{ resource: 'VendorCredit', exportable: VendorCreditsExportable }
];
/**

View File

@@ -3,6 +3,8 @@ import xlsx from 'xlsx';
import { sanitizeResourceName } from '../Import/_utils';
import ResourceService from '../Resource/ResourceService';
import { ExportableResources } from './ExportResources';
import { ServiceError } from '@/exceptions';
import { Errors } from './common';
@Service()
export class ExportResourceService {
@@ -13,10 +15,10 @@ export class ExportResourceService {
private exportableResources: ExportableResources;
/**
*
* @param {number} tenantId
* @param {string} resourceName
* @param {string} format
* Exports the given resource data through csv, xlsx or pdf.
* @param {number} tenantId - Tenant id.
* @param {string} resourceName - Resource name.
* @param {string} format - File format.
*/
async export(tenantId: number, resourceName: string, format: string = 'csv') {
const resource = sanitizeResourceName(resourceName);
@@ -27,24 +29,25 @@ export class ExportResourceService {
const exportable =
this.exportableResources.registry.getExportable(resource);
if (!resourceMeta.exportable) {
throw new ServiceError(Errors.RESOURCE_NOT_EXPORTABLE);
}
const data = await exportable.exportable(tenantId, {});
const exportableColumns = [
{
label: 'Account Normal',
accessor: 'accountNormalFormatted',
},
{
label: 'Account Type',
accessor: 'accountTypeFormatted',
},
];
const exportableColumns = Object.entries(resourceMeta.columns)
.filter(([_, value]) => value.exportable)
.map(([key, value]) => ({
name: value.name,
type: value.type,
accessor: value.accessor || key,
}));
const workbook = xlsx.utils.book_new();
const worksheetData = data.map((item) =>
exportableColumns.map((col) => item[col.accessor])
);
worksheetData.unshift(exportableColumns.map((col) => col.label)); // Add header row
worksheetData.unshift(exportableColumns.map((col) => col.name)); // Add header row
const worksheet = xlsx.utils.aoa_to_sheet(worksheetData);
xlsx.utils.book_append_sheet(workbook, worksheet, 'Exported Data');

View File

@@ -0,0 +1,3 @@
export enum Errors {
RESOURCE_NOT_EXPORTABLE = 'RESOURCE_NOT_EXPORTABLE',
}

View File

@@ -0,0 +1,29 @@
import { Inject, Service } from 'typedi';
import { Exportable } from '../Export/Exportable';
import { IAccountsFilter, IAccountsStructureType } from '@/interfaces';
import ItemCategoriesService from './ItemCategoriesService';
@Service()
export class ItemCategoriesExportable extends Exportable {
@Inject()
private itemCategoriesApplication: ItemCategoriesService;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IAccountsFilter) {
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
inactiveMode: false,
...query,
structure: IAccountsStructureType.Flat,
} as IAccountsFilter;
return this.itemCategoriesApplication
.getItemCategoriesList(tenantId, parsedQuery, {})
.then((output) => output.itemCategories);
}
}

View File

@@ -14,7 +14,13 @@ export class ItemsExportable extends Exportable {
* @returns
*/
public exportable(tenantId: number, query: IItemsFilter) {
const parsedQuery = {} as IItemsFilter;
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
page: 1,
...query,
pageSize: 12,
} as IItemsFilter;
return this.itemsApplication
.getItems(tenantId, parsedQuery)

View File

@@ -0,0 +1,29 @@
import { Inject, Service } from 'typedi';
import { IManualJournalsFilter } from '@/interfaces';
import { Exportable } from '../Export/Exportable';
import { ManualJournalsApplication } from './ManualJournalsApplication';
@Service()
export class ManualJournalsExportable extends Exportable {
@Inject()
private manualJournalsApplication: ManualJournalsApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IManualJournalsFilter) {
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
...query,
page: 1,
pageSize: 12000,
} as IManualJournalsFilter;
return this.manualJournalsApplication
.getManualJournals(tenantId, parsedQuery)
.then((output) => output.manualJournals);
}
}

View File

@@ -0,0 +1,24 @@
import { Inject, Service } from 'typedi';
import { Exportable } from '@/services/Export/Exportable';
import { BillPaymentsApplication } from './BillPaymentsApplication';
@Service()
export class BillPaymentExportable extends Exportable {
@Inject()
private billPaymentsApplication: BillPaymentsApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: any) {
const parsedQuery = {
...query,
} as any;
return this.billPaymentsApplication
.getBillPayments(tenantId, parsedQuery)
.then((output) => output.billPayments);
}
}

View File

@@ -0,0 +1,25 @@
import { Inject, Service } from 'typedi';
import { IBillsFilter } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import { BillsApplication } from './BillsApplication';
@Service()
export class BillsExportable extends Exportable {
@Inject()
private billsApplication: BillsApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: IBillsFilter) {
const parsedQuery = {
...query,
} as IBillsFilter;
return this.billsApplication
.getBills(tenantId, parsedQuery)
.then((output) => output.bills);
}
}

View File

@@ -0,0 +1,26 @@
import { Inject, Service } from 'typedi';
import { IVendorCreditsQueryDTO } from '@/interfaces';
import ListVendorCredits from './ListVendorCredits';
import { Exportable } from '@/services/Export/Exportable';
@Service()
export class VendorCreditsExportable extends Exportable {
@Inject()
private getVendorCredits: ListVendorCredits;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId -
* @param {IVendorCreditsQueryDTO} query -
* @returns {}
*/
public exportable(tenantId: number, query: IVendorCreditsQueryDTO) {
const parsedQuery = {
...query,
} as IVendorCreditsQueryDTO;
return this.getVendorCredits
.getVendorCredits(tenantId, parsedQuery)
.then((output) => output.vendorCredits);
}
}

View File

@@ -113,6 +113,7 @@ export default class ResourceService {
['fields2', qim.$each, 'name'],
['fields2', qim.$each, $enumerationType, 'options', qim.$each, 'label'],
['fields2', qim.$each, $hasFields, 'fields', qim.$each, 'name'],
['columns', qim.$each, 'name'],
];
return this.i18nService.i18nApply(naviagations, meta, tenantId);
}

View File

@@ -0,0 +1,25 @@
import { Inject, Service } from 'typedi';
import { ISalesInvoicesFilter } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import { SaleEstimatesApplication } from './SaleEstimatesApplication';
@Service()
export class SaleEstimatesExportable extends Exportable {
@Inject()
private saleEstimatesApplication: SaleEstimatesApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: ISalesInvoicesFilter) {
const parsedQuery = {
...query,
} as ISalesInvoicesFilter;
return this.saleEstimatesApplication
.getSaleEstimates(tenantId, parsedQuery)
.then((output) => output.salesEstimates);
}
}

View File

@@ -0,0 +1,25 @@
import { Inject, Service } from 'typedi';
import { ISalesInvoicesFilter } from '@/interfaces';
import { SaleInvoiceApplication } from './SaleInvoicesApplication';
import { Exportable } from '@/services/Export/Exportable';
@Service()
export class SaleInvoicesExportable extends Exportable {
@Inject()
private saleInvoicesApplication: SaleInvoiceApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: ISalesInvoicesFilter) {
const parsedQuery = {
...query,
} as ISalesInvoicesFilter;
return this.saleInvoicesApplication
.getSaleInvoices(tenantId, parsedQuery)
.then((output) => output.salesInvoices);
}
}

View File

@@ -0,0 +1,30 @@
import { Inject, Service } from 'typedi';
import { IAccountsStructureType, IPaymentReceivesFilter } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import { PaymentReceivesApplication } from './PaymentReceivesApplication';
@Service()
export class PaymentsReceivedExportable extends Exportable {
@Inject()
private paymentReceivedApp: PaymentReceivesApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @param {IPaymentReceivesFilter} query -
* @returns
*/
public exportable(tenantId: number, query: IPaymentReceivesFilter) {
const parsedQuery = {
sortOrder: 'desc',
columnSortBy: 'created_at',
inactiveMode: false,
...query,
structure: IAccountsStructureType.Flat,
} as IPaymentReceivesFilter;
return this.paymentReceivedApp
.getPaymentReceives(tenantId, parsedQuery)
.then((output) => output.paymentReceives);
}
}

View File

@@ -0,0 +1,25 @@
import { Inject, Service } from 'typedi';
import { ISalesInvoicesFilter, ISalesReceiptsFilter } from '@/interfaces';
import { Exportable } from '@/services/Export/Exportable';
import { SaleReceiptApplication } from './SaleReceiptApplication';
@Service()
export class SaleReceiptsExportable extends Exportable {
@Inject()
private saleReceiptsApp: SaleReceiptApplication;
/**
* Retrieves the accounts data to exportable sheet.
* @param {number} tenantId
* @returns
*/
public exportable(tenantId: number, query: ISalesReceiptsFilter) {
const parsedQuery = {
...query,
} as ISalesInvoicesFilter;
return this.saleReceiptsApp
.getSaleReceipts(tenantId, parsedQuery)
.then((output) => output.data);
}
}