mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
wip
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
|||||||
Get,
|
Get,
|
||||||
Query,
|
Query,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
|
DefaultValuePipe,
|
||||||
|
ParseBoolPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { AccountsApplication } from './AccountsApplication.service';
|
import { AccountsApplication } from './AccountsApplication.service';
|
||||||
import { CreateAccountDTO } from './CreateAccount.dto';
|
import { CreateAccountDTO } from './CreateAccount.dto';
|
||||||
@@ -64,14 +66,25 @@ export class AccountsController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple accounts in bulk.' })
|
@ApiOperation({ summary: 'Deletes multiple accounts in bulk.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable accounts will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'The accounts have been successfully deleted.',
|
description: 'The accounts have been successfully deleted.',
|
||||||
})
|
})
|
||||||
async bulkDeleteAccounts(
|
async bulkDeleteAccounts(
|
||||||
@Body() bulkDeleteDto: BulkDeleteDto,
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.accountsApplication.bulkDeleteAccounts(bulkDeleteDto.ids);
|
return this.accountsApplication.bulkDeleteAccounts(bulkDeleteDto.ids, {
|
||||||
|
skipUndeletable,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export class AccountsApplication {
|
|||||||
private readonly getAccountsService: GetAccountsService,
|
private readonly getAccountsService: GetAccountsService,
|
||||||
private readonly bulkDeleteAccountsService: BulkDeleteAccountsService,
|
private readonly bulkDeleteAccountsService: BulkDeleteAccountsService,
|
||||||
private readonly validateBulkDeleteAccountsService: ValidateBulkDeleteAccountsService,
|
private readonly validateBulkDeleteAccountsService: ValidateBulkDeleteAccountsService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new account.
|
* Creates a new account.
|
||||||
@@ -148,7 +148,13 @@ export class AccountsApplication {
|
|||||||
/**
|
/**
|
||||||
* Deletes multiple accounts in bulk.
|
* Deletes multiple accounts in bulk.
|
||||||
*/
|
*/
|
||||||
public bulkDeleteAccounts = (accountIds: number[]): Promise<void> => {
|
public bulkDeleteAccounts = (
|
||||||
return this.bulkDeleteAccountsService.bulkDeleteAccounts(accountIds);
|
accountIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
): Promise<void> => {
|
||||||
|
return this.bulkDeleteAccountsService.bulkDeleteAccounts(
|
||||||
|
accountIds,
|
||||||
|
options,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,25 @@ export class BulkDeleteAccountsService {
|
|||||||
*/
|
*/
|
||||||
async bulkDeleteAccounts(
|
async bulkDeleteAccounts(
|
||||||
accountIds: number | Array<number>,
|
accountIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const accountsIds = uniq(castArray(accountIds));
|
const accountsIds = uniq(castArray(accountIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(accountsIds)
|
.for(accountsIds)
|
||||||
.process(async (accountId: number) => {
|
.process(async (accountId: number) => {
|
||||||
await this.deleteAccountService.deleteAccount(accountId);
|
try {
|
||||||
|
await this.deleteAccountService.deleteAccount(accountId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,11 @@ export class BillsApplication {
|
|||||||
* Deletes multiple bills.
|
* Deletes multiple bills.
|
||||||
* @param {number[]} billIds
|
* @param {number[]} billIds
|
||||||
*/
|
*/
|
||||||
public bulkDeleteBills(billIds: number[]) {
|
public bulkDeleteBills(
|
||||||
return this.bulkDeleteBillsService.bulkDeleteBills(billIds);
|
billIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
|
return this.bulkDeleteBillsService.bulkDeleteBills(billIds, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -15,6 +16,8 @@ import {
|
|||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
Query,
|
Query,
|
||||||
|
DefaultValuePipe,
|
||||||
|
ParseBoolPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { BillsApplication } from './Bills.application';
|
import { BillsApplication } from './Bills.application';
|
||||||
import { IBillsFilter } from './Bills.types';
|
import { IBillsFilter } from './Bills.types';
|
||||||
@@ -56,12 +59,25 @@ export class BillsController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple bills.' })
|
@ApiOperation({ summary: 'Deletes multiple bills.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable bills will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Bills deleted successfully',
|
description: 'Bills deleted successfully',
|
||||||
})
|
})
|
||||||
bulkDeleteBills(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
|
bulkDeleteBills(
|
||||||
return this.billsApplication.bulkDeleteBills(bulkDeleteDto.ids);
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
return this.billsApplication.bulkDeleteBills(bulkDeleteDto.ids, {
|
||||||
|
skipUndeletable,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
|||||||
@@ -10,17 +10,25 @@ export class BulkDeleteBillsService {
|
|||||||
|
|
||||||
async bulkDeleteBills(
|
async bulkDeleteBills(
|
||||||
billIds: number | Array<number>,
|
billIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const billsIds = uniq(castArray(billIds));
|
const billsIds = uniq(castArray(billIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(billsIds)
|
.for(billsIds)
|
||||||
.process(async (billId: number) => {
|
.process(async (billId: number) => {
|
||||||
await this.deleteBillService.deleteBill(billId);
|
try {
|
||||||
|
await this.deleteBillService.deleteBill(billId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,25 @@ export class BulkDeleteCreditNotesService {
|
|||||||
|
|
||||||
async bulkDeleteCreditNotes(
|
async bulkDeleteCreditNotes(
|
||||||
creditNoteIds: number | Array<number>,
|
creditNoteIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const notesIds = uniq(castArray(creditNoteIds));
|
const notesIds = uniq(castArray(creditNoteIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(notesIds)
|
.for(notesIds)
|
||||||
.process(async (creditNoteId: number) => {
|
.process(async (creditNoteId: number) => {
|
||||||
await this.deleteCreditNoteService.deleteCreditNote(creditNoteId);
|
try {
|
||||||
|
await this.deleteCreditNoteService.deleteCreditNote(creditNoteId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,9 +107,13 @@ export class CreditNoteApplication {
|
|||||||
* @param {number[]} creditNoteIds
|
* @param {number[]} creditNoteIds
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
bulkDeleteCreditNotes(creditNoteIds: number[]) {
|
bulkDeleteCreditNotes(
|
||||||
|
creditNoteIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
return this.bulkDeleteCreditNotesService.bulkDeleteCreditNotes(
|
return this.bulkDeleteCreditNotesService.bulkDeleteCreditNotes(
|
||||||
creditNoteIds,
|
creditNoteIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
} from '@nestjs/swagger';
|
} from '@nestjs/swagger';
|
||||||
@@ -11,7 +12,9 @@ import {
|
|||||||
Controller,
|
Controller,
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
|
DefaultValuePipe,
|
||||||
Param,
|
Param,
|
||||||
|
ParseBoolPipe,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
@@ -37,7 +40,7 @@ export class CreditNotesController {
|
|||||||
/**
|
/**
|
||||||
* @param {CreditNoteApplication} creditNoteApplication - The credit note application service.
|
* @param {CreditNoteApplication} creditNoteApplication - The credit note application service.
|
||||||
*/
|
*/
|
||||||
constructor(private creditNoteApplication: CreditNoteApplication) {}
|
constructor(private creditNoteApplication: CreditNoteApplication) { }
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@ApiOperation({ summary: 'Create a new credit note' })
|
@ApiOperation({ summary: 'Create a new credit note' })
|
||||||
@@ -140,13 +143,25 @@ export class CreditNotesController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple credit notes.' })
|
@ApiOperation({ summary: 'Deletes multiple credit notes.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable credit notes will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Credit notes deleted successfully',
|
description: 'Credit notes deleted successfully',
|
||||||
})
|
})
|
||||||
bulkDeleteCreditNotes(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
|
bulkDeleteCreditNotes(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
): Promise<void> {
|
||||||
return this.creditNoteApplication.bulkDeleteCreditNotes(
|
return this.creditNoteApplication.bulkDeleteCreditNotes(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,29 @@ import { DeleteExpense } from './commands/DeleteExpense.service';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BulkDeleteExpensesService {
|
export class BulkDeleteExpensesService {
|
||||||
constructor(private readonly deleteExpenseService: DeleteExpense) {}
|
constructor(private readonly deleteExpenseService: DeleteExpense) { }
|
||||||
|
|
||||||
async bulkDeleteExpenses(
|
async bulkDeleteExpenses(
|
||||||
expenseIds: number | Array<number>,
|
expenseIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const expensesIds = uniq(castArray(expenseIds));
|
const expensesIds = uniq(castArray(expenseIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(expensesIds)
|
.for(expensesIds)
|
||||||
.process(async (expenseId: number) => {
|
.process(async (expenseId: number) => {
|
||||||
await this.deleteExpenseService.deleteExpense(expenseId);
|
try {
|
||||||
|
await this.deleteExpenseService.deleteExpense(expenseId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,15 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
|
DefaultValuePipe,
|
||||||
|
ParseBoolPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ExpensesApplication } from './ExpensesApplication.service';
|
import { ExpensesApplication } from './ExpensesApplication.service';
|
||||||
import { IExpensesFilter } from './Expenses.types';
|
import { IExpensesFilter } from './Expenses.types';
|
||||||
import {
|
import {
|
||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -59,12 +62,25 @@ export class ExpensesController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple expenses.' })
|
@ApiOperation({ summary: 'Deletes multiple expenses.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable expenses will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Expenses deleted successfully',
|
description: 'Expenses deleted successfully',
|
||||||
})
|
})
|
||||||
public bulkDeleteExpenses(@Body() bulkDeleteDto: BulkDeleteDto) {
|
public bulkDeleteExpenses(
|
||||||
return this.expensesApplication.bulkDeleteExpenses(bulkDeleteDto.ids);
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
) {
|
||||||
|
return this.expensesApplication.bulkDeleteExpenses(bulkDeleteDto.ids, {
|
||||||
|
skipUndeletable,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class ExpensesApplication {
|
|||||||
private readonly getExpensesService: GetExpensesService,
|
private readonly getExpensesService: GetExpensesService,
|
||||||
private readonly bulkDeleteExpensesService: BulkDeleteExpensesService,
|
private readonly bulkDeleteExpensesService: BulkDeleteExpensesService,
|
||||||
private readonly validateBulkDeleteExpensesService: ValidateBulkDeleteExpensesService,
|
private readonly validateBulkDeleteExpensesService: ValidateBulkDeleteExpensesService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new expense transaction.
|
* Create a new expense transaction.
|
||||||
@@ -55,8 +55,14 @@ export class ExpensesApplication {
|
|||||||
* Deletes expenses in bulk.
|
* Deletes expenses in bulk.
|
||||||
* @param {number[]} expenseIds - Expense ids.
|
* @param {number[]} expenseIds - Expense ids.
|
||||||
*/
|
*/
|
||||||
public bulkDeleteExpenses(expenseIds: number[]) {
|
public bulkDeleteExpenses(
|
||||||
return this.bulkDeleteExpensesService.bulkDeleteExpenses(expenseIds);
|
expenseIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
|
return this.bulkDeleteExpensesService.bulkDeleteExpenses(
|
||||||
|
expenseIds,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,23 +8,31 @@ import { DeleteManualJournalService } from './commands/DeleteManualJournal.servi
|
|||||||
export class BulkDeleteManualJournalsService {
|
export class BulkDeleteManualJournalsService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deleteManualJournalService: DeleteManualJournalService,
|
private readonly deleteManualJournalService: DeleteManualJournalService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
async bulkDeleteManualJournals(
|
async bulkDeleteManualJournals(
|
||||||
manualJournalIds: number | Array<number>,
|
manualJournalIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const journalsIds = uniq(castArray(manualJournalIds));
|
const journalsIds = uniq(castArray(manualJournalIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(journalsIds)
|
.for(journalsIds)
|
||||||
.process(async (manualJournalId: number) => {
|
.process(async (manualJournalId: number) => {
|
||||||
await this.deleteManualJournalService.deleteManualJournal(
|
try {
|
||||||
manualJournalId,
|
await this.deleteManualJournalService.deleteManualJournal(
|
||||||
);
|
manualJournalId,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
|
DefaultValuePipe,
|
||||||
|
ParseBoolPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ManualJournalsApplication } from './ManualJournalsApplication.service';
|
import { ManualJournalsApplication } from './ManualJournalsApplication.service';
|
||||||
import {
|
import {
|
||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -61,15 +64,25 @@ export class ManualJournalsController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple manual journals.' })
|
@ApiOperation({ summary: 'Deletes multiple manual journals.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable journals will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Manual journals deleted successfully',
|
description: 'Manual journals deleted successfully',
|
||||||
})
|
})
|
||||||
public bulkDeleteManualJournals(
|
public bulkDeleteManualJournals(
|
||||||
@Body() bulkDeleteDto: BulkDeleteDto,
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.manualJournalsApplication.bulkDeleteManualJournals(
|
return this.manualJournalsApplication.bulkDeleteManualJournals(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class ManualJournalsApplication {
|
|||||||
private getManualJournalsService: GetManualJournals,
|
private getManualJournalsService: GetManualJournals,
|
||||||
private bulkDeleteManualJournalsService: BulkDeleteManualJournalsService,
|
private bulkDeleteManualJournalsService: BulkDeleteManualJournalsService,
|
||||||
private validateBulkDeleteManualJournalsService: ValidateBulkDeleteManualJournalsService,
|
private validateBulkDeleteManualJournalsService: ValidateBulkDeleteManualJournalsService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make journal entries.
|
* Make journal entries.
|
||||||
@@ -65,9 +65,13 @@ export class ManualJournalsApplication {
|
|||||||
* Bulk deletes manual journals.
|
* Bulk deletes manual journals.
|
||||||
* @param {number[]} manualJournalIds
|
* @param {number[]} manualJournalIds
|
||||||
*/
|
*/
|
||||||
public bulkDeleteManualJournals = (manualJournalIds: number[]) => {
|
public bulkDeleteManualJournals = (
|
||||||
|
manualJournalIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) => {
|
||||||
return this.bulkDeleteManualJournalsService.bulkDeleteManualJournals(
|
return this.bulkDeleteManualJournalsService.bulkDeleteManualJournals(
|
||||||
manualJournalIds,
|
manualJournalIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,23 +8,31 @@ import { DeletePaymentReceivedService } from './commands/DeletePaymentReceived.s
|
|||||||
export class BulkDeletePaymentReceivedService {
|
export class BulkDeletePaymentReceivedService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deletePaymentReceivedService: DeletePaymentReceivedService,
|
private readonly deletePaymentReceivedService: DeletePaymentReceivedService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
async bulkDeletePaymentReceived(
|
async bulkDeletePaymentReceived(
|
||||||
paymentReceiveIds: number | Array<number>,
|
paymentReceiveIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const paymentsIds = uniq(castArray(paymentReceiveIds));
|
const paymentsIds = uniq(castArray(paymentReceiveIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(paymentsIds)
|
.for(paymentsIds)
|
||||||
.process(async (paymentReceiveId: number) => {
|
.process(async (paymentReceiveId: number) => {
|
||||||
await this.deletePaymentReceivedService.deletePaymentReceive(
|
try {
|
||||||
paymentReceiveId,
|
await this.deletePaymentReceivedService.deletePaymentReceive(
|
||||||
);
|
paymentReceiveId,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,13 @@ export class PaymentReceivesApplication {
|
|||||||
* Deletes multiple payment receives.
|
* Deletes multiple payment receives.
|
||||||
* @param {number[]} paymentReceiveIds
|
* @param {number[]} paymentReceiveIds
|
||||||
*/
|
*/
|
||||||
public bulkDeletePaymentReceives(paymentReceiveIds: number[]) {
|
public bulkDeletePaymentReceives(
|
||||||
|
paymentReceiveIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
return this.bulkDeletePaymentReceivedService.bulkDeletePaymentReceived(
|
return this.bulkDeletePaymentReceivedService.bulkDeletePaymentReceived(
|
||||||
paymentReceiveIds,
|
paymentReceiveIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -13,10 +14,12 @@ import {
|
|||||||
Headers,
|
Headers,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
Param,
|
Param,
|
||||||
|
ParseBoolPipe,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
|
DefaultValuePipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { PaymentReceivesApplication } from './PaymentReceived.application';
|
import { PaymentReceivesApplication } from './PaymentReceived.application';
|
||||||
import {
|
import {
|
||||||
@@ -171,13 +174,25 @@ export class PaymentReceivesController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple payments received.' })
|
@ApiOperation({ summary: 'Deletes multiple payments received.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable payments will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Payments received deleted successfully.',
|
description: 'Payments received deleted successfully.',
|
||||||
})
|
})
|
||||||
public bulkDeletePaymentsReceived(@Body() bulkDeleteDto: BulkDeleteDto) {
|
public bulkDeletePaymentsReceived(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
) {
|
||||||
return this.paymentReceivesApplication.bulkDeletePaymentReceives(
|
return this.paymentReceivesApplication.bulkDeletePaymentReceives(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,25 @@ export class BulkDeleteSaleEstimatesService {
|
|||||||
|
|
||||||
async bulkDeleteSaleEstimates(
|
async bulkDeleteSaleEstimates(
|
||||||
saleEstimateIds: number | Array<number>,
|
saleEstimateIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const estimatesIds = uniq(castArray(saleEstimateIds));
|
const estimatesIds = uniq(castArray(saleEstimateIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(estimatesIds)
|
.for(estimatesIds)
|
||||||
.process(async (saleEstimateId: number) => {
|
.process(async (saleEstimateId: number) => {
|
||||||
await this.deleteSaleEstimateService.deleteEstimate(saleEstimateId);
|
try {
|
||||||
|
await this.deleteSaleEstimateService.deleteEstimate(saleEstimateId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class SaleEstimatesApplication {
|
|||||||
private readonly getSaleEstimateMailStateService: GetSaleEstimateMailStateService,
|
private readonly getSaleEstimateMailStateService: GetSaleEstimateMailStateService,
|
||||||
private readonly bulkDeleteSaleEstimatesService: BulkDeleteSaleEstimatesService,
|
private readonly bulkDeleteSaleEstimatesService: BulkDeleteSaleEstimatesService,
|
||||||
private readonly validateBulkDeleteSaleEstimatesService: ValidateBulkDeleteSaleEstimatesService,
|
private readonly validateBulkDeleteSaleEstimatesService: ValidateBulkDeleteSaleEstimatesService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a sale estimate.
|
* Create a sale estimate.
|
||||||
@@ -77,9 +77,13 @@ export class SaleEstimatesApplication {
|
|||||||
* @param {number[]} saleEstimateIds
|
* @param {number[]} saleEstimateIds
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public bulkDeleteSaleEstimates(saleEstimateIds: number[]) {
|
public bulkDeleteSaleEstimates(
|
||||||
|
saleEstimateIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
return this.bulkDeleteSaleEstimatesService.bulkDeleteSaleEstimates(
|
return this.bulkDeleteSaleEstimatesService.bulkDeleteSaleEstimates(
|
||||||
saleEstimateIds,
|
saleEstimateIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -11,9 +12,11 @@ import {
|
|||||||
Controller,
|
Controller,
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
|
DefaultValuePipe,
|
||||||
Headers,
|
Headers,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
Param,
|
Param,
|
||||||
|
ParseBoolPipe,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
@@ -72,15 +75,25 @@ export class SaleEstimatesController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple sale estimates.' })
|
@ApiOperation({ summary: 'Deletes multiple sale estimates.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable estimates will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Sale estimates deleted successfully',
|
description: 'Sale estimates deleted successfully',
|
||||||
})
|
})
|
||||||
public bulkDeleteSaleEstimates(
|
public bulkDeleteSaleEstimates(
|
||||||
@Body() bulkDeleteDto: BulkDeleteDto,
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.saleEstimatesApplication.bulkDeleteSaleEstimates(
|
return this.saleEstimatesApplication.bulkDeleteSaleEstimates(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,25 @@ export class BulkDeleteSaleInvoicesService {
|
|||||||
|
|
||||||
async bulkDeleteSaleInvoices(
|
async bulkDeleteSaleInvoices(
|
||||||
saleInvoiceIds: number | Array<number>,
|
saleInvoiceIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const invoicesIds = uniq(castArray(saleInvoiceIds));
|
const invoicesIds = uniq(castArray(saleInvoiceIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(invoicesIds)
|
.for(invoicesIds)
|
||||||
.process(async (saleInvoiceId: number) => {
|
.process(async (saleInvoiceId: number) => {
|
||||||
await this.deleteSaleInvoiceService.deleteSaleInvoice(saleInvoiceId);
|
try {
|
||||||
|
await this.deleteSaleInvoiceService.deleteSaleInvoice(saleInvoiceId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
if (results.errors && results.errors.length > 0) {
|
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class SaleInvoiceApplication {
|
|||||||
private generateShareLinkService: GenerateShareLink,
|
private generateShareLinkService: GenerateShareLink,
|
||||||
private bulkDeleteSaleInvoicesService: BulkDeleteSaleInvoicesService,
|
private bulkDeleteSaleInvoicesService: BulkDeleteSaleInvoicesService,
|
||||||
private validateBulkDeleteSaleInvoicesService: ValidateBulkDeleteSaleInvoicesService,
|
private validateBulkDeleteSaleInvoicesService: ValidateBulkDeleteSaleInvoicesService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new sale invoice with associated GL entries.
|
* Creates a new sale invoice with associated GL entries.
|
||||||
@@ -87,9 +87,13 @@ export class SaleInvoiceApplication {
|
|||||||
* @param {number[]} saleInvoiceIds
|
* @param {number[]} saleInvoiceIds
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public bulkDeleteSaleInvoices(saleInvoiceIds: number[]) {
|
public bulkDeleteSaleInvoices(
|
||||||
|
saleInvoiceIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
return this.bulkDeleteSaleInvoicesService.bulkDeleteSaleInvoices(
|
return this.bulkDeleteSaleInvoicesService.bulkDeleteSaleInvoices(
|
||||||
saleInvoiceIds,
|
saleInvoiceIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { Response } from 'express';
|
|||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
|
DefaultValuePipe,
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
Headers,
|
Headers,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
Param,
|
Param,
|
||||||
|
ParseBoolPipe,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
@@ -78,13 +80,25 @@ export class SaleInvoicesController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple sale invoices.' })
|
@ApiOperation({ summary: 'Deletes multiple sale invoices.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable invoices will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Sale invoices deleted successfully',
|
description: 'Sale invoices deleted successfully',
|
||||||
})
|
})
|
||||||
bulkDeleteSaleInvoices(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
|
bulkDeleteSaleInvoices(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
): Promise<void> {
|
||||||
return this.saleInvoiceApplication.bulkDeleteSaleInvoices(
|
return this.saleInvoiceApplication.bulkDeleteSaleInvoices(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,25 @@ export class BulkDeleteSaleReceiptsService {
|
|||||||
|
|
||||||
async bulkDeleteSaleReceipts(
|
async bulkDeleteSaleReceipts(
|
||||||
saleReceiptIds: number | number[],
|
saleReceiptIds: number | number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const receiptIds = uniq(castArray(saleReceiptIds));
|
const receiptIds = uniq(castArray(saleReceiptIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(receiptIds)
|
.for(receiptIds)
|
||||||
.process(async (saleReceiptId: number) => {
|
.process(async (saleReceiptId: number) => {
|
||||||
await this.deleteSaleReceiptService.deleteSaleReceipt(saleReceiptId);
|
try {
|
||||||
|
await this.deleteSaleReceiptService.deleteSaleReceipt(saleReceiptId);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,9 +93,13 @@ export class SaleReceiptApplication {
|
|||||||
* Deletes multiple sale receipts.
|
* Deletes multiple sale receipts.
|
||||||
* @param {number[]} saleReceiptIds
|
* @param {number[]} saleReceiptIds
|
||||||
*/
|
*/
|
||||||
public async bulkDeleteSaleReceipts(saleReceiptIds: number[]) {
|
public async bulkDeleteSaleReceipts(
|
||||||
|
saleReceiptIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
return this.bulkDeleteSaleReceiptsService.bulkDeleteSaleReceipts(
|
return this.bulkDeleteSaleReceiptsService.bulkDeleteSaleReceipts(
|
||||||
saleReceiptIds,
|
saleReceiptIds,
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {
|
|||||||
Headers,
|
Headers,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
Param,
|
Param,
|
||||||
|
ParseBoolPipe,
|
||||||
|
DefaultValuePipe,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
@@ -17,6 +19,7 @@ import {
|
|||||||
ApiExtraModels,
|
ApiExtraModels,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
getSchemaPath,
|
getSchemaPath,
|
||||||
@@ -70,13 +73,25 @@ export class SaleReceiptsController {
|
|||||||
|
|
||||||
@Post('bulk-delete')
|
@Post('bulk-delete')
|
||||||
@ApiOperation({ summary: 'Deletes multiple sale receipts.' })
|
@ApiOperation({ summary: 'Deletes multiple sale receipts.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable receipts will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Sale receipts deleted successfully',
|
description: 'Sale receipts deleted successfully',
|
||||||
})
|
})
|
||||||
bulkDeleteSaleReceipts(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
|
bulkDeleteSaleReceipts(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
): Promise<void> {
|
||||||
return this.saleReceiptApplication.bulkDeleteSaleReceipts(
|
return this.saleReceiptApplication.bulkDeleteSaleReceipts(
|
||||||
bulkDeleteDto.ids,
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,31 @@ import { DeleteVendorCreditService } from './commands/DeleteVendorCredit.service
|
|||||||
export class BulkDeleteVendorCreditsService {
|
export class BulkDeleteVendorCreditsService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deleteVendorCreditService: DeleteVendorCreditService,
|
private readonly deleteVendorCreditService: DeleteVendorCreditService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
async bulkDeleteVendorCredits(
|
async bulkDeleteVendorCredits(
|
||||||
vendorCreditIds: number | Array<number>,
|
vendorCreditIds: number | Array<number>,
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
trx?: Knex.Transaction,
|
trx?: Knex.Transaction,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { skipUndeletable = false } = options ?? {};
|
||||||
const creditsIds = uniq(castArray(vendorCreditIds));
|
const creditsIds = uniq(castArray(vendorCreditIds));
|
||||||
|
|
||||||
const results = await PromisePool.withConcurrency(1)
|
const results = await PromisePool.withConcurrency(1)
|
||||||
.for(creditsIds)
|
.for(creditsIds)
|
||||||
.process(async (vendorCreditId: number) => {
|
.process(async (vendorCreditId: number) => {
|
||||||
await this.deleteVendorCreditService.deleteVendorCredit(vendorCreditId);
|
try {
|
||||||
|
await this.deleteVendorCreditService.deleteVendorCredit(
|
||||||
|
vendorCreditId,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (!skipUndeletable) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (results.errors && results.errors.length > 0) {
|
if (!skipUndeletable && results.errors && results.errors.length > 0) {
|
||||||
throw results.errors[0].raw;
|
throw results.errors[0].raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,23 +7,82 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
|
DefaultValuePipe,
|
||||||
|
ParseBoolPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
|
import { VendorCreditsApplicationService } from './VendorCreditsApplication.service';
|
||||||
import { IVendorCreditsQueryDTO } from './types/VendorCredit.types';
|
import { IVendorCreditsQueryDTO } from './types/VendorCredit.types';
|
||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
import {
|
||||||
|
ApiExtraModels,
|
||||||
|
ApiOperation,
|
||||||
|
ApiQuery,
|
||||||
|
ApiResponse,
|
||||||
|
ApiTags,
|
||||||
|
getSchemaPath,
|
||||||
|
} from '@nestjs/swagger';
|
||||||
import {
|
import {
|
||||||
CreateVendorCreditDto,
|
CreateVendorCreditDto,
|
||||||
EditVendorCreditDto,
|
EditVendorCreditDto,
|
||||||
} from './dtos/VendorCredit.dto';
|
} from './dtos/VendorCredit.dto';
|
||||||
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
|
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
|
||||||
|
import {
|
||||||
|
BulkDeleteDto,
|
||||||
|
ValidateBulkDeleteResponseDto,
|
||||||
|
} from '@/common/dtos/BulkDelete.dto';
|
||||||
|
|
||||||
@Controller('vendor-credits')
|
@Controller('vendor-credits')
|
||||||
@ApiTags('Vendor Credits')
|
@ApiTags('Vendor Credits')
|
||||||
@ApiCommonHeaders()
|
@ApiCommonHeaders()
|
||||||
|
@ApiExtraModels(ValidateBulkDeleteResponseDto)
|
||||||
export class VendorCreditsController {
|
export class VendorCreditsController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly vendorCreditsApplication: VendorCreditsApplicationService,
|
private readonly vendorCreditsApplication: VendorCreditsApplicationService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
|
@Post('validate-bulk-delete')
|
||||||
|
@ApiOperation({
|
||||||
|
summary:
|
||||||
|
'Validates which vendor credits can be deleted and returns the results.',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description:
|
||||||
|
'Validation completed with counts and IDs of deletable and non-deletable vendor credits.',
|
||||||
|
schema: {
|
||||||
|
$ref: getSchemaPath(ValidateBulkDeleteResponseDto),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
async validateBulkDeleteVendorCredits(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
): Promise<ValidateBulkDeleteResponseDto> {
|
||||||
|
return this.vendorCreditsApplication.validateBulkDeleteVendorCredits(
|
||||||
|
bulkDeleteDto.ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('bulk-delete')
|
||||||
|
@ApiOperation({ summary: 'Deletes multiple vendor credits.' })
|
||||||
|
@ApiQuery({
|
||||||
|
name: 'skip_undeletable',
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
description:
|
||||||
|
'When true, undeletable vendor credits will be skipped and only deletable ones will be removed.',
|
||||||
|
})
|
||||||
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description: 'Vendor credits deleted successfully',
|
||||||
|
})
|
||||||
|
async bulkDeleteVendorCredits(
|
||||||
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
||||||
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
||||||
|
skipUndeletable: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
return this.vendorCreditsApplication.bulkDeleteVendorCredits(
|
||||||
|
bulkDeleteDto.ids,
|
||||||
|
{ skipUndeletable },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@ApiOperation({ summary: 'Create a new vendor credit.' })
|
@ApiOperation({ summary: 'Create a new vendor credit.' })
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
|||||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
||||||
import { VendorCreditsExportable } from './commands/VendorCreditsExportable';
|
import { VendorCreditsExportable } from './commands/VendorCreditsExportable';
|
||||||
import { VendorCreditsImportable } from './commands/VendorCreditsImportable';
|
import { VendorCreditsImportable } from './commands/VendorCreditsImportable';
|
||||||
|
import { BulkDeleteVendorCreditsService } from './BulkDeleteVendorCredits.service';
|
||||||
|
import { ValidateBulkDeleteVendorCreditsService } from './ValidateBulkDeleteVendorCredits.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -61,6 +63,8 @@ import { VendorCreditsImportable } from './commands/VendorCreditsImportable';
|
|||||||
VendorCreditAutoSerialSubscriber,
|
VendorCreditAutoSerialSubscriber,
|
||||||
VendorCreditsExportable,
|
VendorCreditsExportable,
|
||||||
VendorCreditsImportable,
|
VendorCreditsImportable,
|
||||||
|
BulkDeleteVendorCreditsService,
|
||||||
|
ValidateBulkDeleteVendorCreditsService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CreateVendorCreditService,
|
CreateVendorCreditService,
|
||||||
@@ -74,6 +78,8 @@ import { VendorCreditsImportable } from './commands/VendorCreditsImportable';
|
|||||||
OpenVendorCreditService,
|
OpenVendorCreditService,
|
||||||
VendorCreditsExportable,
|
VendorCreditsExportable,
|
||||||
VendorCreditsImportable,
|
VendorCreditsImportable,
|
||||||
|
BulkDeleteVendorCreditsService,
|
||||||
|
ValidateBulkDeleteVendorCreditsService,
|
||||||
],
|
],
|
||||||
controllers: [VendorCreditsController],
|
controllers: [VendorCreditsController],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,12 +3,21 @@ import { CreateVendorCreditService } from './commands/CreateVendorCredit.service
|
|||||||
import { DeleteVendorCreditService } from './commands/DeleteVendorCredit.service';
|
import { DeleteVendorCreditService } from './commands/DeleteVendorCredit.service';
|
||||||
import { EditVendorCreditService } from './commands/EditVendorCredit.service';
|
import { EditVendorCreditService } from './commands/EditVendorCredit.service';
|
||||||
import { GetVendorCreditService } from './queries/GetVendorCredit.service';
|
import { GetVendorCreditService } from './queries/GetVendorCredit.service';
|
||||||
import { IVendorCreditEditDTO, IVendorCreditsQueryDTO } from './types/VendorCredit.types';
|
import {
|
||||||
|
IVendorCreditEditDTO,
|
||||||
|
IVendorCreditsQueryDTO,
|
||||||
|
} from './types/VendorCredit.types';
|
||||||
import { IVendorCreditCreateDTO } from './types/VendorCredit.types';
|
import { IVendorCreditCreateDTO } from './types/VendorCredit.types';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
|
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
|
||||||
import { GetVendorCreditsService } from './queries/GetVendorCredits.service';
|
import { GetVendorCreditsService } from './queries/GetVendorCredits.service';
|
||||||
import { CreateVendorCreditDto, EditVendorCreditDto } from './dtos/VendorCredit.dto';
|
import {
|
||||||
|
CreateVendorCreditDto,
|
||||||
|
EditVendorCreditDto,
|
||||||
|
} from './dtos/VendorCredit.dto';
|
||||||
|
import { BulkDeleteVendorCreditsService } from './BulkDeleteVendorCredits.service';
|
||||||
|
import { ValidateBulkDeleteVendorCreditsService } from './ValidateBulkDeleteVendorCredits.service';
|
||||||
|
import { ValidateBulkDeleteResponseDto } from '@/common/dtos/BulkDelete.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VendorCreditsApplicationService {
|
export class VendorCreditsApplicationService {
|
||||||
@@ -25,7 +34,9 @@ export class VendorCreditsApplicationService {
|
|||||||
private readonly getVendorCreditService: GetVendorCreditService,
|
private readonly getVendorCreditService: GetVendorCreditService,
|
||||||
private readonly openVendorCreditService: OpenVendorCreditService,
|
private readonly openVendorCreditService: OpenVendorCreditService,
|
||||||
private readonly getVendorCreditsService: GetVendorCreditsService,
|
private readonly getVendorCreditsService: GetVendorCreditsService,
|
||||||
) {}
|
private readonly bulkDeleteVendorCreditsService: BulkDeleteVendorCreditsService,
|
||||||
|
private readonly validateBulkDeleteVendorCreditsService: ValidateBulkDeleteVendorCreditsService,
|
||||||
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new vendor credit.
|
* Creates a new vendor credit.
|
||||||
@@ -90,4 +101,22 @@ export class VendorCreditsApplicationService {
|
|||||||
getVendorCredits(query: IVendorCreditsQueryDTO) {
|
getVendorCredits(query: IVendorCreditsQueryDTO) {
|
||||||
return this.getVendorCreditsService.getVendorCredits(query);
|
return this.getVendorCreditsService.getVendorCredits(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bulkDeleteVendorCredits(
|
||||||
|
vendorCreditIds: number[],
|
||||||
|
options?: { skipUndeletable?: boolean },
|
||||||
|
) {
|
||||||
|
return this.bulkDeleteVendorCreditsService.bulkDeleteVendorCredits(
|
||||||
|
vendorCreditIds,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateBulkDeleteVendorCredits(
|
||||||
|
vendorCreditIds: number[],
|
||||||
|
): Promise<ValidateBulkDeleteResponseDto> {
|
||||||
|
return this.validateBulkDeleteVendorCreditsService.validateBulkDeleteVendorCredits(
|
||||||
|
vendorCreditIds,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user