From 533451f39d71c42def1079196c95dfcd3e4016e4 Mon Sep 17 00:00:00 2001 From: Senad Uka Date: Mon, 16 Oct 2023 05:44:09 +0200 Subject: [PATCH] Upstream sync --- database/contract/contract.go | 62 +++++++++++++++++++++++--- database/device/device.go | 83 +++++++++++++++++------------------ models/device.go | 1 + 3 files changed, 99 insertions(+), 47 deletions(-) diff --git a/database/contract/contract.go b/database/contract/contract.go index ca1b898..368fb2c 100644 --- a/database/contract/contract.go +++ b/database/contract/contract.go @@ -2,12 +2,14 @@ package contract import ( "errors" + "fmt" "log" "net/http" "time" "github.com/jinzhu/gorm" "github.com/lib/pq" + "gitlab.com/pactual1/backend/database/device" "gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/shared" ) @@ -110,26 +112,76 @@ func GetContracts(status []string, companyName string, companyAddress string, } func UpdateContract(contract models.Contract) (models.Contract, int, error) { + var devices []models.Device + var status int + var err error + if contract.DeviceIDs != nil { + devices, status, err = device.GetDevicesByID(contract.DeviceIDs) + if err != nil { + return contract, status, err + } - // Update contract - if err := shared.GetDb().Model(contract).Updates(contract).Error; err != nil { - log.Printf("UpdateContractByID Error: Could not update contract: %v", err) + status, err = validateContractDevices(contract.ID, devices) + if err != nil { + log.Printf("UpdateContract Error: Invalid Device ID: %v", err) + return contract, status, err + } + } + + err = shared.GetDb().Transaction(func(tx *gorm.DB) error { + // Update contract + if err := tx.Model(contract).Updates(contract).Error; err != nil { + log.Printf("UpdateContract Error: Could not update contract: %v", err) + return err + } + + if devices != nil { + // Update devices + if err := tx.Model(models.Device{}).Where("id IN (?)", contract.DeviceIDs).Updates(models.Device{CurrentContractID: &contract.ID}).Error; err != nil { + log.Printf("UpdateContract Error: Could not update devices: %v", err) + return err + } + } + + // return nil will commit the whole transaction + return nil + }) + if err != nil { + log.Printf("UpdateContract Error: Could not update contract: %v", err) return contract, http.StatusInternalServerError, err } return GetContractByID(uint64(contract.ID)) +} +func validateContractDevices(contractID uint, devices []models.Device) (int, error) { + + for _, device := range devices { + if device.CurrentContractID != nil && *device.CurrentContractID != contractID { + currentDeviceContract, status, err := GetContractByID(uint64(*device.CurrentContractID)) + if err != nil { + return status, err + } + + if currentDeviceContract.Status != models.ContractStatusExecuted && + currentDeviceContract.Status == models.ContractStatusRevoked { + return http.StatusBadRequest, fmt.Errorf("device id %d is linked to contract id - %d name %s", device.ID, currentDeviceContract.ID, currentDeviceContract.Name) + } + } + } + + return http.StatusOK, nil } func GetContractByID(contractID uint64) (models.Contract, int, error) { // Fetch the contract creation date based on contractID var contract models.Contract - if err := shared.GetDb().Where("id = ?", contractID).First(&contract).Error; err != nil { + if err := shared.GetDb().Unscoped().Where("id = ?", contractID).First(&contract).Error; err != nil { log.Printf("GetContractByID Error: Could not fetch contract: %v", err) return contract, http.StatusInternalServerError, err } return contract, http.StatusOK, nil -} \ No newline at end of file +} diff --git a/database/device/device.go b/database/device/device.go index e0d250b..fe1d1d4 100644 --- a/database/device/device.go +++ b/database/device/device.go @@ -13,28 +13,29 @@ import ( "gitlab.com/pactual1/backend/shared" ) - -func GetDevicesForContract(contractID uint64) ([]models.Device , int, error) { - - // Create a slice to hold the devices - var devices []models.Device +func GetDevicesForContract(contractID uint64) ([]models.Device, int, error) { // Fetch the contract from the database var contract models.Contract if err := shared.GetDb().Where("id = ?", contractID).First(&contract).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Printf("GetDevicesByContract Error: No contract found: %v", err) - return devices, http.StatusNotFound ,err + return nil, http.StatusNotFound, err } else { log.Printf("GetDevicesByContract Error: Database error: %v", err) - return devices, http.StatusInternalServerError, err + return nil, http.StatusInternalServerError, err } } log.Printf("This is the device IDS ID: %v", contract.DeviceIDs) + return GetDevicesByID(contract.DeviceIDs) +} +func GetDevicesByID(deviceIDs []int64) ([]models.Device, int, error) { + // Create a slice to hold the devices + var devices []models.Device // Convert the integer array to a comma-separated string idStrings := []string{} - for _, id := range contract.DeviceIDs { + for _, id := range deviceIDs { idStrings = append(idStrings, strconv.FormatInt(id, 10)) } idStr := strings.Join(idStrings, ",") @@ -50,53 +51,51 @@ func GetDevicesForContract(contractID uint64) ([]models.Device , int, error) { return devices, http.StatusNotFound, err } else { log.Printf("GetDevicesByContract Error: Database error: %v", err) - return devices, http.StatusInternalServerError, err + return devices, http.StatusInternalServerError, err } } - return devices , http.StatusOK, nil + return devices, http.StatusOK, nil } -func GetDeviceInfoForContract (deviceID uint64, contract models.Contract) (models.GeoJSONFeatureCollection , int, error) { +func GetDeviceInfoForContract(deviceID uint64, contract models.Contract) (models.GeoJSONFeatureCollection, int, error) { var deviceInfos []models.DeviceInfo - // Create a GeoJSON feature collection - var featureCollection models.GeoJSONFeatureCollection - featureCollection.Type = "FeatureCollection" - featureCollection.Features = []models.GeoJSONFeature{} + // Create a GeoJSON feature collection + var featureCollection models.GeoJSONFeatureCollection + featureCollection.Type = "FeatureCollection" + featureCollection.Features = []models.GeoJSONFeature{} + // Modify your query to include filtering based on the contract's creation date + query := shared.GetDb().Where("device_id = ?", deviceID).Where("created_at >= ? AND created_at <= ?", contract.StartTime, contract.EndTime) - // Modify your query to include filtering based on the contract's creation date - query := shared.GetDb().Where("device_id = ?", deviceID).Where("created_at >= ? AND created_at <= ?", contract.StartTime,contract.EndTime) - - if err := query.Find(&deviceInfos).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - log.Printf("GetDeviceData Error: No device info found: %v", err) + if err := query.Find(&deviceInfos).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Printf("GetDeviceData Error: No device info found: %v", err) return featureCollection, http.StatusNotFound, err - } else { - log.Printf("GetDeviceData Error: Database error: %v", err) + } else { + log.Printf("GetDeviceData Error: Database error: %v", err) return featureCollection, http.StatusNotFound, err - } - } + } + } deviceInfosResponse := models.ConvertDeviceInfoToResponse(deviceInfos) - // Loop through each deviceInfo to create GeoJSON features - for _, info := range deviceInfosResponse { - info.RawJSON = "" - feature := models.GeoJSONFeature{ - Type: "Feature", - DeviceInfoResponse: &info, - Geometry: models.GeoJSONGeometry{ - Type: "Point", - Coordinates: []float64{info.Lon, info.Lat}, - }, - Properties: map[string]interface{}{}, - } - featureCollection.Features = append(featureCollection.Features, feature) - } + // Loop through each deviceInfo to create GeoJSON features + for _, info := range deviceInfosResponse { + info.RawJSON = "" + feature := models.GeoJSONFeature{ + Type: "Feature", + DeviceInfoResponse: &info, + Geometry: models.GeoJSONGeometry{ + Type: "Point", + Coordinates: []float64{info.Lon, info.Lat}, + }, + Properties: map[string]interface{}{}, + } + featureCollection.Features = append(featureCollection.Features, feature) + } - return featureCollection , 0, nil + return featureCollection, 0, nil - -} \ No newline at end of file +} diff --git a/models/device.go b/models/device.go index 3a32a56..24ea6be 100644 --- a/models/device.go +++ b/models/device.go @@ -13,6 +13,7 @@ type Device struct { DeviceConfiguration string `json:"deviceConfiguration" gorm:"type:json"` CompanyID uint `json:"companyId"` DeviceInfos *[]DeviceInfo `json:"deviceInfos"` + CurrentContractID *uint `json:"currentContractId"` } type DeviceResponse struct {