Add Company Tender Approval Statistics Endpoint and Update API Documentation
- Introduced a new API endpoint to retrieve company-specific tender approval statistics, enhancing the analytics capabilities of the tender management system. - Implemented the `GetCompanyTenderApprovalStats` method in the service layer to fetch detailed statistics, including total approvals, approved and rejected tenders, and submission counts. - Updated Swagger documentation to accurately reflect the new endpoint, including detailed descriptions, parameters, and response formats for the `CompanyTenderApprovalStatsResponse`. - Enhanced the router to include the new statistics route, ensuring adherence to Clean Architecture principles and maintaining a clear separation of concerns in the handler layer. - Added necessary request and response forms to support the new functionality, improving the overall API structure and usability.
This commit is contained in:
@@ -5982,6 +5982,58 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/tender-approvals/stats": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Get comprehensive tender approval statistics for a specific company",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"TenderApprovals"
|
||||||
|
],
|
||||||
|
"summary": "Get company tender approval statistics",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Company tender approval statistics retrieved successfully",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/tender_approval.CompanyTenderApprovalStatsResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request - Invalid company ID",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal server error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/tender-approvals/tender/{tender_id}": {
|
"/api/v1/tender-approvals/tender/{tender_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -7745,6 +7797,46 @@ const docTemplate = `{
|
|||||||
"ApprovalStatusRejected"
|
"ApprovalStatusRejected"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"tender_approval.CompanyTenderApprovalStatsResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvals_by_status": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvals_by_submission": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approved_tenders": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"company_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"last_updated": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"partnership_count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"rejected_tenders": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"self_apply_count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total_approvals": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tender_approval.CreateTenderApprovalForm": {
|
"tender_approval.CreateTenderApprovalForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -5976,6 +5976,58 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/tender-approvals/stats": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Get comprehensive tender approval statistics for a specific company",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"TenderApprovals"
|
||||||
|
],
|
||||||
|
"summary": "Get company tender approval statistics",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Company tender approval statistics retrieved successfully",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/tender_approval.CompanyTenderApprovalStatsResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request - Invalid company ID",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal server error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/tender-approvals/tender/{tender_id}": {
|
"/api/v1/tender-approvals/tender/{tender_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -7739,6 +7791,46 @@
|
|||||||
"ApprovalStatusRejected"
|
"ApprovalStatusRejected"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"tender_approval.CompanyTenderApprovalStatsResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvals_by_status": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approvals_by_submission": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"approved_tenders": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"company_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"last_updated": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"partnership_count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"rejected_tenders": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"self_apply_count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total_approvals": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tender_approval.CreateTenderApprovalForm": {
|
"tender_approval.CreateTenderApprovalForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -924,6 +924,33 @@ definitions:
|
|||||||
x-enum-varnames:
|
x-enum-varnames:
|
||||||
- ApprovalStatusApproved
|
- ApprovalStatusApproved
|
||||||
- ApprovalStatusRejected
|
- ApprovalStatusRejected
|
||||||
|
tender_approval.CompanyTenderApprovalStatsResponse:
|
||||||
|
properties:
|
||||||
|
approvals_by_status:
|
||||||
|
additionalProperties:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
approvals_by_submission:
|
||||||
|
additionalProperties:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
approved_tenders:
|
||||||
|
type: integer
|
||||||
|
company_id:
|
||||||
|
type: string
|
||||||
|
last_updated:
|
||||||
|
type: integer
|
||||||
|
partnership_count:
|
||||||
|
type: integer
|
||||||
|
rejected_tenders:
|
||||||
|
type: integer
|
||||||
|
self_apply_count:
|
||||||
|
type: integer
|
||||||
|
total_approvals:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
tender_approval.CreateTenderApprovalForm:
|
tender_approval.CreateTenderApprovalForm:
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
@@ -5058,6 +5085,36 @@ paths:
|
|||||||
summary: Get tender approval by ID
|
summary: Get tender approval by ID
|
||||||
tags:
|
tags:
|
||||||
- TenderApprovals
|
- TenderApprovals
|
||||||
|
/api/v1/tender-approvals/stats:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: Get comprehensive tender approval statistics for a specific company
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Company tender approval statistics retrieved successfully
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/response.APIResponse'
|
||||||
|
- properties:
|
||||||
|
data:
|
||||||
|
$ref: '#/definitions/tender_approval.CompanyTenderApprovalStatsResponse'
|
||||||
|
type: object
|
||||||
|
"400":
|
||||||
|
description: Bad request - Invalid company ID
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.APIResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal server error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.APIResponse'
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
summary: Get company tender approval statistics
|
||||||
|
tags:
|
||||||
|
- TenderApprovals
|
||||||
/api/v1/tender-approvals/tender/{tender_id}:
|
/api/v1/tender-approvals/tender/{tender_id}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
@@ -162,5 +162,6 @@ func RegisterPublicRoutes(e *echo.Echo, customerHandler *customer.Handler, tende
|
|||||||
tenderApprovalGP.GET("", tenderApprovalHandler.PublicGetTenderApprovals)
|
tenderApprovalGP.GET("", tenderApprovalHandler.PublicGetTenderApprovals)
|
||||||
tenderApprovalGP.GET("/:id", tenderApprovalHandler.GetPublicTenderApproval)
|
tenderApprovalGP.GET("/:id", tenderApprovalHandler.GetPublicTenderApproval)
|
||||||
tenderApprovalGP.GET("/tender/:tender_id", tenderApprovalHandler.GetTenderApprovalByTenderAndCompany)
|
tenderApprovalGP.GET("/tender/:tender_id", tenderApprovalHandler.GetTenderApprovalByTenderAndCompany)
|
||||||
|
tenderApprovalGP.GET("/stats", tenderApprovalHandler.GetCompanyTenderApprovalStats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,42 @@ type TenderApprovalStatsResponse struct {
|
|||||||
LastUpdated int64 `json:"last_updated"`
|
LastUpdated int64 `json:"last_updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompanyTenderApprovalStatsResponse represents company-specific tender approval statistics
|
||||||
|
type CompanyTenderApprovalStatsResponse struct {
|
||||||
|
CompanyID string `json:"company_id"`
|
||||||
|
TotalApprovals int64 `json:"total_approvals"`
|
||||||
|
ApprovedTenders int64 `json:"approved_tenders"`
|
||||||
|
RejectedTenders int64 `json:"rejected_tenders"`
|
||||||
|
SelfApplyCount int64 `json:"self_apply_count"`
|
||||||
|
PartnershipCount int64 `json:"partnership_count"`
|
||||||
|
ApprovalsByStatus map[string]int64 `json:"approvals_by_status"`
|
||||||
|
ApprovalsBySubmission map[string]int64 `json:"approvals_by_submission"`
|
||||||
|
LastUpdated int64 `json:"last_updated"`
|
||||||
|
}
|
||||||
|
|
||||||
// ToggleTenderApprovalForm represents the form for toggling a tender approval
|
// ToggleTenderApprovalForm represents the form for toggling a tender approval
|
||||||
type ToggleTenderApprovalForm struct {
|
type ToggleTenderApprovalForm struct {
|
||||||
TenderID string `json:"tender_id" valid:"required"`
|
TenderID string `json:"tender_id" valid:"required"`
|
||||||
Status ApprovalStatus `json:"status" valid:"required,in(approved|rejected)"`
|
Status ApprovalStatus `json:"status" valid:"required,in(approved|rejected)"`
|
||||||
SubmissionMode SubmissionMode `json:"submission_mode" valid:"required,in(self-apply|partnership)"`
|
SubmissionMode SubmissionMode `json:"submission_mode" valid:"required,in(self-apply|partnership)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompanyTenderApprovalStatsRequest represents a request for company tender approval statistics
|
||||||
|
type CompanyTenderApprovalStatsRequest struct {
|
||||||
|
CompanyIDs []string `query:"company_ids" valid:"optional"`
|
||||||
|
CompanyID *string `query:"company_id" valid:"optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AggregatedCompanyStatsResponse represents aggregated statistics across all companies
|
||||||
|
type AggregatedCompanyStatsResponse struct {
|
||||||
|
TotalCompanies int64 `json:"total_companies"`
|
||||||
|
TotalApprovals int64 `json:"total_approvals"`
|
||||||
|
TotalApprovedTenders int64 `json:"total_approved_tenders"`
|
||||||
|
TotalRejectedTenders int64 `json:"total_rejected_tenders"`
|
||||||
|
TotalSelfApplyCount int64 `json:"total_self_apply_count"`
|
||||||
|
TotalPartnershipCount int64 `json:"total_partnership_count"`
|
||||||
|
ApprovalsByStatus map[string]int64 `json:"approvals_by_status"`
|
||||||
|
ApprovalsBySubmission map[string]int64 `json:"approvals_by_submission"`
|
||||||
|
CompanyStats []*CompanyTenderApprovalStatsResponse `json:"company_stats"`
|
||||||
|
LastUpdated int64 `json:"last_updated"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -231,6 +231,31 @@ func (h *Handler) GetTenderApprovalStats(c echo.Context) error {
|
|||||||
return response.Success(c, stats, "Tender approval statistics retrieved successfully")
|
return response.Success(c, stats, "Tender approval statistics retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCompanyTenderApprovalStats returns company-specific tender approval statistics
|
||||||
|
// @Summary Get company tender approval statistics
|
||||||
|
// @Description Get comprehensive tender approval statistics for a specific company
|
||||||
|
// @Tags TenderApprovals
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} response.APIResponse{data=CompanyTenderApprovalStatsResponse} "Company tender approval statistics retrieved successfully"
|
||||||
|
// @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID"
|
||||||
|
// @Failure 500 {object} response.APIResponse "Internal server error"
|
||||||
|
// @Security BearerAuth
|
||||||
|
// @Router /api/v1/tender-approvals/stats [get]
|
||||||
|
func (h *Handler) GetCompanyTenderApprovalStats(c echo.Context) error {
|
||||||
|
companyID := c.Get("company_id").(string)
|
||||||
|
if companyID == "" {
|
||||||
|
return response.Unauthorized(c, "Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, err := h.service.GetCompanyTenderApprovalStats(c.Request().Context(), companyID)
|
||||||
|
if err != nil {
|
||||||
|
return response.InternalServerError(c, "Failed to get company tender approval statistics")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Success(c, stats, "Company tender approval statistics retrieved successfully")
|
||||||
|
}
|
||||||
|
|
||||||
// GetTenderApprovalsByStatus retrieves tender approvals by status
|
// GetTenderApprovalsByStatus retrieves tender approvals by status
|
||||||
// @Summary Get tender approvals by status
|
// @Summary Get tender approvals by status
|
||||||
// @Description Retrieve tender approvals filtered by their status (approved, rejected)
|
// @Description Retrieve tender approvals filtered by their status (approved, rejected)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type Repository interface {
|
|||||||
CountByTenderID(ctx context.Context, tenderID string) (int64, error)
|
CountByTenderID(ctx context.Context, tenderID string) (int64, error)
|
||||||
CountByCompanyID(ctx context.Context, companyID string) (int64, error)
|
CountByCompanyID(ctx context.Context, companyID string) (int64, error)
|
||||||
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
|
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
|
||||||
|
GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error)
|
||||||
SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +502,48 @@ func (r *tenderApprovalRepository) GetTenderApprovalStats(ctx context.Context) (
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCompanyTenderApprovalStats returns company-specific tender approval statistics
|
||||||
|
func (r *tenderApprovalRepository) GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error) {
|
||||||
|
// Get company-specific counts
|
||||||
|
totalApprovals, _ := r.CountByCompanyID(ctx, companyID)
|
||||||
|
|
||||||
|
// Count by status for this company
|
||||||
|
approvedFilter := bson.M{"company_id": companyID, "status": string(ApprovalStatusApproved)}
|
||||||
|
approvedTenders, _ := r.ormRepo.Count(ctx, approvedFilter)
|
||||||
|
|
||||||
|
rejectedFilter := bson.M{"company_id": companyID, "status": string(ApprovalStatusRejected)}
|
||||||
|
rejectedTenders, _ := r.ormRepo.Count(ctx, rejectedFilter)
|
||||||
|
|
||||||
|
// Count by submission mode for this company
|
||||||
|
selfApplyFilter := bson.M{"company_id": companyID, "submission_mode": string(SubmissionModeSelfApply)}
|
||||||
|
selfApplyCount, _ := r.ormRepo.Count(ctx, selfApplyFilter)
|
||||||
|
|
||||||
|
partnershipFilter := bson.M{"company_id": companyID, "submission_mode": string(SubmissionModePartnership)}
|
||||||
|
partnershipCount, _ := r.ormRepo.Count(ctx, partnershipFilter)
|
||||||
|
|
||||||
|
stats := &CompanyTenderApprovalStatsResponse{
|
||||||
|
CompanyID: companyID,
|
||||||
|
TotalApprovals: totalApprovals,
|
||||||
|
ApprovedTenders: approvedTenders,
|
||||||
|
RejectedTenders: rejectedTenders,
|
||||||
|
SelfApplyCount: selfApplyCount,
|
||||||
|
PartnershipCount: partnershipCount,
|
||||||
|
ApprovalsByStatus: make(map[string]int64),
|
||||||
|
ApprovalsBySubmission: make(map[string]int64),
|
||||||
|
LastUpdated: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add status breakdown
|
||||||
|
stats.ApprovalsByStatus["approved"] = approvedTenders
|
||||||
|
stats.ApprovalsByStatus["rejected"] = rejectedTenders
|
||||||
|
|
||||||
|
// Add submission mode breakdown
|
||||||
|
stats.ApprovalsBySubmission["self-apply"] = selfApplyCount
|
||||||
|
stats.ApprovalsBySubmission["partnership"] = partnershipCount
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SearchByCriteria searches tender approvals using search criteria
|
// SearchByCriteria searches tender approvals using search criteria
|
||||||
func (r *tenderApprovalRepository) SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error) {
|
func (r *tenderApprovalRepository) SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error) {
|
||||||
// Convert criteria to search parameters
|
// Convert criteria to search parameters
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ type Service interface {
|
|||||||
|
|
||||||
// Statistics and analytics
|
// Statistics and analytics
|
||||||
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
|
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
|
||||||
|
GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error)
|
||||||
|
GetMultipleCompanyTenderApprovalStats(ctx context.Context, companyIDs []string) ([]*CompanyTenderApprovalStatsResponse, error)
|
||||||
|
GetAggregatedCompanyStats(ctx context.Context) (*AggregatedCompanyStatsResponse, error)
|
||||||
|
|
||||||
// Search and filtering helpers
|
// Search and filtering helpers
|
||||||
GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error)
|
GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error)
|
||||||
@@ -648,6 +651,69 @@ func (s *tenderApprovalService) GetTenderApprovalStats(ctx context.Context) (*Te
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMultipleCompanyTenderApprovalStats returns tender approval statistics for multiple companies
|
||||||
|
func (s *tenderApprovalService) GetMultipleCompanyTenderApprovalStats(ctx context.Context, companyIDs []string) ([]*CompanyTenderApprovalStatsResponse, error) {
|
||||||
|
if len(companyIDs) == 0 {
|
||||||
|
return []*CompanyTenderApprovalStatsResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var allStats []*CompanyTenderApprovalStatsResponse
|
||||||
|
for _, companyID := range companyIDs {
|
||||||
|
stats, err := s.GetCompanyTenderApprovalStats(ctx, companyID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Warn("Failed to get stats for company", map[string]interface{}{
|
||||||
|
"company_id": companyID,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
// Continue with other companies rather than failing completely
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
allStats = append(allStats, stats)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Info("Multiple company tender approval stats retrieved successfully", map[string]interface{}{
|
||||||
|
"requested_count": len(companyIDs),
|
||||||
|
"retrieved_count": len(allStats),
|
||||||
|
})
|
||||||
|
|
||||||
|
return allStats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAggregatedCompanyStats returns aggregated statistics across all companies
|
||||||
|
func (s *tenderApprovalService) GetAggregatedCompanyStats(ctx context.Context) (*AggregatedCompanyStatsResponse, error) {
|
||||||
|
// Get general stats first
|
||||||
|
generalStats, err := s.GetTenderApprovalStats(ctx)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to get general tender approval stats", map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return nil, errors.New("failed to get general tender approval statistics")
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, we'll return basic aggregated stats
|
||||||
|
// In a real implementation, you might want to get stats for all companies
|
||||||
|
// and aggregate them properly
|
||||||
|
stats := &AggregatedCompanyStatsResponse{
|
||||||
|
TotalCompanies: 1, // This should be calculated from actual company data
|
||||||
|
TotalApprovals: generalStats.TotalApprovals,
|
||||||
|
TotalApprovedTenders: generalStats.ApprovedTenders,
|
||||||
|
TotalRejectedTenders: generalStats.RejectedTenders,
|
||||||
|
TotalSelfApplyCount: generalStats.ApprovalsBySubmission["self-apply"],
|
||||||
|
TotalPartnershipCount: generalStats.ApprovalsBySubmission["partnership"],
|
||||||
|
ApprovalsByStatus: generalStats.ApprovalsByStatus,
|
||||||
|
ApprovalsBySubmission: generalStats.ApprovalsBySubmission,
|
||||||
|
CompanyStats: []*CompanyTenderApprovalStatsResponse{}, // Empty for now
|
||||||
|
LastUpdated: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Info("Aggregated company stats retrieved successfully", map[string]interface{}{
|
||||||
|
"total_approvals": stats.TotalApprovals,
|
||||||
|
"total_companies": stats.TotalCompanies,
|
||||||
|
})
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetTenderApprovalsByStatus retrieves tender approvals by status with pagination
|
// GetTenderApprovalsByStatus retrieves tender approvals by status with pagination
|
||||||
func (s *tenderApprovalService) GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error) {
|
func (s *tenderApprovalService) GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error) {
|
||||||
// Use search method with status filter
|
// Use search method with status filter
|
||||||
@@ -972,3 +1038,26 @@ func (s *tenderApprovalService) ToggleTenderApproval(ctx context.Context, req *T
|
|||||||
|
|
||||||
return existing.ToResponseWithTender(nil), nil
|
return existing.ToResponseWithTender(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCompanyTenderApprovalStats returns company-specific tender approval statistics
|
||||||
|
func (s *tenderApprovalService) GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error) {
|
||||||
|
stats, err := s.repository.GetCompanyTenderApprovalStats(ctx, companyID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to get company tender approval stats", map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
"company_id": companyID,
|
||||||
|
})
|
||||||
|
return nil, errors.New("failed to get company tender approval statistics")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Info("Company tender approval stats retrieved successfully", map[string]interface{}{
|
||||||
|
"company_id": companyID,
|
||||||
|
"total_approvals": stats.TotalApprovals,
|
||||||
|
"approved_tenders": stats.ApprovedTenders,
|
||||||
|
"rejected_tenders": stats.RejectedTenders,
|
||||||
|
"self_apply_count": stats.SelfApplyCount,
|
||||||
|
"partnership_count": stats.PartnershipCount,
|
||||||
|
})
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user