Integrate Notification Management into Tender Management System

- Added a new notification domain, including entities, services, handlers, and repositories to manage notifications effectively.
- Implemented CRUD operations for notifications, allowing for creation, retrieval, updating, and deletion of notifications via the API.
- Enhanced API documentation with Swagger comments for new notification endpoints, ensuring clarity for API consumers.
- Updated routes to include notification management, improving administrative capabilities within the web panel.
- Introduced validation for notification requests and responses, ensuring data integrity and proper error handling.
- Updated the go.mod file to include the latest version of the go-redis library, ensuring compatibility with the notification service.
This commit is contained in:
n.nakhostin
2025-09-17 16:01:49 +03:30
parent 6906577f6e
commit a06dc5097e
12 changed files with 2244 additions and 16 deletions
+576 -2
View File
@@ -1460,6 +1460,88 @@ const docTemplate = `{
}
}
},
"/admin/v1/customers/{id}/role": {
"patch": {
"security": [
{
"BearerAuth": []
}
],
"description": "Assign a role (admin or analyst) to a customer",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Customers"
],
"summary": "Assign role to customer",
"parameters": [
{
"type": "string",
"description": "Customer ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Role assignment information",
"name": "role",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/customer.AssignRoleForm"
}
}
],
"responses": {
"200": {
"description": "Role assigned successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/customer.AssignRoleResponse"
}
}
}
]
}
},
"400": {
"description": "Bad request - Invalid input data",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not found - Customer not found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"422": {
"description": "Validation error - Invalid request data",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/customers/{id}/status": {
"patch": {
"security": [
@@ -2304,6 +2386,325 @@ const docTemplate = `{
}
}
},
"/admin/v1/notifications": {
"get": {
"description": "Retrieve notifications for a specific user with filtering and pagination",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Get user notifications",
"parameters": [
{
"type": "string",
"description": "Recipient",
"name": "recipient",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Notification type (info, warning, alert, reject)",
"name": "type",
"in": "query"
},
{
"type": "string",
"description": "Notification priority (low, medium, important)",
"name": "priority",
"in": "query"
},
{
"type": "string",
"description": "Delivery status (pending, sent, failed)",
"name": "status",
"in": "query"
},
{
"type": "boolean",
"description": "Read status",
"name": "is_read",
"in": "query"
},
{
"type": "integer",
"default": 1,
"description": "Page number",
"name": "page",
"in": "query"
},
{
"type": "integer",
"default": 20,
"description": "Items per page",
"name": "limit",
"in": "query"
},
{
"type": "string",
"default": "created_at",
"description": "Sort field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"default": "desc",
"description": "Sort order (asc, desc)",
"name": "sort_order",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/notification.NotificationsResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"post": {
"description": "Create a new notification with the provided information",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Create a new notification",
"parameters": [
{
"description": "Notification information",
"name": "notification",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_notification.NotificationRequest"
}
}
],
"responses": {
"201": {
"description": "Notification created successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/notifications/{id}": {
"get": {
"description": "Retrieve a specific notification by its ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Get notification by ID",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/internal_notification.NotificationResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"put": {
"description": "Update an existing notification",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Update notification",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Updated notification information",
"name": "notification",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_notification.NotificationRequest"
}
}
],
"responses": {
"200": {
"description": "Notification updated successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"delete": {
"description": "Delete a specific notification",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Delete notification",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Notification deleted successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/profile": {
"get": {
"security": [
@@ -6497,6 +6898,28 @@ const docTemplate = `{
}
}
},
"customer.AssignRoleForm": {
"type": "object",
"properties": {
"role": {
"type": "string",
"example": "analyst"
}
}
},
"customer.AssignRoleResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Role assigned successfully"
},
"success": {
"type": "boolean",
"example": true
}
}
},
"customer.AuthResponse": {
"type": "object",
"properties": {
@@ -6550,6 +6973,10 @@ const docTemplate = `{
"type": "string",
"example": "+1234567890"
},
"role": {
"type": "string",
"example": "analyst"
},
"type": {
"type": "string",
"example": "individual"
@@ -6601,10 +7028,10 @@ const docTemplate = `{
"last_login_at": {
"type": "integer"
},
"password": {
"phone": {
"type": "string"
},
"phone": {
"role": {
"type": "string"
},
"status": {
@@ -6715,6 +7142,10 @@ const docTemplate = `{
"type": "string",
"example": "+1234567890"
},
"role": {
"type": "string",
"example": "analyst"
},
"type": {
"type": "string",
"example": "individual"
@@ -6974,6 +7405,145 @@ const docTemplate = `{
}
}
},
"internal_notification.NotificationRequest": {
"type": "object",
"properties": {
"channels": {
"type": "array",
"items": {
"$ref": "#/definitions/notification.DeliveryChannel"
}
},
"description": {
"type": "string"
},
"link": {
"type": "string"
},
"priority": {
"$ref": "#/definitions/notification.NotificationPriority"
},
"recipient": {
"type": "array",
"items": {
"type": "string"
}
},
"schedule": {
"$ref": "#/definitions/notification.ScheduleRequest"
},
"tender": {
"type": "string"
},
"title": {
"type": "string"
},
"type": {
"$ref": "#/definitions/notification.NotificationType"
}
}
},
"internal_notification.NotificationResponse": {
"type": "object",
"properties": {
"channels": {
"type": "array",
"items": {
"$ref": "#/definitions/notification.DeliveryChannel"
}
},
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"link": {
"type": "string"
},
"priority": {
"$ref": "#/definitions/notification.NotificationPriority"
},
"schedule": {
"$ref": "#/definitions/notification.ScheduleResponse"
},
"tender": {
"type": "string"
},
"title": {
"type": "string"
},
"type": {
"$ref": "#/definitions/notification.NotificationType"
}
}
},
"notification.DeliveryChannel": {
"type": "string",
"enum": [
"push",
"email"
],
"x-enum-varnames": [
"DeliveryChannelPush",
"DeliveryChannelEmail"
]
},
"notification.NotificationPriority": {
"type": "string",
"enum": [
"low",
"medium",
"important"
],
"x-enum-varnames": [
"NotificationPriorityLow",
"NotificationPriorityMedium",
"NotificationPriorityImportant"
]
},
"notification.NotificationType": {
"type": "string",
"enum": [
"info",
"warning",
"alert",
"reject"
],
"x-enum-varnames": [
"NotificationTypeInfo",
"NotificationTypeWarning",
"NotificationTypeAlert",
"NotificationTypeReject"
]
},
"notification.NotificationsResponse": {
"type": "object",
"properties": {
"notifications": {
"type": "array",
"items": {
"$ref": "#/definitions/internal_notification.NotificationResponse"
}
}
}
},
"notification.ScheduleRequest": {
"type": "object",
"properties": {
"time": {
"type": "integer"
}
}
},
"notification.ScheduleResponse": {
"type": "object",
"properties": {
"time": {
"type": "integer"
}
}
},
"response.APIError": {
"type": "object",
"properties": {
@@ -7675,6 +8245,10 @@ const docTemplate = `{
"description": "Administrative flag management operations for web panel including flag listing and retrieval",
"name": "Admin-Flags"
},
{
"description": "Administrative notification management operations for web panel including CRUD operations, bulk notifications, queue management, and comprehensive filtering with pagination",
"name": "Admin-Notification"
},
{
"description": "Customer authentication and authorization operations for mobile application including login, logout, token refresh, and profile access",
"name": "Authorization"
+576 -2
View File
@@ -1454,6 +1454,88 @@
}
}
},
"/admin/v1/customers/{id}/role": {
"patch": {
"security": [
{
"BearerAuth": []
}
],
"description": "Assign a role (admin or analyst) to a customer",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Customers"
],
"summary": "Assign role to customer",
"parameters": [
{
"type": "string",
"description": "Customer ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Role assignment information",
"name": "role",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/customer.AssignRoleForm"
}
}
],
"responses": {
"200": {
"description": "Role assigned successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/customer.AssignRoleResponse"
}
}
}
]
}
},
"400": {
"description": "Bad request - Invalid input data",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not found - Customer not found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"422": {
"description": "Validation error - Invalid request data",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/customers/{id}/status": {
"patch": {
"security": [
@@ -2298,6 +2380,325 @@
}
}
},
"/admin/v1/notifications": {
"get": {
"description": "Retrieve notifications for a specific user with filtering and pagination",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Get user notifications",
"parameters": [
{
"type": "string",
"description": "Recipient",
"name": "recipient",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Notification type (info, warning, alert, reject)",
"name": "type",
"in": "query"
},
{
"type": "string",
"description": "Notification priority (low, medium, important)",
"name": "priority",
"in": "query"
},
{
"type": "string",
"description": "Delivery status (pending, sent, failed)",
"name": "status",
"in": "query"
},
{
"type": "boolean",
"description": "Read status",
"name": "is_read",
"in": "query"
},
{
"type": "integer",
"default": 1,
"description": "Page number",
"name": "page",
"in": "query"
},
{
"type": "integer",
"default": 20,
"description": "Items per page",
"name": "limit",
"in": "query"
},
{
"type": "string",
"default": "created_at",
"description": "Sort field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"default": "desc",
"description": "Sort order (asc, desc)",
"name": "sort_order",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/notification.NotificationsResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"post": {
"description": "Create a new notification with the provided information",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Create a new notification",
"parameters": [
{
"description": "Notification information",
"name": "notification",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_notification.NotificationRequest"
}
}
],
"responses": {
"201": {
"description": "Notification created successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/notifications/{id}": {
"get": {
"description": "Retrieve a specific notification by its ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Get notification by ID",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/internal_notification.NotificationResponse"
}
}
}
]
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"put": {
"description": "Update an existing notification",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Update notification",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Updated notification information",
"name": "notification",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_notification.NotificationRequest"
}
}
],
"responses": {
"200": {
"description": "Notification updated successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
},
"delete": {
"description": "Delete a specific notification",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Notification"
],
"summary": "Delete notification",
"parameters": [
{
"type": "string",
"description": "Notification ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Notification deleted successfully",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/profile": {
"get": {
"security": [
@@ -6491,6 +6892,28 @@
}
}
},
"customer.AssignRoleForm": {
"type": "object",
"properties": {
"role": {
"type": "string",
"example": "analyst"
}
}
},
"customer.AssignRoleResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Role assigned successfully"
},
"success": {
"type": "boolean",
"example": true
}
}
},
"customer.AuthResponse": {
"type": "object",
"properties": {
@@ -6544,6 +6967,10 @@
"type": "string",
"example": "+1234567890"
},
"role": {
"type": "string",
"example": "analyst"
},
"type": {
"type": "string",
"example": "individual"
@@ -6595,10 +7022,10 @@
"last_login_at": {
"type": "integer"
},
"password": {
"phone": {
"type": "string"
},
"phone": {
"role": {
"type": "string"
},
"status": {
@@ -6709,6 +7136,10 @@
"type": "string",
"example": "+1234567890"
},
"role": {
"type": "string",
"example": "analyst"
},
"type": {
"type": "string",
"example": "individual"
@@ -6968,6 +7399,145 @@
}
}
},
"internal_notification.NotificationRequest": {
"type": "object",
"properties": {
"channels": {
"type": "array",
"items": {
"$ref": "#/definitions/notification.DeliveryChannel"
}
},
"description": {
"type": "string"
},
"link": {
"type": "string"
},
"priority": {
"$ref": "#/definitions/notification.NotificationPriority"
},
"recipient": {
"type": "array",
"items": {
"type": "string"
}
},
"schedule": {
"$ref": "#/definitions/notification.ScheduleRequest"
},
"tender": {
"type": "string"
},
"title": {
"type": "string"
},
"type": {
"$ref": "#/definitions/notification.NotificationType"
}
}
},
"internal_notification.NotificationResponse": {
"type": "object",
"properties": {
"channels": {
"type": "array",
"items": {
"$ref": "#/definitions/notification.DeliveryChannel"
}
},
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"link": {
"type": "string"
},
"priority": {
"$ref": "#/definitions/notification.NotificationPriority"
},
"schedule": {
"$ref": "#/definitions/notification.ScheduleResponse"
},
"tender": {
"type": "string"
},
"title": {
"type": "string"
},
"type": {
"$ref": "#/definitions/notification.NotificationType"
}
}
},
"notification.DeliveryChannel": {
"type": "string",
"enum": [
"push",
"email"
],
"x-enum-varnames": [
"DeliveryChannelPush",
"DeliveryChannelEmail"
]
},
"notification.NotificationPriority": {
"type": "string",
"enum": [
"low",
"medium",
"important"
],
"x-enum-varnames": [
"NotificationPriorityLow",
"NotificationPriorityMedium",
"NotificationPriorityImportant"
]
},
"notification.NotificationType": {
"type": "string",
"enum": [
"info",
"warning",
"alert",
"reject"
],
"x-enum-varnames": [
"NotificationTypeInfo",
"NotificationTypeWarning",
"NotificationTypeAlert",
"NotificationTypeReject"
]
},
"notification.NotificationsResponse": {
"type": "object",
"properties": {
"notifications": {
"type": "array",
"items": {
"$ref": "#/definitions/internal_notification.NotificationResponse"
}
}
}
},
"notification.ScheduleRequest": {
"type": "object",
"properties": {
"time": {
"type": "integer"
}
}
},
"notification.ScheduleResponse": {
"type": "object",
"properties": {
"time": {
"type": "integer"
}
}
},
"response.APIError": {
"type": "object",
"properties": {
@@ -7669,6 +8239,10 @@
"description": "Administrative flag management operations for web panel including flag listing and retrieval",
"name": "Admin-Flags"
},
{
"description": "Administrative notification management operations for web panel including CRUD operations, bulk notifications, queue management, and comprehensive filtering with pagination",
"name": "Admin-Notification"
},
{
"description": "Customer authentication and authorization operations for mobile application including login, logout, token refresh, and profile access",
"name": "Authorization"
+379 -2
View File
@@ -303,6 +303,21 @@ definitions:
updated_at:
type: integer
type: object
customer.AssignRoleForm:
properties:
role:
example: analyst
type: string
type: object
customer.AssignRoleResponse:
properties:
message:
example: Role assigned successfully
type: string
success:
example: true
type: boolean
type: object
customer.AuthResponse:
properties:
access_token:
@@ -339,6 +354,9 @@ definitions:
phone:
example: "+1234567890"
type: string
role:
example: analyst
type: string
type:
example: individual
type: string
@@ -373,10 +391,10 @@ definitions:
type: string
last_login_at:
type: integer
password:
type: string
phone:
type: string
role:
type: string
status:
type: string
type:
@@ -451,6 +469,9 @@ definitions:
phone:
example: "+1234567890"
type: string
role:
example: analyst
type: string
type:
example: individual
type: string
@@ -627,6 +648,101 @@ definitions:
example: reviewed
type: string
type: object
internal_notification.NotificationRequest:
properties:
channels:
items:
$ref: '#/definitions/notification.DeliveryChannel'
type: array
description:
type: string
link:
type: string
priority:
$ref: '#/definitions/notification.NotificationPriority'
recipient:
items:
type: string
type: array
schedule:
$ref: '#/definitions/notification.ScheduleRequest'
tender:
type: string
title:
type: string
type:
$ref: '#/definitions/notification.NotificationType'
type: object
internal_notification.NotificationResponse:
properties:
channels:
items:
$ref: '#/definitions/notification.DeliveryChannel'
type: array
description:
type: string
id:
type: string
link:
type: string
priority:
$ref: '#/definitions/notification.NotificationPriority'
schedule:
$ref: '#/definitions/notification.ScheduleResponse'
tender:
type: string
title:
type: string
type:
$ref: '#/definitions/notification.NotificationType'
type: object
notification.DeliveryChannel:
enum:
- push
- email
type: string
x-enum-varnames:
- DeliveryChannelPush
- DeliveryChannelEmail
notification.NotificationPriority:
enum:
- low
- medium
- important
type: string
x-enum-varnames:
- NotificationPriorityLow
- NotificationPriorityMedium
- NotificationPriorityImportant
notification.NotificationType:
enum:
- info
- warning
- alert
- reject
type: string
x-enum-varnames:
- NotificationTypeInfo
- NotificationTypeWarning
- NotificationTypeAlert
- NotificationTypeReject
notification.NotificationsResponse:
properties:
notifications:
items:
$ref: '#/definitions/internal_notification.NotificationResponse'
type: array
type: object
notification.ScheduleRequest:
properties:
time:
type: integer
type: object
notification.ScheduleResponse:
properties:
time:
type: integer
type: object
response.APIError:
properties:
code:
@@ -2002,6 +2118,56 @@ paths:
summary: Update customer information
tags:
- Admin-Customers
/admin/v1/customers/{id}/role:
patch:
consumes:
- application/json
description: Assign a role (admin or analyst) to a customer
parameters:
- description: Customer ID
in: path
name: id
required: true
type: string
- description: Role assignment information
in: body
name: role
required: true
schema:
$ref: '#/definitions/customer.AssignRoleForm'
produces:
- application/json
responses:
"200":
description: Role assigned successfully
schema:
allOf:
- $ref: '#/definitions/response.APIResponse'
- properties:
data:
$ref: '#/definitions/customer.AssignRoleResponse'
type: object
"400":
description: Bad request - Invalid input data
schema:
$ref: '#/definitions/response.APIResponse'
"404":
description: Not found - Customer not found
schema:
$ref: '#/definitions/response.APIResponse'
"422":
description: Validation error - Invalid request data
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- BearerAuth: []
summary: Assign role to customer
tags:
- Admin-Customers
/admin/v1/customers/{id}/status:
patch:
consumes:
@@ -2526,6 +2692,213 @@ paths:
summary: Update inquiry status
tags:
- Admin-Inquiries
/admin/v1/notifications:
get:
consumes:
- application/json
description: Retrieve notifications for a specific user with filtering and pagination
parameters:
- description: Recipient
in: query
name: recipient
required: true
type: string
- description: Notification type (info, warning, alert, reject)
in: query
name: type
type: string
- description: Notification priority (low, medium, important)
in: query
name: priority
type: string
- description: Delivery status (pending, sent, failed)
in: query
name: status
type: string
- description: Read status
in: query
name: is_read
type: boolean
- default: 1
description: Page number
in: query
name: page
type: integer
- default: 20
description: Items per page
in: query
name: limit
type: integer
- default: created_at
description: Sort field
in: query
name: sort_by
type: string
- default: desc
description: Sort order (asc, desc)
in: query
name: sort_order
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.APIResponse'
- properties:
data:
$ref: '#/definitions/notification.NotificationsResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get user notifications
tags:
- Admin-Notification
post:
consumes:
- application/json
description: Create a new notification with the provided information
parameters:
- description: Notification information
in: body
name: notification
required: true
schema:
$ref: '#/definitions/internal_notification.NotificationRequest'
produces:
- application/json
responses:
"201":
description: Notification created successfully
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Create a new notification
tags:
- Admin-Notification
/admin/v1/notifications/{id}:
delete:
consumes:
- application/json
description: Delete a specific notification
parameters:
- description: Notification ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Notification deleted successfully
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Delete notification
tags:
- Admin-Notification
get:
consumes:
- application/json
description: Retrieve a specific notification by its ID
parameters:
- description: Notification ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.APIResponse'
- properties:
data:
$ref: '#/definitions/internal_notification.NotificationResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get notification by ID
tags:
- Admin-Notification
put:
consumes:
- application/json
description: Update an existing notification
parameters:
- description: Notification ID
in: path
name: id
required: true
type: string
- description: Updated notification information
in: body
name: notification
required: true
schema:
$ref: '#/definitions/internal_notification.NotificationRequest'
produces:
- application/json
responses:
"200":
description: Notification updated successfully
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Update notification
tags:
- Admin-Notification
/admin/v1/profile:
get:
consumes:
@@ -4909,6 +5282,10 @@ tags:
- description: Administrative flag management operations for web panel including flag
listing and retrieval
name: Admin-Flags
- description: Administrative notification management operations for web panel including
CRUD operations, bulk notifications, queue management, and comprehensive filtering
with pagination
name: Admin-Notification
- description: Customer authentication and authorization operations for mobile application
including login, logout, token refresh, and profile access
name: Authorization
+12 -5
View File
@@ -53,6 +53,9 @@ package main
// @tag.name Admin-Flags
// @tag.description Administrative flag management operations for web panel including flag listing and retrieval
// @tag.name Admin-Notification
// @tag.description Administrative notification management operations for web panel including CRUD operations, bulk notifications, queue management, and comprehensive filtering with pagination
// @tag.name Authorization
// @tag.description Customer authentication and authorization operations for mobile application including login, logout, token refresh, and profile access
@@ -85,6 +88,7 @@ import (
"tm/internal/customer"
"tm/internal/feedback"
"tm/internal/inquiry"
"tm/internal/notification"
"tm/internal/tender"
"tm/internal/tender_approval"
"tm/internal/user"
@@ -138,8 +142,9 @@ func main() {
feedbackRepo := feedback.NewFeedbackRepository(mongoManager, logger)
tenderApprovalRepository := tender_approval.NewTenderApprovalRepository(mongoManager, logger)
inquiryRepository := inquiry.NewInquiryRepository(mongoManager, logger)
notificationRepository := notification.NewNotificationRepository(mongoManager, logger)
logger.Info("Repositories initialized successfully", map[string]interface{}{
"repositories": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry"},
"repositories": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "notification"},
})
// Initialize validation service
@@ -155,8 +160,9 @@ func main() {
tenderApprovalService := tender_approval.NewTenderApprovalService(tenderApprovalRepository, tenderService, logger)
inquiryService := inquiry.NewInquiryService(inquiryRepository, logger)
flagService := assets.NewFlagService(logger, conf.Assets.FlagsPath)
notificationService := notification.NewNotificationService(notificationRepository, logger)
logger.Info("Services initialized successfully", map[string]interface{}{
"services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag"},
"services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification"},
})
// Initialize handlers with services
@@ -169,16 +175,17 @@ func main() {
tenderApprovalHandler := tender_approval.NewHandler(tenderApprovalService, logger)
inquiryHandler := inquiry.NewHandler(inquiryService, logger)
flagHandler := assets.NewHandler(flagService, logger)
notificationHandler := notification.NewHandler(notificationService, logger)
logger.Info("Handlers initialized successfully", map[string]interface{}{
"handlers": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag"},
"handlers": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification"},
})
// Initialize HTTP server
e := bootstrap.InitHTTPServer(conf, logger)
// Register routes
router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, inquiryHandler, categoryHandler, flagHandler)
router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler, inquiryHandler, categoryHandler, flagHandler)
router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler)
router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler)
// Start server
serverAddr := fmt.Sprintf("%s:%d", conf.Server.Host, conf.Server.Port)
+28 -2
View File
@@ -7,6 +7,7 @@ import (
"tm/internal/customer"
"tm/internal/feedback"
"tm/internal/inquiry"
"tm/internal/notification"
"tm/internal/tender"
"tm/internal/tender_approval"
"tm/internal/user"
@@ -14,7 +15,7 @@ import (
"github.com/labstack/echo/v4"
)
func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler *company.Handler, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler) {
func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler *company.Handler, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler) {
adminV1 := e.Group("/admin/v1")
// Admin Users Routes
@@ -128,9 +129,24 @@ func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler
{
flagsGP.GET("/:country_code", flagHandler.AdminGetFlagSVG)
}
// Admin Notifications Routes
// notificationsGP := adminV1.Group("/notifications")
// {
// notificationsGP.Use(userHandler.AuthMiddleware())
// notificationsGP.POST("", notificationHandler.CreateNotification)
// notificationsGP.POST("/bulk", notificationHandler.CreateBulkNotification)
// notificationsGP.GET("", notificationHandler.GetNotifications)
// notificationsGP.GET("/stats", notificationHandler.GetNotificationStats)
// notificationsGP.POST("/mark-read", notificationHandler.MarkAsRead)
// notificationsGP.POST("/process-pending", notificationHandler.ProcessPendingNotifications)
// notificationsGP.GET("/:id", notificationHandler.GetNotificationByID)
// notificationsGP.PUT("/:id", notificationHandler.UpdateNotification)
// notificationsGP.DELETE("/:id", notificationHandler.DeleteNotification)
// }
}
func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, companyHandler *company.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler) {
func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tenderHandler *tender.TenderHandler, feedbackHandler *feedback.Handler, tenderApprovalHandler *tender_approval.Handler, companyHandler *company.Handler, inquiryHandler *inquiry.Handler, categoryHandler *company_category.Handler, flagHandler *assets.Handler, notificationHandler *notification.NotificationHandler) {
v1 := e.Group("/api/v1")
customerGP := v1.Group("/profile")
@@ -198,4 +214,14 @@ func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tende
{
flagsGP.GET("/:country_code", flagHandler.GetFlagSVG)
}
// Public Notifications Routes
// notificationsGP := v1.Group("/notifications")
// {
// notificationsGP.Use(customerHandler.AuthMiddleware())
// notificationsGP.GET("", notificationHandler.GetNotifications)
// notificationsGP.GET("/stats", notificationHandler.GetNotificationStats)
// notificationsGP.POST("/mark-read", notificationHandler.MarkAsRead)
// notificationsGP.GET("/:id", notificationHandler.GetNotificationByID)
// }
}