// This file is auto-generated by OpenAPI Generator (https://openapi-generator.tech). // it lists all the endpoints of the Mambu API and maps them to methods in the MambuService. // The MambuService is a wrapper around the Mambu SDK that provides methods to call the Mambu API. import { Controller, Get, Post, Delete, Param, Body, Query, HttpException, HttpStatus, Logger, BadRequestException, } from '@nestjs/common'; import { AxiosError } from 'axios'; import { MambuService } from './mambu.service'; import type { Client } from '../mambu-sdk/clients/models'; import type { ClientSearchCriteria } from '../mambu-sdk/clients/models'; import type { LoanAccountSearchCriteria } from '../mambu-sdk/loans/models'; import type { DepositAccountSearchCriteria } from '../mambu-sdk/deposits/models'; import type { GroupSearchCriteria } from '../mambu-sdk/groups/models'; import type { LoanTransactionSearchCriteria } from '../mambu-sdk/loans-transactions/models'; import type { DepositTransactionSearchCriteria } from '../mambu-sdk/deposits-transactions/models'; const logger = new Logger('MambuController'); function getErrorMessage(error: unknown, defaultMsg: string): string { if (error instanceof AxiosError) { logger.error( `${error.code} ${error.message} [${error.response?.status}] ${JSON.stringify(error.response?.data)}`, ); return String(error.response?.data || defaultMsg); } logger.error(defaultMsg, error instanceof Error ? error.stack : undefined); return defaultMsg; } function getErrorStatus(error: unknown): number { if (error instanceof AxiosError) { return error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR; } return HttpStatus.INTERNAL_SERVER_ERROR; } function validateSearchCriteria(criteria: { filterCriteria?: unknown[]; }): void { if ( !criteria || !criteria.filterCriteria || !Array.isArray(criteria.filterCriteria) ) { throw new BadRequestException( 'Request body must include a filterCriteria array', ); } } @Controller('mambu') export class MambuController { constructor(private readonly mambuService: MambuService) {} // ============ CLIENTS ============ @Get('clients') async getClients( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.clients.getAll( offset, limit, 'OFF', // paginationDetails 'BASIC', // detailsLevel ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch clients'), getErrorStatus(error), ); } } @Get('clients/:clientId') async getClient(@Param('clientId') clientId: string) { try { const response = await this.mambuService.clients.getById( clientId, 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch client'), getErrorStatus(error), ); } } @Post('clients') async createClient(@Body() client: Client) { try { const response = await this.mambuService.clients.create(client); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to create client'), getErrorStatus(error), ); } } @Post('clients:search') async searchClients( @Body() criteria: ClientSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.clients.search( criteria, offset, limit, 'OFF', 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search clients'), getErrorStatus(error), ); } } // ============ BRANCHES ============ @Get('branches') async getBranches( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.branches.getAll( offset, limit, 'OFF', 'BASIC', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch branches'), getErrorStatus(error), ); } } @Get('branches/:branchId') async getBranch(@Param('branchId') branchId: string) { try { const response = await this.mambuService.branches.getById( branchId, 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch branch'), getErrorStatus(error), ); } } // ============ LOAN PRODUCTS ============ @Get('loan-products') async getLoanProducts( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.loanProducts.getAll( offset, limit, 'OFF', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch loan products'), getErrorStatus(error), ); } } // ============ DEPOSIT PRODUCTS ============ @Get('deposit-products') async getDepositProducts( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.depositProducts.getAll( offset, limit, 'OFF', 'BASIC', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch deposit products'), getErrorStatus(error), ); } } // ============ LOANS ============ @Get('loans') async getLoans( @Query('offset') offset?: number, @Query('limit') limit?: number, @Query('accountHolderType') accountHolderType: 'CLIENT' | 'GROUP' = 'CLIENT', ) { try { const response = await this.mambuService.loans.getAll( offset, limit, 'OFF', 'BASIC', undefined, // creditOfficerUsername undefined, // branchId undefined, // centreId undefined, // accountState accountHolderType, ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch loans'), getErrorStatus(error), ); } } @Get('loans/:loanId') async getLoan(@Param('loanId') loanId: string) { try { const response = await this.mambuService.loans.getById(loanId, 'FULL'); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch loan'), getErrorStatus(error), ); } } @Post('loans:search') async searchLoans( @Body() criteria: LoanAccountSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.loansSearch.search( criteria, offset, limit, 'OFF', undefined, // cursor 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search loans'), getErrorStatus(error), ); } } // ============ DEPOSITS ============ @Get('deposits') async getDeposits( @Query('offset') offset?: number, @Query('limit') limit?: number, @Query('accountHolderType') accountHolderType: 'CLIENT' | 'GROUP' = 'CLIENT', ) { try { const response = await this.mambuService.deposits.getAll( offset, limit, 'OFF', 'BASIC', undefined, // creditOfficerUsername undefined, // branchId undefined, // centreId undefined, // accountState accountHolderType, ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch deposits'), getErrorStatus(error), ); } } @Get('deposits/:depositId') async getDeposit(@Param('depositId') depositId: string) { try { const response = await this.mambuService.deposits.getById( depositId, 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch deposit'), getErrorStatus(error), ); } } @Post('deposits:search') async searchDeposits( @Body() criteria: DepositAccountSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.deposits.search( criteria, offset, limit, 'OFF', undefined, // cursor 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search deposits'), getErrorStatus(error), ); } } // ============ USERS ============ @Get('users') async getUsers( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.users.getAll( offset, limit, 'OFF', 'BASIC', undefined, // branchId undefined, // branchIdType ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch users'), getErrorStatus(error), ); } } // ============ GROUPS ============ @Get('groups') async getGroups( @Query('offset') offset?: number, @Query('limit') limit?: number, ) { try { const response = await this.mambuService.groups.getAll( offset, limit, 'OFF', 'BASIC', undefined, // branchId undefined, // centreId undefined, // creditOfficerUsername ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch groups'), getErrorStatus(error), ); } } // ============ SEARCH: GROUPS ============ @Post('groups:search') async searchGroups( @Body() criteria: GroupSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.groups.search( criteria, offset, limit, 'OFF', 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search groups'), getErrorStatus(error), ); } } // ============ SEARCH: LOAN TRANSACTIONS ============ @Post('loan-transactions:search') async searchLoanTransactions( @Body() criteria: LoanTransactionSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.loanTransactions.search( criteria, offset, limit, 'OFF', undefined, // cursor 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search loan transactions'), getErrorStatus(error), ); } } // ============ SEARCH: DEPOSIT TRANSACTIONS ============ @Post('deposit-transactions:search') async searchDepositTransactions( @Body() criteria: DepositTransactionSearchCriteria, @Query('offset') offset?: number, @Query('limit') limit?: number, ) { validateSearchCriteria(criteria); try { const response = await this.mambuService.depositTransactions.search( criteria, offset, limit, 'OFF', undefined, // cursor 'FULL', ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to search deposit transactions'), getErrorStatus(error), ); } } // ============ CLIENT DOCUMENTS ============ @Get('clients/:clientId/documents') async getClientDocuments(@Param('clientId') clientId: string) { try { const response = await this.mambuService.clientDocuments.getDocumentsByClientId( clientId, ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch client documents'), getErrorStatus(error), ); } } @Get('clients/documents/:documentId') async getClientDocument(@Param('documentId') documentId: string) { try { const response = await this.mambuService.clientDocuments.getClientDocumentById( documentId, ); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to fetch client document'), getErrorStatus(error), ); } } @Delete('documents/:documentId') async deleteDocument(@Param('documentId') documentId: string) { try { const response = await this.mambuService.documents.deleteDocumentById(documentId); return response.data; } catch (error) { throw new HttpException( getErrorMessage(error, 'Failed to delete document'), getErrorStatus(error), ); } } }