fix: deposit_return and fix transction

This commit is contained in:
ilham 2021-12-20 00:18:22 +07:00
parent e7db0073c5
commit 38f24a1480
7 changed files with 360 additions and 67 deletions

View File

@ -2,12 +2,15 @@ export enum statusTransaction {
PENDING, PENDING,
SUCCESS, SUCCESS,
FAILED, FAILED,
APPROVED,
REJECTED,
} }
export enum typeTransaction { export enum typeTransaction {
DISTRIBUTION, DISTRIBUTION,
ORDER, ORDER,
DEPOSIT_IRS, DEPOSIT_SUPPLIER,
DEPOSIT_RETURN,
} }
export enum productType { export enum productType {

View File

@ -1,11 +1,4 @@
import { IsNotEmpty, IsUUID } from 'class-validator'; import { IsNotEmpty, IsUUID } from 'class-validator';
import {
balanceType,
coaType,
statusTransaction,
typeTransaction,
} from 'src/helper/enum-list';
import { EntityManager } from 'typeorm';
export class AddSaldoSupplier { export class AddSaldoSupplier {
@IsNotEmpty() @IsNotEmpty()

View File

@ -0,0 +1,7 @@
import { DistributeTransactionDto } from './distribute-transaction.dto';
import { IsNotEmpty } from 'class-validator';
export class DepositReturnDto extends DistributeTransactionDto {
@IsNotEmpty()
image_prove: string;
}

View File

@ -6,7 +6,4 @@ export class DistributeTransactionDto {
@IsNotEmpty() @IsNotEmpty()
destination: string; destination: string;
@IsNotEmpty()
supplier: string;
} }

View File

@ -37,5 +37,10 @@ export class Transactions extends BaseModel {
@ManyToOne(() => ProductHistoryPrice, (product) => product.id) @ManyToOne(() => ProductHistoryPrice, (product) => product.id)
product_price: ProductHistoryPrice; product_price: ProductHistoryPrice;
@Column({
nullable: true,
})
image_prove: string;
mark_up_price: number; mark_up_price: number;
} }

View File

@ -9,12 +9,14 @@ import {
Request, Request,
HttpStatus, HttpStatus,
Query, Query,
Put,
ParseUUIDPipe,
} from '@nestjs/common'; } from '@nestjs/common';
import { TransactionService } from './transaction.service'; import { TransactionService } from './transaction.service';
import { DistributeTransactionDto } from './dto/distribute-transaction.dto'; import { DistributeTransactionDto } from './dto/distribute-transaction.dto';
import { OrderTransactionDto } from './dto/order-transaction.dto'; import { OrderTransactionDto } from './dto/order-transaction.dto';
import { UpdateTransactionDto } from './dto/update-transaction.dto';
import { AddSaldoSupplier } from './dto/add-saldo-supplier.dto'; import { AddSaldoSupplier } from './dto/add-saldo-supplier.dto';
import { DepositReturnDto } from './dto/deposit_return.dto';
@Controller({ @Controller({
path: 'transaction', path: 'transaction',
@ -24,23 +26,27 @@ export class TransactionController {
constructor(private readonly transactionService: TransactionService) {} constructor(private readonly transactionService: TransactionService) {}
@Post('distribute') @Post('distribute')
create( async create(
@Body() createTransactionDto: DistributeTransactionDto,
@Request() req,
) {
return this.transactionService.distributeDeposit(
createTransactionDto,
req.user,
);
}
@Post('distribute-admin')
distributeAdmin(
@Body() createTransactionDto: DistributeTransactionDto, @Body() createTransactionDto: DistributeTransactionDto,
@Request() req, @Request() req,
) { ) {
return { return {
data: this.transactionService.distributeFromAdmin( data: await this.transactionService.distributeDeposit(
createTransactionDto,
req.user,
),
statusCode: HttpStatus.CREATED,
message: 'success',
};
}
@Post('distribute-admin')
async distributeAdmin(
@Body() createTransactionDto: DistributeTransactionDto,
@Request() req,
) {
return {
data: await this.transactionService.distributeFromAdmin(
createTransactionDto, createTransactionDto,
req.user, req.user,
), ),
@ -65,14 +71,33 @@ export class TransactionController {
} }
@Post('order') @Post('order')
orderTransaction( async orderTransaction(
@Body() orderTransactionDto: OrderTransactionDto, @Body() orderTransactionDto: OrderTransactionDto,
@Request() req, @Request() req,
) { ) {
return this.transactionService.orderTransaction( return {
orderTransactionDto, data: await this.transactionService.orderTransaction(
req.user, orderTransactionDto,
); req.user,
),
statusCode: HttpStatus.CREATED,
message: 'success',
};
}
@Post('deposit-return')
async depositReturn(
@Body() depositReturnDto: DepositReturnDto,
@Request() req,
) {
return {
data: await this.transactionService.createDepositReturn(
req.user,
depositReturnDto,
),
statusCode: HttpStatus.CREATED,
message: 'success',
};
} }
@Get('history') @Get('history')
@ -88,4 +113,69 @@ export class TransactionController {
message: 'success', message: 'success',
}; };
} }
@Get('deposit-return')
async findDepositReturn(@Query('page') page: number, @Request() req) {
const data = await this.transactionService.getAllDepositReturnFromUser(
req.user.userId,
page,
);
return {
...data,
statusCode: HttpStatus.OK,
message: 'success',
};
}
@Get('deposit-return/confirmation')
async findDepositReturnConfirmation(
@Query('page') page: number,
@Request() req,
) {
const data = await this.transactionService.getAllDepositReturnToUser(
req.user.userId,
page,
);
return {
...data,
statusCode: HttpStatus.OK,
message: 'success',
};
}
@Put('deposit-return/confirmation/:id')
async confirmDepositReturn(
@Param('id', ParseUUIDPipe) id: string,
@Request() req,
@Body() status: string,
) {
return {
data: await this.transactionService.confirmationDepositReturn(
id,
req.user,
status,
),
statusCode: HttpStatus.OK,
message: 'success',
};
}
@Put('deposit-return/confirmation-admin/:id')
async confirmDepositReturnAdmin(
@Param('id', ParseUUIDPipe) id: string,
@Request() req,
@Body() status: string,
) {
return {
data: await this.transactionService.confirmationAdminDepositReturn(
id,
req.user,
status,
),
statusCode: HttpStatus.OK,
message: 'success',
};
}
} }

View File

@ -28,7 +28,7 @@ import { AddSaldoSupplier } from './dto/add-saldo-supplier.dto';
import { SupplierService } from '../users/supplier/supplier.service'; import { SupplierService } from '../users/supplier/supplier.service';
import { ProductHistoryPriceService } from '../product/history-price/history-price.service'; import { ProductHistoryPriceService } from '../product/history-price/history-price.service';
import { CommissionService } from '../configurable/commission.service'; import { CommissionService } from '../configurable/commission.service';
import { catchError } from 'rxjs'; import { DepositReturnDto } from './dto/deposit_return.dto';
interface JournalEntry { interface JournalEntry {
coa_id: string; coa_id: string;
@ -88,7 +88,7 @@ export class TransactionService {
transactionData.amount = addSaldoSupplier.amount; transactionData.amount = addSaldoSupplier.amount;
transactionData.user = userData.id; transactionData.user = userData.id;
transactionData.status = statusTransaction.SUCCESS; transactionData.status = statusTransaction.SUCCESS;
transactionData.type = typeTransaction.DEPOSIT_IRS; transactionData.type = typeTransaction.DEPOSIT_SUPPLIER;
await manager.insert(Transactions, transactionData); await manager.insert(Transactions, transactionData);
@ -130,21 +130,18 @@ export class TransactionService {
currentUser.username, currentUser.username,
); );
if (userData.roles.name != 'Admin') { const supplier = await this.supplierService.findByActive();
throw new HttpException(
{
statusCode: HttpStatus.NOT_ACCEPTABLE,
error: 'Roles Not Admin',
},
HttpStatus.NOT_ACCEPTABLE,
);
}
try { try {
//GET Supplier if (userData.roles.name != 'Admin') {
const supplier = await this.supplierService.findByCode( throw new HttpException(
distributeTransactionDto.supplier, {
); statusCode: HttpStatus.NOT_ACCEPTABLE,
error: 'Roles Not Admin',
},
HttpStatus.NOT_ACCEPTABLE,
);
}
// GET COA // GET COA
const coaAR = await this.coaService.findByTwoUser( const coaAR = await this.coaService.findByTwoUser(
@ -171,6 +168,7 @@ export class TransactionService {
transactionData.id = uuid.v4(); transactionData.id = uuid.v4();
transactionData.amount = distributeTransactionDto.amount; transactionData.amount = distributeTransactionDto.amount;
transactionData.user = userData.id; transactionData.user = userData.id;
transactionData.user_destination = distributeTransactionDto.destination;
transactionData.status = statusTransaction.SUCCESS; transactionData.status = statusTransaction.SUCCESS;
transactionData.type = typeTransaction.DISTRIBUTION; transactionData.type = typeTransaction.DISTRIBUTION;
@ -201,11 +199,11 @@ export class TransactionService {
], ],
}); });
}); });
return true;
} catch (e) { } catch (e) {
throw e; throw e;
} }
return true;
} }
async distributeDeposit( async distributeDeposit(
@ -246,6 +244,7 @@ export class TransactionService {
transactionData.id = uuid.v4(); transactionData.id = uuid.v4();
transactionData.amount = distributeTransactionDto.amount; transactionData.amount = distributeTransactionDto.amount;
transactionData.user = userData.id; transactionData.user = userData.id;
transactionData.user_destination = distributeTransactionDto.destination;
transactionData.status = statusTransaction.SUCCESS; transactionData.status = statusTransaction.SUCCESS;
transactionData.type = typeTransaction.DISTRIBUTION; transactionData.type = typeTransaction.DISTRIBUTION;
@ -301,7 +300,7 @@ export class TransactionService {
let supervisorData = []; let supervisorData = [];
const profit = product_price.mark_up_price - product_price.price; let profit = product_price.mark_up_price - product_price.price;
if (!userData.partner) { if (!userData.partner) {
//GET SALES //GET SALES
@ -310,6 +309,9 @@ export class TransactionService {
profit, profit,
userData, userData,
); );
profit = supervisorData
.map((item) => item.credit)
.reduce((prev, curr) => prev + curr, 0);
} }
//GET COA //GET COA
@ -380,7 +382,7 @@ export class TransactionService {
}, },
{ {
coa_id: coaExpense.id, coa_id: coaExpense.id,
credit: userData.partner ? 0 : profit, debit: userData.partner ? 0 : profit,
}, },
].concat(supervisorData), ].concat(supervisorData),
}); });
@ -392,6 +394,154 @@ export class TransactionService {
return true; return true;
} }
async createDepositReturn(currentUser, depositReturnDto: DepositReturnDto) {
const userData = await this.userService.findByUsername(
currentUser.username,
);
try {
const transactionData = new Transactions();
transactionData.id = uuid.v4();
transactionData.amount = depositReturnDto.amount;
transactionData.user = userData.id;
transactionData.user_destination = depositReturnDto.destination;
transactionData.status = statusTransaction.PENDING;
transactionData.type = typeTransaction.DEPOSIT_RETURN;
await this.connection.transaction(async (manager) => {
await manager.insert(Transactions, transactionData);
});
return transactionData;
} catch (e) {
throw e;
}
}
async confirmationDepositReturn(
id: string,
userData,
statusApproval: string,
) {
const transactionData = await this.findApprovalDepositReturn(id);
const coaSenderWallet = await this.coaService.findByUser(
transactionData.user_destination,
coaType.WALLET,
);
const coaAP = await this.coaService.findByUserWithRelated(
userData.userId,
transactionData.user_destination,
coaType.ACCOUNT_PAYABLE,
);
const coaReceiverWallet = await this.coaService.findByUser(
transactionData.user_destination,
coaType.WALLET,
);
const coaAR = await this.coaService.findByUserWithRelated(
userData.userId,
transactionData.user_destination,
coaType.ACCOUNT_RECEIVABLE,
);
try {
await this.connection.transaction(async (manager) => {
transactionData.status =
statusApproval === 'Accept'
? statusTransaction.APPROVED
: statusTransaction.REJECTED;
await manager.save(transactionData);
await this.accountingTransaction({
createTransaction: false,
transactionalEntityManager: manager,
transaction: transactionData,
amount: transactionData.amount,
journals: [
{
coa_id: coaSenderWallet.id,
credit: transactionData.amount,
},
{
coa_id: coaReceiverWallet.id,
debit: transactionData.amount,
},
{
coa_id: coaAR.id,
credit: transactionData.amount,
},
{
coa_id: coaAP.id,
debit: transactionData.amount,
},
],
});
});
return transactionData;
} catch (e) {
throw e;
}
return transactionData;
}
async confirmationAdminDepositReturn(
id: string,
userData,
statusApproval: string,
) {
const transactionData = await this.findApprovalDepositReturn(id);
const coaAR = await this.coaService.findByUserWithRelated(
userData.userId,
transactionData.user_destination,
coaType.ACCOUNT_RECEIVABLE,
);
const coaBank = await this.coaService.findByName(
`${coaType[coaType.BANK]}-SYSTEM`,
);
try {
await this.connection.transaction(async (manager) => {
transactionData.status =
statusApproval === 'Accept'
? statusTransaction.APPROVED
: statusTransaction.REJECTED;
await manager.save(transactionData);
await this.accountingTransaction({
createTransaction: false,
transactionalEntityManager: manager,
transaction: transactionData,
amount: transactionData.amount,
journals: [
{
coa_id: coaAR.id,
credit: transactionData.amount,
},
{
coa_id: coaBank.id,
debit: transactionData.amount,
},
],
});
});
return transactionData;
} catch (e) {
throw e;
}
return transactionData;
}
async transactionHistoryByUser(page: number, user: string) { async transactionHistoryByUser(page: number, user: string) {
const baseQuery = this.transactionRepository const baseQuery = this.transactionRepository
.createQueryBuilder('transaction') .createQueryBuilder('transaction')
@ -422,6 +572,58 @@ export class TransactionService {
}; };
} }
async findApprovalDepositReturn(id: string) {
try {
return await this.transactionRepository.findOneOrFail({
where: {
id: id,
type: typeTransaction.DEPOSIT_RETURN,
status: statusTransaction.PENDING,
},
});
} catch (e) {
if (e instanceof EntityNotFoundError) {
throw new HttpException(
{
statusCode: HttpStatus.NOT_FOUND,
error: 'Return Deposit not found',
},
HttpStatus.NOT_FOUND,
);
} else {
throw e;
}
}
}
async getAllDepositReturnFromUser(user: string, page: number) {
return this.transactionRepository.findAndCount({
skip: page * 10,
take: 10,
where: {
user: user,
type: typeTransaction.DEPOSIT_RETURN,
},
order: {
createdAt: 'DESC',
},
});
}
async getAllDepositReturnToUser(user: string, page: number) {
return this.transactionRepository.findAndCount({
skip: page * 10,
take: 10,
where: {
user_destination: user,
type: typeTransaction.DEPOSIT_RETURN,
},
order: {
createdAt: 'DESC',
},
});
}
async calculateCommission(data, totalPrice, userData) { async calculateCommission(data, totalPrice, userData) {
const supervisorData = []; const supervisorData = [];
@ -436,25 +638,21 @@ export class TransactionService {
), ),
); );
//GET Admin return Promise.all(
supervisorData.push( supervisorData.map(async (it) => {
await this.userService.findByUsername( const coaAccount = await this.coaService.findByUser(
supervisorData[1].superior.username, it.id,
), coaType.WALLET,
);
const commissionValue = await this.commissionService.findOne(
it.roles.id,
);
return {
coa_id: coaAccount.id,
credit: (totalPrice * commissionValue.commission) / 100,
};
}),
); );
return supervisorData.map(async (it) => {
const coaAccount = await this.coaService.findByUser(
it.id,
coaType.WALLET,
);
const commissionValue = await this.commissionService.findOne(it.role.id);
return {
coa_id: coaAccount.id,
credit: totalPrice * commissionValue.commission,
};
});
} }
async accountingTransaction(createJournalDto: CreateJournalDto) { async accountingTransaction(createJournalDto: CreateJournalDto) {