Add Contact Management Functionality
- Introduced a new contact management feature, including the ability to create, retrieve, search, update, and delete contact messages. - Implemented the Contact entity, repository, service, and handler layers following Clean Architecture principles. - Added API endpoints for contact operations in Swagger documentation, ensuring comprehensive API specifications. - Enhanced error handling and validation for contact data, improving robustness and user experience. - Updated the main application to initialize the contact repository and service, integrating them into the existing system.
This commit is contained in:
@@ -1043,6 +1043,337 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts": {
|
||||
"get": {
|
||||
"description": "Search contacts with filters and pagination (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Search contacts",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"pending",
|
||||
"in_progress",
|
||||
"resolved",
|
||||
"closed"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Contact status",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Date from (Unix timestamp)",
|
||||
"name": "date_from",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Date to (Unix timestamp)",
|
||||
"name": "date_to",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"default": 20,
|
||||
"description": "Number of contacts per page (1-100)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Number of contacts to skip for pagination",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"full_name",
|
||||
"email",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"status"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "created_at",
|
||||
"description": "Field to sort by",
|
||||
"name": "sort_by",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"asc",
|
||||
"desc"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "desc",
|
||||
"description": "Sort order",
|
||||
"name": "sort_order",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts/stats": {
|
||||
"get": {
|
||||
"description": "Get contact statistics by status (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Get contact statistics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactStats"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts/{id}": {
|
||||
"get": {
|
||||
"description": "Retrieve a contact message by its ID (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Get contact by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"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 contact message by ID (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Delete contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"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/contacts/{id}/status": {
|
||||
"put": {
|
||||
"description": "Update the status of a contact message (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Update contact status",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Status update information",
|
||||
"name": "status",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/contact.UpdateContactStatusForm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"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/customers": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -4699,6 +5030,64 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/contacts": {
|
||||
"post": {
|
||||
"description": "Create a new contact message from a user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Create a new contact message",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Contact information",
|
||||
"name": "contact",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/contact.CreateContactForm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/feedback": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -7369,6 +7758,109 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactListResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin_notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"resolved_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resolved_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"closed": {
|
||||
"type": "integer"
|
||||
},
|
||||
"in_progress": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pending": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resolved": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.CreateContactForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string",
|
||||
"example": "John Doe"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "I have a question about your services"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"example": "+1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.UpdateContactStatusForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin_notes": {
|
||||
"type": "string",
|
||||
"example": "Customer inquiry handled"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"example": "in_progress"
|
||||
}
|
||||
}
|
||||
},
|
||||
"customer.AssignCompaniesForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -1035,6 +1035,337 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts": {
|
||||
"get": {
|
||||
"description": "Search contacts with filters and pagination (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Search contacts",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"pending",
|
||||
"in_progress",
|
||||
"resolved",
|
||||
"closed"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Contact status",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Date from (Unix timestamp)",
|
||||
"name": "date_from",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Date to (Unix timestamp)",
|
||||
"name": "date_to",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"default": 20,
|
||||
"description": "Number of contacts per page (1-100)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"minimum": 0,
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Number of contacts to skip for pagination",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"full_name",
|
||||
"email",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"status"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "created_at",
|
||||
"description": "Field to sort by",
|
||||
"name": "sort_by",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"asc",
|
||||
"desc"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "desc",
|
||||
"description": "Sort order",
|
||||
"name": "sort_order",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts/stats": {
|
||||
"get": {
|
||||
"description": "Get contact statistics by status (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Get contact statistics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactStats"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/admin/v1/contacts/{id}": {
|
||||
"get": {
|
||||
"description": "Retrieve a contact message by its ID (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Get contact by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"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 contact message by ID (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Delete contact",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"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/contacts/{id}/status": {
|
||||
"put": {
|
||||
"description": "Update the status of a contact message (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Update contact status",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Contact ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Status update information",
|
||||
"name": "status",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/contact.UpdateContactStatusForm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"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/customers": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -4691,6 +5022,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/contacts": {
|
||||
"post": {
|
||||
"description": "Create a new contact message from a user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"contacts"
|
||||
],
|
||||
"summary": "Create a new contact message",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Contact information",
|
||||
"name": "contact",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/contact.CreateContactForm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/feedback": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -7361,6 +7750,109 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactListResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/contact.ContactResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin_notes": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"resolved_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resolved_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.ContactStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"closed": {
|
||||
"type": "integer"
|
||||
},
|
||||
"in_progress": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pending": {
|
||||
"type": "integer"
|
||||
},
|
||||
"resolved": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.CreateContactForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string",
|
||||
"example": "John Doe"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "I have a question about your services"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"example": "+1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contact.UpdateContactStatusForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin_notes": {
|
||||
"type": "string",
|
||||
"example": "Customer inquiry handled"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"example": "in_progress"
|
||||
}
|
||||
}
|
||||
},
|
||||
"customer.AssignCompaniesForm": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -302,6 +302,75 @@ definitions:
|
||||
updated_at:
|
||||
type: integer
|
||||
type: object
|
||||
contact.ContactListResponse:
|
||||
properties:
|
||||
contacts:
|
||||
items:
|
||||
$ref: '#/definitions/contact.ContactResponse'
|
||||
type: array
|
||||
type: object
|
||||
contact.ContactResponse:
|
||||
properties:
|
||||
admin_notes:
|
||||
type: string
|
||||
created_at:
|
||||
type: integer
|
||||
email:
|
||||
type: string
|
||||
full_name:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
resolved_at:
|
||||
type: integer
|
||||
resolved_by:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
updated_at:
|
||||
type: integer
|
||||
type: object
|
||||
contact.ContactStats:
|
||||
properties:
|
||||
closed:
|
||||
type: integer
|
||||
in_progress:
|
||||
type: integer
|
||||
pending:
|
||||
type: integer
|
||||
resolved:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
type: object
|
||||
contact.CreateContactForm:
|
||||
properties:
|
||||
email:
|
||||
example: john.doe@example.com
|
||||
type: string
|
||||
full_name:
|
||||
example: John Doe
|
||||
type: string
|
||||
message:
|
||||
example: I have a question about your services
|
||||
type: string
|
||||
phone:
|
||||
example: "+1234567890"
|
||||
type: string
|
||||
type: object
|
||||
contact.UpdateContactStatusForm:
|
||||
properties:
|
||||
admin_notes:
|
||||
example: Customer inquiry handled
|
||||
type: string
|
||||
status:
|
||||
example: in_progress
|
||||
type: string
|
||||
type: object
|
||||
customer.AssignCompaniesForm:
|
||||
properties:
|
||||
companies:
|
||||
@@ -1999,6 +2068,221 @@ paths:
|
||||
summary: Toggle category publish status
|
||||
tags:
|
||||
- Admin-Company-Categories
|
||||
/admin/v1/contacts:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Search contacts with filters and pagination (admin only)
|
||||
parameters:
|
||||
- description: Search query
|
||||
in: query
|
||||
name: q
|
||||
type: string
|
||||
- description: Contact status
|
||||
enum:
|
||||
- pending
|
||||
- in_progress
|
||||
- resolved
|
||||
- closed
|
||||
in: query
|
||||
name: status
|
||||
type: string
|
||||
- description: Date from (Unix timestamp)
|
||||
in: query
|
||||
name: date_from
|
||||
type: integer
|
||||
- description: Date to (Unix timestamp)
|
||||
in: query
|
||||
name: date_to
|
||||
type: integer
|
||||
- default: 20
|
||||
description: Number of contacts per page (1-100)
|
||||
in: query
|
||||
maximum: 100
|
||||
minimum: 1
|
||||
name: limit
|
||||
type: integer
|
||||
- default: 0
|
||||
description: Number of contacts to skip for pagination
|
||||
in: query
|
||||
minimum: 0
|
||||
name: offset
|
||||
type: integer
|
||||
- default: created_at
|
||||
description: Field to sort by
|
||||
enum:
|
||||
- full_name
|
||||
- email
|
||||
- created_at
|
||||
- updated_at
|
||||
- status
|
||||
in: query
|
||||
name: sort_by
|
||||
type: string
|
||||
- default: desc
|
||||
description: Sort order
|
||||
enum:
|
||||
- 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/contact.ContactListResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Search contacts
|
||||
tags:
|
||||
- contacts
|
||||
/admin/v1/contacts/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Delete a contact message by ID (admin only)
|
||||
parameters:
|
||||
- description: Contact ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
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 contact
|
||||
tags:
|
||||
- contacts
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieve a contact message by its ID (admin only)
|
||||
parameters:
|
||||
- description: Contact 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/contact.ContactResponse'
|
||||
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 contact by ID
|
||||
tags:
|
||||
- contacts
|
||||
/admin/v1/contacts/{id}/status:
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update the status of a contact message (admin only)
|
||||
parameters:
|
||||
- description: Contact ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Status update information
|
||||
in: body
|
||||
name: status
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/contact.UpdateContactStatusForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
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 contact status
|
||||
tags:
|
||||
- contacts
|
||||
/admin/v1/contacts/stats:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get contact statistics by status (admin only)
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.APIResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/contact.ContactStats'
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Get contact statistics
|
||||
tags:
|
||||
- contacts
|
||||
/admin/v1/customers:
|
||||
get:
|
||||
consumes:
|
||||
@@ -4314,6 +4598,41 @@ paths:
|
||||
summary: Get my company profile
|
||||
tags:
|
||||
- Company
|
||||
/api/v1/contacts:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create a new contact message from a user
|
||||
parameters:
|
||||
- description: Contact information
|
||||
in: body
|
||||
name: contact
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/contact.CreateContactForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.APIResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/contact.ContactResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Create a new contact message
|
||||
tags:
|
||||
- contacts
|
||||
/api/v1/feedback:
|
||||
get:
|
||||
consumes:
|
||||
|
||||
+10
-6
@@ -85,6 +85,7 @@ import (
|
||||
"tm/internal/assets"
|
||||
"tm/internal/company"
|
||||
"tm/internal/company_category"
|
||||
"tm/internal/contact"
|
||||
"tm/internal/customer"
|
||||
"tm/internal/feedback"
|
||||
"tm/internal/inquiry"
|
||||
@@ -142,8 +143,9 @@ func main() {
|
||||
feedbackRepo := feedback.NewRepository(mongoManager, logger)
|
||||
tenderApprovalRepository := tender_approval.NewRepository(mongoManager, logger)
|
||||
inquiryRepository := inquiry.NewRepository(mongoManager, logger)
|
||||
contactRepository := contact.NewContactRepository(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", "contact"},
|
||||
})
|
||||
|
||||
// Initialize validation services
|
||||
@@ -161,8 +163,9 @@ func main() {
|
||||
inquiryService := inquiry.NewService(inquiryRepository, notificationSDK, logger)
|
||||
flagService := assets.NewService(logger, conf.Assets.FlagsPath)
|
||||
notificationService := notification.NewService(notificationSDK, userService, customerService, logger)
|
||||
contactService := contact.NewService(contactRepository, logger)
|
||||
logger.Info("Services initialized successfully", map[string]interface{}{
|
||||
"services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification"},
|
||||
"services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification", "contact"},
|
||||
})
|
||||
|
||||
// Initialize handlers with services
|
||||
@@ -175,17 +178,18 @@ func main() {
|
||||
tenderApprovalHandler := tender_approval.NewHandler(tenderApprovalService, logger)
|
||||
inquiryHandler := inquiry.NewHandler(inquiryService, logger)
|
||||
flagHandler := assets.NewHandler(flagService, logger)
|
||||
notificationHandler := notification.NewHandler(notificationService, logger)
|
||||
notificationHandler := notification.NewHandler(notificationService)
|
||||
contactHandler := contact.NewHandler(contactService)
|
||||
logger.Info("Handlers initialized successfully", map[string]interface{}{
|
||||
"handlers": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification"},
|
||||
"handlers": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification", "contact"},
|
||||
})
|
||||
|
||||
// Initialize HTTP server
|
||||
e := bootstrap.InitHTTPServer(conf, logger)
|
||||
|
||||
// Register routes
|
||||
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)
|
||||
router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler)
|
||||
router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler, inquiryHandler, categoryHandler, flagHandler, notificationHandler, contactHandler)
|
||||
|
||||
// Start server
|
||||
serverAddr := fmt.Sprintf("%s:%d", conf.Server.Host, conf.Server.Port)
|
||||
|
||||
Reference in New Issue
Block a user