Merge pull request 'fix/data' (#45) from fix/data into development
continuous-integration/drone/tag Build is passing Details

Reviewed-on: #45
pull/48/head devel_16.0.0
aswin 2024-07-31 11:27:39 +00:00
commit 77d8e7ae1e
49 changed files with 305 additions and 157 deletions

View File

@ -25,7 +25,7 @@ export class RolesGuard extends JWTGuard {
if (isNotAllow) { if (isNotAllow) {
throw new ForbiddenException({ throw new ForbiddenException({
statusCode: 10003, statusCode: 10003,
message: `Forbidden Access, you don't have access to this module!`, message: `Akses Terlarang, anda tidak punya akses ke module ini!`,
error: 'ACCESS_FORBIDDEN', error: 'ACCESS_FORBIDDEN',
}); });
} }

View File

@ -52,7 +52,7 @@ export class PrivilegeService {
if (!moduleKey) { if (!moduleKey) {
throw new ForbiddenException({ throw new ForbiddenException({
statusCode: 10005, statusCode: 10005,
message: `Forbidden Access, access Module is Require!`, message: `Akses Terlarang, anda tidak punya akses ke module ini!`,
error: 'MODULE_KEY_NOT_FOUND', error: 'MODULE_KEY_NOT_FOUND',
}); });
} }

View File

@ -43,9 +43,9 @@ export class CheckDuplicateHelper {
if (data_exists > 0) { if (data_exists > 0) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Entity with ${columnCheck.column} : ${ message: `Gagal! Data dengan ${columnCheck.column} : ${
this.entity[columnCheck.column] this.entity[columnCheck.column]
} already exist`, } telah ada`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -38,7 +38,7 @@ export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
if (!entity) { if (!entity) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${id} not found`, message: `Gagal! data dengan id ${id} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }

View File

@ -44,7 +44,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
if (!entity) { if (!entity) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${id} not found`, message: `Gagal! data dengan id ${id} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }

View File

@ -29,7 +29,7 @@ export abstract class BaseChangePosition<Entity> extends BaseManager {
if (!this.data?.end || this.data.start == this.data?.end) { if (!this.data?.end || this.data.start == this.data?.end) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: 'Please drag to another position', message: 'Gagal! tolong pindahkan ke posisi lain',
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -43,7 +43,7 @@ export abstract class BaseChangePosition<Entity> extends BaseManager {
if (!this.startData) { if (!this.startData) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Entity with id : ${this.data.start} not found`, message: `Gagal! data dengan id : ${this.data.start} tidak ditemukan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -57,7 +57,7 @@ export abstract class BaseChangePosition<Entity> extends BaseManager {
if (!this.endData) { if (!this.endData) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Entity with id : ${this.data.end} not found`, message: `Gagal! data dengan id : ${this.data.end} tidak ditemukan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -23,7 +23,7 @@ export abstract class BaseDeleteManager<Entity> extends BaseManager {
if (!this.data) if (!this.data)
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Data with id ${this.dataId} not found`, message: `Gagal! Data denga id ${this.dataId} tidak ditemukan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });

View File

@ -27,7 +27,7 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
if (!this.oldData) { if (!this.oldData) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${this.dataId} not found`, message: `Gagal! Data denga id ${this.dataId} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }

View File

@ -179,6 +179,6 @@ export const PrivilegePOSConstant = [
menu: 'POS_DISCOUNT_CODE', menu: 'POS_DISCOUNT_CODE',
menu_label: 'Print Receipt', menu_label: 'Print Receipt',
actions: [PrivilegeAction.CREATE], actions: [PrivilegeAction.CREATE],
index: 18, index: 19,
}, },
]; ];

View File

@ -133,7 +133,7 @@ export class LoginManager extends BaseCustomManager<UserEntity> {
throwError() { throwError() {
throw new UnauthorizedException({ throw new UnauthorizedException({
statusCode: HttpStatus.UNAUTHORIZED, statusCode: HttpStatus.UNAUTHORIZED,
message: `Failed! You have entered an invalid username or password`, message: `Gagal! username atau password tidak sesuai`,
error: 'Unauthorized', error: 'Unauthorized',
}); });
} }

View File

@ -45,6 +45,7 @@ export class UserUpdatedHandler
], ],
}) })
.then((item) => { .then((item) => {
if (item.role != 'superadmin') {
const user_privilege_configurations = item[ const user_privilege_configurations = item[
'user_privilege' 'user_privilege'
]?.user_privilege_configurations?.filter( ]?.user_privilege_configurations?.filter(
@ -53,6 +54,7 @@ export class UserUpdatedHandler
Object.assign(item['user_privilege'], { Object.assign(item['user_privilege'], {
user_privilege_configurations: user_privilege_configurations, user_privilege_configurations: user_privilege_configurations,
}); });
}
return item; return item;
}); });
@ -103,7 +105,7 @@ export class UserPrivilegeUpdateHandler
const users = await this.userService const users = await this.userService
.getManyByOptions({ .getManyByOptions({
where: { where: {
user_privilege_id: data.user_privilege_id, user_privilege_id: data.user_privilege_id ?? data.id,
status: STATUS.ACTIVE, status: STATUS.ACTIVE,
}, },
relations: [ relations: [
@ -113,7 +115,6 @@ export class UserPrivilegeUpdateHandler
}) })
.then((items) => { .then((items) => {
return items?.map((item) => { return items?.map((item) => {
console.log(item, 'dsa');
const user_privilege_configurations = item[ const user_privilege_configurations = item[
'user_privilege' 'user_privilege'
]?.user_privilege_configurations?.filter( ]?.user_privilege_configurations?.filter(

View File

@ -16,6 +16,7 @@ export async function sendEmail(receivers, subject) {
let templateName = 'payment-confirmation-bank'; let templateName = 'payment-confirmation-bank';
for (const receiver of receivers) { for (const receiver of receivers) {
try {
if (receiver.payment_type == TransactionPaymentType.MIDTRANS) if (receiver.payment_type == TransactionPaymentType.MIDTRANS)
templateName = 'payment-confirmation-midtrans'; templateName = 'payment-confirmation-midtrans';
@ -41,10 +42,13 @@ export async function sendEmail(receivers, subject) {
smtpTransport.sendMail(emailContext, function (err, data) { smtpTransport.sendMail(emailContext, function (err, data) {
if (err) { if (err) {
console.log(`Error occurs on send to ${receiver.email}`); console.log(err, `Error occurs on send to ${ receiver.email }`);
} else { } else {
console.log(`Email sent to ${ receiver.email }`); console.log(`Email sent to ${ receiver.email }`);
} }
}); });
} catch (error) {
console.log(error, `Error occurs on send to ${ receiver.email }`)
}
} }
} }

View File

@ -24,7 +24,13 @@ export class BatchDeleteItemCategoryManager extends BaseBatchDeleteManager<ItemC
} }
get validateRelations(): validateRelations[] { get validateRelations(): validateRelations[] {
return [{ relation: 'items' }]; return [
{
relation: 'items',
message:
'Gagal! tidak dapat mengubah tipe item karena sudah berelasi dengan item',
},
];
} }
get entityTarget(): any { get entityTarget(): any {

View File

@ -24,7 +24,13 @@ export class BatchInactiveItemCategoryManager extends BaseBatchUpdateStatusManag
} }
get validateRelations(): validateRelations[] { get validateRelations(): validateRelations[] {
return [{ relation: 'items' }]; return [
{
relation: 'items',
message:
'Gagal! tidak dapat mengubah tipe item karena sudah berelasi dengan item',
},
];
} }
get entityTarget(): any { get entityTarget(): any {

View File

@ -27,7 +27,13 @@ export class DeleteItemCategoryManager extends BaseDeleteManager<ItemCategoryEnt
} }
get validateRelations(): validateRelations[] { get validateRelations(): validateRelations[] {
return [{ relation: 'items' }]; return [
{
relation: 'items',
message:
'Gagal! tidak dapat mengubah tipe item karena sudah berelasi dengan item',
},
];
} }
get entityTarget(): any { get entityTarget(): any {

View File

@ -27,7 +27,13 @@ export class InactiveItemCategoryManager extends BaseUpdateStatusManager<ItemCat
} }
get validateRelations(): validateRelations[] { get validateRelations(): validateRelations[] {
return [{ relation: 'items' }]; return [
{
relation: 'items',
message:
'Gagal! tidak dapat mengubah tipe item karena sudah berelasi dengan item',
},
];
} }
get entityTarget(): any { get entityTarget(): any {

View File

@ -27,11 +27,17 @@ export class UpdateItemCategoryManager extends BaseUpdateManager<ItemCategoryEnt
} }
get validateRelations(): validateRelations[] { get validateRelations(): validateRelations[] {
if (this.data.item_type != this.oldData.item_type) {
return [ return [
{ {
relation: 'items', relation: 'items',
message:
'Gagal! tidak dapat mengubah tipe item karena sudah berelasi dengan item',
}, },
]; ];
} else {
return [];
}
} }
get uniqueColumns(): columnUniques[] { get uniqueColumns(): columnUniques[] {

View File

@ -32,6 +32,7 @@ export class SeasonPeriodHolidayHandler
const rate = new ItemRateModel(); const rate = new ItemRateModel();
rate.item_id = event.data.id; rate.item_id = event.data.id;
rate.season_period_id = season.id; rate.season_period_id = season.id;
rate.price = event.data.data.total_price ?? event.data.data.base_price;
rates.push(rate); rates.push(rate);
} }

View File

@ -36,7 +36,7 @@ export class ActiveItemManager extends BaseUpdateStatusManager<ItemEntity> {
{ {
relation: 'tenant', relation: 'tenant',
singleQuery: ['status', '!=', STATUS.ACTIVE], singleQuery: ['status', '!=', STATUS.ACTIVE],
message: `Failed! Tenant of item must be active first`, message: `Gagal! Belum ada item yang aktif`,
}, },
]; ];
} }

View File

@ -33,7 +33,7 @@ export class BatchActiveItemManager extends BaseBatchUpdateStatusManager<ItemEnt
{ {
relation: 'tenant', relation: 'tenant',
singleQuery: ['status', '!=', STATUS.ACTIVE], singleQuery: ['status', '!=', STATUS.ACTIVE],
message: `Failed! Tenant of item must be active first`, message: `Gagal! Belum ada item yang aktif`,
}, },
]; ];
} }

View File

@ -29,7 +29,7 @@ export class BatchConfirmItemManager extends BaseBatchUpdateStatusManager<ItemEn
{ {
relation: 'tenant', relation: 'tenant',
singleQuery: ['status', '!=', STATUS.ACTIVE], singleQuery: ['status', '!=', STATUS.ACTIVE],
message: `Failed! Tenant of item must be active first`, message: `Gagal! Belum ada item yang aktif`,
}, },
]; ];
} }

View File

@ -32,7 +32,7 @@ export class ConfirmItemManager extends BaseUpdateStatusManager<ItemEntity> {
{ {
relation: 'tenant', relation: 'tenant',
singleQuery: ['status', '!=', STATUS.ACTIVE], singleQuery: ['status', '!=', STATUS.ACTIVE],
message: `Failed! Tenant of item must be active first`, message: `Gagal! Belum ada item yang aktif`,
}, },
]; ];
} }

View File

@ -12,7 +12,7 @@ export async function validateRelation(dataService, id) {
if (haveRelation) { if (haveRelation) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! this data already connected to bunding item`, message: `Gagal! data telah digunakan untuk bundling`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -4,6 +4,8 @@ import { EnumDays } from '../../constants';
export interface FilterSeasonPeriodEntity extends BaseFilterEntity { export interface FilterSeasonPeriodEntity extends BaseFilterEntity {
start_date: Date; start_date: Date;
end_date: Date; end_date: Date;
season_type_ids: string[];
holiday_names: string[]; holiday_names: string[];
days: EnumDays[]; days: EnumDays[];
} }

View File

@ -59,7 +59,7 @@ export async function ValidateSeasonPeriodHelper(dataService, data) {
if (datas.length > 0) { if (datas.length > 0) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! there is another season period in same range date`, message: `Gagal! terdapat data periode dengan rentang tanggal yang sama`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -74,6 +74,12 @@ export class IndexSeasonPeriodManager extends BaseIndexManager<SeasonPeriodEntit
); );
} }
if (this.filterParam.season_type_ids) {
queryBuilder.andWhere(`user_privilege_id In (:...seasonIds)`, {
seasonIds: this.filterParam.season_type_ids,
});
}
return queryBuilder; return queryBuilder;
} }
} }

View File

@ -21,7 +21,7 @@ export class UpdateSeasonPeriodPriceManager extends BaseCustomManager<SeasonPeri
if (!existSeason) { if (!existSeason) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! There is no season type ${this.data.season_period.name}`, message: `Gagagl! Tidak terdapat data denga tipe season ${this.data.season_period.name}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -25,4 +25,10 @@ export class FilterSeasonPeriodDto
return Array.isArray(body.value) ? body.value : [body.value]; return Array.isArray(body.value) ? body.value : [body.value];
}) })
days: EnumDays[]; days: EnumDays[];
@ApiProperty({ type: ['string'], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
season_type_ids: string[];
} }

View File

@ -26,7 +26,7 @@ export class BatchCancelReconciliationManager extends BaseBatchUpdateStatusManag
if ([STATUS.SETTLED, STATUS.WAITING].includes(transaction.status)) { if ([STATUS.SETTLED, STATUS.WAITING].includes(transaction.status)) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! cant cancel transaction not settled`, message: `Gagal! tidak bisa batalkan, karena status transaksi tidak settled`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -43,7 +43,7 @@ export class BatchCancelReconciliationManager extends BaseBatchUpdateStatusManag
if (data.is_recap_transaction) { if (data.is_recap_transaction) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! cant cancel recap data`, message: `Gagagl! tidak dapat batalkan data rekap`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -30,13 +30,13 @@ export class CancelReconciliationManager extends BaseUpdateStatusManager<Transac
if ([STATUS.SETTLED, STATUS.WAITING].includes(transaction.status)) { if ([STATUS.SETTLED, STATUS.WAITING].includes(transaction.status)) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! cant cancel transaction not settled`, message: `Gagal! tidak bisa batalkan, karena status transaksi tidak settled`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} else if (this.data.is_recap_transaction) { } else if (this.data.is_recap_transaction) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! cant cancel recap data`, message: `Gagagl! tidak dapat batalkan data rekap`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -48,6 +48,7 @@ export class IndexReconciliationManager extends BaseIndexManager<TransactionEnti
`${this.tableName}.customer_name`, `${this.tableName}.customer_name`,
`${this.tableName}.creator_counter_no`, `${this.tableName}.creator_counter_no`,
`${this.tableName}.booking_date`,
`${this.tableName}.payment_type`, `${this.tableName}.payment_type`,
`${this.tableName}.payment_type_method_id`, `${this.tableName}.payment_type_method_id`,
`${this.tableName}.payment_type_method_name`, `${this.tableName}.payment_type_method_name`,

View File

@ -4,23 +4,23 @@ import { EventTopics } from 'src/core/strings/constants/interface.constants';
import { TransactionType } from 'src/modules/transaction/transaction/constants'; import { TransactionType } from 'src/modules/transaction/transaction/constants';
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
import { Between } from 'typeorm'; import { Between, ILike } from 'typeorm';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as moment from 'moment'; import * as moment from 'moment';
import { STATUS } from 'src/core/strings/constants/base.constants'; import { EMPTY_UUID, STATUS } from 'src/core/strings/constants/base.constants';
@Injectable() @Injectable()
export class RecapReconciliationManager extends BaseCustomManager<TransactionEntity> { export class RecapReconciliationManager extends BaseCustomManager<TransactionEntity> {
private recapTransactions = {}; private recapTransactions = {};
private startOfDay = moment().startOf('day').unix(); private startOfDay = moment().startOf('day').valueOf();
private endOfDay = moment().endOf('day').unix(); private endOfDay = moment().endOf('day').valueOf();
get entityTarget(): any { get entityTarget(): any {
return TransactionModel; return TransactionModel;
} }
getResult() { getResult() {
return; return 'Berhasil recap data transaksi';
} }
get eventTopics(): EventTopics[] { get eventTopics(): EventTopics[] {
@ -36,22 +36,26 @@ export class RecapReconciliationManager extends BaseCustomManager<TransactionEnt
where: { where: {
is_recap_transaction: false, is_recap_transaction: false,
type: TransactionType.COUNTER, type: TransactionType.COUNTER,
status: STATUS.SETTLED,
created_at: Between(this.startOfDay, this.endOfDay), created_at: Between(this.startOfDay, this.endOfDay),
}, },
}); });
const payCounserTransactions = await this.dataService.getManyByOptions({
where: {
is_recap_transaction: false,
payment_code: ILike('%SLS%'),
status: STATUS.SETTLED,
created_at: Between(this.startOfDay, this.endOfDay),
},
});
transactions.push(...payCounserTransactions);
for (const transaction of transactions) { for (const transaction of transactions) {
const { const { creator_counter_no, payment_type, payment_type_method_id } =
creator_counter_no, transaction;
payment_type_method_name,
payment_type_method_number,
} = transaction;
const group_by = const group_by =
creator_counter_no + creator_counter_no + '-' + payment_type + '-' + payment_type_method_id;
'-' +
payment_type_method_name +
'-' +
payment_type_method_number;
if (!this.recapTransactions[group_by]) { if (!this.recapTransactions[group_by]) {
this.recapTransactions[group_by] = []; this.recapTransactions[group_by] = [];
} }
@ -65,32 +69,29 @@ export class RecapReconciliationManager extends BaseCustomManager<TransactionEnt
const total_recap = Object.keys(this.recapTransactions); const total_recap = Object.keys(this.recapTransactions);
for (const recap of total_recap) { for (const recap of total_recap) {
const first_transaction = this.recapTransactions[recap][0]; const first_transaction = this.recapTransactions[recap][0];
const { const { creator_counter_no, payment_type, payment_type_method_id } =
creator_counter_no, first_transaction;
payment_type_method_number,
payment_type_method_name,
} = first_transaction;
const exist = await this.dataService.getOneByOptions({ const exist = await this.dataService.getOneByOptions({
where: { where: {
is_recap_transaction: true, is_recap_transaction: true,
created_at: Between(this.startOfDay, this.endOfDay), created_at: Between(this.startOfDay, this.endOfDay),
creator_counter_no: creator_counter_no, creator_counter_no: creator_counter_no,
payment_type_method_number: payment_type_method_number, payment_type: payment_type,
payment_type_method_name: payment_type_method_name, payment_type_method_id: payment_type_method_id ?? EMPTY_UUID,
}, },
}); });
const new_recap = new TransactionModel(); const new_recap = new TransactionModel();
const total = _.sumBy(this.recapTransactions[recap], (recap) =>
parseFloat(recap.payment_total),
);
if (exist) { if (exist) {
Object.assign(exist, { Object.assign(exist, {
payment_total: _.sumBy(this.recapTransactions[recap], (recap) => payment_total: Number(exist.payment_total) + total,
parseFloat(recap.payment_total), payment_total_net_profit:
), Number(exist.payment_total_net_profit) + total,
payment_total_net_profit: _.sumBy(
this.recapTransactions[recap],
(recap) => parseFloat(recap.payment_total),
),
editor_id: this.user.id, editor_id: this.user.id,
editor_name: this.user.name, editor_name: this.user.name,
updated_at: new Date().getTime(), updated_at: new Date().getTime(),
@ -98,17 +99,13 @@ export class RecapReconciliationManager extends BaseCustomManager<TransactionEnt
} else { } else {
Object.assign(new_recap, { Object.assign(new_recap, {
is_recap_transaction: true, is_recap_transaction: true,
payment_total: _.sumBy(this.recapTransactions[recap], (recap) => payment_total: total,
parseFloat(recap.payment_total), payment_total_net_profit: total,
),
payment_total_net_profit: _.sumBy(
this.recapTransactions[recap],
(recap) => parseFloat(recap.payment_total),
),
reconciliation_status: STATUS.PENDING, reconciliation_status: STATUS.PENDING,
status: STATUS.SETTLED, status: STATUS.SETTLED,
type: TransactionType.COUNTER, type: TransactionType.COUNTER,
booking_date: first_transaction.booking_date, booking_date: new Date(),
payment_date: new Date(),
creator_counter_no: first_transaction.creator_counter_no, creator_counter_no: first_transaction.creator_counter_no,
payment_type: first_transaction.payment_type, payment_type: first_transaction.payment_type,
payment_type_method_id: first_transaction.payment_type_method_id, payment_type_method_id: first_transaction.payment_type_method_id,

View File

@ -25,13 +25,13 @@ export class BatchConfirmRefundManager extends BaseBatchUpdateStatusManager<Refu
) { ) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, message: `Gagal! hanya data dengan status ${STATUS.SETTLED} dapat dikembalikan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} else if (![STATUS.DRAFT, STATUS.PENDING].includes(data.status)) { } else if (![STATUS.DRAFT, STATUS.PENDING].includes(data.status)) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data with status ${STATUS.DRAFT} and ${STATUS.PENDING} can be confirmed`, message: `Gagal! hanya data dengan status ${STATUS.DRAFT} and ${STATUS.PENDING} dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -23,7 +23,7 @@ export class ConfirmRefundManager extends BaseUpdateStatusManager<RefundEntity>
if (![STATUS.DRAFT, STATUS.PENDING].includes(this.oldData.status)) { if (![STATUS.DRAFT, STATUS.PENDING].includes(this.oldData.status)) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data with status ${STATUS.DRAFT} and ${STATUS.PENDING} can be confirmed`, message: `Gagal! hanya data dengan status ${STATUS.DRAFT} dan ${STATUS.PENDING} dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -46,7 +46,7 @@ export class ConfirmRefundManager extends BaseUpdateStatusManager<RefundEntity>
) { ) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, message: `Gagal! hanya pemesanan dengan status ${STATUS.SETTLED} dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -38,7 +38,7 @@ export class CreateRefundManager extends BaseCreateManager<RefundEntity> {
if (exist) { if (exist) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! refund transaction with invoice ${this.data.transaction.invoice_code} already exist`, message: `Gagal! pengembalian pemesanan dengan nomor invoice ${this.data.transaction.invoice_code} telah dibuat`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -53,7 +53,7 @@ export class CreateRefundManager extends BaseCreateManager<RefundEntity> {
if (!transaction) { if (!transaction) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, message: `Gagal! hanya pemesanan dengan status ${STATUS.SETTLED} dapat dikembalikan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -27,7 +27,7 @@ export class UpdateRefundManager extends BaseUpdateManager<RefundEntity> {
if (!transaction) { if (!transaction) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, message: `Gagal! hanya pemesanan dengan status ${STATUS.SETTLED} yang dapat dikembalikan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -117,7 +117,7 @@ function returnError(throwError, e, taxes) {
if (throwError) { if (throwError) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! Formula error`, message: `Gagal! Formula error`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} else { } else {

View File

@ -9,7 +9,7 @@ export async function validateUsedInFormula(formulaDataService, name) {
if (allWords.find((item) => item.toLowerCase() == name)) if (allWords.find((item) => item.toLowerCase() == name))
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! tax ${name} already used in ${formula.type} formula`, message: `Gagal! pajak dengan nama ${name} telah dogunakan pada formula ${formula.type}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
}); });

View File

@ -40,7 +40,7 @@ export class BatchConfirmDataTransactionManager extends BaseBatchUpdateStatusMan
) { ) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagal! hanya pemesanan dengan status ${STATUS.PENDING}, ${STATUS.REJECTED}, ${STATUS.EXPIRED} dapat dikonfirmasi`, message: `Gagal! hanya pemesanan dengan status ${STATUS.PENDING}, ${STATUS.REJECTED}, ${STATUS.EXPIRED} dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -24,7 +24,7 @@ export class BatchConfirmTransactionManager extends BaseBatchUpdateStatusManager
if (data.status != STATUS.DRAFT) { if (data.status != STATUS.DRAFT) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, message: `Gagal! hanya data booking dengan status ${STATUS.DRAFT} yang dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -42,7 +42,7 @@ export class BatchConfirmTransactionManager extends BaseBatchUpdateStatusManager
} catch (error) { } catch (error) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! this transaction already created, please check your email to continue payment`, message: `Gagal! transaksi telah terbuat, silahkan periksa email untuk melanjutkan pembayaran`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -23,7 +23,7 @@ export class CancelTransactionManager extends BaseUpdateStatusManager<Transactio
if (![STATUS.EXPIRED, STATUS.PENDING].includes(this.data.status)) { if (![STATUS.EXPIRED, STATUS.PENDING].includes(this.data.status)) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, message: `Gagal! hanya tranksaksi dengan status ${STATUS.PENDING} dan ${STATUS.EXPIRED} yang dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -27,7 +27,7 @@ export class ConfirmTransactionManager extends BaseUpdateStatusManager<Transacti
if (this.oldData.status != STATUS.DRAFT) { if (this.oldData.status != STATUS.DRAFT) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, message: `Gagal! hanya data booking dengan status ${STATUS.DRAFT} yang dapat di${this.dataStatus}`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -49,7 +49,7 @@ export class ConfirmTransactionManager extends BaseUpdateStatusManager<Transacti
} catch (error) { } catch (error) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! this transaction already created, please check your email to continue payment`, message: `Gagal! transaksi telah terbuat, silahkan periksa email untuk melanjutkan pembayaran`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -22,7 +22,7 @@ export class BatchDeleteTenantManager extends BaseBatchDeleteManager<UserEntity>
statuses: [STATUS.ACTIVE], statuses: [STATUS.ACTIVE],
}); });
}, },
message: 'Failed! There is active item', message: 'Gagal! terdapat item yang aktif',
}, },
]; ];
} }

View File

@ -22,7 +22,7 @@ export class BatchInactiveTenantManager extends BaseBatchUpdateStatusManager<Use
statuses: [STATUS.ACTIVE], statuses: [STATUS.ACTIVE],
}); });
}, },
message: 'Failed! There is active item', message: 'Gagal! terdapat item yang aktif',
}, },
]; ];
} }

View File

@ -21,7 +21,7 @@ export class DeleteTenantManager extends BaseDeleteManager<UserEntity> {
statuses: [STATUS.ACTIVE], statuses: [STATUS.ACTIVE],
}); });
}, },
message: 'Failed! There is active item', message: 'Gagal! terdapat item yang aktif',
}, },
]; ];
} }

View File

@ -21,7 +21,7 @@ export class InactiveTenantManager extends BaseUpdateStatusManager<UserEntity> {
statuses: [STATUS.ACTIVE], statuses: [STATUS.ACTIVE],
}); });
}, },
message: 'Failed! There is active item', message: 'Gagal! terdapat item yang aktif',
}, },
]; ];
} }

View File

@ -1,66 +1,108 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs'; import { EventBus, EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { UserPrivilegeConfigUpdatedEvent } from '../../../entities/event/user-privilege-configuration-updated.event'; import { UserPrivilegeConfigUpdatedEvent } from '../../../entities/event/user-privilege-configuration-updated.event';
import { UserPrivilegeConfigurationService } from 'src/modules/user-related/user-privilege/data/service/user-privilege-configuration.service';
import { UserPrivilegeConfigurationHelper } from '../helpers/generate-user-privilege-configuration.helper'; import { UserPrivilegeConfigurationHelper } from '../helpers/generate-user-privilege-configuration.helper';
import { UserPrivilegeDataService } from 'src/modules/user-related/user-privilege/data/service/user-privilege-data.service';
import { PrivilegeAction } from 'src/core/strings/constants/privilege.constants';
import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model'; import { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model';
import { UserPrivilegeUpdatedEvent } from '../../../entities/event/user-privilege-updated.event';
import { OPERATION } from 'src/core/strings/constants/base.constants';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
@EventsHandler(UserPrivilegeConfigUpdatedEvent) @EventsHandler(UserPrivilegeConfigUpdatedEvent)
export class UserPrivilegeConfigUpdateHandler export class UserPrivilegeConfigUpdateHandler
implements IEventHandler<UserPrivilegeConfigUpdatedEvent> implements IEventHandler<UserPrivilegeConfigUpdatedEvent>
{ {
constructor(private dataService: UserPrivilegeConfigurationService) {} constructor(
private dataService: UserPrivilegeDataService,
private eventBus: EventBus,
) {}
async handle(event: UserPrivilegeConfigUpdatedEvent) { async handle(event: UserPrivilegeConfigUpdatedEvent) {
const data = event.data.data; const data = event.data.data;
console.log(data.user_privilege_id); const configuration = await this.dataService.getOneByOptions({
const configurations = await this.dataService.getManyByOptions({
where: { where: {
user_privilege_id: data.user_privilege_id, id: data.user_privilege_id,
}, },
relations: ['user_privilege_configurations'],
}); });
let configurationData = configuration?.[
'user_privilege_configurations'
]?.sort((a, b) => a.index - b.index);
const configs = UserPrivilegeConfigurationHelper.createConfigurations(); const configs = UserPrivilegeConfigurationHelper.createConfigurations();
const createdConfig = configs configs
.filter( .filter(
(base) => (base) =>
!configurations.some((data) => { !configurationData.some((data) => {
return base.menu_label == data.menu_label; return base.menu_label == data.menu_label;
}), }),
) )
.map((item) => { .map((item) => {
Object.assign(item, {
user_privilege_id: data.user_privilege_id,
});
configurationData.push(item);
});
configurationData = configurationData
?.filter((item) =>
configs.some((data) => {
return item.menu_label == data.menu_label;
}),
)
?.map((item) => {
const exist = configs.find(
(config) => config.menu_label == item.menu_label,
);
return { return {
...item, ...item,
user_privilege_id: data.user_privilege_id, view: exist.actions.includes(PrivilegeAction.VIEW)
? item.view ?? false
: null,
cancel: exist.actions.includes(PrivilegeAction.CANCEL)
? item.cancel ?? false
: null,
confirm: exist.actions.includes(PrivilegeAction.CONFIRM)
? item.confirm ?? false
: null,
create: exist.actions.includes(PrivilegeAction.CREATE)
? item.create ?? false
: null,
delete: exist.actions.includes(PrivilegeAction.DELETE)
? item.delete ?? false
: null,
edit: exist.actions.includes(PrivilegeAction.EDIT)
? item.edit ?? false
: null,
}; };
}); });
const deletedConfig = configurations Object.assign(configuration, {
.filter( user_privilege_configurations: configurationData,
(base) => });
!configs.some((data) => {
return base.menu_label == data.menu_label;
}),
)
?.map((item) => item.id);
const queryRunner = this.dataService const queryRunner = this.dataService
.getRepository() .getRepository()
.manager.connection.createQueryRunner(); .manager.connection.createQueryRunner();
if (createdConfig.length) { await this.dataService.update(
await this.dataService.createBatch(
queryRunner, queryRunner,
UserPrivilegeConfigurationModel, UserPrivilegeConfigurationModel,
createdConfig, { id: data.user_privilege_id },
configuration,
); );
}
if (deletedConfig.length) { this.eventBus.publishAll([
await this.dataService.deleteByIds( new UserPrivilegeUpdatedEvent({
queryRunner, id: configuration.id,
UserPrivilegeConfigurationModel, old: null,
deletedConfig, data: configuration,
); user: event.data.user,
} description: '',
module: TABLE_NAME.USER_PRIVILEGE_CONFIGURATION,
op: OPERATION.UPDATE,
}),
]);
} }
} }

View File

@ -7,6 +7,8 @@ import {
RelationParam, RelationParam,
} from 'src/core/modules/domain/entities/base-filter.entity'; } from 'src/core/modules/domain/entities/base-filter.entity';
import { ORDER_TYPE } from 'src/core/strings/constants/base.constants'; import { ORDER_TYPE } from 'src/core/strings/constants/base.constants';
import { UserPrivilegeConfigurationHelper } from '../helpers/generate-user-privilege-configuration.helper';
import { PrivilegeAction } from 'src/core/strings/constants/privilege.constants';
@Injectable() @Injectable()
export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager<UserPrivilegeConfigurationEntity> { export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager<UserPrivilegeConfigurationEntity> {
@ -24,6 +26,62 @@ export class IndexUserPrivilegeConfigurationManager extends BaseIndexManager<Use
} }
async afterProcess(): Promise<void> { async afterProcess(): Promise<void> {
const configs = UserPrivilegeConfigurationHelper.createConfigurations()
.filter((item) => this.filterParam.modules.includes(item.module))
?.map((item) => {
return {
...item,
};
});
configs
.filter(
(base) =>
!this.result.data.some((data) => {
return base.menu_label == data.menu_label;
}),
)
.map((item) => {
Object.assign(item, {
user_privilege_id: this.filterParam.user_privilege_ids?.[0],
});
this.result.data.push(item);
});
this.result.data = this.result.data
?.filter((item) =>
configs.some((data) => {
return item.menu_label == data.menu_label;
}),
)
?.map((item) => {
const exist = configs.find(
(config) => config.menu_label == item.menu_label,
);
return {
...item,
view: exist.actions.includes(PrivilegeAction.VIEW)
? item.view ?? false
: null,
cancel: exist.actions.includes(PrivilegeAction.CANCEL)
? item.cancel ?? false
: null,
confirm: exist.actions.includes(PrivilegeAction.CONFIRM)
? item.confirm ?? false
: null,
create: exist.actions.includes(PrivilegeAction.CREATE)
? item.create ?? false
: null,
delete: exist.actions.includes(PrivilegeAction.DELETE)
? item.delete ?? false
: null,
edit: exist.actions.includes(PrivilegeAction.EDIT)
? item.edit ?? false
: null,
};
});
return; return;
} }

View File

@ -14,7 +14,7 @@ export async function validateItemGate(dataService, data, id?) {
if (existCode) { if (existCode) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! Gate with code ${data.code} already exist`, message: `Gagal! Gate dengan kode ${data.code} telah ada`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }
@ -31,7 +31,7 @@ export async function validateItemGate(dataService, data, id?) {
if (existType) { if (existType) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! Gate type ${data.type} with item ${data.item.name} already exist`, message: `Gagal! Gate tipe ${data.type} dengan item ${data.item.name} telah ada`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }