diff --git a/src/transaction/entities/callback-partner.entity.ts b/src/transaction/entities/callback-partner.entity.ts new file mode 100644 index 0000000..f7c03b4 --- /dev/null +++ b/src/transaction/entities/callback-partner.entity.ts @@ -0,0 +1,18 @@ +import { Column, Entity, ManyToOne, OneToMany } from 'typeorm'; +import { BaseModel } from '../../config/basemodel.entity'; +import { statusTransaction, typeTransaction } from '../../helper/enum-list'; +import { ProductHistoryPrice } from '../../product/entities/product-history-price.entity'; +import { UserDetail } from '../../users/entities/user_detail.entity'; +import { TransactionJournal } from './transaction-journal.entity'; + +@Entity() +export class CallbackPartner extends BaseModel { + @Column() + trx_id: string; + + @Column() + partner_trx_id: string; + + @Column() + url: string; +} diff --git a/src/transaction/transaction.controller.ts b/src/transaction/transaction.controller.ts index 0ebaf40..8cac296 100644 --- a/src/transaction/transaction.controller.ts +++ b/src/transaction/transaction.controller.ts @@ -132,6 +132,40 @@ export class TransactionController { }; } + @Post('rollback-jurnal') + async rollbackJurnal(@Body() request, @Request() req) { + const data = await this.transactionService.rollbackJurnal(request.trxId); + return { + data, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + + @Get('resend-partner/success/:code') + async resendSuccess(@Request() req, @Param('code') code: string) { + const data = await this.transactionService.resendOrderToPartner(code, true); + return { + data, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + + @Get('resend-partner/failed/:code') + async resendFailed(@Request() req, @Param('code') code: string) { + const data = await this.transactionService.resendOrderToPartner( + code, + false, + ); + + return { + data, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + @Get('history') async getHistoryTransactionUser( @Query('page') page: number, diff --git a/src/transaction/transaction.module.ts b/src/transaction/transaction.module.ts index a384646..5e7c0ee 100644 --- a/src/transaction/transaction.module.ts +++ b/src/transaction/transaction.module.ts @@ -11,6 +11,7 @@ import { ProductModule } from '../product/product.module'; import { UsersModule } from 'src/users/users.module'; import { ConfigurableModule } from '../configurable/configurable.module'; import { CheckBillHistory } from './entities/check-bill-history.entity'; +import { CallbackPartner } from './entities/callback-partner.entity'; @Module({ imports: [ @@ -19,6 +20,7 @@ import { CheckBillHistory } from './entities/check-bill-history.entity'; TransactionJournal, Transactions, CheckBillHistory, + CallbackPartner, ]), ProductModule, ConfigurableModule, diff --git a/src/transaction/transaction.service.ts b/src/transaction/transaction.service.ts index a28fbfb..e33c081 100644 --- a/src/transaction/transaction.service.ts +++ b/src/transaction/transaction.service.ts @@ -3,7 +3,7 @@ import { DistributeTransactionDto } from './dto/distribute-transaction.dto'; import { OrderTransactionDto } from './dto/order-transaction.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { Transactions } from './entities/transactions.entity'; -import { Between, Connection, EntityNotFoundError, Repository } from 'typeorm'; +import { Between, Connection, EntityNotFoundError, In, Repository } from 'typeorm'; import { COA } from './entities/coa.entity'; import { TransactionJournal } from './entities/transaction-journal.entity'; import { CoaService } from './coa.service'; @@ -29,6 +29,7 @@ import { doTransaction } from '../helper/irs-api'; import { ProductHistoryPrice } from '../product/entities/product-history-price.entity'; import axios from 'axios'; import { CheckBillHistory } from './entities/check-bill-history.entity'; +import { CallbackPartner } from './entities/callback-partner.entity'; @Injectable() export class TransactionService { @@ -43,6 +44,8 @@ export class TransactionService { private coaRepository: Repository, @InjectRepository(CheckBillHistory) private checkBillHistoryRepository: Repository, + @InjectRepository(CallbackPartner) + private callbackPartnerRepository: Repository, private coaService: CoaService, private productService: ProductService, private productHistoryPriceService: ProductHistoryPriceService, @@ -1064,17 +1067,6 @@ export class TransactionService { relations: ['product_price'], }); - if (dataTransaction.status == statusTransaction.FAILED) { - return { - statusCode: HttpStatus.BAD_REQUEST, - message: 'failed to update, the transaction already failed', - }; - } else if (dataTransaction.status == statusTransaction.SUCCESS) { - return { - statusCode: HttpStatus.BAD_REQUEST, - message: 'failed to update, the transaction already success', - }; - } else { const dataMsg = callback.msg; const failedReason = dataMsg.split('.'); @@ -1085,29 +1077,29 @@ export class TransactionService { const userData = await this.userService.findExist(dataTransaction.user); const product_price = await this.productHistoryPriceService.findById( - dataTransaction.product_price.id, + dataTransaction.product_price.id, ); const product = await this.productService.findOneById( - product_price.product.id, + product_price.product.id, ); //GET COA const coaAccount = await this.coaService.findByUser( - userData.id, - coaType.WALLET, + userData.id, + coaType.WALLET, ); const coaInventory = await this.coaService.findByName( - `${coaType[coaType.INVENTORY]}-${product.supplier.code}`, + `${coaType[coaType.INVENTORY]}-${product.supplier.code}`, ); const coaCostOfSales = await this.coaService.findByName( - `${coaType[coaType.COST_OF_SALES]}-${product.supplier.code}`, + `${coaType[coaType.COST_OF_SALES]}-${product.supplier.code}`, ); const coaSales = await this.coaService.findByName( - `${coaType[coaType.SALES]}-SYSTEM`, + `${coaType[coaType.SALES]}-SYSTEM`, ); try { @@ -1146,23 +1138,16 @@ export class TransactionService { if (userData.partner) { const message = `Transaksi ${product.code} dengan tujuan ${dataTransaction.destination} telah gagal.`; this.callbackToPartner( - userData.id, - message, - dataTransaction.partner_trx_id, - dataTransaction.amount, - product.code, - dataTransaction.destination, - '-', - 'gagal', + userData.partner.id, + message, + dataTransaction.partner_trx_id, + dataTransaction.amount, + product.code, + dataTransaction.destination, + '-', + 'gagal', ); } - - return { - statusCode: HttpStatus.BAD_REQUEST, - message: 'failed to proccess', - }; - - } } async callbackOrderSuccess(supplier_trx_id: string, callback: any) { @@ -1173,21 +1158,15 @@ export class TransactionService { relations: ['product_price'], }); - - if (dataTransaction.status == statusTransaction.FAILED) { - return { - statusCode: HttpStatus.BAD_REQUEST, - message: 'failed to update, the transaction already failed', - }; - } else if (dataTransaction.status == statusTransaction.SUCCESS) { - return { - statusCode: HttpStatus.BAD_REQUEST, - message: 'failed to update, the transaction already success', - }; - } else { - dataTransaction.status = statusTransaction.SUCCESS; - dataTransaction.seri_number = callback['sn']; + if(callback['sn']){ + dataTransaction.seri_number = callback['sn']; + } else { + const response = callback['message']; + const responseBaru = response.split(' '); + dataTransaction.seri_number = + responseBaru[10].length > 1 ? responseBaru[10] : responseBaru[9]; + } dataTransaction.callback_json = callback; const userData = await this.userService.findExist(dataTransaction.user); @@ -1195,33 +1174,34 @@ export class TransactionService { let supervisorData = []; const product_price = await this.productHistoryPriceService.findById( - dataTransaction.product_price.id, + dataTransaction.product_price.id, ); const product = await this.productService.findOneById( - product_price.product.id, + product_price.product.id, ); let profit = product_price.mark_up_price; //GET COA const coaExpense = await this.coaService.findByName( - `${coaType[coaType.EXPENSE]}-SYSTEM`, + `${coaType[coaType.EXPENSE]}-SYSTEM`, ); - if (userData.partner != null) { + + if (userData.partner == null) { //GET SALES supervisorData = await this.calculateCommission( - supervisorData, - profit, - userData, + supervisorData, + profit, + userData, ); profit = supervisorData - .map((item) => { - return item.credit; - }) - .reduce((prev, curr) => { - return prev + curr; - }, 0); + .map((item) => { + return item.credit; + }) + .reduce((prev, curr) => { + return prev + curr; + }, 0); supervisorData = supervisorData.concat([ { @@ -1250,21 +1230,63 @@ export class TransactionService { if (userData.partner) { const message = `Transaksi ${product.code} dengan tujuan ${dataTransaction.destination} telah berhasil.`; this.callbackToPartner( - userData.id, - message, - dataTransaction.partner_trx_id, - dataTransaction.amount, - product.code, - dataTransaction.destination, - dataTransaction.seri_number, - 'berhasil', + userData.partner.id, + message, + dataTransaction.partner_trx_id, + dataTransaction.amount, + product.code, + dataTransaction.destination, + dataTransaction.seri_number, + 'berhasil', ); } - return { - statusCode: HttpStatus.OK, - message: 'success', - }; } + + async resendOrderToPartner(supplier_trx_id: string, status: boolean){ + const dataTransaction = await this.transactionRepository.findOne({ + where: { + supplier_trx_id: supplier_trx_id, + }, + relations: ['product_price'], + }); + + const userData = await this.userService.findExist(dataTransaction.user); + + const product_price = await this.productHistoryPriceService.findById( + dataTransaction.product_price.id, + ); + + const product = await this.productService.findOneById( + product_price.product.id, + ); + + if (status) { + const message = `Transaksi ${product.code} dengan tujuan ${dataTransaction.destination} telah berhasil.`; + await this.callbackToPartner( + userData.partner.id, + message, + dataTransaction.partner_trx_id, + dataTransaction.amount, + product.code, + dataTransaction.destination, + dataTransaction.seri_number, + 'berhasil', + ); + } else { + const message = `Transaksi ${product.code} dengan tujuan ${dataTransaction.destination} telah gagal.`; + this.callbackToPartner( + userData.partner.id, + message, + dataTransaction.partner_trx_id, + dataTransaction.amount, + product.code, + dataTransaction.destination, + '-', + 'gagal', + ); + } + + } async callbackToPartner( @@ -1278,9 +1300,73 @@ export class TransactionService { status: string, ) { const partnerData = await this.userService.findPartner(partnerId); - const res = await axios.get( - `${partnerData.callback_url}?status=${status}&memberID=${partnerData.code}&trxid=${trxId}&harga=${harga}&product=${productCode}&dest=${destination}&seriNumber=${seriNumber}&message=${message}`, + const userData = await this.userService.findOneByPartner(partnerId); + + const coaAccount = await this.coaService.findByUser( + userData.id, + coaType.WALLET, ); + + const url = `${partnerData.callback_url}?status=${status}&memberID=${partnerData.code}&trxid=${trxId}&harga=${harga}&product=${productCode}&dest=${destination}&seriNumber=${seriNumber}&message=${message}&saldo=${coaAccount.amount}`; + const result = await this.callbackPartnerRepository.insert({ + partner_trx_id: partnerId, + trx_id: trxId, + url: url, + }); + const res = await axios.get(url); + return res; + } + + async rollbackJurnal(trxId: string[]) { + // const dataTransaction = await this.transactionRepository.findOne({ + // where: { + // id: trxId, + // }, + // relations: ['product_price'], + // }); + + if (trxId.length % 2 != 0) { + throw Error("Not Balance") + } + + const dataTransactionJurnal = await this.transactionJournalRepository.find({ + where: { + id: In(trxId), + }, + relations: ['coa'], + }); + + let dataRollbackJurnal = []; + + dataTransactionJurnal.map((it) => { + let data = { + coa_id: it.coa.id, + }; + + if (it.type == 0) { + data['credit'] = it.amount; + } else { + data['debit'] = it.amount; + } + + dataRollbackJurnal.push(data); + }); + + const dataTransaction = new Transactions(); + + try { + await this.connection.transaction(async (manager) => { + await this.accountingTransaction({ + createTransaction: false, + transactionalEntityManager: manager, + transaction: dataTransaction, + amount: dataTransaction.amount, + journals: dataRollbackJurnal, + }); + }); + } catch (e) { + throw e; + } } async withdrawBenefit(user) { diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 6382310..285c036 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -366,7 +366,7 @@ export class UsersService { where: { id: id, }, - relations: ['superior', 'roles'], + relations: ['superior', 'roles', 'partner'], }); } catch (e) { if (e instanceof EntityNotFoundError) {