diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f03415b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# Builder image +FROM --platform=linux/amd64 golang:1.21 as builder + +WORKDIR /src + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN go build -mod=readonly -v -o pactual-backend main.go + +# Runtime image +FROM --platform=linux/amd64 golang:1.21 + +WORKDIR /app + +COPY --from=builder /src/pactual-backend . +CMD ["/app/pactual-backend"] diff --git a/controllers/buyers_controller.go b/controllers/buyers_controller.go deleted file mode 100644 index d4d8bb3..0000000 --- a/controllers/buyers_controller.go +++ /dev/null @@ -1,60 +0,0 @@ -package controllers - -import ( - "errors" - "log" - "net/http" - "strconv" - - "github.com/gin-gonic/gin" - "github.com/jinzhu/gorm" - "gitlab.com/pactual1/backend/models" - "gitlab.com/pactual1/backend/shared" -) - -func ListBuyers(c *gin.Context) { - // Get limit and offset from query parameter with defaults - limitStr := c.DefaultQuery("limit", "99999999999999999999999999999999") - offsetStr := c.DefaultQuery("offset", "0") - - // Convert limit and offset to int - limit, err := strconv.Atoi(limitStr) - if err != nil { - log.Printf("ListBuyers Error: Invalid limit value: %v", err) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid limit value"}) - return - } - - offset, err := strconv.Atoi(offsetStr) - if err != nil { - log.Printf("ListBuyers Error: Invalid offset value: %v", err) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid offset value"}) - return - } - - // Create a slice to hold the buyers - var buyers []models.Buyer - - // Count the total number of buyers - var total int64 - if err := shared.GetDb().Model(&models.Buyer{}).Count(&total).Error; err != nil { - log.Printf("ListBuyers Error: Database error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) - return - } - - // Fetch the buyers from the database with LIMIT and OFFSET - if err := shared.GetDb().Order("created_at desc").Limit(limit).Offset(offset).Find(&buyers).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - log.Printf("ListBuyers Error: No buyers found: %v", err) - c.JSON(http.StatusNotFound, gin.H{"error": "No buyers found"}) - } else { - log.Printf("ListBuyers Error: Database error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) - } - return - } - - // Respond with the buyers and the total count - c.JSON(http.StatusOK, gin.H{"total": total, "data": buyers}) -} diff --git a/controllers/companies_controller.go b/controllers/companies_controller.go new file mode 100644 index 0000000..d9f3a2f --- /dev/null +++ b/controllers/companies_controller.go @@ -0,0 +1,81 @@ +package controllers + +import ( + "log" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "gitlab.com/pactual1/backend/database/company" +) + +func ListCompanies(c *gin.Context) { + // Get limit and offset from query parameter with defaults + limitStr := c.DefaultQuery("limit", "50") + offsetStr := c.DefaultQuery("offset", "0") + iDsStr := c.QueryArray("ids[]") + + // Convert limit and offset to int + limit, err := strconv.Atoi(limitStr) + if err != nil { + log.Printf("ListCompanies Error: Invalid limit value: %v", err) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid limit value"}) + return + } + + offset, err := strconv.Atoi(offsetStr) + if err != nil { + log.Printf("ListCompanies Error: Invalid offset value: %v", err) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid offset value"}) + return + } + + // Convert ids to []int64 + var companyIDs []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 + } + companyIDs = append(companyIDs, id) + } + + // Fetch companies + companies, total, st, err := company.GetCompanies(companyIDs, limit, offset) + if err != nil { + c.JSON(st, gin.H{"error": err.Error()}) + return + } + + // Respond with the companies and the total count + c.JSON(http.StatusOK, gin.H{"total": total, "data": companies}) +} + +func GetCompanyByID(c *gin.Context) { + // Get the company ID from url parameters + companyIDStr := c.Param("company_id") + + if companyIDStr == "" { + log.Printf("GetCompanyByID Error: ID is required") + c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"}) + return + } + + companyID, err := strconv.ParseUint(companyIDStr, 10, 32) + if err != nil { + log.Printf("GetCompanyByID Error: Invalid ID: %v", err) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) + return + } + + // Fetch company + companies, _, st, err := company.GetCompanies([]int64{int64(companyID)}, 1, 0) + if err != nil { + c.JSON(st, gin.H{"error": err.Error()}) + return + } + + // Respond with the companies and the total count + c.JSON(http.StatusOK, gin.H{"data": companies[0]}) +} diff --git a/controllers/buyers_controller_test.go b/controllers/companies_controller_test.go similarity index 91% rename from controllers/buyers_controller_test.go rename to controllers/companies_controller_test.go index 22481b5..a17ccff 100644 --- a/controllers/buyers_controller_test.go +++ b/controllers/companies_controller_test.go @@ -9,7 +9,7 @@ import ( "gitlab.com/pactual1/backend/shared" ) -func TestListBuyers(t *testing.T) { +func TestListCompanies(t *testing.T) { ts := runTestServer() defer ts.Close() defer shared.CloseDb() diff --git a/controllers/contracts_controller.go b/controllers/contracts_controller.go index dc075c9..2793a7f 100644 --- a/controllers/contracts_controller.go +++ b/controllers/contracts_controller.go @@ -15,10 +15,10 @@ import ( ) 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), ",") + // 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") @@ -29,6 +29,7 @@ func GetLatestContracts(c *gin.Context) { startTimeStr := c.Query("start_time") endTimeStr := c.Query("end_time") deviceIDsStr := c.QueryArray("deviceIDs[]") + iDsStr := c.QueryArray("ids[]") // Convert limit and offset to int limit, err := strconv.Atoi(limitStr) @@ -76,84 +77,119 @@ func GetLatestContracts(c *gin.Context) { deviceIDs = append(deviceIDs, id) } - // Fetch contracts - contracts, total, st, err := contract.GetContracts(status, companyName, companyAddress, companyEmail, companyPhone, &startTime, &endTime, contractName, deviceIDs, 0, nil, limit, offset) - - if err != nil { - c.JSON(st, gin.H{"error": err.Error()}) - return - } + // 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) + } - // Respond with the contracts and the total count - c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToResponse(contracts)}) -} + // Fetch contracts + contracts, total, st, err := contract.GetContracts(status, companyName, companyAddress, companyEmail, companyPhone, &startTime, &endTime, contractName, deviceIDs, contractIDs, nil, limit, offset) - -func GetBuyerContracts(c *gin.Context) { - // Existing parameters - limitStr := c.DefaultQuery("limit", "50") - offsetStr := c.DefaultQuery("offset", "0") - status := strings.Split(c.DefaultQuery("status", models.ContractStatusActive), ",") - - contractIDStr := c.DefaultQuery("contract_id","0") - dateCreatedStr := c.Query("date_created") - - - // 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 limit and offset to int - contractID, err := strconv.Atoi(contractIDStr) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid contractID value"}) - return - } - - // 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) - } - - - - // Fetch contracts - contracts, total, st, err := contract.GetContracts(status, "", "", "", "", nil, nil, "", nil, contractID, &dateCreated, limit, offset) - - if err != nil { - c.JSON(st, gin.H{"error": err.Error()}) - return - } + 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.ConvertContractToResponseModel(contracts)}) + c.JSON(http.StatusOK, gin.H{"total": total, "data": models.ConvertContractToResponse(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[]") + dateCreatedStr := c.Query("date_created") + startTimeStr := c.Query("start_time") + endTimeStr := c.Query("end_time") + + // 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, "", nil, contractIDs, &dateCreated, 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.ConvertContractToResponseModel(contracts)}) } func GetContractStatuses(c *gin.Context) { - // Respond with the contract statuses - c.JSON(http.StatusOK, gin.H{"data": models.GetContractStatuses()}) + // Respond with the contract statuses + c.JSON(http.StatusOK, gin.H{"data": models.GetContractStatuses()}) } func CreateContract(c *gin.Context) { - var payload models.CreateContractRequestPayload - + 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) @@ -163,16 +199,19 @@ func CreateContract(c *gin.Context) { db := shared.GetDb() newContract := models.Contract{ - 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.PenaltyRec, - PenaltyValue : payload.PenaltyValue, - PenaltyRec : payload.PenaltyRec, + 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.PenaltyRec, + PenaltyValue: payload.PenaltyValue, + PenaltyRec: payload.PenaltyRec, + StartLat: payload.StartLat, + StartLon: payload.StartLon, + Status: models.ContractStatusDraft, } if err := db.Create(&newContract).Error; err != nil { @@ -228,7 +267,6 @@ func UpdateContract(c *gin.Context) { // 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"}) @@ -254,4 +292,3 @@ func UpdateContract(c *gin.Context) { // Respond with the contracts and the total count c.JSON(http.StatusOK, gin.H{"data": contractModel}) } - diff --git a/controllers/devices_controller.go b/controllers/devices_controller.go index cb6237c..0e00d9b 100644 --- a/controllers/devices_controller.go +++ b/controllers/devices_controller.go @@ -57,7 +57,7 @@ func SaveDeviceInfo(c *gin.Context) { } else { log.Printf("Current device deleted at: %v", device.DeletedAt) - if device.DeletedAt != nil { + if device.DeletedAt.Valid { // Use raw SQL to update the record if err := shared.GetDb().Exec("UPDATE devices SET deleted_at = NULL, company_id = NULL WHERE id = ?", device.ID).Error; err != nil { log.Printf("UNDELETE -Device DB Error: %v", err) @@ -161,5 +161,5 @@ func GetDevicesByContract(c *gin.Context) { return } // Respond with the devices - c.JSON(http.StatusOK,gin.H{"data" : models.ConvertDeviceToResponse(devices)}) + c.JSON(http.StatusOK, gin.H{"data": models.ConvertDeviceToResponse(devices)}) } diff --git a/controllers/health_controller.go b/controllers/health_controller.go new file mode 100644 index 0000000..b061c2c --- /dev/null +++ b/controllers/health_controller.go @@ -0,0 +1,11 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +func HealthCheck(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"health": "ready"}) +} diff --git a/controllers/invoices_controller.go b/controllers/invoices_controller.go index 9ae8f1c..7269905 100644 --- a/controllers/invoices_controller.go +++ b/controllers/invoices_controller.go @@ -14,6 +14,7 @@ func GetInvoices(c *gin.Context) { offsetStr := c.DefaultQuery("offset", "0") buyerName := c.Query("buyer_name") sortBy := c.Query("sort_by") + iDsStr := c.QueryArray("ids[]") limit, err := strconv.Atoi(limitStr) if err != nil { @@ -27,7 +28,18 @@ func GetInvoices(c *gin.Context) { return } - invoices, total, err := invoice.GetInvoices(buyerName, sortBy, limit, offset, 0) + // Convert ids to []int64 + var invoiceIDs []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 + } + invoiceIDs = append(invoiceIDs, id) + } + + invoices, total, err := invoice.GetInvoices(buyerName, sortBy, limit, offset, invoiceIDs) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return @@ -40,32 +52,30 @@ func GetInvoices(c *gin.Context) { } func GetInvoiceByID(c *gin.Context) { - idStr := c.Param("id") - id, err := strconv.Atoi(idStr) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) - return - } + idStr := c.Param("id") + id, err := strconv.Atoi(idStr) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) + return + } - invoices, _, err := invoice.GetInvoices("", "", 1, 0, uint(id)) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) - return - } + invoices, _, err := invoice.GetInvoices("", "", 1, 0, []int64{int64(id)}) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } invoiceResponses := models.ConvertInvoiceToResponse(invoices) - if len(invoices) > 0 { - c.JSON(http.StatusOK, gin.H{"data": invoiceResponses[0]}) - } else { - c.JSON(http.StatusNotFound, gin.H{"error": "Invoice not found"}) - } + if len(invoices) > 0 { + c.JSON(http.StatusOK, gin.H{"data": invoiceResponses[0]}) + } else { + c.JSON(http.StatusNotFound, gin.H{"error": "Invoice not found"}) + } } - - func convertToResponseModel(invoices []models.Invoice) []models.ListInvoiceResponse { - var listInvoiceResponses []models.ListInvoiceResponse + listInvoiceResponses := []models.ListInvoiceResponse{} // Get all statuses statuses := models.GetInvoiceStatuses() @@ -82,16 +92,14 @@ func convertToResponseModel(invoices []models.Invoice) []models.ListInvoiceRespo } listInvoiceResponse := models.ListInvoiceResponse{ - Status: models.KeyValue{Key: status.Key, Value: status.Value}, - Buyer: models.CompanyShortResponse{ID: int(invoice.BuyerID), Name: invoice.BuyerName}, - ContractID: int(invoice.ContractID), - DateCreated: invoice.InvoiceDate, - DueDate: invoice.InvoiceDueDate, - Amount: strconv.FormatInt(invoice.PriceCents, 10), + Status: models.KeyValue{Key: status.Key, Value: status.Value}, + Buyer: models.CompanyShortResponse{ID: int(invoice.BuyerID), Name: invoice.BuyerName}, + ContractID: int(invoice.ContractID), + DateCreated: invoice.InvoiceDate, + DueDate: invoice.InvoiceDueDate, + Amount: strconv.FormatInt(invoice.PriceCents, 10), } listInvoiceResponses = append(listInvoiceResponses, listInvoiceResponse) } return listInvoiceResponses } - - diff --git a/controllers/product_templates_controller.go b/controllers/product_templates_controller.go index eb3e16c..6e04cd0 100644 --- a/controllers/product_templates_controller.go +++ b/controllers/product_templates_controller.go @@ -15,8 +15,9 @@ import ( func ListProductTemplates(c *gin.Context) { // Get limit and offset from query parameter with defaults - limitStr := c.DefaultQuery("limit", "99999999999999999999999999999999") + limitStr := c.DefaultQuery("limit", "50") offsetStr := c.DefaultQuery("offset", "0") + iDsStr := c.QueryArray("ids[]") // Convert limit and offset to int limit, err := strconv.Atoi(limitStr) @@ -34,18 +35,36 @@ func ListProductTemplates(c *gin.Context) { } // Create a slice to hold the product templates - var productTemplates []models.ProductTemplate + productTemplates := []models.ProductTemplate{} + + // Convert ids to []int64 + var productIDs []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 + } + productIDs = append(productIDs, id) + } + + countDb := shared.GetDb() + db := shared.GetDb() + if len(productIDs) > 0 { + countDb = countDb.Where("id IN (?)", productIDs) + db = db.Where("id IN (?)", productIDs) + } // Count the total number of product templates var total int64 - if err := shared.GetDb().Model(&models.ProductTemplate{}).Count(&total).Error; err != nil { + if err := countDb.Model(&models.ProductTemplate{}).Count(&total).Error; err != nil { log.Printf("ListProductTemplates Error: Database error: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) return } // Fetch the product templates from the database with LIMIT and OFFSET - if err := shared.GetDb().Order("created_at desc").Limit(limit).Offset(offset).Find(&productTemplates).Error; err != nil { + if err := db.Order("created_at desc").Limit(limit).Offset(offset).Find(&productTemplates).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Printf("ListProductTemplates Error: No product templates found: %v", err) c.JSON(http.StatusNotFound, gin.H{"error": "No product templates found"}) diff --git a/controllers/product_templates_controller_test.go b/controllers/product_templates_controller_test.go index 977c4f7..8cf4c31 100644 --- a/controllers/product_templates_controller_test.go +++ b/controllers/product_templates_controller_test.go @@ -15,7 +15,7 @@ func TestListProductTemplates(t *testing.T) { defer shared.CloseDb() t.Run("it should return 200", func(t *testing.T) { - resp, err := http.Get(fmt.Sprintf("%s/product_templates?limit=20", ts.URL)) + resp, err := http.Get(fmt.Sprintf("%s/products?limit=20", ts.URL)) if err != nil { t.Fatalf("Expected no error, got %v", err) diff --git a/controllers/text_templates_controller.go b/controllers/text_templates_controller.go index 4723a45..f0a9aaf 100644 --- a/controllers/text_templates_controller.go +++ b/controllers/text_templates_controller.go @@ -15,8 +15,9 @@ import ( func ListTextTemplates(c *gin.Context) { // Get limit and offset from query parameter with defaults - limitStr := c.DefaultQuery("limit", "99999999999999999999999999999999") + limitStr := c.DefaultQuery("limit", "50") offsetStr := c.DefaultQuery("offset", "0") + iDsStr := c.QueryArray("ids[]") // Convert limit and offset to int limit, err := strconv.Atoi(limitStr) @@ -33,19 +34,36 @@ func ListTextTemplates(c *gin.Context) { return } + // Convert ids to []int64 + var templateIDs []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 + } + templateIDs = append(templateIDs, id) + } + // Create a slice to hold the text templates - var textTemplates []models.TextTemplate + textTemplates := []models.TextTemplate{} // Count the total number of text templates var total int64 - if err := shared.GetDb().Model(&models.TextTemplate{}).Count(&total).Error; err != nil { + countDb := shared.GetDb() + db := shared.GetDb() + if len(templateIDs) > 0 { + countDb = countDb.Where("id IN (?)", templateIDs) + db = db.Where("id IN (?)", templateIDs) + } + if err := countDb.Model(&models.TextTemplate{}).Count(&total).Error; err != nil { log.Printf("ListTextTemplates Error: Database error: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) return } // Fetch the text templates from the database with LIMIT and OFFSET - if err := shared.GetDb().Order("created_at desc").Limit(limit).Offset(offset).Find(&textTemplates).Error; err != nil { + if err := db.Order("created_at desc").Limit(limit).Offset(offset).Find(&textTemplates).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Printf("ListTextTemplates Error: No text templates found: %v", err) c.JSON(http.StatusNotFound, gin.H{"error": "No text templates found"}) @@ -82,4 +100,3 @@ func CreateTextTemplate(c *gin.Context) { log.Printf("Successfully received and saved text template: %v", textTemplate) c.JSON(http.StatusOK, gin.H{"data": textTemplate}) } - diff --git a/controllers/text_templates_controller_test.go b/controllers/text_templates_controller_test.go index 791e1e7..b55a297 100644 --- a/controllers/text_templates_controller_test.go +++ b/controllers/text_templates_controller_test.go @@ -17,7 +17,7 @@ func TestListTextTemplates(t *testing.T) { defer shared.CloseDb() t.Run("it should return 200", func(t *testing.T) { - resp, err := http.Get(fmt.Sprintf("%s/text_templates?limit=20", ts.URL)) + resp, err := http.Get(fmt.Sprintf("%s/templates?limit=20", ts.URL)) if err != nil { t.Fatalf("Expected no error, got %v", err) @@ -39,7 +39,7 @@ func CreateTextTemplate(t *testing.T) { } payload, _ := json.Marshal(data) - resp, err := http.Post(fmt.Sprintf("%s/text_templates/save", ts.URL), "application/json", bytes.NewBuffer(payload)) + resp, err := http.Post(fmt.Sprintf("%s/templates/save", ts.URL), "application/json", bytes.NewBuffer(payload)) if err != nil { t.Fatalf("Expected no error, got %v", err) } diff --git a/database/company/company.go b/database/company/company.go new file mode 100644 index 0000000..cd0843c --- /dev/null +++ b/database/company/company.go @@ -0,0 +1,48 @@ +package company + +import ( + "errors" + "log" + "net/http" + + "github.com/jinzhu/gorm" + "gitlab.com/pactual1/backend/models" + "gitlab.com/pactual1/backend/shared" +) + +func GetCompanies(companyIDs []int64, limit, offset int) ([]models.Company, int64, int, error) { + + companies := []models.Company{} + db := shared.GetDb() + countDb := db + + // Search by IDs + if len(companyIDs) > 0 { + db = db.Where("companies.id IN (?)", companyIDs) + countDb = countDb.Where("companies.id IN (?)", companyIDs) + } + + // Fetch total count of filtered records + var total int64 + if err := countDb.Model(&models.Company{}).Count(&total).Error; err != nil { + log.Printf("GetCompanies Error: Database error: %v", err) + return companies, total, http.StatusInternalServerError, err + } + + // Fetch companies with custom fields + if err := db.Select("*"). + Order("created_at desc"). + Limit(limit). + Offset(offset). + Find(&companies).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Printf("GetCompanies Error: No companies found: %v", err) + return companies, total, http.StatusNotFound, err + } else { + log.Printf("GetCompanies Error: Database error: %v", err) + return companies, total, http.StatusInternalServerError, err + } + } + + return companies, total, http.StatusOK, nil +} diff --git a/database/contract/contract.go b/database/contract/contract.go index e2de180..ca1b898 100644 --- a/database/contract/contract.go +++ b/database/contract/contract.go @@ -12,17 +12,16 @@ import ( "gitlab.com/pactual1/backend/shared" ) - func GetContracts(status []string, companyName string, companyAddress string, companyEmail string, companyPhone string, startTime *time.Time, endTime *time.Time, - contractName string, deviceIDs []int64, contractID int, dateCreated *time.Time, limit, offset int) ([]models.Contract, int64, int, error) { + contractName string, deviceIDs []int64, contractIDs []int64, dateCreated *time.Time, limit, offset int) ([]models.Contract, int64, int, error) { var contracts []models.Contract db := shared.GetDb() countDb := db // Define custom fields to be selected, varies based on joined tables - customFields := "contracts.*, array_length(contracts.device_ids, 1) as number_of_devices" + customFields := "distinct contracts.*, array_length(contracts.device_ids, 1) as number_of_devices" // Search by Statuses if len(status) > 0 { @@ -30,6 +29,12 @@ func GetContracts(status []string, companyName string, companyAddress string, countDb = countDb.Where("contracts.status IN (?)", status) } + // Search by IDs + if len(contractIDs) > 0 { + db = db.Where("contracts.id IN (?)", contractIDs) + countDb = countDb.Where("contracts.id IN (?)", contractIDs) + } + // Search by Company Fields db = db.Joins("left join companies on companies.id = contracts.buyer_id") countDb = countDb.Joins("left join companies on companies.id = contracts.buyer_id") @@ -57,14 +62,8 @@ func GetContracts(status []string, companyName string, companyAddress string, countDb = countDb.Where("contracts.name LIKE ?", "%"+contractName+"%") } - // Search by Contract Name - if contractID != 0{ - db = db.Where("contracts.id = ?", contractID) - countDb = countDb.Where("contracts.id = ?", contractID) - } - // Search by Start Time and End Time - if startTime != nil &&!startTime.IsZero() { + if startTime != nil && !startTime.IsZero() { db = db.Where("start_time >= ?", startTime) countDb = countDb.Where("start_time >= ?", startTime) } @@ -76,10 +75,9 @@ func GetContracts(status []string, companyName string, companyAddress string, if dateCreated != nil && !dateCreated.IsZero() { db = db.Where("contracts.created_at = ?", dateCreated) - countDb = countDb.Where("created_at = ?", dateCreated) + countDb = countDb.Where("contracts.created_at = ?", dateCreated) } - // Search by Device IDs if len(deviceIDs) > 0 { db = db.Where("device_ids && ?", pq.Array(deviceIDs)) @@ -114,7 +112,7 @@ func GetContracts(status []string, companyName string, companyAddress string, func UpdateContract(contract models.Contract) (models.Contract, int, error) { // Update contract - if err := shared.GetDb().Update(contract).Error; err != nil { + if err := shared.GetDb().Model(contract).Updates(contract).Error; err != nil { log.Printf("UpdateContractByID Error: Could not update contract: %v", err) return contract, http.StatusInternalServerError, err } diff --git a/database/invoice/invoice.go b/database/invoice/invoice.go index 6183b31..84bc447 100644 --- a/database/invoice/invoice.go +++ b/database/invoice/invoice.go @@ -8,55 +8,55 @@ import ( "gitlab.com/pactual1/backend/shared" ) -func GetInvoices(buyerName string, sortBy string, limit int, offset int, id uint) ([]models.Invoice, int64, error) { - var invoices []models.Invoice +func GetInvoices(buyerName string, sortBy string, limit int, offset int, ids []int64) ([]models.Invoice, int64, error) { + var invoices []models.Invoice - // Default sort by InvoiceDate DESC - sortField := "invoice_date" - sortOrder := "desc" + // Default sort by InvoiceDate DESC + sortField := "invoice_date" + sortOrder := "desc" - if sortBy == "InvoiceDate" || sortBy == "InvoiceDueDate" { - sortField = strings.ToLower(sortBy) - } + if sortBy == "InvoiceDate" || sortBy == "InvoiceDueDate" { + sortField = strings.ToLower(sortBy) + } - dbOrder := fmt.Sprintf("%s %s", sortField, sortOrder) + dbOrder := fmt.Sprintf("%s %s", sortField, sortOrder) - db := shared.GetDb() - countDb := db + db := shared.GetDb() + countDb := db - if buyerName != "" { - db = db.Where("buyer_name LIKE ?", "%"+buyerName+"%") - countDb = countDb.Where("buyer_name LIKE ?", "%"+buyerName+"%") - } + if buyerName != "" { + db = db.Where("buyer_name LIKE ?", "%"+buyerName+"%") + countDb = countDb.Where("buyer_name LIKE ?", "%"+buyerName+"%") + } - // Added conditional for ID search - if id != 0 { - db = db.Where("id = ?", id) - countDb = countDb.Where("id = ?", id) - } + // Added conditional for ID search + if len(ids) > 0 { + db = db.Where("id in (?)", ids) + countDb = countDb.Where("id in (?)", ids) + } - var total int64 - if err := countDb.Model(&models.Invoice{}).Count(&total).Error; err != nil { - return nil, 0, err - } + var total int64 + if err := countDb.Model(&models.Invoice{}).Count(&total).Error; err != nil { + return nil, 0, err + } - if err := db.Preload("InvoiceItem"). - Order(dbOrder). - Limit(limit). - Offset(offset). - Find(&invoices).Error; err != nil { - return nil, 0, err - } - - for i := range invoices { - var sum int64 - if invoices[i].InvoiceItem != nil { - for _, item := range *invoices[i].InvoiceItem { - sum += item.PriceCents * item.Quantity - } - invoices[i].PriceCents = sum - } - } + if err := db.Preload("InvoiceItem"). + Order(dbOrder). + Limit(limit). + Offset(offset). + Find(&invoices).Error; err != nil { + return nil, 0, err + } - return invoices, total, nil + for i := range invoices { + var sum int64 + if invoices[i].InvoiceItem != nil { + for _, item := range *invoices[i].InvoiceItem { + sum += item.PriceCents * item.Quantity + } + invoices[i].PriceCents = sum + } + } + + return invoices, total, nil } diff --git a/main.go b/main.go index 359fba9..d9be506 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ func main() { // Add User and Device resources Admin.AddResource(&models.User{}) Admin.AddResource(&models.Device{}) - Admin.AddResource(&models.Buyer{}) + Admin.AddResource(&models.Company{}) Admin.AddResource(&models.ProductTemplate{}) // Initialize HTTP request multiplexer mux := http.NewServeMux() diff --git a/models/buyer.go b/models/buyer.go deleted file mode 100644 index 069c0a3..0000000 --- a/models/buyer.go +++ /dev/null @@ -1,18 +0,0 @@ -package models - -import "github.com/jinzhu/gorm" - -type Buyer struct { - gorm.Model - Name string -} - -func (Buyer) Update() (bool, error) { - return false, nil -} -func (Buyer) Create() (bool, error) { - return false, nil -} -func (Buyer) Delete() (bool, error) { - return false, nil -} diff --git a/models/company.go b/models/company.go index 4127862..a861586 100644 --- a/models/company.go +++ b/models/company.go @@ -1,23 +1,24 @@ package models import ( + "database/sql" "time" - - "github.com/jinzhu/gorm" ) type BaseModel struct { - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` - UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` + ID uint `json:"id" gorm:"primaryKey"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt sql.NullTime `json:"deletedAt,omitempty" gorm:"index"` } + type Company struct { - gorm.Model - Name string `json:"name"` - Address string `json:"address"` - Email string `json:"email"` - Phone string `json:"phone"` - Users []User `json:"users"` + BaseModel + Name string `json:"name"` + Address string `json:"address"` + Email string `json:"email"` + Phone string `json:"phone"` + Users []User `json:"users"` Devices []Device `json:"devices"` } @@ -26,7 +27,6 @@ type CompanyShortResponse struct { Name string `json:"name"` } - func (Company) Update() (bool, error) { return false, nil } diff --git a/models/contract.go b/models/contract.go index 45d39de..f20dca4 100644 --- a/models/contract.go +++ b/models/contract.go @@ -3,12 +3,11 @@ package models import ( "time" - "github.com/jinzhu/gorm" "github.com/lib/pq" ) type Contract struct { - gorm.Model + BaseModel Name string `json:"name"` DeviceIDs pq.Int64Array `json:"deviceIds" gorm:"type:integer[]"` BuyerID uint `json:"buyerId"` @@ -64,7 +63,7 @@ type ContractResponse struct { } func ConvertContractToResponse(contracts []Contract) []ContractResponse { - var contractResponses []ContractResponse + contractResponses := []ContractResponse{} for _, contract := range contracts { contractResponse := ContractResponse{ BaseModel: BaseModel{ @@ -102,13 +101,13 @@ func ConvertContractToResponse(contracts []Contract) []ContractResponse { } func ConvertContractToResponseModel(contracts []Contract) []ListContractResponse { - var listInvoiceResponses []ListContractResponse + listInvoiceResponses := []ListContractResponse{} // Get all statuses statuses := GetContractStatuses() statusMap := make(map[string]Status) for _, s := range statuses { - statusMap[s.Value] = s + statusMap[s.Key] = s } for _, contract := range contracts { @@ -171,16 +170,22 @@ type ListContractResponse struct { } type CreateContractRequestPayload struct { - SellerID uint `json:"sellerId" binding:"required"` - BuyerID uint `json:"buyerId" binding:"required"` - Description string `json:"description"` - ProductID uint `json:"productId"` - MinTemp float64 `json:"minTemp" binding:"required"` - MaxTemp float64 `json:"maxTemp" binding:"required"` - ArrivalDate int64 `json:"arrivalDate"` - PenaltyType string `json:"penaltyType"` - PenaltyValue int `json:"penaltyValue"` - PenaltyRec string `json:"penaltyRec"` + SellerID uint `json:"sellerId" binding:"required"` + BuyerID uint `json:"buyerId" binding:"required"` + Description string `json:"description"` + ProductID uint `json:"productId"` + MinTemp float64 `json:"minTemp" binding:"required"` + MaxTemp float64 `json:"maxTemp" binding:"required"` + ArrivalDate int64 `json:"arrivalDate"` + PenaltyType string `json:"penaltyType"` + PenaltyValue int `json:"penaltyValue"` + PenaltyRec string `json:"penaltyRec"` + StartPlaceName string `json:"startPlaceName"` + StartLat float64 `json:"startLat"` + StartLon float64 `json:"startLon"` + EndPlaceName string `json:"endPlaceName"` + EndLat float64 `json:"endLat"` + EndLon float64 `json:"endLon"` } func (Contract) Update() (bool, error) { diff --git a/models/contract_info.go b/models/contract_info.go index 718eb05..e6b648b 100644 --- a/models/contract_info.go +++ b/models/contract_info.go @@ -1,9 +1,7 @@ package models -import "github.com/jinzhu/gorm" - type ContractInfo struct { - gorm.Model + BaseModel RawJSON string `json:"raw_json" gorm:"type:json"` } diff --git a/models/device.go b/models/device.go index ba25a37..3a32a56 100644 --- a/models/device.go +++ b/models/device.go @@ -4,26 +4,25 @@ import ( "github.com/jinzhu/gorm" ) - type Device struct { - gorm.Model - DeviceID string `json:"deviceId"` - DeviceName string `json:"deviceName"` - IMEI string `json:"imei"` - IMSI string `json:"imsi"` - DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"` - CompanyID uint `json:"companyId"` + BaseModel + DeviceID string `json:"deviceId"` + DeviceName string `json:"deviceName"` + IMEI string `json:"imei"` + IMSI string `json:"imsi"` + DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"` + CompanyID uint `json:"companyId"` DeviceInfos *[]DeviceInfo `json:"deviceInfos"` } type DeviceResponse struct { BaseModel - DeviceID string `json:"deviceId"` - DeviceName string `json:"deviceName"` - IMEI string `json:"imei"` - IMSI string `json:"imsi"` - DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"` - CompanyID uint `json:"companyId"` + DeviceID string `json:"deviceId"` + DeviceName string `json:"deviceName"` + IMEI string `json:"imei"` + IMSI string `json:"imsi"` + DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"` + CompanyID uint `json:"companyId"` DeviceInfos *[]DeviceInfo `json:"deviceInfos"` } @@ -69,4 +68,3 @@ func (d *Device) Delete(db *gorm.DB) (bool, error) { return true, nil } - diff --git a/models/device_info.go b/models/device_info.go index e4a0fcc..1b82677 100644 --- a/models/device_info.go +++ b/models/device_info.go @@ -1,9 +1,5 @@ package models -import ( - "github.com/jinzhu/gorm" -) - // Location holds latitude and longitude. type Location struct { Lat float64 `json:"lat"` @@ -12,32 +8,31 @@ type Location struct { // ImportantInfo holds fields that are important for quick access. type SensorData struct { - IMEI string `json:"imei"` - IMSI string `json:"imsi"` - Timestamp int64 `json:"timestamp"` - Lat float64 `json:"lat"` - Lon float64 `json:"lon"` - WifiLoc Location `json:"wifiLocation"` - CellLoc Location `json:"cellLocation"` - Temperature float64 `json:"temperature"` - AccInfo AccelerometerInfo `json:"accelerometerInfo"` + IMEI string `json:"imei"` + IMSI string `json:"imsi"` + Timestamp int64 `json:"timestamp"` + Lat float64 `json:"lat"` + Lon float64 `json:"lon"` + WifiLoc Location `json:"wifiLocation"` + CellLoc Location `json:"cellLocation"` + Temperature float64 `json:"temperature"` + AccInfo AccelerometerInfo `json:"accelerometerInfo"` AccelerometerInfo } type DeviceInfo struct { - gorm.Model + BaseModel RawJSON string `json:"raw_json" gorm:"type:json"` SensorData - DeviceID uint + DeviceID uint ExternalDeviceID string `json:"deviceId"` } - type DeviceInfoResponse struct { BaseModel RawJSON string `json:"rawJson" gorm:"type:json"` SensorData - DeviceID uint `json:"deviceId"` + DeviceID uint `json:"deviceId"` ExternalDeviceID string `json:"externalDeviceId"` } @@ -51,7 +46,7 @@ func ConvertDeviceInfoToResponse(deviceInfos []DeviceInfo) []DeviceInfoResponse UpdatedAt: deviceInfo.UpdatedAt, }, RawJSON: deviceInfo.RawJSON, - SensorData: deviceInfo.SensorData, + SensorData: deviceInfo.SensorData, DeviceID: deviceInfo.DeviceID, ExternalDeviceID: deviceInfo.ExternalDeviceID, } @@ -71,10 +66,10 @@ type GeoJSONFeatureCollection struct { } type GeoJSONFeature struct { - Type string `json:"type"` - Geometry GeoJSONGeometry `json:"geometry"` - DeviceInfoResponse *DeviceInfoResponse `json:"deviceInfo,omitempty"` - Properties map[string]interface{} `json:"properties"` + Type string `json:"type"` + Geometry GeoJSONGeometry `json:"geometry"` + DeviceInfoResponse *DeviceInfoResponse `json:"deviceInfo,omitempty"` + Properties map[string]interface{} `json:"properties"` } type GeoJSONGeometry struct { @@ -91,6 +86,3 @@ func (DeviceInfo) Create() (bool, error) { func (DeviceInfo) Delete() (bool, error) { return false, nil } - - - diff --git a/models/invoice.go b/models/invoice.go index ba7f7f4..1ad7d98 100644 --- a/models/invoice.go +++ b/models/invoice.go @@ -3,68 +3,62 @@ package models import ( "database/sql" "time" - - "github.com/jinzhu/gorm" ) type Invoice struct { - gorm.Model - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` - BuyerID uint `json:"buyerId"` - BuyerName string `json:"buyerName"` - BuyerAddress string `json:"buyerAddress"` - BuyerEmail string `json:"buyerEmail"` - BuyerPhone string `json:"buyerPhone"` - SellerID uint `json:"sellerId"` - SellerName string `json:"sellerName"` - SellerAddress string `json:"sellerAddress"` - SellerEmail string `json:"sellerEmail"` - SellerPhone string `json:"sellerPhone"` - PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` - Discount int64 `json:"discount"` - Tax int64 `json:"tax"` - TermsAndConditions string `json:"termsAndConditions"` - InvoiceName string `json:"invoiceName"` - InvoiceDate time.Time `json:"invoiceDate"` - InvoiceDueDate time.Time `json:"invoiceDueDate"` - ContractID uint `json:"contractId"` + BaseModel + BuyerID uint `json:"buyerId"` + BuyerName string `json:"buyerName"` + BuyerAddress string `json:"buyerAddress"` + BuyerEmail string `json:"buyerEmail"` + BuyerPhone string `json:"buyerPhone"` + SellerID uint `json:"sellerId"` + SellerName string `json:"sellerName"` + SellerAddress string `json:"sellerAddress"` + SellerEmail string `json:"sellerEmail"` + SellerPhone string `json:"sellerPhone"` + PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` + Discount int64 `json:"discount"` + Tax int64 `json:"tax"` + TermsAndConditions string `json:"termsAndConditions"` + InvoiceName string `json:"invoiceName"` + InvoiceDate time.Time `json:"invoiceDate"` + InvoiceDueDate time.Time `json:"invoiceDueDate"` + ContractID uint `json:"contractId"` InvoiceItem *[]InvoiceItem `json:"invoiceItem"` - Status string `json:"status"` + Status string `json:"status"` } type InvoiceResponse struct { BaseModel - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` - BuyerID uint `json:"buyerId"` - BuyerName string `json:"buyerName"` - BuyerAddress string `json:"buyerAddress"` - BuyerEmail string `json:"buyerEmail"` - BuyerPhone string `json:"buyerPhone"` - SellerID uint `json:"sellerId"` - SellerName string `json:"sellerName"` - SellerAddress string `json:"sellerAddress"` - SellerEmail string `json:"sellerEmail"` - SellerPhone string `json:"sellerPhone"` - PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` - Discount int64 `json:"discount"` - Tax int64 `json:"tax"` - TermsAndConditions string `json:"termsAndConditions"` - InvoiceName string `json:"invoiceName"` - InvoiceDate time.Time `json:"invoiceDate"` - InvoiceDueDate time.Time `json:"invoiceDueDate"` - ContractID uint `json:"contractId"` + ID uint `json:"id" gorm:"primaryKey"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` + BuyerID uint `json:"buyerId"` + BuyerName string `json:"buyerName"` + BuyerAddress string `json:"buyerAddress"` + BuyerEmail string `json:"buyerEmail"` + BuyerPhone string `json:"buyerPhone"` + SellerID uint `json:"sellerId"` + SellerName string `json:"sellerName"` + SellerAddress string `json:"sellerAddress"` + SellerEmail string `json:"sellerEmail"` + SellerPhone string `json:"sellerPhone"` + PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` + Discount int64 `json:"discount"` + Tax int64 `json:"tax"` + TermsAndConditions string `json:"termsAndConditions"` + InvoiceName string `json:"invoiceName"` + InvoiceDate time.Time `json:"invoiceDate"` + InvoiceDueDate time.Time `json:"invoiceDueDate"` + ContractID uint `json:"contractId"` InvoiceItem *[]InvoiceItem `json:"invoiceItem"` - Status string `json:"status"` + Status string `json:"status"` } func ConvertInvoiceToResponse(invoices []Invoice) []InvoiceResponse { - var invoiceResponses []InvoiceResponse + invoiceResponses := []InvoiceResponse{} for _, invoice := range invoices { if invoice.InvoiceItem == nil { emptySlice := make([]InvoiceItem, 0) @@ -95,7 +89,7 @@ func ConvertInvoiceToResponse(invoices []Invoice) []InvoiceResponse { InvoiceDate: invoice.InvoiceDate, InvoiceDueDate: invoice.InvoiceDueDate, ContractID: invoice.ContractID, - InvoiceItem: invoice.InvoiceItem, + InvoiceItem: invoice.InvoiceItem, Status: invoice.Status, } invoiceResponses = append(invoiceResponses, invoiceResponse) @@ -103,23 +97,19 @@ func ConvertInvoiceToResponse(invoices []Invoice) []InvoiceResponse { return invoiceResponses } - - type ListInvoiceResponse struct { - Status KeyValue `json:"status"` - Buyer CompanyShortResponse `json:"buyer"` - ContractID int `json:"contractId"` - DateCreated time.Time `json:"dateCreated"` - DueDate time.Time `json:"dueDate"` - Amount string `json:"amount"` + Status KeyValue `json:"status"` + Buyer CompanyShortResponse `json:"buyer"` + ContractID int `json:"contractId"` + DateCreated time.Time `json:"dateCreated"` + DueDate time.Time `json:"dueDate"` + Amount string `json:"amount"` } type KeyValue struct { Key string `json:"key"` Value string `json:"value"` } - - func GetInvoiceStatuses() []Status { return []Status{ {Key: "Insurance claimed", Value: "insurance_claimed"}, diff --git a/models/invoice_item.go b/models/invoice_item.go index 76079ae..e095dca 100644 --- a/models/invoice_item.go +++ b/models/invoice_item.go @@ -3,34 +3,28 @@ package models import ( "database/sql" "time" - - "github.com/jinzhu/gorm" ) type InvoiceItem struct { - gorm.Model - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` - Description string `json:"description"` - Quantity int64 `json:"quantity"` - Unit string `json:"unit"` - PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` - InvoiceID uint `json:"invoiceId"` + BaseModel + Description string `json:"description"` + Quantity int64 `json:"quantity"` + Unit string `json:"unit"` + PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` + InvoiceID uint `json:"invoiceId"` } type InvoiceItemResponse struct { BaseModel - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` - Description string `json:"description"` - Quantity int64 `json:"quantity"` - Unit string `json:"unit"` - PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` - InvoiceID uint `json:"invoiceId"` + ID uint `json:"id" gorm:"primaryKey"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` + Description string `json:"description"` + Quantity int64 `json:"quantity"` + Unit string `json:"unit"` + PriceCents int64 `json:"priceCents" gorm:"column:price_cents"` + InvoiceID uint `json:"invoiceId"` } // ConvertSliceOfInvoiceItemToResponse converts a slice of InvoiceItem models to a slice of InvoiceItemResponse models @@ -54,9 +48,6 @@ func ConvertInvoiceItemToResponse(items []InvoiceItem) []InvoiceItemResponse { return itemResponses } - - - func (InvoiceItem) Update() (bool, error) { return false, nil } @@ -66,4 +57,3 @@ func (InvoiceItem) Create() (bool, error) { func (InvoiceItem) Delete() (bool, error) { return false, nil } - diff --git a/models/product_template.go b/models/product_template.go index 28c9519..d28f405 100644 --- a/models/product_template.go +++ b/models/product_template.go @@ -1,12 +1,8 @@ package models -import ( - "github.com/jinzhu/gorm" -) - type ProductTemplate struct { - gorm.Model - Name string + BaseModel + Name string `json:"name"` ProductTemplateConfig map[string]interface{} `json:",omitempty" sql:"-"` Config string `json:"raw_config" gorm:"type:json"` } diff --git a/models/text_template.go b/models/text_template.go index 4d3722c..04ab2a4 100644 --- a/models/text_template.go +++ b/models/text_template.go @@ -1,10 +1,9 @@ package models -import "github.com/jinzhu/gorm" - type TextTemplate struct { - gorm.Model - Value string + BaseModel + Name string `json:"name"` + Value string `json:"value"` } func (TextTemplate) Update() (bool, error) { diff --git a/models/user.go b/models/user.go index 2375d5a..ef04325 100644 --- a/models/user.go +++ b/models/user.go @@ -1,18 +1,7 @@ package models -import ( - "database/sql" - "time" - - "github.com/jinzhu/gorm" -) - type User struct { - gorm.Model - ID uint `json:"id" gorm:"primaryKey"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt sql.NullTime `json:"deletedAt" gorm:"index"` + BaseModel Username string `json:"username"` Password string `json:"password"` Email string `json:"email"` diff --git a/routes/public_routes.go b/routes/public_routes.go index d26201e..153792d 100644 --- a/routes/public_routes.go +++ b/routes/public_routes.go @@ -8,6 +8,9 @@ import ( func RegisterPublicRoutes(r *gin.Engine) { + // Health checks + r.GET("/health", controllers.HealthCheck) + // Map dashboard r.GET("/dashboard/map/contract/devices", controllers.GetDevicesByContract) r.GET("/dashboard/map/contracts", controllers.GetLatestContracts) @@ -15,14 +18,14 @@ func RegisterPublicRoutes(r *gin.Engine) { // Invoices r.GET("/invoices", controllers.GetInvoices) - r.GET("/invoice/:id", controllers.GetInvoiceByID) + r.GET("/invoices/:id", controllers.GetInvoiceByID) r.POST("/device_data/save", controllers.SaveDeviceInfo) - r.GET("/buyers/", controllers.ListBuyers) - r.GET("/product_templates/", controllers.ListProductTemplates) - r.GET("/text_templates/", controllers.ListTextTemplates) - r.POST("/text_templates/save", controllers.CreateTextTemplate) - r.GET("/product_templates/:template_id", controllers.GetProductTemplate) + r.GET("/buyers", controllers.ListCompanies) + r.GET("/products", controllers.ListProductTemplates) + r.GET("/templates", controllers.ListTextTemplates) + r.POST("/templates/save", controllers.CreateTextTemplate) + r.GET("/products/:template_id", controllers.GetProductTemplate) // Contracts r.GET("/contracts/statuses", controllers.GetContractStatuses) diff --git a/shared/database.go b/shared/database.go index fbe907b..98f3ca8 100644 --- a/shared/database.go +++ b/shared/database.go @@ -32,7 +32,7 @@ func Init() error { } //TODO AUTOMIGRATE models once we have them db.AutoMigrate(&models.User{}, &models.Company{}, &models.Device{}, &models.DeviceInfo{}, - &models.Contract{}, &models.ContractInfo{}, &models.Buyer{}, + &models.Contract{}, &models.ContractInfo{}, &models.ProductTemplate{}, &models.TextTemplate{}, &models.Invoice{}, &models.InvoiceItem{} ) return nil