diff --git a/src/transaction/dto/order-transaction.dto.ts b/src/transaction/dto/order-transaction.dto.ts index c492017..ff3d293 100644 --- a/src/transaction/dto/order-transaction.dto.ts +++ b/src/transaction/dto/order-transaction.dto.ts @@ -1,4 +1,4 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty, IsOptional } from 'class-validator'; export class OrderTransactionDto { @IsNotEmpty() @@ -7,5 +7,6 @@ export class OrderTransactionDto { @IsNotEmpty() destination: string; + @IsOptional() trx_id: string; } diff --git a/src/transaction/entities/transactions.entity.ts b/src/transaction/entities/transactions.entity.ts index a8b00c0..092050c 100644 --- a/src/transaction/entities/transactions.entity.ts +++ b/src/transaction/entities/transactions.entity.ts @@ -1,4 +1,4 @@ -import { Column, Entity, ManyToOne } from 'typeorm'; +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'; @@ -65,9 +65,13 @@ export class Transactions extends BaseModel { }) callback_json: string; + @OneToMany( + () => TransactionJournal, + (transaction_journal) => transaction_journal.transaction_head, + ) + transactionJournal: TransactionJournal[]; + mark_up_price: number; userData: UserDetail; - - transactionJournal: TransactionJournal; } diff --git a/src/transaction/transaction.controller.ts b/src/transaction/transaction.controller.ts index ada8c68..2818c7a 100644 --- a/src/transaction/transaction.controller.ts +++ b/src/transaction/transaction.controller.ts @@ -169,7 +169,29 @@ export class TransactionController { @Get('total-order') async findTotalOrder(@Request() req) { - const data = await this.transactionService.getTotalSell(); + const data = await this.transactionService.getTotalSell(req.user); + + return { + data, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + + @Get('total-order-b2b') + async findTotalOrderB2B(@Request() req) { + const data = await this.transactionService.getTotalSellB2B(req.user); + + return { + data, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + + @Get('total-order-partner') + async findTotalOrderPartner(@Request() req) { + const data = await this.transactionService.getTotalSellPartner(req.user); return { data, diff --git a/src/transaction/transaction.service.ts b/src/transaction/transaction.service.ts index ae6b9e1..62951db 100644 --- a/src/transaction/transaction.service.ts +++ b/src/transaction/transaction.service.ts @@ -901,7 +901,7 @@ export class TransactionService { .leftJoin('product_price.product', 'product') .addSelect('transaction.amount', 'price') .addSelect('transaction.destination') - .addSelect('transaction.seri_number','seri_number') + .addSelect('transaction.seri_number', 'seri_number') .addSelect('transaction.supplier_trx_id', 'transaction_code') .addSelect('transaction.status', 'status') .addSelect('transaction.partner_trx_id', 'partner_transaction_code') @@ -910,10 +910,13 @@ export class TransactionService { .addSelect('product.id', 'product_id'); if (startDate && endDate) { - baseQuery.andWhere('transaction.created_at between :startDate and :enDate', { - startDate: new Date(startDate), - enDate: new Date(endDate), - }); + baseQuery.andWhere( + 'transaction.created_at between :startDate and :enDate', + { + startDate: new Date(startDate), + enDate: new Date(endDate), + }, + ); } const data = await baseQuery @@ -1051,22 +1054,79 @@ export class TransactionService { }); } - async getTotalSell() { - const { total_amount } = await this.transactionRepository + async getTotalSell(currentUser) { + const baseQuery = this.transactionRepository .createQueryBuilder('transactions') + .innerJoin('transactions.product_price', 'product_price') + .where('transactions.type = 1 and partner_trx_id is NULL'); + + const data = await baseQuery .select('SUM(transactions.amount) as total_amount') + .addSelect('SUM(product_price.price) as total_modal') + .addSelect('SUM(product_price.mark_up_price) as total_profit') + .addSelect('COUNT(transactions.id) as total_transaction') .getRawOne(); - return parseInt(total_amount); + const { total_expense } = await baseQuery + .select('SUM(transaction_journal.amount) as total_expense') + .innerJoin('transactions.transactionJournal', 'transaction_journal') + .where( + `transaction_journal.type = '0' and transaction_journal.amount < product_price.price`, + ) + .getRawOne(); + + return { + total_amount: parseInt(data.total_amount), + total_transaction: parseInt(data.total_transaction), + total_modal: parseInt(data.total_modal), + total_profit: parseInt(data.total_profit), + total_commission: parseInt(data.total_profit) - parseInt(total_expense), + }; } - async getTotalProfit() { - const { total_amount } = await this.transactionRepository + async getTotalSellB2B(currentUser) { + const baseQuery = this.transactionRepository .createQueryBuilder('transactions') + .innerJoin('transactions.product_price', 'product_price') + .where('transactions.type = 1 and partner_trx_id is not NULL'); + + const data = await baseQuery .select('SUM(transactions.amount) as total_amount') + .addSelect('SUM(product_price.price) as total_modal') + .addSelect('SUM(product_price.mark_up_price) as total_profit') + .addSelect('COUNT(transactions.id) as total_transaction') .getRawOne(); - return parseInt(total_amount); + return { + total_amount: parseInt(data.total_amount), + total_transaction: parseInt(data.total_transaction), + total_modal: parseInt(data.total_modal), + total_profit: parseInt(data.total_profit), + }; + } + + async getTotalSellPartner(currentUser) { + const userData = await this.userService.findByUsername( + currentUser.username, + ); + + const baseQuery = this.transactionRepository + .createQueryBuilder('transactions') + .innerJoin('transactions.product_price', 'product_price') + .where('transactions.type = 1') + .andWhere('transactions.user = :id', { + id: userData.id, + }); + + const data = await baseQuery + .select('SUM(transactions.amount) as total_amount') + .addSelect('COUNT(transactions.id) as total_transaction') + .getRawOne(); + + return { + total_amount: parseInt(data.total_amount), + total_transaction: parseInt(data.total_transaction), + }; } async calculateCommission(data, totalPrice, userData) { diff --git a/src/users/users.service.ts b/src/users/users.service.ts index ba2e965..e84a914 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -1,4 +1,10 @@ -import { forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; +import { + forwardRef, + HttpException, + HttpStatus, + Inject, + Injectable, +} from '@nestjs/common'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { Connection, EntityNotFoundError, Not, Repository } from 'typeorm'; @@ -58,24 +64,29 @@ export class UsersService { userData.username = createUserDto.username; userData.password = await hashPassword(createUserDto.password, salt); userData.salt = salt; + if (createUserDto.superior) { userData.superior = superior; } else { userData.superior = null; userData.partner = createUserDto.partner; } + userData.roles = roles; await this.connection.transaction(async (manager) => { const result = await manager.insert(User, userData); const userDetailData = new UserDetail(); + userDetailData.name = createUserDto.name; userDetailData.phone_number = createUserDto.phone_number; userDetailData.user = userData; + const user_detail = await manager.insert(UserDetail, userDetailData); const dataCoaWallet = new InputCoaDto(); + dataCoaWallet.user = userData; dataCoaWallet.balanceType = balanceType.CREDIT; dataCoaWallet.type = coaType.WALLET; @@ -83,6 +94,7 @@ export class UsersService { await this.coaService.create(dataCoaWallet); const dataCoaAR = new InputCoaDto(); + dataCoaAR.user = userData; dataCoaAR.balanceType = balanceType.DEBIT; dataCoaAR.relatedUserId = superior.id; @@ -92,6 +104,7 @@ export class UsersService { if (roles.name == 'Supervisor' || roles.name == 'Sales') { const dataCOAProfit = new InputCoaDto(); + dataCOAProfit.user = userData; dataCOAProfit.balanceType = balanceType.CREDIT; dataCOAProfit.type = coaType.PROFIT; @@ -101,6 +114,7 @@ export class UsersService { if (createUserDto.superior) { const dataCoaAP = new InputCoaDto(); + dataCoaAP.user = userData; dataCoaAP.balanceType = balanceType.CREDIT; dataCoaAP.relatedUserId = superior.id; @@ -180,28 +194,37 @@ export class UsersService { superior: id, }, }); - const listId = baseQuery.map((x) => x.id); + const listId = baseQuery.map((x) => { + return x.id; + }); + listUser = listUser.concat(listId); listToFind = listId; + if (role == 1) { return listUser; - } else { - for (let it = 2; it <= role; it++) { - let newListToFind = []; - await mapSeries(listToFind, async (ltf) => { - const getListUser = await this.usersRepository.find({ - where: { - superior: ltf, - }, - }); - if (getListUser.length > 0) { - const listId = getListUser.map((x) => x.id); - newListToFind = newListToFind.concat(listId); - listUser = listUser.concat(listId); - } + } + + for (let it = 2; it <= role; it++) { + let newListToFind = []; + + await mapSeries(listToFind, async (ltf) => { + const getListUser = await this.usersRepository.find({ + where: { + superior: ltf, + }, }); - listToFind = newListToFind; - } + + if (getListUser.length > 0) { + const listId = getListUser.map((x) => { + return x.id; + }); + + newListToFind = newListToFind.concat(listId); + listUser = listUser.concat(listId); + } + }); + listToFind = newListToFind; } return listUser; @@ -335,10 +358,13 @@ export class UsersService { .getOne(); const coa = await this.coaService.findByUser(id, coaType.WALLET); let coaProfit; - if(userData.roles.id != 'e4dfb6a3-2338-464a-8fb8-5cbc089d4209'){ - coaProfit = await this.coaService.findByUser(id, coaType.PROFIT); - }; + if ( + userData.roles.id != 'e4dfb6a3-2338-464a-8fb8-5cbc089d4209' && + userData.roles.id != '21dceea2-416e-4b55-b74c-12605e1f8d1b' + ) { + coaProfit = await this.coaService.findByUser(id, coaType.PROFIT); + } return { ...userData, @@ -416,11 +442,14 @@ export class UsersService { async updatePassword(id: string, updateUserDto: UpdateUserDto) { try { const dataUser = await this.usersRepository.findOneOrFail(id); + dataUser.password = await hashPassword( updateUserDto.password, dataUser.salt, ); + const result = await this.usersRepository.save(dataUser); + return dataUser; } catch (e) { if (e instanceof EntityNotFoundError) { @@ -444,11 +473,14 @@ export class UsersService { partner: id, }, }); + dataUser.password = await hashPassword( updateUserDto.password, dataUser.salt, ); + const result = await this.usersRepository.save(dataUser); + return dataUser; } catch (e) { if (e instanceof EntityNotFoundError) {