add: parser upload product

This commit is contained in:
ilham 2021-12-22 22:56:44 +07:00
parent 97bcf40ac4
commit 3f57e574a6
12 changed files with 181 additions and 10 deletions

View File

@ -35,7 +35,9 @@
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"crypto": "^1.0.1",
"csv-parser": "^3.0.0",
"decimal.js": "^10.3.1",
"fs": "^0.0.1-security",
"fs-extra": "^10.0.0",
"joi": "^17.4.2",
"lodash": "^4.17.21",

28
src/helper/csv-parser.ts Normal file
View 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;
}

View File

@ -105,6 +105,14 @@ export class ProductSubCategoriesService {
}
}
async findOneForCSVParser(code: string) {
return await this.productSubCategoriesRepository.findOne({
where: {
code: code,
},
});
}
async update(
id: string,
updateCategoriesProductDto: UpdateSubCategoriesProductDto,

View File

@ -92,10 +92,7 @@ export class ProductController {
@Get('test')
async test(@Request() req) {
const data = await this.productHistoryPriceService.findOne(
'4d3b328c-3ce4-4c84-84bb-cd9c36e85a45',
'27effb3e-0351-428a-ba7f-08a21c54e16a',
);
const data = await this.productService.processUploadCSV();
return {
data,

View File

@ -1,5 +1,5 @@
import { HttpException, HttpStatus } from '@nestjs/common';
import { EntityNotFoundError, Repository } from 'typeorm';
import { EntityNotFoundError, IsNull, Repository } from 'typeorm';
import { Product } from './entities/product.entity';
import { InjectRepository } from '@nestjs/typeorm';
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 { UsersService } from '../users/users.service';
import { SupplierService } from '../users/supplier/supplier.service';
import { parsingFile } from '../helper/csv-parser';
import { PartnerService } from '../users/partner/partner.service';
export class ProductService {
constructor(
@ -20,6 +22,7 @@ export class ProductService {
private productSubCategoriesService: ProductSubCategoriesService,
private usersService: UsersService,
private supplierService: SupplierService,
private partnerService: PartnerService,
) {}
async create(createProductDto: CreateProductDto) {
@ -47,6 +50,83 @@ export class ProductService {
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(
page: number,
supplier: string,

View File

@ -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 { DistributeTransactionDto } from './dto/distribute-transaction.dto';
import { OrderTransactionDto } from './dto/order-transaction.dto';

View File

@ -10,6 +10,9 @@ export class CreatePartnerDto {
@IsNotEmpty()
owner: string;
@IsNotEmpty()
code: string;
@IsNotEmpty()
npwp: string;

View File

@ -11,6 +11,11 @@ export class Partner extends BaseModel {
@Column()
name: string;
@Column({
nullable: true,
})
code: string;
@Column()
npwp: string;

View File

@ -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 { Connection, Not, Repository } from 'typeorm';
import { Connection, EntityNotFoundError, Not, Repository } from 'typeorm';
import { CoaService } from '../../transaction/coa.service';
import { CreatePartnerDto } from '../dto/create-partner.dto';
import { Partner } from '../entities/partner.entity';
@ -9,6 +15,7 @@ import { UsersService } from '../users.service';
import { CreateUserDto } from '../dto/create-user.dto';
import { UpdatePartnerDto } from '../dto/update-partner.dto';
import { UpdateUserDto } from '../dto/update-user.dto';
import { when } from 'joi';
@Injectable()
export class PartnerService {
@ -41,10 +48,12 @@ export class PartnerService {
}
const partnerData = new Partner();
partnerData.id = uuid.v4();
partnerData.name = createPartnerDto.name;
partnerData.npwp = createPartnerDto.npwp;
partnerData.address = createPartnerDto.address;
partnerData.code = createPartnerDto.code;
partnerData.status = true;
await this.connection.transaction(async (manager) => {
@ -52,6 +61,7 @@ export class PartnerService {
});
const dataUser = new CreateUserDto();
dataUser.username = `admin_${partnerData.name}`;
dataUser.name = partnerData.name;
dataUser.phone_number = partnerData.phone_number;
@ -129,6 +139,14 @@ export class PartnerService {
return partnerData;
};
async findOne(code: string) {
return await this.partnerRepository.findOne({
where: {
code: code,
},
});
}
findAllPartner(page, pageSize?) {
return this.partnerRepository.findAndCount({
skip: page * (pageSize || 10),

View File

@ -19,6 +19,6 @@ import { UserDetail } from './entities/user_detail.entity';
],
controllers: [UsersController],
providers: [UsersService, SupplierService, PartnerService],
exports: [UsersService, SupplierService],
exports: [UsersService, SupplierService, PartnerService],
})
export class UsersModule {}

View File

@ -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';
@ -383,6 +389,7 @@ export class UsersService {
return this.usersRepository.findOneOrFail({
where: {
username,
isActive: true,
},
relations: ['roles', 'partner'],
});

View File

@ -2110,6 +2110,13 @@ cssstyle@^2.3.0:
dependencies:
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:
version "2.0.0"
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"
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:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"