Merge branch 'master' of https://gitlab.com/empatnusabangsa/ppob/ppob-backend into devops-production
This commit is contained in:
commit
68a3dc4ea6
11217
package-lock.json
generated
11217
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -38,12 +38,14 @@
|
||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
"csv-parser": "^3.0.0",
|
"csv-parser": "^3.0.0",
|
||||||
"decimal.js": "^10.3.1",
|
"decimal.js": "^10.3.1",
|
||||||
|
"exceljs": "^4.3.0",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"joi": "^17.4.2",
|
"joi": "^17.4.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"moment": "^2.29.4",
|
||||||
"nestjs-pino": "^2.3.1",
|
"nestjs-pino": "^2.3.1",
|
||||||
"passport": "^0.5.0",
|
"passport": "^0.4.0",
|
||||||
"passport-jwt": "^4.0.0",
|
"passport-jwt": "^4.0.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"pg": "^8.7.1",
|
"pg": "^8.7.1",
|
||||||
|
@ -52,6 +54,7 @@
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "^7.2.0",
|
"rxjs": "^7.2.0",
|
||||||
|
"tmp": "^0.2.1",
|
||||||
"typeorm": "^0.2.37",
|
"typeorm": "^0.2.37",
|
||||||
"typeorm-naming-strategies": "^2.0.0"
|
"typeorm-naming-strategies": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
|
8
src/transaction/dto/export-transaction.dto.ts
Normal file
8
src/transaction/dto/export-transaction.dto.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { IsNotEmpty, IsOptional } from 'class-validator';
|
||||||
|
|
||||||
|
export class ExportTransactionDto {
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
dateStart: string;
|
||||||
|
|
||||||
|
}
|
36
src/transaction/excel.controller.ts
Normal file
36
src/transaction/excel.controller.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Res,
|
||||||
|
Header,
|
||||||
|
Post,
|
||||||
|
Body,
|
||||||
|
Request, Param, ParseUUIDPipe,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Response } from 'express';
|
||||||
|
import { TransactionService } from './transaction.service';
|
||||||
|
import { ExportTransactionDto } from './dto/export-transaction.dto';
|
||||||
|
|
||||||
|
@Controller({
|
||||||
|
path: 'excel',
|
||||||
|
version: '1',
|
||||||
|
})
|
||||||
|
export class ExcelController {
|
||||||
|
constructor(private transactionService: TransactionService) {}
|
||||||
|
|
||||||
|
@Post('history-user/export/:id')
|
||||||
|
@Header('Content-Type', 'text/xlsx')
|
||||||
|
async exportTransactionHistory(
|
||||||
|
@Param('id', ParseUUIDPipe) id: string,
|
||||||
|
@Body() exportTransactionDto: ExportTransactionDto,
|
||||||
|
@Request() req,
|
||||||
|
@Res() res: Response,
|
||||||
|
) {
|
||||||
|
const result = await this.transactionService.exportDataExcel(
|
||||||
|
exportTransactionDto.dateStart,
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
|
||||||
|
res.download(`${result}`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,22 @@
|
||||||
import { Body, Controller, Get, HttpStatus, Param, ParseUUIDPipe, Post, Put, Query, Request } from '@nestjs/common';
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Header,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
ParseUUIDPipe,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Query,
|
||||||
|
Request, Res
|
||||||
|
} 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 { AddSaldoSupplier } from './dto/add-saldo-supplier.dto';
|
import { AddSaldoSupplier } from './dto/add-saldo-supplier.dto';
|
||||||
import { DepositReturnDto } from './dto/deposit_return.dto';
|
import { DepositReturnDto } from './dto/deposit_return.dto';
|
||||||
|
import { ExportTransactionDto } from './dto/export-transaction.dto';
|
||||||
|
|
||||||
@Controller({
|
@Controller({
|
||||||
path: 'transaction',
|
path: 'transaction',
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { CheckBillHistory } from './entities/check-bill-history.entity';
|
||||||
import { CallbackPartner } from './entities/callback-partner.entity';
|
import { CallbackPartner } from './entities/callback-partner.entity';
|
||||||
import { ProductHistoryPrice } from '../product/entities/product-history-price.entity';
|
import { ProductHistoryPrice } from '../product/entities/product-history-price.entity';
|
||||||
import { ProductHistoryStatus } from '../product/entities/product-history-status.entity';
|
import { ProductHistoryStatus } from '../product/entities/product-history-status.entity';
|
||||||
|
import { ExcelController } from './excel.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -28,9 +29,11 @@ import { ProductHistoryStatus } from '../product/entities/product-history-status
|
||||||
]),
|
]),
|
||||||
ProductModule,
|
ProductModule,
|
||||||
ConfigurableModule,
|
ConfigurableModule,
|
||||||
forwardRef(() => UsersModule),
|
forwardRef(() => {
|
||||||
|
return UsersModule;
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
controllers: [TransactionController, PpobCallbackController],
|
controllers: [TransactionController, PpobCallbackController, ExcelController],
|
||||||
providers: [TransactionService, CoaService],
|
providers: [TransactionService, CoaService],
|
||||||
exports: [CoaService],
|
exports: [CoaService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
HttpException,
|
||||||
|
HttpStatus,
|
||||||
|
Injectable,
|
||||||
|
Logger,
|
||||||
|
NotFoundException,
|
||||||
|
} from '@nestjs/common';
|
||||||
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 { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
@ -38,6 +45,7 @@ import { CheckBillHistory } from './entities/check-bill-history.entity';
|
||||||
import { CallbackPartner } from './entities/callback-partner.entity';
|
import { CallbackPartner } from './entities/callback-partner.entity';
|
||||||
import { doAuthorizeHemat } from '../helper/sihemat-authorization';
|
import { doAuthorizeHemat } from '../helper/sihemat-authorization';
|
||||||
import { ProductHistoryStatusService } from '../product/history-status/history-status.service';
|
import { ProductHistoryStatusService } from '../product/history-status/history-status.service';
|
||||||
|
import { Workbook } from 'exceljs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TransactionService {
|
export class TransactionService {
|
||||||
|
@ -2123,6 +2131,202 @@ export class TransactionService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async exportDataExcel(startDate, user: any) {
|
||||||
|
const userData = await this.userService.findExist(user);
|
||||||
|
|
||||||
|
let userBySupperior = [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
userData.roles.id != 'e4dfb6a3-2338-464a-8fb8-5cbc089d4209' &&
|
||||||
|
userData.roles.id != '21dceea2-416e-4b55-b74c-12605e1f8d1b'
|
||||||
|
) {
|
||||||
|
let roleNumber;
|
||||||
|
|
||||||
|
if (userData.roles.id == '3196cdf4-ae5f-4677-9bcd-98be35c72321') {
|
||||||
|
roleNumber = 3;
|
||||||
|
} else if (userData.roles.id == '3196cdf4-ae5f-4677-9bcd-98be35c72322') {
|
||||||
|
roleNumber = 2;
|
||||||
|
} else if (userData.roles.id == 'e4dfb6a3-2348-464a-8fb8-5cbc089d4209') {
|
||||||
|
roleNumber = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listUser = await this.userService.findAllSubordinate(
|
||||||
|
userData.id,
|
||||||
|
roleNumber,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (listUser.length < 1) {
|
||||||
|
userBySupperior.push(userData.id);
|
||||||
|
} else {
|
||||||
|
userBySupperior = listUser;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
userBySupperior.push(userData.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseQuery = this.transactionRepository
|
||||||
|
.createQueryBuilder('transaction')
|
||||||
|
.select('transaction.id', 'id')
|
||||||
|
.addSelect('transaction.created_at', 'created_at')
|
||||||
|
.where('transaction.user IN (:...id) and transaction.type = 1', {
|
||||||
|
id: userBySupperior,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
.leftJoinAndMapOne(
|
||||||
|
'transaction.userData',
|
||||||
|
UserDetail,
|
||||||
|
'userData',
|
||||||
|
'userData.user = transaction.user',
|
||||||
|
).select(['userData.user'])
|
||||||
|
.leftJoin('transaction.product_price', 'product_price')
|
||||||
|
.leftJoin('product_price.product', 'product')
|
||||||
|
.leftJoin('product.supplier', 'supplier')
|
||||||
|
|
||||||
|
.addSelect('product.name', 'product_name')
|
||||||
|
.addSelect('product.code', 'product_code')
|
||||||
|
.addSelect('transaction.amount', 'price')
|
||||||
|
.addSelect('transaction.balance_remaining', 'balance_remaining')
|
||||||
|
.addSelect('userData.name', 'buyer')
|
||||||
|
.addSelect('transaction.destination', 'destination')
|
||||||
|
.addSelect('transaction.supplier_trx_id', 'transaction_code')
|
||||||
|
.addSelect(`CASE
|
||||||
|
WHEN "transaction"."status" = 1 THEN 'Success'
|
||||||
|
WHEN "transaction"."status" = 2 THEN 'Failed'
|
||||||
|
ELSE 'Pending'
|
||||||
|
END`, 'status')
|
||||||
|
.addSelect('transaction.seri_number', 'serial_number')
|
||||||
|
.addSelect('transaction.partner_trx_id', 'partner_trx_id')
|
||||||
|
.addSelect('transaction.created_at', 'transaction_date')
|
||||||
|
.addSelect('transaction.failed_reason', 'failed_reason')
|
||||||
|
|
||||||
|
.orderBy('transaction.created_at', 'DESC');
|
||||||
|
|
||||||
|
if (startDate) {
|
||||||
|
baseQuery.andWhere(
|
||||||
|
'transaction.created_at between :startDate and :enDate',
|
||||||
|
{
|
||||||
|
startDate: `${startDate} 00:00:00`,
|
||||||
|
enDate: `${startDate} 23:59:59`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await baseQuery.getRawMany();
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// data,
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
let rows = [];
|
||||||
|
|
||||||
|
// First create the array of keys/net_total so that we can sort it:
|
||||||
|
var sort_array = [];
|
||||||
|
for (var key in data) {
|
||||||
|
sort_array.push({key: key, product_name: data[key].product_name});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now sort it:
|
||||||
|
sort_array.sort((x, y) => {
|
||||||
|
return x.product_name - y.product_name;
|
||||||
|
});
|
||||||
|
|
||||||
|
let dataSorted = [];
|
||||||
|
|
||||||
|
// Now process that object with it:
|
||||||
|
for (var i = 0; i < sort_array.length; i++) {
|
||||||
|
var item = data[sort_array[i].key];
|
||||||
|
|
||||||
|
// now do stuff with each item
|
||||||
|
const moment = require("moment");
|
||||||
|
|
||||||
|
dataSorted.push({
|
||||||
|
product_name: item.product_name,
|
||||||
|
product_code: item.product_code,
|
||||||
|
price: item.price,
|
||||||
|
balance_remaining: item.balance_remaining,
|
||||||
|
buyer: item.buyer,
|
||||||
|
destination: item.destination,
|
||||||
|
transaction_code: item.transaction_code,
|
||||||
|
status: item.status,
|
||||||
|
serial_number: item.serial_number,
|
||||||
|
partner_trx_id: item.partner_trx_id,
|
||||||
|
transaction_date: moment(item.transaction_date.toLocaleString()).format("MM-DD-YYYY HH:mm:ss"),
|
||||||
|
failed_reason: item.failed_reason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSorted.forEach((doc) => {
|
||||||
|
rows.push(Object.values(doc));
|
||||||
|
});
|
||||||
|
|
||||||
|
//creating a workbook
|
||||||
|
let book = new Workbook();
|
||||||
|
|
||||||
|
//adding a worksheet to workbook
|
||||||
|
let sheet = book.addWorksheet('Mutasi Transaksi');
|
||||||
|
|
||||||
|
//add the header
|
||||||
|
rows.unshift(Object.keys(dataSorted[0]));
|
||||||
|
|
||||||
|
|
||||||
|
//adding multiple rows in the sheet
|
||||||
|
sheet.addRows(rows);
|
||||||
|
|
||||||
|
//customize column
|
||||||
|
sheet.columns = [
|
||||||
|
{header: 'Nama Produk', key: 'product_name'},
|
||||||
|
{header: 'Kode Produk', key: 'product_code'},
|
||||||
|
{header: 'Harga', key: 'price'},
|
||||||
|
{header: 'Sisa Saldo', key: 'balance_remaining'},
|
||||||
|
{header: 'Pembeli', key: 'buyer'},
|
||||||
|
{header: 'Tujuan', key: 'destination'},
|
||||||
|
{header: 'Kode Transaksi', key: 'transaction_code'},
|
||||||
|
{header: 'Status', key: 'status'},
|
||||||
|
{header: 'No Seri', key: 'serial_number'},
|
||||||
|
{header: 'IDTrx Mitra', key: 'partner_trx_id'},
|
||||||
|
{header: 'Tanggal Transaksi', key: 'transaction_date'},
|
||||||
|
{header: 'Alasan Gagal', key: 'failed_reason'},
|
||||||
|
];
|
||||||
|
|
||||||
|
this.styleSheet(sheet)
|
||||||
|
|
||||||
|
const tmp = require('tmp');
|
||||||
|
|
||||||
|
let File = await new Promise((resolve, reject) => {
|
||||||
|
tmp.file(
|
||||||
|
{
|
||||||
|
discardDescriptor: true,
|
||||||
|
prefix: `Mutasi Transaksi ${userData?.partner.name} ${startDate}`,
|
||||||
|
postfix: '.xlsx',
|
||||||
|
mode: parseInt('0600', 8),
|
||||||
|
},
|
||||||
|
async (err, file) => {
|
||||||
|
if (err) throw new BadRequestException(err);
|
||||||
|
|
||||||
|
//writing temporary file
|
||||||
|
book.xlsx
|
||||||
|
.writeFile(file)
|
||||||
|
.then((_) => {
|
||||||
|
resolve(file);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new BadRequestException(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
//returning the path of file
|
||||||
|
return File;
|
||||||
|
} catch (e) {
|
||||||
|
throw new HttpException('No data to export', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getTotalSell(currentUser) {
|
async getTotalSell(currentUser) {
|
||||||
const baseQuery = this.transactionRepository
|
const baseQuery = this.transactionRepository
|
||||||
.createQueryBuilder('transactions')
|
.createQueryBuilder('transactions')
|
||||||
|
@ -2187,7 +2391,8 @@ export class TransactionService {
|
||||||
total_modal: parseInt(data.total_modal),
|
total_modal: parseInt(data.total_modal),
|
||||||
total_amount: parseInt(data.total_amount),
|
total_amount: parseInt(data.total_amount),
|
||||||
total_transaction: parseInt(data.total_transaction),
|
total_transaction: parseInt(data.total_transaction),
|
||||||
total_profit: parseInt(data.total_profit),
|
total_profit: data.total_amount - data.total_modal,
|
||||||
|
// total_profit: parseInt(data.total_profit),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2441,4 +2646,76 @@ export class TransactionService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private styleSheet(sheet) {
|
||||||
|
//set the width of each column
|
||||||
|
sheet.getColumn(1).width = 40;
|
||||||
|
sheet.getColumn(2).width = 20.5;
|
||||||
|
sheet.getColumn(3).width = 20.5;
|
||||||
|
sheet.getColumn(4).width = 20.5;
|
||||||
|
sheet.getColumn(5).width = 20.5;
|
||||||
|
sheet.getColumn(6).width = 20.5;
|
||||||
|
sheet.getColumn(7).width = 20.5;
|
||||||
|
sheet.getColumn(8).width = 20.5;
|
||||||
|
sheet.getColumn(9).width = 20.5;
|
||||||
|
sheet.getColumn(10).width = 20.5;
|
||||||
|
sheet.getColumn(11).width = 20.5;
|
||||||
|
sheet.getColumn(12).width = 20.5;
|
||||||
|
|
||||||
|
//set the height of header
|
||||||
|
sheet.getRow(1).height = 30.5;
|
||||||
|
|
||||||
|
//font color
|
||||||
|
sheet.getRow(1).font = {size: 11.5, bold: true, color: {argb: 'FFFFFF'}}
|
||||||
|
|
||||||
|
//background color
|
||||||
|
sheet.getRow(1).fill = {type: 'pattern', pattern: 'solid', bgColor: {argb: '000000'}, fgColor: {argb: '000000'}}
|
||||||
|
|
||||||
|
//alignments
|
||||||
|
sheet.getColumn(1).alignment = {vertical: "start", horizontal: "start", wrapText: true}
|
||||||
|
sheet.getColumn(2).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(3).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(4).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(5).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(6).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(7).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(8).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(9).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(10).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(11).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
sheet.getColumn(12).alignment = {vertical: "start", horizontal: "start", wrapText: true}
|
||||||
|
|
||||||
|
sheet.getRow(1).alignment = {vertical: "middle", horizontal: "center", wrapText: true}
|
||||||
|
|
||||||
|
//borders
|
||||||
|
const borderStyle = {
|
||||||
|
top: {style: 'double', color: {argb: 'FF00FF00'}},
|
||||||
|
left: {style: 'double', color: {argb: '000000'}},
|
||||||
|
bottom: {style: 'double', color: {argb: '000000'}},
|
||||||
|
right: {style: 'double', color: {argb: '000000'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sheet.getColumn(1).border = borderStyle
|
||||||
|
sheet.getColumn(2).border = borderStyle
|
||||||
|
sheet.getColumn(3).border = borderStyle
|
||||||
|
sheet.getColumn(4).border = borderStyle
|
||||||
|
sheet.getColumn(5).border = borderStyle
|
||||||
|
sheet.getColumn(6).border = borderStyle
|
||||||
|
sheet.getColumn(7).border = borderStyle
|
||||||
|
sheet.getColumn(8).border = borderStyle
|
||||||
|
sheet.getColumn(9).border = borderStyle
|
||||||
|
sheet.getColumn(10).border = borderStyle
|
||||||
|
sheet.getColumn(11).border = borderStyle
|
||||||
|
sheet.getColumn(12).border = borderStyle
|
||||||
|
|
||||||
|
|
||||||
|
sheet.getRow(1).border = {
|
||||||
|
top: {style: 'thin', color: {argb: '000000'}},
|
||||||
|
left: {style: 'thin', color: {argb: 'FFFFFF'}},
|
||||||
|
bottom: {style: 'thin', color: {argb: '000000'}},
|
||||||
|
right: {style: 'thin', color: {argb: 'FFFFFF'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user