fix: port assignment bulk update
This commit is contained in:
parent
689505fa6a
commit
0c25a3a941
|
|
@ -64,8 +64,6 @@ func (s *Server) setupController() {
|
|||
publicRegistration.POST("/register", controller.NewUserRegistrationController(s.ucManager.NewUserUsecase(), rg).RegisterUser)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add user registration controller (public endpoints)
|
||||
// controller.NewUserRegistrationController(s.ucManager.NewUserUsecase(), rg).Route()
|
||||
|
||||
|
|
@ -96,8 +94,6 @@ func (s *Server) setupController() {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (s *Server) Run() {
|
||||
s.setupController()
|
||||
if err := s.engine.Run(s.host); err != nil {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ type infraManager struct {
|
|||
func (im *infraManager) openConn() error {
|
||||
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s TimeZone=Asia/Shanghai",
|
||||
im.cfg.DBHost, im.cfg.DBUser, im.cfg.DBPass, im.cfg.DBName, im.cfg.DBPort)
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
|
||||
// Configure GORM to disable foreign key constraint during migration
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -41,13 +45,13 @@ func (im *infraManager) autoMigrate(db *gorm.DB) error {
|
|||
&entity.Role{},
|
||||
&entity.User{},
|
||||
&entity.Device{},
|
||||
&entity.Tower{},
|
||||
&entity.OLT{},
|
||||
&entity.DevicePort{},
|
||||
&entity.Backbone{},
|
||||
&entity.Fishbone{},
|
||||
&entity.Tower{},
|
||||
&entity.DevicePort{},
|
||||
&entity.CountAssets{},
|
||||
&entity.ActivityLog{},
|
||||
&entity.OLT{},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package middleware
|
|||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
|
@ -14,13 +15,13 @@ func CORSMiddleware() gin.HandlerFunc {
|
|||
allowedOrigins := []string{
|
||||
"http://localhost:3000",
|
||||
"http://localhost:3001",
|
||||
"http://localhost:5173", // Vite development server
|
||||
"http://127.0.0.1:3000",
|
||||
"http://127.0.0.1:5173",
|
||||
"http://103.110.8.103:80",// Add production URL
|
||||
"http://103.110.8.103:80", // Add production URL
|
||||
"http://103.110.8.103",
|
||||
|
||||
"http://nam.winteraccess.id",
|
||||
|
||||
"https://nam.winteraccess.id",
|
||||
}
|
||||
|
||||
// Check if origin is in allowed list
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ type UpdateDeviceDetailsDTO struct {
|
|||
type AssignMultipleCustomersDTO struct {
|
||||
CustomerName string `json:"customer_name" binding:"required"`
|
||||
PortNumber *int `json:"port_number,omitempty"`
|
||||
IsOccupied *bool `json:"is_occupied,omitempty"`
|
||||
Status *entity.PortStatus `json:"status,omitempty"` // Add status field
|
||||
Bandwidth *string `json:"bandwidth,omitempty"` // Add bandwidth field
|
||||
}
|
||||
|
|
@ -46,6 +47,7 @@ type AssignMultipleCustomersDTO struct {
|
|||
type UpdateCustomerByPortDTO struct {
|
||||
PortNumber int `json:"port_number,omitempty"`
|
||||
NewCustomerName *string `json:"new_customer_name,omitempty"`
|
||||
IsOccupied *bool `json:"is_occupied,omitempty"`
|
||||
Status *entity.PortStatus `json:"status,omitempty"` // Add status field
|
||||
Bandwidth *string `json:"bandwidth,omitempty"` // Add bandwidth field
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ type UpdateDevicePort struct {
|
|||
PortNumber *int `json:"port_number,omitempty" validate:"omitempty,min=1"`
|
||||
}
|
||||
|
||||
|
||||
type AssignCustomerToPortDTO struct {
|
||||
CustomerName string `json:"customer_name" binding:"required"`
|
||||
PortNumber *int `json:"port_number,omitempty"` // Optional, will auto-assign if not provided
|
||||
|
|
@ -31,6 +30,7 @@ type UpdatePortUsageDTO struct {
|
|||
type PortAssignmentDTO struct {
|
||||
PortNumber int `json:"port_number" binding:"required,min=1"`
|
||||
CustomerName *string `json:"customer_name,omitempty"`
|
||||
IsOccupied *bool `json:"is_occupied,omitempty"`
|
||||
Status *entity.PortStatus `json:"status,omitempty" validate:"omitempty,portstatus"`
|
||||
Bandwidth *string `json:"bandwidth,omitempty" validate:"omitempty,min=1"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ func (s *StringSlice) Scan(value interface{}) error {
|
|||
type PortAssignment struct {
|
||||
PortNumber int `json:"port_number"`
|
||||
CustomerName *string `json:"customer_name"` // Nullable for empty ports
|
||||
IsOccupied bool `json:"is_occupied"` // Explicitly store occupation status
|
||||
Status PortStatus `json:"status"` // Add status field
|
||||
Bandwidth *string `json:"bandwidth"` // Add bandwidth field (nullable)
|
||||
}
|
||||
|
|
@ -222,23 +223,39 @@ func (dp *DevicePort) GetPortAssignmentsWithDetails() []PortAssignmentResponse {
|
|||
|
||||
// Sort to get them in order
|
||||
sort.Ints(portsWithCustomers)
|
||||
|
||||
// Step 3: Determine occupied ports
|
||||
// Step 3: Determine occupied ports - USE EXPLICIT IsOccupied FIELD
|
||||
occupiedPorts := make(map[int]bool)
|
||||
|
||||
// All ports with customers are occupied
|
||||
for _, portNum := range portsWithCustomers {
|
||||
occupiedPorts[portNum] = true
|
||||
// For modern approach: use the explicitly stored IsOccupied field
|
||||
for portNum, assignment := range portMap {
|
||||
// Use the explicitly stored IsOccupied value
|
||||
// If not set, fallback to checking customer name presence
|
||||
isOccupied := assignment.IsOccupied
|
||||
if !isOccupied && assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
isOccupied = true
|
||||
}
|
||||
|
||||
// Fill remaining slots to reach port_used
|
||||
occupiedCount := len(portsWithCustomers)
|
||||
if occupiedCount < dp.PortUsed {
|
||||
// Need to occupy more ports (ports without customer names but still occupied)
|
||||
for i := 1; i <= maxPort && occupiedCount < dp.PortUsed; i++ {
|
||||
occupiedPorts[portNum] = isOccupied
|
||||
}
|
||||
|
||||
// Legacy fallback: if we don't have enough explicit port assignments,
|
||||
// use the old logic only for ports that don't have explicit assignment data
|
||||
currentOccupiedCount := 0
|
||||
for _, isOccupied := range occupiedPorts {
|
||||
if isOccupied {
|
||||
currentOccupiedCount++
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply legacy logic if we have fewer occupied ports than port_used
|
||||
// and only for ports that don't have explicit assignment data
|
||||
if currentOccupiedCount < dp.PortUsed {
|
||||
for i := 1; i <= maxPort && currentOccupiedCount < dp.PortUsed; i++ {
|
||||
if _, hasExplicitData := portMap[i]; !hasExplicitData {
|
||||
if !occupiedPorts[i] {
|
||||
occupiedPorts[i] = true
|
||||
occupiedCount++
|
||||
currentOccupiedCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -253,8 +270,10 @@ func (dp *DevicePort) GetPortAssignmentsWithDetails() []PortAssignmentResponse {
|
|||
customerName = assignment.CustomerName
|
||||
status = assignment.Status
|
||||
bandwidth = assignment.Bandwidth
|
||||
} else if occupiedPorts[i] {
|
||||
// Port is occupied but no assignment data - use defaults
|
||||
}
|
||||
|
||||
// Override status for legacy occupied ports (those without explicit assignment)
|
||||
if occupiedPorts[i] && portMap[i] == nil {
|
||||
status = PortStatusOn
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ type DeviceDetailsRepo interface {
|
|||
GetDevicesWithoutConnections(deviceTypes []string) ([]entity.DeviceDetails, error)
|
||||
ValidateTowerExists(towerID uuid.UUID) (bool, error)
|
||||
SyncTowerLocationWithDevice(deviceID uuid.UUID) error
|
||||
|
||||
|
||||
}
|
||||
|
||||
type deviceDetailsRepo struct {
|
||||
|
|
@ -152,6 +150,7 @@ func (r *deviceDetailsRepo) UpdateCustomerByPort(deviceID uuid.UUID, update req.
|
|||
devicePort.PortAssignments[i] = entity.PortAssignment{
|
||||
PortNumber: i + 1,
|
||||
CustomerName: nil,
|
||||
IsOccupied: false,
|
||||
Status: entity.PortStatusOff,
|
||||
Bandwidth: nil,
|
||||
}
|
||||
|
|
@ -165,7 +164,16 @@ func (r *deviceDetailsRepo) UpdateCustomerByPort(deviceID uuid.UUID, update req.
|
|||
|
||||
portIndex := update.PortNumber - 1
|
||||
|
||||
// If assigning a new customer name
|
||||
// Determine if port should be occupied
|
||||
isOccupied := false
|
||||
if update.IsOccupied != nil {
|
||||
isOccupied = *update.IsOccupied
|
||||
} else if update.NewCustomerName != nil {
|
||||
// If not specified, determine based on customer name
|
||||
isOccupied = *update.NewCustomerName != ""
|
||||
}
|
||||
|
||||
// If assigning a new customer name and the customer name is provided
|
||||
if update.NewCustomerName != nil && *update.NewCustomerName != "" {
|
||||
// Check if customer name already exists on another port
|
||||
for i, assignment := range devicePort.PortAssignments {
|
||||
|
|
@ -175,26 +183,35 @@ func (r *deviceDetailsRepo) UpdateCustomerByPort(deviceID uuid.UUID, update req.
|
|||
}
|
||||
}
|
||||
|
||||
if update.NewCustomerName == nil {
|
||||
// Remove customer from port
|
||||
devicePort.PortAssignments[portIndex].CustomerName = nil
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOff
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = nil
|
||||
} else {
|
||||
// Assign/update customer on port
|
||||
// Update customer name
|
||||
if update.NewCustomerName != nil {
|
||||
devicePort.PortAssignments[portIndex].CustomerName = update.NewCustomerName
|
||||
}
|
||||
|
||||
// Update status if provided, otherwise default to "on"
|
||||
// Explicitly set the IsOccupied field
|
||||
devicePort.PortAssignments[portIndex].IsOccupied = isOccupied
|
||||
|
||||
// Update status (independent of occupation)
|
||||
if update.Status != nil {
|
||||
devicePort.PortAssignments[portIndex].Status = *update.Status
|
||||
} else {
|
||||
} else if isOccupied {
|
||||
// Only set default status if not provided and port is occupied
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOn
|
||||
} else {
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOff
|
||||
}
|
||||
|
||||
// Update bandwidth if provided
|
||||
// Update bandwidth
|
||||
if update.Bandwidth != nil {
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = update.Bandwidth
|
||||
} else if !isOccupied {
|
||||
// Clear bandwidth when port is not occupied
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = nil
|
||||
}
|
||||
|
||||
// If explicitly marked as not occupied, clear customer name
|
||||
if update.IsOccupied != nil && !*update.IsOccupied {
|
||||
devicePort.PortAssignments[portIndex].CustomerName = nil
|
||||
}
|
||||
|
||||
// Update counters and backward compatibility fields
|
||||
|
|
@ -269,57 +286,64 @@ func (r *deviceDetailsRepo) BulkUpdateCustomersByPort(deviceID uuid.UUID, update
|
|||
}
|
||||
}
|
||||
|
||||
// Apply all updates - FIX: Include Status and Bandwidth updates
|
||||
// Apply all updates - Include Status, Bandwidth and IsOccupied updates
|
||||
highestOccupiedPort := 0
|
||||
for _, update := range updates {
|
||||
portIndex := update.PortNumber - 1
|
||||
|
||||
// Update customer name
|
||||
devicePort.PortAssignments[portIndex].CustomerName = update.NewCustomerName
|
||||
|
||||
// Update status if provided
|
||||
// Determine if port should be occupied
|
||||
isOccupied := false
|
||||
if update.IsOccupied != nil {
|
||||
isOccupied = *update.IsOccupied
|
||||
} else {
|
||||
// If not specified, determine based on customer name
|
||||
isOccupied = update.NewCustomerName != nil && *update.NewCustomerName != ""
|
||||
}
|
||||
|
||||
// Explicitly set the IsOccupied field
|
||||
devicePort.PortAssignments[portIndex].IsOccupied = isOccupied
|
||||
|
||||
// Update status (independent of occupation)
|
||||
if update.Status != nil {
|
||||
devicePort.PortAssignments[portIndex].Status = *update.Status
|
||||
} else {
|
||||
// Set default status based on customer assignment
|
||||
if update.NewCustomerName != nil && *update.NewCustomerName != "" {
|
||||
} else if isOccupied {
|
||||
// Only set default status if not provided and port is occupied
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOn
|
||||
} else {
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOff
|
||||
}
|
||||
}
|
||||
|
||||
// Update bandwidth if provided
|
||||
if update.Bandwidth != nil {
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = update.Bandwidth
|
||||
} else if update.NewCustomerName == nil || *update.NewCustomerName == "" {
|
||||
// Clear bandwidth when removing customer
|
||||
} else if !isOccupied {
|
||||
// Clear bandwidth when port is not occupied
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = nil
|
||||
}
|
||||
|
||||
// Track highest occupied port
|
||||
if isOccupied && update.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = update.PortNumber
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate port_used based on actual assignments
|
||||
highestUsedPort := 0
|
||||
customerCount := 0
|
||||
|
||||
// Recalculate port_used based on occupied ports (not just customer count)
|
||||
if highestOccupiedPort == 0 {
|
||||
// No explicitly occupied ports from updates, check existing assignments
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
customerCount++
|
||||
if assignment.PortNumber > highestUsedPort {
|
||||
highestUsedPort = assignment.PortNumber
|
||||
if assignment.IsOccupied {
|
||||
if assignment.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = assignment.PortNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update port_used to reflect actual usage
|
||||
if customerCount == 0 {
|
||||
devicePort.PortUsed = 0
|
||||
} else {
|
||||
// Set port_used to the highest port with a customer
|
||||
// or keep current port_used if it's higher (for reserved ports)
|
||||
if highestUsedPort > devicePort.PortUsed {
|
||||
devicePort.PortUsed = highestUsedPort
|
||||
}
|
||||
}
|
||||
// Update port_used to reflect highest occupied port
|
||||
devicePort.PortUsed = highestOccupiedPort
|
||||
|
||||
// Recalculate port_available
|
||||
devicePort.PortAvailable = device.PortAmount - devicePort.PortUsed
|
||||
|
|
@ -367,7 +391,6 @@ func (r *deviceDetailsRepo) RemoveCustomerByPort(deviceID uuid.UUID, portNumber
|
|||
r.updateDevicePortCounters(&devicePort)
|
||||
devicePort.UpdatedAt = time.Now()
|
||||
|
||||
|
||||
return tx.Save(&devicePort).Error
|
||||
})
|
||||
}
|
||||
|
|
@ -424,6 +447,9 @@ func (r *deviceDetailsRepo) UpdatePortAssignments(deviceID uuid.UUID, assignment
|
|||
}
|
||||
}
|
||||
|
||||
// Track highest occupied port for calculating port_used
|
||||
highestOccupiedPort := 0
|
||||
|
||||
// Update port assignments
|
||||
for _, assignment := range assignments {
|
||||
portIndex := assignment.PortNumber - 1
|
||||
|
|
@ -431,10 +457,23 @@ func (r *deviceDetailsRepo) UpdatePortAssignments(deviceID uuid.UUID, assignment
|
|||
devicePort.PortAssignments[portIndex].PortNumber = assignment.PortNumber
|
||||
devicePort.PortAssignments[portIndex].CustomerName = assignment.CustomerName
|
||||
|
||||
// Update status if provided, otherwise default based on customer presence
|
||||
// Handle is_occupied field
|
||||
isOccupied := false
|
||||
if assignment.IsOccupied != nil {
|
||||
isOccupied = *assignment.IsOccupied
|
||||
} else {
|
||||
// If not specified, determine based on customer name
|
||||
isOccupied = assignment.CustomerName != nil && *assignment.CustomerName != ""
|
||||
}
|
||||
|
||||
// Explicitly set the IsOccupied field
|
||||
devicePort.PortAssignments[portIndex].IsOccupied = isOccupied
|
||||
|
||||
// Update status (independent of occupation)
|
||||
if assignment.Status != nil {
|
||||
devicePort.PortAssignments[portIndex].Status = *assignment.Status
|
||||
} else if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
} else if isOccupied {
|
||||
// Only set default status if not provided and port is occupied
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOn
|
||||
} else {
|
||||
devicePort.PortAssignments[portIndex].Status = entity.PortStatusOff
|
||||
|
|
@ -444,29 +483,37 @@ func (r *deviceDetailsRepo) UpdatePortAssignments(deviceID uuid.UUID, assignment
|
|||
if assignment.Bandwidth != nil {
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = assignment.Bandwidth
|
||||
}
|
||||
|
||||
// Track highest occupied port
|
||||
if isOccupied && assignment.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = assignment.PortNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate port usage based on highest occupied port (not just customer count)
|
||||
if highestOccupiedPort == 0 {
|
||||
// No explicitly occupied ports, calculate from existing assignments
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
if assignment.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = assignment.PortNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
devicePort.PortUsed = highestOccupiedPort
|
||||
devicePort.PortAvailable = device.PortAmount - highestOccupiedPort
|
||||
|
||||
// Update counters and backward compatibility fields
|
||||
r.updateDevicePortCounters(&devicePort)
|
||||
|
||||
// Calculate port usage based on assignments
|
||||
portUsed := 0
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
portUsed++
|
||||
}
|
||||
}
|
||||
|
||||
devicePort.PortUsed = portUsed
|
||||
devicePort.PortAvailable = device.PortAmount - portUsed
|
||||
devicePort.UpdatedAt = time.Now()
|
||||
|
||||
return tx.Save(&devicePort).Error
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func (r *deviceDetailsRepo) Create(device entity.Device) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// Validate tower exists if TowerID is provided
|
||||
|
|
@ -800,8 +847,6 @@ func (r *deviceDetailsRepo) GetTowersByDeviceID(deviceID uuid.UUID) ([]entity.To
|
|||
return towers, 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
|
||||
|
|
@ -962,29 +1007,70 @@ func (r *deviceDetailsRepo) updateDevicePortCounters(devicePort *entity.DevicePo
|
|||
device = devicePort.Device
|
||||
}
|
||||
|
||||
// Count actual customers and find highest used port
|
||||
// Count actual customers and find highest occupied port
|
||||
customerCount := 0
|
||||
customerNames := make([]string, 0)
|
||||
highestCustomerPort := 0
|
||||
highestOccupiedPort := 0
|
||||
|
||||
// Get ports with customers and check IsOccupied field
|
||||
portsWithCustomers := make([]int, 0)
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
// Count customers
|
||||
if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
customerCount++
|
||||
customerNames = append(customerNames, *assignment.CustomerName) // Just customer names, not with port numbers
|
||||
if assignment.PortNumber > highestCustomerPort {
|
||||
highestCustomerPort = assignment.PortNumber
|
||||
customerNames = append(customerNames, *assignment.CustomerName)
|
||||
portsWithCustomers = append(portsWithCustomers, assignment.PortNumber)
|
||||
}
|
||||
|
||||
// Check occupation (either by IsOccupied field or customer presence)
|
||||
if assignment.IsOccupied || (assignment.CustomerName != nil && *assignment.CustomerName != "") {
|
||||
if assignment.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = assignment.PortNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set port_used to the highest port number that has a customer
|
||||
// This ensures we don't have gaps in port usage
|
||||
if customerCount == 0 {
|
||||
devicePort.PortUsed = 0
|
||||
} else {
|
||||
devicePort.PortUsed = highestCustomerPort
|
||||
// For ODP devices, we need to maintain the concept of "used ports" even without customer names
|
||||
// This handles the case where port_used was set manually or ports are occupied without customer names
|
||||
if device.DeviceType == "ODP" {
|
||||
// If current port_used is higher than what we calculated from customer names,
|
||||
// it means there are occupied ports without customer names
|
||||
if devicePort.PortUsed > highestOccupiedPort {
|
||||
highestOccupiedPort = devicePort.PortUsed
|
||||
}
|
||||
|
||||
// Ensure we have assignments for all ports up to the highest occupied port
|
||||
if len(devicePort.PortAssignments) == 0 || len(devicePort.PortAssignments) < device.PortAmount {
|
||||
devicePort.PortAssignments = make(entity.PortAssignments, device.PortAmount)
|
||||
for i := 0; i < device.PortAmount; i++ {
|
||||
devicePort.PortAssignments[i] = entity.PortAssignment{
|
||||
PortNumber: i + 1,
|
||||
CustomerName: nil,
|
||||
IsOccupied: false,
|
||||
Status: entity.PortStatusOff,
|
||||
Bandwidth: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Restore customer assignments
|
||||
for _, portNum := range portsWithCustomers {
|
||||
portIndex := portNum - 1
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
if assignment.PortNumber == portNum && assignment.CustomerName != nil {
|
||||
devicePort.PortAssignments[portIndex].CustomerName = assignment.CustomerName
|
||||
devicePort.PortAssignments[portIndex].IsOccupied = assignment.IsOccupied
|
||||
devicePort.PortAssignments[portIndex].Status = assignment.Status
|
||||
devicePort.PortAssignments[portIndex].Bandwidth = assignment.Bandwidth
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set port_used to the highest occupied port (with or without customer)
|
||||
devicePort.PortUsed = highestOccupiedPort
|
||||
|
||||
// Calculate port_available
|
||||
devicePort.PortAvailable = device.PortAmount - devicePort.PortUsed
|
||||
|
||||
|
|
@ -1098,24 +1184,30 @@ func (r *deviceDetailsRepo) RecalculatePortUsageAfterBulkUpdate(deviceID uuid.UU
|
|||
return err
|
||||
}
|
||||
|
||||
// Find the highest port number with a customer
|
||||
highestUsedPort := 0
|
||||
// Find the highest port number that is occupied (using IsOccupied field)
|
||||
highestOccupiedPort := 0
|
||||
customerCount := 0
|
||||
|
||||
// Check all assignments for occupation and customers
|
||||
for _, assignment := range devicePort.PortAssignments {
|
||||
// Count customers
|
||||
if assignment.CustomerName != nil && *assignment.CustomerName != "" {
|
||||
customerCount++
|
||||
if assignment.PortNumber > highestUsedPort {
|
||||
highestUsedPort = assignment.PortNumber
|
||||
}
|
||||
|
||||
// Check occupation using IsOccupied field or customer presence
|
||||
if assignment.IsOccupied || (assignment.CustomerName != nil && *assignment.CustomerName != "") {
|
||||
if assignment.PortNumber > highestOccupiedPort {
|
||||
highestOccupiedPort = assignment.PortNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update port usage
|
||||
devicePort.PortUsed = highestUsedPort
|
||||
// Update port usage - this represents the highest occupied port number
|
||||
devicePort.PortUsed = highestOccupiedPort
|
||||
devicePort.PortAvailable = device.PortAmount - devicePort.PortUsed
|
||||
|
||||
// Update other counters
|
||||
// Update other counters using the updated logic
|
||||
r.updateDevicePortCounters(&devicePort)
|
||||
devicePort.UpdatedAt = time.Now()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue