package controllers import ( "encoding/json" "log" "net/http" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "gitlab.com/pactual1/backend/database/contract" "gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/shared" ) const ( BlockchainSecretLength = 16 ) func GetLatestContracts(c *gin.Context) { // Existing parameters limitStr := c.DefaultQuery("limit", "50") offsetStr := c.DefaultQuery("offset", "0") status := strings.Split(c.DefaultQuery("status", models.ContractStatusActive), ",") // New/Updated optional parameters companyName := c.Query("company_name") companyAddress := c.Query("company_address") companyEmail := c.Query("company_email") companyPhone := c.Query("company_phone") contractName := c.Query("contract_name") startTimeStr := c.Query("start_time") endTimeStr := c.Query("end_time") deviceIDsStr := c.QueryArray("deviceIDs[]") iDsStr := c.QueryArray("ids[]") company := c.GetInt("companyID") uuid := c.Query("uuid") // Convert limit and offset to int limit, err := strconv.Atoi(limitStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid limit value"}) return } offset, err := strconv.Atoi(offsetStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid offset value"}) return } // Convert startTime to time.Time var startTime time.Time if startTimeStr != "" { startTimeUnix, err := strconv.ParseInt(startTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid start_time value"}) return } startTime = time.Unix(startTimeUnix, 0) } // Convert endTime to time.Time var endTime time.Time if endTimeStr != "" { endTimeUnix, err := strconv.ParseInt(endTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid end_time value"}) return } endTime = time.Unix(endTimeUnix, 0) } // Convert deviceIDs to []int64 var deviceIDs []int64 for _, idStr := range deviceIDsStr { id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid deviceID value"}) return } deviceIDs = append(deviceIDs, id) } // Convert ids to []int64 var contractIDs []int64 for _, idStr := range iDsStr { id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid id value"}) return } contractIDs = append(contractIDs, id) } // Fetch contracts contracts, total, st, err := contract.GetContracts(status, companyName, companyAddress, companyEmail, companyPhone, &startTime, &endTime, contractName, deviceIDs, contractIDs, nil, uuid, company, limit, offset) if err != nil { c.JSON(st, gin.H{"error": err.Error()}) return } // Respond with the contracts and the total count c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToDashboardResponse(contracts)}) } func GetBuyerContracts(c *gin.Context) { // Existing parameters limitStr := c.DefaultQuery("limit", "50") offsetStr := c.DefaultQuery("offset", "0") status := c.QueryArray("status") iDsStr := c.QueryArray("ids[]") qStr := c.Query("q") dateCreatedStr := c.Query("date_created") startTimeStr := c.Query("start_time") endTimeStr := c.Query("end_time") company := c.GetInt("companyID") // Convert limit and offset to int limit, err := strconv.Atoi(limitStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid limit value"}) return } offset, err := strconv.Atoi(offsetStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid offset value"}) return } // Convert startTime to time.Time var startTime *time.Time if startTimeStr != "" { startTimeUnix, err := strconv.ParseInt(startTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid start_time value"}) return } startTimeValue := time.Unix(startTimeUnix, 0) startTime = &startTimeValue } // Convert endTime to time.Time var endTime *time.Time if endTimeStr != "" { endTimeUnix, err := strconv.ParseInt(endTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid end_time value"}) return } endTimeValue := time.Unix(endTimeUnix, 0) endTime = &endTimeValue } // Convert startTime to time.Time var dateCreated time.Time if dateCreatedStr != "" { startTimeUnix, err := strconv.ParseInt(dateCreatedStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid start_time value"}) return } dateCreated = time.Unix(startTimeUnix, 0) } // Convert ids to []int64 var contractIDs []int64 for _, idStr := range iDsStr { id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid id value"}) return } contractIDs = append(contractIDs, id) } // Fetch contracts contracts, total, st, err := contract.GetContracts(status, "", "", "", "", startTime, endTime, qStr, nil, contractIDs, &dateCreated, "", company, limit, offset) if err != nil { c.JSON(st, gin.H{"error": err.Error()}) return } // Respond with the contracts and the total count c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToListResponse(contracts)}) } func GetContractStatuses(c *gin.Context) { // Respond with the contract statuses c.JSON(http.StatusOK, gin.H{"data": models.GetContractStatuses()}) } func CreateContract(c *gin.Context) { var payload models.CreateContractRequestPayload if err := c.ShouldBindJSON(&payload); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"}) log.Printf("Invalid JSON payload: %v", err) return } db := shared.GetDb() newContract := models.Contract{ UUID: uuid.New().String(), BuyerID: payload.BuyerID, SellerID: payload.SellerID, Description: payload.Description, ProductID: payload.ProductID, MinTemp: payload.MinTemp, MaxTemp: payload.MaxTemp, ArrivalDate: time.Unix(payload.ArrivalDate, 0), PenaltyType: payload.PenaltyType, PenaltyValue: payload.PenaltyValue, PenaltyRec: payload.PenaltyRec, StartLat: payload.StartLat, StartLon: payload.StartLon, Status: models.ContractStatusPending, StartPlaceName: payload.StartPlaceName, EndPlaceName: payload.EndPlaceName, Name: payload.Name, EndLat: payload.EndLat, EndLon: payload.EndLon, BlockchainSecret: shared.GenerateRandomString(BlockchainSecretLength), } if err := db.Create(&newContract).Error; err != nil { log.Printf("SaveContractInfo CREATE - Contract DB Error: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create new contract"}) return } log.Printf("Successfully received and saved contract: %v", newContract) c.JSON(http.StatusOK, gin.H{"message": "Successfully received and saved contract", "id": newContract.ID}) } func GetContractByID(c *gin.Context) { // Get the contract ID from url parameters contractIDStr := c.Param("contract_id") if contractIDStr == "" { log.Printf("GetContractByID Error: ID is required") c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"}) return } contractID, err := strconv.ParseUint(contractIDStr, 10, 32) if err != nil { log.Printf("GetContractByID Error: Invalid ID: %v", err) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) return } // Fetch contract contract, st, err := contract.GetContractByID(uint(contractID), "") if err != nil { c.JSON(st, gin.H{"error": err.Error()}) return } // Respond with the contracts and the total count c.JSON(http.StatusOK, gin.H{"data": models.ConvertContractToContractResponse(contract)}) } func UpdateContract(c *gin.Context) { var contractModel models.Contract rawData, _ := c.GetRawData() // Unmarshal to the important info structure err := json.Unmarshal(rawData, &contractModel) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"}) log.Printf("Invalid json pyload : %v", err) return } // Get the contract ID from url parameters contractIDStr := c.Param("contract_id") if contractIDStr == "" { log.Printf("UpdateContract Error: ID is required") c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"}) return } contractID, err := strconv.ParseUint(contractIDStr, 10, 32) if err != nil { log.Printf("UpdateContract Error: Invalid ID: %v", err) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) return } contractModel.ID = uint(contractID) // update contract contractModel, st, err := contract.UpdateContract(contractModel) if err != nil { c.JSON(st, gin.H{"error": err.Error()}) return } // Respond with the contracts and the total count c.JSON(http.StatusOK, gin.H{"data": models.ConvertContractToContractResponse(contractModel)}) } func GetContractCountByStatus(c *gin.Context) { companyID := c.DefaultQuery("company_id", "") startTimeStr := c.DefaultQuery("start_time", "") endTimeStr := c.DefaultQuery("end_time", "") if companyID == "" || startTimeStr == "" || endTimeStr == "" { c.JSON(http.StatusBadRequest, gin.H{ "error": "Missing required query parameters", }) return } // Convert to uint and time.Time companyIDUint, err := strconv.ParseUint(companyID, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid companyID", }) return } // Convert string to Unix timestamp startUnix, err := strconv.ParseInt(startTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid start time", }) return } endUnix, err := strconv.ParseInt(endTimeStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid end time", }) return } // Convert Unix timestamps to time.Time startTime := time.Unix(startUnix, 0) endTime := time.Unix(endUnix, 0) activeCount, executedCount, _, monthly, err := contract.CountContractsByMultipleStatusesAndTotal(uint(companyIDUint), startTime, endTime) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal Server Error", }) return } c.JSON(http.StatusOK, gin.H{"data": models.ActiveContractsResponse{ActiveCount: activeCount, ExecutedCount: executedCount, MonthlyContracts: monthly}}) } func GetTotalContractCount(c *gin.Context) { companyID := c.DefaultQuery("company_id", "0") startTimeStr := c.DefaultQuery("start_time", "") endTimeStr := c.DefaultQuery("end_time", "") // Convert to uint and time.Time companyIDUint, err := strconv.ParseUint(companyID, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid companyID", }) return } // Convert string to Unix timestamp startUnix, _ := strconv.ParseInt(startTimeStr, 10, 64) endUnix, _ := strconv.ParseInt(endTimeStr, 10, 64) // Convert Unix timestamps to time.Time startTime := time.Unix(startUnix, 0) endTime := time.Unix(endUnix, 0) _, _, totalCount, _, err := contract.CountContractsByMultipleStatusesAndTotal(uint(companyIDUint), startTime, endTime) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal Server Error", }) return } c.JSON(http.StatusOK, gin.H{"data": totalCount}) }