Enhance Tender Search API with Advanced Filtering and Documentation Updates

- Updated the Tender Search API to include additional query parameters for enhanced filtering capabilities, such as currency, deadline ranges, publication dates, languages, and buyer organization ID.
- Changed existing query parameter types from integer to string for better flexibility in search queries.
- Improved Swagger and YAML documentation to reflect the new parameters and their descriptions, ensuring clarity for API consumers.
- Updated handler comments to align with the new query structure, providing comprehensive details for each parameter.
- Enhanced response structures to return a well-defined SearchResponse, improving the overall API usability and documentation consistency.
This commit is contained in:
n.nakhostin
2025-09-08 14:25:02 +03:30
parent 3911180486
commit a76aa16cba
4 changed files with 639 additions and 120 deletions
+221 -36
View File
@@ -5370,21 +5370,51 @@ const docTemplate = `{
"summary": "Get public tenders", "summary": "Get public tenders",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "string",
"description": "Number of items per page (default: 20, max: 50)", "description": "Search query for title and description",
"name": "limit", "name": "q",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query" "in": "query"
}, },
{ {
"type": "string", "type": "string",
"description": "Filter by country code", "description": "Filter by notice type code",
"name": "country_code", "name": "notice_type",
"in": "query"
},
{
"type": "string",
"description": "Filter by procurement type code",
"name": "procurement_type",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by country codes (comma-separated)",
"name": "country_codes",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by status (comma-separated)",
"name": "status",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by source (comma-separated)",
"name": "source",
"in": "query" "in": "query"
}, },
{ {
@@ -5400,15 +5430,73 @@ const docTemplate = `{
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "string",
"description": "Publication from", "description": "Filter by currency",
"name": "publication_from", "name": "currency",
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "number",
"description": "Publication to", "description": "Deadline from",
"name": "publication_to", "name": "deadline_from",
"in": "query"
},
{
"type": "number",
"description": "Deadline to",
"name": "deadline_to",
"in": "query"
},
{
"type": "number",
"description": "Publication date from",
"name": "publication_date_from",
"in": "query"
},
{
"type": "number",
"description": "Publication date to",
"name": "publication_date_to",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by languages (comma-separated)",
"name": "languages",
"in": "query"
},
{
"type": "string",
"description": "Filter by buyer organization ID",
"name": "buyer_organization_id",
"in": "query"
},
{
"type": "integer",
"description": "Number of items per page (default: 20, max: 100)",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query"
},
{
"type": "string",
"description": "Sort by field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"description": "Sort order (asc or desc)",
"name": "sort_order",
"in": "query" "in": "query"
} }
], ],
@@ -5424,8 +5512,7 @@ const docTemplate = `{
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "object", "$ref": "#/definitions/tender.SearchResponse"
"additionalProperties": true
} }
} }
} }
@@ -5523,21 +5610,51 @@ const docTemplate = `{
"summary": "Get public tenders", "summary": "Get public tenders",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "string",
"description": "Number of items per page (default: 20, max: 50)", "description": "Search query for title and description",
"name": "limit", "name": "q",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query" "in": "query"
}, },
{ {
"type": "string", "type": "string",
"description": "Filter by country code", "description": "Filter by notice type code",
"name": "country_code", "name": "notice_type",
"in": "query"
},
{
"type": "string",
"description": "Filter by procurement type code",
"name": "procurement_type",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by country codes (comma-separated)",
"name": "country_codes",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by status (comma-separated)",
"name": "status",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by source (comma-separated)",
"name": "source",
"in": "query" "in": "query"
}, },
{ {
@@ -5553,15 +5670,73 @@ const docTemplate = `{
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "string",
"description": "Publication from", "description": "Filter by currency",
"name": "publication_from", "name": "currency",
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "number",
"description": "Publication to", "description": "Deadline from",
"name": "publication_to", "name": "deadline_from",
"in": "query"
},
{
"type": "number",
"description": "Deadline to",
"name": "deadline_to",
"in": "query"
},
{
"type": "number",
"description": "Publication date from",
"name": "publication_date_from",
"in": "query"
},
{
"type": "number",
"description": "Publication date to",
"name": "publication_date_to",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by languages (comma-separated)",
"name": "languages",
"in": "query"
},
{
"type": "string",
"description": "Filter by buyer organization ID",
"name": "buyer_organization_id",
"in": "query"
},
{
"type": "integer",
"description": "Number of items per page (default: 20, max: 100)",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query"
},
{
"type": "string",
"description": "Sort by field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"description": "Sort order (asc or desc)",
"name": "sort_order",
"in": "query" "in": "query"
} }
], ],
@@ -5577,8 +5752,7 @@ const docTemplate = `{
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "object", "$ref": "#/definitions/tender.SearchResponse"
"additionalProperties": true
} }
} }
} }
@@ -6509,6 +6683,17 @@ const docTemplate = `{
} }
} }
}, },
"tender.SearchResponse": {
"type": "object",
"properties": {
"tenders": {
"type": "array",
"items": {
"$ref": "#/definitions/tender.TenderResponse"
}
}
}
},
"tender.TenderResponse": { "tender.TenderResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
+221 -36
View File
@@ -5364,21 +5364,51 @@
"summary": "Get public tenders", "summary": "Get public tenders",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "string",
"description": "Number of items per page (default: 20, max: 50)", "description": "Search query for title and description",
"name": "limit", "name": "q",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query" "in": "query"
}, },
{ {
"type": "string", "type": "string",
"description": "Filter by country code", "description": "Filter by notice type code",
"name": "country_code", "name": "notice_type",
"in": "query"
},
{
"type": "string",
"description": "Filter by procurement type code",
"name": "procurement_type",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by country codes (comma-separated)",
"name": "country_codes",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by status (comma-separated)",
"name": "status",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by source (comma-separated)",
"name": "source",
"in": "query" "in": "query"
}, },
{ {
@@ -5394,15 +5424,73 @@
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "string",
"description": "Publication from", "description": "Filter by currency",
"name": "publication_from", "name": "currency",
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "number",
"description": "Publication to", "description": "Deadline from",
"name": "publication_to", "name": "deadline_from",
"in": "query"
},
{
"type": "number",
"description": "Deadline to",
"name": "deadline_to",
"in": "query"
},
{
"type": "number",
"description": "Publication date from",
"name": "publication_date_from",
"in": "query"
},
{
"type": "number",
"description": "Publication date to",
"name": "publication_date_to",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by languages (comma-separated)",
"name": "languages",
"in": "query"
},
{
"type": "string",
"description": "Filter by buyer organization ID",
"name": "buyer_organization_id",
"in": "query"
},
{
"type": "integer",
"description": "Number of items per page (default: 20, max: 100)",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query"
},
{
"type": "string",
"description": "Sort by field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"description": "Sort order (asc or desc)",
"name": "sort_order",
"in": "query" "in": "query"
} }
], ],
@@ -5418,8 +5506,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "object", "$ref": "#/definitions/tender.SearchResponse"
"additionalProperties": true
} }
} }
} }
@@ -5517,21 +5604,51 @@
"summary": "Get public tenders", "summary": "Get public tenders",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "string",
"description": "Number of items per page (default: 20, max: 50)", "description": "Search query for title and description",
"name": "limit", "name": "q",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query" "in": "query"
}, },
{ {
"type": "string", "type": "string",
"description": "Filter by country code", "description": "Filter by notice type code",
"name": "country_code", "name": "notice_type",
"in": "query"
},
{
"type": "string",
"description": "Filter by procurement type code",
"name": "procurement_type",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by country codes (comma-separated)",
"name": "country_codes",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by status (comma-separated)",
"name": "status",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by source (comma-separated)",
"name": "source",
"in": "query" "in": "query"
}, },
{ {
@@ -5547,15 +5664,73 @@
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "string",
"description": "Publication from", "description": "Filter by currency",
"name": "publication_from", "name": "currency",
"in": "query" "in": "query"
}, },
{ {
"type": "number", "type": "number",
"description": "Publication to", "description": "Deadline from",
"name": "publication_to", "name": "deadline_from",
"in": "query"
},
{
"type": "number",
"description": "Deadline to",
"name": "deadline_to",
"in": "query"
},
{
"type": "number",
"description": "Publication date from",
"name": "publication_date_from",
"in": "query"
},
{
"type": "number",
"description": "Publication date to",
"name": "publication_date_to",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv",
"description": "Filter by languages (comma-separated)",
"name": "languages",
"in": "query"
},
{
"type": "string",
"description": "Filter by buyer organization ID",
"name": "buyer_organization_id",
"in": "query"
},
{
"type": "integer",
"description": "Number of items per page (default: 20, max: 100)",
"name": "limit",
"in": "query"
},
{
"type": "integer",
"description": "Number of items to skip (default: 0)",
"name": "offset",
"in": "query"
},
{
"type": "string",
"description": "Sort by field",
"name": "sort_by",
"in": "query"
},
{
"type": "string",
"description": "Sort order (asc or desc)",
"name": "sort_order",
"in": "query" "in": "query"
} }
], ],
@@ -5571,8 +5746,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"data": { "data": {
"type": "object", "$ref": "#/definitions/tender.SearchResponse"
"additionalProperties": true
} }
} }
} }
@@ -6503,6 +6677,17 @@
} }
} }
}, },
"tender.SearchResponse": {
"type": "object",
"properties": {
"tenders": {
"type": "array",
"items": {
"$ref": "#/definitions/tender.TenderResponse"
}
}
}
},
"tender.TenderResponse": { "tender.TenderResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
+159 -34
View File
@@ -612,6 +612,13 @@ definitions:
name: name:
type: string type: string
type: object type: object
tender.SearchResponse:
properties:
tenders:
items:
$ref: '#/definitions/tender.TenderResponse'
type: array
type: object
tender.TenderResponse: tender.TenderResponse:
properties: properties:
application_deadline: application_deadline:
@@ -4364,18 +4371,39 @@ paths:
description: Retrieve active tenders for mobile application users with automatic description: Retrieve active tenders for mobile application users with automatic
company-based matching from customer profile company-based matching from customer profile
parameters: parameters:
- description: 'Number of items per page (default: 20, max: 50)' - description: Search query for title and description
in: query in: query
name: limit name: q
type: integer
- description: 'Number of items to skip (default: 0)'
in: query
name: offset
type: integer
- description: Filter by country code
in: query
name: country_code
type: string type: string
- description: Filter by notice type code
in: query
name: notice_type
type: string
- description: Filter by procurement type code
in: query
name: procurement_type
type: string
- collectionFormat: csv
description: Filter by country codes (comma-separated)
in: query
items:
type: string
name: country_codes
type: array
- collectionFormat: csv
description: Filter by status (comma-separated)
in: query
items:
type: string
name: status
type: array
- collectionFormat: csv
description: Filter by source (comma-separated)
in: query
items:
type: string
name: source
type: array
- description: Minimum estimated value - description: Minimum estimated value
in: query in: query
name: min_estimated_value name: min_estimated_value
@@ -4384,14 +4412,53 @@ paths:
in: query in: query
name: max_estimated_value name: max_estimated_value
type: number type: number
- description: Publication from - description: Filter by currency
in: query in: query
name: publication_from name: currency
type: number type: string
- description: Publication to - description: Deadline from
in: query in: query
name: publication_to name: deadline_from
type: number type: number
- description: Deadline to
in: query
name: deadline_to
type: number
- description: Publication date from
in: query
name: publication_date_from
type: number
- description: Publication date to
in: query
name: publication_date_to
type: number
- collectionFormat: csv
description: Filter by languages (comma-separated)
in: query
items:
type: string
name: languages
type: array
- description: Filter by buyer organization ID
in: query
name: buyer_organization_id
type: string
- description: 'Number of items per page (default: 20, max: 100)'
in: query
name: limit
type: integer
- description: 'Number of items to skip (default: 0)'
in: query
name: offset
type: integer
- description: Sort by field
in: query
name: sort_by
type: string
- description: Sort order (asc or desc)
in: query
name: sort_order
type: string
produces: produces:
- application/json - application/json
responses: responses:
@@ -4402,8 +4469,7 @@ paths:
- $ref: '#/definitions/response.APIResponse' - $ref: '#/definitions/response.APIResponse'
- properties: - properties:
data: data:
additionalProperties: true $ref: '#/definitions/tender.SearchResponse'
type: object
type: object type: object
"400": "400":
description: Bad Request description: Bad Request
@@ -4459,18 +4525,39 @@ paths:
description: Retrieve active tenders for mobile application users with automatic description: Retrieve active tenders for mobile application users with automatic
company-based matching from customer profile company-based matching from customer profile
parameters: parameters:
- description: 'Number of items per page (default: 20, max: 50)' - description: Search query for title and description
in: query in: query
name: limit name: q
type: integer
- description: 'Number of items to skip (default: 0)'
in: query
name: offset
type: integer
- description: Filter by country code
in: query
name: country_code
type: string type: string
- description: Filter by notice type code
in: query
name: notice_type
type: string
- description: Filter by procurement type code
in: query
name: procurement_type
type: string
- collectionFormat: csv
description: Filter by country codes (comma-separated)
in: query
items:
type: string
name: country_codes
type: array
- collectionFormat: csv
description: Filter by status (comma-separated)
in: query
items:
type: string
name: status
type: array
- collectionFormat: csv
description: Filter by source (comma-separated)
in: query
items:
type: string
name: source
type: array
- description: Minimum estimated value - description: Minimum estimated value
in: query in: query
name: min_estimated_value name: min_estimated_value
@@ -4479,14 +4566,53 @@ paths:
in: query in: query
name: max_estimated_value name: max_estimated_value
type: number type: number
- description: Publication from - description: Filter by currency
in: query in: query
name: publication_from name: currency
type: number type: string
- description: Publication to - description: Deadline from
in: query in: query
name: publication_to name: deadline_from
type: number type: number
- description: Deadline to
in: query
name: deadline_to
type: number
- description: Publication date from
in: query
name: publication_date_from
type: number
- description: Publication date to
in: query
name: publication_date_to
type: number
- collectionFormat: csv
description: Filter by languages (comma-separated)
in: query
items:
type: string
name: languages
type: array
- description: Filter by buyer organization ID
in: query
name: buyer_organization_id
type: string
- description: 'Number of items per page (default: 20, max: 100)'
in: query
name: limit
type: integer
- description: 'Number of items to skip (default: 0)'
in: query
name: offset
type: integer
- description: Sort by field
in: query
name: sort_by
type: string
- description: Sort order (asc or desc)
in: query
name: sort_order
type: string
produces: produces:
- application/json - application/json
responses: responses:
@@ -4497,8 +4623,7 @@ paths:
- $ref: '#/definitions/response.APIResponse' - $ref: '#/definitions/response.APIResponse'
- properties: - properties:
data: data:
additionalProperties: true $ref: '#/definitions/tender.SearchResponse'
type: object
type: object type: object
"400": "400":
description: Bad Request description: Bad Request
+38 -14
View File
@@ -179,14 +179,26 @@ func (h *TenderHandler) Search(c echo.Context) error {
// @Description Retrieve active tenders for mobile application users with automatic company-based matching from customer profile // @Description Retrieve active tenders for mobile application users with automatic company-based matching from customer profile
// @Tags Tenders // @Tags Tenders
// @Produce json // @Produce json
// @Param limit query int false "Number of items per page (default: 20, max: 50)" // @Param q query string false "Search query for title and description"
// @Param offset query int false "Number of items to skip (default: 0)" // @Param notice_type query string false "Filter by notice type code"
// @Param country_code query string false "Filter by country code" // @Param procurement_type query string false "Filter by procurement type code"
// @Param country_codes query []string false "Filter by country codes (comma-separated)"
// @Param status query []string false "Filter by status (comma-separated)"
// @Param source query []string false "Filter by source (comma-separated)"
// @Param min_estimated_value query number false "Minimum estimated value" // @Param min_estimated_value query number false "Minimum estimated value"
// @Param max_estimated_value query number false "Maximum estimated value" // @Param max_estimated_value query number false "Maximum estimated value"
// @Param publication_from query number false "Publication from" // @Param currency query string false "Filter by currency"
// @Param publication_to query number false "Publication to" // @Param deadline_from query number false "Deadline from"
// @Success 200 {object} response.APIResponse{data=map[string]interface{}} // @Param deadline_to query number false "Deadline to"
// @Param publication_date_from query number false "Publication date from"
// @Param publication_date_to query number false "Publication date to"
// @Param languages query []string false "Filter by languages (comma-separated)"
// @Param buyer_organization_id query string false "Filter by buyer organization ID"
// @Param limit query int false "Number of items per page (default: 20, max: 100)"
// @Param offset query int false "Number of items to skip (default: 0)"
// @Param sort_by query string false "Sort by field"
// @Param sort_order query string false "Sort order (asc or desc)"
// @Success 200 {object} response.APIResponse{data=SearchResponse}
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Security BearerAuth // @Security BearerAuth
@@ -216,7 +228,7 @@ func (h *TenderHandler) GetPublicTenders(c echo.Context) error {
return response.InternalServerError(c, "Failed to retrieve tenders") return response.InternalServerError(c, "Failed to retrieve tenders")
} }
return response.Success(c, result, "Tenders retrieved successfully") return response.SuccessWithMeta(c, result, result.Metadata, "Tenders retrieved successfully")
} }
// GetPublicTenders retrieves public tenders for mobile app // GetPublicTenders retrieves public tenders for mobile app
@@ -224,14 +236,26 @@ func (h *TenderHandler) GetPublicTenders(c echo.Context) error {
// @Description Retrieve active tenders for mobile application users with automatic company-based matching from customer profile // @Description Retrieve active tenders for mobile application users with automatic company-based matching from customer profile
// @Tags Tenders // @Tags Tenders
// @Produce json // @Produce json
// @Param limit query int false "Number of items per page (default: 20, max: 50)" // @Param q query string false "Search query for title and description"
// @Param offset query int false "Number of items to skip (default: 0)" // @Param notice_type query string false "Filter by notice type code"
// @Param country_code query string false "Filter by country code" // @Param procurement_type query string false "Filter by procurement type code"
// @Param country_codes query []string false "Filter by country codes (comma-separated)"
// @Param status query []string false "Filter by status (comma-separated)"
// @Param source query []string false "Filter by source (comma-separated)"
// @Param min_estimated_value query number false "Minimum estimated value" // @Param min_estimated_value query number false "Minimum estimated value"
// @Param max_estimated_value query number false "Maximum estimated value" // @Param max_estimated_value query number false "Maximum estimated value"
// @Param publication_from query number false "Publication from" // @Param currency query string false "Filter by currency"
// @Param publication_to query number false "Publication to" // @Param deadline_from query number false "Deadline from"
// @Success 200 {object} response.APIResponse{data=map[string]interface{}} // @Param deadline_to query number false "Deadline to"
// @Param publication_date_from query number false "Publication date from"
// @Param publication_date_to query number false "Publication date to"
// @Param languages query []string false "Filter by languages (comma-separated)"
// @Param buyer_organization_id query string false "Filter by buyer organization ID"
// @Param limit query int false "Number of items per page (default: 20, max: 100)"
// @Param offset query int false "Number of items to skip (default: 0)"
// @Param sort_by query string false "Sort by field"
// @Param sort_order query string false "Sort order (asc or desc)"
// @Success 200 {object} response.APIResponse{data=SearchResponse}
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Security BearerAuth // @Security BearerAuth
@@ -261,7 +285,7 @@ func (h *TenderHandler) RecommendTenders(c echo.Context) error {
return response.InternalServerError(c, "Failed to retrieve tenders") return response.InternalServerError(c, "Failed to retrieve tenders")
} }
return response.Success(c, result, "Tenders retrieved successfully") return response.SuccessWithMeta(c, result, result.Metadata, "Tenders retrieved successfully")
} }
// GetPublicTenderDetails retrieves public tender details for mobile app // GetPublicTenderDetails retrieves public tender details for mobile app