refactor: import resource module to nestjs

This commit is contained in:
Ahmed Bouhuolia
2025-01-13 10:15:57 +02:00
parent 270b421a6c
commit 72818759a5
38 changed files with 479 additions and 424 deletions

View File

@@ -2,6 +2,7 @@ import { Knex } from 'knex';
import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
import { AttachmentLinkDTO } from '../Attachments/Attachments.types';
import { Bill } from './models/Bill';
import { IDynamicListFilter } from '../DynamicListing/DynamicFilter/DynamicFilter.types';
export interface IBillDTO {
vendorId: number;
@@ -42,12 +43,12 @@ export interface IBillEditDTO {
attachments?: AttachmentLinkDTO[];
}
// export interface IBillsFilter extends IDynamicListFilterDTO {
// stringifiedFilterRoles?: string;
// page: number;
// pageSize: number;
// filterQuery?: (q: any) => void;
// }
export interface IBillsFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string;
page: number;
pageSize: number;
filterQuery?: (q: any) => void;
}
export interface IBillCreatedPayload {
// tenantId: number;

View File

@@ -1,25 +1,26 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import * as R from 'ramda';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { Bill } from '../models/Bill';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { BillTransformer } from './Bill.transformer';
import { IBillsFilter } from '../Bills.types';
@Injectable()
export class GetBillsService {
constructor(
private transformer: TransformerInjectable,
private dynamicListService: DynamicListService,
@Inject(Bill.name) private billModel: typeof Bill,
) {}
/**
* Retrieve bills data table list.
* @param {IBillsFilter} billsFilter -
* @param {IBillsFilter} billsFilter -
*/
public async getBills(
filterDTO: IBillsFilter,
): Promise<{
public async getBills(filterDTO: IBillsFilter): Promise<{
bills: Bill;
pagination: IPaginationMeta;
filterMeta: IFilterMeta;
@@ -32,7 +33,8 @@ export class GetBillsService {
Bill,
filter,
);
const { results, pagination } = await Bill.query()
const { results, pagination } = await this.billModel
.query()
.onBuild((builder) => {
builder.withGraphFetched('vendor');
builder.withGraphFetched('entries.item');

View File

@@ -7,7 +7,9 @@ import { GetCreditNotePdf } from './queries/GetCreditNotePdf.serivce';
import {
ICreditNoteEditDTO,
ICreditNoteNewDTO,
ICreditNotesQueryDTO,
} from './types/CreditNotes.types';
import { GetCreditNotesService } from './queries/GetCreditNotes.service';
@Injectable()
export class CreditNoteApplication {
@@ -17,6 +19,7 @@ export class CreditNoteApplication {
private openCreditNoteService: OpenCreditNoteService,
private deleteCreditNoteService: DeleteCreditNoteService,
private getCreditNotePdfService: GetCreditNotePdf,
private getCreditNotesService: GetCreditNotesService,
) {}
/**
@@ -67,4 +70,13 @@ export class CreditNoteApplication {
getCreditNotePdf(creditNoteId: number) {
return this.getCreditNotePdfService.getCreditNotePdf(creditNoteId);
}
/**
* Retrieves the credit notes list.
* @param {ICreditNotesQueryDTO} creditNotesQuery
* @returns {Promise<GetCreditNotesResponse>}
*/
getCreditNotes(creditNotesQuery: ICreditNotesQueryDTO) {
return this.getCreditNotesService.getCreditNotesList(creditNotesQuery);
}
}

View File

@@ -1,8 +1,18 @@
import { Body, Controller, Delete, Param, Post, Put } from '@nestjs/common';
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
Query,
} from '@nestjs/common';
import { CreditNoteApplication } from './CreditNoteApplication.service';
import {
ICreditNoteEditDTO,
ICreditNoteNewDTO,
ICreditNotesQueryDTO,
} from './types/CreditNotes.types';
import { PublicRoute } from '../Auth/Jwt.guard';
@@ -19,6 +29,11 @@ export class CreditNotesController {
return this.creditNoteApplication.createCreditNote(creditNoteDTO);
}
@Get()
getCreditNotes(@Query() creditNotesQuery: ICreditNotesQueryDTO) {
return this.creditNoteApplication.getCreditNotes(creditNotesQuery);
}
@Put(':id')
editCreditNote(
@Param('id') creditNoteId: number,

View File

@@ -1,68 +1,67 @@
// import { Service, Inject } from 'typedi';
// import * as R from 'ramda';
// import { ICreditNotesQueryDTO } from '@/interfaces';
// import DynamicListingService from '@/services/DynamicListing/DynamicListService';
// import BaseCreditNotes from './commands/CommandCreditNoteDTOTransform.service';
// import { CreditNoteTransformer } from './queries/CreditNoteTransformer';
// import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
import * as R from 'ramda';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { ICreditNotesQueryDTO } from '../types/CreditNotes.types';
import { CreditNote } from '../models/CreditNote';
import { CreditNoteTransformer } from './CreditNoteTransformer';
import { Inject } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
// @Service()
// export default class ListCreditNotes extends BaseCreditNotes {
// @Inject()
// private dynamicListService: DynamicListingService;
@Injectable()
export class GetCreditNotesService {
constructor(
private readonly dynamicListService: DynamicListService,
private readonly transformer: TransformerInjectable,
// @Inject()
// private transformer: TransformerInjectable;
@Inject(CreditNote.name)
private readonly creditNoteModel: typeof CreditNote,
) {}
// /**
// * Parses the sale invoice list filter DTO.
// * @param filterDTO
// * @returns
// */
// private parseListFilterDTO = (filterDTO) => {
// return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
// };
/**
* Parses the sale invoice list filter DTO.
* @param filterDTO
* @returns
*/
private parseListFilterDTO = (filterDTO) => {
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
};
// /**
// * Retrieves the paginated and filterable credit notes list.
// * @param {number} tenantId -
// * @param {ICreditNotesQueryDTO} creditNotesQuery -
// */
// public getCreditNotesList = async (
// tenantId: number,
// creditNotesQuery: ICreditNotesQueryDTO
// ) => {
// const { CreditNote } = this.tenancy.models(tenantId);
/**
* Retrieves the paginated and filterable credit notes list.
* @param {number} tenantId -
* @param {ICreditNotesQueryDTO} creditNotesQuery -
*/
public async getCreditNotesList(
creditNotesQuery: ICreditNotesQueryDTO,
): Promise<GetCreditNotesResponse> {
// Parses stringified filter roles.
const filter = this.parseListFilterDTO(creditNotesQuery);
// // Parses stringified filter roles.
// const filter = this.parseListFilterDTO(creditNotesQuery);
// Dynamic list service.
const dynamicFilter = await this.dynamicListService.dynamicList(
CreditNote,
filter,
);
const { results, pagination } = await this.creditNoteModel
.query()
.onBuild((builder) => {
builder.withGraphFetched('entries.item');
builder.withGraphFetched('customer');
dynamicFilter.buildQuery()(builder);
creditNotesQuery?.filterQuery && creditNotesQuery?.filterQuery(builder);
})
.pagination(filter.page - 1, filter.pageSize);
// // Dynamic list service.
// const dynamicFilter = await this.dynamicListService.dynamicList(
// tenantId,
// CreditNote,
// filter
// );
// const { results, pagination } = await CreditNote.query()
// .onBuild((builder) => {
// builder.withGraphFetched('entries.item');
// builder.withGraphFetched('customer');
// dynamicFilter.buildQuery()(builder);
// creditNotesQuery?.filterQuery && creditNotesQuery?.filterQuery(builder);
// })
// .pagination(filter.page - 1, filter.pageSize);
// Transforomes the credit notes to POJO.
const creditNotes = await this.transformer.transform(
results,
new CreditNoteTransformer(),
);
// // Transforomes the credit notes to POJO.
// const creditNotes = await this.transformer.transform(
// tenantId,
// results,
// new CreditNoteTransformer()
// );
// return {
// creditNotes,
// pagination,
// filterMeta: dynamicFilter.getResponseMeta(),
// };
// };
// }
return {
creditNotes,
pagination,
filterMeta: dynamicFilter.getResponseMeta(),
};
}
}

View File

@@ -11,7 +11,7 @@ import { CreditNoteInventoryTransactions } from '../commands/CreditNotesInventor
@Injectable()
export class CreditNoteInventoryTransactionsSubscriber {
constructor(
private readonly inventoryTransactions: CreditNoteInventoryTransactions;
private readonly inventoryTransactions: CreditNoteInventoryTransactions,
) {}
/**
@@ -30,9 +30,9 @@ export class CreditNoteInventoryTransactionsSubscriber {
await this.inventoryTransactions.createInventoryTransactions(
creditNote,
trx
trx,
);
};
}
/**
* Rewrites inventory transactions once credit note edited.
@@ -48,11 +48,11 @@ export class CreditNoteInventoryTransactionsSubscriber {
if (!creditNote.isOpen) return;
await this.inventoryTransactions.editInventoryTransactions(
creditNoteId,
creditNote.id,
creditNote,
trx
trx,
);
};
}
/**
* Reverts inventory transactions once credit note deleted.
@@ -67,8 +67,8 @@ export class CreditNoteInventoryTransactionsSubscriber {
if (!oldCreditNote.isOpen) return;
await this.inventoryTransactions.deleteInventoryTransactions(
creditNoteId,
trx
oldCreditNote.id,
trx,
);
};
}
}

View File

@@ -3,8 +3,11 @@ import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectab
import { Inject, Injectable } from '@nestjs/common';
import * as R from 'ramda';
import { Customer } from '../models/Customer';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { CustomerTransfromer } from './CustomerTransformer';
import {
GetCustomersResponse,
ICustomersFilter,
} from '../types/Customers.types';
@Injectable()
export class GetCustomers {
@@ -26,12 +29,11 @@ export class GetCustomers {
/**
* Retrieve customers paginated list.
* @param {ICustomersFilter} filter - Cusotmers filter.
* @returns {Promise<GetCustomersResponse>}
*/
public async getCustomersList(filterDTO: ICustomersFilter): Promise<{
customers: Customer[];
pagination: IPaginationMeta;
filterMeta: IFilterMeta;
}> {
public async getCustomersList(
filterDTO: ICustomersFilter,
): Promise<GetCustomersResponse> {
// Parses customers list filter DTO.
const filter = this.parseCustomersListFilterDTO(filterDTO);

View File

@@ -1,6 +1,8 @@
import { Knex } from 'knex';
import { Customer } from '../models/Customer';
import { IContactAddressDTO } from '@/modules/Contacts/types/Contacts.types';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
// Customer Interfaces.
// ----------------------------------
@@ -47,12 +49,17 @@ export interface ICustomerEditDTO extends IContactAddressDTO {
active?: boolean;
}
// export interface ICustomersFilter extends IDynamicListFilter {
// stringifiedFilterRoles?: string;
// page?: number;
// pageSize?: number;
// }
export interface ICustomersFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string;
page?: number;
pageSize?: number;
}
export interface GetCustomersResponse {
customers: Customer[];
pagination: IPaginationMeta;
filterMeta: IFilterMeta;
}
// Customer Events.
// ----------------------------------
export interface ICustomerEventCreatedPayload {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import { OPERATION } from '@/libs/logic-evaluation/Parser';
export default class QueryParser {

View File

@@ -1,7 +1,7 @@
import { Service } from 'typedi';
import { AsyncLocalStorage } from 'async_hooks';
import { Injectable } from '@nestjs/common';
@Service()
@Injectable()
export class ImportAls {
private als: AsyncLocalStorage<Map<string, any>>;

View File

@@ -1,6 +1,5 @@
import bluebird from 'bluebird';
import * as R from 'ramda';
import { Inject, Service } from 'typedi';
import { first } from 'lodash';
import { ImportFileDataValidator } from './ImportFileDataValidator';
import { Knex } from 'knex';
@@ -10,40 +9,35 @@ import {
ImportOperSuccess,
ImportableContext,
} from './interfaces';
import { ServiceError } from '@/exceptions';
import { getUniqueImportableValue, trimObject } from './_utils';
import { ImportableResources } from './ImportableResources';
import ResourceService from '../Resource/ResourceService';
import { ResourceService } from '../Resource/ResourceService';
import { Import } from '@/system/models';
import { Injectable } from '@nestjs/common';
import { ServiceError } from '../Items/ServiceError';
@Service()
@Injectable()
export class ImportFileCommon {
@Inject()
private importFileValidator: ImportFileDataValidator;
constructor(
private readonly importFileValidator: ImportFileDataValidator,
private readonly importable: ImportableResources,
private readonly resource: ResourceService,
) {}
@Inject()
private importable: ImportableResources;
@Inject()
private resource: ResourceService;
/**
* Imports the given parsed data to the resource storage through registered importable service.
* @param {number} tenantId -
* @param {string} resourceName - Resource name.
* @param {Record<string, any>} parsedData - Parsed data.
* @param {Knex.Transaction} trx - Knex transaction.
* @returns {Promise<[ImportOperSuccess[], ImportOperError[]]>}
*/
public async import(
tenantId: number,
importFile: Import,
parsedData: Record<string, any>[],
trx?: Knex.Transaction
trx?: Knex.Transaction,
): Promise<[ImportOperSuccess[], ImportOperError[]]> {
const resourceFields = this.resource.getResourceFields2(
tenantId,
importFile.resource
importFile.resource,
);
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(importFile.resource);
@@ -69,14 +63,14 @@ export class ImportFileCommon {
// Validate the DTO object before passing it to the service layer.
await this.importFileValidator.validateData(
resourceFields,
transformedDTO
transformedDTO,
);
try {
// Run the importable function and listen to the errors.
const data = await importable.importable(
tenantId,
transformedDTO,
trx
trx,
);
success.push({ index, data });
} catch (err) {
@@ -117,7 +111,7 @@ export class ImportFileCommon {
*/
public async validateParamsSchema(
resourceName: string,
params: Record<string, any>
params: Record<string, any>,
) {
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);
@@ -143,7 +137,7 @@ export class ImportFileCommon {
public async validateParams(
tenantId: number,
resourceName: string,
params: Record<string, any>
params: Record<string, any>,
) {
const ImportableRegistry = this.importable.registry;
const importable = ImportableRegistry.getImportable(resourceName);

View File

@@ -1,4 +1,3 @@
import { Inject, Service } from 'typedi';
import bluebird from 'bluebird';
import { isUndefined, pickBy, set } from 'lodash';
import { Knex } from 'knex';
@@ -11,17 +10,15 @@ import {
sanitizeSheetData,
getMapToPath,
} from './_utils';
import ResourceService from '../Resource/ResourceService';
import HasTenancyService from '../Tenancy/TenancyService';
import { ResourceService } from '../Resource/ResourceService';
import { CurrencyParsingDTOs } from './_constants';
import { Injectable } from '@nestjs/common';
@Service()
@Injectable()
export class ImportFileDataTransformer {
@Inject()
private resource: ResourceService;
@Inject()
private tenancy: HasTenancyService;
constructor(
private readonly resource: ResourceService,
) {}
/**
* Parses the given sheet data before passing to the service layer.
@@ -30,7 +27,6 @@ export class ImportFileDataTransformer {
* @param {}
*/
public async parseSheetData(
tenantId: number,
importFile: any,
importableFields: ResourceMetaFieldsMap,
data: Record<string, unknown>[],
@@ -46,13 +42,11 @@ export class ImportFileDataTransformer {
);
// Parse the mapped sheet values.
const parsedValues = await this.parseExcelValues(
tenantId,
importableFields,
mappedDTOs,
trx
);
const aggregateValues = this.aggregateParsedValues(
tenantId,
importFile.resource,
parsedValues
);
@@ -66,13 +60,12 @@ export class ImportFileDataTransformer {
* @param {Record<string, any>} parsedData
* @returns {Record<string, any>[]}
*/
public aggregateParsedValues = (
tenantId: number,
public aggregateParsedValues(
resourceName: string,
parsedData: Record<string, any>[]
): Record<string, any>[] => {
): Record<string, any>[] {
let _value = parsedData;
const meta = this.resource.getResourceMeta(tenantId, resourceName);
const meta = this.resource.getResourceMeta(resourceName);
if (meta.importAggregator === 'group') {
_value = aggregate(
@@ -113,7 +106,6 @@ export class ImportFileDataTransformer {
* @returns {Record<string, any>}
*/
public async parseExcelValues(
tenantId: number,
fields: ResourceMetaFieldsMap,
valueDTOs: Record<string, any>[],
trx?: Knex.Transaction

View File

@@ -1,10 +1,11 @@
import { Service } from 'typedi';
import { ImportInsertError, ResourceMetaFieldsMap } from './interfaces';
import { ERRORS, convertFieldsToYupValidation } from './_utils';
import { IModelMeta } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import { Injectable } from '@nestjs/common';
import { IModelMeta } from '@/interfaces/Model';
import { ServiceError } from '../Items/ServiceError';
@Service()
@Injectable()
export class ImportFileDataValidator {
/**
* Validates the given resource is importable.

View File

@@ -1,19 +1,18 @@
import { Injectable } from '@nestjs/common';
import { fromPairs, isUndefined } from 'lodash';
import { Inject, Service } from 'typedi';
import {
ImportDateFormats,
ImportFileMapPOJO,
ImportMappingAttr,
} from './interfaces';
import ResourceService from '../Resource/ResourceService';
import { ServiceError } from '@/exceptions';
import { ResourceService } from '../Resource/ResourceService';
import { ServiceError } from '../Items/ServiceError';
import { ERRORS } from './_utils';
import { Import } from '@/system/models';
import { Import } from './models/Import';
@Service()
@Injectable()
export class ImportFileMapping {
@Inject()
private resource: ResourceService;
constructor(private readonly resource: ResourceService) {}
/**
* Mapping the excel sheet columns with resource columns.
@@ -22,16 +21,15 @@ export class ImportFileMapping {
* @param {ImportMappingAttr} maps
*/
public async mapping(
tenantId: number,
importId: string,
maps: ImportMappingAttr[]
maps: ImportMappingAttr[],
): Promise<ImportFileMapPOJO> {
const importFile = await Import.query()
.findOne('filename', importId)
.throwIfNotFound();
// Invalidate the from/to map attributes.
this.validateMapsAttrs(tenantId, importFile, maps);
this.validateMapsAttrs(importFile, maps);
// @todo validate the required fields.
@@ -39,7 +37,7 @@ export class ImportFileMapping {
this.validateDuplicatedMapAttrs(maps);
// Validate the date format mapping.
this.validateDateFormatMapping(tenantId, importFile.resource, maps);
this.validateDateFormatMapping(importFile.resource, maps);
const mappingStringified = JSON.stringify(maps);
@@ -61,17 +59,10 @@ export class ImportFileMapping {
* @param {ImportMappingAttr[]} maps
* @throws {ServiceError(ERRORS.INVALID_MAP_ATTRS)}
*/
private validateMapsAttrs(
tenantId: number,
importFile: any,
maps: ImportMappingAttr[]
) {
const fields = this.resource.getResourceFields2(
tenantId,
importFile.resource
);
private validateMapsAttrs(importFile: any, maps: ImportMappingAttr[]) {
const fields = this.resource.getResourceFields2(importFile.resource);
const columnsMap = fromPairs(
importFile.columnsParsed.map((field) => [field, ''])
importFile.columnsParsed.map((field) => [field, '']),
);
const invalid = [];
@@ -130,14 +121,10 @@ export class ImportFileMapping {
* @param {ImportMappingAttr[]} maps
*/
private validateDateFormatMapping(
tenantId: number,
resource: string,
maps: ImportMappingAttr[]
maps: ImportMappingAttr[],
) {
const fields = this.resource.getResourceImportableFields(
tenantId,
resource
);
const fields = this.resource.getResourceImportableFields(resource);
// @todo Validate date type of the nested fields.
maps.forEach((map) => {
if (

View File

@@ -1,16 +1,11 @@
import { Inject, Service } from 'typedi';
import HasTenancyService from '../Tenancy/TenancyService';
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
import { Import } from './models/Import';
import { ImportFileMetaTransformer } from './ImportFileMetaTransformer';
import { Import } from '@/system/models';
import { Injectable } from '@nestjs/common';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
@Service()
@Injectable()
export class ImportFileMeta {
@Inject()
private tenancy: HasTenancyService;
@Inject()
private transformer: TransformerInjectable;
constructor(private readonly transformer: TransformerInjectable) {}
/**
* Retrieves the import meta of the given import model id.
@@ -18,16 +13,15 @@ export class ImportFileMeta {
* @param {number} importId
* @returns {}
*/
async getImportMeta(tenantId: number, importId: string) {
async getImportMeta(importId: string) {
const importFile = await Import.query()
.where('tenantId', tenantId)
.findOne('importId', importId);
// Retrieves the transformed accounts collection.
return this.transformer.transform(
tenantId,
importFile,
new ImportFileMetaTransformer()
new ImportFileMetaTransformer(),
);
}
}

View File

@@ -1,4 +1,4 @@
import { Transformer } from '@/lib/Transformer/Transformer';
import { Transformer } from '../Transformer/Transformer';
export class ImportFileMetaTransformer extends Transformer {
/**
@@ -11,9 +11,9 @@ export class ImportFileMetaTransformer extends Transformer {
public excludeAttributes = (): string[] => {
return ['id', 'filename', 'columns', 'mappingParsed', 'mapping'];
}
};
map(importFile) {
return importFile.mappingParsed;
return importFile.mappingParsed;
}
}

View File

@@ -1,49 +1,36 @@
import { Inject, Service } from 'typedi';
import HasTenancyService from '../Tenancy/TenancyService';
import { ImportFilePreviewPOJO } from './interfaces';
import { ImportFileProcess } from './ImportFileProcess';
import { ImportAls } from './ImportALS';
import { Injectable } from '@nestjs/common';
@Service()
@Injectable()
export class ImportFilePreview {
@Inject()
private tenancy: HasTenancyService;
@Inject()
private importFile: ImportFileProcess;
@Inject()
private importAls: ImportAls;
constructor(
private readonly importFile: ImportFileProcess,
private readonly importAls: ImportAls,
) {}
/**
* Preview the imported file results before commiting the transactions.
* @param {number} tenantId -
* @param {string} importId -
* @param {string} importId -
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async preview(
tenantId: number,
importId: string
): Promise<ImportFilePreviewPOJO> {
public async preview(importId: string): Promise<ImportFilePreviewPOJO> {
return this.importAls.runPreview<Promise<ImportFilePreviewPOJO>>(() =>
this.previewAlsRun(tenantId, importId)
this.previewAlsRun(importId),
);
}
/**
* Preview the imported file results before commiting the transactions.
* @param {number} tenantId
* @param {number} importId
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async previewAlsRun(
tenantId: number,
importId: string
): Promise<ImportFilePreviewPOJO> {
public async previewAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
const knex = this.tenancy.knex(tenantId);
const trx = await knex.transaction({ isolationLevel: 'read uncommitted' });
const meta = await this.importFile.import(tenantId, importId, trx);
const meta = await this.importFile.import(importId, trx);
// Rollback the successed transaction.
await trx.rollback();

View File

@@ -1,29 +1,23 @@
import { Inject, Service } from 'typedi';
import { chain } from 'lodash';
import { Knex } from 'knex';
import { ServiceError } from '@/exceptions';
import { ERRORS, getUnmappedSheetColumns, readImportFile } from './_utils';
import { ImportFileCommon } from './ImportFileCommon';
import { ImportFileDataTransformer } from './ImportFileDataTransformer';
import ResourceService from '../Resource/ResourceService';
import UnitOfWork from '../UnitOfWork';
import { ImportFilePreviewPOJO } from './interfaces';
import { Import } from '@/system/models';
import { parseSheetData } from './sheet_utils';
import { Injectable } from '@nestjs/common';
import { ResourceService } from '../Resource/ResourceService';
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
import { ServiceError } from '../Items/ServiceError';
@Service()
@Injectable()
export class ImportFileProcess {
@Inject()
private resource: ResourceService;
@Inject()
private importCommon: ImportFileCommon;
@Inject()
private importParser: ImportFileDataTransformer;
@Inject()
private uow: UnitOfWork;
constructor(
private readonly resource: ResourceService,
private readonly importCommon: ImportFileCommon,
private readonly importParser: ImportFileDataTransformer,
private readonly uow: UnitOfWork,
) {}
/**
* Preview the imported file results before commiting the transactions.
@@ -32,9 +26,8 @@ export class ImportFileProcess {
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async import(
tenantId: number,
importId: string,
trx?: Knex.Transaction
trx?: Knex.Transaction,
): Promise<ImportFilePreviewPOJO> {
const importFile = await Import.query()
.findOne('importId', importId)
@@ -51,7 +44,7 @@ export class ImportFileProcess {
const [sheetData, sheetColumns] = parseSheetData(buffer);
const resource = importFile.resource;
const resourceFields = this.resource.getResourceFields2(tenantId, resource);
const resourceFields = this.resource.getResourceFields2(resource);
// Runs the importing operation with ability to return errors that will happen.
const [successedImport, failedImport, allData] =
@@ -64,18 +57,18 @@ export class ImportFileProcess {
importFile,
resourceFields,
sheetData,
trx
trx,
);
const [successedImport, failedImport] =
await this.importCommon.import(
tenantId,
importFile,
parsedData,
trx
trx,
);
return [successedImport, failedImport, parsedData];
},
trx
trx,
);
const mapping = importFile.mappingParsed;
const errors = chain(failedImport)

View File

@@ -1,64 +1,46 @@
import { Inject, Service } from 'typedi';
import HasTenancyService from '../Tenancy/TenancyService';
import { ImportFilePreviewPOJO } from './interfaces';
import { ImportFileProcess } from './ImportFileProcess';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
import { IImportFileCommitedEventPayload } from '@/interfaces/Import';
import { ImportAls } from './ImportALS';
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { events } from '@/common/events/events';
@Service()
@Injectable()
export class ImportFileProcessCommit {
@Inject()
private tenancy: HasTenancyService;
@Inject()
private importFile: ImportFileProcess;
@Inject()
private importAls: ImportAls;
@Inject()
private eventPublisher: EventPublisher;
constructor(
private readonly importFile: ImportFileProcess,
private readonly importAls: ImportAls,
private readonly eventEmitter: EventEmitter2,
) {}
/**
* Commits the imported file under ALS.
* @param {number} tenantId
* @param {string} importId
* @param {string} importId - The import ID.
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public commit(
tenantId: number,
importId: string
): Promise<ImportFilePreviewPOJO> {
public commit(importId: string): Promise<ImportFilePreviewPOJO> {
return this.importAls.runCommit<Promise<ImportFilePreviewPOJO>>(() =>
this.commitAlsRun(tenantId, importId)
this.commitAlsRun(importId),
);
}
/**
* Commits the imported file.
* @param {number} tenantId
* @param {number} importId
* @param {number} importId - The import ID.
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async commitAlsRun(
tenantId: number,
importId: string
): Promise<ImportFilePreviewPOJO> {
const knex = this.tenancy.knex(tenantId);
public async commitAlsRun(importId: string): Promise<ImportFilePreviewPOJO> {
const trx = await knex.transaction({ isolationLevel: 'read uncommitted' });
const meta = await this.importFile.import(tenantId, importId, trx);
const meta = await this.importFile.import(importId, trx);
// Commit the successed transaction.
await trx.commit();
// Triggers `onImportFileCommitted` event.
await this.eventPublisher.emitAsync(events.import.onImportCommitted, {
await this.eventEmitter.emitAsync(events.import.onImportCommitted, {
meta,
importId,
tenantId,
} as IImportFileCommitedEventPayload);
return meta;

View File

@@ -1,4 +1,3 @@
import { Inject, Service } from 'typedi';
import {
deleteImportFile,
getResourceColumns,
@@ -6,23 +5,21 @@ import {
sanitizeResourceName,
validateSheetEmpty,
} from './_utils';
import ResourceService from '../Resource/ResourceService';
import { ResourceService } from '../Resource/ResourceService';
import { ImportFileCommon } from './ImportFileCommon';
import { ImportFileDataValidator } from './ImportFileDataValidator';
import { ImportFileUploadPOJO } from './interfaces';
import { Import } from '@/system/models';
import { parseSheetData } from './sheet_utils';
import { Injectable } from '@nestjs/common';
@Service()
@Injectable()
export class ImportFileUploadService {
@Inject()
private resourceService: ResourceService;
@Inject()
private importFileCommon: ImportFileCommon;
@Inject()
private importValidator: ImportFileDataValidator;
constructor(
private resourceService: ResourceService,
private importFileCommon: ImportFileCommon,
private importValidator: ImportFileDataValidator,
) {}
/**
* Imports the specified file for the given resource.
@@ -34,17 +31,16 @@ export class ImportFileUploadService {
* @returns {Promise<ImportFileUploadPOJO>}
*/
public async import(
tenantId: number,
resourceName: string,
filename: string,
params: Record<string, number | string>
params: Record<string, number | string>,
): Promise<ImportFileUploadPOJO> {
try {
return await this.importUnhandled(
tenantId,
resourceName,
filename,
params
params,
);
} catch (err) {
deleteImportFile(filename);
@@ -61,16 +57,12 @@ export class ImportFileUploadService {
* @returns {Promise<ImportFileUploadPOJO>}
*/
public async importUnhandled(
tenantId: number,
resourceName: string,
filename: string,
params: Record<string, number | string>
params: Record<string, number | string>,
): Promise<ImportFileUploadPOJO> {
const resource = sanitizeResourceName(resourceName);
const resourceMeta = this.resourceService.getResourceMeta(
tenantId,
resource
);
const resourceMeta = this.resourceService.getResourceMeta(resource);
// Throw service error if the resource does not support importing.
this.importValidator.validateResourceImportable(resourceMeta);
@@ -107,7 +99,7 @@ export class ImportFileUploadService {
});
const resourceColumnsMap = this.resourceService.getResourceFields2(
tenantId,
resource
resource,
);
const resourceColumns = getResourceColumns(resourceColumnsMap);

View File

@@ -1,10 +1,10 @@
import moment from 'moment';
import bluebird from 'bluebird';
import { Import } from '@/system/models';
import { deleteImportFile } from './_utils';
import { Service } from 'typedi';
import { Injectable } from '@nestjs/common';
import { Import } from './models/Import';
@Service()
@Injectable()
export class ImportDeleteExpiredFiles {
/**
* Delete expired files.

View File

@@ -0,0 +1,25 @@
import { Module } from '@nestjs/common';
import { ImportResourceApplication } from './ImportResourceApplication';
import { ImportFileUploadService } from './ImportFileUpload';
import { ImportFileMapping } from './ImportFileMapping';
import { ImportFileProcess } from './ImportFileProcess';
import { ImportFilePreview } from './ImportFilePreview';
import { ImportFileProcessCommit } from './ImportFileProcessCommit';
import { ImportFileMeta } from './ImportFileMeta';
import { ImportSampleService } from './ImportSample';
@Module({
imports: [],
providers: [
ImportResourceApplication,
ImportFileUploadService,
ImportFileMapping,
ImportFileProcess,
ImportFilePreview,
ImportSampleService,
ImportFileMeta,
ImportFileProcessCommit,
],
exports: [ImportResourceApplication],
})
export class ImportResourceModule {}

View File

@@ -1,4 +1,3 @@
import { Inject } from 'typedi';
import { ImportFileUploadService } from './ImportFileUpload';
import { ImportFileMapping } from './ImportFileMapping';
import { ImportMappingAttr } from './interfaces';
@@ -7,100 +6,75 @@ import { ImportFilePreview } from './ImportFilePreview';
import { ImportSampleService } from './ImportSample';
import { ImportFileMeta } from './ImportFileMeta';
import { ImportFileProcessCommit } from './ImportFileProcessCommit';
import { Injectable } from '@nestjs/common';
@Inject()
@Injectable()
export class ImportResourceApplication {
@Inject()
private importFileService: ImportFileUploadService;
@Inject()
private importMappingService: ImportFileMapping;
@Inject()
private importProcessService: ImportFileProcess;
@Inject()
private ImportFilePreviewService: ImportFilePreview;
@Inject()
private importSampleService: ImportSampleService;
@Inject()
private importMetaService: ImportFileMeta;
@Inject()
private importProcessCommit: ImportFileProcessCommit;
constructor(
private readonly importFileService: ImportFileUploadService,
private readonly importMappingService: ImportFileMapping,
private readonly importProcessService: ImportFileProcess,
private readonly ImportFilePreviewService: ImportFilePreview,
private readonly importSampleService: ImportSampleService,
private readonly importMetaService: ImportFileMeta,
private readonly importProcessCommit: ImportFileProcessCommit,
) {}
/**
* Reads the imported file and stores the import file meta under unqiue id.
* @param {number} tenantId -
* @param {string} resource - Resource name.
* @param {string} fileName - File name.
* @returns {Promise<ImportFileUploadPOJO>}
*/
public async import(
tenantId: number,
resource: string,
filename: string,
params: Record<string, any>
params: Record<string, any>,
) {
return this.importFileService.import(tenantId, resource, filename, params);
return this.importFileService.import(resource, filename, params);
}
/**
* Mapping the excel sheet columns with resource columns.
* @param {number} tenantId
* @param {number} importId - Import id.
* @param {ImportMappingAttr} maps
*/
public async mapping(
tenantId: number,
importId: string,
maps: ImportMappingAttr[]
) {
return this.importMappingService.mapping(tenantId, importId, maps);
public async mapping(importId: string, maps: ImportMappingAttr[]) {
return this.importMappingService.mapping(importId, maps);
}
/**
* Preview the mapped results before process importing.
* @param {number} tenantId
* @param {number} importId - Import id.
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async preview(tenantId: number, importId: string) {
return this.ImportFilePreviewService.preview(tenantId, importId);
public async preview(importId: string) {
return this.ImportFilePreviewService.preview(importId);
}
/**
* Process the import file sheet through service for creating entities.
* @param {number} tenantId
* @param {number} importId
* @returns {Promise<ImportFilePreviewPOJO>}
*/
public async process(tenantId: number, importId: string) {
return this.importProcessCommit.commit(tenantId, importId);
public async process(importId: string) {
return this.importProcessCommit.commit(importId);
}
/**
* Retrieves the import meta of the given import id.
* @param {number} tenantId -
* @param {string} importId - Import id.
* @returns {}
*/
public importMeta(tenantId: number, importId: string) {
return this.importMetaService.getImportMeta(tenantId, importId);
public importMeta(importId: string) {
return this.importMetaService.getImportMeta(importId);
}
/**
* Retrieves the csv/xlsx sample sheet of the given
* @param {number} tenantId
* @param {number} resource - Resource name.
*/
public sample(
tenantId: number,
resource: string,
format: 'csv' | 'xlsx' = 'csv'
) {
return this.importSampleService.sample(tenantId, resource, format);
public sample(resource: string, format: 'csv' | 'xlsx' = 'csv') {
return this.importSampleService.sample(resource, format);
}
}

View File

@@ -1,22 +1,21 @@
import XLSX from 'xlsx';
import { Inject, Service } from 'typedi';
import { ImportableResources } from './ImportableResources';
import { sanitizeResourceName } from './_utils';
import { Injectable } from '@nestjs/common';
@Service()
@Injectable()
export class ImportSampleService {
@Inject()
private importable: ImportableResources;
constructor(
private readonly importable: ImportableResources,
) {}
/**
* Retrieves the sample sheet of the given resource.
* @param {number} tenantId
* @param {string} resource
* @param {string} format
* @returns {Buffer | string}
*/
public sample(
tenantId: number,
resource: string,
format: 'csv' | 'xlsx'
): Buffer | string {

View File

@@ -6,11 +6,16 @@ import {
Param,
Post,
Put,
Query,
} from '@nestjs/common';
import { InventoryAdjustmentsApplicationService } from './InventoryAdjustmentsApplication.service';
import { IQuickInventoryAdjustmentDTO } from './types/InventoryAdjustments.types';
import {
IInventoryAdjustmentsFilter,
IQuickInventoryAdjustmentDTO,
} from './types/InventoryAdjustments.types';
import { InventoryAdjustment } from './models/InventoryAdjustment';
import { PublicRoute } from '../Auth/Jwt.guard';
import { IPaginationMeta } from '@/interfaces/Model';
@Controller('inventory-adjustments')
@PublicRoute()
@@ -37,6 +42,18 @@ export class InventoryAdjustmentsController {
);
}
@Get()
public async getInventoryAdjustments(
@Query() filterDTO: IInventoryAdjustmentsFilter,
): Promise<{
inventoryAdjustments: InventoryAdjustment[];
pagination: IPaginationMeta;
}> {
return this.inventoryAdjustmentsApplicationService.getInventoryAdjustments(
filterDTO,
);
}
@Get(':id')
public async getInventoryAdjustment(
@Param('id') inventoryAdjustmentId: number,

View File

@@ -2,9 +2,14 @@ import { Injectable } from '@nestjs/common';
import { DeleteInventoryAdjustmentService } from './commands/DeleteInventoryAdjustment.service';
import { PublishInventoryAdjustmentService } from './commands/PublishInventoryAdjustment.service';
import { CreateQuickInventoryAdjustmentService } from './commands/CreateQuickInventoryAdjustment.service';
import { IQuickInventoryAdjustmentDTO } from './types/InventoryAdjustments.types';
import {
IInventoryAdjustmentsFilter,
IQuickInventoryAdjustmentDTO,
} from './types/InventoryAdjustments.types';
import { InventoryAdjustment } from './models/InventoryAdjustment';
import { GetInventoryAdjustmentService } from './queries/GetInventoryAdjustment.service';
import { GetInventoryAdjustmentsService } from './queries/GetInventoryAdjustments.service';
import { IPaginationMeta } from '@/interfaces/Model';
@Injectable()
export class InventoryAdjustmentsApplicationService {
@@ -13,6 +18,7 @@ export class InventoryAdjustmentsApplicationService {
private readonly deleteInventoryAdjustmentService: DeleteInventoryAdjustmentService,
private readonly publishInventoryAdjustmentService: PublishInventoryAdjustmentService,
private readonly getInventoryAdjustmentService: GetInventoryAdjustmentService,
private readonly getInventoryAdjustmentsService: GetInventoryAdjustmentsService,
) {}
/**
@@ -63,4 +69,19 @@ export class InventoryAdjustmentsApplicationService {
inventoryAdjustmentId,
);
}
/**
* Retrieves the inventory adjustments paginated list.
* @param {IInventoryAdjustmentsFilter} adjustmentsFilter - Inventory adjustments filter.
*/
public async getInventoryAdjustments(
filterDTO: IInventoryAdjustmentsFilter,
): Promise<{
inventoryAdjustments: InventoryAdjustment[];
pagination: IPaginationMeta;
}> {
return this.getInventoryAdjustmentsService.getInventoryAdjustments(
filterDTO,
);
}
}

View File

@@ -1,56 +1,65 @@
// import { InventoryAdjustmentTransformer } from "../InventoryAdjustmentTransformer";
// import { InventoryAdjustment } from "../models/InventoryAdjustment";
// import { IInventoryAdjustmentsFilter } from "../types/InventoryAdjustments.types";
import { Inject } from '@nestjs/common';
import * as R from 'ramda';
import { IPaginationMeta } from '@/interfaces/Model';
import { InventoryAdjustmentTransformer } from '../InventoryAdjustmentTransformer';
import { InventoryAdjustment } from '../models/InventoryAdjustment';
import { IInventoryAdjustmentsFilter } from '../types/InventoryAdjustments.types';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
// import { TransformerInjectable } from "@/modules/Transformer/TransformerInjectable.service";
export class GetInventoryAdjustmentsService {
constructor(
public readonly transformer: TransformerInjectable,
private readonly dynamicListService: DynamicListService,
// export class GetInventoryAdjustmentsService {
@Inject(InventoryAdjustment.name)
private readonly inventoryAdjustmentModel: typeof InventoryAdjustment,
) {}
/**
* Retrieve the inventory adjustments paginated list.
* @param {number} tenantId
* @param {IInventoryAdjustmentsFilter} adjustmentsFilter
*/
public async getInventoryAdjustments(
filterDTO: IInventoryAdjustmentsFilter,
): Promise<{
inventoryAdjustments: InventoryAdjustment[];
pagination: IPaginationMeta;
}> {
// Parses inventory adjustments list filter DTO.
const filter = this.parseListFilterDTO(filterDTO);
// constructor(
// public readonly transformer: TransformerInjectable,
// private readonly inventoryAdjustmentModel: typeof InventoryAdjustment,
// ) {
// }
// /**
// * Retrieve the inventory adjustments paginated list.
// * @param {number} tenantId
// * @param {IInventoryAdjustmentsFilter} adjustmentsFilter
// */
// public async getInventoryAdjustments(
// tenantId: number,
// filterDTO: IInventoryAdjustmentsFilter,
// ): Promise<{
// inventoryAdjustments: IInventoryAdjustment[];
// pagination: IPaginationMeta;
// }> {
// Dynamic list service.
const dynamicFilter = await this.dynamicListService.dynamicList(
InventoryAdjustment,
filter,
);
const { results, pagination } = await this.inventoryAdjustmentModel
.query()
.onBuild((query) => {
query.withGraphFetched('entries.item');
query.withGraphFetched('adjustmentAccount');
// // Parses inventory adjustments list filter DTO.
// const filter = this.parseListFilterDTO(filterDTO);
dynamicFilter.buildQuery()(query);
})
.pagination(filter.page - 1, filter.pageSize);
// // Dynamic list service.
// const dynamicFilter = await this.dynamicListService.dynamicList(
// tenantId,
// InventoryAdjustment,
// filter,
// );
// const { results, pagination } = await this.inventoryAdjustmentModel.query()
// .onBuild((query) => {
// query.withGraphFetched('entries.item');
// query.withGraphFetched('adjustmentAccount');
// Retrieves the transformed inventory adjustments.
const inventoryAdjustments = await this.transformer.transform(
results,
new InventoryAdjustmentTransformer(),
);
return {
inventoryAdjustments,
pagination,
};
}
// dynamicFilter.buildQuery()(query);
// })
// .pagination(filter.page - 1, filter.pageSize);
// // Retrieves the transformed inventory adjustments.
// const inventoryAdjustments = await this.transformer.transform(
// results,
// new InventoryAdjustmentTransformer(),
// );
// return {
// inventoryAdjustments,
// pagination,
// };
// }
// }
/**
* Parses inventory adjustments list filter DTO.
* @param filterDTO -
*/
private parseListFilterDTO(filterDTO) {
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
}
}

View File

@@ -1,5 +1,8 @@
import { Injectable } from '@nestjs/common';
import { IItemCategoryOTD } from './ItemCategory.interfaces';
import {
IItemCategoriesFilter,
IItemCategoryOTD,
} from './ItemCategory.interfaces';
import { CreateItemCategoryService } from './commands/CreateItemCategory.service';
import { DeleteItemCategoryService } from './commands/DeleteItemCategory.service';
import { EditItemCategoryService } from './commands/EditItemCategory.service';
@@ -75,7 +78,7 @@ export class ItemCategoryApplication {
/**
* Retrieves the item categories list.
* @param {IItemCategoriesFilter} filterDTO - The item categories filter DTO.
* @returns {Promise<IItemCategory[]>}
* @returns {Promise<GetItemCategoriesResponse>}
*/
public getItemCategories(filterDTO: IItemCategoriesFilter) {
return this.getItemCategoriesService.getItemCategories(filterDTO);

View File

@@ -6,9 +6,14 @@ import {
Param,
Post,
Put,
Query,
} from '@nestjs/common';
import { ItemCategoryApplication } from './ItemCategory.application';
import { IItemCategoryOTD } from './ItemCategory.interfaces';
import {
GetItemCategoriesResponse,
IItemCategoriesFilter,
IItemCategoryOTD,
} from './ItemCategory.interfaces';
import { PublicRoute } from '../Auth/Jwt.guard';
@Controller('item-categories')
@@ -29,6 +34,13 @@ export class ItemCategoryController {
);
}
@Get()
async getItemCategories(
@Query() filterDTO: IItemCategoriesFilter,
): Promise<GetItemCategoriesResponse> {
return this.itemCategoryApplication.getItemCategories(filterDTO);
}
@Put(':id')
async editItemCategory(
@Param('id') id: number,

View File

@@ -2,7 +2,8 @@ import { Knex } from 'knex';
// import { IDynamicListFilterDTO } from './DynamicFilter';
// import { ISystemUser } from './User';
import { ItemCategory } from './models/ItemCategory.model';
import { IDynamicListFilter } from '../DynamicListing/DynamicFilter/DynamicFilter.types';
import { IFilterMeta } from '@/interfaces/Model';
export interface IItemCategoryOTD {
name: string;
@@ -35,3 +36,13 @@ export interface IItemCategoryDeletedPayload {
itemCategoryId: number;
oldItemCategory: ItemCategory;
}
export interface IItemCategoriesFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string;
filterQuery?: (trx: Knex.Transaction) => void;
}
export interface GetItemCategoriesResponse {
itemCategories: ItemCategory[];
filterMeta: IFilterMeta;
}

View File

@@ -2,6 +2,10 @@ import * as R from 'ramda';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { ItemCategory } from '../models/ItemCategory.model';
import { Inject } from '@nestjs/common';
import {
GetItemCategoriesResponse,
IItemCategoriesFilter,
} from '../ItemCategory.interfaces';
export class GetItemCategoriesService {
constructor(
@@ -25,12 +29,12 @@ export class GetItemCategoriesService {
/**
* Retrieve item categories list.
* @param {number} tenantId
* @param filter
* @param {IItemCategoriesFilter} filterDTO
* @returns {Promise<GetItemCategoriesResponse>}
*/
public async getItemCategories(
filterDTO: IItemCategoriesFilter,
): Promise<{ itemCategories: ItemCategory[]; filterMeta: IFilterMeta }> {
): Promise<GetItemCategoriesResponse> {
// Parses list filter DTO.
const filter = this.parsesListFilterDTO(filterDTO);

View File

@@ -158,10 +158,7 @@ export class PaymentReceivesApplication {
* @param {PaymentReceive} paymentReceive
* @returns
*/
public getPaymentReceivePdf = (
tenantId: number,
paymentReceiveId: number,
) => {
public getPaymentReceivePdf = (paymentReceiveId: number) => {
return this.getPaymentReceivePdfService.getPaymentReceivePdf(
paymentReceiveId,
);

View File

@@ -5,6 +5,7 @@ import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectab
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { PaymentReceived } from '../models/PaymentReceived';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { IPaymentsReceivedFilter } from '../types/PaymentReceived.types';
@Injectable()
export class GetPaymentsReceivedService {
@@ -18,7 +19,7 @@ export class GetPaymentsReceivedService {
/**
* Retrieve payment receives paginated and filterable list.
* @param {IPaymentsReceivedFilter} paymentReceivesFilter
* @param {IPaymentsReceivedFilter} filterDTO
*/
public async getPaymentReceives(filterDTO: IPaymentsReceivedFilter): Promise<{
paymentReceives: PaymentReceived[];

View File

@@ -1,6 +1,7 @@
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
import { Knex } from 'knex';
import { PaymentReceived } from '../models/PaymentReceived';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
export interface IPaymentReceivedCreateDTO {
customerId: number;
@@ -39,10 +40,10 @@ export interface IPaymentReceivedEntryDTO {
paymentAmount: number;
}
// export interface IPaymentsReceivedFilter extends IDynamicListFilterDTO {
// stringifiedFilterRoles?: string;
// filterQuery?: (trx: Knex.Transaction) => void;
// }
export interface IPaymentsReceivedFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string;
filterQuery?: (trx: Knex.Transaction) => void;
}
export interface IPaymentReceivePageEntry {
invoiceId: number;

View File

@@ -6,6 +6,7 @@ import {
Param,
Post,
Put,
Query,
} from '@nestjs/common';
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
import {
@@ -31,6 +32,11 @@ export class VendorCreditsController {
return this.vendorCreditsApplication.openVendorCredit(vendorCreditId);
}
@Get()
async getVendorCredits(@Query() filterDTO: IVendorCreditsFilter) {
return this.vendorCreditsApplication.getVendorCredits(filterDTO);
}
@Put(':id')
async editVendorCredit(
@Param('id') vendorCreditId: number,

View File

@@ -9,6 +9,7 @@ import {
IVendorEditDTO,
IVendorNewDTO,
IVendorOpeningBalanceEditDTO,
IVendorsFilter,
} from './types/Vendors.types';
import { GetVendorsService } from './queries/GetVendors.service';
@@ -78,10 +79,10 @@ export class VendorsApplication {
/**
* Retrieves the vendors paginated list.
* @param {IVendorsFilter} filterDTO
* @returns {Promise<{vendors: Vendor[], pagination: IPaginationMeta, filterMeta: IFilterMeta}>>}
* @param {IVendorsFilter} filterDTO
* @returns {Promise<{ vendors: Vendor[], pagination: IPaginationMeta, filterMeta: IFilterMeta }>>}
*/
public getVendors = (filterDTO: IVendorsFilter) => {
public getVendors(filterDTO: IVendorsFilter) {
return this.getVendorsService.getVendorsList(filterDTO);
};
}

View File

@@ -1,13 +1,19 @@
import * as R from 'ramda';
import { Inject, Injectable } from '@nestjs/common';
import { Vendor } from '../models/Vendor';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { Inject, Injectable } from '@nestjs/common';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { VendorTransfromer } from './VendorTransformer';
import { GetVendorsResponse, IVendorsFilter } from '../types/Vendors.types';
@Injectable()
export class GetVendorsService {
/**
* Constructor method.
* @param {DynamicListService} dynamicListService
* @param {TransformerInjectable} transformer
* @param {typeof Vendor} vendorModel
*/
constructor(
private dynamicListService: DynamicListService,
private transformer: TransformerInjectable,
@@ -18,12 +24,11 @@ export class GetVendorsService {
/**
* Retrieve vendors datatable list.
* @param {IVendorsFilter} vendorsFilter - Vendors filter.
* @returns {Promise<GetVendorsResponse>}
*/
public async getVendorsList(filterDTO: IVendorsFilter): Promise<{
vendors: Vendor[];
pagination: IPaginationMeta;
filterMeta: IFilterMeta;
}> {
public async getVendorsList(
filterDTO: IVendorsFilter,
): Promise<GetVendorsResponse> {
// Parses vendors list filter DTO.
const filter = this.parseVendorsListFilterDTO(filterDTO);

View File

@@ -3,6 +3,8 @@
import { Knex } from 'knex';
import { Vendor } from '../models/Vendor';
import { IContactAddressDTO } from '@/modules/Contacts/types/Contacts.types';
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
// ----------------------------------
export interface IVendorNewDTO extends IContactAddressDTO {
@@ -43,11 +45,17 @@ export interface IVendorEditDTO extends IContactAddressDTO {
active?: boolean;
}
// export interface IVendorsFilter extends IDynamicListFilter {
// stringifiedFilterRoles?: string;
// page?: number;
// pageSize?: number;
// }
export interface IVendorsFilter extends IDynamicListFilter {
stringifiedFilterRoles?: string;
page?: number;
pageSize?: number;
}
export interface GetVendorsResponse {
vendors: Vendor[];
pagination: IPaginationMeta;
filterMeta: IFilterMeta;
}
// Vendor Events.
// ----------------------------------