Merge branch 'development' into 'devops-staging'
Development See merge request empatnusabangsa/ppob/ppob-backend!16
This commit is contained in:
commit
02be8ac43e
|
@ -28,6 +28,7 @@ export class AuthService {
|
|||
username: user.username,
|
||||
sub: user.id,
|
||||
role: user.roles.name,
|
||||
partner: user.partner.id,
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
48
src/configurable/commission.service.ts
Normal file
48
src/configurable/commission.service.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { EntityNotFoundError, Repository } from 'typeorm';
|
||||
import { Roles } from './entities/roles.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { UpdateUserDto } from '../users/dto/update-user.dto';
|
||||
import { CommissionSetting } from './entities/commission_setting.entity';
|
||||
|
||||
@Injectable()
|
||||
export class CommissionService {
|
||||
constructor(
|
||||
@InjectRepository(CommissionSetting)
|
||||
private commissionRepository: Repository<CommissionSetting>,
|
||||
) {}
|
||||
|
||||
findAllRoles(page) {
|
||||
return this.commissionRepository.findAndCount({
|
||||
skip: page * 10,
|
||||
take: 10,
|
||||
order: {
|
||||
version: 'DESC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async updateCommission(id: string, request) {
|
||||
try {
|
||||
await this.commissionRepository.findOneOrFail(id);
|
||||
} catch (e) {
|
||||
if (e instanceof EntityNotFoundError) {
|
||||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Data not found',
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
const result = await this.commissionRepository.update(id, {
|
||||
commission: request.value,
|
||||
});
|
||||
|
||||
return this.commissionRepository.findOneOrFail(id);
|
||||
}
|
||||
}
|
|
@ -11,13 +11,17 @@ import {
|
|||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { RoleService } from './roles.service';
|
||||
import { CommissionService } from './commission.service';
|
||||
|
||||
@Controller({
|
||||
path: 'config',
|
||||
version: '1',
|
||||
})
|
||||
export class ConfigurableController {
|
||||
constructor(private readonly roleService: RoleService) {}
|
||||
constructor(
|
||||
private readonly roleService: RoleService,
|
||||
private readonly commissionService: CommissionService,
|
||||
) {}
|
||||
|
||||
@Get('/roles')
|
||||
async findAll(@Query('page') page: number) {
|
||||
|
@ -31,6 +35,18 @@ export class ConfigurableController {
|
|||
};
|
||||
}
|
||||
|
||||
@Get('/commission')
|
||||
async findCommission(@Query('page') page: number) {
|
||||
const [data, count] = await this.commissionService.findAllRoles(page);
|
||||
|
||||
return {
|
||||
data,
|
||||
count,
|
||||
statusCode: HttpStatus.OK,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@Param('id', ParseUUIDPipe) id: string) {
|
||||
return {
|
||||
|
@ -39,4 +55,16 @@ export class ConfigurableController {
|
|||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Put('/commission/:id')
|
||||
async updateCommission(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() request,
|
||||
) {
|
||||
return {
|
||||
data: await this.commissionService.updateCommission(id, request),
|
||||
statusCode: HttpStatus.OK,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
|||
import { Roles } from './entities/roles.entity';
|
||||
import { ConfigurableController } from './configurable.controller';
|
||||
import { RoleService } from './roles.service';
|
||||
import { CommissionService } from './commission.service';
|
||||
import { CommissionSetting } from './entities/commission_setting.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Roles])],
|
||||
imports: [TypeOrmModule.forFeature([Roles, CommissionSetting])],
|
||||
controllers: [ConfigurableController],
|
||||
providers: [RoleService],
|
||||
exports: [RoleService]
|
||||
providers: [RoleService, CommissionService],
|
||||
exports: [RoleService],
|
||||
})
|
||||
export class ConfigurableModule {}
|
||||
|
|
16
src/configurable/entities/commission_setting.entity.ts
Normal file
16
src/configurable/entities/commission_setting.entity.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { Entity, Column, OneToOne, JoinColumn } from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { Roles } from './roles.entity';
|
||||
|
||||
@Entity()
|
||||
export class CommissionSetting extends BaseModel {
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
commission: number;
|
||||
|
||||
@OneToOne(() => Roles)
|
||||
@JoinColumn()
|
||||
role: Roles;
|
||||
}
|
|
@ -28,7 +28,7 @@ export class RoleService {
|
|||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Data not found',
|
||||
error: 'Data Role not found',
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
|
|
|
@ -24,10 +24,17 @@ export enum coaType {
|
|||
BANK,
|
||||
EXPENSE,
|
||||
ACCOUNT_RECEIVABLE,
|
||||
ACCOUNT_PAYABLE
|
||||
ACCOUNT_PAYABLE,
|
||||
BUDGET,
|
||||
CONTRA_BUDGET,
|
||||
}
|
||||
|
||||
export enum balanceType {
|
||||
DEBIT,
|
||||
CREDIT,
|
||||
}
|
||||
|
||||
export enum accountType {
|
||||
PARTNER,
|
||||
CUSTOMER,
|
||||
}
|
||||
|
|
|
@ -18,4 +18,7 @@ export class CreateProductDto {
|
|||
|
||||
@IsUUID()
|
||||
subCategoriesId: string;
|
||||
|
||||
@IsUUID()
|
||||
supplierId: string;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
|
|||
import { Product } from './product.entity';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { productType } from '../../helper/enum-list';
|
||||
import { User } from '../../users/entities/user.entity';
|
||||
|
||||
@Entity()
|
||||
export class ProductHistoryPrice extends BaseModel {
|
||||
|
@ -11,6 +12,9 @@ export class ProductHistoryPrice extends BaseModel {
|
|||
@ManyToOne(() => Product, (product) => product.id)
|
||||
product: Product;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.id)
|
||||
user: User;
|
||||
|
||||
@Column()
|
||||
price: number;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from 'typeorm';
|
||||
import { ProductSubCategories } from './product-sub-category.entity';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { Supplier } from '../../users/entities/supplier.entity';
|
||||
|
||||
@Entity()
|
||||
export class Product extends BaseModel {
|
||||
|
@ -43,4 +44,14 @@ export class Product extends BaseModel {
|
|||
},
|
||||
)
|
||||
sub_categories: ProductSubCategories;
|
||||
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Supplier;
|
||||
},
|
||||
(partner) => {
|
||||
return partner.id;
|
||||
},
|
||||
)
|
||||
supplier: Supplier;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
forwardRef,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { EntityNotFoundError, Repository } from 'typeorm';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { COA } from './entities/coa.entity';
|
||||
|
@ -10,24 +16,40 @@ export class CoaService {
|
|||
constructor(
|
||||
@InjectRepository(COA)
|
||||
private coaRepository: Repository<COA>,
|
||||
@Inject(forwardRef(() => UsersService))
|
||||
@Inject(
|
||||
forwardRef(() => {
|
||||
return UsersService;
|
||||
}),
|
||||
)
|
||||
private userService: UsersService,
|
||||
) {}
|
||||
|
||||
async create(inputCoaDto: InputCoaDto) {
|
||||
const user = inputCoaDto.user
|
||||
let coaData = new COA();
|
||||
coaData.user = user.id;
|
||||
coaData.name = coaType[inputCoaDto.type] + '-' + user.username;
|
||||
const coaData = new COA();
|
||||
let name = '';
|
||||
if (inputCoaDto.user) {
|
||||
coaData.user = inputCoaDto.user.id;
|
||||
name = inputCoaDto.user.username;
|
||||
}
|
||||
|
||||
if (inputCoaDto.supplier) {
|
||||
coaData.supplier = inputCoaDto.supplier.id;
|
||||
name = inputCoaDto.supplier.code;
|
||||
}
|
||||
|
||||
coaData.name = `${coaType[inputCoaDto.type]}-${name}`;
|
||||
coaData.balanceType = inputCoaDto.balanceType;
|
||||
coaData.type = inputCoaDto.type;
|
||||
coaData.amount = 0;
|
||||
|
||||
const result = await inputCoaDto.coaEntityManager.insert(COA, coaData);
|
||||
|
||||
if(inputCoaDto.type == coaType.ACCOUNT_RECEIVABLE || inputCoaDto.type == coaType.ACCOUNT_PAYABLE){
|
||||
if (
|
||||
inputCoaDto.type == coaType.ACCOUNT_RECEIVABLE ||
|
||||
inputCoaDto.type == coaType.ACCOUNT_PAYABLE
|
||||
) {
|
||||
coaData.relatedUser = inputCoaDto.relatedUserId;
|
||||
await inputCoaDto.coaEntityManager.save(coaData)
|
||||
await inputCoaDto.coaEntityManager.save(coaData);
|
||||
}
|
||||
|
||||
return coaData;
|
||||
|
@ -35,7 +57,10 @@ export class CoaService {
|
|||
|
||||
async findByUser(id: string, typeOfCoa: coaType) {
|
||||
try {
|
||||
return await this.coaRepository.findOneOrFail({ user: id, type: typeOfCoa });
|
||||
return await this.coaRepository.findOneOrFail({
|
||||
user: id,
|
||||
type: typeOfCoa,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof EntityNotFoundError) {
|
||||
throw new HttpException(
|
||||
|
@ -51,9 +76,17 @@ export class CoaService {
|
|||
}
|
||||
}
|
||||
|
||||
async findByUserWithRelated(id: string, relatedId: string, typeOfCoa: coaType) {
|
||||
async findByUserWithRelated(
|
||||
id: string,
|
||||
relatedId: string,
|
||||
typeOfCoa: coaType,
|
||||
) {
|
||||
try {
|
||||
return await this.coaRepository.findOneOrFail({ user: id, type: typeOfCoa, relatedUser:relatedId });
|
||||
return await this.coaRepository.findOneOrFail({
|
||||
user: id,
|
||||
type: typeOfCoa,
|
||||
relatedUser: relatedId,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof EntityNotFoundError) {
|
||||
throw new HttpException(
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
import { balanceType, coaType, statusTransaction, typeTransaction } from 'src/helper/enum-list';
|
||||
import {
|
||||
balanceType,
|
||||
coaType,
|
||||
statusTransaction,
|
||||
typeTransaction,
|
||||
} from 'src/helper/enum-list';
|
||||
import { EntityManager } from 'typeorm';
|
||||
|
||||
|
||||
export class AddSaldoSupplier {
|
||||
@IsNotEmpty()
|
||||
supplier?: string;
|
||||
supplier: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
amount?: number;
|
||||
amount: number;
|
||||
}
|
||||
|
|
|
@ -6,4 +6,7 @@ export class DistributeTransactionDto {
|
|||
|
||||
@IsNotEmpty()
|
||||
destination: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
supplier: string;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { IsNotEmpty, IsUUID } from 'class-validator';
|
|||
import { balanceType, coaType } from 'src/helper/enum-list';
|
||||
import { User } from 'src/users/entities/user.entity';
|
||||
import { EntityManager } from 'typeorm';
|
||||
import { Supplier } from '../../users/entities/supplier.entity';
|
||||
|
||||
export class InputCoaDto {
|
||||
@IsUUID()
|
||||
|
@ -16,6 +17,9 @@ export class InputCoaDto {
|
|||
@IsUUID()
|
||||
relatedUserId: string;
|
||||
|
||||
@IsUUID()
|
||||
supplier: Supplier;
|
||||
|
||||
@IsNotEmpty()
|
||||
coaEntityManager: EntityManager;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import {
|
||||
Entity,
|
||||
Column,
|
||||
} from 'typeorm';
|
||||
import { Entity, Column } from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { coaType, balanceType } from '../../helper/enum-list';
|
||||
|
||||
|
@ -19,11 +16,18 @@ export class COA extends BaseModel {
|
|||
@Column()
|
||||
amount: number;
|
||||
|
||||
@Column()
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
user: string;
|
||||
|
||||
@Column({
|
||||
nullable:true
|
||||
nullable: true,
|
||||
})
|
||||
relatedUser: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
supplier: string;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { COA } from './coa.entity';
|
||||
import { Transactions } from './transactions.entity';
|
||||
import { TransactionType } from './transaction-type.entity';
|
||||
import { balanceType } from '../../helper/enum-list';
|
||||
|
||||
@Entity()
|
||||
|
@ -20,15 +19,15 @@ export class TransactionJournal extends BaseModel {
|
|||
@Column()
|
||||
amount: number;
|
||||
|
||||
@OneToOne(
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Transactions;
|
||||
},
|
||||
(trans) => {
|
||||
return trans.id;
|
||||
(transaction) => {
|
||||
return transaction.id;
|
||||
},
|
||||
)
|
||||
transaction: Transactions;
|
||||
transaction_head: Transactions;
|
||||
|
||||
@ManyToOne(
|
||||
() => {
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import {
|
||||
Entity,
|
||||
Column,
|
||||
} from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
|
||||
@Entity()
|
||||
export class TransactionType extends BaseModel {
|
||||
@Column()
|
||||
name: string;
|
||||
}
|
|
@ -54,7 +54,7 @@ export class TransactionController {
|
|||
@Request() req,
|
||||
) {
|
||||
return {
|
||||
data: await this.transactionService.addIRSWallet(
|
||||
data: await this.transactionService.addPartnerSaldo(
|
||||
addSaldoSupplier,
|
||||
req.user,
|
||||
),
|
||||
|
|
|
@ -4,7 +4,6 @@ import { TransactionController } from './transaction.controller';
|
|||
import { PpobCallbackController } from './ppob_callback.controller';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { COA } from './entities/coa.entity';
|
||||
import { TransactionType } from './entities/transaction-type.entity';
|
||||
import { TransactionJournal } from './entities/transaction-journal.entity';
|
||||
import { Transactions } from './entities/transactions.entity';
|
||||
import { CoaService } from './coa.service';
|
||||
|
@ -13,17 +12,12 @@ import { UsersModule } from 'src/users/users.module';
|
|||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([
|
||||
TransactionType,
|
||||
COA,
|
||||
TransactionJournal,
|
||||
Transactions,
|
||||
]),
|
||||
TypeOrmModule.forFeature([COA, TransactionJournal, Transactions]),
|
||||
ProductModule,
|
||||
forwardRef(() => UsersModule),
|
||||
],
|
||||
controllers: [TransactionController, PpobCallbackController],
|
||||
providers: [TransactionService, CoaService],
|
||||
exports:[CoaService]
|
||||
exports: [CoaService],
|
||||
})
|
||||
export class TransactionModule {}
|
||||
|
|
|
@ -5,7 +5,6 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||
import { Transactions } from './entities/transactions.entity';
|
||||
import { Connection, EntityManager, Repository } from 'typeorm';
|
||||
import { COA } from './entities/coa.entity';
|
||||
import { TransactionType } from './entities/transaction-type.entity';
|
||||
import { TransactionJournal } from './entities/transaction-journal.entity';
|
||||
import { CoaService } from './coa.service';
|
||||
import * as uuid from 'uuid';
|
||||
|
@ -22,6 +21,7 @@ import * as irsService from '../helper/irs-service';
|
|||
import { CreateJournalDto } from './dto/create-journal.dto';
|
||||
import { UsersService } from 'src/users/users.service';
|
||||
import { AddSaldoSupplier } from './dto/add-saldo-supplier.dto';
|
||||
import { SupplierService } from '../users/supplier/supplier.service';
|
||||
|
||||
interface JournalEntry {
|
||||
coa_id: string;
|
||||
|
@ -34,8 +34,6 @@ export class TransactionService {
|
|||
constructor(
|
||||
@InjectRepository(Transactions)
|
||||
private transactionRepository: Repository<Transactions>,
|
||||
@InjectRepository(TransactionType)
|
||||
private transactionTypeRepository: Repository<TransactionType>,
|
||||
@InjectRepository(TransactionJournal)
|
||||
private transactionJournalRepository: Repository<TransactionJournal>,
|
||||
@InjectRepository(COA)
|
||||
|
@ -43,17 +41,29 @@ export class TransactionService {
|
|||
private coaService: CoaService,
|
||||
private productService: ProductService,
|
||||
private userService: UsersService,
|
||||
private supplierService: SupplierService,
|
||||
private connection: Connection,
|
||||
) {}
|
||||
|
||||
async addIRSWallet(addSaldoSupplier: AddSaldoSupplier, currentUser: any) {
|
||||
async addPartnerSaldo(addSaldoSupplier: AddSaldoSupplier, currentUser: any) {
|
||||
const supplier = await this.supplierService.findByCode(
|
||||
addSaldoSupplier.supplier,
|
||||
);
|
||||
// GET COA
|
||||
const coaBank = await this.coaService.findByName(
|
||||
`${coaType[coaType.BANK]}-SYSTEM`,
|
||||
);
|
||||
|
||||
const coaInventory = await this.coaService.findByName(
|
||||
`${coaType[coaType.INVENTORY]}-${addSaldoSupplier.supplier}`,
|
||||
`${coaType[coaType.INVENTORY]}-${supplier.code}`,
|
||||
);
|
||||
|
||||
const coaBudget = await this.coaService.findByName(
|
||||
`${coaType[coaType.BUDGET]}-${supplier.code}`,
|
||||
);
|
||||
|
||||
const coaContraBudget = await this.coaService.findByName(
|
||||
`${coaType[coaType.CONTRA_BUDGET]}-${supplier.code}`,
|
||||
);
|
||||
|
||||
//GET USER
|
||||
|
@ -81,10 +91,18 @@ export class TransactionService {
|
|||
journals: [
|
||||
{
|
||||
coa_id: coaBank.id,
|
||||
debit: transactionData.amount,
|
||||
credit: transactionData.amount,
|
||||
},
|
||||
{
|
||||
coa_id: coaInventory.id,
|
||||
debit: transactionData.amount,
|
||||
},
|
||||
{
|
||||
coa_id: coaBudget.id,
|
||||
debit: transactionData.amount,
|
||||
},
|
||||
{
|
||||
coa_id: coaContraBudget.id,
|
||||
credit: transactionData.amount,
|
||||
},
|
||||
],
|
||||
|
@ -98,6 +116,25 @@ export class TransactionService {
|
|||
distributeTransactionDto: DistributeTransactionDto,
|
||||
currentUser: any,
|
||||
) {
|
||||
//GET USER
|
||||
const userData = await this.userService.findByUsername(
|
||||
currentUser.username,
|
||||
);
|
||||
if (userData.roles.name != 'Admin') {
|
||||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_ACCEPTABLE,
|
||||
error: 'Roles Not Admin',
|
||||
},
|
||||
HttpStatus.NOT_ACCEPTABLE,
|
||||
);
|
||||
}
|
||||
|
||||
//GET Supplier
|
||||
const supplier = await this.supplierService.findByCode(
|
||||
distributeTransactionDto.supplier,
|
||||
);
|
||||
|
||||
// GET COA
|
||||
const coaAR = await this.coaService.findByUser(
|
||||
distributeTransactionDto.destination,
|
||||
|
@ -107,10 +144,12 @@ export class TransactionService {
|
|||
distributeTransactionDto.destination,
|
||||
coaType.WALLET,
|
||||
);
|
||||
const coaBudget = await this.coaService.findByName(
|
||||
`${coaType[coaType.BUDGET]}-${supplier.code}`,
|
||||
);
|
||||
|
||||
//GET USER
|
||||
const userData = await this.userService.findByUsername(
|
||||
currentUser.username,
|
||||
const coaContraBudget = await this.coaService.findByName(
|
||||
`${coaType[coaType.CONTRA_BUDGET]}-${supplier.code}`,
|
||||
);
|
||||
|
||||
await this.connection.transaction(async (manager) => {
|
||||
|
@ -139,6 +178,14 @@ export class TransactionService {
|
|||
coa_id: coaWallet.id,
|
||||
credit: transactionData.amount,
|
||||
},
|
||||
{
|
||||
coa_id: coaBudget.id,
|
||||
credit: transactionData.amount,
|
||||
},
|
||||
{
|
||||
coa_id: coaContraBudget.id,
|
||||
debit: transactionData.amount,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -394,9 +441,9 @@ export class TransactionService {
|
|||
? balanceType.DEBIT
|
||||
: balanceType.CREDIT;
|
||||
journalEntry.amount = journal.debit ? journal.debit : journal.credit;
|
||||
journalEntry.transaction = transaction;
|
||||
journalEntry.transaction_head = transaction;
|
||||
|
||||
return this.transactionJournalRepository.save(journalEntry);
|
||||
return createJournalDto.transactionalEntityManager.save(journalEntry);
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -432,15 +479,12 @@ export class TransactionService {
|
|||
);
|
||||
|
||||
let balance = new Decimal(coa.amount);
|
||||
|
||||
if (coa.balanceType === balanceType.DEBIT) {
|
||||
if (coa.balanceType == balanceType.DEBIT) {
|
||||
balance = balance.plus(debitSum.minus(creditSum));
|
||||
} else if (coa.balanceType === balanceType.CREDIT) {
|
||||
} else if (coa.balanceType == balanceType.CREDIT) {
|
||||
balance = balance.plus(creditSum.minus(debitSum));
|
||||
}
|
||||
|
||||
const diff = balance.minus(new Decimal(coa.amount));
|
||||
|
||||
return createJournalDto.transactionalEntityManager
|
||||
.createQueryBuilder()
|
||||
.update(COA)
|
||||
|
|
18
src/users/dto/create-partner.dto.ts
Normal file
18
src/users/dto/create-partner.dto.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class CreatePartnerDto {
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
address: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
owner: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
npwp: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
password_account: string;
|
||||
}
|
9
src/users/dto/create-supplier.dto.ts
Normal file
9
src/users/dto/create-supplier.dto.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class CreateSupplierDto {
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
code: string;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { IsNotEmpty, IsOptional, IsUUID, ValidateIf } from 'class-validator';
|
||||
import { Partner } from '../entities/partner.entity';
|
||||
|
||||
export class CreateUserDto {
|
||||
@IsNotEmpty()
|
||||
|
@ -13,6 +14,7 @@ export class CreateUserDto {
|
|||
@IsNotEmpty()
|
||||
superior: boolean;
|
||||
|
||||
partner: Partner;
|
||||
// @ValidateIf((o) => {
|
||||
// return !!o.superior;
|
||||
// })
|
||||
|
|
22
src/users/entities/partner.entity.ts
Normal file
22
src/users/entities/partner.entity.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Roles } from 'src/configurable/entities/roles.entity';
|
||||
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { hashPassword } from '../../helper/hash_password';
|
||||
|
||||
@Entity()
|
||||
export class Partner extends BaseModel {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
npwp: string;
|
||||
|
||||
@Column()
|
||||
address: string;
|
||||
|
||||
@Column({ default: true })
|
||||
status: boolean;
|
||||
}
|
19
src/users/entities/supplier.entity.ts
Normal file
19
src/users/entities/supplier.entity.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Roles } from 'src/configurable/entities/roles.entity';
|
||||
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { hashPassword } from '../../helper/hash_password';
|
||||
|
||||
@Entity()
|
||||
export class Supplier extends BaseModel {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
code: string;
|
||||
|
||||
@Column()
|
||||
status: boolean;
|
||||
}
|
|
@ -2,6 +2,7 @@ import { Roles } from 'src/configurable/entities/roles.entity';
|
|||
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
|
||||
import { BaseModel } from '../../config/basemodel.entity';
|
||||
import { hashPassword } from '../../helper/hash_password';
|
||||
import { Partner } from './partner.entity';
|
||||
|
||||
@Entity()
|
||||
export class User extends BaseModel {
|
||||
|
@ -39,4 +40,14 @@ export class User extends BaseModel {
|
|||
},
|
||||
)
|
||||
roles: Roles;
|
||||
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Partner;
|
||||
},
|
||||
(partner) => {
|
||||
return partner.id;
|
||||
},
|
||||
)
|
||||
partner: Partner;
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
import {
|
||||
Entity,
|
||||
Column,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
DeleteDateColumn,
|
||||
VersionColumn,
|
||||
CreateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
firstName: string;
|
||||
}
|
22
src/users/entities/user_detail.entity.ts
Normal file
22
src/users/entities/user_detail.entity.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { accountType } from '../../helper/enum-list';
|
||||
|
||||
@Entity()
|
||||
export class UserDetail {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
first_name: string;
|
||||
|
||||
@Column()
|
||||
phone_number: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
type: accountType;
|
||||
}
|
18
src/users/partner/partner.service.spec.ts
Normal file
18
src/users/partner/partner.service.spec.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PartnerService } from './partner.service';
|
||||
|
||||
describe('PartnerService', () => {
|
||||
let service: PartnerService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [PartnerService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<PartnerService>(PartnerService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
79
src/users/partner/partner.service.ts
Normal file
79
src/users/partner/partner.service.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
import {
|
||||
forwardRef,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Connection, EntityNotFoundError, Repository } from 'typeorm';
|
||||
import { CoaService } from '../../transaction/coa.service';
|
||||
import { CreatePartnerDto } from '../dto/create-partner.dto';
|
||||
import { Partner } from '../entities/partner.entity';
|
||||
import * as uuid from 'uuid';
|
||||
import { UsersService } from '../users.service';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
|
||||
@Injectable()
|
||||
export class PartnerService {
|
||||
constructor(
|
||||
@InjectRepository(Partner)
|
||||
private partnerRepository: Repository<Partner>,
|
||||
@Inject(
|
||||
forwardRef(() => {
|
||||
return CoaService;
|
||||
}),
|
||||
)
|
||||
private coaService: CoaService,
|
||||
private userService: UsersService,
|
||||
private connection: Connection,
|
||||
) {}
|
||||
|
||||
async create(createPartnerDto: CreatePartnerDto, currentUser: any) {
|
||||
const check = await this.partnerRepository.findOne({
|
||||
npwp: createPartnerDto.npwp,
|
||||
});
|
||||
|
||||
if (check) {
|
||||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_ACCEPTABLE,
|
||||
error: 'N Already Exist',
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const partnerData = new Partner();
|
||||
partnerData.id = uuid.v4();
|
||||
partnerData.name = createPartnerDto.name;
|
||||
partnerData.npwp = createPartnerDto.npwp;
|
||||
partnerData.address = createPartnerDto.address;
|
||||
partnerData.status = true;
|
||||
|
||||
await this.connection.transaction(async (manager) => {
|
||||
const result = await manager.insert(Partner, partnerData);
|
||||
});
|
||||
|
||||
const dataUser = new CreateUserDto();
|
||||
dataUser.username = `admin_${partnerData.name}`;
|
||||
dataUser.roleId = '21dceea2-416e-4b55-b74c-12605e1f8d1b';
|
||||
dataUser.superior = false;
|
||||
dataUser.partner = partnerData;
|
||||
dataUser.password = createPartnerDto.password_account;
|
||||
|
||||
await this.userService.create(dataUser, currentUser);
|
||||
|
||||
return partnerData;
|
||||
}
|
||||
|
||||
findAllPartner(page) {
|
||||
return this.partnerRepository.findAndCount({
|
||||
skip: page * 10,
|
||||
take: 10,
|
||||
order: {
|
||||
version: 'DESC',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
18
src/users/supplier/supplier.service.spec.ts
Normal file
18
src/users/supplier/supplier.service.spec.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { SupplierService } from './supplier.service';
|
||||
|
||||
describe('PartnerService', () => {
|
||||
let service: SupplierService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [SupplierService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<SupplierService>(SupplierService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
116
src/users/supplier/supplier.service.ts
Normal file
116
src/users/supplier/supplier.service.ts
Normal file
|
@ -0,0 +1,116 @@
|
|||
import {
|
||||
forwardRef,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Connection, EntityNotFoundError, Repository } from 'typeorm';
|
||||
import { Supplier } from '../entities/supplier.entity';
|
||||
import { InputCoaDto } from '../../transaction/dto/input-coa.dto';
|
||||
import { balanceType, coaType } from '../../helper/enum-list';
|
||||
import { CreateSupplierDto } from '../dto/create-supplier.dto';
|
||||
import { CoaService } from '../../transaction/coa.service';
|
||||
import * as uuid from 'uuid';
|
||||
|
||||
@Injectable()
|
||||
export class SupplierService {
|
||||
constructor(
|
||||
@InjectRepository(Supplier)
|
||||
private supplierRepository: Repository<Supplier>,
|
||||
@Inject(
|
||||
forwardRef(() => {
|
||||
return CoaService;
|
||||
}),
|
||||
)
|
||||
private coaService: CoaService,
|
||||
private connection: Connection,
|
||||
) {}
|
||||
|
||||
async create(createSupplierDto: CreateSupplierDto) {
|
||||
const check = await this.supplierRepository.findOne({
|
||||
code: createSupplierDto.code,
|
||||
});
|
||||
|
||||
if (check) {
|
||||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_ACCEPTABLE,
|
||||
error: 'Supplier Already Exist',
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const supplierData = new Supplier();
|
||||
supplierData.id = uuid.v4();
|
||||
supplierData.name = createSupplierDto.name;
|
||||
supplierData.code = createSupplierDto.code;
|
||||
supplierData.status = true;
|
||||
|
||||
await this.connection.transaction(async (manager) => {
|
||||
const result = await manager.insert(Supplier, supplierData);
|
||||
|
||||
const dataCoaInventory = new InputCoaDto();
|
||||
dataCoaInventory.supplier = supplierData;
|
||||
dataCoaInventory.balanceType = balanceType.DEBIT;
|
||||
dataCoaInventory.type = coaType.INVENTORY;
|
||||
dataCoaInventory.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaInventory);
|
||||
|
||||
const dataCoaCostOfSales = new InputCoaDto();
|
||||
dataCoaCostOfSales.supplier = supplierData;
|
||||
dataCoaCostOfSales.balanceType = balanceType.DEBIT;
|
||||
dataCoaCostOfSales.type = coaType.COST_OF_SALES;
|
||||
dataCoaCostOfSales.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaCostOfSales);
|
||||
|
||||
const dataCoaBudget = new InputCoaDto();
|
||||
dataCoaBudget.supplier = supplierData;
|
||||
dataCoaBudget.balanceType = balanceType.DEBIT;
|
||||
dataCoaBudget.type = coaType.BUDGET;
|
||||
dataCoaBudget.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaBudget);
|
||||
|
||||
const dataCoaContraBudget = new InputCoaDto();
|
||||
dataCoaContraBudget.supplier = supplierData;
|
||||
dataCoaContraBudget.balanceType = balanceType.CREDIT;
|
||||
dataCoaContraBudget.type = coaType.CONTRA_BUDGET;
|
||||
dataCoaContraBudget.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaContraBudget);
|
||||
});
|
||||
|
||||
return supplierData;
|
||||
}
|
||||
|
||||
findAllSupplier(page) {
|
||||
return this.supplierRepository.findAndCount({
|
||||
skip: page * 10,
|
||||
take: 10,
|
||||
order: {
|
||||
version: 'DESC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findByCode(code: string) {
|
||||
try {
|
||||
return await this.supplierRepository.findOneOrFail({
|
||||
code: code,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof EntityNotFoundError) {
|
||||
throw new HttpException(
|
||||
{
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Data not found',
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,13 +15,21 @@ import { UsersService } from './users.service';
|
|||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { Public } from '../auth/public.decorator';
|
||||
import { CreateSupplierDto } from './dto/create-supplier.dto';
|
||||
import { SupplierService } from './supplier/supplier.service';
|
||||
import { PartnerService } from './partner/partner.service';
|
||||
import { CreatePartnerDto } from './dto/create-partner.dto';
|
||||
|
||||
@Controller({
|
||||
path: 'users',
|
||||
version: '1',
|
||||
})
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
constructor(
|
||||
private readonly usersService: UsersService,
|
||||
private readonly supplierService: SupplierService,
|
||||
private readonly partnerService: PartnerService,
|
||||
) {}
|
||||
|
||||
@Post()
|
||||
async create(@Request() req, @Body() createUserDto: CreateUserDto) {
|
||||
|
@ -32,10 +40,58 @@ export class UsersController {
|
|||
};
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Post('supplier')
|
||||
async createSupplier(@Body() createPartnerDto: CreateSupplierDto) {
|
||||
return {
|
||||
data: await this.supplierService.create(createPartnerDto),
|
||||
statusCode: HttpStatus.CREATED,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Post('partner')
|
||||
async createPartner(
|
||||
@Request() req,
|
||||
@Body() createPartnerDto: CreatePartnerDto,
|
||||
) {
|
||||
return {
|
||||
data: await this.partnerService.create(createPartnerDto, req.user),
|
||||
statusCode: HttpStatus.CREATED,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Query('page') page: number) {
|
||||
const [data, count] = await this.usersService.findAll(page);
|
||||
async findAll(@Request() req, @Query('page') page: number) {
|
||||
const [data, count] = await this.usersService.findAll(
|
||||
page,
|
||||
req.user.userId,
|
||||
);
|
||||
|
||||
return {
|
||||
data,
|
||||
count,
|
||||
statusCode: HttpStatus.OK,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Get('supplier')
|
||||
async findAllSupplier(@Query('page') page: number) {
|
||||
const [data, count] = await this.supplierService.findAllSupplier(page);
|
||||
|
||||
return {
|
||||
data,
|
||||
count,
|
||||
statusCode: HttpStatus.OK,
|
||||
message: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@Get('partner')
|
||||
async findAllPartner(@Query('page') page: number) {
|
||||
const [data, count] = await this.partnerService.findAllPartner(page);
|
||||
|
||||
return {
|
||||
data,
|
||||
|
@ -51,6 +107,7 @@ export class UsersController {
|
|||
req.user.userId,
|
||||
page,
|
||||
);
|
||||
|
||||
return {
|
||||
data,
|
||||
count,
|
||||
|
@ -65,6 +122,7 @@ export class UsersController {
|
|||
@Query('page') page: number,
|
||||
) {
|
||||
const [data, count] = await this.usersService.findByRoles(id, page);
|
||||
|
||||
return {
|
||||
data,
|
||||
count,
|
||||
|
|
|
@ -5,11 +5,19 @@ import { UsersController } from './users.controller';
|
|||
import { User } from './entities/user.entity';
|
||||
import { TransactionModule } from 'src/transaction/transaction.module';
|
||||
import { ConfigurableModule } from 'src/configurable/configurable.module';
|
||||
import { SupplierService } from './supplier/supplier.service';
|
||||
import { Supplier } from './entities/supplier.entity';
|
||||
import { Partner } from './entities/partner.entity';
|
||||
import { PartnerService } from './partner/partner.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([User]), forwardRef(() => TransactionModule), ConfigurableModule],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([User, Supplier, Partner]),
|
||||
forwardRef(() => TransactionModule),
|
||||
ConfigurableModule,
|
||||
],
|
||||
controllers: [UsersController],
|
||||
providers: [UsersService],
|
||||
exports: [UsersService],
|
||||
providers: [UsersService, SupplierService, PartnerService],
|
||||
exports: [UsersService, SupplierService],
|
||||
})
|
||||
export class UsersModule {}
|
||||
|
|
|
@ -7,7 +7,13 @@ import {
|
|||
} from '@nestjs/common';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { Connection, EntityNotFoundError, Repository } from 'typeorm';
|
||||
import {
|
||||
Connection,
|
||||
EntityNotFoundError,
|
||||
Equal,
|
||||
Not,
|
||||
Repository,
|
||||
} from 'typeorm';
|
||||
import { User } from './entities/user.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util';
|
||||
|
@ -59,53 +65,56 @@ 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 dataCoaWallet = new InputCoaDto();
|
||||
|
||||
dataCoaWallet.user = userData;
|
||||
dataCoaWallet.balanceType = balanceType.CREDIT;
|
||||
dataCoaWallet.type = coaType.WALLET;
|
||||
dataCoaWallet.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaWallet);
|
||||
|
||||
if (createUserDto.superior) {
|
||||
const dataCoaAP = new InputCoaDto();
|
||||
|
||||
dataCoaAP.user = userData;
|
||||
dataCoaAP.balanceType = balanceType.CREDIT;
|
||||
dataCoaAP.relatedUserId = superior.id;
|
||||
dataCoaAP.type = coaType.ACCOUNT_PAYABLE;
|
||||
dataCoaAP.coaEntityManager = manager;
|
||||
await this.coaService.create(dataCoaAP);
|
||||
|
||||
const dataCoaAR = new InputCoaDto();
|
||||
|
||||
dataCoaAR.user = userData;
|
||||
dataCoaAR.balanceType = balanceType.DEBIT;
|
||||
dataCoaAR.relatedUserId = superior.id;
|
||||
dataCoaAR.type = coaType.ACCOUNT_RECEIVABLE;
|
||||
dataCoaAR.coaEntityManager = manager;
|
||||
|
||||
await this.coaService.create(dataCoaAP);
|
||||
await this.coaService.create(dataCoaAR);
|
||||
}
|
||||
|
||||
await this.coaService.create(dataCoaWallet);
|
||||
});
|
||||
|
||||
return userData;
|
||||
}
|
||||
|
||||
findAll(page: number) {
|
||||
findAll(page: number, id: string) {
|
||||
return this.usersRepository.findAndCount({
|
||||
skip: page * 10,
|
||||
take: 10,
|
||||
order: {
|
||||
version: 'DESC',
|
||||
},
|
||||
where: {
|
||||
id: Not(Equal(id)),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -157,7 +166,10 @@ export class UsersService {
|
|||
async findByUsername(username: string) {
|
||||
try {
|
||||
return await this.usersRepository.findOneOrFail({
|
||||
where: {
|
||||
username: username,
|
||||
},
|
||||
relations: ['roles'],
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof EntityNotFoundError) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user