diff --git a/packages/server/src/common/config/bank-feed.ts b/packages/server/src/common/config/bankfeed.ts similarity index 76% rename from packages/server/src/common/config/bank-feed.ts rename to packages/server/src/common/config/bankfeed.ts index 8c8fca1ff..ec9ef6494 100644 --- a/packages/server/src/common/config/bank-feed.ts +++ b/packages/server/src/common/config/bankfeed.ts @@ -1,6 +1,6 @@ import { registerAs } from '@nestjs/config'; -export default registerAs('bank-feed', () => ({ +export default registerAs('bankfeed', () => ({ enabled: process.env.BANK_FEED_ENABLED === 'true' || process.env.BANK_FEED_ENABLED === 'yes', diff --git a/packages/server/src/common/config/index.ts b/packages/server/src/common/config/index.ts index 9095c21db..2e9a5fc30 100644 --- a/packages/server/src/common/config/index.ts +++ b/packages/server/src/common/config/index.ts @@ -13,6 +13,7 @@ import signupRestrictions from './signup-restrictions'; import jwt from './jwt'; import mail from './mail'; import loops from './loops'; +import bankfeed from './bankfeed'; export const config = [ systemDatabase, @@ -29,5 +30,6 @@ export const config = [ signupRestrictions, jwt, mail, - loops + loops, + bankfeed, ]; diff --git a/packages/server/src/modules/App/App.module.ts b/packages/server/src/modules/App/App.module.ts index b04b92c28..2342e762f 100644 --- a/packages/server/src/modules/App/App.module.ts +++ b/packages/server/src/modules/App/App.module.ts @@ -89,6 +89,7 @@ import { CurrenciesModule } from '../Currencies/Currencies.module'; import { MiscellaneousModule } from '../Miscellaneous/Miscellaneous.module'; import { UsersModule } from '../UsersModule/Users.module'; import { ContactsModule } from '../Contacts/Contacts.module'; +import { BankingPlaidModule } from '../BankingPlaid/BankingPlaid.module'; @Module({ imports: [ @@ -186,6 +187,7 @@ import { ContactsModule } from '../Contacts/Contacts.module'; BankingTransactionsExcludeModule, BankingTransactionsRegonizeModule, BankingMatchingModule, + BankingPlaidModule, TransactionsLockingModule, SettingsModule, FeaturesModule, diff --git a/packages/server/src/modules/BankingPlaid/BankingPlaid.controller.ts b/packages/server/src/modules/BankingPlaid/BankingPlaid.controller.ts new file mode 100644 index 000000000..bf1b93787 --- /dev/null +++ b/packages/server/src/modules/BankingPlaid/BankingPlaid.controller.ts @@ -0,0 +1,22 @@ +import { Body, Controller, Post } from '@nestjs/common'; +import { PlaidApplication } from './PlaidApplication'; +import { PlaidItemDto } from './dtos/PlaidItem.dto'; +import { ApiOperation, ApiTags } from '@nestjs/swagger'; + +@Controller('banking/plaid') +@ApiTags('banking-plaid') +export class BankingPlaidController { + constructor(private readonly plaidApplication: PlaidApplication) {} + + @Post('link-token') + @ApiOperation({ summary: 'Get Plaid link token' }) + getLinkToken() { + return this.plaidApplication.getLinkToken(); + } + + @Post('exchange-token') + @ApiOperation({ summary: 'Exchange Plaid access token' }) + exchangeToken(@Body() itemDTO: PlaidItemDto) { + return this.plaidApplication.exchangeToken(itemDTO); + } +} diff --git a/packages/server/src/modules/BankingPlaid/BankingPlaid.module.ts b/packages/server/src/modules/BankingPlaid/BankingPlaid.module.ts index 77f11adca..072eca26a 100644 --- a/packages/server/src/modules/BankingPlaid/BankingPlaid.module.ts +++ b/packages/server/src/modules/BankingPlaid/BankingPlaid.module.ts @@ -15,6 +15,7 @@ import { PlaidItemService } from './command/PlaidItem'; import { TenancyContext } from '../Tenancy/TenancyContext.service'; import { InjectSystemModel } from '../System/SystemModels/SystemModels.module'; import { SystemPlaidItem } from './models/SystemPlaidItem'; +import { BankingPlaidController } from './BankingPlaid.controller'; const models = [RegisterTenancyModel(PlaidItem)]; @@ -38,5 +39,6 @@ const models = [RegisterTenancyModel(PlaidItem)]; TenancyContext, ], exports: [...models], + controllers: [BankingPlaidController] }) export class BankingPlaidModule {} diff --git a/packages/server/src/modules/BankingPlaid/PlaidApplication.ts b/packages/server/src/modules/BankingPlaid/PlaidApplication.ts index 77be991a2..a2c945ff8 100644 --- a/packages/server/src/modules/BankingPlaid/PlaidApplication.ts +++ b/packages/server/src/modules/BankingPlaid/PlaidApplication.ts @@ -3,6 +3,7 @@ import { PlaidItemService } from './command/PlaidItem'; import { PlaidWebooks } from './command/PlaidWebhooks'; import { Injectable } from '@nestjs/common'; import { PlaidItemDTO } from './types/BankingPlaid.types'; +import { PlaidItemDto } from './dtos/PlaidItem.dto'; @Injectable() export class PlaidApplication { @@ -25,7 +26,7 @@ export class PlaidApplication { * @param {PlaidItemDTO} itemDTO * @returns */ - public exchangeToken(itemDTO: PlaidItemDTO): Promise { + public exchangeToken(itemDTO: PlaidItemDto): Promise { return this.plaidItemService.item(itemDTO); } diff --git a/packages/server/src/modules/BankingPlaid/command/PlaidItem.ts b/packages/server/src/modules/BankingPlaid/command/PlaidItem.ts index e500f6fd2..122a85e63 100644 --- a/packages/server/src/modules/BankingPlaid/command/PlaidItem.ts +++ b/packages/server/src/modules/BankingPlaid/command/PlaidItem.ts @@ -6,11 +6,9 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { events } from '@/common/events/events'; import { SystemPlaidItem } from '../models/SystemPlaidItem'; import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service'; -import { - IPlaidItemCreatedEventPayload, - PlaidItemDTO, -} from '../types/BankingPlaid.types'; +import { IPlaidItemCreatedEventPayload } from '../types/BankingPlaid.types'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; +import { PlaidItemDto } from '../dtos/PlaidItem.dto'; @Injectable() export class PlaidItemService { @@ -33,10 +31,10 @@ export class PlaidItemService { /** * Exchanges the public token to get access token and item id and then creates * a new Plaid item. - * @param {PlaidItemDTO} itemDTO - Plaid item data transfer object. + * @param {PlaidItemDto} itemDTO - Plaid item data transfer object. * @returns {Promise} */ - public async item(itemDTO: PlaidItemDTO): Promise { + public async item(itemDTO: PlaidItemDto): Promise { const { publicToken, institutionId } = itemDTO; const tenant = await this.tenancyContext.getTenant(); diff --git a/packages/server/src/modules/BankingPlaid/command/PlaidUpdateTransactions.ts b/packages/server/src/modules/BankingPlaid/command/PlaidUpdateTransactions.ts index 3d7658af0..641126617 100644 --- a/packages/server/src/modules/BankingPlaid/command/PlaidUpdateTransactions.ts +++ b/packages/server/src/modules/BankingPlaid/command/PlaidUpdateTransactions.ts @@ -15,6 +15,13 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; @Injectable() export class PlaidUpdateTransactions { + /** + * Constructor method. + * @param {PlaidSyncDb} plaidSync - Plaid sync service. + * @param {UnitOfWork} uow - Unit of work. + * @param {TenantModelProxy} plaidItemModel - Plaid item model. + * @param {PlaidApi} plaidClient - Plaid client. + */ constructor( private readonly plaidSync: PlaidSyncDb, private readonly uow: UnitOfWork, @@ -28,8 +35,7 @@ export class PlaidUpdateTransactions { /** * Handles sync the Plaid item to Bigcaptial under UOW. - * @param {number} tenantId - Tenant id. - * @param {number} plaidItemId - Plaid item id. + * @param {string} plaidItemId - Plaid item id. * @returns {Promise<{ addedCount: number; modifiedCount: number; removedCount: number; }>} */ public async updateTransactions(plaidItemId: string) { @@ -44,9 +50,9 @@ export class PlaidUpdateTransactions { * - New bank accounts. * - Last accounts feeds updated at. * - Turn on the accounts feed flag. - * @param {number} tenantId - Tenant ID. * @param {string} plaidItemId - The Plaid ID for the item. - * @returns {Promise<{ addedCount: number; modifiedCount: number; removedCount: number; }>} + * @param {Knex.Transaction} trx - Knex transaction. + * @returns {Promise<{ addedCount: number; modifiedCount: number; removedCount: number; }>} */ public async updateTransactionsWork( plaidItemId: string, diff --git a/packages/server/src/modules/BankingPlaid/dtos/PlaidItem.dto.ts b/packages/server/src/modules/BankingPlaid/dtos/PlaidItem.dto.ts new file mode 100644 index 000000000..6935f91c7 --- /dev/null +++ b/packages/server/src/modules/BankingPlaid/dtos/PlaidItem.dto.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty, IsString } from 'class-validator'; + +export class PlaidItemDto { + @IsString() + @IsNotEmpty() + publicToken: string; + + @IsString() + @IsNotEmpty() + institutionId: string; +} diff --git a/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.controller.ts b/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.controller.ts index 6c307b41a..c6484f9d6 100644 --- a/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.controller.ts +++ b/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.controller.ts @@ -1,5 +1,5 @@ import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { Body, Controller, Delete, Param, Post } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common'; import { ICreditNoteRefundDTO } from '../CreditNotes/types/CreditNotes.types'; import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service'; import { RefundCreditNote } from './models/RefundCreditNote'; @@ -12,6 +12,14 @@ export class CreditNoteRefundsController { private readonly creditNotesRefundsApplication: CreditNotesRefundsApplication, ) {} + @Get(':creditNoteId/refunds') + @ApiOperation({ summary: 'Retrieve the credit note graph.' }) + getCreditNoteRefunds(@Param('creditNoteId') creditNoteId: number) { + return this.creditNotesRefundsApplication.getCreditNoteRefunds( + creditNoteId, + ); + } + /** * Create a refund credit note. * @param {number} creditNoteId - The credit note ID. diff --git a/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.module.ts b/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.module.ts index f09a95b65..9fe7c7bdb 100644 --- a/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.module.ts +++ b/packages/server/src/modules/CreditNoteRefunds/CreditNoteRefunds.module.ts @@ -6,6 +6,7 @@ import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditN import { CreditNotesRefundsApplication } from './CreditNotesRefundsApplication.service'; import { CreditNoteRefundsController } from './CreditNoteRefunds.controller'; import { CreditNotesModule } from '../CreditNotes/CreditNotes.module'; +import { GetCreditNoteRefundsService } from './queries/GetCreditNoteRefunds.service'; @Module({ imports: [forwardRef(() => CreditNotesModule)], @@ -15,10 +16,9 @@ import { CreditNotesModule } from '../CreditNotes/CreditNotes.module'; RefundCreditNoteService, RefundSyncCreditNoteBalanceService, CreditNotesRefundsApplication, + GetCreditNoteRefundsService, ], - exports: [ - RefundSyncCreditNoteBalanceService - ], + exports: [RefundSyncCreditNoteBalanceService], controllers: [CreditNoteRefundsController], }) export class CreditNoteRefundsModule {} diff --git a/packages/server/src/modules/CreditNoteRefunds/CreditNotesRefundsApplication.service.ts b/packages/server/src/modules/CreditNoteRefunds/CreditNotesRefundsApplication.service.ts index 40c8917ca..d7c02a933 100644 --- a/packages/server/src/modules/CreditNoteRefunds/CreditNotesRefundsApplication.service.ts +++ b/packages/server/src/modules/CreditNoteRefunds/CreditNotesRefundsApplication.service.ts @@ -5,16 +5,27 @@ import { DeleteRefundCreditNoteService } from './commands/DeleteRefundCreditNote import { RefundCreditNoteService } from './commands/RefundCreditNote.service'; import { RefundSyncCreditNoteBalanceService } from './commands/RefundSyncCreditNoteBalance'; import { CreditNoteRefundDto } from './dto/CreditNoteRefund.dto'; +import { GetCreditNoteRefundsService } from './queries/GetCreditNoteRefunds.service'; @Injectable() export class CreditNotesRefundsApplication { constructor( private readonly createRefundCreditNoteService: CreateRefundCreditNoteService, private readonly deleteRefundCreditNoteService: DeleteRefundCreditNoteService, + private readonly getCreditNoteRefundsService: GetCreditNoteRefundsService, private readonly refundCreditNoteService: RefundCreditNoteService, private readonly refundSyncCreditNoteBalanceService: RefundSyncCreditNoteBalanceService, ) {} + /** + * Retrieve the credit note graph. + * @param {number} creditNoteId - Credit note id. + * @returns {Promise} + */ + public getCreditNoteRefunds(creditNoteId: number) { + return this.getCreditNoteRefundsService.getCreditNoteRefunds(creditNoteId); + } + /** * Create a refund credit note. * @param {number} creditNoteId - The credit note ID. diff --git a/packages/server/src/modules/CreditNoteRefunds/queries/GetCreditNoteRefunds.service.ts b/packages/server/src/modules/CreditNoteRefunds/queries/GetCreditNoteRefunds.service.ts index fd60b4366..b84767793 100644 --- a/packages/server/src/modules/CreditNoteRefunds/queries/GetCreditNoteRefunds.service.ts +++ b/packages/server/src/modules/CreditNoteRefunds/queries/GetCreditNoteRefunds.service.ts @@ -6,7 +6,7 @@ import { IRefundCreditNotePOJO } from '../types/CreditNoteRefunds.types'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; @Injectable() -export class ListCreditNoteRefunds { +export class GetCreditNoteRefundsService { constructor( private readonly transformer: TransformerInjectable, @@ -18,7 +18,7 @@ export class ListCreditNoteRefunds { /** * Retrieve the credit note graph. - * @param {number} creditNoteId + * @param {number} creditNoteId - Credit note id. * @returns {Promise} */ public async getCreditNoteRefunds( diff --git a/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.controller.ts b/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.controller.ts new file mode 100644 index 000000000..e134cbf1f --- /dev/null +++ b/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.controller.ts @@ -0,0 +1,39 @@ +import { Body, Controller, Get, Param, Post } from '@nestjs/common'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { GetCreditNoteAssociatedAppliedInvoices } from './queries/GetCreditNoteAssociatedAppliedInvoices.service'; + +@Controller('credit-notes') +@ApiTags('credit-notes-apply-invoice') +export class CreditNotesApplyInvoiceController { + constructor( + private readonly getCreditNoteAssociatedAppliedInvoicesService: GetCreditNoteAssociatedAppliedInvoices, + ) {} + + @Get(':creditNoteId/applied-invoices') + @ApiOperation({ summary: 'Applied credit note to invoices' }) + @ApiResponse({ + status: 200, + description: 'Credit note successfully applied to invoices', + }) + @ApiResponse({ status: 404, description: 'Credit note not found' }) + @ApiResponse({ status: 400, description: 'Invalid input data' }) + appliedCreditNoteToInvoices(@Param('creditNoteId') creditNoteId: number) { + return this.getCreditNoteAssociatedAppliedInvoicesService.getCreditAssociatedAppliedInvoices( + creditNoteId, + ); + } + + @Post(':creditNoteId/apply-invoices') + @ApiOperation({ summary: 'Apply credit note to invoices' }) + @ApiResponse({ + status: 200, + description: 'Credit note successfully applied to invoices', + }) + @ApiResponse({ status: 404, description: 'Credit note not found' }) + @ApiResponse({ status: 400, description: 'Invalid input data' }) + applyCreditNoteToInvoices(@Param('creditNoteId') creditNoteId: number) { + return this.getCreditNoteAssociatedAppliedInvoicesService.getCreditAssociatedAppliedInvoices( + creditNoteId, + ); + } +} diff --git a/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.module.ts b/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.module.ts index 65d363028..7998e3e63 100644 --- a/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.module.ts +++ b/packages/server/src/modules/CreditNotesApplyInvoice/CreditNotesApplyInvoice.module.ts @@ -8,6 +8,7 @@ import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.modu import { CreditNotesModule } from '../CreditNotes/CreditNotes.module'; import { GetCreditNoteAssociatedAppliedInvoices } from './queries/GetCreditNoteAssociatedAppliedInvoices.service'; import { GetCreditNoteAssociatedInvoicesToApply } from './queries/GetCreditNoteAssociatedInvoicesToApply.service'; +import { CreditNotesApplyInvoiceController } from './CreditNotesApplyInvoice.controller'; @Module({ providers: [ @@ -16,12 +17,11 @@ import { GetCreditNoteAssociatedInvoicesToApply } from './queries/GetCreditNoteA CreditNoteApplyToInvoices, CreditNoteApplySyncInvoicesCreditedAmount, CreditNoteApplySyncCredit, - // GetCreditNoteAssociatedAppliedInvoices, - // GetCreditNoteAssociatedInvoicesToApply - ], - exports: [ - DeleteCustomerLinkedCreditNoteService, + GetCreditNoteAssociatedAppliedInvoices, + GetCreditNoteAssociatedInvoicesToApply, ], + exports: [DeleteCustomerLinkedCreditNoteService], imports: [PaymentsReceivedModule, forwardRef(() => CreditNotesModule)], + controllers: [CreditNotesApplyInvoiceController], }) export class CreditNotesApplyInvoiceModule {} diff --git a/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedAppliedInvoices.service.ts b/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedAppliedInvoices.service.ts index 4d0af7722..32639282b 100644 --- a/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedAppliedInvoices.service.ts +++ b/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedAppliedInvoices.service.ts @@ -7,9 +7,16 @@ import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; @Injectable() export class GetCreditNoteAssociatedAppliedInvoices { + /** + * @param {TransformerInjectable} transformer - The transformer service. + * @param {TenantModelProxy} creditNoteAppliedInvoiceModel - The credit note applied invoice model. + * @param {TenantModelProxy} creditNoteModel - The credit note model. + */ constructor( private readonly transformer: TransformerInjectable, - private readonly creditNoteAppliedInvoiceModel: typeof CreditNoteAppliedInvoice, + + @Inject(CreditNoteAppliedInvoice.name) + private readonly creditNoteAppliedInvoiceModel: TenantModelProxy, @Inject(CreditNote.name) private readonly creditNoteModel: TenantModelProxy, @@ -29,7 +36,7 @@ export class GetCreditNoteAssociatedAppliedInvoices { .findById(creditNoteId) .throwIfNotFound(); - const appliedToInvoices = await this.creditNoteAppliedInvoiceModel + const appliedToInvoices = await this.creditNoteAppliedInvoiceModel() .query() .where('credit_note_id', creditNoteId) .withGraphFetched('saleInvoice') diff --git a/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedInvoicesToApply.service.ts b/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedInvoicesToApply.service.ts index 1eb03a838..da412de19 100644 --- a/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedInvoicesToApply.service.ts +++ b/packages/server/src/modules/CreditNotesApplyInvoice/queries/GetCreditNoteAssociatedInvoicesToApply.service.ts @@ -10,7 +10,7 @@ export class GetCreditNoteAssociatedInvoicesToApply { /** * @param {TransformerInjectable} transformer - Transformer service. * @param {GetCreditNote} getCreditNote - Get credit note service. - * @param {typeof SaleInvoice} saleInvoiceModel - Sale invoice model. + * @param {TenantModelProxy} saleInvoiceModel - Sale invoice model. */ constructor( private transformer: TransformerInjectable, diff --git a/packages/server/src/modules/Features/FeaturesConfigure.ts b/packages/server/src/modules/Features/FeaturesConfigure.ts index fd8d430d5..faa8f9d65 100644 --- a/packages/server/src/modules/Features/FeaturesConfigure.ts +++ b/packages/server/src/modules/Features/FeaturesConfigure.ts @@ -24,7 +24,7 @@ export class FeaturesConfigure { }, { name: Features.BankSyncing, - defaultValue: this.configService.get('bankSync.enabled') ?? false, + defaultValue: this.configService.get('bankfeed.enabled') ?? false, }, ]; } diff --git a/packages/server/src/modules/ItemCategories/commands/EditItemCategory.service.ts b/packages/server/src/modules/ItemCategories/commands/EditItemCategory.service.ts index ac8c5e2c2..02da1e723 100644 --- a/packages/server/src/modules/ItemCategories/commands/EditItemCategory.service.ts +++ b/packages/server/src/modules/ItemCategories/commands/EditItemCategory.service.ts @@ -74,11 +74,10 @@ export class EditItemCategoryService { ); // Creates item category under unit-of-work evnirement. return this.uow.withTransaction(async (trx: Knex.Transaction) => { - // - const itemCategory = await ItemCategory.query().patchAndFetchById( - itemCategoryId, - { ...itemCategoryObj }, - ); + const itemCategory = await this.itemCategoryModel() + .query(trx) + .patchAndFetchById(itemCategoryId, { ...itemCategoryObj }); + // Triggers `onItemCategoryEdited` event. await this.eventEmitter.emitAsync(events.itemCategory.onEdited, { oldItemCategory, diff --git a/packages/server/src/modules/ItemCategories/dtos/ItemCategory.dto.ts b/packages/server/src/modules/ItemCategories/dtos/ItemCategory.dto.ts index 83878d71b..fcea6f0cf 100644 --- a/packages/server/src/modules/ItemCategories/dtos/ItemCategory.dto.ts +++ b/packages/server/src/modules/ItemCategories/dtos/ItemCategory.dto.ts @@ -1,6 +1,7 @@ +import { IsOptional, ToNumber } from '@/common/decorators/Validators'; import { ApiProperty } from '@nestjs/swagger'; import { IsNumber } from 'class-validator'; -import { IsOptional, IsString } from 'class-validator'; +import { IsString } from 'class-validator'; import { IsNotEmpty } from 'class-validator'; class CommandItemCategoryDto { @@ -17,16 +18,19 @@ class CommandItemCategoryDto { }) description?: string; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ example: 1, description: 'The cost account ID' }) costAccountId?: number; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ example: 1, description: 'The sell account ID' }) sellAccountId?: number; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ example: 1, description: 'The inventory account ID' }) diff --git a/packages/server/src/modules/PaymentReceived/PaymentReceived.application.ts b/packages/server/src/modules/PaymentReceived/PaymentReceived.application.ts index a706837b2..943d419d6 100644 --- a/packages/server/src/modules/PaymentReceived/PaymentReceived.application.ts +++ b/packages/server/src/modules/PaymentReceived/PaymentReceived.application.ts @@ -18,6 +18,7 @@ import { CreatePaymentReceivedDto, EditPaymentReceivedDto, } from './dtos/PaymentReceived.dto'; +import { PaymentsReceivedPagesService } from './queries/PaymentsReceivedPages.service'; @Injectable() export class PaymentReceivesApplication { @@ -31,6 +32,7 @@ export class PaymentReceivesApplication { private sendPaymentReceiveMailNotification: SendPaymentReceiveMailNotification, private getPaymentReceivePdfService: GetPaymentReceivedPdfService, private getPaymentReceivedStateService: GetPaymentReceivedStateService, + private paymentsReceivedPagesService: PaymentsReceivedPagesService, ) {} /** @@ -147,4 +149,14 @@ export class PaymentReceivesApplication { public getPaymentReceivedState() { return this.getPaymentReceivedStateService.getPaymentReceivedState(); } + + /** + * Retrieve the payment received edit page. + * @param {number} paymentReceiveId - Payment receive id. + */ + public getPaymentReceivedEditPage(paymentReceiveId: number) { + return this.paymentsReceivedPagesService.getPaymentReceiveEditPage( + paymentReceiveId, + ); + } } diff --git a/packages/server/src/modules/PaymentReceived/PaymentsReceived.controller.ts b/packages/server/src/modules/PaymentReceived/PaymentsReceived.controller.ts index da2a404e9..0c44d1140 100644 --- a/packages/server/src/modules/PaymentReceived/PaymentsReceived.controller.ts +++ b/packages/server/src/modules/PaymentReceived/PaymentsReceived.controller.ts @@ -44,6 +44,20 @@ export class PaymentReceivesController { ); } + @Get(':id/edit-page') + @ApiResponse({ + status: 200, + description: + 'The payment received edit page has been successfully retrieved.', + }) + public getPaymentReceiveEditPage( + @Param('id', ParseIntPipe) paymentReceiveId: number, + ) { + return this.paymentReceivesApplication.getPaymentReceivedEditPage( + paymentReceiveId, + ); + } + @Get(':id/mail') @ApiResponse({ status: 200, diff --git a/packages/server/src/modules/PaymentReceived/PaymentsReceived.module.ts b/packages/server/src/modules/PaymentReceived/PaymentsReceived.module.ts index 64b0343f4..4d611bcf2 100644 --- a/packages/server/src/modules/PaymentReceived/PaymentsReceived.module.ts +++ b/packages/server/src/modules/PaymentReceived/PaymentsReceived.module.ts @@ -36,6 +36,7 @@ import { SendPaymentReceivedMailProcessor } from './processors/PaymentReceivedMa import { SEND_PAYMENT_RECEIVED_MAIL_QUEUE } from './constants'; import { PaymentsReceivedExportable } from './commands/PaymentsReceivedExportable'; import { PaymentsReceivedImportable } from './commands/PaymentsReceivedImportable'; +import { PaymentsReceivedPagesService } from './queries/PaymentsReceivedPages.service'; @Module({ controllers: [PaymentReceivesController], @@ -63,6 +64,7 @@ import { PaymentsReceivedImportable } from './commands/PaymentsReceivedImportabl SendPaymentReceivedMailProcessor, PaymentsReceivedExportable, PaymentsReceivedImportable, + PaymentsReceivedPagesService ], exports: [ PaymentReceivesApplication, diff --git a/packages/server/src/modules/PaymentReceived/queries/PaymentsReceivedPages.service.ts b/packages/server/src/modules/PaymentReceived/queries/PaymentsReceivedPages.service.ts index 70a1532a7..6eeb2536a 100644 --- a/packages/server/src/modules/PaymentReceived/queries/PaymentsReceivedPages.service.ts +++ b/packages/server/src/modules/PaymentReceived/queries/PaymentsReceivedPages.service.ts @@ -41,11 +41,10 @@ export class PaymentsReceivedPagesService { /** * Retrieve payment receive new page receivable entries. - * @param {number} tenantId - Tenant id. * @param {number} vendorId - Vendor id. * @return {IPaymentReceivePageEntry[]} */ - public async getNewPageEntries(tenantId: number, customerId: number) { + public async getNewPageEntries(customerId: number) { // Retrieve due invoices. const entries = await this.saleInvoice() .query() @@ -62,10 +61,7 @@ export class PaymentsReceivedPagesService { * @param {number} tenantId - Tenant id. * @param {Integer} paymentReceiveId - Payment receive id. */ - public async getPaymentReceiveEditPage( - tenantId: number, - paymentReceiveId: number, - ): Promise<{ + public async getPaymentReceiveEditPage(paymentReceiveId: number): Promise<{ paymentReceive: Omit; entries: IPaymentReceivePageEntry[]; }> { diff --git a/packages/server/src/modules/SaleEstimates/SaleEstimates.controller.ts b/packages/server/src/modules/SaleEstimates/SaleEstimates.controller.ts index b1330df62..e2a1b69f4 100644 --- a/packages/server/src/modules/SaleEstimates/SaleEstimates.controller.ts +++ b/packages/server/src/modules/SaleEstimates/SaleEstimates.controller.ts @@ -232,7 +232,7 @@ export class SaleEstimatesController { public async getSaleEstimate( @Param('id', ParseIntPipe) estimateId: number, @Headers('accept') acceptHeader: string, - @Res() res: Response, + @Res({ passthrough: true }) res: Response, ) { if (acceptHeader.includes(AcceptType.ApplicationPdf)) { const pdfContent = diff --git a/packages/server/src/modules/SaleReceipts/SaleReceipts.controller.ts b/packages/server/src/modules/SaleReceipts/SaleReceipts.controller.ts index 62c85882e..aeb53c5a5 100644 --- a/packages/server/src/modules/SaleReceipts/SaleReceipts.controller.ts +++ b/packages/server/src/modules/SaleReceipts/SaleReceipts.controller.ts @@ -46,6 +46,12 @@ export class SaleReceiptsController { return this.saleReceiptApplication.getSaleReceiptMail(id); } + @Get('state') + @ApiOperation({ summary: 'Retrieves the sale receipt state.' }) + getSaleReceiptState() { + return this.saleReceiptApplication.getSaleReceiptState(); + } + @Get(':id/mail') @HttpCode(200) @ApiOperation({ summary: 'Retrieves the sale receipt mail.' }) @@ -86,7 +92,7 @@ export class SaleReceiptsController { required: true, type: Number, description: 'The sale receipt id', -}) + }) async getSaleReceipt( @Param('id', ParseIntPipe) id: number, @Headers('accept') acceptHeader: string, @@ -135,10 +141,4 @@ export class SaleReceiptsController { closeSaleReceipt(@Param('id', ParseIntPipe) id: number) { return this.saleReceiptApplication.closeSaleReceipt(id); } - - @Get('state') - @ApiOperation({ summary: 'Retrieves the sale receipt state.' }) - getSaleReceiptState() { - return this.saleReceiptApplication.getSaleReceiptState(); - } } diff --git a/packages/server/static/imports/.gitkeep b/packages/server/static/imports/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/server/static/pdf/.gitkeep b/packages/server/static/pdf/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/webapp/src/hooks/query/creditNote.tsx b/packages/webapp/src/hooks/query/creditNote.tsx index 9946db82b..19fa99c06 100644 --- a/packages/webapp/src/hooks/query/creditNote.tsx +++ b/packages/webapp/src/hooks/query/creditNote.tsx @@ -150,7 +150,7 @@ export function useCreditNote(id, props, requestProps) { [t.CREDIT_NOTE, id], { method: 'get', url: `credit-notes/${id}`, ...requestProps }, { - select: (res) => res.data.credit_note, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -176,7 +176,7 @@ export function useCreateRefundCreditNote(props) { return useMutation( ([id, values]) => - apiRequest.post(`credit-notes/${id}/refund`, values), + apiRequest.post(`credit-notes/${id}/refunds`, values), { onSuccess: (res, [id, values]) => { // Common invalidate queries. @@ -220,9 +220,9 @@ export function useDeleteRefundCreditNote(props) { export function useRefundCreditNote(id, props, requestProps) { return useRequestQuery( [t.REFUND_CREDIT_NOTE, id], - { method: 'get', url: `credit-notes/${id}/refund`, ...requestProps }, + { method: 'get', url: `credit-notes/${id}/refunds`, ...requestProps }, { - select: (res) => res.data.data, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -258,11 +258,11 @@ export function useReconcileCreditNote(id, props, requestProps) { [t.RECONCILE_CREDIT_NOTE, id], { method: 'get', - url: `credit-notes/${id}/apply-to-invoices`, + url: `credit-notes/${id}/applied-invoices`, ...requestProps, }, { - select: (res) => res.data.data, + select: (res) => res.data, defaultData: [], ...props, }, @@ -278,7 +278,7 @@ export function useCreateReconcileCreditNote(props) { return useMutation( ([id, values]) => - apiRequest.post(`credit-notes/${id}/apply-to-invoices`, values), + apiRequest.post(`credit-notes/${id}/apply-invoices`, values), { onSuccess: (res, [id, values]) => { // Common invalidate queries. @@ -304,7 +304,7 @@ export function useReconcileCreditNotes(id, props, requestProps) { ...requestProps, }, { - select: (res) => res.data.data, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -319,7 +319,7 @@ export function useDeleteReconcileCredit(props) { const apiRequest = useApiRequest(); return useMutation( - (id) => apiRequest.delete(`credit-notes/applied-to-invoices/${id}`), + (id) => apiRequest.delete(`credit-notes/applied-invoices/${id}`), { onSuccess: (res, id) => { // Common invalidate queries. @@ -343,7 +343,7 @@ export function useRefundCreditTransaction(id, props, requestProps) { [t.REFUND_CREDIT_NOTE_TRANSACTION, id], { method: 'get', url: `credit-notes/refunds/${id}`, ...requestProps }, { - select: (res) => res.data.refund_credit, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -370,7 +370,7 @@ export function useGetCreditNoteState( () => apiRequest .get('/credit-notes/state') - .then((res) => transformToCamelCase(res.data?.data)), + .then((res) => transformToCamelCase(res.data)), { ...options }, ); } diff --git a/packages/webapp/src/hooks/query/estimates.tsx b/packages/webapp/src/hooks/query/estimates.tsx index d0aac3639..7ed31e34a 100644 --- a/packages/webapp/src/hooks/query/estimates.tsx +++ b/packages/webapp/src/hooks/query/estimates.tsx @@ -150,7 +150,7 @@ export function useApproveEstimate(props) { const queryClient = useQueryClient(); const apiRequest = useApiRequest(); - return useMutation((id) => apiRequest.post(`sale-estimates/${id}/approve`), { + return useMutation((id) => apiRequest.put(`sale-estimates/${id}/approve`), { onSuccess: (res, id) => { // Common invalidate queries. commonInvalidateQueries(queryClient); @@ -169,7 +169,7 @@ export function useRejectEstimate(props) { const queryClient = useQueryClient(); const apiRequest = useApiRequest(); - return useMutation((id) => apiRequest.post(`sale-estimates/${id}/reject`), { + return useMutation((id) => apiRequest.put(`sale-estimates/${id}/reject`), { onSuccess: (res, id) => { // Common invalidate queries. commonInvalidateQueries(queryClient); @@ -240,7 +240,7 @@ export function useEstimateSMSDetail(estimateId, props, requestProps) { ...requestProps, }, { - select: (res) => res.data.data, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -321,7 +321,7 @@ export function useSaleEstimateMailState( return useQuery([t.SALE_ESTIMATE_MAIL_OPTIONS, estimateId], () => apiRequest .get(`sale-estimates/${estimateId}/mail/state`) - .then((res) => transformToCamelCase(res.data.data)), + .then((res) => transformToCamelCase(res.data)), ); } @@ -339,7 +339,7 @@ export function useGetSaleEstimatesState( () => apiRequest .get('/sale-estimates/state') - .then((res) => transformToCamelCase(res.data?.data)), + .then((res) => transformToCamelCase(res.data)), { ...options }, ); } diff --git a/packages/webapp/src/hooks/query/itemsCategories.tsx b/packages/webapp/src/hooks/query/itemsCategories.tsx index 209d0e6ee..8bb86cea0 100644 --- a/packages/webapp/src/hooks/query/itemsCategories.tsx +++ b/packages/webapp/src/hooks/query/itemsCategories.tsx @@ -36,7 +36,7 @@ export function useEditItemCategory(props) { const apiRequest = useApiRequest(); return useMutation( - ([id, values]) => apiRequest.post(`item-categories/${id}`, values), + ([id, values]) => apiRequest.put(`item-categories/${id}`, values), { onSuccess: (res, [id, values]) => { // Invalidate specific item category. diff --git a/packages/webapp/src/hooks/query/paymentReceives.tsx b/packages/webapp/src/hooks/query/paymentReceives.tsx index 88f022afa..a36295189 100644 --- a/packages/webapp/src/hooks/query/paymentReceives.tsx +++ b/packages/webapp/src/hooks/query/paymentReceives.tsx @@ -159,7 +159,7 @@ export function usePaymentReceive(id, props) { [t.PAYMENT_RECEIVE, id], { method: 'get', url: `payments-received/${id}` }, { - select: (res) => res.data.payment_receive, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -176,7 +176,7 @@ export function usePaymentReceiveEditPage(id, props) { { method: 'get', url: `payments-received/${id}/edit-page` }, { select: (res) => ({ - paymentReceive: res.data.payment_receive, + paymentReceive: res.data, entries: res.data.entries, }), defaultData: { @@ -231,7 +231,7 @@ export function usePaymentReceiveSMSDetail( ...requestProps, }, { - select: (res) => res.data.data, + select: (res) => res.data, defaultData: {}, ...props, }, @@ -336,7 +336,7 @@ export function usePaymentReceivedMailState( () => apiRequest .get(`payments-received/${paymentReceiveId}/mail`) - .then((res) => transformToCamelCase(res.data?.data)), + .then((res) => transformToCamelCase(res.data)), ); } @@ -360,7 +360,7 @@ export function usePaymentReceivedState( () => apiRequest .get('/payments-received/state') - .then((res) => transformToCamelCase(res.data?.data)), + .then((res) => transformToCamelCase(res.data)), { ...options, },