Merge pull request 'adding olt' (#28) from feature/responses-v2 into dev
Reviewed-on: winter-access/backend_nam#28
This commit is contained in:
commit
1ba0df21ed
|
|
@ -0,0 +1,229 @@
|
||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"users_management/m/model/dto/req"
|
||||||
|
"users_management/m/usecase"
|
||||||
|
"users_management/m/utils/common"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OLTController struct {
|
||||||
|
oltUC usecase.OLTUsecase
|
||||||
|
rg *gin.RouterGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOLTController(oltUC usecase.OLTUsecase, rg *gin.RouterGroup) *OLTController {
|
||||||
|
return &OLTController{
|
||||||
|
oltUC: oltUC,
|
||||||
|
rg: rg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) Route() {
|
||||||
|
oltGroup := c.rg.Group("/olt")
|
||||||
|
{
|
||||||
|
oltGroup.POST("", c.createOLT)
|
||||||
|
oltGroup.GET("", c.getAllOLTs)
|
||||||
|
oltGroup.GET("/:id", c.getOLTByID)
|
||||||
|
oltGroup.PUT("/:id", c.updateOLT)
|
||||||
|
oltGroup.DELETE("/:id", c.deleteOLT)
|
||||||
|
oltGroup.POST("/:id/assign-device", c.assignDeviceToOLT)
|
||||||
|
oltGroup.DELETE("/unassign-device/:deviceId", c.unassignDeviceFromOLT)
|
||||||
|
oltGroup.GET("/:id/devices", c.getDevicesByOLT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) createOLT(ctx *gin.Context) {
|
||||||
|
var oltDTO req.OLTDTO
|
||||||
|
if err := ctx.ShouldBindJSON(&oltDTO); err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.oltUC.CreateOLT(oltDTO)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "OLT name already exists" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusConflict, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLT created successfully", gin.H{
|
||||||
|
"olt_name": oltDTO.OLTName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) getAllOLTs(ctx *gin.Context) {
|
||||||
|
// Pagination parameters
|
||||||
|
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
|
||||||
|
if page < 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
olts, err := c.oltUC.GetAllOLTs()
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response := gin.H{
|
||||||
|
"olts": olts,
|
||||||
|
"total": len(olts),
|
||||||
|
"page": page,
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLTs retrieved successfully", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) getOLTByID(ctx *gin.Context) {
|
||||||
|
idStr := ctx.Param("id")
|
||||||
|
id, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid OLT ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
olt, err := c.oltUC.GetOLTByID(id)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, "OLT not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLT details retrieved successfully", olt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) updateOLT(ctx *gin.Context) {
|
||||||
|
idStr := ctx.Param("id")
|
||||||
|
id, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid OLT ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateDTO req.UpdateOLTDTO
|
||||||
|
if err := ctx.ShouldBindJSON(&updateDTO); err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.oltUC.UpdateOLT(id, updateDTO)
|
||||||
|
if err != nil {
|
||||||
|
switch err.Error() {
|
||||||
|
case "OLT not found":
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, err.Error())
|
||||||
|
case "OLT name already exists":
|
||||||
|
common.ErrorResponses(ctx, http.StatusConflict, err.Error())
|
||||||
|
default:
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLT updated successfully", gin.H{
|
||||||
|
"olt_id": id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) deleteOLT(ctx *gin.Context) {
|
||||||
|
idStr := ctx.Param("id")
|
||||||
|
id, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid OLT ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.oltUC.DeleteOLT(id)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "OLT not found" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLT deleted successfully", gin.H{
|
||||||
|
"olt_id": id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) assignDeviceToOLT(ctx *gin.Context) {
|
||||||
|
oltIDStr := ctx.Param("id")
|
||||||
|
oltID, err := uuid.Parse(oltIDStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid OLT ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var assignDTO req.AssignDeviceToOLTDTO
|
||||||
|
if err := ctx.ShouldBindJSON(&assignDTO); err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.oltUC.AssignDeviceToOLT(oltID, assignDTO.DeviceID)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "only ODP devices can be assigned to OLT" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "Device assigned to OLT successfully", gin.H{
|
||||||
|
"olt_id": oltID,
|
||||||
|
"device_id": assignDTO.DeviceID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) unassignDeviceFromOLT(ctx *gin.Context) {
|
||||||
|
deviceIDStr := ctx.Param("deviceId")
|
||||||
|
deviceID, err := uuid.Parse(deviceIDStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.oltUC.UnassignDeviceFromOLT(deviceID)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "Device unassigned from OLT successfully", gin.H{
|
||||||
|
"device_id": deviceID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OLTController) getDevicesByOLT(ctx *gin.Context) {
|
||||||
|
idStr := ctx.Param("id")
|
||||||
|
id, err := uuid.Parse(idStr)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid OLT ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
devices, err := c.oltUC.GetDevicesByOLT(id)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "OLT not found" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response := gin.H{
|
||||||
|
"devices": devices,
|
||||||
|
"total": len(devices),
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, "OLT devices retrieved successfully", response)
|
||||||
|
}
|
||||||
|
|
@ -90,6 +90,7 @@ func (s *Server) setupController() {
|
||||||
controller.NewDeviceInspectionController(s.ucManager.NewDeviceInspectionUsecase(), protected).Route()
|
controller.NewDeviceInspectionController(s.ucManager.NewDeviceInspectionUsecase(), protected).Route()
|
||||||
controller.NewNearestDeviceController(s.ucManager.NewNearestDeviceUsecase(), protected, s.cfg).Route()
|
controller.NewNearestDeviceController(s.ucManager.NewNearestDeviceUsecase(), protected, s.cfg).Route()
|
||||||
controller.NewDeviceDetailsController(s.ucManager.NewDeviceDetailsUsecase(), protected, s.cfg).Route()
|
controller.NewDeviceDetailsController(s.ucManager.NewDeviceDetailsUsecase(), protected, s.cfg).Route()
|
||||||
|
controller.NewOLTController(s.ucManager.NewOLTUsecase(), protected).Route()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ func (im *infraManager) autoMigrate(db *gorm.DB) error {
|
||||||
&entity.DevicePort{},
|
&entity.DevicePort{},
|
||||||
&entity.CountAssets{},
|
&entity.CountAssets{},
|
||||||
&entity.ActivityLog{},
|
&entity.ActivityLog{},
|
||||||
|
&entity.OLT{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type RepositoryManager interface {
|
||||||
NewNearestDeviceRepository() repository.NearestDeviceRepo
|
NewNearestDeviceRepository() repository.NearestDeviceRepo
|
||||||
|
|
||||||
NewDeviceDetailsRepository() repository.DeviceDetailsRepo
|
NewDeviceDetailsRepository() repository.DeviceDetailsRepo
|
||||||
|
NewOLTRepo() repository.OLTRepo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,3 +72,7 @@ func (rm *repositoryManager) NewActivityLogRepository() repository.ActivityLogRe
|
||||||
func (rm *repositoryManager) NewDeviceInspectionRepository() repository.DeviceInspectionRepo {
|
func (rm *repositoryManager) NewDeviceInspectionRepository() repository.DeviceInspectionRepo {
|
||||||
return repository.NewDeviceInspectionRepo(rm.infra.Conn())
|
return repository.NewDeviceInspectionRepo(rm.infra.Conn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rm *repositoryManager) NewOLTRepo() repository.OLTRepo {
|
||||||
|
return repository.NewOLTRepo(rm.infra.Conn())
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@ type UsecaseManager interface {
|
||||||
NewNearestDeviceUsecase() usecase.NearestDeviceUseCase
|
NewNearestDeviceUsecase() usecase.NearestDeviceUseCase
|
||||||
|
|
||||||
NewDeviceDetailsUsecase() usecase.DeviceDetailsUseCase
|
NewDeviceDetailsUsecase() usecase.DeviceDetailsUseCase
|
||||||
|
NewOLTUsecase() usecase.OLTUsecase
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,3 +108,7 @@ func (um *usecaseManager) NewDeviceInspectionUsecase() usecase.DeviceInspectionU
|
||||||
service.NewGeocodingService(), // Add the geocoding service
|
service.NewGeocodingService(), // Add the geocoding service
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (um *usecaseManager) NewOLTUsecase() usecase.OLTUsecase {
|
||||||
|
return usecase.NewOLTUsecase(um.repo.NewOLTRepo(), um.repo.NewDeviceDetailsRepository(), service.NewGeocodingService())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package req
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
type OLTDTO struct {
|
||||||
|
OLTName string `json:"olt_name" validate:"required,min=3,max=100"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateOLTDTO struct {
|
||||||
|
OLTName *string `json:"olt_name,omitempty" validate:"omitempty,min=3,max=100"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssignDeviceToOLTDTO struct {
|
||||||
|
DeviceID uuid.UUID `json:"device_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnassignDeviceFromOLTDTO struct {
|
||||||
|
DeviceID uuid.UUID `json:"device_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package res
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OLTResponse struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
OLTName string `json:"olt_name"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OLTDetailResponse struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
OLTName string `json:"olt_name"`
|
||||||
|
DeviceCount int `json:"device_count"`
|
||||||
|
Devices []DeviceDetailsResponse `json:"devices"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OLTDeviceResponse struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
DeviceCode string `json:"device_code"`
|
||||||
|
DeviceType string `json:"device_type"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Province *string `json:"province,omitempty"`
|
||||||
|
City *string `json:"city,omitempty"`
|
||||||
|
District *string `json:"district,omitempty"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
PortAmount int `json:"port_amount"`
|
||||||
|
PortUsed int `json:"port_used"`
|
||||||
|
ImageURL *string `json:"image_url,omitempty"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -32,8 +32,11 @@ type Device struct {
|
||||||
District *string `json:"district,omitempty" gorm:"type:varchar(255)"`
|
District *string `json:"district,omitempty" gorm:"type:varchar(255)"`
|
||||||
ImageURL *string `json:"image_url,omitempty" gorm:"type:text"`
|
ImageURL *string `json:"image_url,omitempty" gorm:"type:text"`
|
||||||
ImageURLs StringSlice `json:"image_urls" gorm:"type:jsonb"` // Store multiple images as JSONB
|
ImageURLs StringSlice `json:"image_urls" gorm:"type:jsonb"` // Store multiple images as JSONB
|
||||||
|
OLTID *uuid.UUID `json:"olt_id,omitempty" gorm:"type:uuid"` // Add this field
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
OLT *OLT `json:"olt,omitempty" gorm:"foreignKey:OLTID;references:ID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) GetAllImageURLs() []string {
|
func (d *Device) GetAllImageURLs() []string {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OLT struct {
|
||||||
|
ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"`
|
||||||
|
OLTName string `json:"olt_name" gorm:"unique;not null"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// Relationships - One OLT can have many devices
|
||||||
|
Devices []Device `json:"devices,omitempty" gorm:"foreignKey:OLTID;references:ID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (OLT) TableName() string {
|
||||||
|
return "olts"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"users_management/m/model/entity"
|
||||||
|
"users_management/m/model/dto/req"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OLTRepo interface {
|
||||||
|
Create(olt entity.OLT) error
|
||||||
|
GetAll() ([]entity.OLT, error)
|
||||||
|
GetByID(id uuid.UUID) (entity.OLT, error)
|
||||||
|
GetByIDWithDevices(id uuid.UUID) (entity.OLT, error)
|
||||||
|
Update(id uuid.UUID, updateDTO req.UpdateOLTDTO) error
|
||||||
|
Delete(id uuid.UUID) error
|
||||||
|
AssignDeviceToOLT(oltID, deviceID uuid.UUID) error
|
||||||
|
UnassignDeviceFromOLT(deviceID uuid.UUID) error
|
||||||
|
GetByName(name string) (entity.OLT, error)
|
||||||
|
GetDevicesByOLTID(oltID uuid.UUID) ([]entity.Device, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type oltRepo struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOLTRepo(db *gorm.DB) OLTRepo {
|
||||||
|
return &oltRepo{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) Create(olt entity.OLT) error {
|
||||||
|
return r.db.Create(&olt).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) GetAll() ([]entity.OLT, error) {
|
||||||
|
var olts []entity.OLT
|
||||||
|
err := r.db.Order("created_at DESC").Find(&olts).Error
|
||||||
|
return olts, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) GetByID(id uuid.UUID) (entity.OLT, error) {
|
||||||
|
var olt entity.OLT
|
||||||
|
err := r.db.Where("id = ?", id).First(&olt).Error
|
||||||
|
return olt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) GetByIDWithDevices(id uuid.UUID) (entity.OLT, error) {
|
||||||
|
var olt entity.OLT
|
||||||
|
err := r.db.Preload("Devices").
|
||||||
|
Preload("Devices.DevicePort").
|
||||||
|
Where("id = ?", id).
|
||||||
|
First(&olt).Error
|
||||||
|
return olt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) Update(id uuid.UUID, updateDTO req.UpdateOLTDTO) error {
|
||||||
|
updates := make(map[string]interface{})
|
||||||
|
|
||||||
|
if updateDTO.OLTName != nil {
|
||||||
|
updates["olt_name"] = *updateDTO.OLTName
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(updates) == 0 {
|
||||||
|
return fmt.Errorf("no fields to update")
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.db.Model(&entity.OLT{}).Where("id = ?", id).Updates(updates).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) Delete(id uuid.UUID) error {
|
||||||
|
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// First, unassign all devices from this OLT
|
||||||
|
if err := tx.Model(&entity.Device{}).
|
||||||
|
Where("olt_id = ?", id).
|
||||||
|
Update("olt_id", nil).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then delete the OLT
|
||||||
|
return tx.Where("id = ?", id).Delete(&entity.OLT{}).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) AssignDeviceToOLT(oltID, deviceID uuid.UUID) error {
|
||||||
|
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if OLT exists
|
||||||
|
var olt entity.OLT
|
||||||
|
if err := tx.Where("id = ?", oltID).First(&olt).Error; err != nil {
|
||||||
|
return fmt.Errorf("OLT not found: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if device exists and is ODP type
|
||||||
|
var device entity.Device
|
||||||
|
if err := tx.Where("id = ?", deviceID).First(&device).Error; err != nil {
|
||||||
|
return fmt.Errorf("device not found: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.DeviceType != entity.ODP {
|
||||||
|
return fmt.Errorf("only ODP devices can be assigned to OLT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign device to OLT
|
||||||
|
return tx.Model(&device).Update("olt_id", oltID).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) UnassignDeviceFromOLT(deviceID uuid.UUID) error {
|
||||||
|
return r.db.Model(&entity.Device{}).
|
||||||
|
Where("id = ?", deviceID).
|
||||||
|
Update("olt_id", nil).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) GetByName(name string) (entity.OLT, error) {
|
||||||
|
var olt entity.OLT
|
||||||
|
err := r.db.Where("olt_name = ?", name).First(&olt).Error
|
||||||
|
return olt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *oltRepo) GetDevicesByOLTID(oltID uuid.UUID) ([]entity.Device, error) {
|
||||||
|
var devices []entity.Device
|
||||||
|
err := r.db.Preload("DevicePort").
|
||||||
|
Where("olt_id = ? AND device_type = ?", oltID, entity.ODP).
|
||||||
|
Find(&devices).Error
|
||||||
|
return devices, err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
"users_management/m/model/dto/req"
|
||||||
|
"users_management/m/model/dto/res"
|
||||||
|
"users_management/m/model/entity"
|
||||||
|
"users_management/m/repository"
|
||||||
|
"users_management/m/utils/helper"
|
||||||
|
"users_management/m/utils/service"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OLTUsecase interface {
|
||||||
|
CreateOLT(oltDTO req.OLTDTO) error
|
||||||
|
GetAllOLTs() ([]res.OLTResponse, error)
|
||||||
|
GetOLTByID(id uuid.UUID) (res.OLTDetailResponse, error)
|
||||||
|
UpdateOLT(id uuid.UUID, updateDTO req.UpdateOLTDTO) error
|
||||||
|
DeleteOLT(id uuid.UUID) error
|
||||||
|
AssignDeviceToOLT(oltID, deviceID uuid.UUID) error
|
||||||
|
UnassignDeviceFromOLT(deviceID uuid.UUID) error
|
||||||
|
GetDevicesByOLT(oltID uuid.UUID) ([]res.OLTDeviceResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type oltUsecase struct {
|
||||||
|
oltRepo repository.OLTRepo
|
||||||
|
deviceRepo repository.DeviceDetailsRepo
|
||||||
|
validate *validator.Validate
|
||||||
|
geocoder service.GeocodingService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOLTUsecase(oltRepo repository.OLTRepo, deviceRepo repository.DeviceDetailsRepo, geocoder service.GeocodingService) OLTUsecase {
|
||||||
|
return &oltUsecase{
|
||||||
|
oltRepo: oltRepo,
|
||||||
|
deviceRepo: deviceRepo,
|
||||||
|
validate: validator.New(),
|
||||||
|
geocoder: geocoder,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) CreateOLT(oltDTO req.OLTDTO) error {
|
||||||
|
if err := u.validate.Struct(oltDTO); err != nil {
|
||||||
|
return fmt.Errorf("validation error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if OLT name already exists
|
||||||
|
existingOLT, err := u.oltRepo.GetByName(oltDTO.OLTName)
|
||||||
|
if err == nil && existingOLT.ID != uuid.Nil {
|
||||||
|
return errors.New("OLT name already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
olt := entity.OLT{
|
||||||
|
ID: uuid.New(),
|
||||||
|
OLTName: oltDTO.OLTName,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.oltRepo.Create(olt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) GetAllOLTs() ([]res.OLTResponse, error) {
|
||||||
|
olts, err := u.oltRepo.GetAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var responses []res.OLTResponse
|
||||||
|
for _, olt := range olts {
|
||||||
|
response := res.OLTResponse{
|
||||||
|
ID: olt.ID,
|
||||||
|
OLTName: olt.OLTName,
|
||||||
|
CreatedAt: olt.CreatedAt,
|
||||||
|
UpdatedAt: olt.UpdatedAt,
|
||||||
|
}
|
||||||
|
responses = append(responses, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return responses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) GetOLTByID(id uuid.UUID) (res.OLTDetailResponse, error) {
|
||||||
|
// First, check if OLT exists using the basic GetByID method
|
||||||
|
olt, err := u.oltRepo.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("OLT not found: %v", err)
|
||||||
|
return res.OLTDetailResponse{}, errors.New("OLT not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("OLT found: %+v", olt)
|
||||||
|
|
||||||
|
// Try to get OLT with devices, but fallback to basic info if it fails
|
||||||
|
oltWithDevices, err := u.oltRepo.GetByIDWithDevices(id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting OLT with devices, using basic OLT info: %v", err)
|
||||||
|
// Use the basic OLT info we already retrieved
|
||||||
|
oltWithDevices = olt
|
||||||
|
oltWithDevices.Devices = []entity.Device{} // Ensure devices is empty slice, not nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("OLT retrieved with devices: %+v", oltWithDevices)
|
||||||
|
|
||||||
|
// Convert devices to device details responses
|
||||||
|
var deviceResponses []res.DeviceDetailsResponse
|
||||||
|
for _, device := range oltWithDevices.Devices {
|
||||||
|
log.Printf("Processing device: %s", device.DeviceCode)
|
||||||
|
|
||||||
|
// Get the device details using the existing method which properly loads DevicePort
|
||||||
|
deviceDetails, err := u.deviceRepo.GetByID(device.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting device details for %s: %v", device.DeviceCode, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceResponse, err := helper.ConvertToDeviceDetailsResponse(deviceDetails, u.geocoder)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error converting device response for %s: %v", device.DeviceCode, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deviceResponses = append(deviceResponses, deviceResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize empty slice if nil to ensure JSON response shows empty array instead of null
|
||||||
|
if deviceResponses == nil {
|
||||||
|
deviceResponses = []res.DeviceDetailsResponse{}
|
||||||
|
}
|
||||||
|
|
||||||
|
response := res.OLTDetailResponse{
|
||||||
|
ID: oltWithDevices.ID,
|
||||||
|
OLTName: oltWithDevices.OLTName,
|
||||||
|
DeviceCount: len(deviceResponses),
|
||||||
|
Devices: deviceResponses,
|
||||||
|
CreatedAt: oltWithDevices.CreatedAt,
|
||||||
|
UpdatedAt: oltWithDevices.UpdatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) UpdateOLT(id uuid.UUID, updateDTO req.UpdateOLTDTO) error {
|
||||||
|
if err := u.validate.Struct(updateDTO); err != nil {
|
||||||
|
return fmt.Errorf("validation error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if OLT exists
|
||||||
|
_, err := u.oltRepo.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("OLT not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if new name already exists (if name is being updated)
|
||||||
|
if updateDTO.OLTName != nil {
|
||||||
|
existingOLT, err := u.oltRepo.GetByName(*updateDTO.OLTName)
|
||||||
|
if err == nil && existingOLT.ID != id {
|
||||||
|
return errors.New("OLT name already exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.oltRepo.Update(id, updateDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) DeleteOLT(id uuid.UUID) error {
|
||||||
|
// Check if OLT exists
|
||||||
|
_, err := u.oltRepo.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("OLT not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.oltRepo.Delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) AssignDeviceToOLT(oltID, deviceID uuid.UUID) error {
|
||||||
|
return u.oltRepo.AssignDeviceToOLT(oltID, deviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) UnassignDeviceFromOLT(deviceID uuid.UUID) error {
|
||||||
|
return u.oltRepo.UnassignDeviceFromOLT(deviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *oltUsecase) GetDevicesByOLT(oltID uuid.UUID) ([]res.OLTDeviceResponse, error) {
|
||||||
|
// Check if OLT exists
|
||||||
|
_, err := u.oltRepo.GetByID(oltID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("OLT not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
devices, err := u.oltRepo.GetDevicesByOLTID(oltID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var responses []res.OLTDeviceResponse
|
||||||
|
for _, device := range devices {
|
||||||
|
// Get address using geocoder
|
||||||
|
address := ""
|
||||||
|
if u.geocoder != nil {
|
||||||
|
addr, err := u.geocoder.GetAddressFromCoordinates(device.Latitude, device.Longitude)
|
||||||
|
if err == nil {
|
||||||
|
address = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get port usage from device port repository
|
||||||
|
portUsed := 0
|
||||||
|
portUsageInfo, _, err := u.deviceRepo.GetPortUsageByDevice(device.ID)
|
||||||
|
if err == nil {
|
||||||
|
portUsed = portUsageInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
response := res.OLTDeviceResponse{
|
||||||
|
ID: device.ID,
|
||||||
|
DeviceCode: device.DeviceCode,
|
||||||
|
DeviceType: string(device.DeviceType),
|
||||||
|
Address: address,
|
||||||
|
Province: device.Province,
|
||||||
|
City: device.City,
|
||||||
|
District: device.District,
|
||||||
|
Status: string(device.Status),
|
||||||
|
PortAmount: device.PortAmount,
|
||||||
|
PortUsed: portUsed,
|
||||||
|
ImageURL: device.ImageURL,
|
||||||
|
CreatedAt: device.CreatedAt,
|
||||||
|
UpdatedAt: device.UpdatedAt,
|
||||||
|
}
|
||||||
|
responses = append(responses, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return responses, nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue