add: migration
This commit is contained in:
@@ -239,6 +239,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -441,6 +450,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -691,6 +709,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -919,6 +946,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -1148,6 +1184,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -1375,6 +1420,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -1556,6 +1610,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -1805,6 +1868,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -2033,6 +2105,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -2357,6 +2438,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -2566,6 +2656,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -2818,6 +2917,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -3077,6 +3185,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -3276,6 +3393,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -3710,6 +3836,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -4037,6 +4172,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -4279,6 +4423,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -4478,6 +4631,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -4842,6 +5004,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -5144,6 +5315,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -5385,6 +5565,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -5594,6 +5783,279 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chat_session_status": {
|
||||||
|
"name": "chat_session_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"active",
|
||||||
|
"closed",
|
||||||
|
"archived"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"message_type": {
|
||||||
|
"name": "message_type",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"user",
|
||||||
|
"bot",
|
||||||
|
"system"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"message_status": {
|
||||||
|
"name": "message_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"sent",
|
||||||
|
"delivered",
|
||||||
|
"read",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "uuid"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"length": 6,
|
||||||
|
"default": "current_timestamp",
|
||||||
|
"mappedType": "datetime"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"length": 6,
|
||||||
|
"default": "current_timestamp",
|
||||||
|
"mappedType": "datetime"
|
||||||
|
},
|
||||||
|
"deleted_at": {
|
||||||
|
"name": "deleted_at",
|
||||||
|
"type": "timestamptz",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"length": 6,
|
||||||
|
"mappedType": "datetime"
|
||||||
|
},
|
||||||
|
"reject_reason": {
|
||||||
|
"name": "reject_reason",
|
||||||
|
"type": "text",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "text"
|
||||||
|
},
|
||||||
|
"request_status": {
|
||||||
|
"name": "request_status",
|
||||||
|
"type": "company_request_status",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"nativeEnumName": "company_request_status",
|
||||||
|
"default": "'PENDING'",
|
||||||
|
"enumItems": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
],
|
||||||
|
"mappedType": "enum"
|
||||||
|
},
|
||||||
|
"company_id": {
|
||||||
|
"name": "company_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "uuid"
|
||||||
|
},
|
||||||
|
"business_id": {
|
||||||
|
"name": "business_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "uuid"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "company_request",
|
||||||
|
"schema": "public",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"keyName": "company_request_pkey",
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"composite": false,
|
||||||
|
"constraint": true,
|
||||||
|
"primary": true,
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checks": [],
|
||||||
|
"foreignKeys": {
|
||||||
|
"company_request_company_id_foreign": {
|
||||||
|
"constraintName": "company_request_company_id_foreign",
|
||||||
|
"columnNames": [
|
||||||
|
"company_id"
|
||||||
|
],
|
||||||
|
"localTableName": "public.company_request",
|
||||||
|
"referencedColumnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"referencedTableName": "public.company",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
},
|
||||||
|
"company_request_business_id_foreign": {
|
||||||
|
"constraintName": "company_request_business_id_foreign",
|
||||||
|
"columnNames": [
|
||||||
|
"business_id"
|
||||||
|
],
|
||||||
|
"localTableName": "public.company_request",
|
||||||
|
"referencedColumnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"referencedTableName": "public.business",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
},
|
||||||
|
"company_request_user_id_foreign": {
|
||||||
|
"constraintName": "company_request_user_id_foreign",
|
||||||
|
"columnNames": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"localTableName": "public.company_request",
|
||||||
|
"referencedColumnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"referencedTableName": "public.user",
|
||||||
|
"updateRule": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nativeEnums": {
|
||||||
|
"role_enum": {
|
||||||
|
"name": "role_enum",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"ADMIN",
|
||||||
|
"USER"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notif_type": {
|
||||||
|
"name": "notif_type",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"OTP",
|
||||||
|
"USER_LOGIN",
|
||||||
|
"ANNOUNCEMENT",
|
||||||
|
"WALLET_CHARGE",
|
||||||
|
"WALLET_DEDUCTION",
|
||||||
|
"BILL_INVOICE_REMINDER",
|
||||||
|
"BILL_INVOICE",
|
||||||
|
"APPROVE_INVOICE",
|
||||||
|
"CREATE_INVOICE",
|
||||||
|
"INVOICE_OVERDUE",
|
||||||
|
"CREATE_SERVICE",
|
||||||
|
"UNBLOCK_SERVICE",
|
||||||
|
"BLOCK_SERVICE",
|
||||||
|
"ANSWER_TICKET",
|
||||||
|
"CREATE_TICKET",
|
||||||
|
"ASSIGN_TICKET",
|
||||||
|
"RECURRING_INVOICE",
|
||||||
|
"PAYMENT_REMINDER",
|
||||||
|
"PAYMENT_CANCELLATION",
|
||||||
|
"NEW_CUSTOMER",
|
||||||
|
"NEW_TICKET",
|
||||||
|
"NEW_CRITICISM"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"company_status": {
|
||||||
|
"name": "company_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"APPROVED",
|
||||||
|
"PENDING",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ticket_status": {
|
||||||
|
"name": "ticket_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"ANSWERED",
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ticket_priority": {
|
||||||
|
"name": "ticket_priority",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"LOW",
|
||||||
|
"MEDIUM",
|
||||||
|
"HIGH"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"invoice_status": {
|
||||||
|
"name": "invoice_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"DRAFT",
|
||||||
|
"PENDING",
|
||||||
|
"WAIT_PAYMENT",
|
||||||
|
"PAID",
|
||||||
|
"ARCHIVED",
|
||||||
|
"OVERDUE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -5803,6 +6265,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -6036,6 +6507,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -6316,6 +6796,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -6537,6 +7026,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
@@ -6644,6 +7142,15 @@
|
|||||||
"OVERDUE"
|
"OVERDUE"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"company_request_status": {
|
||||||
|
"name": "company_request_status",
|
||||||
|
"schema": "public",
|
||||||
|
"items": [
|
||||||
|
"PENDING",
|
||||||
|
"APPROVED",
|
||||||
|
"REJECTED"
|
||||||
|
]
|
||||||
|
},
|
||||||
"chat_session_status": {
|
"chat_session_status": {
|
||||||
"name": "chat_session_status",
|
"name": "chat_session_status",
|
||||||
"schema": "public",
|
"schema": "public",
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import { Migration } from '@mikro-orm/migrations';
|
|
||||||
|
|
||||||
export class Migration20260217121029_meterageREquired extends Migration {
|
|
||||||
|
|
||||||
override async up(): Promise<void> {
|
|
||||||
this.addSql(`select 1`);
|
|
||||||
}
|
|
||||||
|
|
||||||
override async down(): Promise<void> {
|
|
||||||
this.addSql(`select 1`);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Migration } from "@mikro-orm/migrations";
|
||||||
|
|
||||||
|
export class Migration20260217122512_meterageREquired extends Migration {
|
||||||
|
override async up(): Promise<void> {
|
||||||
|
this.addSql(`alter table "company" alter column "metrage" type int using ("metrage"::int);`);
|
||||||
|
this.addSql(`update "company" set "metrage" = 0 where "metrage" is null;`);
|
||||||
|
this.addSql(`alter table "company" alter column "metrage" set not null;`);
|
||||||
|
|
||||||
|
this.addSql(`alter table "invoice" alter column "total_price" type numeric using ("total_price"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "original_price" type numeric using ("original_price"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "tax" type numeric using ("tax"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "late_fee" type numeric using ("late_fee"::numeric);`);
|
||||||
|
|
||||||
|
this.addSql(`alter table "payment" alter column "amount" type numeric using ("amount"::numeric);`);
|
||||||
|
}
|
||||||
|
|
||||||
|
override async down(): Promise<void> {
|
||||||
|
this.addSql(`alter table "company" alter column "metrage" type int4 using ("metrage"::int4);`);
|
||||||
|
this.addSql(`alter table "company" alter column "metrage" drop not null;`);
|
||||||
|
|
||||||
|
this.addSql(`alter table "invoice" alter column "total_price" type numeric using ("total_price"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "original_price" type numeric using ("original_price"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "tax" type numeric using ("tax"::numeric);`);
|
||||||
|
this.addSql(`alter table "invoice" alter column "late_fee" type numeric using ("late_fee"::numeric);`);
|
||||||
|
|
||||||
|
this.addSql(`alter table "payment" alter column "amount" type numeric using ("amount"::numeric);`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Options } from "@mikro-orm/core";
|
import { Options } from "@mikro-orm/core";
|
||||||
|
import { Migrator } from "@mikro-orm/migrations";
|
||||||
import { PostgreSqlDriver } from "@mikro-orm/postgresql";
|
import { PostgreSqlDriver } from "@mikro-orm/postgresql";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ dotenv.config();
|
|||||||
|
|
||||||
const config: Options = {
|
const config: Options = {
|
||||||
driver: PostgreSqlDriver,
|
driver: PostgreSqlDriver,
|
||||||
|
extensions: [Migrator],
|
||||||
dbName: process.env.DB_NAME,
|
dbName: process.env.DB_NAME,
|
||||||
host: process.env.DB_HOST,
|
host: process.env.DB_HOST,
|
||||||
port: Number(process.env.DB_PORT),
|
port: Number(process.env.DB_PORT),
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Test companies seed (production-safe)
|
||||||
|
|
||||||
|
Add about **1000 test companies** for a specific business, then remove them in one go.
|
||||||
|
|
||||||
|
- **Business ID:** `e5e760b9-46a5-4194-bb3d-00a46c24d72a`
|
||||||
|
- All test rows use the prefix **`TEST_SEED_`** (company name, emails, etc.) so they are easy to identify and delete without touching real data.
|
||||||
|
|
||||||
|
## 1. Seed test companies
|
||||||
|
|
||||||
|
From project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run build
|
||||||
|
pnpm run seed:test-companies
|
||||||
|
```
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- Business `e5e760b9-46a5-4194-bb3d-00a46c24d72a` must exist.
|
||||||
|
- At least one **Industry** must exist for that business (create one in the app if needed).
|
||||||
|
- **Role** `USER` must exist (run `pnpm run seed:run` once if you haven’t).
|
||||||
|
|
||||||
|
## 2. After testing: remove test data
|
||||||
|
|
||||||
|
Same DB, same business:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run seed:cleanup-test-companies
|
||||||
|
```
|
||||||
|
|
||||||
|
This **soft-deletes** all companies whose name starts with `TEST_SEED_` and their linked users for that business. No schema changes, no hard deletes.
|
||||||
|
|
||||||
|
## Changing business ID or count
|
||||||
|
|
||||||
|
Edit the constants at the top of:
|
||||||
|
|
||||||
|
- `database/seeders/test-companies.seeder.ts` — `TEST_BUSINESS_ID`, `TEST_COMPANIES_COUNT`
|
||||||
|
- `database/seeders/cleanup-test-companies.seeder.ts` — `TEST_BUSINESS_ID` (must match).
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { EntityManager } from "@mikro-orm/postgresql";
|
||||||
|
import { Seeder } from "@mikro-orm/seeder";
|
||||||
|
import { Logger } from "@nestjs/common";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
import { TEST_SEED_PREFIX } from "./test-companies.seeder";
|
||||||
|
import { Company } from "../../src/modules/companies/entities/company.entity";
|
||||||
|
|
||||||
|
/** Must match the business ID used in TestCompaniesSeeder. */
|
||||||
|
const TEST_BUSINESS_ID = "e5e760b9-46a5-4194-bb3d-00a46c24d72a";
|
||||||
|
|
||||||
|
export class CleanupTestCompaniesSeeder extends Seeder {
|
||||||
|
private readonly logger = new Logger(CleanupTestCompaniesSeeder.name);
|
||||||
|
|
||||||
|
async run(em: EntityManager): Promise<void> {
|
||||||
|
this.logger.log(`Cleaning up test companies (name like '${TEST_SEED_PREFIX}%') for business ${TEST_BUSINESS_ID}...`);
|
||||||
|
|
||||||
|
const companies = await em.find(
|
||||||
|
Company,
|
||||||
|
{
|
||||||
|
name: { $like: `${TEST_SEED_PREFIX}%` },
|
||||||
|
business: { id: TEST_BUSINESS_ID },
|
||||||
|
deletedAt: null,
|
||||||
|
},
|
||||||
|
{ populate: ["user"] },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (companies.length === 0) {
|
||||||
|
this.logger.log("No test companies found. Nothing to delete.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = dayjs().toDate();
|
||||||
|
for (const company of companies) {
|
||||||
|
company.deletedAt = now;
|
||||||
|
if (company.user?.deletedAt == null) {
|
||||||
|
company.user.deletedAt = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await em.flush();
|
||||||
|
this.logger.log(`Soft-deleted ${companies.length} test companies and their users.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import { EntityManager } from "@mikro-orm/postgresql";
|
||||||
|
import { Seeder } from "@mikro-orm/seeder";
|
||||||
|
import { Logger } from "@nestjs/common";
|
||||||
|
import { genSalt, hash } from "bcrypt";
|
||||||
|
|
||||||
|
import { Business } from "../../src/modules/businesses/entities/business.entity";
|
||||||
|
import { CompanyProduct } from "../../src/modules/companies/entities/company-product.entity";
|
||||||
|
import { CompanyService } from "../../src/modules/companies/entities/company-service.entity";
|
||||||
|
import { Company } from "../../src/modules/companies/entities/company.entity";
|
||||||
|
import { CompanyStatus } from "../../src/modules/companies/enums/company-status.enum";
|
||||||
|
import { Industry } from "../../src/modules/industries/entities/industry.entity";
|
||||||
|
import { Role } from "../../src/modules/users/entities/role.entity";
|
||||||
|
import { User } from "../../src/modules/users/entities/user.entity";
|
||||||
|
import { RoleEnum } from "../../src/modules/users/enums/role.enum";
|
||||||
|
|
||||||
|
/** Business ID to seed test companies for. Change or use env if needed. */
|
||||||
|
const TEST_BUSINESS_ID = "e5e760b9-46a5-4194-bb3d-00a46c24d72a";
|
||||||
|
|
||||||
|
/** All test companies/users use this prefix so they can be safely deleted later. */
|
||||||
|
export const TEST_SEED_PREFIX = "TEST_SEED_";
|
||||||
|
|
||||||
|
const TEST_COMPANIES_COUNT = 1000;
|
||||||
|
const BATCH_SIZE = 50;
|
||||||
|
const TEST_PASSWORD = "TestPassword1!";
|
||||||
|
|
||||||
|
export class TestCompaniesSeeder extends Seeder {
|
||||||
|
private readonly logger = new Logger(TestCompaniesSeeder.name);
|
||||||
|
|
||||||
|
async run(em: EntityManager): Promise<void> {
|
||||||
|
const business = await em.findOne(Business, { id: TEST_BUSINESS_ID, deletedAt: null });
|
||||||
|
if (!business) {
|
||||||
|
this.logger.error(`Business not found: ${TEST_BUSINESS_ID}. Aborting.`);
|
||||||
|
throw new Error(`Business not found: ${TEST_BUSINESS_ID}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const industry = await em.findOne(Industry, { business: { id: TEST_BUSINESS_ID }, deletedAt: null });
|
||||||
|
if (!industry) {
|
||||||
|
this.logger.error(`No industry found for business ${TEST_BUSINESS_ID}. Create an industry first.`);
|
||||||
|
throw new Error("No industry found for business");
|
||||||
|
}
|
||||||
|
|
||||||
|
const role = await em.findOne(Role, { name: RoleEnum.USER });
|
||||||
|
if (!role) {
|
||||||
|
this.logger.error("USER role not found. Run default seed first (RoleSeeder).");
|
||||||
|
throw new Error("USER role not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashedPassword = await hash(TEST_PASSWORD, await genSalt(10));
|
||||||
|
const baseDate = "2020-01-01";
|
||||||
|
const baseUrl = "https://example.com";
|
||||||
|
|
||||||
|
this.logger.log(`Seeding ${TEST_COMPANIES_COUNT} test companies for business ${TEST_BUSINESS_ID}...`);
|
||||||
|
|
||||||
|
for (let i = 1; i <= TEST_COMPANIES_COUNT; i++) {
|
||||||
|
const pad4 = String(i).padStart(4, "0");
|
||||||
|
const pad5 = String(i).padStart(5, "0");
|
||||||
|
const pad7 = String(i).padStart(7, "0");
|
||||||
|
const phone = `0912${pad7}`;
|
||||||
|
const email = `test.seed.${i}@test.local`;
|
||||||
|
const nationalCode = `0000${pad5}`;
|
||||||
|
const userName = `testseed${i}`;
|
||||||
|
|
||||||
|
const user = em.create(User, {
|
||||||
|
firstName: "Test",
|
||||||
|
lastName: `User${i}`,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
userName,
|
||||||
|
nationalCode,
|
||||||
|
password: hashedPassword,
|
||||||
|
role,
|
||||||
|
business,
|
||||||
|
});
|
||||||
|
await em.persist(user);
|
||||||
|
|
||||||
|
const company = em.create(Company, {
|
||||||
|
name: `${TEST_SEED_PREFIX}Company_${pad4}`,
|
||||||
|
chiefExecutiveOfficer: `Test CEO ${i}`,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
identificationNumber: `TESTSEEDID${pad5}`,
|
||||||
|
dateOfEstablishment: new Date(baseDate),
|
||||||
|
address: `${TEST_SEED_PREFIX} Address ${i}`,
|
||||||
|
mapAddressLink: `${baseUrl}/map`,
|
||||||
|
description: `${TEST_SEED_PREFIX} Description ${i}`,
|
||||||
|
websiteUrl: `${baseUrl}`,
|
||||||
|
profileImageUrl: `${baseUrl}/profile.png`,
|
||||||
|
coverImageUrl: `${baseUrl}/cover.png`,
|
||||||
|
metrage: 100,
|
||||||
|
isActive: true,
|
||||||
|
status: CompanyStatus.APPROVED,
|
||||||
|
industry,
|
||||||
|
business,
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
const product = em.create(CompanyProduct, {
|
||||||
|
title: `${TEST_SEED_PREFIX}Product_${i}`,
|
||||||
|
imageUrl: `${baseUrl}/product.png`,
|
||||||
|
company,
|
||||||
|
});
|
||||||
|
const service = em.create(CompanyService, {
|
||||||
|
title: `${TEST_SEED_PREFIX}Service_${i}`,
|
||||||
|
imageUrl: `${baseUrl}/service.png`,
|
||||||
|
company,
|
||||||
|
});
|
||||||
|
company.products.add(product);
|
||||||
|
company.services.add(service);
|
||||||
|
await em.persist(company);
|
||||||
|
|
||||||
|
if (i % BATCH_SIZE === 0) {
|
||||||
|
await em.flush();
|
||||||
|
this.logger.log(` ... ${i}/${TEST_COMPANIES_COUNT}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await em.flush();
|
||||||
|
this.logger.log(`Done. Created ${TEST_COMPANIES_COUNT} test companies (name like '${TEST_SEED_PREFIX}%').`);
|
||||||
|
this.logger.warn(`To remove them later, run: pnpm run seed:cleanup-test-companies`);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
"orm:create": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
"orm:create": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
||||||
"orm:up": "mikro-orm migration:up --config=database/mikro-orm.config.ts",
|
"orm:up": "mikro-orm migration:up --config=database/mikro-orm.config.ts",
|
||||||
"orm:down": "mikro-orm migration:down --config=database/mikro-orm.config.ts",
|
"orm:down": "mikro-orm migration:down --config=database/mikro-orm.config.ts",
|
||||||
"orm:generate": "mikro-orm migration:create --blank --config=database/mikro-orm.config.ts",
|
"orm:generate": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
||||||
"orm:update": "mikro-orm schema:update --run --config=database/mikro-orm.config.ts",
|
"orm:update": "mikro-orm schema:update --run --config=database/mikro-orm.config.ts",
|
||||||
"orm:drop": "mikro-orm schema:drop --run --drop-migrations-table --drop-db --config=database/mikro-orm.config.ts",
|
"orm:drop": "mikro-orm schema:drop --run --drop-migrations-table --drop-db --config=database/mikro-orm.config.ts",
|
||||||
"orm:seed": "mikro-orm seeder:create --config=database/mikro-orm.config.ts",
|
"orm:seed": "mikro-orm seeder:create --config=database/mikro-orm.config.ts",
|
||||||
|
|||||||
@@ -32,11 +32,7 @@ export class BillsController {
|
|||||||
@UseInterceptors(FileInterceptor("file"))
|
@UseInterceptors(FileInterceptor("file"))
|
||||||
@ApiBody({ type: CreateWaterBillFromExcelDto })
|
@ApiBody({ type: CreateWaterBillFromExcelDto })
|
||||||
@Post("water/excel")
|
@Post("water/excel")
|
||||||
createWaterBillByExcel(
|
createWaterBillByExcel(@UploadedFile() file: IFile, @Body() dto: CreateWaterBillFromExcelDto, @BusinessDec() business: Business) {
|
||||||
@UploadedFile() file: IFile,
|
|
||||||
@Body() dto: CreateWaterBillFromExcelDto,
|
|
||||||
@BusinessDec() business: Business,
|
|
||||||
) {
|
|
||||||
return this.billsService.createWaterBillByExcel(file, dto, business);
|
return this.billsService.createWaterBillByExcel(file, dto, business);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||||
|
import { BullModule } from "@nestjs/bullmq";
|
||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
|
||||||
import { BillsController } from "./bills.controller";
|
import { BillsController } from "./bills.controller";
|
||||||
@@ -6,17 +7,20 @@ import { BillsService } from "./bills.service";
|
|||||||
import { Bill } from "./entities/bill.entity";
|
import { Bill } from "./entities/bill.entity";
|
||||||
import { BusinessesModule } from "../businesses/businesses.module";
|
import { BusinessesModule } from "../businesses/businesses.module";
|
||||||
import { CompaniesModule } from "../companies/companies.module";
|
import { CompaniesModule } from "../companies/companies.module";
|
||||||
import { NotificationModule } from "../notifications/notifications.module";
|
|
||||||
import { InvoicesModule } from "../invoices/invoices.module";
|
|
||||||
import { BullModule } from "@nestjs/bullmq";
|
|
||||||
import { INVOICE } from "../invoices/constants";
|
import { INVOICE } from "../invoices/constants";
|
||||||
|
import { InvoicesModule } from "../invoices/invoices.module";
|
||||||
|
import { NotificationModule } from "../notifications/notifications.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
BullModule.registerQueue({ name: INVOICE.QUEUE_NAME }),
|
BullModule.registerQueue({ name: INVOICE.QUEUE_NAME }),
|
||||||
MikroOrmModule.forFeature([Bill]), CompaniesModule, BusinessesModule
|
MikroOrmModule.forFeature([Bill]),
|
||||||
, NotificationModule, InvoicesModule],
|
CompaniesModule,
|
||||||
|
BusinessesModule,
|
||||||
|
NotificationModule,
|
||||||
|
InvoicesModule,
|
||||||
|
],
|
||||||
controllers: [BillsController],
|
controllers: [BillsController],
|
||||||
providers: [BillsService],
|
providers: [BillsService],
|
||||||
})
|
})
|
||||||
export class BillsModule { }
|
export class BillsModule {}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { EntityManager } from "@mikro-orm/postgresql";
|
import { EntityManager } from "@mikro-orm/postgresql";
|
||||||
|
import { InjectQueue } from "@nestjs/bullmq";
|
||||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||||
|
import { Queue } from "bullmq";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import { Workbook } from "exceljs";
|
import { Workbook } from "exceljs";
|
||||||
|
|
||||||
import { IFile } from "../utils/interfaces/IFile";
|
|
||||||
|
|
||||||
import { BillListQueryDto } from "./dto/bill-list-query.dto";
|
import { BillListQueryDto } from "./dto/bill-list-query.dto";
|
||||||
import { CreateChargeBillDto } from "./dto/create-charge-bill.dto";
|
import { CreateChargeBillDto } from "./dto/create-charge-bill.dto";
|
||||||
import { CreateWaterBillDto, CreateWaterBillFromExcelDto } from "./dto/create-water-bill.dto";
|
import { CreateWaterBillDto, CreateWaterBillFromExcelDto } from "./dto/create-water-bill.dto";
|
||||||
@@ -16,13 +16,11 @@ import { CompanyMessage } from "../../common/enums/message.enum";
|
|||||||
import { Business } from "../businesses/entities/business.entity";
|
import { Business } from "../businesses/entities/business.entity";
|
||||||
import { Company } from "../companies/entities/company.entity";
|
import { Company } from "../companies/entities/company.entity";
|
||||||
import { CompaniesService } from "../companies/services/companies.service";
|
import { CompaniesService } from "../companies/services/companies.service";
|
||||||
|
import { INVOICE } from "../invoices/constants";
|
||||||
import { InvoiceItem } from "../invoices/entities/invoice-item.entity";
|
import { InvoiceItem } from "../invoices/entities/invoice-item.entity";
|
||||||
import { Invoice } from "../invoices/entities/invoice.entity";
|
import { Invoice } from "../invoices/entities/invoice.entity";
|
||||||
import { NotificationQueue } from "../notifications/queue/notification.queue";
|
import { NotificationQueue } from "../notifications/queue/notification.queue";
|
||||||
import { InjectQueue } from "@nestjs/bullmq";
|
import { IFile } from "../utils/interfaces/IFile";
|
||||||
import { INVOICE } from "../invoices/constants";
|
|
||||||
import { Queue } from "bullmq";
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BillsService {
|
export class BillsService {
|
||||||
@@ -33,8 +31,7 @@ export class BillsService {
|
|||||||
@InjectQueue(INVOICE.QUEUE_NAME)
|
@InjectQueue(INVOICE.QUEUE_NAME)
|
||||||
private readonly invoiceQueue: Queue,
|
private readonly invoiceQueue: Queue,
|
||||||
private readonly notificationQueue: NotificationQueue,
|
private readonly notificationQueue: NotificationQueue,
|
||||||
|
) {}
|
||||||
) { }
|
|
||||||
|
|
||||||
async createWaterBill(dto: CreateWaterBillDto, business: Business) {
|
async createWaterBill(dto: CreateWaterBillDto, business: Business) {
|
||||||
const { values, waterRate, dueDays } = dto;
|
const { values, waterRate, dueDays } = dto;
|
||||||
@@ -95,8 +92,8 @@ export class BillsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addInvoiceReminderJobs(billId: string) {
|
private async addInvoiceReminderJobs(billId: string) {
|
||||||
const invoices = await this.em.find(Invoice, { bill: { id: billId } }, { populate: ["items", "company","company.user"] });
|
const invoices = await this.em.find(Invoice, { bill: { id: billId } }, { populate: ["items", "company", "company.user"] });
|
||||||
|
|
||||||
for (const invoice of invoices) {
|
for (const invoice of invoices) {
|
||||||
await this.notificationQueue.addInvoiceCreationNotification(invoice.company.user.id, {
|
await this.notificationQueue.addInvoiceCreationNotification(invoice.company.user.id, {
|
||||||
@@ -196,7 +193,7 @@ export class BillsService {
|
|||||||
await em.flush();
|
await em.flush();
|
||||||
await em.commit();
|
await em.commit();
|
||||||
|
|
||||||
await this.addInvoiceReminderJobs(bill.id)
|
await this.addInvoiceReminderJobs(bill.id);
|
||||||
|
|
||||||
return bill;
|
return bill;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -223,10 +220,7 @@ export class BillsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async remove(id: string, businessId: string) {
|
async remove(id: string, businessId: string) {
|
||||||
const bill = await this.billRepository.findOne(
|
const bill = await this.billRepository.findOne({ id, business: { id: businessId } }, { populate: ["invoices"] });
|
||||||
{ id, business: { id: businessId } },
|
|
||||||
{ populate: ["invoices"] },
|
|
||||||
);
|
|
||||||
if (!bill) {
|
if (!bill) {
|
||||||
throw new BadRequestException("Bill not found");
|
throw new BadRequestException("Bill not found");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,5 @@ export class Bill extends BaseEntity {
|
|||||||
@Property({ persist: false })
|
@Property({ persist: false })
|
||||||
invoiceCount?: number;
|
invoiceCount?: number;
|
||||||
|
|
||||||
|
|
||||||
[EntityRepositoryType]?: BillsRepository;
|
[EntityRepositoryType]?: BillsRepository;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,65 +5,62 @@ import { BillListQueryDto } from "../dto/bill-list-query.dto";
|
|||||||
import { Bill } from "../entities/bill.entity";
|
import { Bill } from "../entities/bill.entity";
|
||||||
|
|
||||||
export class BillsRepository extends EntityRepository<Bill> {
|
export class BillsRepository extends EntityRepository<Bill> {
|
||||||
|
|
||||||
async getBillsList(queryDto: BillListQueryDto, businessId: string) {
|
async getBillsList(queryDto: BillListQueryDto, businessId: string) {
|
||||||
const { limit, skip } = PaginationUtils(queryDto);
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
|
|
||||||
const knex = this.em.getKnex();
|
const knex = this.em.getKnex();
|
||||||
const query = knex
|
const query = knex
|
||||||
.select('b.*')
|
.select("b.*")
|
||||||
.select(knex.raw('COUNT(i.id) as invoice_count'))
|
.select(knex.raw("COUNT(i.id) as invoice_count"))
|
||||||
.from('bill as b')
|
.from("bill as b")
|
||||||
.leftJoin('invoice as i', 'i.bill_id', 'b.id')
|
.leftJoin("invoice as i", "i.bill_id", "b.id")
|
||||||
.where('b.business_id', businessId)
|
.where("b.business_id", businessId)
|
||||||
.groupBy('b.id')
|
.groupBy("b.id")
|
||||||
.orderBy('b.created_at', 'desc')
|
.orderBy("b.created_at", "desc")
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(skip);
|
.offset(skip);
|
||||||
|
|
||||||
// Add filters
|
// Add filters
|
||||||
if (queryDto.type) {
|
if (queryDto.type) {
|
||||||
query.andWhere('b.type', queryDto.type);
|
query.andWhere("b.type", queryDto.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryDto.since) {
|
if (queryDto.since) {
|
||||||
query.andWhere('b.created_at', '>=', new Date(queryDto.since));
|
query.andWhere("b.created_at", ">=", new Date(queryDto.since));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryDto.to) {
|
if (queryDto.to) {
|
||||||
query.andWhere('b.created_at', '<=', new Date(queryDto.to));
|
query.andWhere("b.created_at", "<=", new Date(queryDto.to));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
const results = await query;
|
const results = await query;
|
||||||
|
|
||||||
// Get total count for pagination
|
// Get total count for pagination
|
||||||
const countQuery = knex('bill')
|
const countQuery = knex("bill").count("* as total").where("business_id", businessId);
|
||||||
.count('* as total')
|
|
||||||
.where('business_id', businessId);
|
|
||||||
|
|
||||||
if (queryDto.type) {
|
if (queryDto.type) {
|
||||||
countQuery.andWhere('type', queryDto.type);
|
countQuery.andWhere("type", queryDto.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryDto.since) {
|
if (queryDto.since) {
|
||||||
countQuery.andWhere('created_at', '>=', new Date(queryDto.since));
|
countQuery.andWhere("created_at", ">=", new Date(queryDto.since));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryDto.to) {
|
if (queryDto.to) {
|
||||||
countQuery.andWhere('created_at', '<=', new Date(queryDto.to));
|
countQuery.andWhere("created_at", "<=", new Date(queryDto.to));
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalResult = await countQuery;
|
const totalResult = await countQuery;
|
||||||
const total = Number(totalResult[0].total);
|
const total = Number(totalResult[0].total);
|
||||||
|
|
||||||
// Map results back to Bill entities (invoice_count from knex may be string/bigint)
|
// Map results back to Bill entities (invoice_count from knex may be string/bigint)
|
||||||
const bills = results.map((row) => {
|
const bills = results.map((row) => {
|
||||||
const bill = this.em.map(Bill, row);
|
const bill = this.em.map(Bill, row);
|
||||||
bill.invoiceCount = Number(row.invoice_count ?? 0);
|
bill.invoiceCount = Number(row.invoice_count ?? 0);
|
||||||
return bill;
|
return bill;
|
||||||
});
|
});
|
||||||
|
|
||||||
return [bills, total];
|
return [bills, total];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export class CreateCompanyRequestDto extends PickType(CreateCompanyDto, [
|
|||||||
"industryId",
|
"industryId",
|
||||||
"products",
|
"products",
|
||||||
"services",
|
"services",
|
||||||
"metrage"
|
"metrage",
|
||||||
]) {
|
]) {
|
||||||
@IsNotEmpty({ message: CompanyMessage.CHIEF_EXECUTIVE_REQUIRED })
|
@IsNotEmpty({ message: CompanyMessage.CHIEF_EXECUTIVE_REQUIRED })
|
||||||
@IsString({ message: CompanyMessage.CHIEF_EXECUTIVE_MUST_BE_STRING })
|
@IsString({ message: CompanyMessage.CHIEF_EXECUTIVE_MUST_BE_STRING })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Module } from "@nestjs/common";
|
|||||||
|
|
||||||
import { CompaniesController } from "./companies.controller";
|
import { CompaniesController } from "./companies.controller";
|
||||||
import { CompanyProduct } from "./entities/company-product.entity";
|
import { CompanyProduct } from "./entities/company-product.entity";
|
||||||
import { CompanyRequest } from "./entities/company-request.enitiy";
|
import { CompanyRequest } from "./entities/company-request.entity";
|
||||||
import { CompanyService } from "./entities/company-service.entity";
|
import { CompanyService } from "./entities/company-service.entity";
|
||||||
import { Company } from "./entities/company.entity";
|
import { Company } from "./entities/company.entity";
|
||||||
import { CompaniesService } from "./services/companies.service";
|
import { CompaniesService } from "./services/companies.service";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||||
|
|
||||||
import { CompanyRequest } from "../entities/company-request.enitiy";
|
import { CompanyRequest } from "../entities/company-request.entity";
|
||||||
|
|
||||||
export class CompanyRequestRepository extends EntityRepository<CompanyRequest> {}
|
export class CompanyRequestRepository extends EntityRepository<CompanyRequest> {}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { CompanyListPublicQueryDto, CompanyListQueryDto } from "../DTO/company-l
|
|||||||
import { ChangeCompanyRequestStatusDto, CreateCompanyDto, CreateCompanyRequestDto } from "../DTO/create-company.dto";
|
import { ChangeCompanyRequestStatusDto, CreateCompanyDto, CreateCompanyRequestDto } from "../DTO/create-company.dto";
|
||||||
import { UpdateCompanyDto, UpdateUserCompanyDto } from "../DTO/update-company.dto";
|
import { UpdateCompanyDto, UpdateUserCompanyDto } from "../DTO/update-company.dto";
|
||||||
import { CompanyProduct } from "../entities/company-product.entity";
|
import { CompanyProduct } from "../entities/company-product.entity";
|
||||||
import { CompanyRequest } from "../entities/company-request.enitiy";
|
import { CompanyRequest } from "../entities/company-request.entity";
|
||||||
import { CompanyService } from "../entities/company-service.entity";
|
import { CompanyService } from "../entities/company-service.entity";
|
||||||
import { Company } from "../entities/company.entity";
|
import { Company } from "../entities/company.entity";
|
||||||
import { CompanyRequestStatus } from "../enums/company-request-status.enum";
|
import { CompanyRequestStatus } from "../enums/company-request-status.enum";
|
||||||
|
|||||||
Reference in New Issue
Block a user