NAM-APJATEL-BACKEND/repository/device_details.go

254 lines
8.6 KiB
Go

package repository
import (
"errors"
"users_management/m/model/entity"
"github.com/google/uuid"
"gorm.io/gorm"
)
type DeviceDetailsRepo interface {
Create(device entity.Device) error
GetAll() ([]entity.DeviceDetails, error)
GetByID(id uuid.UUID) (entity.DeviceDetails, error)
Update(id uuid.UUID, updates map[string]interface{}) error
Delete(id uuid.UUID) error
// Port management
UpdateDevicePortUsage(deviceID uuid.UUID) error
ValidatePortAvailability(deviceID uuid.UUID, requiredPorts int) error
// Connection management
GetBackbonesByDeviceID(deviceID uuid.UUID) ([]entity.Backbone, error)
GetFishbonesByDeviceID(deviceID uuid.UUID) ([]entity.Fishbone, error)
GetTowersByDeviceID(deviceID uuid.UUID) ([]entity.Tower, error)
// Validation helpers
CheckDeviceExists(deviceID uuid.UUID) (bool, error)
GetPortUsageByDevice(deviceID uuid.UUID) (portUsed, portAvailable int, err error)
}
type deviceDetailsRepo struct {
db *gorm.DB
}
func NewDeviceDetailsRepo(db *gorm.DB) DeviceDetailsRepo {
return &deviceDetailsRepo{
db: db,
}
}
func (r *deviceDetailsRepo) Create(device entity.Device) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// Create device
if err := tx.Create(&device).Error; err != nil {
return err
}
// Create corresponding device port
devicePort := entity.DevicePort{
ID: uuid.New(),
DeviceID: device.ID,
PortUsed: 0,
PortAvailable: device.PortAmount,
CreatedAt: device.CreatedAt,
UpdatedAt: device.UpdatedAt,
}
return tx.Create(&devicePort).Error
})
}
func (r *deviceDetailsRepo) GetAll() ([]entity.DeviceDetails, error) {
var devices []entity.DeviceDetails
err := r.db.
Preload("DevicePort").
Preload("BackbonesStart").
Preload("BackbonesStart.DeviceStart").
Preload("BackbonesStart.DeviceEnd").
Preload("BackbonesEnd").
Preload("BackbonesEnd.DeviceStart").
Preload("BackbonesEnd.DeviceEnd").
Preload("FishbonesStart").
Preload("FishbonesStart.DeviceStart").
Preload("FishbonesStart.DeviceEnd").
Preload("FishbonesStart.Backbone").
Preload("FishbonesEnd").
Preload("FishbonesEnd.DeviceStart").
Preload("FishbonesEnd.DeviceEnd").
Preload("FishbonesEnd.Backbone").
Preload("Towers").
Find(&devices).Error
return devices, err
}
func (r *deviceDetailsRepo) GetByID(id uuid.UUID) (entity.DeviceDetails, error) {
var device entity.DeviceDetails
err := r.db.
Preload("DevicePort").
Preload("BackbonesStart").
Preload("BackbonesStart.DeviceStart").
Preload("BackbonesStart.DeviceEnd").
Preload("BackbonesEnd").
Preload("BackbonesEnd.DeviceStart").
Preload("BackbonesEnd.DeviceEnd").
Preload("FishbonesStart").
Preload("FishbonesStart.DeviceStart").
Preload("FishbonesStart.DeviceEnd").
Preload("FishbonesStart.Backbone").
Preload("FishbonesEnd").
Preload("FishbonesEnd.DeviceStart").
Preload("FishbonesEnd.DeviceEnd").
Preload("FishbonesEnd.Backbone").
Preload("Towers").
Where("id = ?", id).
First(&device).Error
return device, err
}
func (r *deviceDetailsRepo) Update(id uuid.UUID, updates map[string]interface{}) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// Update device
if err := tx.Model(&entity.Device{}).Where("id = ?", id).Updates(updates).Error; err != nil {
return err
}
// If port_amount is updated, update device_port
if portAmount, exists := updates["port_amount"]; exists {
if err := r.updatePortAmountCascade(tx, id, portAmount.(int)); err != nil {
return err
}
}
return nil
})
}
func (r *deviceDetailsRepo) updatePortAmountCascade(tx *gorm.DB, deviceID uuid.UUID, newPortAmount int) error {
// Get current port usage
var devicePort entity.DevicePort
if err := tx.Where("device_id = ?", deviceID).First(&devicePort).Error; err != nil {
return err
}
// Check if new port amount is sufficient for current usage
if newPortAmount < devicePort.PortUsed {
return errors.New("cannot reduce port amount below current usage")
}
// Update port available
newPortAvailable := newPortAmount - devicePort.PortUsed
return tx.Model(&entity.DevicePort{}).
Where("device_id = ?", deviceID).
Updates(map[string]interface{}{
"port_available": newPortAvailable,
"updated_at": gorm.Expr("NOW()"),
}).Error
}
func (r *deviceDetailsRepo) UpdateDevicePortUsage(deviceID uuid.UUID) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// Get device info
var device entity.Device
if err := tx.Where("id = ?", deviceID).First(&device).Error; err != nil {
return err
}
var portUsed int
if device.DeviceType == "OTB" {
// For OTB: count backbones (each backbone uses 1 port)
var backboneCount int64
if err := tx.Model(&entity.Backbone{}).
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Count(&backboneCount).Error; err != nil {
return err
}
portUsed = int(backboneCount)
} else if device.DeviceType == "ODP" {
// For ODP: sum fishbone core amounts (each core uses 1 port)
var totalCores int64
if err := tx.Model(&entity.Fishbone{}).
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Select("COALESCE(SUM(core_amount), 0)").
Scan(&totalCores).Error; err != nil {
return err
}
portUsed = int(totalCores)
}
portAvailable := device.PortAmount - portUsed
return tx.Model(&entity.DevicePort{}).
Where("device_id = ?", deviceID).
Updates(map[string]interface{}{
"port_used": portUsed,
"port_available": portAvailable,
"updated_at": gorm.Expr("NOW()"),
}).Error
})
}
func (r *deviceDetailsRepo) ValidatePortAvailability(deviceID uuid.UUID, requiredPorts int) error {
var devicePort entity.DevicePort
if err := r.db.Where("device_id = ?", deviceID).First(&devicePort).Error; err != nil {
return err
}
if devicePort.PortAvailable < requiredPorts {
return errors.New("insufficient available ports")
}
return nil
}
func (r *deviceDetailsRepo) GetBackbonesByDeviceID(deviceID uuid.UUID) ([]entity.Backbone, error) {
var backbones []entity.Backbone
err := r.db.Preload("DeviceStart").Preload("DeviceEnd").
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Find(&backbones).Error
return backbones, err
}
func (r *deviceDetailsRepo) GetFishbonesByDeviceID(deviceID uuid.UUID) ([]entity.Fishbone, error) {
var fishbones []entity.Fishbone
err := r.db.Preload("Backbone").Preload("DeviceStart").Preload("DeviceEnd").
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Find(&fishbones).Error
return fishbones, err
}
func (r *deviceDetailsRepo) GetTowersByDeviceID(deviceID uuid.UUID) ([]entity.Tower, error) {
var towers []entity.Tower
err := r.db.Where("dev_id = ?", deviceID).Find(&towers).Error
return towers, err
}
func (r *deviceDetailsRepo) CheckDeviceExists(deviceID uuid.UUID) (bool, error) {
var count int64
err := r.db.Model(&entity.Device{}).Where("id = ?", deviceID).Count(&count).Error
return count > 0, err
}
func (r *deviceDetailsRepo) GetPortUsageByDevice(deviceID uuid.UUID) (portUsed, portAvailable int, err error) {
var devicePort entity.DevicePort
err = r.db.Where("device_id = ?", deviceID).First(&devicePort).Error
if err != nil {
return 0, 0, err
}
return devicePort.PortUsed, devicePort.PortAvailable, nil
}
func (r *deviceDetailsRepo) Delete(id uuid.UUID) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// Delete device port first
if err := tx.Where("device_id = ?", id).Delete(&entity.DevicePort{}).Error; err != nil {
return err
}
// Delete device
return tx.Delete(&entity.Device{}, id).Error
})
}