feat(sdk): add banking and vendor credits SDK utilities

- Add SDK types for bank rules, cashflow accounts, and vendor credits
- Update banking controllers with proper OpenAPI annotations
- Update vendor credits controllers with new endpoints and DTOs
- Enhance banking transaction handling for categorize, recognize, pending, and exclude operations
- Add vendor credit apply bills and refund functionality

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ahmed Bouhuolia
2026-03-05 23:06:44 +02:00
parent 4c059d610e
commit 631df56cee
14 changed files with 587 additions and 49 deletions

View File

@@ -3,7 +3,9 @@ import { castArray, omit } from 'lodash';
import { BankingCategorizeApplication } from './BankingCategorize.application';
import { CategorizeBankTransactionRouteDto } from './dtos/CategorizeBankTransaction.dto';
import {
ApiBody,
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
ApiTags,
@@ -20,6 +22,7 @@ export class BankingCategorizeController {
@Post()
@ApiOperation({ summary: 'Categorize bank transactions.' })
@ApiBody({ type: CategorizeBankTransactionRouteDto })
@ApiResponse({
status: 200,
description: 'The bank transactions have been categorized successfully.',
@@ -60,6 +63,12 @@ export class BankingCategorizeController {
@Delete('/:id')
@ApiOperation({ summary: 'Uncategorize a bank transaction.' })
@ApiParam({
name: 'id',
required: true,
type: Number,
description: 'Uncategorized transaction ID to uncategorize',
})
@ApiResponse({
status: 200,
description: 'The bank transaction has been uncategorized successfully.',

View File

@@ -8,13 +8,14 @@ import {
ApiExtraModels,
getSchemaPath,
} from '@nestjs/swagger';
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
import { GetRecognizedTransactionResponseDto } from './dtos/GetRecognizedTransactionResponse.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@Controller('banking/recognized')
@ApiTags('Banking Recognized Transactions')
@ApiExtraModels(GetRecognizedTransactionResponseDto)
@ApiExtraModels(GetRecognizedTransactionResponseDto, PaginatedResponseDto)
@ApiCommonHeaders()
export class BankingRecognizedTransactionsController {
constructor(
@@ -58,10 +59,17 @@ export class BankingRecognizedTransactionsController {
status: 200,
description: 'Returns a list of recognized transactions',
schema: {
type: 'array',
items: {
$ref: getSchemaPath(GetRecognizedTransactionResponseDto),
},
allOf: [
{ $ref: getSchemaPath(PaginatedResponseDto) },
{
properties: {
data: {
type: 'array',
items: { $ref: getSchemaPath(GetRecognizedTransactionResponseDto) },
},
},
},
],
},
})
async getRecognizedTransactions(@Query() query: any) {

View File

@@ -7,14 +7,15 @@ import {
getSchemaPath,
ApiExtraModels,
} from '@nestjs/swagger';
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import { BankingTransactionsApplication } from '../BankingTransactionsApplication.service';
import { GetPendingTransactionsQueryDto } from '../dtos/GetPendingTransactionsQuery.dto';
import { GetPendingTransactionResponseDto } from '../dtos/GetPendingTransactionResponse.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@Controller('banking/pending')
@ApiTags('Banking Pending Transactions')
@ApiExtraModels(GetPendingTransactionResponseDto)
@ApiExtraModels(GetPendingTransactionResponseDto, PaginatedResponseDto)
@ApiCommonHeaders()
export class BankingPendingTransactionsController {
constructor(
@@ -27,7 +28,17 @@ export class BankingPendingTransactionsController {
status: 200,
description: 'Returns a list of pending bank account transactions',
schema: {
$ref: getSchemaPath(GetPendingTransactionResponseDto),
allOf: [
{ $ref: getSchemaPath(PaginatedResponseDto) },
{
properties: {
data: {
type: 'array',
items: { $ref: getSchemaPath(GetPendingTransactionResponseDto) },
},
},
},
],
},
})
@ApiQuery({

View File

@@ -15,14 +15,15 @@ import {
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import { GetExcludedBankTransactionResponseDto } from './dtos/GetExcludedBankTransactionResponse.dto';
import { ExcludeBankTransactionsBulkDto } from './dtos/ExcludeBankTransactionsBulk.dto';
import { GetExcludedBankTransactionsQueryDto } from './dtos/GetExcludedBankTransactionsQuery.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
@Controller('banking/exclude')
@ApiTags('Banking Transactions')
@ApiExtraModels(GetExcludedBankTransactionResponseDto, ExcludeBankTransactionsBulkDto)
@ApiExtraModels(GetExcludedBankTransactionResponseDto, ExcludeBankTransactionsBulkDto, PaginatedResponseDto)
@ApiCommonHeaders()
export class BankingTransactionsExcludeController {
constructor(
@@ -54,10 +55,17 @@ export class BankingTransactionsExcludeController {
description:
'The excluded bank transactions has been retrieved successfully.',
schema: {
type: 'array',
items: {
$ref: getSchemaPath(GetExcludedBankTransactionResponseDto),
},
allOf: [
{ $ref: getSchemaPath(PaginatedResponseDto) },
{
properties: {
data: {
type: 'array',
items: { $ref: getSchemaPath(GetExcludedBankTransactionResponseDto) },
},
},
},
],
},
})
public getExcludedBankTransactions(

View File

@@ -8,9 +8,9 @@ import {
UseGuards,
} from '@nestjs/common';
import { VendorCreditApplyBillsApplicationService } from './VendorCreditApplyBillsApplication.service';
import { IVendorCreditApplyToInvoicesDTO } from './types/VendorCreditApplyBills.types';
import { ApiTags } from '@nestjs/swagger';
import { ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import { ApplyVendorCreditToBillsDto } from './dtos/ApplyVendorCreditToBills.dto';
import { RequirePermission } from '@/modules/Roles/RequirePermission.decorator';
import { PermissionGuard } from '@/modules/Roles/Permission.guard';
import { AuthorizationGuard } from '@/modules/Roles/Authorization.guard';
@@ -28,6 +28,7 @@ export class VendorCreditApplyBillsController {
@Get(':vendorCreditId/bills-to-apply')
@RequirePermission(VendorCreditAction.View, AbilitySubject.VendorCredit)
@ApiOperation({ summary: 'Get bills that can be applied with this vendor credit.' })
async getVendorCreditToApplyBills(
@Param('vendorCreditId') vendorCreditId: number,
) {
@@ -38,9 +39,11 @@ export class VendorCreditApplyBillsController {
@Post(':vendorCreditId/apply-to-bills')
@RequirePermission(VendorCreditAction.Edit, AbilitySubject.VendorCredit)
@ApiOperation({ summary: 'Apply vendor credit to the given bills.' })
@ApiBody({ type: ApplyVendorCreditToBillsDto })
async applyVendorCreditToBills(
@Param('vendorCreditId') vendorCreditId: number,
@Body() applyCreditToBillsDTO: IVendorCreditApplyToInvoicesDTO,
@Body() applyCreditToBillsDTO: ApplyVendorCreditToBillsDto,
) {
return this.vendorCreditApplyBillsApplication.applyVendorCreditToBills(
vendorCreditId,
@@ -50,6 +53,7 @@ export class VendorCreditApplyBillsController {
@Delete('applied-bills/:vendorCreditAppliedBillId')
@RequirePermission(VendorCreditAction.Edit, AbilitySubject.VendorCredit)
@ApiOperation({ summary: 'Remove an applied bill from the vendor credit.' })
async deleteAppliedBillToVendorCredit(
@Param('vendorCreditAppliedBillId') vendorCreditAppliedBillId: number,
) {
@@ -60,6 +64,7 @@ export class VendorCreditApplyBillsController {
@Get(':vendorCreditId/applied-bills')
@RequirePermission(VendorCreditAction.View, AbilitySubject.VendorCredit)
@ApiOperation({ summary: 'Get bills already applied to this vendor credit.' })
async getAppliedBillsToVendorCredit(
@Param('vendorCreditId') vendorCreditId: number,
) {

View File

@@ -0,0 +1,38 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
ArrayMinSize,
IsArray,
IsInt,
IsNotEmpty,
IsNumber,
ValidateNested,
} from 'class-validator';
export class ApplyVendorCreditToBillEntryDto {
@IsNotEmpty()
@IsInt()
@ApiProperty({ description: 'Bill ID to apply vendor credit to', example: 1 })
billId: number;
@IsNotEmpty()
@IsNumber()
@ApiProperty({ description: 'Amount to apply', example: 100.5 })
amount: number;
}
export class ApplyVendorCreditToBillsDto {
@IsArray()
@ArrayMinSize(1)
@ValidateNested({ each: true })
@Type(() => ApplyVendorCreditToBillEntryDto)
@ApiProperty({
description: 'Entries of bill ID and amount to apply',
type: [ApplyVendorCreditToBillEntryDto],
example: [
{ billId: 1, amount: 100.5 },
{ billId: 2, amount: 50 },
],
})
entries: ApplyVendorCreditToBillEntryDto[];
}

View File

@@ -3,6 +3,7 @@ import { DeleteRefundVendorCreditService } from './commands/DeleteRefundVendorCr
import { RefundVendorCredit } from './models/RefundVendorCredit';
import { CreateRefundVendorCredit } from './commands/CreateRefundVendorCredit.service';
import { RefundVendorCreditDto } from './dtos/RefundVendorCredit.dto';
import { GetRefundVendorCreditService } from './queries/GetRefundVendorCredit.service';
import { GetRefundVendorCreditsService } from './queries/GetRefundVendorCredits.service';
import { IRefundVendorCreditPOJO } from './types/VendorCreditRefund.types';
@@ -12,11 +13,13 @@ export class VendorCreditsRefundApplication {
* @param {CreateRefundVendorCredit} createRefundVendorCreditService
* @param {DeleteRefundVendorCreditService} deleteRefundVendorCreditService
* @param {GetRefundVendorCreditsService} getRefundVendorCreditsService
* @param {GetRefundVendorCreditService} getRefundVendorCreditService
*/
constructor(
private readonly createRefundVendorCreditService: CreateRefundVendorCredit,
private readonly deleteRefundVendorCreditService: DeleteRefundVendorCreditService,
private readonly getRefundVendorCreditsService: GetRefundVendorCreditsService,
private readonly getRefundVendorCreditService: GetRefundVendorCreditService,
) { }
/**
@@ -48,6 +51,19 @@ export class VendorCreditsRefundApplication {
);
}
/**
* Retrieve a single refund vendor credit transaction by id.
* @param {number} refundCreditId
* @returns {Promise<IRefundVendorCreditPOJO>}
*/
public getRefundVendorCreditTransaction(
refundCreditId: number,
): Promise<IRefundVendorCreditPOJO> {
return this.getRefundVendorCreditService.getRefundCreditTransaction(
refundCreditId,
);
}
/**
* Deletes a refund vendor credit.
* @param {number} refundCreditId

View File

@@ -27,6 +27,22 @@ export class VendorCreditsRefundController {
private readonly vendorCreditsRefundApplication: VendorCreditsRefundApplication,
) { }
/**
* Retrieve a single refund vendor credit transaction by id.
* @param {number} refundCreditId
* @returns {Promise<IRefundVendorCreditPOJO>}
*/
@Get('refunds/:refundCreditId')
@RequirePermission(VendorCreditAction.View, AbilitySubject.VendorCredit)
@ApiOperation({ summary: 'Retrieve a refund vendor credit transaction by id.' })
public getRefundVendorCreditTransaction(
@Param('refundCreditId') refundCreditId: string,
) {
return this.vendorCreditsRefundApplication.getRefundVendorCreditTransaction(
Number(refundCreditId),
);
}
/**
* Retrieve the vendor credit refunds graph.
* @param {number} vendorCreditId - Vendor credit id.

View File

@@ -1,4 +1,5 @@
import { Module } from '@nestjs/common';
import { GetRefundVendorCreditService } from './queries/GetRefundVendorCredit.service';
import { GetRefundVendorCreditsService } from './queries/GetRefundVendorCredits.service';
import { DeleteRefundVendorCreditService } from './commands/DeleteRefundVendorCredit.service';
import { VendorCreditsRefundController } from './VendorCreditsRefund.controller';
@@ -14,6 +15,7 @@ import { AccountsModule } from '../Accounts/Accounts.module';
@Module({
imports: [WarehousesModule, BranchesModule, LedgerModule, AccountsModule],
providers: [
GetRefundVendorCreditService,
GetRefundVendorCreditsService,
DeleteRefundVendorCreditService,
CreateRefundVendorCredit,

View File

@@ -11329,6 +11329,47 @@
}
},
"/api/vendor-credits/refunds/{refundCreditId}": {
"get": {
"operationId": "VendorCreditsRefundController_getRefundVendorCreditTransaction",
"summary": "Retrieve a refund vendor credit transaction by id.",
"parameters": [
{
"name": "Authorization",
"in": "header",
"description": "Value must be 'Bearer <token>' where <token> is an API key prefixed with 'bc_' or a JWT token.",
"required": true,
"schema": {
"type": "string",
"example": "Bearer bc_1234567890abcdef"
}
},
{
"name": "organization-id",
"in": "header",
"description": "Required if Authorization is a JWT token. The organization ID to operate within.",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "refundCreditId",
"required": true,
"in": "path",
"schema": {
"type": "number"
}
}
],
"responses": {
"200": {
"description": ""
}
},
"tags": [
"Vendor Credits Refunds"
]
},
"delete": {
"operationId": "VendorCreditsRefundController_deleteRefundVendorCredit",
"summary": "Delete a refund for the given vendor credit.",
@@ -12492,7 +12533,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetPendingTransactionResponseDto"
"allOf": [
{ "$ref": "#/components/schemas/PaginatedResponseDto" },
{
"properties": {
"data": {
"type": "array",
"items": { "$ref": "#/components/schemas/GetPendingTransactionResponseDto" }
}
}
}
]
}
}
}
@@ -12832,10 +12883,17 @@
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/GetRecognizedTransactionResponseDto"
}
"allOf": [
{ "$ref": "#/components/schemas/PaginatedResponseDto" },
{
"properties": {
"data": {
"type": "array",
"items": { "$ref": "#/components/schemas/GetRecognizedTransactionResponseDto" }
}
}
}
]
}
}
}
@@ -12871,6 +12929,16 @@
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ExcludeBankTransactionsBulkDto"
}
}
}
},
"responses": {
"200": {
"description": ""
@@ -12904,6 +12972,16 @@
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ExcludeBankTransactionsBulkDto"
}
}
}
},
"responses": {
"200": {
"description": ""
@@ -12945,10 +13023,17 @@
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/GetExcludedBankTransactionResponseDto"
}
"allOf": [
{ "$ref": "#/components/schemas/PaginatedResponseDto" },
{
"properties": {
"data": {
"type": "array",
"items": { "$ref": "#/components/schemas/GetExcludedBankTransactionResponseDto" }
}
}
}
]
}
}
}
@@ -45120,6 +45205,18 @@
"bankRuleName"
]
},
"ExcludeBankTransactionsBulkDto": {
"type": "object",
"required": ["ids"],
"properties": {
"ids": {
"type": "array",
"items": { "type": "number" },
"description": "IDs of uncategorized bank transactions to exclude or unexclude",
"example": [1, 2, 3]
}
}
},
"GetExcludedBankTransactionResponseDto": {
"type": "object",
"properties": {

View File

@@ -59,6 +59,15 @@ export type AutofillCategorizeTransactionResponse = OpResponseBody<OpForPath<typ
/** Response for GET /api/banking/recognized (single). */
export type RecognizedTransactionResponse = OpResponseBody<OpForPath<typeof BANK_RULES_ROUTES.RECOGNIZED, 'get'>>;
/** Paginated list response for GET /api/banking/recognized (from OpenAPI schema). */
export type BankTransactionsListPage = OpResponseBody<OpForPath<typeof BANK_RULES_ROUTES.RECOGNIZED_LIST, 'get'>>;
/** Paginated list response for GET /api/banking/exclude (from OpenAPI schema). */
export type ExcludedBankTransactionsListPage = OpResponseBody<OpForPath<typeof BANK_RULES_ROUTES.EXCLUDED_LIST, 'get'>>;
/** Paginated list response for GET /api/banking/pending (from OpenAPI schema). */
export type PendingBankTransactionsListPage = OpResponseBody<OpForPath<typeof BANK_RULES_ROUTES.PENDING, 'get'>>;
export async function fetchBankRules(fetcher: ApiFetcher): Promise<BankRulesListResponse> {
const get = fetcher.path(BANK_RULES_ROUTES.RULES).method('get').create();
const { data } = await get({});
@@ -195,7 +204,7 @@ export async function excludeBankTransactionsBulk(
body: ExcludeBankTransactionsBulkBody
): Promise<void> {
const put = fetcher.path(BANK_RULES_ROUTES.EXCLUDE_BULK).method('put').create();
await put(body);
await (put as (params: ExcludeBankTransactionsBulkBody) => Promise<unknown>)(body);
}
export async function unexcludeBankTransactionsBulk(
@@ -203,7 +212,7 @@ export async function unexcludeBankTransactionsBulk(
body: ExcludeBankTransactionsBulkBody
): Promise<void> {
const del = fetcher.path(BANK_RULES_ROUTES.EXCLUDE_BULK).method('delete').create();
await del(body);
await (del as (params: ExcludeBankTransactionsBulkBody) => Promise<unknown>)(body);
}
export async function fetchRecognizedTransaction(
@@ -218,7 +227,7 @@ export async function fetchRecognizedTransaction(
export async function fetchRecognizedTransactions(
fetcher: ApiFetcher,
params?: Record<string, unknown>
): Promise<unknown> {
): Promise<BankTransactionsListPage> {
const get = fetcher.path(BANK_RULES_ROUTES.RECOGNIZED_LIST).method('get').create();
const { data } = await get(params ?? {});
return data;
@@ -227,7 +236,7 @@ export async function fetchRecognizedTransactions(
export async function fetchExcludedBankTransactions(
fetcher: ApiFetcher,
params?: GetExcludedBankTransactionsQuery
): Promise<unknown> {
): Promise<ExcludedBankTransactionsListPage> {
const get = fetcher.path(BANK_RULES_ROUTES.EXCLUDED_LIST).method('get').create();
const { data } = await get(params ?? {});
return data;
@@ -236,7 +245,7 @@ export async function fetchExcludedBankTransactions(
export async function fetchPendingTransactions(
fetcher: ApiFetcher,
params?: GetPendingTransactionsQuery
): Promise<unknown> {
): Promise<PendingBankTransactionsListPage> {
const get = fetcher.path(BANK_RULES_ROUTES.PENDING).method('get').create();
const { data } = await get(params ?? {});
return data;

View File

@@ -1,10 +1,16 @@
import type { ApiFetcher } from './fetch-utils';
import { paths } from './schema';
import { OpForPath, OpResponseBody } from './utils';
import { OpForPath, OpQueryParams, OpRequestBody, OpResponseBody } from './utils';
export const BANKING_ACCOUNTS_ROUTES = {
LIST: '/api/banking/accounts',
SUMMARY: '/api/banking/accounts/{bankAccountId}/summary',
TRANSACTIONS: '/api/banking/transactions',
TRANSACTION_BY_ID: '/api/banking/transactions/{id}',
UNCATEGORIZED_BY_ACCOUNT: '/api/banking/uncategorized/accounts/{accountId}',
UNCATEGORIZED_BY_ID: '/api/banking/uncategorized/{uncategorizedTransactionId}',
CATEGORIZE: '/api/banking/categorize',
UNCATEGORIZE: '/api/banking/categorize/{id}',
} as const satisfies Record<string, keyof paths>;
export type BankingAccountsListResponse = OpResponseBody<OpForPath<typeof BANKING_ACCOUNTS_ROUTES.LIST, 'get'>>;
@@ -30,3 +36,103 @@ export async function fetchBankingAccountSummary(
const { data } = await get({ bankAccountId });
return data as BankingAccountSummaryResponse;
}
/** Query params for GET /api/banking/transactions. */
export type GetBankingTransactionsQuery = OpQueryParams<
OpForPath<typeof BANKING_ACCOUNTS_ROUTES.TRANSACTIONS, 'get'>
>;
/** Server returns { transactions, pagination } (OpenAPI schema says data). */
export type BankingTransactionsListResponse = OpResponseBody<
OpForPath<typeof BANKING_ACCOUNTS_ROUTES.TRANSACTIONS, 'get'>
> & { transactions?: unknown[] };
/** Query params for GET /api/banking/uncategorized/accounts/{accountId}. */
export type GetUncategorizedTransactionsQuery = OpQueryParams<
OpForPath<typeof BANKING_ACCOUNTS_ROUTES.UNCATEGORIZED_BY_ACCOUNT, 'get'>
>;
/** Body for POST /api/banking/transactions. */
export type CreateBankingTransactionBody = OpRequestBody<
OpForPath<typeof BANKING_ACCOUNTS_ROUTES.TRANSACTIONS, 'post'>
>;
/** Body for POST /api/banking/categorize. */
export type CategorizeTransactionBody = OpRequestBody<
OpForPath<typeof BANKING_ACCOUNTS_ROUTES.CATEGORIZE, 'post'>
>;
export async function fetchBankingTransactions(
fetcher: ApiFetcher,
query: GetBankingTransactionsQuery
): Promise<BankingTransactionsListResponse> {
const get = fetcher.path(BANKING_ACCOUNTS_ROUTES.TRANSACTIONS).method('get').create();
const { data } = await get(query);
return data as BankingTransactionsListResponse;
}
export async function getBankingTransaction(
fetcher: ApiFetcher,
id: string | number
): Promise<unknown> {
const get = fetcher.path(BANKING_ACCOUNTS_ROUTES.TRANSACTION_BY_ID).method('get').create();
const { data } = await get({ id: String(id) });
return data;
}
export async function createBankingTransaction(
fetcher: ApiFetcher,
body: CreateBankingTransactionBody
): Promise<void> {
const post = fetcher.path(BANKING_ACCOUNTS_ROUTES.TRANSACTIONS).method('post').create();
await post(body);
}
export async function deleteBankingTransaction(
fetcher: ApiFetcher,
id: string | number
): Promise<void> {
const del = fetcher.path(BANKING_ACCOUNTS_ROUTES.TRANSACTION_BY_ID).method('delete').create();
await del({ id: String(id) });
}
export async function fetchUncategorizedTransactions(
fetcher: ApiFetcher,
accountId: number,
query: GetUncategorizedTransactionsQuery
): Promise<{ data?: unknown[]; pagination: { page: number; pageSize: number; total: number } }> {
const get = fetcher
.path(BANKING_ACCOUNTS_ROUTES.UNCATEGORIZED_BY_ACCOUNT)
.method('get')
.create();
const { data } = await get({ accountId, ...query });
return data as { data?: unknown[]; pagination: { page: number; pageSize: number; total: number } };
}
export async function getUncategorizedTransaction(
fetcher: ApiFetcher,
uncategorizedTransactionId: number
): Promise<unknown> {
const get = fetcher
.path(BANKING_ACCOUNTS_ROUTES.UNCATEGORIZED_BY_ID)
.method('get')
.create();
const { data } = await get({ uncategorizedTransactionId });
return data;
}
export async function categorizeTransaction(
fetcher: ApiFetcher,
body: CategorizeTransactionBody
): Promise<void> {
const post = fetcher.path(BANKING_ACCOUNTS_ROUTES.CATEGORIZE).method('post').create();
await post(body);
}
export async function uncategorizeTransaction(
fetcher: ApiFetcher,
id: number
): Promise<void> {
const del = fetcher.path(BANKING_ACCOUNTS_ROUTES.UNCATEGORIZE).method('delete').create();
await del({ id });
}

View File

@@ -3018,7 +3018,8 @@ export interface paths {
path?: never;
cookie?: never;
};
get?: never;
/** Retrieve a refund vendor credit transaction by id. */
get: operations["VendorCreditsRefundController_getRefundVendorCreditTransaction"];
put?: never;
post?: never;
/** Delete a refund for the given vendor credit. */
@@ -11258,6 +11259,17 @@ export interface components {
*/
bankRuleName: string;
};
ExcludeBankTransactionsBulkDto: {
/**
* @description IDs of uncategorized bank transactions to exclude or unexclude
* @example [
* 1,
* 2,
* 3
* ]
*/
ids: number[];
};
GetExcludedBankTransactionResponseDto: {
/** @description Transaction amount (positive for deposit, negative for withdrawal) */
amount: number;
@@ -18847,6 +18859,30 @@ export interface operations {
};
};
};
VendorCreditsRefundController_getRefundVendorCreditTransaction: {
parameters: {
query?: never;
header: {
/** @description Value must be 'Bearer <token>' where <token> is an API key prefixed with 'bc_' or a JWT token. */
Authorization: string;
/** @description Required if Authorization is a JWT token. The organization ID to operate within. */
"organization-id": string;
};
path: {
refundCreditId: number;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
VendorCreditsRefundController_deleteRefundVendorCredit: {
parameters: {
query?: never;
@@ -19447,7 +19483,9 @@ export interface operations {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GetPendingTransactionResponseDto"];
"application/json": components["schemas"]["PaginatedResponseDto"] & {
data?: components["schemas"]["GetPendingTransactionResponseDto"][];
};
};
};
};
@@ -19644,7 +19682,9 @@ export interface operations {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GetRecognizedTransactionResponseDto"][];
"application/json": components["schemas"]["PaginatedResponseDto"] & {
data?: components["schemas"]["GetRecognizedTransactionResponseDto"][];
};
};
};
};
@@ -19661,7 +19701,11 @@ export interface operations {
path?: never;
cookie?: never;
};
requestBody?: never;
requestBody: {
content: {
"application/json": components["schemas"]["ExcludeBankTransactionsBulkDto"];
};
};
responses: {
200: {
headers: {
@@ -19683,7 +19727,11 @@ export interface operations {
path?: never;
cookie?: never;
};
requestBody?: never;
requestBody: {
content: {
"application/json": components["schemas"]["ExcludeBankTransactionsBulkDto"];
};
};
responses: {
200: {
headers: {
@@ -19713,7 +19761,9 @@ export interface operations {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["GetExcludedBankTransactionResponseDto"][];
"application/json": components["schemas"]["PaginatedResponseDto"] & {
data?: components["schemas"]["GetExcludedBankTransactionResponseDto"][];
};
};
};
};

View File

@@ -1,6 +1,11 @@
import type { ApiFetcher } from './fetch-utils';
import { paths } from './schema';
import { OpForPath, OpRequestBody, OpResponseBody } from './utils';
import {
OpForPath,
OpQueryParams,
OpRequestBody,
OpResponseBody,
} from './utils';
export const VENDOR_CREDITS_ROUTES = {
LIST: '/api/vendor-credits',
@@ -8,20 +13,59 @@ export const VENDOR_CREDITS_ROUTES = {
OPEN: '/api/vendor-credits/{id}/open',
VALIDATE_BULK_DELETE: '/api/vendor-credits/validate-bulk-delete',
BULK_DELETE: '/api/vendor-credits/bulk-delete',
REFUND: '/api/vendor-credits/{vendorCreditId}/refund',
REFUND_BY_ID: '/api/vendor-credits/refunds/{refundCreditId}',
BILLS_TO_APPLY: '/api/vendor-credits/{vendorCreditId}/bills-to-apply',
APPLY_TO_BILLS: '/api/vendor-credits/{vendorCreditId}/apply-to-bills',
APPLIED_BILLS: '/api/vendor-credits/{vendorCreditId}/applied-bills',
DELETE_APPLIED_BILL: '/api/vendor-credits/applied-bills/{vendorCreditAppliedBillId}',
} as const satisfies Record<string, keyof paths>;
export type VendorCreditsListResponse = OpResponseBody<OpForPath<typeof VENDOR_CREDITS_ROUTES.LIST, 'get'>>;
export type VendorCredit = OpResponseBody<OpForPath<typeof VENDOR_CREDITS_ROUTES.BY_ID, 'get'>>;
export type CreateVendorCreditBody = OpRequestBody<OpForPath<typeof VENDOR_CREDITS_ROUTES.LIST, 'post'>>;
export type EditVendorCreditBody = OpRequestBody<OpForPath<typeof VENDOR_CREDITS_ROUTES.BY_ID, 'put'>>;
export type VendorCreditsListResponse = OpResponseBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.LIST, 'get'>
>;
export type VendorCredit = OpResponseBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.BY_ID, 'get'>
>;
export type CreateVendorCreditBody = OpRequestBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.LIST, 'post'>
>;
export type EditVendorCreditBody = OpRequestBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.BY_ID, 'put'>
>;
export type GetVendorCreditsQuery = OpQueryParams<
OpForPath<typeof VENDOR_CREDITS_ROUTES.LIST, 'get'>
>;
export type BulkDeleteVendorCreditsBody = OpRequestBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.BULK_DELETE, 'post'>
>;
export type ValidateBulkDeleteVendorCreditsResponse = OpResponseBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.VALIDATE_BULK_DELETE, 'post'>
>;
export type CreateRefundVendorCreditBody = OpRequestBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.REFUND, 'post'>
>;
export type ApplyVendorCreditToBillsBody = OpRequestBody<
OpForPath<typeof VENDOR_CREDITS_ROUTES.APPLY_TO_BILLS, 'post'>
>;
export async function fetchVendorCredits(fetcher: ApiFetcher): Promise<VendorCreditsListResponse> {
export async function fetchVendorCredits(
fetcher: ApiFetcher,
query?: GetVendorCreditsQuery
): Promise<VendorCreditsListResponse> {
const get = fetcher.path(VENDOR_CREDITS_ROUTES.LIST).method('get').create();
const { data } = await get({});
const { data } = await (
get as (params?: GetVendorCreditsQuery) => Promise<{
data: VendorCreditsListResponse;
}>
)(query ?? {});
return data;
}
export async function fetchVendorCredit(fetcher: ApiFetcher, id: number): Promise<VendorCredit> {
export async function fetchVendorCredit(
fetcher: ApiFetcher,
id: number
): Promise<VendorCredit> {
const get = fetcher.path(VENDOR_CREDITS_ROUTES.BY_ID).method('get').create();
const { data } = await get({ id });
return data;
@@ -44,12 +88,131 @@ export async function editVendorCredit(
await put({ id, ...values });
}
export async function deleteVendorCredit(fetcher: ApiFetcher, id: number): Promise<void> {
export async function deleteVendorCredit(
fetcher: ApiFetcher,
id: number
): Promise<void> {
const del = fetcher.path(VENDOR_CREDITS_ROUTES.BY_ID).method('delete').create();
await del({ id });
}
export async function openVendorCredit(fetcher: ApiFetcher, id: number): Promise<void> {
export async function openVendorCredit(
fetcher: ApiFetcher,
id: number
): Promise<void> {
const put = fetcher.path(VENDOR_CREDITS_ROUTES.OPEN).method('put').create();
await put({ id });
}
export async function bulkDeleteVendorCredits(
fetcher: ApiFetcher,
body: BulkDeleteVendorCreditsBody
): Promise<void> {
const post = fetcher
.path(VENDOR_CREDITS_ROUTES.BULK_DELETE)
.method('post')
.create();
await post(body);
}
export async function validateBulkDeleteVendorCredits(
fetcher: ApiFetcher,
body: BulkDeleteVendorCreditsBody
): Promise<ValidateBulkDeleteVendorCreditsResponse> {
const post = fetcher
.path(VENDOR_CREDITS_ROUTES.VALIDATE_BULK_DELETE)
.method('post')
.create();
const { data } = await post(body);
return data;
}
// Refunds (path param vendorCreditId is string in OpenAPI)
export async function fetchVendorCreditRefunds(
fetcher: ApiFetcher,
vendorCreditId: number
): Promise<unknown> {
const get = fetcher.path(VENDOR_CREDITS_ROUTES.REFUND).method('get').create();
const { data } = await get({ vendorCreditId: String(vendorCreditId) });
return data;
}
export async function createRefundVendorCredit(
fetcher: ApiFetcher,
vendorCreditId: number,
values: CreateRefundVendorCreditBody
): Promise<void> {
const post = fetcher.path(VENDOR_CREDITS_ROUTES.REFUND).method('post').create();
await post({ vendorCreditId: String(vendorCreditId), ...values });
}
export async function fetchRefundVendorCreditTransaction(
fetcher: ApiFetcher,
refundCreditId: number
): Promise<unknown> {
const get = fetcher
.path(VENDOR_CREDITS_ROUTES.REFUND_BY_ID)
.method('get')
.create();
const { data } = await get({ refundCreditId });
return data;
}
export async function deleteRefundVendorCredit(
fetcher: ApiFetcher,
refundCreditId: number
): Promise<void> {
const del = fetcher
.path(VENDOR_CREDITS_ROUTES.REFUND_BY_ID)
.method('delete')
.create();
await del({ refundCreditId: String(refundCreditId) });
}
// Apply to bills
export async function fetchVendorCreditToApplyBills(
fetcher: ApiFetcher,
vendorCreditId: number
): Promise<unknown> {
const get = fetcher
.path(VENDOR_CREDITS_ROUTES.BILLS_TO_APPLY)
.method('get')
.create();
const { data } = await get({ vendorCreditId });
return data;
}
export async function applyVendorCreditToBills(
fetcher: ApiFetcher,
vendorCreditId: number,
body: ApplyVendorCreditToBillsBody
): Promise<void> {
const post = fetcher
.path(VENDOR_CREDITS_ROUTES.APPLY_TO_BILLS)
.method('post')
.create();
await post({ vendorCreditId, ...body });
}
export async function fetchAppliedBillsToVendorCredit(
fetcher: ApiFetcher,
vendorCreditId: number
): Promise<unknown> {
const get = fetcher
.path(VENDOR_CREDITS_ROUTES.APPLIED_BILLS)
.method('get')
.create();
const { data } = await get({ vendorCreditId });
return data;
}
export async function deleteAppliedBillToVendorCredit(
fetcher: ApiFetcher,
vendorCreditAppliedBillId: number
): Promise<void> {
const del = fetcher
.path(VENDOR_CREDITS_ROUTES.DELETE_APPLIED_BILL)
.method('delete')
.create();
await del({ vendorCreditAppliedBillId });
}