This commit is contained in:
Ahmed Bouhuolia
2026-01-12 01:04:28 +02:00
parent 16f1d57279
commit 3c1273becb
32 changed files with 180 additions and 132 deletions

View File

@@ -8,6 +8,7 @@ import {
Query,
ParseIntPipe,
Put,
HttpCode,
} from '@nestjs/common';
import { AccountsApplication } from './AccountsApplication.service';
import { CreateAccountDTO } from './CreateAccount.dto';
@@ -43,6 +44,7 @@ export class AccountsController {
constructor(private readonly accountsApplication: AccountsApplication) { }
@Post('validate-bulk-delete')
@HttpCode(200)
@ApiOperation({
summary:
'Validates which accounts can be deleted and returns counts of deletable and non-deletable accounts.',
@@ -64,6 +66,7 @@ export class AccountsController {
}
@Post('bulk-delete')
@HttpCode(200)
@ApiOperation({ summary: 'Deletes multiple accounts in bulk.' })
@ApiResponse({
status: 200,
@@ -125,6 +128,7 @@ export class AccountsController {
}
@Post(':id/activate')
@HttpCode(200)
@ApiOperation({ summary: 'Activate the given account.' })
@ApiResponse({
status: 200,
@@ -142,6 +146,7 @@ export class AccountsController {
}
@Post(':id/inactivate')
@HttpCode(200)
@ApiOperation({ summary: 'Inactivate the given account.' })
@ApiResponse({
status: 200,

View File

@@ -18,7 +18,7 @@ export class DeleteAccount {
private eventEmitter: EventEmitter2,
private uow: UnitOfWork,
private validator: CommandAccountValidators,
) {}
) { }
/**
* Authorize account delete.
@@ -57,7 +57,10 @@ export class DeleteAccount {
trx?: Knex.Transaction,
): Promise<void> => {
// Retrieve account or not found service error.
const oldAccount = await this.accountModel().query().findById(accountId);
const oldAccount = await this.accountModel()
.query()
.findById(accountId)
.throwIfNotFound();
// Authorize before delete account.
await this.authorize(accountId, oldAccount);

View File

@@ -3,7 +3,7 @@ import {
Get,
Query,
Param,
Post,
Patch,
ParseIntPipe,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiParam } from '@nestjs/swagger';
@@ -27,7 +27,7 @@ export class ContactsController {
return this.getAutoCompleteService.autocompleteContacts(query);
}
@Post(':id/activate')
@Patch(':id/activate')
@ApiOperation({ summary: 'Activate a contact' })
@ApiParam({ name: 'id', type: 'number', description: 'Contact ID' })
async activateContact(@Param('id', ParseIntPipe) contactId: number) {
@@ -35,7 +35,7 @@ export class ContactsController {
return { id: contactId, activated: true };
}
@Post(':id/inactivate')
@Patch(':id/inactivate')
@ApiOperation({ summary: 'Inactivate a contact' })
@ApiParam({ name: 'id', type: 'number', description: 'Contact ID' })
async inactivateContact(@Param('id', ParseIntPipe) contactId: number) {

View File

@@ -16,7 +16,7 @@ import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@ApiTags('Reports')
@ApiCommonHeaders()
export class APAgingSummaryController {
constructor(private readonly APAgingSummaryApp: APAgingSummaryApplication) {}
constructor(private readonly APAgingSummaryApp: APAgingSummaryApplication) { }
@Get()
@ApiOperation({ summary: 'Get payable aging summary' })
@@ -37,12 +37,13 @@ export class APAgingSummaryController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.APAgingSummaryApp.table(filter);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const csv = await this.APAgingSummaryApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -50,7 +51,7 @@ export class APAgingSummaryController {
res.send(csv);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.APAgingSummaryApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -60,7 +61,7 @@ export class APAgingSummaryController {
);
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.APAgingSummaryApp.pdf(filter);
res.set({

View File

@@ -38,8 +38,9 @@ export class ARAgingSummaryController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the xlsx format.
if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.ARAgingSummaryApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -49,11 +50,11 @@ export class ARAgingSummaryController {
);
res.send(buffer);
// Retrieves the table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.ARAgingSummaryApp.table(filter);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.ARAgingSummaryApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -61,7 +62,7 @@ export class ARAgingSummaryController {
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.ARAgingSummaryApp.pdf(filter);
res.set({

View File

@@ -43,13 +43,14 @@ export class BalanceSheetStatementController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
const table = await this.balanceSheetApp.table(query);
return table;
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.balanceSheetApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -57,7 +58,7 @@ export class BalanceSheetStatementController {
res.send(buffer);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.balanceSheetApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -67,7 +68,7 @@ export class BalanceSheetStatementController {
);
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.balanceSheetApp.pdf(query);
res.set({

View File

@@ -16,7 +16,7 @@ import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@ApiTags('Reports')
@ApiCommonHeaders()
export class CashflowController {
constructor(private readonly cashflowSheetApp: CashflowSheetApplication) {}
constructor(private readonly cashflowSheetApp: CashflowSheetApplication) { }
@Get()
@ApiResponse({
@@ -37,11 +37,12 @@ export class CashflowController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.cashflowSheetApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.cashflowSheetApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -49,7 +50,7 @@ export class CashflowController {
res.status(200).send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.cashflowSheetApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -59,7 +60,7 @@ export class CashflowController {
);
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.cashflowSheetApp.pdf(query);
res.set({

View File

@@ -34,8 +34,9 @@ export class CustomerBalanceSummaryController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the xlsx format.
if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.customerBalanceSummaryApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
res.setHeader(
@@ -44,18 +45,18 @@ export class CustomerBalanceSummaryController {
);
res.send(buffer);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.customerBalanceSummaryApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
res.setHeader('Content-Type', 'text/csv');
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.customerBalanceSummaryApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const buffer = await this.customerBalanceSummaryApp.pdf(filter);
res.set({

View File

@@ -39,11 +39,12 @@ export class GeneralLedgerController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.generalLedgerApplication.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.generalLedgerApplication.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -51,7 +52,7 @@ export class GeneralLedgerController {
res.send(buffer);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.generalLedgerApplication.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -61,7 +62,7 @@ export class GeneralLedgerController {
);
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.generalLedgerApplication.pdf(query);
res.set({
'Content-Type': 'application/pdf',

View File

@@ -21,7 +21,8 @@ export class InventoryItemDetailsController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const accept = acceptHeader || '';
if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.inventoryItemDetailsApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -29,7 +30,7 @@ export class InventoryItemDetailsController {
res.send(buffer);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.inventoryItemDetailsApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -39,10 +40,10 @@ export class InventoryItemDetailsController {
);
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.inventoryItemDetailsApp.table(query);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const buffer = await this.inventoryItemDetailsApp.pdf(query);
res.set({

View File

@@ -37,11 +37,12 @@ export class InventoryValuationController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.inventoryValuationApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.inventoryValuationApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -49,7 +50,7 @@ export class InventoryValuationController {
res.send(buffer);
// Retrieves the xslx buffer format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.inventoryValuationApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -59,7 +60,7 @@ export class InventoryValuationController {
);
res.send(buffer);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.inventoryValuationApp.pdf(query);
res.set({

View File

@@ -37,12 +37,13 @@ export class JournalSheetController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.journalSheetApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.journalSheetApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -50,7 +51,7 @@ export class JournalSheetController {
res.send(buffer);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.journalSheetApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -60,7 +61,7 @@ export class JournalSheetController {
);
res.send(buffer);
// Retrieves the json format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.journalSheetApp.pdf(query);
res.set({

View File

@@ -45,8 +45,9 @@ export class ProfitLossSheetController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the csv format.
if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
if (accept.includes(AcceptType.ApplicationCsv)) {
const sheet = await this.profitLossSheetApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -54,11 +55,11 @@ export class ProfitLossSheetController {
res.send(sheet);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.profitLossSheetApp.table(query);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const sheet = await this.profitLossSheetApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -68,7 +69,7 @@ export class ProfitLossSheetController {
);
res.send(sheet);
// Retrieves the json format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.profitLossSheetApp.pdf(query);
res.set({

View File

@@ -22,11 +22,12 @@ export class PurchasesByItemReportController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// JSON table response format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.purchasesByItemsApp.table(filter);
// CSV response format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.purchasesByItemsApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -34,7 +35,7 @@ export class PurchasesByItemReportController {
res.send(buffer);
// Xlsx response format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.purchasesByItemsApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -44,7 +45,7 @@ export class PurchasesByItemReportController {
);
res.send(buffer);
// PDF response format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.purchasesByItemsApp.pdf(filter);
res.set({

View File

@@ -31,8 +31,9 @@ export class SalesByItemsController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the csv format.
if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.salesByItemsApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -40,10 +41,10 @@ export class SalesByItemsController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.salesByItemsApp.table(filter);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = this.salesByItemsApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -53,7 +54,7 @@ export class SalesByItemsController {
);
res.send(buffer);
// Retrieves the json format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.salesByItemsApp.pdf(filter);
res.set({

View File

@@ -37,11 +37,12 @@ export class SalesTaxLiabilitySummaryController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.salesTaxLiabilitySummaryApp.table(query);
// Retrieves the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.salesTaxLiabilitySummaryApp.xlsx(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -51,14 +52,14 @@ export class SalesTaxLiabilitySummaryController {
);
res.send(buffer);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.salesTaxLiabilitySummaryApp.csv(query);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
res.setHeader('Content-Type', 'text/csv');
res.send(buffer);
// Retrieves the json format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.salesTaxLiabilitySummaryApp.pdf(query);
res.set({
'Content-Type': 'application/pdf',

View File

@@ -9,17 +9,18 @@ import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model';
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
import { Account } from '@/modules/Accounts/models/Account.model';
import { ModelObject } from 'objection';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable({ scope: Scope.TRANSIENT })
export class SalesTaxLiabilitySummaryRepository {
@Inject(TaxRateModel.name)
private readonly taxRateModel: typeof TaxRateModel;
private readonly taxRateModel: TenantModelProxy<typeof TaxRateModel>;
@Inject(AccountTransaction.name)
private readonly accountTransactionModel: typeof AccountTransaction;
private readonly accountTransactionModel: TenantModelProxy<typeof AccountTransaction>;
@Inject(Account.name)
private readonly accountModel: typeof Account;
private readonly accountModel: TenantModelProxy<typeof Account>;
/**
* @param {SalesTaxLiabilitySummarySalesById}
@@ -77,7 +78,7 @@ export class SalesTaxLiabilitySummaryRepository {
* @returns {Promise<TaxRate[]>}
*/
public getTaxRates = () => {
return this.taxRateModel.query().orderBy('name', 'desc');
return this.taxRateModel().query().orderBy('name', 'desc');
};
/**
@@ -86,13 +87,13 @@ export class SalesTaxLiabilitySummaryRepository {
*/
public async getTaxesPayableSumGroupedByRateId(): Promise<SalesTaxLiabilitySummaryPayableById> {
// Retrieves tax payable accounts.
const taxPayableAccounts = await this.accountModel
const taxPayableAccounts = await this.accountModel()
.query()
.whereIn('accountType', [ACCOUNT_TYPE.TAX_PAYABLE]);
const payableAccountsIds = taxPayableAccounts.map((account) => account.id);
const groupedTaxesById = await this.accountTransactionModel
const groupedTaxesById = await this.accountTransactionModel()
.query()
.whereIn('account_id', payableAccountsIds)
.whereNot('tax_rate_id', null)
@@ -110,7 +111,7 @@ export class SalesTaxLiabilitySummaryRepository {
*/
public taxesSalesSumGroupedByRateId =
async (): Promise<SalesTaxLiabilitySummarySalesById> => {
const incomeAccounts = await this.accountModel
const incomeAccounts = await this.accountModel()
.query()
.whereIn('accountType', [
ACCOUNT_TYPE.INCOME,
@@ -118,7 +119,7 @@ export class SalesTaxLiabilitySummaryRepository {
]);
const incomeAccountsIds = incomeAccounts.map((account) => account.id);
const groupedTaxesById = await this.accountTransactionModel
const groupedTaxesById = await this.accountTransactionModel()
.query()
.whereIn('account_id', incomeAccountsIds)
.whereNot('tax_rate_id', null)

View File

@@ -23,12 +23,13 @@ export class TransactionsByCustomerController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.transactionsByCustomersApp.table(filter);
// Retrieve the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const csv = await this.transactionsByCustomersApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -37,7 +38,7 @@ export class TransactionsByCustomerController {
res.send(csv);
// Retrieve the xlsx format.
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.transactionsByCustomersApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
res.setHeader(
@@ -47,7 +48,7 @@ export class TransactionsByCustomerController {
res.send(buffer);
// Retrieve the json format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.transactionsByCustomersApp.pdf(filter);
res.set({
'Content-Type': 'application/pdf',

View File

@@ -24,6 +24,7 @@ export class TransactionsByReferenceRepository {
): Promise<Array<ModelObject<AccountTransaction>>> {
return this.accountTransactionModel()
.query()
.skipUndefined()
.where('reference_id', referenceId)
.where('reference_type', referenceType)
.withGraphFetched('account');

View File

@@ -23,8 +23,9 @@ export class TransactionsByVendorController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the xlsx format.
if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.transactionsByVendorsApp.xlsx(filter);
res.setHeader('Content-Type', 'application/vnd.openxmlformats');
@@ -32,7 +33,7 @@ export class TransactionsByVendorController {
res.send(buffer);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.transactionsByVendorsApp.csv(filter);
res.setHeader('Content-Type', 'text/csv');
@@ -40,10 +41,10 @@ export class TransactionsByVendorController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.transactionsByVendorsApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.transactionsByVendorsApp.pdf(filter);
res.set({
'Content-Type': 'application/pdf',

View File

@@ -40,15 +40,16 @@ export class TrialBalanceSheetController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
const filter = {
...query,
accountIds: castArray(query.accountIds),
};
// Retrieves in json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.trialBalanceSheetApp.table(filter);
// Retrieves in xlsx format
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.trialBalanceSheetApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -58,7 +59,7 @@ export class TrialBalanceSheetController {
);
res.send(buffer);
// Retrieves in csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
} else if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.trialBalanceSheetApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
@@ -66,7 +67,7 @@ export class TrialBalanceSheetController {
res.send(buffer);
// Retrieves in pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.trialBalanceSheetApp.pdf(filter);
res.set({

View File

@@ -35,15 +35,16 @@ export class VendorBalanceSummaryController {
@Res({ passthrough: true }) res: Response,
@Headers('accept') acceptHeader: string,
) {
const accept = acceptHeader || '';
// Retrieves the csv format.
if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
if (accept.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.vendorBalanceSummaryApp.csv(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
res.setHeader('Content-Type', 'text/csv');
res.send(buffer);
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
} else if (accept.includes(AcceptType.ApplicationXlsx)) {
const buffer = await this.vendorBalanceSummaryApp.xlsx(filter);
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
@@ -52,10 +53,10 @@ export class VendorBalanceSummaryController {
res.send(buffer);
// Retrieves the json table format.
} else if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
} else if (accept.includes(AcceptType.ApplicationJsonTable)) {
return this.vendorBalanceSummaryApp.table(filter);
// Retrieves the pdf format.
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
} else if (accept.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.vendorBalanceSummaryApp.pdf(filter);
res.set({

View File

@@ -25,7 +25,7 @@ export class DeleteItemService {
@Inject(Item.name)
private readonly itemModel: TenantModelProxy<typeof Item>,
) {}
) { }
/**
* Delete the given item from the storage.

View File

@@ -8,6 +8,7 @@ import {
Get,
Put,
Query,
HttpCode,
} from '@nestjs/common';
import { TenantController } from '../Tenancy/Tenant.controller';
import { ItemsApplicationService } from './ItemsApplication.service';
@@ -156,9 +157,10 @@ export class ItemsController extends TenantController {
async editItem(
@Param('id') id: string,
@Body() editItemDto: EditItemDto,
): Promise<number> {
): Promise<{ id: number; message: string }> {
const itemId = parseInt(id, 10);
return this.itemsApplication.editItem(itemId, editItemDto);
await this.itemsApplication.editItem(itemId, editItemDto);
return { id: itemId, message: 'The item has been successfully updated.' };
}
@Post()
@@ -168,8 +170,12 @@ export class ItemsController extends TenantController {
description: 'The item has been successfully created.',
})
// @UsePipes(new ZodValidationPipe(createItemSchema))
async createItem(@Body() createItemDto: CreateItemDto): Promise<number> {
return this.itemsApplication.createItem(createItemDto);
async createItem(
@Body() createItemDto: CreateItemDto,
): Promise<{ id: number; message: string }> {
const itemId = await this.itemsApplication.createItem(createItemDto);
return { id: itemId, message: 'The item has been successfully created.' };
}
@Delete(':id')
@@ -347,6 +353,7 @@ export class ItemsController extends TenantController {
}
@Post('validate-bulk-delete')
@HttpCode(200)
@ApiOperation({
summary:
'Validates which items can be deleted and returns counts of deletable and non-deletable items.',

View File

@@ -28,7 +28,7 @@ export class ItemsEntriesService {
@Inject(ItemEntry.name)
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
) {}
) { }
/**
* Retrieve the inventory items entries of the reference id and type.
@@ -226,6 +226,10 @@ export class ItemsEntriesService {
return entries.map((entry) => {
const item = items.find((i) => i.id === entry.itemId);
if (!item) {
throw new Error(`Item with id ${entry.itemId} not found`);
}
return {
...entry,
sellAccountId: entry.sellAccountId || item.sellAccountId,