Merge branch 'development' into 'devops-staging'
Development See merge request empatnusabangsa/ppob/ppob-backend!50
This commit is contained in:
commit
514c274be0
|
@ -35,7 +35,9 @@
|
||||||
"class-transformer": "^0.4.0",
|
"class-transformer": "^0.4.0",
|
||||||
"class-validator": "^0.13.1",
|
"class-validator": "^0.13.1",
|
||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
|
"csv-parser": "^3.0.0",
|
||||||
"decimal.js": "^10.3.1",
|
"decimal.js": "^10.3.1",
|
||||||
|
"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",
|
||||||
|
|
28
src/helper/csv-parser.ts
Normal file
28
src/helper/csv-parser.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { createReadStream } from 'fs';
|
||||||
|
import * as csvParser from 'csv-parser';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export async function parsingFile(dataFile) {
|
||||||
|
const parsingData: any = await new Promise((resolve, reject) => {
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
const file = createReadStream(
|
||||||
|
path.join(
|
||||||
|
process.cwd(),
|
||||||
|
'./files/Template Upload Product - Sheet1-a532.csv',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
file
|
||||||
|
.pipe(
|
||||||
|
csvParser({
|
||||||
|
headers: false,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.on('data', (data) => results.push(data))
|
||||||
|
.on('end', () => {
|
||||||
|
resolve(results);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return parsingData;
|
||||||
|
}
|
|
@ -105,6 +105,14 @@ export class ProductSubCategoriesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findOneForCSVParser(code: string) {
|
||||||
|
return await this.productSubCategoriesRepository.findOne({
|
||||||
|
where: {
|
||||||
|
code: code,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async update(
|
async update(
|
||||||
id: string,
|
id: string,
|
||||||
updateCategoriesProductDto: UpdateSubCategoriesProductDto,
|
updateCategoriesProductDto: UpdateSubCategoriesProductDto,
|
||||||
|
|
|
@ -92,10 +92,7 @@ export class ProductController {
|
||||||
|
|
||||||
@Get('test')
|
@Get('test')
|
||||||
async test(@Request() req) {
|
async test(@Request() req) {
|
||||||
const data = await this.productHistoryPriceService.findOne(
|
const data = await this.productService.processUploadCSV();
|
||||||
'4d3b328c-3ce4-4c84-84bb-cd9c36e85a45',
|
|
||||||
'27effb3e-0351-428a-ba7f-08a21c54e16a',
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { HttpException, HttpStatus } from '@nestjs/common';
|
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||||
import { EntityNotFoundError, Repository } from 'typeorm';
|
import { EntityNotFoundError, IsNull, Repository } from 'typeorm';
|
||||||
import { Product } from './entities/product.entity';
|
import { Product } from './entities/product.entity';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { CreateProductDto } from './dto/product/create-product.dto';
|
import { CreateProductDto } from './dto/product/create-product.dto';
|
||||||
|
@ -10,6 +10,8 @@ import { productType } from '../helper/enum-list';
|
||||||
import { UpdatePriceProductDto } from './dto/product/update-price-product.dto';
|
import { UpdatePriceProductDto } from './dto/product/update-price-product.dto';
|
||||||
import { UsersService } from '../users/users.service';
|
import { UsersService } from '../users/users.service';
|
||||||
import { SupplierService } from '../users/supplier/supplier.service';
|
import { SupplierService } from '../users/supplier/supplier.service';
|
||||||
|
import { parsingFile } from '../helper/csv-parser';
|
||||||
|
import { PartnerService } from '../users/partner/partner.service';
|
||||||
|
|
||||||
export class ProductService {
|
export class ProductService {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -20,6 +22,7 @@ export class ProductService {
|
||||||
private productSubCategoriesService: ProductSubCategoriesService,
|
private productSubCategoriesService: ProductSubCategoriesService,
|
||||||
private usersService: UsersService,
|
private usersService: UsersService,
|
||||||
private supplierService: SupplierService,
|
private supplierService: SupplierService,
|
||||||
|
private partnerService: PartnerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(createProductDto: CreateProductDto) {
|
async create(createProductDto: CreateProductDto) {
|
||||||
|
@ -47,6 +50,83 @@ export class ProductService {
|
||||||
return this.productRepository.findOneOrFail(result.identifiers[0].id);
|
return this.productRepository.findOneOrFail(result.identifiers[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async processUploadCSV() {
|
||||||
|
const data = await parsingFile('');
|
||||||
|
data.shift();
|
||||||
|
await Promise.all(
|
||||||
|
data.map(async (it) => {
|
||||||
|
let dataHistoryPrice;
|
||||||
|
let partnerData;
|
||||||
|
|
||||||
|
const subCategories =
|
||||||
|
await this.productSubCategoriesService.findOneForCSVParser(it[2]);
|
||||||
|
|
||||||
|
if (!subCategories) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const productData = await this.productRepository.findOne({
|
||||||
|
code: it[0],
|
||||||
|
});
|
||||||
|
if (productData) {
|
||||||
|
//TODO : Handle Update Product
|
||||||
|
productData.name = it[1];
|
||||||
|
productData.status = it[5] == 'active' ? 'ACTIVE' : 'NOT ACTIVE';
|
||||||
|
await this.productRepository.save(productData);
|
||||||
|
|
||||||
|
//TODO : Handle History Price
|
||||||
|
if (it[6] != '-' && it[6] != '') {
|
||||||
|
partnerData = await this.partnerService.findOne(it[6]);
|
||||||
|
dataHistoryPrice = await this.productHistoryPrice.findOne({
|
||||||
|
product: productData,
|
||||||
|
partner: partnerData,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dataHistoryPrice = await this.productHistoryPrice.findOne({
|
||||||
|
product: productData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataHistoryPrice.endDate = new Date();
|
||||||
|
await this.productHistoryPrice.save(dataHistoryPrice);
|
||||||
|
|
||||||
|
await this.productHistoryPrice.insert({
|
||||||
|
product: productData,
|
||||||
|
mark_up_price: it[4],
|
||||||
|
price: it[3],
|
||||||
|
type: productType.NORMAL,
|
||||||
|
startDate: new Date(),
|
||||||
|
endDate: null,
|
||||||
|
partner: it[6] != '-' ? partnerData : null,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let partnerData;
|
||||||
|
if (it[6] != '-' && it[6] != '') {
|
||||||
|
partnerData = await this.partnerService.findOne(it[6]);
|
||||||
|
}
|
||||||
|
const savedProduct = await this.productRepository.insert({
|
||||||
|
name: it[1],
|
||||||
|
code: it[0],
|
||||||
|
status: it[5] == 'active' ? 'ACTIVE' : 'NOT ACTIVE',
|
||||||
|
sub_categories: subCategories,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.productHistoryPrice.insert({
|
||||||
|
product: savedProduct.identifiers[0],
|
||||||
|
mark_up_price: it[4],
|
||||||
|
price: it[3],
|
||||||
|
type: productType.NORMAL,
|
||||||
|
startDate: new Date(),
|
||||||
|
endDate: null,
|
||||||
|
partner: it[6] != '-' ? partnerData : null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
async findAll(
|
async findAll(
|
||||||
page: number,
|
page: number,
|
||||||
supplier: string,
|
supplier: string,
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
import { Body, Controller, Get, HttpStatus, Param, ParseUUIDPipe, Post, Put, Query, Request } from '@nestjs/common';
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
ParseUUIDPipe,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Query,
|
||||||
|
Request,
|
||||||
|
} 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';
|
||||||
|
|
|
@ -10,6 +10,9 @@ export class CreatePartnerDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
code: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
npwp: string;
|
npwp: string;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,11 @@ export class Partner extends BaseModel {
|
||||||
@Column()
|
@Column()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
code: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
npwp: string;
|
npwp: string;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
|
import {
|
||||||
|
forwardRef,
|
||||||
|
HttpException,
|
||||||
|
HttpStatus,
|
||||||
|
Inject,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Connection, Not, Repository } from 'typeorm';
|
import { Connection, EntityNotFoundError, Not, Repository } from 'typeorm';
|
||||||
import { CoaService } from '../../transaction/coa.service';
|
import { CoaService } from '../../transaction/coa.service';
|
||||||
import { CreatePartnerDto } from '../dto/create-partner.dto';
|
import { CreatePartnerDto } from '../dto/create-partner.dto';
|
||||||
import { Partner } from '../entities/partner.entity';
|
import { Partner } from '../entities/partner.entity';
|
||||||
|
@ -9,6 +15,7 @@ import { UsersService } from '../users.service';
|
||||||
import { CreateUserDto } from '../dto/create-user.dto';
|
import { CreateUserDto } from '../dto/create-user.dto';
|
||||||
import { UpdatePartnerDto } from '../dto/update-partner.dto';
|
import { UpdatePartnerDto } from '../dto/update-partner.dto';
|
||||||
import { UpdateUserDto } from '../dto/update-user.dto';
|
import { UpdateUserDto } from '../dto/update-user.dto';
|
||||||
|
import { when } from 'joi';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PartnerService {
|
export class PartnerService {
|
||||||
|
@ -41,10 +48,12 @@ export class PartnerService {
|
||||||
}
|
}
|
||||||
|
|
||||||
const partnerData = new Partner();
|
const partnerData = new Partner();
|
||||||
|
|
||||||
partnerData.id = uuid.v4();
|
partnerData.id = uuid.v4();
|
||||||
partnerData.name = createPartnerDto.name;
|
partnerData.name = createPartnerDto.name;
|
||||||
partnerData.npwp = createPartnerDto.npwp;
|
partnerData.npwp = createPartnerDto.npwp;
|
||||||
partnerData.address = createPartnerDto.address;
|
partnerData.address = createPartnerDto.address;
|
||||||
|
partnerData.code = createPartnerDto.code;
|
||||||
partnerData.status = true;
|
partnerData.status = true;
|
||||||
|
|
||||||
await this.connection.transaction(async (manager) => {
|
await this.connection.transaction(async (manager) => {
|
||||||
|
@ -52,6 +61,7 @@ export class PartnerService {
|
||||||
});
|
});
|
||||||
|
|
||||||
const dataUser = new CreateUserDto();
|
const dataUser = new CreateUserDto();
|
||||||
|
|
||||||
dataUser.username = `admin_${partnerData.name}`;
|
dataUser.username = `admin_${partnerData.name}`;
|
||||||
dataUser.name = partnerData.name;
|
dataUser.name = partnerData.name;
|
||||||
dataUser.phone_number = partnerData.phone_number;
|
dataUser.phone_number = partnerData.phone_number;
|
||||||
|
@ -129,6 +139,14 @@ export class PartnerService {
|
||||||
return partnerData;
|
return partnerData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async findOne(code: string) {
|
||||||
|
return await this.partnerRepository.findOne({
|
||||||
|
where: {
|
||||||
|
code: code,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
findAllPartner(page, pageSize?) {
|
findAllPartner(page, pageSize?) {
|
||||||
return this.partnerRepository.findAndCount({
|
return this.partnerRepository.findAndCount({
|
||||||
skip: page * (pageSize || 10),
|
skip: page * (pageSize || 10),
|
||||||
|
|
|
@ -19,6 +19,6 @@ import { UserDetail } from './entities/user_detail.entity';
|
||||||
],
|
],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
providers: [UsersService, SupplierService, PartnerService],
|
providers: [UsersService, SupplierService, PartnerService],
|
||||||
exports: [UsersService, SupplierService],
|
exports: [UsersService, SupplierService, PartnerService],
|
||||||
})
|
})
|
||||||
export class UsersModule {}
|
export class UsersModule {}
|
||||||
|
|
|
@ -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 { CreateUserDto } from './dto/create-user.dto';
|
||||||
import { UpdateUserDto } from './dto/update-user.dto';
|
import { UpdateUserDto } from './dto/update-user.dto';
|
||||||
import { Connection, EntityNotFoundError, Not, Repository } from 'typeorm';
|
import { Connection, EntityNotFoundError, Not, Repository } from 'typeorm';
|
||||||
|
@ -383,6 +389,7 @@ export class UsersService {
|
||||||
return this.usersRepository.findOneOrFail({
|
return this.usersRepository.findOneOrFail({
|
||||||
where: {
|
where: {
|
||||||
username,
|
username,
|
||||||
|
isActive: true,
|
||||||
},
|
},
|
||||||
relations: ['roles', 'partner'],
|
relations: ['roles', 'partner'],
|
||||||
});
|
});
|
||||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -2110,6 +2110,13 @@ cssstyle@^2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cssom "~0.3.6"
|
cssom "~0.3.6"
|
||||||
|
|
||||||
|
csv-parser@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/csv-parser/-/csv-parser-3.0.0.tgz#b88a6256d79e090a97a1b56451f9327b01d710e7"
|
||||||
|
integrity sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==
|
||||||
|
dependencies:
|
||||||
|
minimist "^1.2.0"
|
||||||
|
|
||||||
data-urls@^2.0.0:
|
data-urls@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
|
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
|
||||||
|
@ -2867,6 +2874,11 @@ fs.realpath@^1.0.0:
|
||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
|
fs@^0.0.1-security:
|
||||||
|
version "0.0.1-security"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
|
||||||
|
integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ=
|
||||||
|
|
||||||
fsevents@^2.3.2, fsevents@~2.3.2:
|
fsevents@^2.3.2, fsevents@~2.3.2:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user