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

Reviewed-on: #43
pull/44/head devel_14.0.0
aswin 2024-07-30 11:33:11 +00:00
commit 30ffdca550
27 changed files with 172 additions and 33 deletions

View File

@ -62,6 +62,14 @@ export abstract class BaseDataService<Entity> {
await this.repository.delete(id); await this.repository.delete(id);
} }
async deleteByIds(
queryRunner: QueryRunner,
entityTarget: EntityTarget<Entity>,
ids: string[],
): Promise<void> {
await this.repository.delete(ids);
}
async deleteByOptions( async deleteByOptions(
queryRunner: QueryRunner, queryRunner: QueryRunner,
entityTarget: EntityTarget<Entity>, entityTarget: EntityTarget<Entity>,

View File

@ -1,3 +1,3 @@
export interface BaseCoreEntity { export interface BaseCoreEntity {
id: string; id?: string;
} }

View File

@ -49,14 +49,14 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
}); });
} }
this.oldData = _.cloneDeep(entity); this.oldData = _.cloneDeep(entity);
await this.validateData(entity);
Object.assign(entity, { Object.assign(entity, {
status: this.dataStatus, status: this.dataStatus,
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(),
}); });
await this.validateData(entity);
await new ValidateRelationHelper( await new ValidateRelationHelper(
id, id,
this.dataService, this.dataService,

View File

@ -147,6 +147,7 @@ export const PrivilegePOSConstant = [
PrivilegeAction.CREATE, PrivilegeAction.CREATE,
PrivilegeAction.DELETE, PrivilegeAction.DELETE,
PrivilegeAction.EDIT, PrivilegeAction.EDIT,
PrivilegeAction.CANCEL,
], ],
index: 14, index: 14,
}, },
@ -174,4 +175,10 @@ export const PrivilegePOSConstant = [
actions: [PrivilegeAction.CREATE], actions: [PrivilegeAction.CREATE],
index: 18, index: 18,
}, },
{
menu: 'POS_DISCOUNT_CODE',
menu_label: 'Print Receipt',
actions: [PrivilegeAction.CREATE],
index: 18,
},
]; ];

View File

@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateColumnToTransactionTable1722334034920
implements MigrationInterface
{
name = 'UpdateColumnToTransactionTable1722334034920';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transaction_items" ADD "qr_image_url" character varying`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_code" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_code"`,
);
await queryRunner.query(
`ALTER TABLE "transaction_items" DROP COLUMN "qr_image_url"`,
);
}
}

View File

@ -19,10 +19,7 @@ export class BatchConfirmReconciliationManager extends BaseBatchUpdateStatusMana
reconciliation_confirm_date: new Date().getTime(), reconciliation_confirm_date: new Date().getTime(),
status: STATUS.SETTLED, status: STATUS.SETTLED,
reconciliation_status: this.dataStatus, reconciliation_status: this.dataStatus,
payment_code_reference: await generateInvoiceCodeHelper( payment_code: await generateInvoiceCodeHelper(this.dataService, 'PMY'),
this.dataService,
'PMY',
),
}); });
return; return;
} }

View File

@ -26,10 +26,7 @@ export class ConfirmReconciliationManager extends BaseUpdateStatusManager<Transa
reconciliation_confirm_date: new Date().getTime(), reconciliation_confirm_date: new Date().getTime(),
status: STATUS.SETTLED, status: STATUS.SETTLED,
reconciliation_status: this.dataStatus, reconciliation_status: this.dataStatus,
payment_code_reference: await generateInvoiceCodeHelper( payment_code: await generateInvoiceCodeHelper(this.dataService, 'PMY'),
this.dataService,
'PMY',
),
}); });
return; return;

View File

@ -40,6 +40,7 @@ export class DetailReconciliationManager extends BaseDetailManager<TransactionEn
`${this.tableName}.payment_type_method_name`, `${this.tableName}.payment_type_method_name`,
`${this.tableName}.payment_type_method_number`, `${this.tableName}.payment_type_method_number`,
`${this.tableName}.payment_code_reference`, `${this.tableName}.payment_code_reference`,
`${this.tableName}.payment_code`,
`${this.tableName}.payment_date`, `${this.tableName}.payment_date`,
`${this.tableName}.payment_total`, `${this.tableName}.payment_total`,

View File

@ -53,6 +53,7 @@ export class IndexReconciliationManager extends BaseIndexManager<TransactionEnti
`${this.tableName}.payment_type_method_name`, `${this.tableName}.payment_type_method_name`,
`${this.tableName}.payment_type_method_number`, `${this.tableName}.payment_type_method_number`,
`${this.tableName}.payment_code_reference`, `${this.tableName}.payment_code_reference`,
`${this.tableName}.payment_code`,
`${this.tableName}.payment_date`, `${this.tableName}.payment_date`,
`${this.tableName}.payment_total`, `${this.tableName}.payment_total`,

View File

@ -17,10 +17,17 @@ import { STATUS } from 'src/core/strings/constants/base.constants';
@Injectable() @Injectable()
export class BatchCancelRefundManager extends BaseBatchUpdateStatusManager<RefundEntity> { export class BatchCancelRefundManager extends BaseBatchUpdateStatusManager<RefundEntity> {
validateData(data: RefundEntity): Promise<void> { validateData(data: RefundEntity): Promise<void> {
if (![STATUS.REFUNDED, STATUS.PENDING].includes(data.status)) { if (
![
STATUS.REFUNDED,
STATUS.PENDING,
STATUS.PROCESS_REFUND,
STATUS.PARTIAL_REFUND,
].includes(data.status)
) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Failed! only data with status ${STATUS.REFUNDED} and ${STATUS.PENDING} can be cancelled`, message: `Gagal! hanya data dengan status ${STATUS.REFUNDED}, ${STATUS.PROCESS_REFUND} , ${STATUS.PARTIAL_REFUND} dan ${STATUS.PENDING} yang dapat dicancel`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -20,10 +20,17 @@ export class CancelRefundManager extends BaseUpdateStatusManager<RefundEntity> {
} }
async validateProcess(): Promise<void> { async validateProcess(): Promise<void> {
if (![STATUS.REFUNDED, STATUS.PENDING].includes(this.data.status)) { if (
![
STATUS.REFUNDED,
STATUS.PENDING,
STATUS.PROCESS_REFUND,
STATUS.PARTIAL_REFUND,
].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.REFUNDED} and ${STATUS.PENDING} can be cancelled`, message: `Gagal! hanya data dengan status ${STATUS.REFUNDED}, ${STATUS.PROCESS_REFUND} , ${STATUS.PARTIAL_REFUND} dan ${STATUS.PENDING} yang dapat dicancel`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -14,6 +14,9 @@ export class TransactionItemModel
@Column('varchar', { name: 'item_id', nullable: true }) @Column('varchar', { name: 'item_id', nullable: true })
item_id: string; item_id: string;
@Column('varchar', { name: 'qr_image_url', nullable: true })
qr_image_url: string;
@Column('varchar', { name: 'item_name', nullable: true }) @Column('varchar', { name: 'item_name', nullable: true })
item_name: string; item_name: string;

View File

@ -107,6 +107,9 @@ export class TransactionModel
}) })
payment_type: TransactionPaymentType; payment_type: TransactionPaymentType;
@Column('varchar', { name: 'payment_code', nullable: true })
payment_code: string;
@Column('varchar', { name: 'payment_type_method_id', nullable: true }) @Column('varchar', { name: 'payment_type_method_id', nullable: true })
payment_type_method_id: string; payment_type_method_id: string;

View File

@ -10,6 +10,7 @@ export interface TransactionItemEntity extends BaseCoreEntity {
item_category_id: string; item_category_id: string;
item_category_name: string; item_category_name: string;
item_bundlings: string; item_bundlings: string;
qr_image_url: string;
// item tenant data // item tenant data
item_tenant_id: string; item_tenant_id: string;

View File

@ -47,6 +47,7 @@ export interface TransactionEntity extends BaseStatusEntity {
payment_type_method_qr: string; payment_type_method_qr: string;
payment_card_information: string; payment_card_information: string;
payment_code_reference: string; payment_code_reference: string;
payment_code: string;
payment_midtrans_token: string; payment_midtrans_token: string;
payment_midtrans_url: string; payment_midtrans_url: string;
payment_date: Date; payment_date: Date;

View File

@ -10,6 +10,7 @@ import {
import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { generateInvoiceCodeHelper } from '../managers/helpers/generate-invoice-code.helper';
@EventsHandler(MidtransCallbackEvent) @EventsHandler(MidtransCallbackEvent)
export class MidtransCallbackHandler export class MidtransCallbackHandler
@ -36,6 +37,7 @@ export class MidtransCallbackHandler
Object.assign(transaction, { Object.assign(transaction, {
status: STATUS.SETTLED, status: STATUS.SETTLED,
settlement_date: new Date(data.settlement_time), settlement_date: new Date(data.settlement_time),
payment_code: await generateInvoiceCodeHelper(this.dataService, 'PMY'),
payment_code_reference: data.approval_code, payment_code_reference: data.approval_code,
}); });
} else if (['pending'].includes(data['transaction_status'])) { } else if (['pending'].includes(data['transaction_status'])) {

View File

@ -20,7 +20,7 @@ export class BatchCancelTransactionManager extends BaseBatchUpdateStatusManager<
if (![STATUS.EXPIRED, STATUS.PENDING].includes(data.status)) { if (![STATUS.EXPIRED, STATUS.PENDING].includes(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

@ -56,10 +56,7 @@ export class ConfirmTransactionManager extends BaseUpdateStatusManager<Transacti
} }
Object.assign(this.data, { Object.assign(this.data, {
invoice_code: invoice_code: await generateInvoiceCodeHelper(this.dataService, 'INV'),
this.data.payment_type == TransactionPaymentType.COUNTER
? null
: await generateInvoiceCodeHelper(this.dataService, 'INV'),
status: freeTransaction ? STATUS.ACTIVE : STATUS.PENDING, status: freeTransaction ? STATUS.ACTIVE : STATUS.PENDING,
invoice_date: new Date(), invoice_date: new Date(),
}); });

View File

@ -69,6 +69,7 @@ export class DetailTransactionManager extends BaseDetailManager<TransactionEntit
`${this.tableName}.payment_type_method_number`, `${this.tableName}.payment_type_method_number`,
`${this.tableName}.payment_card_information`, `${this.tableName}.payment_card_information`,
`${this.tableName}.payment_code_reference`, `${this.tableName}.payment_code_reference`,
`${this.tableName}.payment_code`,
`${this.tableName}.payment_sub_total`, `${this.tableName}.payment_sub_total`,
`${this.tableName}.payment_discount_total`, `${this.tableName}.payment_discount_total`,

View File

@ -14,7 +14,7 @@ export async function generateInvoiceCodeHelper(dataService, code) {
if (code == 'PYM') { if (code == 'PYM') {
query = { query = {
payment_code_reference: ILike(`%${month_year}%`), payment_code: ILike(`%${month_year}%`),
}; };
} }

View File

@ -61,7 +61,6 @@ export function mappingTransaction(data) {
season_period: season_period, season_period: season_period,
items: items, items: items,
payment_type_bank: payment_type_bank, payment_type_bank: payment_type_bank,
payment_code: data.payment_code_reference,
}); });
delete data.season_period_id; delete data.season_period_id;
@ -82,17 +81,18 @@ export function mappingRevertTransaction(data, type) {
editor_id: data.pos_admin?.id, editor_id: data.pos_admin?.id,
editor_name: data.pos_admin?.name, editor_name: data.pos_admin?.name,
edited_at: new Date(data.created_at), edited_at: new Date(data.created_at),
payment_code: data.code,
}); });
} else { } else {
Object.assign(data, { Object.assign(data, {
creator_id: data.pos_admin?.id, creator_id: data.pos_admin?.id,
creator_name: data.pos_admin?.name, creator_name: data.pos_admin?.name,
invoice_code: data.code,
}); });
} }
Object.assign(data, { Object.assign(data, {
id: data.booking_id ?? data._id, id: data.booking_id ?? data._id,
invoice_code: data.code,
creator_counter_no: Number(data.pos_number), creator_counter_no: Number(data.pos_number),
status: STATUS.SETTLED, status: STATUS.SETTLED,
settlement_date: new Date(data.created_at), settlement_date: new Date(data.created_at),

View File

@ -67,6 +67,8 @@ export class IndexTransactionManager extends BaseIndexManager<TransactionEntity>
`${this.tableName}.editor_id`, `${this.tableName}.editor_id`,
`${this.tableName}.editor_name`, `${this.tableName}.editor_name`,
`${this.tableName}.payment_code`,
`${this.tableName}.payment_card_information`,
`${this.tableName}.payment_type`, `${this.tableName}.payment_type`,
`${this.tableName}.payment_date`, `${this.tableName}.payment_date`,
`${this.tableName}.payment_total_pay`, `${this.tableName}.payment_total_pay`,

View File

@ -42,7 +42,6 @@ export class UpdateTransactionManager extends BaseUpdateManager<TransactionEntit
return [ return [
{ {
topic: TransactionUpdatedEvent, topic: TransactionUpdatedEvent,
data: this.data,
}, },
]; ];
} }

View File

@ -15,6 +15,7 @@ import { BatchCancelTransactionManager } from './managers/batch-cancel-transacti
import { ConfirmDataTransactionManager } from './managers/confirm-data-transaction.manager'; import { ConfirmDataTransactionManager } from './managers/confirm-data-transaction.manager';
import { BatchConfirmDataTransactionManager } from './managers/batch-confirm-data-transaction.manager'; import { BatchConfirmDataTransactionManager } from './managers/batch-confirm-data-transaction.manager';
import { MidtransService } from 'src/modules/configuration/midtrans/data/services/midtrans.service'; import { MidtransService } from 'src/modules/configuration/midtrans/data/services/midtrans.service';
import { InvoiceTransactionManager } from './managers/download-invoice-transaction.manager';
@Injectable() @Injectable()
export class TransactionDataOrchestrator { export class TransactionDataOrchestrator {
@ -29,6 +30,7 @@ export class TransactionDataOrchestrator {
private batchDeleteManager: BatchDeleteTransactionManager, private batchDeleteManager: BatchDeleteTransactionManager,
private cancelManager: CancelTransactionManager, private cancelManager: CancelTransactionManager,
private batchCancelManager: BatchCancelTransactionManager, private batchCancelManager: BatchCancelTransactionManager,
private invoiceManager: InvoiceTransactionManager,
private serviceData: TransactionDataService, private serviceData: TransactionDataService,
private midtransService: MidtransService, private midtransService: MidtransService,
) {} ) {}
@ -47,6 +49,15 @@ export class TransactionDataOrchestrator {
return this.updateManager.getResult(); return this.updateManager.getResult();
} }
async invoice(dataId): Promise<any> {
this.invoiceManager.setData({
id: dataId,
});
this.invoiceManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);
await this.invoiceManager.execute();
return this.invoiceManager.getResult();
}
async delete(dataId): Promise<string> { async delete(dataId): Promise<string> {
this.deleteManager.setData(dataId); this.deleteManager.setData(dataId);
this.deleteManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); this.deleteManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);

View File

@ -5,13 +5,13 @@ export interface UserPrivilegeConfigurationEntity extends BaseCoreEntity {
module_label: string; module_label: string;
menu: string; menu: string;
menu_label: string; menu_label: string;
sub_menu: string; sub_menu?: string;
sub_menu_label: string; sub_menu_label?: string;
view: boolean; view?: boolean;
create: boolean; create?: boolean;
edit: boolean; edit?: boolean;
delete: boolean; delete?: boolean;
cancel: boolean; cancel?: boolean;
confirm: boolean; confirm?: boolean;
index: number; index?: number;
} }

