Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into staging
commit
46b92afb89
|
@ -35,4 +35,7 @@ docker-compose.yml
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# IGNORE UPLOAD FOLDER
|
||||||
|
/uploads
|
|
@ -6,6 +6,8 @@ JWT_REFRESH_EXPIRES="7d"
|
||||||
ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9"
|
ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9"
|
||||||
IV="a671a96159e97a4f"
|
IV="a671a96159e97a4f"
|
||||||
|
|
||||||
|
COUCHDB_CONFIG="http://root:password@172.10.10.2:5970"
|
||||||
|
|
||||||
DEFAULT_DB_HOST="postgres"
|
DEFAULT_DB_HOST="postgres"
|
||||||
DEFAULT_DB_PORT="5432"
|
DEFAULT_DB_PORT="5432"
|
||||||
DEFAULT_DB_USER="root"
|
DEFAULT_DB_USER="root"
|
||||||
|
@ -15,3 +17,20 @@ DEFAULT_DB_NAME="pos"
|
||||||
ELASTIC_APM_ACTIVATE=true
|
ELASTIC_APM_ACTIVATE=true
|
||||||
ELASTIC_APM_SERVICE_NAME="Skyworld POS"
|
ELASTIC_APM_SERVICE_NAME="Skyworld POS"
|
||||||
ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200"
|
ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200"
|
||||||
|
|
||||||
|
CRON_MIDNIGHT="55 11 * * *"
|
||||||
|
CRON_EVERY_MINUTE="55 11 * * *"
|
||||||
|
CRON_EVERY_HOUR="0 * * * *"
|
||||||
|
|
||||||
|
EMAIL_HOST="sandbox.smtp.mailtrap.io"
|
||||||
|
EMAIL_POST=465
|
||||||
|
EMAIL_USER="developer@eigen.co.id"
|
||||||
|
EMAIL_TOKEN="bitqkbkzjzfywxqx"
|
||||||
|
|
||||||
|
MIDTRANS_URL=https://app.sandbox.midtrans.com
|
||||||
|
MIDTRANS_PRODUCTION=false
|
||||||
|
MIDTRANS_SERVER_KEY=
|
||||||
|
MIDTRANS_CLIENT_KEY=
|
||||||
|
|
||||||
|
EXPORT_LIMIT_PARTITION=200
|
||||||
|
ASSETS="https://asset.sky.eigen.co.id/"
|
|
@ -0,0 +1,36 @@
|
||||||
|
PORT="3346"
|
||||||
|
|
||||||
|
JWT_SECRET="ftyYM4t4kjuj/0ixvIrS18gpdvBJw42NnW71GrFrEhcn0alQkkH7TQIHU5MFFJ1e"
|
||||||
|
JWT_EXPIRES="24h"
|
||||||
|
JWT_REFRESH_EXPIRES="7d"
|
||||||
|
ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9"
|
||||||
|
IV="a671a96159e97a4f"
|
||||||
|
|
||||||
|
COUCHDB_CONFIG="http://root:password@172.10.10.2:5970"
|
||||||
|
|
||||||
|
DEFAULT_DB_HOST="postgres"
|
||||||
|
DEFAULT_DB_PORT="5432"
|
||||||
|
DEFAULT_DB_USER="root"
|
||||||
|
DEFAULT_DB_PASS="password"
|
||||||
|
DEFAULT_DB_NAME="pos"
|
||||||
|
|
||||||
|
ELASTIC_APM_ACTIVATE=true
|
||||||
|
ELASTIC_APM_SERVICE_NAME="Skyworld POS"
|
||||||
|
ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200"
|
||||||
|
|
||||||
|
CRON_MIDNIGHT="55 11 * * *"
|
||||||
|
CRON_EVERY_MINUTE="55 11 * * *"
|
||||||
|
CRON_EVERY_HOUR="0 * * * *"
|
||||||
|
|
||||||
|
EMAIL_HOST="sandbox.smtp.mailtrap.io"
|
||||||
|
EMAIL_POST=465
|
||||||
|
EMAIL_USER=
|
||||||
|
EMAIL_TOKEN=
|
||||||
|
|
||||||
|
MIDTRANS_URL=https://app.midtrans.com
|
||||||
|
MIDTRANS_PRODUCTION=true
|
||||||
|
MIDTRANS_SERVER_KEY=
|
||||||
|
MIDTRANS_CLIENT_KEY=
|
||||||
|
|
||||||
|
EXPORT_LIMIT_PARTITION=200
|
||||||
|
ASSETS="https://asset.sky.eigen.co.id/"
|
|
@ -0,0 +1,42 @@
|
||||||
|
## Formula Calculation
|
||||||
|
|
||||||
|
### Instalation
|
||||||
|
```
|
||||||
|
yarn add mathjs algebra.js
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```ts
|
||||||
|
import * as math from 'mathjs'
|
||||||
|
import { Equation, parse } from 'algebra.js'
|
||||||
|
|
||||||
|
const formula = 'dpp - (dpp*ppn) - (dpp*retribusi) - (dpp*service) - (dpp*ppn3)'
|
||||||
|
const total = '300000'
|
||||||
|
|
||||||
|
const variable = {
|
||||||
|
ppn: 11,
|
||||||
|
retribusi: 5000,
|
||||||
|
service: 5,
|
||||||
|
ppn3: 5000
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const x1 = math.simplify(formula, variable).toString()
|
||||||
|
console.log('Formula ', x1)
|
||||||
|
const dppFormula = parse(x1)
|
||||||
|
const totalFormula = parse(total)
|
||||||
|
const equation = new Equation(totalFormula, dppFormula)
|
||||||
|
|
||||||
|
console.log(equation.toString())
|
||||||
|
const result = equation.solveFor('dpp').toString()
|
||||||
|
console.log(result)
|
||||||
|
|
||||||
|
const value = math.evaluate(result)
|
||||||
|
console.log(value)
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
```
|
12
package.json
12
package.json
|
@ -34,15 +34,25 @@
|
||||||
"@nestjs/cqrs": "^10.2.7",
|
"@nestjs/cqrs": "^10.2.7",
|
||||||
"@nestjs/jwt": "^10.2.0",
|
"@nestjs/jwt": "^10.2.0",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
|
"@nestjs/schedule": "^4.1.0",
|
||||||
"@nestjs/swagger": "^7.3.1",
|
"@nestjs/swagger": "^7.3.1",
|
||||||
"@nestjs/typeorm": "^10.0.2",
|
"@nestjs/typeorm": "^10.0.2",
|
||||||
|
"@types/multer": "^1.4.11",
|
||||||
|
"algebra.js": "^0.2.6",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"elastic-apm-node": "^4.5.4",
|
"elastic-apm-node": "^4.5.4",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
|
"fs-extra": "^11.2.0",
|
||||||
"googleapis": "^140.0.0",
|
"googleapis": "^140.0.0",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"mathjs": "^13.0.2",
|
||||||
|
"midtrans-client": "^1.3.1",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"nano": "^10.1.3",
|
"nano": "^10.1.3",
|
||||||
|
"nodemailer": "^6.9.14",
|
||||||
"pg": "^8.11.5",
|
"pg": "^8.11.5",
|
||||||
"plop": "^4.0.1",
|
"plop": "^4.0.1",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
|
@ -90,4 +100,4 @@
|
||||||
"coverageDirectory": "../coverage",
|
"coverageDirectory": "../coverage",
|
||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ module.exports = function (plop) {
|
||||||
name: 'location',
|
name: 'location',
|
||||||
message: 'Location: ',
|
message: 'Location: ',
|
||||||
choices: function () {
|
choices: function () {
|
||||||
return ['item related', 'user related', 'season related', 'transaction'];
|
return ['item related', 'user related', 'season related', 'transaction', 'web information'];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -42,6 +42,33 @@ import { SeasonPeriodModel } from './modules/season-related/season-period/data/m
|
||||||
import { ItemRateModule } from './modules/item-related/item-rate/item-rate.module';
|
import { ItemRateModule } from './modules/item-related/item-rate/item-rate.module';
|
||||||
import { ItemRateModel } from './modules/item-related/item-rate/data/models/item-rate.model';
|
import { ItemRateModel } from './modules/item-related/item-rate/data/models/item-rate.model';
|
||||||
import { GoogleCalendarModule } from './modules/configuration/google-calendar/google-calendar.module';
|
import { GoogleCalendarModule } from './modules/configuration/google-calendar/google-calendar.module';
|
||||||
|
import { TransactionModule } from './modules/transaction/transaction/transaction.module';
|
||||||
|
import { TransactionModel } from './modules/transaction/transaction/data/models/transaction.model';
|
||||||
|
import { TransactionItemModel } from './modules/transaction/transaction/data/models/transaction-item.model';
|
||||||
|
import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model';
|
||||||
|
import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module';
|
||||||
|
import { ReportModule } from './modules/reports/report/report.module';
|
||||||
|
import { ReportBookmarkModule } from './modules/reports/report-bookmark/report-bookmark.module';
|
||||||
|
import { ReportExportModule } from './modules/reports/report-export/report-export.module';
|
||||||
|
import { ReportBookmarkModel } from './modules/reports/shared/models/report-bookmark.model';
|
||||||
|
import { ExportReportHistoryModel } from './modules/reports/shared/models/export-report-history.model';
|
||||||
|
import { CronModule } from './modules/configuration/cron/cron.module';
|
||||||
|
import { MidtransModule } from './modules/configuration/midtrans/midtrans.module';
|
||||||
|
import { RefundModule } from './modules/transaction/refund/refund.module';
|
||||||
|
import { RefundModel } from './modules/transaction/refund/data/models/refund.model';
|
||||||
|
import { RefundItemModel } from './modules/transaction/refund/data/models/refund-item.model';
|
||||||
|
import { GateModule } from './modules/web-information/gate/gate.module';
|
||||||
|
import { GateModel } from './modules/web-information/gate/data/models/gate.model';
|
||||||
|
import { TermConditionModule } from './modules/web-information/term-condition/term-condition.module';
|
||||||
|
import { TermConditionModel } from './modules/web-information/term-condition/data/models/term-condition.model';
|
||||||
|
import { FaqModel } from './modules/web-information/faq/data/models/faq.model';
|
||||||
|
import { FaqModule } from './modules/web-information/faq/faq.module';
|
||||||
|
import { UploadModule } from './modules/configuration/upload/upload.module';
|
||||||
|
import { NewsModule } from './modules/web-information/news/news.module';
|
||||||
|
import { NewsModel } from './modules/web-information/news/data/models/news.model';
|
||||||
|
import { BannerModule } from './modules/web-information/banner/banner.module';
|
||||||
|
import { BannerModel } from './modules/web-information/banner/data/models/banner.model';
|
||||||
|
import { MailModule } from './modules/configuration/mail/mail.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -59,19 +86,33 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go
|
||||||
database: process.env.DEFAULT_DB_NAME,
|
database: process.env.DEFAULT_DB_NAME,
|
||||||
entities: [
|
entities: [
|
||||||
...UserPrivilegeModels,
|
...UserPrivilegeModels,
|
||||||
|
BannerModel,
|
||||||
ErrorLogModel,
|
ErrorLogModel,
|
||||||
|
FaqModel,
|
||||||
|
GateModel,
|
||||||
ItemModel,
|
ItemModel,
|
||||||
ItemCategoryModel,
|
ItemCategoryModel,
|
||||||
ItemRateModel,
|
ItemRateModel,
|
||||||
LogModel,
|
LogModel,
|
||||||
|
NewsModel,
|
||||||
PaymentMethodModel,
|
PaymentMethodModel,
|
||||||
|
RefundModel,
|
||||||
|
RefundItemModel,
|
||||||
SalesPriceFormulaModel,
|
SalesPriceFormulaModel,
|
||||||
SeasonPeriodModel,
|
SeasonPeriodModel,
|
||||||
SeasonTypeModel,
|
SeasonTypeModel,
|
||||||
TaxModel,
|
TaxModel,
|
||||||
|
TermConditionModel,
|
||||||
|
TransactionModel,
|
||||||
|
TransactionItemModel,
|
||||||
|
TransactionTaxModel,
|
||||||
UserModel,
|
UserModel,
|
||||||
VipCategoryModel,
|
VipCategoryModel,
|
||||||
VipCodeModel,
|
VipCodeModel,
|
||||||
|
|
||||||
|
// report
|
||||||
|
ReportBookmarkModel,
|
||||||
|
ExportReportHistoryModel,
|
||||||
],
|
],
|
||||||
synchronize: false,
|
synchronize: false,
|
||||||
}),
|
}),
|
||||||
|
@ -79,9 +120,13 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go
|
||||||
ConstantModule,
|
ConstantModule,
|
||||||
CqrsModule,
|
CqrsModule,
|
||||||
CouchModule,
|
CouchModule,
|
||||||
|
CronModule,
|
||||||
GoogleCalendarModule,
|
GoogleCalendarModule,
|
||||||
LogModule,
|
LogModule,
|
||||||
|
MailModule,
|
||||||
|
MidtransModule,
|
||||||
SessionModule,
|
SessionModule,
|
||||||
|
UploadModule,
|
||||||
|
|
||||||
// user
|
// user
|
||||||
TenantModule,
|
TenantModule,
|
||||||
|
@ -96,14 +141,29 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go
|
||||||
// transaction
|
// transaction
|
||||||
PaymentMethodModule,
|
PaymentMethodModule,
|
||||||
ProfitShareFormulaModule,
|
ProfitShareFormulaModule,
|
||||||
|
ReconciliationModule,
|
||||||
|
RefundModule,
|
||||||
SalesPriceFormulaModule,
|
SalesPriceFormulaModule,
|
||||||
TaxModule,
|
TaxModule,
|
||||||
|
TransactionModule,
|
||||||
VipCategoryModule,
|
VipCategoryModule,
|
||||||
VipCodeModule,
|
VipCodeModule,
|
||||||
|
|
||||||
// session
|
// session
|
||||||
SeasonTypeModule,
|
SeasonTypeModule,
|
||||||
SeasonPeriodModule,
|
SeasonPeriodModule,
|
||||||
|
|
||||||
|
// web information
|
||||||
|
BannerModule,
|
||||||
|
FaqModule,
|
||||||
|
GateModule,
|
||||||
|
NewsModule,
|
||||||
|
TermConditionModule,
|
||||||
|
|
||||||
|
// report
|
||||||
|
ReportModule,
|
||||||
|
ReportBookmarkModule,
|
||||||
|
ReportExportModule,
|
||||||
],
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [
|
providers: [
|
||||||
|
|
|
@ -61,7 +61,7 @@ export class PrivilegeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async privilegeConfiguration(): Promise<UserPrivilegeConfigurationEntity> {
|
async privilegeConfiguration(): Promise<UserPrivilegeConfigurationEntity> {
|
||||||
const { module, menu, sub_menu, section } = this.moduleKey();
|
const { module, menu } = this.moduleKey();
|
||||||
return await this.repository.findOne({
|
return await this.repository.findOne({
|
||||||
select: ['id', 'view', 'create', 'edit', 'delete', 'cancel', 'confirm'],
|
select: ['id', 'view', 'create', 'edit', 'delete', 'cancel', 'confirm'],
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import * as fs from 'fs-extra';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export async function MoveFilePathHelper(data) {
|
||||||
|
const imagePath = data['qr_image'] ?? data['image_url'];
|
||||||
|
const sourcePath = path.join(__dirname, '../../../../uploads/', imagePath);
|
||||||
|
const movePath =
|
||||||
|
'data/' +
|
||||||
|
imagePath
|
||||||
|
.split('/')
|
||||||
|
.filter((item) => !['uploads', 'tmp'].includes(item))
|
||||||
|
.join('/');
|
||||||
|
const destinationPath = path.join(
|
||||||
|
__dirname,
|
||||||
|
'../../../../uploads/',
|
||||||
|
movePath,
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.move(sourcePath, destinationPath);
|
||||||
|
|
||||||
|
Object.assign(data, {
|
||||||
|
image_url: movePath,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Failed! Error move file data`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { extname } from 'path';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
|
||||||
|
import { diskStorage } from 'multer';
|
||||||
|
|
||||||
|
const MB = 1024 * 1024;
|
||||||
|
|
||||||
|
const fileFilter = (req, file, callback) => {
|
||||||
|
if (file.mimetype.match(/\/(jpg|jpeg|png)$/)) {
|
||||||
|
callback(null, true);
|
||||||
|
} else {
|
||||||
|
callback(
|
||||||
|
new HttpException(
|
||||||
|
`Unsupported file type ${extname(file.originalname)}`,
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const editFileName = (req, file, callback) => {
|
||||||
|
const fileExtName = extname(file.originalname);
|
||||||
|
const randomName = uuidv4();
|
||||||
|
callback(null, `${randomName}${fileExtName}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const destinationPath = (req, file, cb) => {
|
||||||
|
let modulePath = req.body.module;
|
||||||
|
if (req.body.sub_module) modulePath = `${modulePath}/${req.body.sub_module}`;
|
||||||
|
|
||||||
|
fs.mkdirSync(`./uploads/tmp/${modulePath}`, { recursive: true });
|
||||||
|
cb(null, `./uploads/tmp/${modulePath}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StoreFileConfig: MulterOptions = {
|
||||||
|
storage: diskStorage({
|
||||||
|
destination: destinationPath,
|
||||||
|
filename: editFileName,
|
||||||
|
}),
|
||||||
|
fileFilter: fileFilter,
|
||||||
|
};
|
|
@ -10,39 +10,14 @@ export function setQueryFilterDefault(
|
||||||
baseFilter: BaseFilterEntity,
|
baseFilter: BaseFilterEntity,
|
||||||
tableName: TABLE_NAME,
|
tableName: TABLE_NAME,
|
||||||
): SelectQueryBuilder<any> {
|
): SelectQueryBuilder<any> {
|
||||||
// filter berdasarkan statuses
|
|
||||||
if (!!baseFilter.statuses) {
|
|
||||||
queryBuilder.andWhere(
|
|
||||||
new Brackets((qb) => {
|
|
||||||
baseFilter.statuses.map((status) => {
|
|
||||||
// trim search
|
|
||||||
const statusData = status.includes("'")
|
|
||||||
? status.trim().replace(/'/g, "''").replace(/\s+/g, ' ')
|
|
||||||
: status.trim().replace(/\s+/g, ' ');
|
|
||||||
|
|
||||||
// jika searching status terdapat dalam enum, maka dia mencari specific data
|
|
||||||
// ? karena jika tidak, ketika dia search "active" maka "inactive" juga ikut
|
|
||||||
if (STATUS[statusData.toUpperCase()])
|
|
||||||
qb.orWhere(`${tableName}.status = :statusData`, {
|
|
||||||
statusData: statusData,
|
|
||||||
});
|
|
||||||
else
|
|
||||||
qb['orWhere'](
|
|
||||||
`${tableName}.status::text ILIKE '%${[statusData]}%'`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter berdasarkan id pembuat
|
// filter berdasarkan id pembuat
|
||||||
if (!!baseFilter.created_ids)
|
if (!!baseFilter.created_ids)
|
||||||
new WhereInQueryHelper(
|
new WhereInQueryHelper(
|
||||||
queryBuilder,
|
queryBuilder,
|
||||||
tableName,
|
tableName,
|
||||||
'created_id',
|
'creator_id',
|
||||||
baseFilter.created_ids,
|
baseFilter.created_ids,
|
||||||
'created_ids',
|
'creator_ids',
|
||||||
).getQuery();
|
).getQuery();
|
||||||
|
|
||||||
// filter berdasarkan tanggal terakhir dibuat
|
// filter berdasarkan tanggal terakhir dibuat
|
||||||
|
|
|
@ -63,7 +63,7 @@ export class ValidateRelationHelper<Entity> {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
throw new UnprocessableEntityException(message);
|
throw new UnprocessableEntityException(message);
|
||||||
} else if (data[`total_${relation.relation} `])
|
} else if (data[`total_${relation.relation}`] > 0)
|
||||||
throw new UnprocessableEntityException(message);
|
throw new UnprocessableEntityException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,15 @@ export abstract class BaseDataService<Entity> {
|
||||||
return await queryRunner.manager.save(newEntity);
|
return await queryRunner.manager.save(newEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createMany(
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
entityTarget: EntityTarget<Entity>,
|
||||||
|
entity: Entity[],
|
||||||
|
): Promise<Entity[]> {
|
||||||
|
const newEntity = queryRunner.manager.create(entityTarget, entity);
|
||||||
|
return await queryRunner.manager.save(newEntity);
|
||||||
|
}
|
||||||
|
|
||||||
async createBatch(
|
async createBatch(
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
entityTarget: EntityTarget<Entity>,
|
entityTarget: EntityTarget<Entity>,
|
||||||
|
@ -68,4 +77,8 @@ export abstract class BaseDataService<Entity> {
|
||||||
async getOneByOptions(findOneOptions): Promise<Entity> {
|
async getOneByOptions(findOneOptions): Promise<Entity> {
|
||||||
return await this.repository.findOne(findOneOptions);
|
return await this.repository.findOne(findOneOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getManyByOptions(findOneOptions): Promise<Entity[]> {
|
||||||
|
return await this.repository.find(findOneOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,11 @@ export abstract class BaseReadService<Entity> {
|
||||||
queryBuilder: SelectQueryBuilder<Entity>,
|
queryBuilder: SelectQueryBuilder<Entity>,
|
||||||
params: BaseFilterEntity,
|
params: BaseFilterEntity,
|
||||||
): Promise<PaginationResponse<Entity>> {
|
): Promise<PaginationResponse<Entity>> {
|
||||||
|
const limit = params.limit ?? 10;
|
||||||
|
const page = params.page ?? 1;
|
||||||
const [data, total] = await queryBuilder
|
const [data, total] = await queryBuilder
|
||||||
.take(+params.limit)
|
.take(+limit)
|
||||||
.skip(+params.limit * +params.page - +params.limit)
|
.skip(+limit * +page - +limit)
|
||||||
.getManyAndCount();
|
.getManyAndCount();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -25,7 +25,7 @@ export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
|
||||||
async process(): Promise<void> {
|
async process(): Promise<void> {
|
||||||
let totalFailed = 0;
|
let totalFailed = 0;
|
||||||
let totalSuccess = 0;
|
let totalSuccess = 0;
|
||||||
let messages = [];
|
const messages = [];
|
||||||
|
|
||||||
for (const id of this.dataIds) {
|
for (const id of this.dataIds) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,11 +4,14 @@ import { HttpStatus, NotFoundException } from '@nestjs/common';
|
||||||
import { OPERATION, STATUS } from 'src/core/strings/constants/base.constants';
|
import { OPERATION, STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
|
import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper';
|
||||||
import { RecordLog } from 'src/modules/configuration/log/domain/entities/log.event';
|
import { RecordLog } from 'src/modules/configuration/log/domain/entities/log.event';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
protected dataIds: string[];
|
protected dataIds: string[];
|
||||||
|
protected relations: string[] = [];
|
||||||
protected result: BatchResult;
|
protected result: BatchResult;
|
||||||
protected dataStatus: STATUS;
|
protected dataStatus: STATUS;
|
||||||
|
protected oldData: Entity;
|
||||||
abstract get entityTarget(): any;
|
abstract get entityTarget(): any;
|
||||||
|
|
||||||
setData(ids: string[], status: STATUS): void {
|
setData(ids: string[], status: STATUS): void {
|
||||||
|
@ -27,7 +30,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
async process(): Promise<void> {
|
async process(): Promise<void> {
|
||||||
let totalFailed = 0;
|
let totalFailed = 0;
|
||||||
let totalSuccess = 0;
|
let totalSuccess = 0;
|
||||||
let messages = [];
|
const messages = [];
|
||||||
|
|
||||||
for (const id of this.dataIds) {
|
for (const id of this.dataIds) {
|
||||||
try {
|
try {
|
||||||
|
@ -35,6 +38,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
id: id,
|
||||||
},
|
},
|
||||||
|
relations: this.relations,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
|
@ -44,6 +48,13 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
error: 'Entity Not Found',
|
error: 'Entity Not Found',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.oldData = _.cloneDeep(entity);
|
||||||
|
Object.assign(entity, {
|
||||||
|
status: this.dataStatus,
|
||||||
|
editor_id: this.user.id,
|
||||||
|
editor_name: this.user.name,
|
||||||
|
updated_at: new Date().getTime(),
|
||||||
|
});
|
||||||
|
|
||||||
await this.validateData(entity);
|
await this.validateData(entity);
|
||||||
await new ValidateRelationHelper(
|
await new ValidateRelationHelper(
|
||||||
|
@ -57,15 +68,10 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
this.queryRunner,
|
this.queryRunner,
|
||||||
this.entityTarget,
|
this.entityTarget,
|
||||||
{ id: id },
|
{ id: id },
|
||||||
{
|
entity,
|
||||||
status: this.dataStatus,
|
|
||||||
editor_id: this.user.id,
|
|
||||||
editor_name: this.user.name,
|
|
||||||
updated_at: new Date().getTime(),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.publishEvents(entity, result);
|
this.publishEvents(this.oldData, result);
|
||||||
|
|
||||||
totalSuccess = totalSuccess + 1;
|
totalSuccess = totalSuccess + 1;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -101,7 +107,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
|
||||||
if (!this.eventTopics.length) return;
|
if (!this.eventTopics.length) return;
|
||||||
for (const topic of this.eventTopics) {
|
for (const topic of this.eventTopics) {
|
||||||
let data;
|
let data;
|
||||||
if (!topic.relations) {
|
if (topic.relations?.length) {
|
||||||
data = await this.dataService.getOneByOptions({
|
data = await this.dataService.getOneByOptions({
|
||||||
where: {
|
where: {
|
||||||
id: dataNew.id,
|
id: dataNew.id,
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
import { BaseManager } from '../base.manager';
|
||||||
|
import {
|
||||||
|
EventTopics,
|
||||||
|
columnUniques,
|
||||||
|
validateRelations,
|
||||||
|
} from 'src/core/strings/constants/interface.constants';
|
||||||
|
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
|
||||||
|
import { SelectQueryBuilder } from 'typeorm';
|
||||||
|
|
||||||
|
export abstract class BaseChangePosition<Entity> extends BaseManager {
|
||||||
|
protected result: Entity;
|
||||||
|
protected duplicateColumn: string[];
|
||||||
|
protected startData: Entity;
|
||||||
|
protected endData: Entity;
|
||||||
|
protected columnSort: string;
|
||||||
|
|
||||||
|
protected firstDataId: number;
|
||||||
|
protected lastSort: number;
|
||||||
|
protected sortTo: number;
|
||||||
|
|
||||||
|
abstract get entityTarget(): any;
|
||||||
|
|
||||||
|
setData(entity: Entity, columnSort: string): void {
|
||||||
|
this.data = entity;
|
||||||
|
this.columnSort = columnSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeProcess(): Promise<void> {
|
||||||
|
if (!this.data?.end || this.data.start == this.data?.end) {
|
||||||
|
throw new UnprocessableEntityException({
|
||||||
|
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||||
|
message: 'Please drag to another position',
|
||||||
|
error: 'Unprocessable Entity',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startData = await this.dataService.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id: this.data.start,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.startData) {
|
||||||
|
throw new UnprocessableEntityException({
|
||||||
|
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||||
|
message: `Entity with id : ${this.data.start} not found`,
|
||||||
|
error: 'Unprocessable Entity',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.endData = await this.dataService.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id: this.data.end,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.endData) {
|
||||||
|
throw new UnprocessableEntityException({
|
||||||
|
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||||
|
message: `Entity with id : ${this.data.end} not found`,
|
||||||
|
error: 'Unprocessable Entity',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
|
||||||
|
// drag from up
|
||||||
|
this.firstDataId = this.startData[this.columnSort];
|
||||||
|
this.lastSort = this.endData[this.columnSort];
|
||||||
|
this.sortTo = this.lastSort;
|
||||||
|
} else if (
|
||||||
|
this.endData[this.columnSort] < this.startData[this.columnSort]
|
||||||
|
) {
|
||||||
|
// drag from bottom
|
||||||
|
this.firstDataId = this.endData[this.columnSort];
|
||||||
|
this.lastSort = this.startData[this.columnSort];
|
||||||
|
this.sortTo = this.firstDataId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareData(): Promise<void> {
|
||||||
|
Object.assign(this.data, {
|
||||||
|
creator_id: this.user.id,
|
||||||
|
creator_name: this.user.name,
|
||||||
|
created_at: new Date().getTime(),
|
||||||
|
updated_at: new Date().getTime(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async validateProcess(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async process(): Promise<void> {
|
||||||
|
let dataArrange: Entity[];
|
||||||
|
|
||||||
|
const queryBuilder = this.dataService
|
||||||
|
.getRepository()
|
||||||
|
.createQueryBuilder(this.tableName)
|
||||||
|
.where(`${this.tableName}.${this.columnSort} between :data1 and :data2`, {
|
||||||
|
data1: this.firstDataId,
|
||||||
|
data2: this.lastSort,
|
||||||
|
});
|
||||||
|
|
||||||
|
const datas = await queryBuilder
|
||||||
|
.orderBy(`${this.tableName}.${this.columnSort}`, 'ASC')
|
||||||
|
.getManyAndCount();
|
||||||
|
|
||||||
|
if (datas[0].length) {
|
||||||
|
let dataFirst = datas[0][0][this.columnSort];
|
||||||
|
const data = datas[0];
|
||||||
|
const length = datas[1];
|
||||||
|
|
||||||
|
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
|
||||||
|
// drag from above
|
||||||
|
const dataDragged = data[0];
|
||||||
|
const arraySlice = data.slice(1, length);
|
||||||
|
dataArrange = arraySlice.concat([dataDragged]);
|
||||||
|
} else if (
|
||||||
|
this.endData[this.columnSort] < this.startData[this.columnSort]
|
||||||
|
) {
|
||||||
|
// drag from bottom
|
||||||
|
const dataDragged = data[length - 1];
|
||||||
|
const arraySlice = data.slice(0, length - 1);
|
||||||
|
|
||||||
|
dataArrange = [dataDragged].concat(arraySlice);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
dataArrange[i][this.columnSort] = dataFirst;
|
||||||
|
dataFirst++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.dataService.createMany(
|
||||||
|
this.queryRunner,
|
||||||
|
this.entityTarget,
|
||||||
|
dataArrange,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get validateRelations(): validateRelations[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get eventTopics(): EventTopics[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getResult(): string {
|
||||||
|
return `Success! Data ${this.startData['name']} successfully moved to ${this.sortTo}`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import {
|
||||||
columnUniques,
|
columnUniques,
|
||||||
validateRelations,
|
validateRelations,
|
||||||
} from 'src/core/strings/constants/interface.constants';
|
} from 'src/core/strings/constants/interface.constants';
|
||||||
|
import { MoveFilePathHelper } from 'src/core/helpers/path/move-file-path.helper';
|
||||||
|
|
||||||
export abstract class BaseCreateManager<Entity> extends BaseManager {
|
export abstract class BaseCreateManager<Entity> extends BaseManager {
|
||||||
protected result: Entity;
|
protected result: Entity;
|
||||||
|
@ -43,6 +44,15 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
async process(): Promise<void> {
|
async process(): Promise<void> {
|
||||||
|
const keys = Object.keys(this.data);
|
||||||
|
if (
|
||||||
|
(keys.includes('qr_image') || keys.includes('image_url')) &&
|
||||||
|
(this.data['image_url']?.includes('tmp') ||
|
||||||
|
this.data['qr_image']?.includes('tmp'))
|
||||||
|
) {
|
||||||
|
await MoveFilePathHelper(this.data);
|
||||||
|
}
|
||||||
|
|
||||||
this.result = await this.dataService.create(
|
this.result = await this.dataService.create(
|
||||||
this.queryRunner,
|
this.queryRunner,
|
||||||
this.entityTarget,
|
this.entityTarget,
|
||||||
|
@ -75,11 +85,21 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
|
||||||
|
|
||||||
if (!this.eventTopics.length) return;
|
if (!this.eventTopics.length) return;
|
||||||
for (const topic of this.eventTopics) {
|
for (const topic of this.eventTopics) {
|
||||||
|
let data;
|
||||||
|
if (!topic.data) {
|
||||||
|
data = await this.dataService.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id: this.result['id'],
|
||||||
|
},
|
||||||
|
relations: topic.relations,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.eventBus.publishAll([
|
this.eventBus.publishAll([
|
||||||
new topic.topic({
|
new topic.topic({
|
||||||
id: this.result['id'],
|
id: data?.['id'] ?? topic?.data?.['id'],
|
||||||
old: null,
|
old: null,
|
||||||
data: topic.data,
|
data: data ?? topic.data,
|
||||||
user: this.user,
|
user: this.user,
|
||||||
description: '',
|
description: '',
|
||||||
module: this.tableName,
|
module: this.tableName,
|
||||||
|
|
|
@ -5,7 +5,7 @@ export abstract class BaseCustomManager<Entity> extends BaseManager {
|
||||||
protected result: any;
|
protected result: any;
|
||||||
abstract get entityTarget(): any;
|
abstract get entityTarget(): any;
|
||||||
|
|
||||||
setData(entity: Entity): void {
|
setData(entity: any): void {
|
||||||
this.data = entity;
|
this.data = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ export abstract class BaseDeleteManager<Entity> extends BaseManager {
|
||||||
this.eventBus.publishAll([
|
this.eventBus.publishAll([
|
||||||
new topic.topic({
|
new topic.topic({
|
||||||
id: topic.data['id'],
|
id: topic.data['id'],
|
||||||
old: null,
|
old: this.data,
|
||||||
data: topic.data,
|
data: topic.data,
|
||||||
user: this.user,
|
user: this.user,
|
||||||
description: '',
|
description: '',
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from 'src/core/helpers/query/default-filter.helper';
|
} from 'src/core/helpers/query/default-filter.helper';
|
||||||
import { Param } from '../../entities/base-filter.entity';
|
import { Param } from '../../entities/base-filter.entity';
|
||||||
import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper';
|
import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper';
|
||||||
|
import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
|
|
||||||
export abstract class BaseIndexManager<Entity> extends BaseReadManager {
|
export abstract class BaseIndexManager<Entity> extends BaseReadManager {
|
||||||
protected result: PaginationResponse<Entity>;
|
protected result: PaginationResponse<Entity>;
|
||||||
|
@ -19,6 +20,7 @@ export abstract class BaseIndexManager<Entity> extends BaseReadManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
async process(): Promise<void> {
|
async process(): Promise<void> {
|
||||||
|
const specificFilter = this.specificFilter;
|
||||||
const { joinRelations, selectRelations, countRelations } = this.relations;
|
const { joinRelations, selectRelations, countRelations } = this.relations;
|
||||||
|
|
||||||
if (joinRelations?.length)
|
if (joinRelations?.length)
|
||||||
|
@ -40,10 +42,26 @@ export abstract class BaseIndexManager<Entity> extends BaseReadManager {
|
||||||
|
|
||||||
if (this.selects?.length) this.queryBuilder.select(this.selects);
|
if (this.selects?.length) this.queryBuilder.select(this.selects);
|
||||||
|
|
||||||
|
if (this.filterParam.statuses?.length > 0) {
|
||||||
|
const data = this.filterParam.statuses.map((status) => {
|
||||||
|
const statusData = status.includes("'")
|
||||||
|
? status.trim().replace(/'/g, "''").replace(/\s+/g, ' ')
|
||||||
|
: status.trim().replace(/\s+/g, ' ');
|
||||||
|
|
||||||
|
// jika searching status terdapat dalam enum, maka dia mencari specific data
|
||||||
|
// ? karena jika tidak, ketika dia search "active" maka "inactive" juga ikut
|
||||||
|
return STATUS[statusData.toUpperCase()] ?? statusData;
|
||||||
|
});
|
||||||
|
specificFilter.push({
|
||||||
|
cols: `${this.tableName}.status::text`,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
new SpecificSearchFilter<Entity>(
|
new SpecificSearchFilter<Entity>(
|
||||||
this.queryBuilder,
|
this.queryBuilder,
|
||||||
this.tableName,
|
this.tableName,
|
||||||
this.specificFilter,
|
specificFilter,
|
||||||
).getFilter();
|
).getFilter();
|
||||||
|
|
||||||
getOrderBy(this.filterParam, this.queryBuilder, this.tableName);
|
getOrderBy(this.filterParam, this.queryBuilder, this.tableName);
|
||||||
|
|
|
@ -9,6 +9,7 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
|
||||||
protected result: Entity;
|
protected result: Entity;
|
||||||
protected oldData: Entity;
|
protected oldData: Entity;
|
||||||
protected dataStatus: STATUS;
|
protected dataStatus: STATUS;
|
||||||
|
protected relations = [];
|
||||||
protected duplicateColumn: string[];
|
protected duplicateColumn: string[];
|
||||||
abstract get entityTarget(): any;
|
abstract get entityTarget(): any;
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
|
||||||
where: {
|
where: {
|
||||||
id: this.dataId,
|
id: this.dataId,
|
||||||
},
|
},
|
||||||
|
relations: this.relations,
|
||||||
});
|
});
|
||||||
this.oldData = _.cloneDeep(this.data);
|
this.oldData = _.cloneDeep(this.data);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,18 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareData(): Promise<void> {
|
async prepareData(): Promise<void> {
|
||||||
|
this.oldData = await this.dataService.getOneByOptions({
|
||||||
|
where: { id: this.dataId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.oldData) {
|
||||||
|
throw new NotFoundException({
|
||||||
|
statusCode: HttpStatus.NOT_FOUND,
|
||||||
|
message: `Failed! Entity with id ${this.dataId} not found`,
|
||||||
|
error: 'Entity Not Found',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(this.data, {
|
Object.assign(this.data, {
|
||||||
editor_id: this.user.id,
|
editor_id: this.user.id,
|
||||||
editor_name: this.user.name,
|
editor_name: this.user.name,
|
||||||
|
@ -38,18 +50,6 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
async process(): Promise<void> {
|
async process(): Promise<void> {
|
||||||
this.oldData = await this.dataService.getOneByOptions({
|
|
||||||
where: { id: this.dataId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.oldData) {
|
|
||||||
throw new NotFoundException({
|
|
||||||
statusCode: HttpStatus.NOT_FOUND,
|
|
||||||
message: `Failed! Entity with id ${this.dataId} not found`,
|
|
||||||
error: 'Entity Not Found',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await new ValidateRelationHelper(
|
await new ValidateRelationHelper(
|
||||||
this.dataId,
|
this.dataId,
|
||||||
this.dataService,
|
this.dataService,
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { BaseDataOrchestrator } from './base-data.orchestrator';
|
||||||
export abstract class BaseDataTransactionOrchestrator<
|
export abstract class BaseDataTransactionOrchestrator<
|
||||||
Entity,
|
Entity,
|
||||||
> extends BaseDataOrchestrator<Entity> {
|
> extends BaseDataOrchestrator<Entity> {
|
||||||
abstract active(dataId: string): Promise<String>;
|
abstract active(dataId: string): Promise<string>;
|
||||||
abstract confirm(dataId: string): Promise<String>;
|
abstract confirm(dataId: string): Promise<string>;
|
||||||
abstract inactive(dataId: string): Promise<String>;
|
abstract inactive(dataId: string): Promise<string>;
|
||||||
abstract batchConfirm(dataIds: string[]): Promise<BatchResult>;
|
abstract batchConfirm(dataIds: string[]): Promise<BatchResult>;
|
||||||
abstract batchActive(dataIds: string[]): Promise<BatchResult>;
|
abstract batchActive(dataIds: string[]): Promise<BatchResult>;
|
||||||
abstract batchInactive(dataIds: string[]): Promise<BatchResult>;
|
abstract batchInactive(dataIds: string[]): Promise<BatchResult>;
|
||||||
|
|
|
@ -3,6 +3,6 @@ import { BatchResult } from 'src/core/response/domain/ok-response.interface';
|
||||||
export abstract class BaseDataOrchestrator<Entity> {
|
export abstract class BaseDataOrchestrator<Entity> {
|
||||||
abstract create(data: Entity): Promise<Entity>;
|
abstract create(data: Entity): Promise<Entity>;
|
||||||
abstract update(dataId: string, data: Entity): Promise<Entity>;
|
abstract update(dataId: string, data: Entity): Promise<Entity>;
|
||||||
abstract delete(dataId: string): Promise<String>;
|
abstract delete(dataId: string): Promise<string>;
|
||||||
abstract batchDelete(dataIds: string[]): Promise<BatchResult>;
|
abstract batchDelete(dataIds: string[]): Promise<BatchResult>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export class ChangePositionDto {
|
||||||
|
start: string;
|
||||||
|
end: string;
|
||||||
|
}
|
|
@ -6,7 +6,9 @@ export enum STATUS {
|
||||||
DRAFT = 'draft',
|
DRAFT = 'draft',
|
||||||
EXPIRED = 'expired',
|
EXPIRED = 'expired',
|
||||||
INACTIVE = 'inactive',
|
INACTIVE = 'inactive',
|
||||||
|
PARTIAL_REFUND = 'partial refund',
|
||||||
PENDING = 'pending',
|
PENDING = 'pending',
|
||||||
|
PROCESS_REFUND = 'proses refund',
|
||||||
REFUNDED = 'refunded',
|
REFUNDED = 'refunded',
|
||||||
REJECTED = 'rejected',
|
REJECTED = 'rejected',
|
||||||
SETTLED = 'settled',
|
SETTLED = 'settled',
|
||||||
|
@ -46,3 +48,5 @@ export const BLANK_USER = {
|
||||||
role: null,
|
role: null,
|
||||||
user_privilege_id: null,
|
user_privilege_id: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const EMPTY_UUID = '00000000-0000-0000-0000-000000000000';
|
||||||
|
|
|
@ -24,7 +24,7 @@ export interface validateRelations {
|
||||||
|
|
||||||
export interface columnUniques {
|
export interface columnUniques {
|
||||||
column: string;
|
column: string;
|
||||||
query?: Object;
|
query?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEvent<Entity = any> {
|
export interface IEvent<Entity = any> {
|
||||||
|
|
|
@ -1,15 +1,27 @@
|
||||||
export enum MODULE_NAME {
|
export enum MODULE_NAME {
|
||||||
|
BANNER = 'banners',
|
||||||
|
FAQ = 'faqs',
|
||||||
|
GATE = 'gates',
|
||||||
ITEM = 'items',
|
ITEM = 'items',
|
||||||
ITEM_CATEGORY = 'item-categories',
|
ITEM_CATEGORY = 'item-categories',
|
||||||
ITEM_RATE = 'item-rates',
|
ITEM_RATE = 'item-rates',
|
||||||
|
NEWS = 'news',
|
||||||
PAYMENT_METHOD = 'payment-methods',
|
PAYMENT_METHOD = 'payment-methods',
|
||||||
|
RECONCILIATION = 'reconciliations',
|
||||||
|
REFUND = 'refunds',
|
||||||
SEASON_TYPE = 'season-types',
|
SEASON_TYPE = 'season-types',
|
||||||
SEASON_PERIOD = 'season-periods',
|
SEASON_PERIOD = 'season-periods',
|
||||||
TAX = 'taxes',
|
TAX = 'taxes',
|
||||||
|
TERM_CONDITION = 'term_conditions',
|
||||||
TENANT = 'tenants',
|
TENANT = 'tenants',
|
||||||
|
TRANSACTION = 'transactions',
|
||||||
USER = 'users',
|
USER = 'users',
|
||||||
USER_PRIVILEGE = 'user-privileges',
|
USER_PRIVILEGE = 'user-privileges',
|
||||||
USER_PRIVILEGE_CONFIGURATION = 'user-privilege-configurations',
|
USER_PRIVILEGE_CONFIGURATION = 'user-privilege-configurations',
|
||||||
VIP_CATEGORY = 'vip-categories',
|
VIP_CATEGORY = 'vip-categories',
|
||||||
VIP_CODE = 'vip-codes',
|
VIP_CODE = 'vip-codes',
|
||||||
|
|
||||||
|
REPORT = 'report',
|
||||||
|
REPORT_BOOKMARK = 'report-bookmark',
|
||||||
|
REPORT_EXPORT = 'report-export',
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ export const PrivilegeAdminConstant = [
|
||||||
index: 4,
|
index: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menu: 'REKONSILIASI',
|
menu: 'RECONCILIATION',
|
||||||
menu_label: 'Rekonsiliasi',
|
menu_label: 'Rekonsiliasi',
|
||||||
actions: [
|
actions: [
|
||||||
PrivilegeAction.VIEW,
|
PrivilegeAction.VIEW,
|
||||||
|
@ -126,13 +126,13 @@ export const PrivilegeAdminConstant = [
|
||||||
index: 11,
|
index: 11,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menu: 'LAPORAN',
|
menu: 'REPORT',
|
||||||
menu_label: 'Laporan',
|
menu_label: 'Laporan',
|
||||||
actions: [PrivilegeAction.VIEW],
|
actions: [PrivilegeAction.VIEW],
|
||||||
index: 12,
|
index: 12,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menu: 'DISKON_CODE',
|
menu: 'DISCOUNT_CODE',
|
||||||
menu_label: 'Generate Diskon Kode',
|
menu_label: 'Generate Diskon Kode',
|
||||||
actions: [PrivilegeAction.CREATE],
|
actions: [PrivilegeAction.CREATE],
|
||||||
index: 13,
|
index: 13,
|
||||||
|
@ -170,7 +170,7 @@ export const PrivilegePOSConstant = [
|
||||||
index: 17,
|
index: 17,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
menu: 'POS_DISKON_CODE',
|
menu: 'POS_DISCOUNT_CODE',
|
||||||
menu_label: 'Generate Diskon Kode',
|
menu_label: 'Generate Diskon Kode',
|
||||||
actions: [PrivilegeAction.CREATE],
|
actions: [PrivilegeAction.CREATE],
|
||||||
index: 18,
|
index: 18,
|
||||||
|
|
|
@ -1,15 +1,25 @@
|
||||||
export enum TABLE_NAME {
|
export enum TABLE_NAME {
|
||||||
|
BANNER = 'banners',
|
||||||
ERROR_LOG = 'log_errors',
|
ERROR_LOG = 'log_errors',
|
||||||
|
FAQ = 'faqs',
|
||||||
ITEM = 'items',
|
ITEM = 'items',
|
||||||
ITEM_CATEGORY = 'item_categories',
|
ITEM_CATEGORY = 'item_categories',
|
||||||
ITEM_RATE = 'item_rates',
|
ITEM_RATE = 'item_rates',
|
||||||
|
GATE = 'gates',
|
||||||
LOG = 'logs',
|
LOG = 'logs',
|
||||||
|
NEWS = 'news',
|
||||||
PAYMENT_METHOD = 'payment_methods',
|
PAYMENT_METHOD = 'payment_methods',
|
||||||
PRICE_FORMULA = 'price_formulas',
|
PRICE_FORMULA = 'price_formulas',
|
||||||
|
REFUND = 'refunds',
|
||||||
|
REFUND_ITEM = 'refund_items',
|
||||||
SEASON_TYPE = 'season_types',
|
SEASON_TYPE = 'season_types',
|
||||||
SEASON_PERIOD = 'season_periods',
|
SEASON_PERIOD = 'season_periods',
|
||||||
TAX = 'taxes',
|
TAX = 'taxes',
|
||||||
|
TERM_CONDITION = 'term_conditions',
|
||||||
TENANT = 'tenants',
|
TENANT = 'tenants',
|
||||||
|
TRANSACTION = 'transactions',
|
||||||
|
TRANSACTION_ITEM = 'transaction_items',
|
||||||
|
TRANSACTION_TAX = 'transaction_taxes',
|
||||||
USER = 'users',
|
USER = 'users',
|
||||||
USER_PRIVILEGE = 'user_privileges',
|
USER_PRIVILEGE = 'user_privileges',
|
||||||
USER_PRIVILEGE_CONFIGURATION = 'user_privilege_configurations',
|
USER_PRIVILEGE_CONFIGURATION = 'user_privilege_configurations',
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
|
||||||
import { Public } from 'src/core/guards';
|
import { Public } from 'src/core/guards';
|
||||||
|
|
||||||
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - read`)
|
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - read`)
|
||||||
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`)
|
@Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
|
||||||
@Public(false)
|
@Public(false)
|
||||||
@ApiBearerAuth('JWT')
|
@ApiBearerAuth('JWT')
|
||||||
export class {{pascalCase name}}ReadController {
|
export class {{pascalCase name}}ReadController {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto'
|
||||||
import { Public } from 'src/core/guards';
|
import { Public } from 'src/core/guards';
|
||||||
|
|
||||||
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
|
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
|
||||||
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`)
|
@Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
|
||||||
@Public(false)
|
@Public(false)
|
||||||
@ApiBearerAuth('JWT')
|
@ApiBearerAuth('JWT')
|
||||||
export class {{pascalCase name}}DataController {
|
export class {{pascalCase name}}DataController {
|
||||||
|
@ -36,7 +36,7 @@ export class {{pascalCase name}}DataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/active')
|
@Patch(':id/active')
|
||||||
async active(@Param('id') dataId: string): Promise<String> {
|
async active(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.active(dataId);
|
return await this.orchestrator.active(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ export class {{pascalCase name}}DataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/confirm')
|
@Patch(':id/confirm')
|
||||||
async confirm(@Param('id') dataId: string): Promise<String> {
|
async confirm(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.confirm(dataId);
|
return await this.orchestrator.confirm(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export class {{pascalCase name}}DataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/inactive')
|
@Patch(':id/inactive')
|
||||||
async inactive(@Param('id') dataId: string): Promise<String> {
|
async inactive(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.inactive(dataId);
|
return await this.orchestrator.inactive(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export class {{pascalCase name}}DataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async delete(@Param('id') dataId: string): Promise<String> {
|
async delete(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.delete(dataId);
|
return await this.orchestrator.delete(dataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
import { Public } from 'src/core/guards';
|
import { Public } from 'src/core/guards';
|
||||||
|
|
||||||
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
|
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
|
||||||
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`)
|
@Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
|
||||||
@Public(false)
|
@Public(false)
|
||||||
@ApiBearerAuth('JWT')
|
@ApiBearerAuth('JWT')
|
||||||
export class {{pascalCase name}}DataController {
|
export class {{pascalCase name}}DataController {
|
||||||
|
@ -43,7 +43,7 @@ import {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async delete(@Param('id') dataId: string): Promise<String> {
|
async delete(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.delete(dataId);
|
return await this.orchestrator.delete(dataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
|
||||||
return this.updateManager.getResult();
|
return this.updateManager.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.{{constantCase name}});
|
this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
||||||
await this.deleteManager.execute();
|
await this.deleteManager.execute();
|
||||||
|
@ -65,7 +65,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
|
||||||
return this.batchDeleteManager.getResult();
|
return this.batchDeleteManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async active(dataId): Promise<String> {
|
async active(dataId): Promise<string> {
|
||||||
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.activeManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
this.activeManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
||||||
await this.activeManager.execute();
|
await this.activeManager.execute();
|
||||||
|
@ -82,7 +82,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
|
||||||
return this.batchActiveManager.getResult();
|
return this.batchActiveManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async confirm(dataId): Promise<String> {
|
async confirm(dataId): Promise<string> {
|
||||||
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.confirmManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
this.confirmManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
||||||
await this.confirmManager.execute();
|
await this.confirmManager.execute();
|
||||||
|
@ -99,7 +99,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
|
||||||
return this.batchConfirmManager.getResult();
|
return this.batchConfirmManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async inactive(dataId): Promise<String> {
|
async inactive(dataId): Promise<string> {
|
||||||
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
||||||
this.inactiveManager.setService(
|
this.inactiveManager.setService(
|
||||||
this.serviceData,
|
this.serviceData,
|
||||||
|
|
|
@ -36,7 +36,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
|
||||||
return this.updateManager.getResult();
|
return this.updateManager.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.{{constantCase name}});
|
this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
|
||||||
await this.deleteManager.execute();
|
await this.deleteManager.execute();
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class Transaction1719572714752 implements MigrationInterface {
|
||||||
|
name = 'Transaction1719572714752';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "transaction_items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "item_id" character varying, "item_name" character varying, "item_type" character varying, "item_price" bigint, "item_tenant_id" character varying, "item_tenant_name" character varying, "item_tenant_share_margin" numeric, "total_price" numeric, "total_hpp" numeric, "total_profit" numeric, "total_share_tenant" numeric, "qty" integer, "transaction_id" uuid, CONSTRAINT "PK_ff5a487ad820dccafd53bebf578" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "transaction_taxes" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "tax_id" character varying, "tax_name" character varying, "taxt_value" character varying, "transaction_id" uuid, CONSTRAINT "PK_208b2abdb10640e1991972fc754" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_type_enum" AS ENUM('counter', 'admin', 'online')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_customer_type_enum" AS ENUM('group', 'vip')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_payment_type_enum" AS ENUM('midtrans', 'bank transfer', 'qris', 'counter', 'cash', 'credit card', 'debit', 'e-money')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "transactions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."transactions_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."transactions_type_enum" NOT NULL DEFAULT 'admin', "invoice_code" character varying, "creator_counter_no" integer, "season_period_id" character varying, "season_period_name" character varying, "season_period_type_id" character varying, "season_period_type_name" character varying, "customer_type" "public"."transactions_customer_type_enum", "customer_category_id" character varying, "customer_category_name" character varying, "customer_name" character varying, "customer_phone" character varying, "customer_email" character varying, "customer_description" character varying, "no_of_group" character varying, "booking_date" date, "settlement_date" date, "invoice_date" date, "discount_code_id" character varying, "discount_code" character varying, "discount_percentage" integer, "discount_value" numeric, "payment_type" "public"."transactions_payment_type_enum" NOT NULL DEFAULT 'bank transfer', "payment_type_method_id" character varying, "payment_type_method_name" character varying, "payment_type_method_qr" character varying, "payment_card_information" character varying, "payment_code_reference" character varying, "payment_date" date, "payment_sub_total" numeric, "payment_discount_total" numeric, "payment_total" numeric, "payment_total_pay" numeric, "payment_change" numeric, "payment_total_share" numeric, "payment_total_tax" numeric, "payment_total_profit" numeric, "profit_share_formula" character varying, "sales_price_formula" character varying, CONSTRAINT "PK_a219afd8dd77ed80f5a862f1db9" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD CONSTRAINT "FK_5926425896b30c0d681fe879af0" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" ADD CONSTRAINT "FK_d21db1756c6656efc7c082fbaa6" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" DROP CONSTRAINT "FK_d21db1756c6656efc7c082fbaa6"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP CONSTRAINT "FK_5926425896b30c0d681fe879af0"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "transactions"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_payment_type_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_customer_type_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."transactions_type_enum"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."transactions_status_enum"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "transaction_taxes"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "transaction_items"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddReconciliationToTransaction1719925690145
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'AddReconciliationToTransaction1719925690145';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "is_recap_transaction" boolean NOT NULL DEFAULT true`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "payment_type_method_number" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "reconciliation_mdr" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_reconciliation_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "reconciliation_status" "public"."transactions_reconciliation_status_enum" NOT NULL DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "reconciliation_confirm_date" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "reconciliation_confirm_by" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "payment_total_net_profit" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "payment_total_net_profit"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "reconciliation_confirm_by"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "reconciliation_confirm_date"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "reconciliation_status"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_reconciliation_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "reconciliation_mdr"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "payment_type_method_number"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "is_recap_transaction"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateTableTransaction1719934464407 implements MigrationInterface {
|
||||||
|
name = 'UpdateTableTransaction1719934464407';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "item_hpp" bigint`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "item_category_id" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "item_category_name" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "item_bundlings" json`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_invoice_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "sending_invoice_status" "public"."transactions_sending_invoice_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "sending_invoice_at" bigint`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_qr_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "sending_qr_status" "public"."transactions_sending_qr_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "sending_qr_at" bigint`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "sending_qr_at"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "sending_qr_status"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_qr_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "sending_invoice_at"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "sending_invoice_status"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_invoice_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "item_bundlings"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "item_category_name"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "item_category_id"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "item_hpp"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddColumnTypeReportBookmark1719982860855
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'AddColumnTypeReportBookmark1719982860855';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."report_bookmark_type_enum" AS ENUM('TABLE_CONFIG', 'FILTER_TABLE')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "report_bookmark" ADD "type" "public"."report_bookmark_type_enum" NOT NULL DEFAULT 'TABLE_CONFIG'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "report_bookmark" DROP COLUMN "type"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."report_bookmark_type_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateDefaultColumnTransaction1720077765890
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'UpdateDefaultColumnTransaction1720077765890';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "is_recap_transaction" SET DEFAULT false`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "is_recap_transaction" SET DEFAULT true`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateTableTransaction1720436852936 implements MigrationInterface {
|
||||||
|
name = 'UpdateTableTransaction1720436852936';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" ADD "tax_total_value" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" ADD "taxt_value" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" ADD "taxt_value" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_taxes" DROP COLUMN "tax_total_value"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateTableTransaction1720767689625 implements MigrationInterface {
|
||||||
|
name = 'UpdateTableTransaction1720767689625';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "qty_remaining" integer`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`ALTER TABLE "transaction_items" ADD "taxes" json`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "payment_total_dpp" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "payment_total_dpp"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "taxes"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "qty_remaining"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class Refund1720768975877 implements MigrationInterface {
|
||||||
|
name = 'Refund1720768975877';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."refunds_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."refunds_type_enum" AS ENUM('pengembalian booking', 'pengembalian wahana')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "refunds" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."refunds_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."refunds_type_enum" NOT NULL DEFAULT 'pengembalian booking', "code" character varying, "request_date" date, "refund_date" date, "refund_total" numeric, "bank_name" character varying, "bank_account_name" character varying, "bank_account_number" character varying, "transaction_id" uuid, CONSTRAINT "REL_8bb3b7579f49990d2e77684acd" UNIQUE ("transaction_id"), CONSTRAINT "PK_5106efb01eeda7e49a78b869738" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "refund_items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "qty_refund" numeric, "refund_total" numeric, "refund_item_id" uuid, "transaction_item_id" uuid, CONSTRAINT "REL_07b481a163c219f5de8fb1c90b" UNIQUE ("transaction_item_id"), CONSTRAINT "PK_ef892918375a6101948b90f1140" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ADD CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_2a4bd60fb8a9c37f902f4f3da67" FOREIGN KEY ("refund_item_id") REFERENCES "refunds"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3" FOREIGN KEY ("transaction_item_id") REFERENCES "transaction_items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_2a4bd60fb8a9c37f902f4f3da67"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" DROP CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "refund_items"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "refunds"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."refunds_type_enum"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,461 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateEnumStatus1720774145470 implements MigrationInterface {
|
||||||
|
name = 'UpdateEnumStatus1720774145470';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."item_categories_status_enum" RENAME TO "item_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."item_categories_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" TYPE "public"."item_categories_status_enum" USING "status"::"text"::"public"."item_categories_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."item_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."season_types_status_enum" RENAME TO "season_types_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."season_types_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" TYPE "public"."season_types_status_enum" USING "status"::"text"::"public"."season_types_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."season_types_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."season_periods_status_enum" RENAME TO "season_periods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."season_periods_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" TYPE "public"."season_periods_status_enum" USING "status"::"text"::"public"."season_periods_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."season_periods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."items_status_enum" RENAME TO "items_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."items_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" TYPE "public"."items_status_enum" USING "status"::"text"::"public"."items_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."items_status_enum_old"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."users_status_enum" RENAME TO "users_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."users_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" TYPE "public"."users_status_enum" USING "status"::"text"::"public"."users_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."users_status_enum_old"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."user_privileges_status_enum" RENAME TO "user_privileges_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."user_privileges_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" TYPE "public"."user_privileges_status_enum" USING "status"::"text"::"public"."user_privileges_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."user_privileges_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."refunds_status_enum" RENAME TO "refunds_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."refunds_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" TYPE "public"."refunds_status_enum" USING "status"::"text"::"public"."refunds_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum_old"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_status_enum" RENAME TO "transactions_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" TYPE "public"."transactions_status_enum" USING "status"::"text"::"public"."transactions_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_reconciliation_status_enum" RENAME TO "transactions_reconciliation_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_reconciliation_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" TYPE "public"."transactions_reconciliation_status_enum" USING "reconciliation_status"::"text"::"public"."transactions_reconciliation_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_reconciliation_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_sending_invoice_status_enum" RENAME TO "transactions_sending_invoice_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_invoice_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "sending_invoice_status" TYPE "public"."transactions_sending_invoice_status_enum" USING "sending_invoice_status"::"text"::"public"."transactions_sending_invoice_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_invoice_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_sending_qr_status_enum" RENAME TO "transactions_sending_qr_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_qr_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "sending_qr_status" TYPE "public"."transactions_sending_qr_status_enum" USING "sending_qr_status"::"text"::"public"."transactions_sending_qr_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_qr_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."vip_categories_status_enum" RENAME TO "vip_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."vip_categories_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" TYPE "public"."vip_categories_status_enum" USING "status"::"text"::"public"."vip_categories_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."vip_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."taxes_status_enum" RENAME TO "taxes_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."taxes_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" TYPE "public"."taxes_status_enum" USING "status"::"text"::"public"."taxes_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."taxes_status_enum_old"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."payment_methods_status_enum" RENAME TO "payment_methods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."payment_methods_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" TYPE "public"."payment_methods_status_enum" USING "status"::"text"::"public"."payment_methods_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."payment_methods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."payment_methods_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" TYPE "public"."payment_methods_status_enum_old" USING "status"::"text"::"public"."payment_methods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "payment_methods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."payment_methods_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."payment_methods_status_enum_old" RENAME TO "payment_methods_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."taxes_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" TYPE "public"."taxes_status_enum_old" USING "status"::"text"::"public"."taxes_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."taxes_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."taxes_status_enum_old" RENAME TO "taxes_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."vip_categories_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" TYPE "public"."vip_categories_status_enum_old" USING "status"::"text"::"public"."vip_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "vip_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."vip_categories_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."vip_categories_status_enum_old" RENAME TO "vip_categories_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_qr_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "sending_qr_status" TYPE "public"."transactions_sending_qr_status_enum_old" USING "sending_qr_status"::"text"::"public"."transactions_sending_qr_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_qr_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_sending_qr_status_enum_old" RENAME TO "transactions_sending_qr_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_sending_invoice_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "sending_invoice_status" TYPE "public"."transactions_sending_invoice_status_enum_old" USING "sending_invoice_status"::"text"::"public"."transactions_sending_invoice_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_sending_invoice_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_sending_invoice_status_enum_old" RENAME TO "transactions_sending_invoice_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_reconciliation_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" TYPE "public"."transactions_reconciliation_status_enum_old" USING "reconciliation_status"::"text"::"public"."transactions_reconciliation_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`DROP TYPE "public"."transactions_reconciliation_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_reconciliation_status_enum_old" RENAME TO "transactions_reconciliation_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."transactions_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" TYPE "public"."transactions_status_enum_old" USING "status"::"text"::"public"."transactions_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."transactions_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."transactions_status_enum_old" RENAME TO "transactions_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."refunds_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" TYPE "public"."refunds_status_enum_old" USING "status"::"text"::"public"."refunds_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."refunds_status_enum_old" RENAME TO "refunds_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."user_privileges_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" TYPE "public"."user_privileges_status_enum_old" USING "status"::"text"::"public"."user_privileges_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "user_privileges" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."user_privileges_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."user_privileges_status_enum_old" RENAME TO "user_privileges_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."users_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" TYPE "public"."users_status_enum_old" USING "status"::"text"::"public"."users_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "users" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."users_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."users_status_enum_old" RENAME TO "users_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."items_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" TYPE "public"."items_status_enum_old" USING "status"::"text"::"public"."items_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."items_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."items_status_enum_old" RENAME TO "items_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."season_periods_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" TYPE "public"."season_periods_status_enum_old" USING "status"::"text"::"public"."season_periods_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_periods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."season_periods_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."season_periods_status_enum_old" RENAME TO "season_periods_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."season_types_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" TYPE "public"."season_types_status_enum_old" USING "status"::"text"::"public"."season_types_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "season_types" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."season_types_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."season_types_status_enum_old" RENAME TO "season_types_status_enum"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."item_categories_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" DROP DEFAULT`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" TYPE "public"."item_categories_status_enum_old" USING "status"::"text"::"public"."item_categories_status_enum_old"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "item_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."item_categories_status_enum"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TYPE "public"."item_categories_status_enum_old" RENAME TO "item_categories_status_enum"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class Gate1721024987609 implements MigrationInterface {
|
||||||
|
name = 'Gate1721024987609';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."gates_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."gates_type_enum" AS ENUM('gate masuk', 'gate keluar')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "gates" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."gates_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."gates_type_enum" NOT NULL DEFAULT 'gate masuk', "code" character varying, "note" text, "item_id" uuid, CONSTRAINT "PK_2dd58a77462dd2c5695ec4a7975" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "gates" ADD CONSTRAINT "FK_29f020cd153bb079722bcbee830" FOREIGN KEY ("item_id") REFERENCES "items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "gates" DROP CONSTRAINT "FK_29f020cd153bb079722bcbee830"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "gates"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."gates_type_enum"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."gates_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class TermCondition1721029248635 implements MigrationInterface {
|
||||||
|
name = 'TermCondition1721029248635';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."term_conditions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "term_conditions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."term_conditions_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_fc92769e487820f24ed68337feb" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "term_conditions"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."term_conditions_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class FrequentlyAskQuestion1721029454627 implements MigrationInterface {
|
||||||
|
name = 'FrequentlyAskQuestion1721029454627';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."faqs_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "faqs" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."faqs_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_2ddf4f2c910f8e8fa2663a67bf0" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "faqs"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."faqs_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateRefund1721031712642 implements MigrationInterface {
|
||||||
|
name = 'UpdateRefund1721031712642';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" ADD "refund_sub_total" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "refunds" DROP COLUMN "refund_sub_total"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class News1721109817371 implements MigrationInterface {
|
||||||
|
name = 'News1721109817371';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."news_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "news" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."news_status_enum" NOT NULL DEFAULT 'draft', "image_url" character varying, "title" character varying, "teaser" character varying, "description" character varying, CONSTRAINT "PK_39a43dfcb6007180f04aff2357e" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "news"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."news_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class Banner1721111093665 implements MigrationInterface {
|
||||||
|
name = 'Banner1721111093665';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TYPE "public"."banners_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "banners" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."banners_status_enum" NOT NULL DEFAULT 'draft', "image_url" character varying, "title" character varying, "link" character varying, CONSTRAINT "PK_e9b186b959296fcb940790d31c3" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "banners"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."banners_status_enum"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateTableTransactions1721216510569
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'UpdateTableTransactions1721216510569';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "payment_midtrans_token" character varying`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "payment_midtrans_url" character varying`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_url"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_token"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateSortColumn1721284172572 implements MigrationInterface {
|
||||||
|
name = 'UpdateSortColumn1721284172572';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "term_conditions" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "faqs" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "faqs" DROP COLUMN "sort_order"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "term_conditions" DROP COLUMN "sort_order"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateColumnTransaction1721385120750
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'UpdateColumnTransaction1721385120750';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "discount_percentage"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "discount_percentage" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" DROP COLUMN "discount_percentage"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transactions" ADD "discount_percentage" integer`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class UpdateImageColumnItem1721647955446 implements MigrationInterface {
|
||||||
|
name = 'UpdateImageColumnItem1721647955446';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" RENAME COLUMN "image" TO "image_url"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" RENAME COLUMN "image_url" TO "image"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,8 +29,6 @@ export class SeedDefaultFormula implements Seeder {
|
||||||
.into(SalesPriceFormulaModel)
|
.into(SalesPriceFormulaModel)
|
||||||
.values([sales_formula, profit_formula])
|
.values([sales_formula, profit_formula])
|
||||||
.execute();
|
.execute();
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
console.log(error, 'er');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
import { ItemType } from 'src/modules/item-related/item-category/constants';
|
import { ItemType } from 'src/modules/item-related/item-category/constants';
|
||||||
import { LimitType } from 'src/modules/item-related/item/constants';
|
import { LimitType } from 'src/modules/item-related/item/constants';
|
||||||
import { PaymentMethodType } from 'src/modules/transaction/payment-method/constants';
|
import { PaymentMethodType } from 'src/modules/transaction/payment-method/constants';
|
||||||
|
import { RefundType } from 'src/modules/transaction/refund/constants';
|
||||||
|
import { GateType } from 'src/modules/web-information/gate/constants';
|
||||||
|
|
||||||
@ApiTags('configuration - constant')
|
@ApiTags('configuration - constant')
|
||||||
@Controller('v1/constant')
|
@Controller('v1/constant')
|
||||||
@Public(true)
|
@Public(true)
|
||||||
export class ConstantController {
|
export class ConstantController {
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
@Get('master-data-status')
|
@Get('master-data-status')
|
||||||
async masterDataStatus(): Promise<any> {
|
async masterDataStatus(): Promise<any> {
|
||||||
return [STATUS.ACTIVE, STATUS.DRAFT, STATUS.INACTIVE];
|
return [STATUS.ACTIVE, STATUS.DRAFT, STATUS.INACTIVE];
|
||||||
|
@ -31,4 +31,29 @@ export class ConstantController {
|
||||||
async paymentMethodType(): Promise<any> {
|
async paymentMethodType(): Promise<any> {
|
||||||
return Object.values(PaymentMethodType);
|
return Object.values(PaymentMethodType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('transaction-user-type')
|
||||||
|
async userType(): Promise<any> {
|
||||||
|
return ['group', 'vip'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('transaction-payment-type')
|
||||||
|
async transactionPaymentType(): Promise<any> {
|
||||||
|
return ['midtrans', 'bank transfer', 'qris', 'counter'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('transaction-type')
|
||||||
|
async transactionType(): Promise<any> {
|
||||||
|
return ['counter', 'admin', 'online'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('refund-type')
|
||||||
|
async refundType(): Promise<any> {
|
||||||
|
return Object.values(RefundType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('gate-type')
|
||||||
|
async gateType(): Promise<any> {
|
||||||
|
return Object.values(GateType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export const DatabaseListen = ['transaction'];
|
export const DatabaseListen = ['transaction', 'vip_code'];
|
||||||
|
|
|
@ -15,18 +15,64 @@ import {
|
||||||
SeasonPeriodDeletedHandler,
|
SeasonPeriodDeletedHandler,
|
||||||
SeasonPeriodUpdatedHandler,
|
SeasonPeriodUpdatedHandler,
|
||||||
} from './domain/managers/season-period.handler';
|
} from './domain/managers/season-period.handler';
|
||||||
|
import {
|
||||||
|
ItemDeletedHandler,
|
||||||
|
ItemUpdatedHandler,
|
||||||
|
} from './domain/managers/item.handler';
|
||||||
|
import {
|
||||||
|
UserDeletedHandler,
|
||||||
|
UserUpdatedHandler,
|
||||||
|
} from './domain/managers/user.handler';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||||
|
import { UserModel } from 'src/modules/user-related/user/data/models/user.model';
|
||||||
|
import { UserDataService } from 'src/modules/user-related/user/data/services/user-data.service';
|
||||||
|
import { ItemDataService } from 'src/modules/item-related/item/data/services/item-data.service';
|
||||||
|
import {
|
||||||
|
BookingDeletedEvent,
|
||||||
|
BookingHandler,
|
||||||
|
} from './domain/managers/booking.handler';
|
||||||
|
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
|
||||||
|
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
|
||||||
|
import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model';
|
||||||
|
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
|
||||||
|
import { VipCodeCreatedHandler } from './domain/managers/vip-code.handler';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule.forRoot(), CqrsModule],
|
imports: [
|
||||||
|
ConfigModule.forRoot(),
|
||||||
|
TypeOrmModule.forFeature(
|
||||||
|
[
|
||||||
|
ItemModel,
|
||||||
|
UserModel,
|
||||||
|
TransactionModel,
|
||||||
|
TransactionTaxModel,
|
||||||
|
TransactionItemModel,
|
||||||
|
],
|
||||||
|
CONNECTION_NAME.DEFAULT,
|
||||||
|
),
|
||||||
|
CqrsModule,
|
||||||
|
],
|
||||||
controllers: [CouchDataController],
|
controllers: [CouchDataController],
|
||||||
providers: [
|
providers: [
|
||||||
|
BookingHandler,
|
||||||
|
BookingDeletedEvent,
|
||||||
PaymentMethodDeletedHandler,
|
PaymentMethodDeletedHandler,
|
||||||
PaymentMethodUpdatedHandler,
|
PaymentMethodUpdatedHandler,
|
||||||
|
VipCodeCreatedHandler,
|
||||||
VipCategoryDeletedHandler,
|
VipCategoryDeletedHandler,
|
||||||
VipCategoryUpdatedHandler,
|
VipCategoryUpdatedHandler,
|
||||||
SeasonPeriodDeletedHandler,
|
SeasonPeriodDeletedHandler,
|
||||||
SeasonPeriodUpdatedHandler,
|
SeasonPeriodUpdatedHandler,
|
||||||
|
ItemUpdatedHandler,
|
||||||
|
ItemDeletedHandler,
|
||||||
|
UserDeletedHandler,
|
||||||
|
UserUpdatedHandler,
|
||||||
|
|
||||||
|
TransactionDataService,
|
||||||
|
UserDataService,
|
||||||
|
ItemDataService,
|
||||||
CouchService,
|
CouchService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,23 +1,32 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { DatabaseListen } from '../../constants';
|
import { DatabaseListen } from '../../constants';
|
||||||
import { EventBus } from '@nestjs/cqrs';
|
import { EventBus } from '@nestjs/cqrs';
|
||||||
import { ChangeDocEvent } from '../../domain/events/change-doc.event';
|
import { ChangeDocEvent } from '../../domain/events/change-doc.event';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
|
import * as Nano from 'nano';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CouchService {
|
export class CouchService {
|
||||||
constructor(private eventBus: EventBus) {}
|
constructor(
|
||||||
|
private eventBus: EventBus,
|
||||||
|
private configService: ConfigService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
get nanoInstance() {
|
||||||
|
const couchConfiguration = this.configService.get<string>('COUCHDB_CONFIG');
|
||||||
|
return Nano(couchConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
async onModuleInit() {
|
async onModuleInit() {
|
||||||
const nano = require('nano')(
|
const nano = this.nanoInstance;
|
||||||
'http://root:password@db_pos_couch_staging:5984',
|
|
||||||
);
|
|
||||||
for (const database of DatabaseListen) {
|
for (const database of DatabaseListen) {
|
||||||
const db = nano.db.use(database);
|
const db = nano.db.use(database);
|
||||||
db.changesReader.start({ includeDocs: true }).on('change', (change) => {
|
db.changesReader.start({ includeDocs: true }).on('change', (change) => {
|
||||||
this.changeDoc(change, database);
|
this.changeDoc(change, database);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`start listen database ${database}`);
|
Logger.log(`start listen database ${database}`, 'CouchService');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +42,7 @@ export class CouchService {
|
||||||
|
|
||||||
public async createDoc(data, database) {
|
public async createDoc(data, database) {
|
||||||
try {
|
try {
|
||||||
const nano = require('nano')(
|
const nano = this.nanoInstance;
|
||||||
'http://root:password@db_pos_couch_staging:5984',
|
|
||||||
);
|
|
||||||
const db = nano.use(database);
|
const db = nano.use(database);
|
||||||
return await db.insert(data);
|
return await db.insert(data);
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
@ -43,9 +50,7 @@ export class CouchService {
|
||||||
|
|
||||||
public async deleteDoc(data, database) {
|
public async deleteDoc(data, database) {
|
||||||
try {
|
try {
|
||||||
const nano = require('nano')(
|
const nano = this.nanoInstance;
|
||||||
'http://root:password@db_pos_couch_staging:5984',
|
|
||||||
);
|
|
||||||
const db = nano.use(database);
|
const db = nano.use(database);
|
||||||
const result = await db.get(data.id);
|
const result = await db.get(data.id);
|
||||||
await db.destroy(data.id, result._rev);
|
await db.destroy(data.id, result._rev);
|
||||||
|
@ -54,9 +59,7 @@ export class CouchService {
|
||||||
|
|
||||||
public async updateDoc(data, database) {
|
public async updateDoc(data, database) {
|
||||||
try {
|
try {
|
||||||
const nano = require('nano')(
|
const nano = this.nanoInstance;
|
||||||
'http://root:password@db_pos_couch_staging:5984',
|
|
||||||
);
|
|
||||||
const db = nano.use(database);
|
const db = nano.use(database);
|
||||||
const result = await db.get(data.id);
|
const result = await db.get(data.id);
|
||||||
console.log(result, 'dsa');
|
console.log(result, 'dsa');
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
|
||||||
|
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
|
||||||
|
import { TransactionChangeStatusEvent } from 'src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event';
|
||||||
|
import { CouchService } from '../../data/services/couch.service';
|
||||||
|
import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { TransactionPaymentType } from 'src/modules/transaction/transaction/constants';
|
||||||
|
import { mappingTransaction } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper';
|
||||||
|
import { TransactionDeletedEvent } from 'src/modules/transaction/transaction/domain/entities/event/transaction-deleted.event';
|
||||||
|
import { TransactionUpdatedEvent } from 'src/modules/transaction/transaction/domain/entities/event/transaction-updated.event';
|
||||||
|
|
||||||
|
@EventsHandler(TransactionDeletedEvent)
|
||||||
|
export class BookingDeletedEvent
|
||||||
|
implements IEventHandler<TransactionDeletedEvent>
|
||||||
|
{
|
||||||
|
constructor(private couchService: CouchService) {}
|
||||||
|
|
||||||
|
async handle(event: TransactionDeletedEvent) {
|
||||||
|
await this.couchService.deleteDoc(
|
||||||
|
{
|
||||||
|
_id: event.data.id,
|
||||||
|
...event.data.data,
|
||||||
|
},
|
||||||
|
'item',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventsHandler(TransactionChangeStatusEvent, TransactionUpdatedEvent)
|
||||||
|
export class BookingHandler
|
||||||
|
implements IEventHandler<TransactionChangeStatusEvent>
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
private bookingService: TransactionDataService,
|
||||||
|
private couchService: CouchService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async handle(event: TransactionChangeStatusEvent) {
|
||||||
|
const old_data = event.data.old;
|
||||||
|
const data = event.data.data;
|
||||||
|
|
||||||
|
if (data.payment_type != TransactionPaymentType.COUNTER) return;
|
||||||
|
|
||||||
|
const booking = await this.bookingService.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id: data.id,
|
||||||
|
},
|
||||||
|
relations: ['items'],
|
||||||
|
});
|
||||||
|
|
||||||
|
mappingTransaction(booking);
|
||||||
|
|
||||||
|
if (
|
||||||
|
old_data?.status != data.status &&
|
||||||
|
[STATUS.PENDING, STATUS.ACTIVE].includes(data.status)
|
||||||
|
) {
|
||||||
|
await this.couchService.createDoc(
|
||||||
|
{
|
||||||
|
_id: booking.id,
|
||||||
|
...booking,
|
||||||
|
},
|
||||||
|
'booking',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await this.couchService.updateDoc(
|
||||||
|
{
|
||||||
|
_id: booking.id,
|
||||||
|
...booking,
|
||||||
|
},
|
||||||
|
'booking',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
|
||||||
|
import { CouchService } from '../../data/services/couch.service';
|
||||||
|
import { VipCodeCreatedEvent } from 'src/modules/transaction/vip-code/domain/entities/event/vip-code-created.event';
|
||||||
|
|
||||||
|
@EventsHandler(VipCodeCreatedEvent)
|
||||||
|
export class VipCodeCreatedHandler
|
||||||
|
implements IEventHandler<VipCodeCreatedEvent>
|
||||||
|
{
|
||||||
|
constructor(private couchService: CouchService) {}
|
||||||
|
|
||||||
|
async handle(event: VipCodeCreatedEvent) {
|
||||||
|
const data = event.data.data;
|
||||||
|
|
||||||
|
await this.couchService.createDoc(
|
||||||
|
{
|
||||||
|
_id: data.id,
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
'vip_code',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,38 +1,44 @@
|
||||||
import { Body, Controller, Get, Post } from '@nestjs/common';
|
import { Body, Controller, Get, Injectable, Post } from '@nestjs/common';
|
||||||
|
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { Unprotected } from 'src/core/guards';
|
import { Public } from 'src/core/guards';
|
||||||
import * as Nano from 'nano';
|
import * as Nano from 'nano';
|
||||||
import { CreateUserPrivilegeDto } from 'src/modules/user-related/user-privilege/infrastructure/dto/create-user-privilege.dto';
|
import { CreateUserPrivilegeDto } from 'src/modules/user-related/user-privilege/infrastructure/dto/create-user-privilege.dto';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@ApiTags(`couch`)
|
@ApiTags(`couch`)
|
||||||
@Controller('v1/couch')
|
@Controller('v1/couch')
|
||||||
@Unprotected()
|
@Public()
|
||||||
|
@Injectable()
|
||||||
export class CouchDataController {
|
export class CouchDataController {
|
||||||
|
constructor(private configService: ConfigService) {}
|
||||||
|
|
||||||
|
get nanoInstance() {
|
||||||
|
const couchConfiguration = this.configService.get<string>('COUCHDB_CONFIG');
|
||||||
|
return Nano(couchConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async createDoc(@Body() entity: CreateUserPrivilegeDto) {
|
async createDoc(@Body() entity: CreateUserPrivilegeDto) {
|
||||||
try {
|
try {
|
||||||
let n = Nano('http://admin:secret@127.0.0.1:5984');
|
const n = this.nanoInstance;
|
||||||
let db = await n.db.create(entity.name);
|
await n.db.create(entity.name);
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
console.log(error, 'dsa');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('doc')
|
@Post('doc')
|
||||||
async createDocs(@Body() entity: CreateUserPrivilegeDto) {
|
async createDocs(@Body() entity: CreateUserPrivilegeDto) {
|
||||||
try {
|
try {
|
||||||
const nano = require('nano')('http://admin:secret@127.0.0.1:5984');
|
const nano = this.nanoInstance;
|
||||||
const people = nano.db.use('string');
|
const people = nano.db.use('string');
|
||||||
console.log(await people.info());
|
// const data = {
|
||||||
const data = {
|
// id: '1212',
|
||||||
id: '1212',
|
// name: 'dsadas',
|
||||||
name: 'dsadas',
|
// };
|
||||||
};
|
|
||||||
// await people.insert(data)
|
// await people.insert(data)
|
||||||
|
|
||||||
people.changesReader
|
people.changesReader
|
||||||
.start()
|
.start({})
|
||||||
.on('change', (change) => {
|
.on('change', (change) => {
|
||||||
console.log(change);
|
console.log(change);
|
||||||
})
|
})
|
||||||
|
@ -45,20 +51,17 @@ export class CouchDataController {
|
||||||
.on('error', (e) => {
|
.on('error', (e) => {
|
||||||
console.error('error', e);
|
console.error('error', e);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
console.log(error, 'dsa');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async getDoc() {
|
async getDoc() {
|
||||||
try {
|
try {
|
||||||
let n = Nano('http://admin:secret@127.0.0.1:5984');
|
const n = this.nanoInstance;
|
||||||
const people = n.use('string');
|
const people = n.db.get('user');
|
||||||
|
|
||||||
|
return people;
|
||||||
// return people.get();
|
// return people.get();
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
console.log(error, 'dsa');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { MidnightCronManager } from './domain/managers/midnight-cron.manager';
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { CqrsModule } from '@nestjs/cqrs';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [ConfigModule.forRoot(), CqrsModule],
|
||||||
|
controllers: [MidnightCronManager],
|
||||||
|
providers: [],
|
||||||
|
})
|
||||||
|
export class CronModule {}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export class CronMidnightEvent {
|
||||||
|
// constructor(public readonly data: {}) {}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Controller } from '@nestjs/common';
|
||||||
|
import { EventBus } from '@nestjs/cqrs';
|
||||||
|
import { Cron } from '@nestjs/schedule';
|
||||||
|
import { CronMidnightEvent } from '../entities/cron-midnight.event';
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class MidnightCronManager {
|
||||||
|
constructor(public eventBus: EventBus) {}
|
||||||
|
|
||||||
|
@Cron(`${process.env.CRON_MIDNIGHT}`)
|
||||||
|
async scheduler(): Promise<void> {
|
||||||
|
const local_time = new Date().toLocaleDateString('en-US', {
|
||||||
|
timeZone: 'Asia/Jakarta',
|
||||||
|
});
|
||||||
|
const now = new Date(local_time).getTime();
|
||||||
|
|
||||||
|
console.log('Cron Event executed every 00:00 minutes.', now);
|
||||||
|
|
||||||
|
this.eventBus.publishAll([new CronMidnightEvent()]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,5 +6,7 @@ import { ErrorLogService } from '../../data/services/error-log.service';
|
||||||
export class RecordErrorLogHandler implements IEventHandler<RecordErrorLog> {
|
export class RecordErrorLogHandler implements IEventHandler<RecordErrorLog> {
|
||||||
constructor(private dataservice: ErrorLogService) {}
|
constructor(private dataservice: ErrorLogService) {}
|
||||||
|
|
||||||
async handle(event: RecordErrorLog) {}
|
async handle(event: RecordErrorLog) {
|
||||||
|
// TODO: Implement logic here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,7 @@ import { RecordLog } from '../entities/log.event';
|
||||||
|
|
||||||
@EventsHandler(RecordLog)
|
@EventsHandler(RecordLog)
|
||||||
export class RecordLogHandler implements IEventHandler<RecordLog> {
|
export class RecordLogHandler implements IEventHandler<RecordLog> {
|
||||||
async handle(event: RecordLog) {}
|
async handle(event: RecordLog) {
|
||||||
|
// TODO: Implement logic here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,413 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Email Ibunda</title>
|
||||||
|
<style>
|
||||||
|
/* -------------------------------------
|
||||||
|
GLOBAL RESETS
|
||||||
|
------------------------------------- */
|
||||||
|
img {
|
||||||
|
border: none;
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
font-family: sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: separate;
|
||||||
|
mso-table-lspace: 0pt;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
BODY & CONTAINER
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
.body {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink
|
||||||
|
down on a phone or something */
|
||||||
|
.container {
|
||||||
|
display: block;
|
||||||
|
Margin: 0 auto !important;
|
||||||
|
/* makes it centered */
|
||||||
|
max-width: 580px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 580px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should also be a block element, so that it will fill 100% of the .container */
|
||||||
|
.content {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
Margin: 0 auto;
|
||||||
|
max-width: 580px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
HEADER, FOOTER, MAIN
|
||||||
|
------------------------------------- */
|
||||||
|
.main {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-block {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
clear: both;
|
||||||
|
Margin-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer td,
|
||||||
|
.footer p,
|
||||||
|
.footer span,
|
||||||
|
.footer a {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
TYPOGRAPHY
|
||||||
|
------------------------------------- */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
|
color: #000000;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
Margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 35px;
|
||||||
|
font-weight: 300;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
Margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p li,
|
||||||
|
ul li,
|
||||||
|
ol li {
|
||||||
|
list-style-position: inside;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #3498db;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
BUTTONS
|
||||||
|
------------------------------------- */
|
||||||
|
.btn {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn>tbody>tr>td {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn table {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn table td {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn a {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: solid 1px #3498db;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #3498db;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 12px 25px;
|
||||||
|
text-decoration: none;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary table td {
|
||||||
|
background-color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary a {
|
||||||
|
background-color: #3498db;
|
||||||
|
border-color: #3498db;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
OTHER STYLES THAT MIGHT BE USEFUL
|
||||||
|
------------------------------------- */
|
||||||
|
.last {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt0 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preheader {
|
||||||
|
color: transparent;
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
max-height: 0;
|
||||||
|
max-width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.powered-by a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #f6f6f6;
|
||||||
|
Margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||||
|
------------------------------------- */
|
||||||
|
@media only screen and (max-width: 620px) {
|
||||||
|
table[class=body] h1 {
|
||||||
|
font-size: 28px !important;
|
||||||
|
margin-bottom: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] p,
|
||||||
|
table[class=body] ul,
|
||||||
|
table[class=body] ol,
|
||||||
|
table[class=body] td,
|
||||||
|
table[class=body] span,
|
||||||
|
table[class=body] a {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .wrapper,
|
||||||
|
table[class=body] .article {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .container {
|
||||||
|
padding: 0 !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .main {
|
||||||
|
border-left-width: 0 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-right-width: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .btn table {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .btn a {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .img-responsive {
|
||||||
|
height: auto !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
PRESERVE THESE STYLES IN THE HEAD
|
||||||
|
------------------------------------- */
|
||||||
|
@media all {
|
||||||
|
.ExternalClass {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ExternalClass,
|
||||||
|
.ExternalClass p,
|
||||||
|
.ExternalClass span,
|
||||||
|
.ExternalClass font,
|
||||||
|
.ExternalClass td,
|
||||||
|
.ExternalClass div {
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apple-link a {
|
||||||
|
color: inherit !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary table td:hover {
|
||||||
|
background-color: #34495e !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary a:hover {
|
||||||
|
background-color: #34495e !important;
|
||||||
|
border-color: #34495e !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
padding: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol li {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" class="body">
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td class="container">
|
||||||
|
<div class="content">
|
||||||
|
<table class="main">
|
||||||
|
<!-- START MAIN CONTENT AREA -->
|
||||||
|
<tr>
|
||||||
|
<td class="wrapper">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>Halo {{customer_name}}</p>
|
||||||
|
<p>Pemesanan tiket telah berhasil dengan nomor invoice {{invoice_code}}, Silahkan lakukan pembayaran</p>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<b>PEMBAYARAN DAPAT MELALUI</b>
|
||||||
|
<ul>
|
||||||
|
{{#each payment_methods}}
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<b>{{issuer_name}}</b><br>
|
||||||
|
<span>Name: <b>{{account_name}}</b></span><br>
|
||||||
|
<span>Number: <b>{{account_number}}</b></span>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- END MAIN CONTENT AREA -->
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- START FOOTER -->
|
||||||
|
<div class="footer">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block powered-by">
|
||||||
|
Powered by Skyworld
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- END FOOTER -->
|
||||||
|
|
||||||
|
<!-- END CENTERED WHITE CONTAINER -->
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,404 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Email Ibunda</title>
|
||||||
|
<style>
|
||||||
|
/* -------------------------------------
|
||||||
|
GLOBAL RESETS
|
||||||
|
------------------------------------- */
|
||||||
|
img {
|
||||||
|
border: none;
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
font-family: sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: separate;
|
||||||
|
mso-table-lspace: 0pt;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
BODY & CONTAINER
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
.body {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink
|
||||||
|
down on a phone or something */
|
||||||
|
.container {
|
||||||
|
display: block;
|
||||||
|
Margin: 0 auto !important;
|
||||||
|
/* makes it centered */
|
||||||
|
max-width: 580px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 580px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should also be a block element, so that it will fill 100% of the .container */
|
||||||
|
.content {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
Margin: 0 auto;
|
||||||
|
max-width: 580px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
HEADER, FOOTER, MAIN
|
||||||
|
------------------------------------- */
|
||||||
|
.main {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-block {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
clear: both;
|
||||||
|
Margin-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer td,
|
||||||
|
.footer p,
|
||||||
|
.footer span,
|
||||||
|
.footer a {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
TYPOGRAPHY
|
||||||
|
------------------------------------- */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
|
color: #000000;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
Margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 35px;
|
||||||
|
font-weight: 300;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
Margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p li,
|
||||||
|
ul li,
|
||||||
|
ol li {
|
||||||
|
list-style-position: inside;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #3498db;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
BUTTONS
|
||||||
|
------------------------------------- */
|
||||||
|
.btn {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn>tbody>tr>td {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn table {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn table td {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn a {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: solid 1px #3498db;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #3498db;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
padding: 12px 25px;
|
||||||
|
text-decoration: none;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary table td {
|
||||||
|
background-color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary a {
|
||||||
|
background-color: #3498db;
|
||||||
|
border-color: #3498db;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
OTHER STYLES THAT MIGHT BE USEFUL
|
||||||
|
------------------------------------- */
|
||||||
|
.last {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt0 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preheader {
|
||||||
|
color: transparent;
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
max-height: 0;
|
||||||
|
max-width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.powered-by a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #f6f6f6;
|
||||||
|
Margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||||
|
------------------------------------- */
|
||||||
|
@media only screen and (max-width: 620px) {
|
||||||
|
table[class=body] h1 {
|
||||||
|
font-size: 28px !important;
|
||||||
|
margin-bottom: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] p,
|
||||||
|
table[class=body] ul,
|
||||||
|
table[class=body] ol,
|
||||||
|
table[class=body] td,
|
||||||
|
table[class=body] span,
|
||||||
|
table[class=body] a {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .wrapper,
|
||||||
|
table[class=body] .article {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .container {
|
||||||
|
padding: 0 !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .main {
|
||||||
|
border-left-width: 0 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-right-width: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .btn table {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .btn a {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class=body] .img-responsive {
|
||||||
|
height: auto !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
PRESERVE THESE STYLES IN THE HEAD
|
||||||
|
------------------------------------- */
|
||||||
|
@media all {
|
||||||
|
.ExternalClass {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ExternalClass,
|
||||||
|
.ExternalClass p,
|
||||||
|
.ExternalClass span,
|
||||||
|
.ExternalClass font,
|
||||||
|
.ExternalClass td,
|
||||||
|
.ExternalClass div {
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apple-link a {
|
||||||
|
color: inherit !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary table td:hover {
|
||||||
|
background-color: #34495e !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary a:hover {
|
||||||
|
background-color: #34495e !important;
|
||||||
|
border-color: #34495e !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
padding: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol li {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" class="body">
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td class="container">
|
||||||
|
<div class="content">
|
||||||
|
<table class="main">
|
||||||
|
<!-- START MAIN CONTENT AREA -->
|
||||||
|
<tr>
|
||||||
|
<td class="wrapper">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>Halo {{customer_name}}</p>
|
||||||
|
<p>Pemesanan tiket telah berhasil dengan nomor invoice {{invoice_code}}, Silahkan lakukan pembayaran dengan klik button dibawah ini</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"
|
||||||
|
style="font-family: 'Lato', sans-serif; font-size:22px; color:#e5eaf5; line-height:24px; font-weight: 600;">
|
||||||
|
<a href="{{payment_midtrans_url}}">Lanjutkan Pembayaran</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- END MAIN CONTENT AREA -->
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- START FOOTER -->
|
||||||
|
<div class="footer">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block powered-by">
|
||||||
|
Powered by Skyworld
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- END FOOTER -->
|
||||||
|
|
||||||
|
<!-- END CENTERED WHITE CONTAINER -->
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
|
||||||
|
import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { PaymentMethodDataService } from 'src/modules/transaction/payment-method/data/services/payment-method-data.service';
|
||||||
|
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
|
||||||
|
import { TransactionChangeStatusEvent } from 'src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event';
|
||||||
|
import { sendEmail } from '../helpers/send-email.helper';
|
||||||
|
import { TransactionPaymentType } from 'src/modules/transaction/transaction/constants';
|
||||||
|
|
||||||
|
@EventsHandler(TransactionChangeStatusEvent)
|
||||||
|
export class PaymentTransactionHandler
|
||||||
|
implements IEventHandler<TransactionChangeStatusEvent>
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
private dataService: TransactionDataService,
|
||||||
|
private paymentService: PaymentMethodDataService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async handle(event: TransactionChangeStatusEvent) {
|
||||||
|
const data_id = event.data.id;
|
||||||
|
const old_data = event.data.old;
|
||||||
|
const current_data = event.data.data;
|
||||||
|
let payments = [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
old_data.status == STATUS.DRAFT &&
|
||||||
|
current_data.status == STATUS.PENDING &&
|
||||||
|
current_data.payment_type != TransactionPaymentType.COUNTER &&
|
||||||
|
!!current_data.customer_email
|
||||||
|
) {
|
||||||
|
if (current_data.payment_type != TransactionPaymentType.MIDTRANS) {
|
||||||
|
payments = await this.paymentService.getManyByOptions({
|
||||||
|
where: {
|
||||||
|
status: STATUS.ACTIVE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const transaction = await this.dataService.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id: data_id,
|
||||||
|
},
|
||||||
|
relations: ['items'],
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
sendEmail(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
...transaction,
|
||||||
|
email: transaction.customer_email,
|
||||||
|
payment_methods: payments,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'Payment Confirmation',
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import * as nodemailer from 'nodemailer';
|
||||||
|
import * as handlebars from 'handlebars';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import { TransactionPaymentType } from 'src/modules/transaction/transaction/constants';
|
||||||
|
|
||||||
|
export async function sendEmail(receivers, subject) {
|
||||||
|
const smtpTransport = nodemailer.createTransport({
|
||||||
|
host: process.env.EMAIL_HOST,
|
||||||
|
port: process.env.EMAIL_POST,
|
||||||
|
auth: {
|
||||||
|
user: process.env.EMAIL_USER,
|
||||||
|
pass: process.env.EMAIL_TOKEN,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let templateName = 'payment-confirmation-bank';
|
||||||
|
|
||||||
|
for (const receiver of receivers) {
|
||||||
|
if (receiver.payment_type == TransactionPaymentType.MIDTRANS)
|
||||||
|
templateName = 'payment-confirmation-midtrans';
|
||||||
|
|
||||||
|
let templatePath = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
`../email-template/${templateName}.html`,
|
||||||
|
);
|
||||||
|
templatePath = templatePath.replace(/dist/g, 'src');
|
||||||
|
const templateSource = fs.readFileSync(templatePath, 'utf8');
|
||||||
|
|
||||||
|
const template = handlebars.compile(templateSource);
|
||||||
|
const htmlToSend = template(receiver);
|
||||||
|
|
||||||
|
const emailContext = {
|
||||||
|
from: 'no-reply@eigen.co.id',
|
||||||
|
to: receiver.email,
|
||||||
|
subject: subject,
|
||||||
|
html: htmlToSend,
|
||||||
|
attachDataUrls: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
await new Promise((f) => setTimeout(f, 2000));
|
||||||
|
|
||||||
|
smtpTransport.sendMail(emailContext, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
console.log(`Error occurs on send to ${receiver.email}`);
|
||||||
|
} else {
|
||||||
|
console.log(`Email sent to ${receiver.email}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { CqrsModule } from '@nestjs/cqrs';
|
||||||
|
import { PaymentMethodModel } from 'src/modules/transaction/payment-method/data/models/payment-method.model';
|
||||||
|
import { PaymentMethodDataService } from 'src/modules/transaction/payment-method/data/services/payment-method-data.service';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
|
||||||
|
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
|
||||||
|
import { PaymentTransactionHandler } from './domain/handlers/payment-transaction.handler';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ConfigModule.forRoot(),
|
||||||
|
TypeOrmModule.forFeature(
|
||||||
|
[PaymentMethodModel, TransactionModel],
|
||||||
|
CONNECTION_NAME.DEFAULT,
|
||||||
|
),
|
||||||
|
CqrsModule,
|
||||||
|
],
|
||||||
|
controllers: [],
|
||||||
|
providers: [
|
||||||
|
PaymentTransactionHandler,
|
||||||
|
PaymentMethodDataService,
|
||||||
|
TransactionDataService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class MailModule {}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { EventBus } from '@nestjs/cqrs';
|
||||||
|
import { mappingMidtransTransaction } from '../../domain/usecases/helpers/mapping-transaction.helper';
|
||||||
|
const midtransClient = require('midtrans-client');
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MidtransService {
|
||||||
|
constructor(private eventBus: EventBus) {}
|
||||||
|
|
||||||
|
get midtransInstance() {
|
||||||
|
return new midtransClient.Snap({
|
||||||
|
isProduction: false,
|
||||||
|
serverKey: process.env.MIDTRANS_SERVER_KEY,
|
||||||
|
clientKey: process.env.MIDTRANS_CLIENT_KEY,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getStatus(orderId: string): Promise<any> {
|
||||||
|
return await this.midtransInstance.transaction.status(orderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(body): Promise<any> {
|
||||||
|
const data = mappingMidtransTransaction(body);
|
||||||
|
return await this.midtransInstance.createTransaction(data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
export class MidtransCallbackEvent {
|
||||||
|
constructor(public readonly data: IEventMidtrans) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IEventMidtrans {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
export function mappingMidtransTransaction(transaction) {
|
||||||
|
const item_details = transaction.items?.map((item) => {
|
||||||
|
return {
|
||||||
|
quantity: Number(item.qty),
|
||||||
|
price: Number(item.total_price),
|
||||||
|
name: item.item_name,
|
||||||
|
category: item.item_category_name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transaction.payment_discount_total) {
|
||||||
|
item_details.push({
|
||||||
|
quantity: 1,
|
||||||
|
price: -Number(transaction.payment_discount_total),
|
||||||
|
name: 'discount',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
transaction_details: {
|
||||||
|
order_id: transaction.id,
|
||||||
|
gross_amount: Number(transaction.payment_total),
|
||||||
|
},
|
||||||
|
item_details: item_details,
|
||||||
|
customer_details: {
|
||||||
|
first_name: transaction.customer_name,
|
||||||
|
email: transaction.customer_email,
|
||||||
|
phone: transaction.customer_phone,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class MidtransDto {
|
||||||
|
@ApiProperty({
|
||||||
|
type: String,
|
||||||
|
example: '123',
|
||||||
|
})
|
||||||
|
order_id: string;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Body, Controller, Get, Injectable, Param, Post } from '@nestjs/common';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Public } from 'src/core/guards';
|
||||||
|
import { MidtransService } from '../data/services/midtrans.service';
|
||||||
|
import { EventBus } from '@nestjs/cqrs';
|
||||||
|
import { MidtransCallbackEvent } from '../domain/entities/midtrans-callback.event';
|
||||||
|
import { MidtransDto } from './dto/midtrans.dto';
|
||||||
|
|
||||||
|
@ApiTags(`midtrans`)
|
||||||
|
@Controller('v1/midtrans')
|
||||||
|
@Public()
|
||||||
|
@Injectable()
|
||||||
|
export class MidtransController {
|
||||||
|
constructor(
|
||||||
|
private dataService: MidtransService,
|
||||||
|
private eventBus: EventBus,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Get(':id/status')
|
||||||
|
async getStatus(@Param('id') id: string) {
|
||||||
|
return await this.dataService.getStatus(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('callback')
|
||||||
|
async callback(@Body() callback: MidtransDto) {
|
||||||
|
const data = await this.dataService.getStatus(callback?.order_id);
|
||||||
|
this.eventBus.publishAll([
|
||||||
|
new MidtransCallbackEvent({
|
||||||
|
id: data.order_id,
|
||||||
|
data: data,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
console.log(`midtrans callback for order ${data.order_id}`);
|
||||||
|
return 'success listen callback';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { CqrsModule } from '@nestjs/cqrs';
|
||||||
|
import { MidtransController } from './infrastructure/midtrans.controller';
|
||||||
|
import { MidtransService } from './data/services/midtrans.service';
|
||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
imports: [ConfigModule.forRoot(), CqrsModule],
|
||||||
|
controllers: [MidtransController],
|
||||||
|
providers: [MidtransService],
|
||||||
|
exports: [MidtransService],
|
||||||
|
})
|
||||||
|
export class MidtransModule {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface UploadEntity {
|
||||||
|
module: string;
|
||||||
|
sub_module: string;
|
||||||
|
file: any;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { UploadEntity } from '../../domain/entities/upload.entity';
|
||||||
|
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||||
|
|
||||||
|
export class UploadDto implements UploadEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
default: TABLE_NAME.ITEM,
|
||||||
|
})
|
||||||
|
module: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
default: TABLE_NAME.ITEM,
|
||||||
|
})
|
||||||
|
sub_module: string;
|
||||||
|
|
||||||
|
@ApiProperty({ type: 'string', format: 'binary', required: true })
|
||||||
|
file: any;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Post,
|
||||||
|
UseInterceptors,
|
||||||
|
Body,
|
||||||
|
UploadedFile,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ModuleRef } from '@nestjs/core';
|
||||||
|
import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { FileInterceptor } from '@nestjs/platform-express';
|
||||||
|
import { UploadDto } from './dto/upload.dto';
|
||||||
|
import { Public } from 'src/core/guards';
|
||||||
|
import { StoreFileConfig } from 'src/core/helpers/path/upload-store-path.helper';
|
||||||
|
|
||||||
|
@ApiTags('uploads')
|
||||||
|
@Controller('uploads')
|
||||||
|
@Public(true)
|
||||||
|
export class UploadController {
|
||||||
|
constructor(private moduleRef: ModuleRef) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
@ApiConsumes('multipart/form-data')
|
||||||
|
@ApiBody({ type: UploadDto })
|
||||||
|
@UseInterceptors(FileInterceptor('file', StoreFileConfig))
|
||||||
|
async storeFile(
|
||||||
|
@UploadedFile() file: Express.Multer.File,
|
||||||
|
@Body() body: UploadDto,
|
||||||
|
): Promise<any> {
|
||||||
|
return {
|
||||||
|
path: file.path,
|
||||||
|
full_path: `${process.env.ASSETS}${file.path}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { MulterModule } from '@nestjs/platform-express';
|
||||||
|
import { UploadController } from './infrastructure/upload.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ConfigModule.forRoot(),
|
||||||
|
MulterModule.register({
|
||||||
|
dest: './uploads',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
controllers: [UploadController],
|
||||||
|
providers: [],
|
||||||
|
})
|
||||||
|
export class UploadModule {}
|
|
@ -49,7 +49,7 @@ export class ItemCategoryDataOrchestrator extends BaseDataTransactionOrchestrato
|
||||||
return this.updateManager.getResult();
|
return this.updateManager.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.ITEM_CATEGORY);
|
this.deleteManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
||||||
await this.deleteManager.execute();
|
await this.deleteManager.execute();
|
||||||
|
@ -66,7 +66,7 @@ export class ItemCategoryDataOrchestrator extends BaseDataTransactionOrchestrato
|
||||||
return this.batchDeleteManager.getResult();
|
return this.batchDeleteManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async active(dataId): Promise<String> {
|
async active(dataId): Promise<string> {
|
||||||
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.activeManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
this.activeManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
||||||
await this.activeManager.execute();
|
await this.activeManager.execute();
|
||||||
|
@ -83,7 +83,7 @@ export class ItemCategoryDataOrchestrator extends BaseDataTransactionOrchestrato
|
||||||
return this.batchActiveManager.getResult();
|
return this.batchActiveManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async confirm(dataId): Promise<String> {
|
async confirm(dataId): Promise<string> {
|
||||||
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.confirmManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
this.confirmManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
||||||
await this.confirmManager.execute();
|
await this.confirmManager.execute();
|
||||||
|
@ -100,7 +100,7 @@ export class ItemCategoryDataOrchestrator extends BaseDataTransactionOrchestrato
|
||||||
return this.batchConfirmManager.getResult();
|
return this.batchConfirmManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async inactive(dataId): Promise<String> {
|
async inactive(dataId): Promise<string> {
|
||||||
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
||||||
this.inactiveManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
this.inactiveManager.setService(this.serviceData, TABLE_NAME.ITEM_CATEGORY);
|
||||||
await this.inactiveManager.execute();
|
await this.inactiveManager.execute();
|
||||||
|
|
|
@ -22,7 +22,9 @@ export class CreateItemCategoryManager extends BaseCreateManager<ItemCategoryEnt
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
async generateConfig(): Promise<void> {}
|
async generateConfig(): Promise<void> {
|
||||||
|
// TODO: Implement logic here
|
||||||
|
}
|
||||||
|
|
||||||
get validateRelations(): validateRelations[] {
|
get validateRelations(): validateRelations[] {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -34,7 +34,7 @@ export class ItemCategoryDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/active')
|
@Patch(':id/active')
|
||||||
async active(@Param('id') dataId: string): Promise<String> {
|
async active(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.active(dataId);
|
return await this.orchestrator.active(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ export class ItemCategoryDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/confirm')
|
@Patch(':id/confirm')
|
||||||
async confirm(@Param('id') dataId: string): Promise<String> {
|
async confirm(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.confirm(dataId);
|
return await this.orchestrator.confirm(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ export class ItemCategoryDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/inactive')
|
@Patch(':id/inactive')
|
||||||
async inactive(@Param('id') dataId: string): Promise<String> {
|
async inactive(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.inactive(dataId);
|
return await this.orchestrator.inactive(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export class ItemCategoryDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async delete(@Param('id') dataId: string): Promise<String> {
|
async delete(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.delete(dataId);
|
return await this.orchestrator.delete(dataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ export class ItemRateDataOrchestrator extends BaseDataOrchestrator<ItemRateEntit
|
||||||
return this.updateManager.getResult();
|
return this.updateManager.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.ITEM_RATE);
|
this.deleteManager.setService(this.serviceData, TABLE_NAME.ITEM_RATE);
|
||||||
await this.deleteManager.execute();
|
await this.deleteManager.execute();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
RelationParam,
|
RelationParam,
|
||||||
} from 'src/core/modules/domain/entities/base-filter.entity';
|
} from 'src/core/modules/domain/entities/base-filter.entity';
|
||||||
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
|
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
|
||||||
|
import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
|
@ -19,7 +20,7 @@ export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
|
|
||||||
async afterProcess(): Promise<void> {
|
async afterProcess(): Promise<void> {
|
||||||
this.result.data?.map((item) => {
|
this.result.data?.map((item) => {
|
||||||
let prices = [];
|
const prices = [];
|
||||||
for (
|
for (
|
||||||
let d = new Date(this.filterParam.start_date);
|
let d = new Date(this.filterParam.start_date);
|
||||||
d <= new Date(this.filterParam.end_date);
|
d <= new Date(this.filterParam.end_date);
|
||||||
|
@ -27,6 +28,7 @@ export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
) {
|
) {
|
||||||
const rate = item['item_rates']?.find(
|
const rate = item['item_rates']?.find(
|
||||||
(rate) =>
|
(rate) =>
|
||||||
|
rate.season_period?.status == STATUS.ACTIVE &&
|
||||||
d >= new Date(rate.season_period.start_date) &&
|
d >= new Date(rate.season_period.start_date) &&
|
||||||
d <= new Date(rate.season_period.end_date),
|
d <= new Date(rate.season_period.end_date),
|
||||||
);
|
);
|
||||||
|
@ -70,6 +72,7 @@ export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
get selects(): string[] {
|
get selects(): string[] {
|
||||||
return [
|
return [
|
||||||
`${this.tableName}.id`,
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.status`,
|
||||||
`${this.tableName}.created_at`,
|
`${this.tableName}.created_at`,
|
||||||
`${this.tableName}.name`,
|
`${this.tableName}.name`,
|
||||||
`${this.tableName}.base_price`,
|
`${this.tableName}.base_price`,
|
||||||
|
@ -84,6 +87,7 @@ export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
'item_rates.price',
|
'item_rates.price',
|
||||||
|
|
||||||
'season_period.id',
|
'season_period.id',
|
||||||
|
'season_period.status',
|
||||||
'season_period.holiday_name',
|
'season_period.holiday_name',
|
||||||
'season_period.start_date',
|
'season_period.start_date',
|
||||||
'season_period.end_date',
|
'season_period.end_date',
|
||||||
|
@ -121,10 +125,11 @@ export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
|
||||||
queryBuilder.andWhere(`${this.tableName}.tenant_id In (:...tenantIds)`, {
|
queryBuilder.andWhere(`${this.tableName}.tenant_id In (:...tenantIds)`, {
|
||||||
tenantIds: this.filterParam.tenant_ids,
|
tenantIds: this.filterParam.tenant_ids,
|
||||||
});
|
});
|
||||||
} else if (!this.filterParam.all_item) {
|
|
||||||
queryBuilder.andWhere(`${this.tableName}.tenant_id Is Null`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queryBuilder.andWhere(`${this.tableName}.status In (:...statuses)`, {
|
||||||
|
statuses: [STATUS.ACTIVE],
|
||||||
|
});
|
||||||
return queryBuilder;
|
return queryBuilder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ export class ItemRateDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Delete(':id')
|
// @Delete(':id')
|
||||||
// async delete(@Param('id') dataId: string): Promise<String> {
|
// async delete(@Param('id') dataId: string): Promise<string> {
|
||||||
// return await this.orchestrator.delete(dataId);
|
// return await this.orchestrator.delete(dataId);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { LimitType } from '../../constants';
|
||||||
import { ItemCategoryModel } from 'src/modules/item-related/item-category/data/models/item-category.model';
|
import { ItemCategoryModel } from 'src/modules/item-related/item-category/data/models/item-category.model';
|
||||||
import { UserModel } from 'src/modules/user-related/user/data/models/user.model';
|
import { UserModel } from 'src/modules/user-related/user/data/models/user.model';
|
||||||
import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model';
|
import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model';
|
||||||
|
import { GateModel } from 'src/modules/web-information/gate/data/models/gate.model';
|
||||||
|
|
||||||
@Entity(TABLE_NAME.ITEM)
|
@Entity(TABLE_NAME.ITEM)
|
||||||
export class ItemModel
|
export class ItemModel
|
||||||
|
@ -24,8 +25,8 @@ export class ItemModel
|
||||||
@Column('varchar', { name: 'name' })
|
@Column('varchar', { name: 'name' })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column('varchar', { name: 'image', nullable: true })
|
@Column('varchar', { name: 'image_url', nullable: true })
|
||||||
image: string;
|
image_url: string;
|
||||||
|
|
||||||
@Column('enum', {
|
@Column('enum', {
|
||||||
name: 'item_type',
|
name: 'item_type',
|
||||||
|
@ -108,4 +109,11 @@ export class ItemModel
|
||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
})
|
})
|
||||||
item_rates: ItemRateModel[];
|
item_rates: ItemRateModel[];
|
||||||
|
|
||||||
|
// relasi ke gate
|
||||||
|
@OneToMany(() => GateModel, (model) => model.item, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
})
|
||||||
|
gates: GateModel[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,5 @@ export interface FilterItemEntity extends BaseFilterEntity {
|
||||||
limit_types: string[];
|
limit_types: string[];
|
||||||
tenant_ids: string[];
|
tenant_ids: string[];
|
||||||
all_item: boolean;
|
all_item: boolean;
|
||||||
|
season_period_ids: string[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { LimitType } from '../../constants';
|
||||||
export interface ItemEntity extends BaseStatusEntity {
|
export interface ItemEntity extends BaseStatusEntity {
|
||||||
name: string;
|
name: string;
|
||||||
item_type: ItemType;
|
item_type: ItemType;
|
||||||
image: string;
|
image_url: string;
|
||||||
|
|
||||||
hpp: number;
|
hpp: number;
|
||||||
sales_margin: number;
|
sales_margin: number;
|
||||||
|
|
|
@ -15,6 +15,8 @@ import { BatchInactiveItemManager } from './managers/batch-inactive-item.manager
|
||||||
import { BatchActiveItemManager } from './managers/batch-active-item.manager';
|
import { BatchActiveItemManager } from './managers/batch-active-item.manager';
|
||||||
import { BatchDeleteItemManager } from './managers/batch-delete-item.manager';
|
import { BatchDeleteItemManager } from './managers/batch-delete-item.manager';
|
||||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||||
|
import { UpdateItemRatePriceManager } from './managers/update-item-rate-price.manager';
|
||||||
|
import { ItemRateReadService } from 'src/modules/item-related/item-rate/data/services/item-rate-read.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEntity> {
|
export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEntity> {
|
||||||
|
@ -28,8 +30,10 @@ export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEn
|
||||||
private batchDeleteManager: BatchDeleteItemManager,
|
private batchDeleteManager: BatchDeleteItemManager,
|
||||||
private batchActiveManager: BatchActiveItemManager,
|
private batchActiveManager: BatchActiveItemManager,
|
||||||
private batchConfirmManager: BatchConfirmItemManager,
|
private batchConfirmManager: BatchConfirmItemManager,
|
||||||
|
private updatePriceManager: UpdateItemRatePriceManager,
|
||||||
private batchInactiveManager: BatchInactiveItemManager,
|
private batchInactiveManager: BatchInactiveItemManager,
|
||||||
private serviceData: ItemDataService,
|
private serviceData: ItemDataService,
|
||||||
|
private serviceRateData: ItemRateReadService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +64,14 @@ export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEn
|
||||||
return this.updateManager.getResult();
|
return this.updateManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(dataId, tenantId?: string): Promise<String> {
|
async updatePrice(data): Promise<any[]> {
|
||||||
|
this.updatePriceManager.setData(data);
|
||||||
|
this.updatePriceManager.setService(this.serviceRateData, TABLE_NAME.ITEM);
|
||||||
|
await this.updatePriceManager.execute();
|
||||||
|
return this.updatePriceManager.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(dataId, tenantId?: string): Promise<string> {
|
||||||
this.deleteManager.setData(dataId);
|
this.deleteManager.setData(dataId);
|
||||||
this.deleteManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
this.deleteManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
||||||
await this.deleteManager.execute();
|
await this.deleteManager.execute();
|
||||||
|
@ -77,7 +88,7 @@ export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEn
|
||||||
return this.batchDeleteManager.getResult();
|
return this.batchDeleteManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async active(dataId, tenantId?: string): Promise<String> {
|
async active(dataId, tenantId?: string): Promise<string> {
|
||||||
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
this.activeManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.activeManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
this.activeManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
||||||
await this.activeManager.execute();
|
await this.activeManager.execute();
|
||||||
|
@ -94,7 +105,7 @@ export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEn
|
||||||
return this.batchActiveManager.getResult();
|
return this.batchActiveManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async confirm(dataId, tenantId?: string): Promise<String> {
|
async confirm(dataId, tenantId?: string): Promise<string> {
|
||||||
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
this.confirmManager.setData(dataId, STATUS.ACTIVE);
|
||||||
this.confirmManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
this.confirmManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
||||||
await this.confirmManager.execute();
|
await this.confirmManager.execute();
|
||||||
|
@ -111,7 +122,7 @@ export class ItemDataOrchestrator extends BaseDataTransactionOrchestrator<ItemEn
|
||||||
return this.batchConfirmManager.getResult();
|
return this.batchConfirmManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
async inactive(dataId, tenantId?: string): Promise<String> {
|
async inactive(dataId, tenantId?: string): Promise<string> {
|
||||||
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
|
||||||
this.inactiveManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
this.inactiveManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
||||||
await this.inactiveManager.execute();
|
await this.inactiveManager.execute();
|
||||||
|
|
|
@ -33,6 +33,7 @@ export class DetailItemManager extends BaseDetailManager<ItemEntity> {
|
||||||
get selects(): string[] {
|
get selects(): string[] {
|
||||||
return [
|
return [
|
||||||
`${this.tableName}.id`,
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.image_url`,
|
||||||
`${this.tableName}.created_at`,
|
`${this.tableName}.created_at`,
|
||||||
`${this.tableName}.status`,
|
`${this.tableName}.status`,
|
||||||
`${this.tableName}.item_type`,
|
`${this.tableName}.item_type`,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entiti
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IndexItemRatesManager extends BaseIndexManager<ItemRateEntity> {
|
export class IndexItemRatesManager extends BaseIndexManager<ItemRateEntity> {
|
||||||
async prepareData(): Promise<void> {
|
async prepareData(): Promise<void> {
|
||||||
this.filterParam.order_by = `${this.tableName}.id`;
|
this.filterParam.order_by = `season_period.id`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,11 @@ export class IndexItemRatesManager extends BaseIndexManager<ItemRateEntity> {
|
||||||
get selects(): string[] {
|
get selects(): string[] {
|
||||||
return [
|
return [
|
||||||
`${this.tableName}.id`,
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.item_id`,
|
||||||
`${this.tableName}.price`,
|
`${this.tableName}.price`,
|
||||||
|
|
||||||
`season_period.id`,
|
`season_period.id`,
|
||||||
|
`season_period.priority`,
|
||||||
`season_period.created_at`,
|
`season_period.created_at`,
|
||||||
`season_period.creator_name`,
|
`season_period.creator_name`,
|
||||||
`season_period.editor_name`,
|
`season_period.editor_name`,
|
||||||
|
@ -68,6 +70,25 @@ export class IndexItemRatesManager extends BaseIndexManager<ItemRateEntity> {
|
||||||
itemIds: this.filterParam.item_ids,
|
itemIds: this.filterParam.item_ids,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.filterParam.season_period_ids) {
|
||||||
|
queryBuilder.andWhere(`season_period.id In (:...seasonIdss)`, {
|
||||||
|
seasonIdss: this.filterParam.season_period_ids,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.filterParam.start_date) {
|
||||||
|
queryBuilder.andWhere(`season_period.start_date <= :inputStartDate`, {
|
||||||
|
inputStartDate: this.filterParam.end_date,
|
||||||
|
});
|
||||||
|
|
||||||
|
queryBuilder.andWhere(`season_period.end_date >= :inputEndDate`, {
|
||||||
|
inputEndDate: this.filterParam.start_date,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
queryBuilder.addOrderBy('season_period.priority', 'ASC');
|
||||||
|
|
||||||
return queryBuilder;
|
return queryBuilder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { BaseCustomManager } from 'src/core/modules/domain/usecase/managers/base-custom.manager';
|
||||||
|
import { ItemEntity } from '../../entities/item.entity';
|
||||||
|
import { EventTopics } from 'src/core/strings/constants/interface.constants';
|
||||||
|
import { ItemModel } from '../../../data/models/item.model';
|
||||||
|
import { In, LessThanOrEqual, MoreThanOrEqual } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UpdateItemRatePriceManager extends BaseCustomManager<ItemEntity> {
|
||||||
|
protected rates = [];
|
||||||
|
get entityTarget(): any {
|
||||||
|
return ItemModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
get eventTopics(): EventTopics[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async validateProcess(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeProcess(): Promise<void> {
|
||||||
|
let query;
|
||||||
|
const item_ids = this.data.items.map((item) => {
|
||||||
|
return item.item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.data.season_period_id) {
|
||||||
|
query = {
|
||||||
|
item_id: In(item_ids),
|
||||||
|
season_period: {
|
||||||
|
id: this.data.season_period_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
query = {
|
||||||
|
item_id: In(item_ids),
|
||||||
|
season_period: {
|
||||||
|
start_date: MoreThanOrEqual(this.data.booking_date),
|
||||||
|
end_date: LessThanOrEqual(this.data.booking_date),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rates = await this.dataService.getManyByOptions({
|
||||||
|
where: query,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async process(): Promise<void> {
|
||||||
|
this.data.items.map((item) => {
|
||||||
|
const current_price = this.rates.find(
|
||||||
|
(rate) => rate.item_id == item.item.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.assign(item, {
|
||||||
|
total_price: current_price?.price ?? item.item.base_price,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterProcess(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getResult() {
|
||||||
|
return this.data.items;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,12 @@ export class FilterItemDto extends BaseFilterDto implements FilterItemEntity {
|
||||||
})
|
})
|
||||||
item_categories: string[];
|
item_categories: string[];
|
||||||
|
|
||||||
|
@ApiProperty({ type: ['string'], required: false })
|
||||||
|
@Transform((body) => {
|
||||||
|
return Array.isArray(body.value) ? body.value : [body.value];
|
||||||
|
})
|
||||||
|
season_period_ids: string[];
|
||||||
|
|
||||||
@ApiProperty({ type: ['string'], required: false })
|
@ApiProperty({ type: ['string'], required: false })
|
||||||
@Transform((body) => {
|
@Transform((body) => {
|
||||||
return Array.isArray(body.value) ? body.value : [body.value];
|
return Array.isArray(body.value) ? body.value : [body.value];
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class ItemDto extends BaseStatusDto implements ItemEntity {
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@ValidateIf((body) => body.image)
|
@ValidateIf((body) => body.image)
|
||||||
image: string;
|
image_url: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class UpdateItemPriceDto {
|
||||||
|
@ApiProperty({
|
||||||
|
type: [Object],
|
||||||
|
required: true,
|
||||||
|
example: [
|
||||||
|
{
|
||||||
|
item: {
|
||||||
|
id: 'bee5c493-fb35-4ceb-b7a1-7bc3edb3c63b',
|
||||||
|
name: 'TEnant 2 wahana air',
|
||||||
|
item_type: 'wahana',
|
||||||
|
base_price: '100000',
|
||||||
|
hpp: '0',
|
||||||
|
tenant: {
|
||||||
|
id: 'e19a4637-d4db-48cc-89ce-501913d07cdd',
|
||||||
|
name: 'e19a4637-d4db-48cc-89ce-501913d07cdd',
|
||||||
|
share_margin: null,
|
||||||
|
},
|
||||||
|
item_category: {
|
||||||
|
id: '88633772-ec34-4645-bc04-6cfdce6af0cf',
|
||||||
|
name: 'Wahana Air',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
qty: 1,
|
||||||
|
total_price: '100000',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
items: Object[];
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
type: String,
|
||||||
|
example: 'uuid',
|
||||||
|
})
|
||||||
|
season_period_id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
type: Date,
|
||||||
|
example: '2024-08-17',
|
||||||
|
})
|
||||||
|
booking_date: Date;
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import { ItemEntity } from '../domain/entities/item.entity';
|
||||||
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
|
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
|
||||||
import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto';
|
import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto';
|
||||||
import { Public } from 'src/core/guards';
|
import { Public } from 'src/core/guards';
|
||||||
|
import { UpdateItemPriceDto } from './dto/update-item-price.dto';
|
||||||
|
|
||||||
@ApiTags(`${MODULE_NAME.ITEM.split('-').join(' ')} - data`)
|
@ApiTags(`${MODULE_NAME.ITEM.split('-').join(' ')} - data`)
|
||||||
@Controller(`v1/${MODULE_NAME.ITEM}`)
|
@Controller(`v1/${MODULE_NAME.ITEM}`)
|
||||||
|
@ -28,13 +29,18 @@ export class ItemDataController {
|
||||||
return await this.orchestrator.create(data);
|
return await this.orchestrator.create(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('update-price')
|
||||||
|
async updatePrice(@Body() body: UpdateItemPriceDto): Promise<any> {
|
||||||
|
return await this.orchestrator.updatePrice(body);
|
||||||
|
}
|
||||||
|
|
||||||
@Put('/batch-delete')
|
@Put('/batch-delete')
|
||||||
async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
|
async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
|
||||||
return await this.orchestrator.batchDelete(body.ids);
|
return await this.orchestrator.batchDelete(body.ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/active')
|
@Patch(':id/active')
|
||||||
async active(@Param('id') dataId: string): Promise<String> {
|
async active(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.active(dataId);
|
return await this.orchestrator.active(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +50,7 @@ export class ItemDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/confirm')
|
@Patch(':id/confirm')
|
||||||
async confirm(@Param('id') dataId: string): Promise<String> {
|
async confirm(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.confirm(dataId);
|
return await this.orchestrator.confirm(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +60,7 @@ export class ItemDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/inactive')
|
@Patch(':id/inactive')
|
||||||
async inactive(@Param('id') dataId: string): Promise<String> {
|
async inactive(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.inactive(dataId);
|
return await this.orchestrator.inactive(dataId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +78,7 @@ export class ItemDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async delete(@Param('id') dataId: string): Promise<String> {
|
async delete(@Param('id') dataId: string): Promise<string> {
|
||||||
return await this.orchestrator.delete(dataId);
|
return await this.orchestrator.delete(dataId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue