From d6ae891de485b30b72968477fb5da46bff7e0c2e Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Tue, 1 Oct 2024 22:03:59 +0700 Subject: [PATCH 1/2] feat: add module report summary --- src/app.module.ts | 2 + .../strings/constants/module.constants.ts | 1 + .../report-summary.controller.ts | 27 +++++++ .../report-summary/report-summary.module.ts | 10 +++ .../report-summary/report-summary.service.ts | 71 +++++++++++++++++++ .../shared/dto/summary-report.get.dto.ts | 8 +++ 6 files changed, 119 insertions(+) create mode 100644 src/modules/reports/report-summary/report-summary.controller.ts create mode 100644 src/modules/reports/report-summary/report-summary.module.ts create mode 100644 src/modules/reports/report-summary/report-summary.service.ts create mode 100644 src/modules/reports/shared/dto/summary-report.get.dto.ts diff --git a/src/app.module.ts b/src/app.module.ts index e552023..b8001b4 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -82,6 +82,7 @@ import { GateScanModule } from './modules/gates/gate.module'; import { UserLoginModel } from './modules/user-related/user/data/models/user-login.model'; import { LogUserLoginModel } from './modules/configuration/log/data/models/log-user-login.model'; import { AuthService } from './core/guards/domain/services/auth.service'; +import { ReportSummaryModule } from './modules/reports/report-summary/report-summary.module'; @Module({ imports: [ @@ -186,6 +187,7 @@ import { AuthService } from './core/guards/domain/services/auth.service'; ReportModule, ReportBookmarkModule, ReportExportModule, + ReportSummaryModule, // superset SupersetModule, diff --git a/src/core/strings/constants/module.constants.ts b/src/core/strings/constants/module.constants.ts index 92913b4..f78ebca 100644 --- a/src/core/strings/constants/module.constants.ts +++ b/src/core/strings/constants/module.constants.ts @@ -24,4 +24,5 @@ export enum MODULE_NAME { REPORT = 'report', REPORT_BOOKMARK = 'report-bookmark', REPORT_EXPORT = 'report-export', + REPORT_SUMMARY = 'report-summary', } diff --git a/src/modules/reports/report-summary/report-summary.controller.ts b/src/modules/reports/report-summary/report-summary.controller.ts new file mode 100644 index 0000000..0bfd0fc --- /dev/null +++ b/src/modules/reports/report-summary/report-summary.controller.ts @@ -0,0 +1,27 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ExcludePrivilege, Public } from 'src/core/guards'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; + +import { ReportSummaryService } from './report-summary.service'; +import { GetSummaryReportDto } from '../shared/dto/summary-report.get.dto'; + +@ApiTags(`${MODULE_NAME.REPORT_SUMMARY.split('-').join(' ')}`) +@Controller(`v1/${MODULE_NAME.REPORT_SUMMARY}`) +@Public(false) +@ApiBearerAuth('JWT') +export class ReportSummaryController { + constructor(private service: ReportSummaryService) {} + + @Get('income-item') + @ExcludePrivilege() + async getReportItem(@Query() query: GetSummaryReportDto) { + return await this.service.getReportItem(query); + } + + @Get('income-item-master') + @ExcludePrivilege() + async getReportItemMaster(@Query() query: GetSummaryReportDto) { + return await this.service.getReportItemMaster(query); + } +} diff --git a/src/modules/reports/report-summary/report-summary.module.ts b/src/modules/reports/report-summary/report-summary.module.ts new file mode 100644 index 0000000..a20367c --- /dev/null +++ b/src/modules/reports/report-summary/report-summary.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { ReportSummaryController } from './report-summary.controller'; +import { ReportSummaryService } from './report-summary.service'; + +@Module({ + imports: [], + controllers: [ReportSummaryController], + providers: [ReportSummaryService], +}) +export class ReportSummaryModule {} diff --git a/src/modules/reports/report-summary/report-summary.service.ts b/src/modules/reports/report-summary/report-summary.service.ts new file mode 100644 index 0000000..89e8857 --- /dev/null +++ b/src/modules/reports/report-summary/report-summary.service.ts @@ -0,0 +1,71 @@ +import { Inject, Injectable, Scope } from '@nestjs/common'; +import { BaseReportService } from '../shared/services/base-report.service'; +import { UserProvider } from 'src/core/sessions'; +import { InjectDataSource } from '@nestjs/typeorm'; +import { DataSource } from 'typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { GetSummaryReportDto } from '../shared/dto/summary-report.get.dto'; + +@Injectable({ scope: Scope.REQUEST }) +export class ReportSummaryService extends BaseReportService { + @Inject() + protected userProvider: UserProvider; + + constructor( + @InjectDataSource(CONNECTION_NAME.DEFAULT) + private dataSource: DataSource, + ) { + super(); + } + + async getReportItem(query: GetSummaryReportDto) { + return this.dataSource.query(` + select + to_char(main.payment_date, 'DD-MM-YYYY') AS main__payment_date, + CASE WHEN tenant.name is not null THEN tenant.name ELSE 'Company' END AS item_owner, + tr_item.item_name AS tr_item__item_name, + SUM(tr_item.qty) AS tr_item__qty, + SUM(tr_item.total_net_price) AS tr_item__total_net_price + from transactions main + LEFT JOIN transaction_items tr_item ON tr_item.transaction_id = main.id + LEFT JOIN items item ON item.id::text = tr_item.item_id::text + LEFT JOIN users tenant ON tenant.id::text = item.tenant_id::text + where + main.status = 'settled' + and tr_item.item_name is not null + and main.is_recap_transaction = false + and to_char(main.payment_date, 'DD-MM-YYYY') = '${query.date}' + group by + to_char(main.payment_date, 'DD-MM-YYYY'), + CASE WHEN tenant.name is not null THEN tenant.name ELSE 'Company' END, + tr_item.item_name + `); + } + + async getReportItemMaster(query: GetSummaryReportDto) { + return this.dataSource.query(` + select + to_char(main.payment_date, 'DD-MM-YYYY') AS main__payment_date, + CASE WHEN tenant.name is not null THEN tenant.name ELSE 'Company' END AS item_owner, + CASE WHEN tr_item.item_type = 'bundling' THEN tr_item.item_name ELSE tr_item_bundling.item_name END AS tr_item_bundling__item_name, + CASE WHEN tr_item.item_type = 'bundling' THEN tr_item_bundling.item_name ELSE tr_item.item_name END AS tr_item__item_name, + SUM(tr_item.qty) AS tr_item__qty, + SUM(CASE WHEN tr_item.item_type != 'bundling' THEN tr_item.total_net_price ELSE tr_item_bundling.total_net_price END) AS tr_item_bundling__total_net_price + from transactions main + LEFT JOIN transaction_items tr_item ON tr_item.transaction_id = main.id + LEFT JOIN transaction_item_breakdowns tr_item_bundling ON tr_item_bundling.transaction_item_id = tr_item.id + LEFT JOIN items item ON item.id::text = tr_item.item_id::text + LEFT JOIN users tenant ON tenant.id::text = item.tenant_id::text + where + main.status = 'settled' + and tr_item.item_name is not null + and main.is_recap_transaction = false + and to_char(main.payment_date, 'DD-MM-YYYY') = '${query.date}' + group by + to_char(main.payment_date, 'DD-MM-YYYY'), + CASE WHEN tenant.name is not null THEN tenant.name ELSE 'Company' END, + CASE WHEN tr_item.item_type = 'bundling' THEN tr_item.item_name ELSE tr_item_bundling.item_name END, + CASE WHEN tr_item.item_type = 'bundling' THEN tr_item_bundling.item_name ELSE tr_item.item_name END + `); + } +} diff --git a/src/modules/reports/shared/dto/summary-report.get.dto.ts b/src/modules/reports/shared/dto/summary-report.get.dto.ts new file mode 100644 index 0000000..74c11ff --- /dev/null +++ b/src/modules/reports/shared/dto/summary-report.get.dto.ts @@ -0,0 +1,8 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class GetSummaryReportDto { + @ApiProperty({ type: 'string', required: true }) + @IsString() + date: string; +} From 90ab3668b4d80bc8c19daec49fc713a464538a99 Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:38:12 +0700 Subject: [PATCH 2/2] feat: create report demography --- .../transaction-report/configs/demography.ts | 111 ++++++++++++++++++ .../configs/transaction-report/index.ts | 2 + 2 files changed, 113 insertions(+) create mode 100644 src/modules/reports/shared/configs/transaction-report/configs/demography.ts diff --git a/src/modules/reports/shared/configs/transaction-report/configs/demography.ts b/src/modules/reports/shared/configs/transaction-report/configs/demography.ts new file mode 100644 index 0000000..acc1f3f --- /dev/null +++ b/src/modules/reports/shared/configs/transaction-report/configs/demography.ts @@ -0,0 +1,111 @@ +import { + DATA_FORMAT, + DATA_TYPE, + FILTER_FIELD_TYPE, + FILTER_TYPE, + REPORT_GROUP, +} from '../../../constant'; +import { ReportConfigEntity } from '../../../entities/report-config.entity'; +import { TransactionType } from 'src/modules/transaction/transaction/constants'; +import { STATUS } from 'src/core/strings/constants/base.constants'; + +export default { + group_name: REPORT_GROUP.transaction_report, + unique_name: `${REPORT_GROUP.transaction_report}__demography`, + label: 'Demography', + table_schema: `transactions main + left join transaction_demographies demography on demography.transaction_id::uuid = main.id`, + main_table_alias: 'main', + whereDefaultConditions: [ + { + column: 'main.status', + filter_type: FILTER_TYPE.TEXT_IN_MEMBER, + values: [STATUS.SETTLED], + }, + { + column: 'main.is_recap_transaction', + filter_type: FILTER_TYPE.TEXT_EQUAL, + values: [false], + }, + ], + defaultOrderBy: [], + lowLevelOrderBy: [], + filter_period_config: { + hidden: true, + }, + + column_configs: [ + { + column: 'main__date', + query: `CASE WHEN main.type ='counter' THEN to_char(main.payment_date, 'DD-MM-YYYY') ELSE to_char(main.booking_date, 'DD-MM-YYYY') END`, + label: 'Tanggal', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__type', + query: 'main.type', + label: 'Sumber', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__code', + query: `CASE WHEN main.invoice_code is not null THEN main.invoice_code ELSE main.payment_code END`, + label: 'Kode', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'demography__woman', + query: `demography.woman`, + label: 'Wanita', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.NUMBER, + }, + { + column: 'demography__man', + query: `demography.man`, + label: 'Pria', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.NUMBER, + }, + { + column: 'demography__teen', + query: `demography.teen`, + label: 'Remaja', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.NUMBER, + }, + { + column: 'demography__child', + query: `demography.child`, + label: 'Anak-anak', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.NUMBER, + }, + ], + filter_configs: [ + { + filed_label: 'Tanggal', + filter_column: 'main__date', + field_type: FILTER_FIELD_TYPE.date_range_picker, + filter_type: FILTER_TYPE.DATE_IN_RANGE_TIMESTAMP, + date_format: 'DD-MM-YYYY', + }, + + { + filed_label: 'Sumber', + filter_column: 'main__type', + field_type: FILTER_FIELD_TYPE.select, + filter_type: FILTER_TYPE.TEXT_IN_MEMBER, + select_custom_options: [...Object.values(TransactionType)], + }, + { + filed_label: 'Kode', + filter_column: 'main__code', + field_type: FILTER_FIELD_TYPE.input_tag, + filter_type: FILTER_TYPE.TEXT_MULTIPLE_CONTAINS, + }, + ], +}; diff --git a/src/modules/reports/shared/configs/transaction-report/index.ts b/src/modules/reports/shared/configs/transaction-report/index.ts index 87569af..454a22a 100644 --- a/src/modules/reports/shared/configs/transaction-report/index.ts +++ b/src/modules/reports/shared/configs/transaction-report/index.ts @@ -13,6 +13,7 @@ import CashierLogReport from './configs/cashier-log'; import CashWithdrawalsReport from './configs/cash-withdrawals'; import ReconciliationReport from './configs/reconciliation'; import TaxReport from './configs/tax'; +import DemographyReport from './configs/demography'; export const TransactionReportConfig: ReportConfigEntity[] = [ IncomeReport, @@ -28,4 +29,5 @@ export const TransactionReportConfig: ReportConfigEntity[] = [ CashWithdrawalsReport, ReconciliationReport, TaxReport, + DemographyReport, ];