View File

@ -0,0 +1,66 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
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 { UserPrivilegeConfigurationModel } from 'src/modules/user-related/user-privilege/data/models/user-privilege-configuration.model';
@EventsHandler(UserPrivilegeConfigUpdatedEvent)
export class UserPrivilegeConfigUpdateHandler
implements IEventHandler<UserPrivilegeConfigUpdatedEvent>
{
constructor(private dataService: UserPrivilegeConfigurationService) {}
async handle(event: UserPrivilegeConfigUpdatedEvent) {
const data = event.data.data;
console.log(data.user_privilege_id);
const configurations = await this.dataService.getManyByOptions({
where: {
user_privilege_id: data.user_privilege_id,
},
});
const configs = UserPrivilegeConfigurationHelper.createConfigurations();
const createdConfig = configs
.filter(
(base) =>
!configurations.some((data) => {
return base.menu_label == data.menu_label;
}),
)
.map((item) => {
return {
...item,
user_privilege_id: data.user_privilege_id,
};
});
const deletedConfig = configurations
.filter(
(base) =>
!configs.some((data) => {
return base.menu_label == data.menu_label;
}),
)
?.map((item) => item.id);
const queryRunner = this.dataService
.getRepository()
.manager.connection.createQueryRunner();
if (createdConfig.length) {
await this.dataService.createBatch(
queryRunner,
UserPrivilegeConfigurationModel,
createdConfig,
);
}
if (deletedConfig.length) {
await this.dataService.deleteByIds(
queryRunner,
UserPrivilegeConfigurationModel,
deletedConfig,
);
}
}
}

