diff --git a/database/migrations/.snapshot-dmenu.json b/database/migrations/.snapshot-dmenu.json index 6a4d810..13b8606 100644 --- a/database/migrations/.snapshot-dmenu.json +++ b/database/migrations/.snapshot-dmenu.json @@ -961,6 +961,18 @@ "default": "0", "mappedType": "decimal" }, + "credit": { + "name": "credit", + "type": "numeric(10,0)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "precision": 10, + "scale": 0, + "default": "0", + "mappedType": "decimal" + }, "domain": { "name": "domain", "type": "varchar(255)", @@ -2905,6 +2917,394 @@ }, "nativeEnums": {} }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "restaurant_id": { + "name": "restaurant_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "title": { + "name": "title", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "groups": { + "name": "groups", + "type": "jsonb", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "'[]'", + "mappedType": "json" + }, + "sent_type": { + "name": "sent_type", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "enumItems": [ + "push", + "sms" + ], + "mappedType": "enum" + }, + "discount_code": { + "name": "discount_code", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "total_count": { + "name": "total_count", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "total_cost": { + "name": "total_cost", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "refunded": { + "name": "refunded", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "sent_count": { + "name": "sent_count", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "failed_count": { + "name": "failed_count", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "status": { + "name": "status", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "'sending'", + "enumItems": [ + "sending", + "completed" + ], + "mappedType": "enum" + } + }, + "name": "campaigns", + "schema": "public", + "indexes": [ + { + "keyName": "campaigns_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "campaigns_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "campaigns_restaurant_id_index", + "columnNames": [ + "restaurant_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "campaigns_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "campaigns_restaurant_id_foreign": { + "constraintName": "campaigns_restaurant_id_foreign", + "columnNames": [ + "restaurant_id" + ], + "localTableName": "public.campaigns", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.restaurants", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "restaurant_id": { + "name": "restaurant_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "amount": { + "name": "amount", + "type": "numeric(10,0)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "precision": 10, + "scale": 0, + "mappedType": "decimal" + }, + "balance": { + "name": "balance", + "type": "numeric(10,0)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "precision": 10, + "scale": 0, + "mappedType": "decimal" + }, + "type": { + "name": "type", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "enumItems": [ + "credit", + "debit" + ], + "mappedType": "enum" + }, + "reason": { + "name": "reason", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "enumItems": [ + "sms_send", + "deposit", + "adjustment" + ], + "mappedType": "enum" + } + }, + "name": "restaurant_credit_transactions", + "schema": "public", + "indexes": [ + { + "keyName": "restaurant_credit_transactions_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "restaurant_credit_transactions_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "restaurant_credit_transactions_restaurant_id_index", + "columnNames": [ + "restaurant_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "restaurant_credit_transactions_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "restaurant_credit_transactions_restaurant_id_foreign": { + "constraintName": "restaurant_credit_transactions_restaurant_id_foreign", + "columnNames": [ + "restaurant_id" + ], + "localTableName": "public.restaurant_credit_transactions", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.restaurants", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, { "columns": { "id": { @@ -3433,6 +3833,183 @@ "foreignKeys": {}, "nativeEnums": {} }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "restaurant_id": { + "name": "restaurant_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "image_url": { + "name": "image_url", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "title": { + "name": "title", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "link": { + "name": "link", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "order": { + "name": "order", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "true", + "mappedType": "boolean" + } + }, + "name": "sliders", + "schema": "public", + "indexes": [ + { + "keyName": "sliders_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "sliders_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "sliders_restaurant_id_index", + "columnNames": [ + "restaurant_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "sliders_restaurant_id_is_active_index", + "columnNames": [ + "restaurant_id", + "is_active" + ], + "composite": true, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "sliders_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "sliders_restaurant_id_foreign": { + "constraintName": "sliders_restaurant_id_foreign", + "columnNames": [ + "restaurant_id" + ], + "localTableName": "public.sliders", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.restaurants", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, { "columns": { "id": { @@ -3454,30 +4031,30 @@ "length": 26, "mappedType": "character" }, - "phone": { - "name": "phone", - "type": "varchar(255)", + "count": { + "name": "count", + "type": "int", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, - "length": 255, - "mappedType": "string" - }, - "created_at": { - "name": "created_at", - "type": "timestamptz", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "length": 6, - "mappedType": "datetime" + "default": "0", + "mappedType": "integer" } }, "name": "sms_logs", "schema": "public", "indexes": [ + { + "columnNames": [ + "restaurant_id" + ], + "composite": false, + "keyName": "sms_logs_restaurant_id_unique", + "constraint": true, + "primary": false, + "unique": true + }, { "keyName": "sms_logs_pkey", "columnNames": [ @@ -4296,6 +4873,15 @@ "default": "0", "mappedType": "decimal" }, + "prepare_time": { + "name": "prepare_time", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "integer" + }, "total": { "name": "total", "type": "numeric(10,0)", @@ -5699,6 +6285,312 @@ }, "nativeEnums": {} }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "restaurant_id": { + "name": "restaurant_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "count": { + "name": "count", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "0", + "mappedType": "integer" + } + }, + "name": "user_groups", + "schema": "public", + "indexes": [ + { + "keyName": "user_groups_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_groups_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_groups_restaurant_id_index", + "columnNames": [ + "restaurant_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_groups_restaurant_id_name_unique", + "columnNames": [ + "restaurant_id", + "name" + ], + "composite": true, + "constraint": true, + "primary": false, + "unique": true + }, + { + "keyName": "user_groups_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "user_groups_restaurant_id_foreign": { + "constraintName": "user_groups_restaurant_id_foreign", + "columnNames": [ + "restaurant_id" + ], + "localTableName": "public.user_groups", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.restaurants", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "user_id": { + "name": "user_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "user_group_id": { + "name": "user_group_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + } + }, + "name": "user_group_users", + "schema": "public", + "indexes": [ + { + "keyName": "user_group_users_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_group_users_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_group_users_user_id_index", + "columnNames": [ + "user_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_group_users_user_group_id_index", + "columnNames": [ + "user_group_id" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "user_group_users_user_id_user_group_id_unique", + "columnNames": [ + "user_id", + "user_group_id" + ], + "composite": true, + "constraint": true, + "primary": false, + "unique": true + }, + { + "keyName": "user_group_users_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "user_group_users_user_id_foreign": { + "constraintName": "user_group_users_user_id_foreign", + "columnNames": [ + "user_id" + ], + "localTableName": "public.user_group_users", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.users", + "updateRule": "cascade" + }, + "user_group_users_user_group_id_foreign": { + "constraintName": "user_group_users_user_group_id_foreign", + "columnNames": [ + "user_group_id" + ], + "localTableName": "public.user_group_users", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.user_groups", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, { "columns": { "id": { diff --git a/database/migrations/Migration20260704100000_addCampaignsTable.ts b/database/migrations/Migration20260704100000_addCampaignsTable.ts new file mode 100644 index 0000000..bcb3afd --- /dev/null +++ b/database/migrations/Migration20260704100000_addCampaignsTable.ts @@ -0,0 +1,41 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260704100000_addCampaignsTable extends Migration { + + override async up(): Promise { + this.addSql(` + create table "campaigns" ( + "id" char(26) not null, + "created_at" timestamptz not null default now(), + "updated_at" timestamptz not null default now(), + "deleted_at" timestamptz null, + "restaurant_id" char(26) not null, + "title" varchar(255) not null, + "groups" jsonb not null default '[]', + "sent_type" text check ("sent_type" in ('push', 'sms')) not null, + "discount_code" varchar(255) not null, + "total_count" int not null default 0, + "total_cost" int not null default 0, + "refunded" int not null default 0, + "sent_count" int not null default 0, + "failed_count" int not null default 0, + "status" text check ("status" in ('sending', 'completed')) not null default 'sending', + constraint "campaigns_pkey" primary key ("id") + ); + `); + this.addSql(`create index "campaigns_created_at_index" on "campaigns" ("created_at");`); + this.addSql(`create index "campaigns_deleted_at_index" on "campaigns" ("deleted_at");`); + this.addSql(`create index "campaigns_restaurant_id_index" on "campaigns" ("restaurant_id");`); + this.addSql(` + alter table "campaigns" + add constraint "campaigns_restaurant_id_foreign" + foreign key ("restaurant_id") references "restaurants" ("id") on update cascade; + `); + } + + override async down(): Promise { + this.addSql(`alter table "campaigns" drop constraint if exists "campaigns_restaurant_id_foreign";`); + this.addSql(`drop table if exists "campaigns" cascade;`); + } + +} diff --git a/src/modules/users/entities/campaign.entity.ts b/src/modules/users/entities/campaign.entity.ts index 7796c79..5bec59b 100644 --- a/src/modules/users/entities/campaign.entity.ts +++ b/src/modules/users/entities/campaign.entity.ts @@ -24,6 +24,12 @@ export class Campaign extends BaseEntity { @Property({ default: 0 }) totalCount: number = 0; + @Property({ default: 0 }) + totalCost: number = 0; + + @Property({ default: 0 }) + refunded: number = 0; + @Property({ default: 0 }) sentCount: number = 0; diff --git a/src/modules/users/providers/campaign-dispatch.listener.ts b/src/modules/users/providers/campaign-dispatch.listener.ts index 6e490bf..eb8ad5e 100644 --- a/src/modules/users/providers/campaign-dispatch.listener.ts +++ b/src/modules/users/providers/campaign-dispatch.listener.ts @@ -61,6 +61,7 @@ export class CampaignDispatchListener { reason: RestaurantCreditTransactionReason.ADJUSTMENT, em, }); + campaign.refunded = refundAmount; } } diff --git a/src/modules/users/providers/campaign.service.ts b/src/modules/users/providers/campaign.service.ts index 79304a4..bc1f541 100644 --- a/src/modules/users/providers/campaign.service.ts +++ b/src/modules/users/providers/campaign.service.ts @@ -54,6 +54,8 @@ export class CampaignService { discountCode: dto.discountCode, status: dto.sentType === CampaignSentType.SMS ? CampaignStatus.SENDING : CampaignStatus.COMPLETED, totalCount: 0, + totalCost: 0, + refunded: 0, sentCount: 0, failedCount: 0, }; @@ -71,6 +73,7 @@ export class CampaignService { ); campaign.totalCount = smsDispatchPlan.totalCount; + campaign.totalCost = smsDispatchPlan.totalCost; if (smsDispatchPlan.totalCount === 0) { campaign.status = CampaignStatus.COMPLETED; } else {