adding without connection and without towers
This commit is contained in:
parent
9456477767
commit
0f034cc332
|
|
@ -12,6 +12,7 @@ import (
|
|||
"users_management/m/config"
|
||||
"users_management/m/middleware"
|
||||
"users_management/m/model/dto/req"
|
||||
"users_management/m/model/dto/res"
|
||||
"users_management/m/usecase"
|
||||
"users_management/m/utils/common"
|
||||
|
||||
|
|
@ -53,10 +54,108 @@ func (c *DeviceDetailsController) Route() {
|
|||
|
||||
// delete images by filename
|
||||
deviceDetails.DELETE("/:id/images/:filename", c.deleteDeviceImage)
|
||||
deviceDetails.GET("/without-towers", c.getDevicesWithoutTowers)
|
||||
|
||||
deviceDetails.GET("/without-connections", c.getDevicesWithoutConnections)
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (c *DeviceDetailsController) getDevicesWithoutConnections(ctx *gin.Context) {
|
||||
// Get device types from query parameters (optional)
|
||||
deviceTypesParam := ctx.Query("device_types")
|
||||
var deviceTypes []string
|
||||
|
||||
if deviceTypesParam != "" {
|
||||
// Split by comma if multiple types provided
|
||||
deviceTypes = strings.Split(deviceTypesParam, ",")
|
||||
// Trim whitespace and normalize case
|
||||
for i, dt := range deviceTypes {
|
||||
trimmed := strings.TrimSpace(dt)
|
||||
if strings.ToUpper(trimmed) == "OTB" {
|
||||
deviceTypes[i] = "OTB"
|
||||
} else if strings.ToLower(trimmed) == "closure" {
|
||||
deviceTypes[i] = "closure"
|
||||
} else {
|
||||
deviceTypes[i] = trimmed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
devices, err := c.deviceDetailsUC.GetDevicesWithoutConnections(deviceTypes)
|
||||
if err != nil {
|
||||
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Categorize devices by type for better response structure
|
||||
closureDevices := make([]res.DeviceDetailsResponse, 0)
|
||||
otbDevices := make([]res.DeviceDetailsResponse, 0)
|
||||
|
||||
for _, device := range devices {
|
||||
if device.DeviceType == "closure" {
|
||||
closureDevices = append(closureDevices, device)
|
||||
} else if device.DeviceType == "OTB" {
|
||||
otbDevices = append(otbDevices, device)
|
||||
}
|
||||
}
|
||||
|
||||
response := gin.H{
|
||||
"devices": devices,
|
||||
"total": len(devices),
|
||||
"breakdown": gin.H{
|
||||
"closure": gin.H{
|
||||
"count": len(closureDevices),
|
||||
"devices": closureDevices,
|
||||
},
|
||||
"otb": gin.H{
|
||||
"count": len(otbDevices),
|
||||
"devices": otbDevices,
|
||||
},
|
||||
},
|
||||
"filter": gin.H{
|
||||
"device_types": deviceTypes,
|
||||
"criteria": "without_fishbones_and_backbones",
|
||||
},
|
||||
}
|
||||
|
||||
common.SingleResponses(ctx, "Devices without connections retrieved successfully", response)
|
||||
}
|
||||
func (c *DeviceDetailsController) getDevicesWithoutTowers(ctx *gin.Context) {
|
||||
// Get device types from query parameters (optional)
|
||||
deviceTypesParam := ctx.Query("device_types")
|
||||
var deviceTypes []string
|
||||
|
||||
if deviceTypesParam != "" {
|
||||
// Split by comma if multiple types provided
|
||||
deviceTypes = strings.Split(deviceTypesParam, ",")
|
||||
// Trim whitespace
|
||||
for i, dt := range deviceTypes {
|
||||
deviceTypes[i] = strings.TrimSpace(strings.ToUpper(dt))
|
||||
}
|
||||
}
|
||||
|
||||
devices, err := c.deviceDetailsUC.GetDevicesWithoutTowers(deviceTypes)
|
||||
if err != nil {
|
||||
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response := gin.H{
|
||||
"devices": devices,
|
||||
"total": len(devices),
|
||||
"filter": gin.H{
|
||||
"device_types": deviceTypes,
|
||||
"without_towers": true,
|
||||
},
|
||||
}
|
||||
|
||||
common.SingleResponses(ctx, "Devices without towers retrieved successfully", response)
|
||||
}
|
||||
|
||||
func (c *DeviceDetailsController) deleteDeviceImage(ctx *gin.Context) {
|
||||
// Parse device ID
|
||||
id := ctx.Param("id")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ type BackboneResponse struct {
|
|||
BackboneCode string `json:"backbone_code"`
|
||||
DevStart string `json:"dev_start"`
|
||||
DevEnd string `json:"dev_end"`
|
||||
DeviceStartID uuid.UUID `json:"device_start_id"`
|
||||
DeviceEndID uuid.UUID `json:"device_end_id"`
|
||||
CoreAmount int `json:"core_amount"`
|
||||
TotalFishbone int `json:"total_fishbone"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ type DeviceDetailsRepo interface {
|
|||
UpdateCustomerByPort(deviceID uuid.UUID, update req.UpdateCustomerByPortDTO) error
|
||||
BulkUpdateCustomersByPort(deviceID uuid.UUID, updates []req.UpdateCustomerByPortDTO) error
|
||||
RemoveCustomerByPort(deviceID uuid.UUID, portNumber int) error
|
||||
GetDevicesWithoutTowers(deviceTypes []string) ([]entity.DeviceDetails, error)
|
||||
GetDevicesWithoutConnections(deviceTypes []string) ([]entity.DeviceDetails, error)
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -51,6 +53,34 @@ func NewDeviceDetailsRepo(db *gorm.DB) DeviceDetailsRepo {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *deviceDetailsRepo) GetDevicesWithoutConnections(deviceTypes []string) ([]entity.DeviceDetails, error) {
|
||||
var devices []entity.DeviceDetails
|
||||
|
||||
query := r.db.Preload("DevicePort")
|
||||
|
||||
// Filter by device types
|
||||
if len(deviceTypes) > 0 {
|
||||
query = query.Where("device_type IN ?", deviceTypes)
|
||||
}
|
||||
|
||||
// For closure devices: exclude those that have fishbones (as start device)
|
||||
// For OTB devices: exclude those that have backbones (as start or end device) or fishbones (as end device)
|
||||
subQueryBackbone := r.db.Table("backbone").
|
||||
Select("DISTINCT CASE WHEN dev_start_id IS NOT NULL THEN dev_start_id ELSE dev_end_id END as device_id").
|
||||
Where("dev_start_id IS NOT NULL OR dev_end_id IS NOT NULL")
|
||||
|
||||
subQueryFishbone := r.db.Table("fishbone").
|
||||
Select("DISTINCT CASE WHEN dev_start_id IS NOT NULL THEN dev_start_id ELSE dev_end_id END as device_id").
|
||||
Where("dev_start_id IS NOT NULL OR dev_end_id IS NOT NULL")
|
||||
|
||||
// Combine both subqueries to exclude devices that have any connections
|
||||
query = query.Where("id NOT IN (?)",
|
||||
r.db.Raw("(?) UNION (?)", subQueryBackbone, subQueryFishbone))
|
||||
|
||||
err := query.Find(&devices).Error
|
||||
return devices, err
|
||||
}
|
||||
|
||||
func (r *deviceDetailsRepo) UpdateCustomerByPort(deviceID uuid.UUID, update req.UpdateCustomerByPortDTO) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// Lock both device and device_port records
|
||||
|
|
@ -426,6 +456,21 @@ func (r *deviceDetailsRepo) Update(id uuid.UUID, updates map[string]interface{})
|
|||
})
|
||||
}
|
||||
|
||||
func (r *deviceDetailsRepo) GetDevicesWithoutTowers(deviceTypes []string) ([]entity.DeviceDetails, error) {
|
||||
var devices []entity.DeviceDetails
|
||||
|
||||
query := r.db.
|
||||
Preload("DevicePort").
|
||||
Where("device_type IN ?", deviceTypes).
|
||||
Where("id NOT IN (?)",
|
||||
r.db.Table("towers").
|
||||
Select("dev_id").
|
||||
Where("dev_id IS NOT NULL"))
|
||||
|
||||
err := query.Find(&devices).Error
|
||||
return devices, err
|
||||
}
|
||||
|
||||
func (r *deviceDetailsRepo) updatePortAmountCascade(tx *gorm.DB, deviceID uuid.UUID, newPortAmount int) error {
|
||||
// Get current port usage
|
||||
var devicePort entity.DevicePort
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ type DeviceDetailsUseCase interface {
|
|||
RemoveCustomerByPort(deviceID uuid.UUID, portNumber int) error
|
||||
UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error
|
||||
DeleteDeviceImage(deviceID uuid.UUID, filename string) error
|
||||
GetDevicesWithoutTowers(deviceTypes []string) ([]res.DeviceDetailsResponse, error)
|
||||
GetDevicesWithoutConnections(deviceTypes []string) ([]res.DeviceDetailsResponse, error)
|
||||
}
|
||||
|
||||
type deviceDetailsUseCase struct {
|
||||
|
|
@ -52,6 +54,33 @@ func NewDeviceDetailsUseCase(deviceDetailsRepo repository.DeviceDetailsRepo, geo
|
|||
}
|
||||
}
|
||||
|
||||
func (u *deviceDetailsUseCase) GetDevicesWithoutConnections(deviceTypes []string) ([]res.DeviceDetailsResponse, error) {
|
||||
// Validate device types
|
||||
validTypes := map[string]bool{"closure": true, "OTB": true}
|
||||
for _, deviceType := range deviceTypes {
|
||||
if !validTypes[deviceType] {
|
||||
return nil, fmt.Errorf("invalid device type: %s. Only closure and OTB are allowed", deviceType)
|
||||
}
|
||||
}
|
||||
|
||||
// If no device types provided, default to closure and OTB
|
||||
if len(deviceTypes) == 0 {
|
||||
deviceTypes = []string{"closure", "OTB"}
|
||||
}
|
||||
|
||||
devices, err := u.deviceDetailsRepo.GetDevicesWithoutConnections(deviceTypes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responses, err := helper.ConvertToDeviceDetailsResponses(devices, u.geocoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (u *deviceDetailsUseCase) DeleteDeviceImage(deviceID uuid.UUID, filename string) error {
|
||||
// Get current device
|
||||
currentDevice, err := u.deviceDetailsRepo.GetByID(deviceID)
|
||||
|
|
@ -118,6 +147,33 @@ func (u *deviceDetailsUseCase) DeleteDeviceImage(deviceID uuid.UUID, filename st
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *deviceDetailsUseCase) GetDevicesWithoutTowers(deviceTypes []string) ([]res.DeviceDetailsResponse, error) {
|
||||
// Validate device types
|
||||
validTypes := map[string]bool{"ODP": true, "OTB": true}
|
||||
for _, deviceType := range deviceTypes {
|
||||
if !validTypes[deviceType] {
|
||||
return nil, fmt.Errorf("invalid device type: %s. Only ODP and OTB are allowed", deviceType)
|
||||
}
|
||||
}
|
||||
|
||||
// If no device types provided, default to ODP and OTB
|
||||
if len(deviceTypes) == 0 {
|
||||
deviceTypes = []string{"ODP", "OTB"}
|
||||
}
|
||||
|
||||
devices, err := u.deviceDetailsRepo.GetDevicesWithoutTowers(deviceTypes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responses, err := helper.ConvertToDeviceDetailsResponses(devices, u.geocoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (u *deviceDetailsUseCase) UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error {
|
||||
err := u.validate.Struct(deviceDTO)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package usecase
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"users_management/m/model/dto/req"
|
||||
"users_management/m/model/dto/res"
|
||||
|
|
@ -78,11 +79,11 @@ func (u *fishboneUseCase) CreateFishbone(fishbone req.FishboneDTO) error {
|
|||
}
|
||||
|
||||
// Validate device types
|
||||
if startDevice.DeviceType != "CLOSURE" || startDevice.DeviceType != "closure" {
|
||||
if strings.ToLower(string(startDevice.DeviceType)) != "closure" {
|
||||
return fmt.Errorf("start device must be of type closure, got %s", startDevice.DeviceType)
|
||||
}
|
||||
|
||||
if endDevice.DeviceType != "ODP" {
|
||||
if strings.ToUpper(string(endDevice.DeviceType)) != "ODP" {
|
||||
return fmt.Errorf("end device must be of type ODP, got %s", endDevice.DeviceType)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ func ConvertToBackboneResponses(backbone []entity.Backbone, totalFishbone map[uu
|
|||
BackboneCode: backbone.BackboneCode,
|
||||
DevStart: backbone.DeviceStart.DeviceCode,
|
||||
DevEnd: backbone.DeviceEnd.DeviceCode,
|
||||
DeviceStartID: backbone.DeviceStart.ID,
|
||||
DeviceEndID: backbone.DeviceEnd.ID,
|
||||
CoreAmount: backbone.CoreAmount,
|
||||
TotalFishbone: count,
|
||||
CreatedAt: backbone.CreatedAt,
|
||||
|
|
@ -35,6 +37,8 @@ func ConvertToBackboneRespId(backbone entity.Backbone, fishboneCount int) (res.B
|
|||
ID: backbone.ID,
|
||||
DevStart: backbone.DeviceStart.DeviceCode,
|
||||
DevEnd: backbone.DeviceEnd.DeviceCode,
|
||||
DeviceStartID: backbone.DeviceStart.ID,
|
||||
DeviceEndID: backbone.DeviceEnd.ID,
|
||||
CoreAmount: backbone.CoreAmount,
|
||||
TotalFishbone: fishboneCount,
|
||||
CreatedAt: backbone.CreatedAt,
|
||||
|
|
|
|||
Loading…
Reference in New Issue