View File

@ -28,6 +28,7 @@ import { UserPrivilegeConfigurationDataOrchestrator } from './domain/usecases/us
import { IndexUserPrivilegeConfigurationManager } from './domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager'; import { IndexUserPrivilegeConfigurationManager } from './domain/usecases/user-privilege-configuration/managers/index-user-privilege-configuration.manager';
import { UserPrivilegeModels } from './constants'; import { UserPrivilegeModels } from './constants';
import { MenuUserPrivilegeConfigurationManager } from './domain/usecases/user-privilege-configuration/managers/menu-user-privilege-configuration.manager'; import { MenuUserPrivilegeConfigurationManager } from './domain/usecases/user-privilege-configuration/managers/menu-user-privilege-configuration.manager';
import { UserPrivilegeConfigUpdateHandler } from './domain/usecases/user-privilege-configuration/handlers/update-user-privilege-configuration.helper';
@Module({ @Module({
imports: [ imports: [
@ -41,6 +42,8 @@ import { MenuUserPrivilegeConfigurationManager } from './domain/usecases/user-pr
UserPrivilegeConfigurationController, UserPrivilegeConfigurationController,
], ],
providers: [ providers: [
UserPrivilegeConfigUpdateHandler,
IndexUserPrivilegeManager, IndexUserPrivilegeManager,
DetailUserPrivilegeManager, DetailUserPrivilegeManager,
CreateUserPrivilegeManager, CreateUserPrivilegeManager,