diff --git a/database/migrations/.snapshot-dpage.json b/database/migrations/.snapshot-dpage.json index d0ed02c..32dc152 100644 --- a/database/migrations/.snapshot-dpage.json +++ b/database/migrations/.snapshot-dpage.json @@ -11,225 +11,63 @@ "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" - }, - "danak_subscription_id": { - "name": "danak_subscription_id", - "type": "uuid", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "uuid" - }, - "name": { - "name": "name", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "length": 255, - "mappedType": "string" - }, - "slug": { - "name": "slug", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "length": 255, - "mappedType": "string" - }, - "domain": { - "name": "domain", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "length": 255, - "mappedType": "string" - }, - "is_domain_verified": { - "name": "is_domain_verified", - "type": "boolean", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "default": "false", - "mappedType": "boolean" - }, - "domain_verification_token": { - "name": "domain_verification_token", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "length": 255, - "mappedType": "string" - }, - "domain_verified_at": { - "name": "domain_verified_at", - "type": "timestamptz", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "length": 6, - "mappedType": "datetime" - }, - "logo_url": { - "name": "logo_url", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "length": 255, - "mappedType": "string" - }, - "max_catalogues_count": { - "name": "max_catalogues_count", - "type": "numeric(10,0)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "precision": 10, - "scale": 0, - "default": "0", - "mappedType": "decimal" - } - }, - "name": "business", - "schema": "public", - "indexes": [ - { - "columnNames": [ - "danak_subscription_id" - ], - "composite": false, - "keyName": "business_danak_subscription_id_unique", - "constraint": true, - "primary": false, - "unique": true - }, - { - "keyName": "business_created_at_index", - "columnNames": [ - "created_at" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "business_deleted_at_index", - "columnNames": [ - "deleted_at" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "business_pkey", - "columnNames": [ - "id" - ], - "composite": false, - "constraint": true, "primary": true, - "unique": true - } - ], - "checks": [], - "foreignKeys": {}, - "nativeEnums": {} - }, - { - "columns": { - "id": { - "name": "id", - "type": "char(26)", - "unsigned": false, - "autoincrement": false, - "primary": false, "nullable": false, + "unique": false, "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "character" }, "created_at": { "name": "created_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "updated_at": { "name": "updated_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "deleted_at": { "name": "deleted_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, + "unique": false, "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "first_name": { @@ -239,7 +77,13 @@ "autoincrement": false, "primary": false, "nullable": true, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "last_name": { @@ -249,7 +93,13 @@ "autoincrement": false, "primary": false, "nullable": true, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "phone": { @@ -259,7 +109,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "business_id": { @@ -269,7 +125,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": true, "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "character" } }, @@ -281,58 +143,60 @@ "business_id" ], "composite": false, - "keyName": "admins_business_id_unique", "constraint": true, - "primary": false, - "unique": true + "keyName": "admins_business_id_unique", + "unique": true, + "primary": false }, { - "keyName": "admins_created_at_index", "columnNames": [ "created_at" ], "composite": false, "constraint": false, - "primary": false, - "unique": false + "keyName": "admins_created_at_index", + "unique": false, + "primary": false }, { - "keyName": "admins_deleted_at_index", "columnNames": [ "deleted_at" ], "composite": false, "constraint": false, - "primary": false, - "unique": false + "keyName": "admins_deleted_at_index", + "unique": false, + "primary": false }, { - "keyName": "admins_pkey", "columnNames": [ "id" ], "composite": false, - "constraint": true, - "primary": true, - "unique": true + "constraint": false, + "keyName": "admins_pkey", + "unique": true, + "primary": true } ], "checks": [], "foreignKeys": { "admins_business_id_foreign": { - "constraintName": "admins_business_id_foreign", "columnNames": [ "business_id" ], + "constraintName": "admins_business_id_foreign", "localTableName": "public.admins", + "referencedTableName": "public.business", "referencedColumnNames": [ "id" ], - "referencedTableName": "public.business", - "updateRule": "cascade" + "updateRule": "cascade", + "deleteRule": "no action" } }, - "nativeEnums": {} + "nativeEnums": {}, + "comment": null }, { "columns": { @@ -341,43 +205,81 @@ "type": "char(26)", "unsigned": false, "autoincrement": false, - "primary": false, + "primary": true, "nullable": false, + "unique": false, "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "character" }, "created_at": { "name": "created_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "updated_at": { "name": "updated_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "deleted_at": { "name": "deleted_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, + "unique": false, "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "datetime" }, + "danak_subscription_id": { + "name": "danak_subscription_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": true, + "length": null, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "uuid" + }, "name": { "name": "name", "type": "varchar(255)", @@ -385,7 +287,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "slug": { @@ -395,7 +303,241 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + }, + "domain": { + "name": "domain", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + }, + "is_domain_verified": { + "name": "is_domain_verified", + "type": "bool", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": null, + "precision": null, + "scale": null, + "default": "false", + "comment": null, + "enumItems": [], + "mappedType": "boolean" + }, + "domain_verification_token": { + "name": "domain_verification_token", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + }, + "domain_verified_at": { + "name": "domain_verified_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "logo_url": { + "name": "logo_url", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + }, + "max_catalogues_count": { + "name": "max_catalogues_count", + "type": "numeric(10,0)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": null, + "precision": 10, + "scale": 0, + "default": "0", + "comment": null, + "enumItems": [], + "mappedType": "decimal" + } + }, + "name": "business", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "keyName": "business_created_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "danak_subscription_id" + ], + "composite": false, + "constraint": true, + "keyName": "business_danak_subscription_id_unique", + "unique": true, + "primary": false + }, + { + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "keyName": "business_deleted_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "id" + ], + "composite": false, + "constraint": false, + "keyName": "business_pkey", + "unique": true, + "primary": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": {}, + "comment": null + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": true, + "nullable": false, + "unique": false, + "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "content": { @@ -405,6 +547,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, + "length": null, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "json" }, "status": { @@ -414,6 +563,12 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, + "length": null, + "precision": null, + "scale": null, + "default": null, + "comment": null, "enumItems": [ "APPROVED", "PENDING", @@ -428,6 +583,12 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, + "length": null, + "precision": null, + "scale": null, + "default": null, + "comment": null, "enumItems": [ "a4", "a3", @@ -442,61 +603,84 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "character" + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" } }, "name": "catalogue", "schema": "public", "indexes": [ { - "keyName": "catalogue_created_at_index", "columnNames": [ "created_at" ], "composite": false, "constraint": false, - "primary": false, - "unique": false + "keyName": "catalogue_created_at_index", + "unique": false, + "primary": false }, { - "keyName": "catalogue_deleted_at_index", "columnNames": [ "deleted_at" ], "composite": false, "constraint": false, - "primary": false, - "unique": false + "keyName": "catalogue_deleted_at_index", + "unique": false, + "primary": false }, { - "keyName": "catalogue_pkey", "columnNames": [ "id" ], "composite": false, - "constraint": true, - "primary": true, - "unique": true + "constraint": false, + "keyName": "catalogue_pkey", + "unique": true, + "primary": true } ], "checks": [], "foreignKeys": { "catalogue_business_id_foreign": { - "constraintName": "catalogue_business_id_foreign", "columnNames": [ "business_id" ], + "constraintName": "catalogue_business_id_foreign", "localTableName": "public.catalogue", + "referencedTableName": "public.business", "referencedColumnNames": [ "id" ], - "referencedTableName": "public.business", - "deleteRule": "restrict", - "updateRule": "cascade" + "updateRule": "cascade", + "deleteRule": "restrict" } }, - "nativeEnums": {} + "nativeEnums": {}, + "comment": null }, { "columns": { @@ -505,41 +689,347 @@ "type": "char(26)", "unsigned": false, "autoincrement": false, - "primary": false, + "primary": true, "nullable": false, + "unique": false, "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "character" }, "created_at": { "name": "created_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "updated_at": { "name": "updated_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, "default": "now()", + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "deleted_at": { "name": "deleted_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, + "unique": false, "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + } + }, + "name": "icon_groups", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "keyName": "icon_groups_created_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "keyName": "icon_groups_deleted_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "id" + ], + "composite": false, + "constraint": false, + "keyName": "icon_groups_pkey", + "unique": true, + "primary": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": {}, + "comment": null + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": true, + "nullable": false, + "unique": false, + "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "url": { + "name": "url", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "string" + }, + "group_id": { + "name": "group_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "character" + } + }, + "name": "icons", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "keyName": "icons_created_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "keyName": "icons_deleted_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "id" + ], + "composite": false, + "constraint": false, + "keyName": "icons_pkey", + "unique": true, + "primary": true + }, + { + "columnNames": [ + "url" + ], + "composite": false, + "constraint": false, + "keyName": "icons_url_index", + "unique": false, + "primary": false + } + ], + "checks": [], + "foreignKeys": { + "icons_group_id_foreign": { + "columnNames": [ + "group_id" + ], + "constraintName": "icons_group_id_foreign", + "localTableName": "public.icons", + "referencedTableName": "public.icon_groups", + "referencedColumnNames": [ + "id" + ], + "updateRule": "cascade", + "deleteRule": "no action" + } + }, + "nativeEnums": {}, + "comment": null + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": true, + "nullable": false, + "unique": false, + "length": 26, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": "now()", + "comment": null, + "enumItems": [], + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz(6)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "unique": false, + "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "datetime" }, "hashed_token": { @@ -549,7 +1039,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "admin_id": { @@ -559,7 +1055,13 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "business_id": { @@ -569,17 +1071,29 @@ "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 255, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "string" }, "expires_at": { "name": "expires_at", - "type": "timestamptz", + "type": "timestamptz(6)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, + "unique": false, "length": 6, + "precision": null, + "scale": null, + "default": null, + "comment": null, + "enumItems": [], "mappedType": "datetime" } }, @@ -587,70 +1101,71 @@ "schema": "public", "indexes": [ { - "keyName": "refreshtokens_created_at_index", - "columnNames": [ - "created_at" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "refreshtokens_deleted_at_index", - "columnNames": [ - "deleted_at" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "refreshtokens_expires_at_index", - "columnNames": [ - "expires_at" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "refreshtokens_hashed_token_index", - "columnNames": [ - "hashed_token" - ], - "composite": false, - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "refreshtokens_admin_id_business_id_index", "columnNames": [ "admin_id", "business_id" ], "composite": true, "constraint": false, - "primary": false, - "unique": false + "keyName": "refreshtokens_admin_id_business_id_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "keyName": "refreshtokens_created_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "keyName": "refreshtokens_deleted_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "expires_at" + ], + "composite": false, + "constraint": false, + "keyName": "refreshtokens_expires_at_index", + "unique": false, + "primary": false + }, + { + "columnNames": [ + "hashed_token" + ], + "composite": false, + "constraint": false, + "keyName": "refreshtokens_hashed_token_index", + "unique": false, + "primary": false }, { - "keyName": "refreshtokens_pkey", "columnNames": [ "id" ], "composite": false, - "constraint": true, - "primary": true, - "unique": true + "constraint": false, + "keyName": "refreshtokens_pkey", + "unique": true, + "primary": true } ], "checks": [], "foreignKeys": {}, - "nativeEnums": {} + "nativeEnums": {}, + "comment": null } ], "nativeEnums": {} diff --git a/database/migrations/Migration20260521055029.ts b/database/migrations/Migration20260521055029.ts new file mode 100644 index 0000000..2b2f698 --- /dev/null +++ b/database/migrations/Migration20260521055029.ts @@ -0,0 +1,18 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260521055029 extends Migration { + + override async up(): Promise { + this.addSql(`create table "icon_groups" ("id" char(26) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "name" varchar(255) not null, constraint "icon_groups_pkey" primary key ("id"));`); + this.addSql(`create index "icon_groups_created_at_index" on "icon_groups" ("created_at");`); + this.addSql(`create index "icon_groups_deleted_at_index" on "icon_groups" ("deleted_at");`); + + this.addSql(`create table "icons" ("id" char(26) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "url" varchar(255) not null, "group_id" char(26) not null, constraint "icons_pkey" primary key ("id"));`); + this.addSql(`create index "icons_created_at_index" on "icons" ("created_at");`); + this.addSql(`create index "icons_deleted_at_index" on "icons" ("deleted_at");`); + this.addSql(`create index "icons_group_id_index" on "icons" ("group_id");`); + + this.addSql(`alter table "icons" add constraint "icons_group_id_foreign" foreign key ("group_id") references "icon_groups" ("id") on update cascade;`); + } + +} diff --git a/database/migrations/Migration20260521055339.ts b/database/migrations/Migration20260521055339.ts new file mode 100644 index 0000000..51c1d4a --- /dev/null +++ b/database/migrations/Migration20260521055339.ts @@ -0,0 +1,17 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260521055339 extends Migration { + + override async up(): Promise { + this.addSql(`drop index "icons_group_id_index";`); + + this.addSql(`create index "icons_url_index" on "icons" ("url");`); + } + + override async down(): Promise { + this.addSql(`drop index "icons_url_index";`); + + this.addSql(`create index "icons_group_id_index" on "icons" ("group_id");`); + } + +} diff --git a/src/app.module.ts b/src/app.module.ts index 2d39f7b..4b556e6 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,6 +11,7 @@ import { EventEmitterModule } from '@nestjs/event-emitter'; import { BusinessModule } from './modules/business/business.module'; import { CatalogueModule } from './modules/catalogue/catalogue.module'; import { HttpModule } from '@nestjs/axios'; +import { IconsModule } from './modules/icons/icons.module'; @Module({ imports: [ @@ -30,7 +31,7 @@ import { HttpModule } from '@nestjs/axios'; BusinessModule, CatalogueModule, HttpModule.register({ global: true, timeout: 10000, headers: { "Content-Type": "application/json" } }), - + IconsModule, ], controllers: [], providers: [], diff --git a/src/modules/icons/controllers/icons.controller.ts b/src/modules/icons/controllers/icons.controller.ts new file mode 100644 index 0000000..e4e65cd --- /dev/null +++ b/src/modules/icons/controllers/icons.controller.ts @@ -0,0 +1,131 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete, UploadedFiles, UseInterceptors } from '@nestjs/common'; +import { IconService } from '../providers/icon.service'; +import { GroupService } from '../providers/group.service'; +import { CreateIconDto } from '../dto/create-icon.dto'; +import { UpdateIconDto } from '../dto/update-icon.dto'; +import { CreateGroupDto } from '../dto/create-group.dto'; +import { UpdateGroupDto } from '../dto/update-group.dto'; +import { ApiTags, ApiOperation, ApiParam, ApiBody, ApiBearerAuth, ApiConsumes } from '@nestjs/swagger'; +import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard'; +import { UseGuards } from '@nestjs/common'; +import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; +import { FilesInterceptor, type File } from '@nest-lab/fastify-multer'; +import { CreateBatchIconsDto } from '../dto/create-batch-icons.dto'; + +@ApiTags('icons') +@Controller() +export class IconsController { + constructor( + private readonly iconService: IconService, + private readonly groupService: GroupService, + ) {} + + @Get('admin/groups/icons') + @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Get all icons' }) + findAllPublicIcons() { + return this.groupService.findAllGroups(); + } + + /** + * Super Admin Endpoints + */ + @Post('super-admin/icons') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Create icon' }) + @ApiBody({ type: CreateIconDto }) + createIcon(@Body() dto: CreateIconDto) { + return this.iconService.create(dto); + } + + + @Post('super-admin/icons/batch') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Upload and create icons in batch' }) + @ApiConsumes('multipart/form-data') + @UseInterceptors(FilesInterceptor('files')) + @ApiBody({ type: CreateBatchIconsDto }) + createBatchIcons( + @Body('groupId') groupId: string, + @UploadedFiles() files: File[], + ) { + return this.iconService.createBatch(groupId, files); + } + + + @Get('super-admin/icons') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Get all icons' }) + findAllIcons() { + return this.iconService.findAll(); + } + + @Get('super-admin/icons/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Get icon by id' }) + @ApiParam({ name: 'id', required: true, type: String }) + findOneIcon(@Param('id') id: string) { + return this.iconService.findOne(id); + } + + @Patch('super-admin/icons/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Update icon' }) + @ApiParam({ name: 'id' }) + @ApiBody({ type: UpdateIconDto }) + updateIcon(@Param('id') id: string, @Body() dto: UpdateIconDto) { + return this.iconService.update(id, dto); + } + + @Delete('super-admin/icons/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Delete icon' }) + @ApiParam({ name: 'id' }) + removeIcon(@Param('id') id: string) { + return this.iconService.remove(id); + } + + // Group endpoints (must come before :id routes to avoid route conflicts) + @Post('super-admin/icons/groups') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Create icon group' }) + @ApiBody({ type: CreateGroupDto }) + createGroup(@Body() dto: CreateGroupDto) { + return this.groupService.create(dto); + } + + @Get('super-admin/icons/groups') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Get all icon groups' }) + async findAllGroups() { + console.log('find icona'); + const a = await this.groupService.findAllGroups(); + console.log(a); + return a; + } + + @Get('super-admin/icons/groups/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Get icon group by id' }) + @ApiParam({ name: 'id', required: true, type: String }) + findOneGroup(@Param('id') id: string) { + return this.groupService.findOne(id); + } + + @Patch('super-admin/icons/groups/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Update icon group' }) + @ApiParam({ name: 'id' }) + updateGroup(@Param('id') id: string, @Body() dto: UpdateGroupDto) { + return this.groupService.update(id, dto); + } + + @Delete('super-admin/icons/groups/:id') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Delete icon group' }) + @ApiParam({ name: 'id' }) + removeGroup(@Param('id') id: string) { + return this.groupService.remove(id); + } +} diff --git a/src/modules/icons/dto/create-batch-icons.dto.ts b/src/modules/icons/dto/create-batch-icons.dto.ts new file mode 100644 index 0000000..dd19fb4 --- /dev/null +++ b/src/modules/icons/dto/create-batch-icons.dto.ts @@ -0,0 +1,17 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class CreateBatchIconsDto { + @IsString() + @ApiProperty({ example: 'group-id-here' }) + groupId!: string; + + @ApiProperty({ + type: 'array', + items: { + type: 'string', + format: 'binary', + }, + }) + files!: any[]; +} diff --git a/src/modules/icons/dto/create-group.dto.ts b/src/modules/icons/dto/create-group.dto.ts new file mode 100644 index 0000000..1cb0d72 --- /dev/null +++ b/src/modules/icons/dto/create-group.dto.ts @@ -0,0 +1,9 @@ +import { IsString } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateGroupDto { + @IsString() + @ApiProperty({ example: 'Social Media' }) + name!: string; +} + diff --git a/src/modules/icons/dto/create-icon.dto.ts b/src/modules/icons/dto/create-icon.dto.ts new file mode 100644 index 0000000..5c06089 --- /dev/null +++ b/src/modules/icons/dto/create-icon.dto.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateIconDto { + @IsString() + @ApiProperty({ example: 'https://example.com/icons/facebook.svg' }) + url!: string; + + @IsString() + @ApiProperty({ example: 'group-id-here' }) + groupId!: string; +} diff --git a/src/modules/icons/dto/update-group.dto.ts b/src/modules/icons/dto/update-group.dto.ts new file mode 100644 index 0000000..8174604 --- /dev/null +++ b/src/modules/icons/dto/update-group.dto.ts @@ -0,0 +1,5 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateGroupDto } from './create-group.dto'; + +export class UpdateGroupDto extends PartialType(CreateGroupDto) {} + diff --git a/src/modules/icons/dto/update-icon.dto.ts b/src/modules/icons/dto/update-icon.dto.ts new file mode 100644 index 0000000..6ad1b53 --- /dev/null +++ b/src/modules/icons/dto/update-icon.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateIconDto } from './create-icon.dto'; + +export class UpdateIconDto extends PartialType(CreateIconDto) {} diff --git a/src/modules/icons/entities/group.entity.ts b/src/modules/icons/entities/group.entity.ts new file mode 100644 index 0000000..a62c4e4 --- /dev/null +++ b/src/modules/icons/entities/group.entity.ts @@ -0,0 +1,15 @@ +import { Entity, Index, Property, Collection, OneToMany, Cascade } from '@mikro-orm/core'; +import { BaseEntity } from '../../../common/entities/base.entity'; +import { Icon } from './icon.entity'; + +@Entity({ tableName: 'icon_groups' }) +export class Group extends BaseEntity { + @Property() + name!: string; + + @OneToMany(() => Icon, icon => icon.group,{ + cascade: [Cascade.ALL], + orphanRemoval: true, + }) + icons = new Collection(this); +} diff --git a/src/modules/icons/entities/icon.entity.ts b/src/modules/icons/entities/icon.entity.ts new file mode 100644 index 0000000..c8eb147 --- /dev/null +++ b/src/modules/icons/entities/icon.entity.ts @@ -0,0 +1,13 @@ +import { Entity, Index, Property, ManyToOne } from '@mikro-orm/core'; +import { BaseEntity } from '../../../common/entities/base.entity'; +import { Group } from './group.entity'; + +@Entity({ tableName: 'icons' }) +@Index({ properties: ['url'] }) +export class Icon extends BaseEntity { + @Property() + url!: string; + + @ManyToOne(() => Group) + group!: Group; +} diff --git a/src/modules/icons/icons.module.ts b/src/modules/icons/icons.module.ts new file mode 100644 index 0000000..4cb0536 --- /dev/null +++ b/src/modules/icons/icons.module.ts @@ -0,0 +1,19 @@ +import { Module } from '@nestjs/common'; +import { MikroOrmModule } from '@mikro-orm/nestjs'; +import { Icon } from './entities/icon.entity'; +import { Group } from './entities/group.entity'; +import { IconService } from './providers/icon.service'; +import { GroupService } from './providers/group.service'; +import { IconRepository } from './repositories/icon.repository'; +import { GroupRepository } from './repositories/group.repository'; +import { IconsController } from './controllers/icons.controller'; +import { JwtModule } from '@nestjs/jwt'; +import { UploaderModule } from '../uploader/uploader.module'; + +@Module({ + imports: [MikroOrmModule.forFeature([Icon, Group]), JwtModule, UploaderModule], + controllers: [IconsController], + providers: [IconService, GroupService, IconRepository, GroupRepository], + exports: [IconRepository, GroupRepository, IconService, GroupService], +}) +export class IconsModule {} diff --git a/src/modules/icons/providers/group.service.ts b/src/modules/icons/providers/group.service.ts new file mode 100644 index 0000000..625bfb4 --- /dev/null +++ b/src/modules/icons/providers/group.service.ts @@ -0,0 +1,56 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { CreateGroupDto } from '../dto/create-group.dto'; +import { UpdateGroupDto } from '../dto/update-group.dto'; +import { GroupRepository } from '../repositories/group.repository'; +import { EntityManager } from '@mikro-orm/postgresql'; +import { RequiredEntityData } from '@mikro-orm/core'; +import { Group } from '../entities/group.entity'; +import { GroupMessage } from 'src/common/enums/message.enum'; + +@Injectable() +export class GroupService { + constructor( + private readonly groupRepository: GroupRepository, + private readonly em: EntityManager, + ) {} + + async create(dto: CreateGroupDto): Promise { + const data: RequiredEntityData = { + name: dto.name, + }; + + const group = this.groupRepository.create(data); + await this.em.persistAndFlush(group); + return group; + } + + async findOne(id: string): Promise { + const group = await this.groupRepository.findOne({ id }, { populate: ['icons'] }); + if (!group) { + throw new NotFoundException(GroupMessage.NOT_FOUND); + } + return group; + } + + async update(id: string, dto: UpdateGroupDto): Promise { + const group = await this.groupRepository.findOne({ id }); + if (!group) { + throw new NotFoundException(GroupMessage.NOT_FOUND); + } + this.em.assign(group, dto); + await this.em.persistAndFlush(group); + return group; + } + + async remove(id: string): Promise { + const group = await this.groupRepository.findOne({ id }, { populate: ['icons'] }); + if (!group) { + throw new NotFoundException(GroupMessage.NOT_FOUND); + } + await this.em.removeAndFlush(group); + } + + findAllGroups(): Promise { + return this.groupRepository.find({}, { populate: ['icons'] }); + } +} diff --git a/src/modules/icons/providers/icon.service.ts b/src/modules/icons/providers/icon.service.ts new file mode 100644 index 0000000..40e2e79 --- /dev/null +++ b/src/modules/icons/providers/icon.service.ts @@ -0,0 +1,99 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { CreateIconDto } from '../dto/create-icon.dto'; +import { UpdateIconDto } from '../dto/update-icon.dto'; +import { IconRepository } from '../repositories/icon.repository'; +import { EntityManager } from '@mikro-orm/postgresql'; +import { RequiredEntityData } from '@mikro-orm/core'; +import { Icon } from '../entities/icon.entity'; +import { IconMessage, GroupMessage } from 'src/common/enums/message.enum'; +import { Group } from '../entities/group.entity'; +import { UploaderService } from 'src/modules/uploader/providers/uploader.service'; +import type { File } from '@nest-lab/fastify-multer'; + +@Injectable() +export class IconService { + constructor( + private readonly iconRepository: IconRepository, + private readonly em: EntityManager, + private readonly uploaderService: UploaderService, + ) {} + + async create(dto: CreateIconDto): Promise { + const group = await this.findGroupOrFail(dto.groupId); + + const data: RequiredEntityData = { + url: dto.url, + group: group, + }; + + const icon = this.iconRepository.create(data); + await this.em.persistAndFlush(icon); + return icon; + } + + async createBatch(groupId: string, files: File[]): Promise { + const group = await this.findGroupOrFail(groupId); + const uploadedFiles = await this.uploaderService.uploadMultiple(files); + + const icons = uploadedFiles.map(({ url }) => + this.iconRepository.create({ + url, + group, + }), + ); + + await this.em.persistAndFlush(icons); + return icons; + } + + async findAll(): Promise { + return this.iconRepository.find({}, { populate: ['group'] }); + } + + async findOne(id: string): Promise { + const icon = await this.iconRepository.findOne({ id }, { populate: ['group'] }); + if (!icon) { + throw new NotFoundException(IconMessage.NOT_FOUND); + } + return icon; + } + + async update(id: string, dto: UpdateIconDto): Promise { + const icon = await this.iconRepository.findOne({ id }); + if (!icon) { + throw new NotFoundException(IconMessage.NOT_FOUND); + } + + if (dto.groupId) { + const group = await this.em.findOne(Group, { id: dto.groupId }); + if (!group) { + throw new NotFoundException(GroupMessage.NOT_FOUND); + } + icon.group = group; + } + + this.em.assign(icon, { + url: dto.url, + }); + + await this.em.persistAndFlush(icon); + return icon; + } + + private async findGroupOrFail(groupId: string): Promise { + const group = await this.em.findOne(Group, { id: groupId }); + if (!group) { + throw new NotFoundException(GroupMessage.NOT_FOUND); + } + + return group; + } + + async remove(id: string): Promise { + const icon = await this.iconRepository.findOne({ id }); + if (!icon) { + throw new NotFoundException(IconMessage.NOT_FOUND); + } + await this.em.removeAndFlush(icon); + } +} diff --git a/src/modules/icons/repositories/group.repository.ts b/src/modules/icons/repositories/group.repository.ts new file mode 100644 index 0000000..fdc6749 --- /dev/null +++ b/src/modules/icons/repositories/group.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { Group } from '../entities/group.entity'; + +@Injectable() +export class GroupRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, Group); + } +} diff --git a/src/modules/icons/repositories/icon.repository.ts b/src/modules/icons/repositories/icon.repository.ts new file mode 100644 index 0000000..c748b94 --- /dev/null +++ b/src/modules/icons/repositories/icon.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { Icon } from '../entities/icon.entity'; + +@Injectable() +export class IconRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, Icon); + } +}