191 lines
3.3 KiB
Go
191 lines
3.3 KiB
Go
// backend\milestone_inventory.go
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"unicode"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
func normalizeMilestoneManufacturer(value string, model string) string {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return ""
|
|
}
|
|
|
|
model = strings.TrimSpace(model)
|
|
normalizedValue := strings.ToLower(value)
|
|
|
|
if strings.EqualFold(value, model) ||
|
|
strings.HasSuffix(normalizedValue, " device") ||
|
|
strings.Contains(normalizedValue, " camera") ||
|
|
strings.Contains(normalizedValue, " encoder") ||
|
|
strings.Contains(normalizedValue, " video") {
|
|
if manufacturer := extractMilestoneManufacturerFromName(value); manufacturer != "" {
|
|
return manufacturer
|
|
}
|
|
}
|
|
|
|
return value
|
|
}
|
|
|
|
func extractMilestoneManufacturerFromName(value string) string {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return ""
|
|
}
|
|
|
|
parts := strings.FieldsFunc(value, func(r rune) bool {
|
|
return unicode.IsSpace(r) ||
|
|
r == '_' ||
|
|
r == '-' ||
|
|
r == '/' ||
|
|
r == '\\' ||
|
|
r == '(' ||
|
|
r == ')' ||
|
|
r == ','
|
|
})
|
|
|
|
ignoredWords := map[string]bool{
|
|
"device": true,
|
|
"camera": true,
|
|
"video": true,
|
|
"encoder": true,
|
|
"ip": true,
|
|
"network": true,
|
|
"hardware": true,
|
|
}
|
|
|
|
for _, part := range parts {
|
|
part = strings.TrimSpace(part)
|
|
|
|
if part == "" {
|
|
continue
|
|
}
|
|
|
|
if isOnlyDigits(part) {
|
|
continue
|
|
}
|
|
|
|
if ignoredWords[strings.ToLower(part)] {
|
|
continue
|
|
}
|
|
|
|
return part
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func buildMilestoneInventoryNumber(
|
|
ctx context.Context,
|
|
tx pgx.Tx,
|
|
hardwareDevice milestoneHardwareDevice,
|
|
) (string, error) {
|
|
inventoryNumber := extractInventoryNumberFromMilestoneDeviceName(
|
|
hardwareDevice.DeviceName,
|
|
)
|
|
|
|
if inventoryNumber == "" {
|
|
inventoryNumber = extractInventoryNumberFromMilestoneDeviceName(
|
|
hardwareDevice.DisplayName,
|
|
)
|
|
}
|
|
|
|
if inventoryNumber == "" {
|
|
inventoryNumber = buildGeneratedMilestoneInventoryNumber(
|
|
hardwareDevice.HardwareID,
|
|
)
|
|
}
|
|
|
|
var exists bool
|
|
|
|
err := tx.QueryRow(
|
|
ctx,
|
|
`
|
|
SELECT EXISTS(
|
|
SELECT 1
|
|
FROM devices
|
|
WHERE lower(inventory_number) = lower($1)
|
|
AND milestone_hardware_id <> $2
|
|
)
|
|
`,
|
|
inventoryNumber,
|
|
hardwareDevice.HardwareID,
|
|
).Scan(&exists)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if !exists {
|
|
return inventoryNumber, nil
|
|
}
|
|
|
|
suffix := strings.ToUpper(strings.ReplaceAll(strings.TrimSpace(hardwareDevice.HardwareID), "-", ""))
|
|
if len(suffix) > 8 {
|
|
suffix = suffix[:8]
|
|
}
|
|
|
|
if suffix == "" {
|
|
suffix = "MS"
|
|
}
|
|
|
|
return inventoryNumber + "-" + suffix, nil
|
|
}
|
|
|
|
func extractInventoryNumberFromMilestoneDeviceName(value string) string {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return ""
|
|
}
|
|
|
|
parts := strings.FieldsFunc(value, func(r rune) bool {
|
|
return r == '_' || r == '-' || unicode.IsSpace(r)
|
|
})
|
|
|
|
for _, part := range parts {
|
|
part = strings.TrimSpace(part)
|
|
|
|
if part == "" {
|
|
continue
|
|
}
|
|
|
|
if isOnlyDigits(part) {
|
|
return part
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func isOnlyDigits(value string) bool {
|
|
if value == "" {
|
|
return false
|
|
}
|
|
|
|
for _, r := range value {
|
|
if r < '0' || r > '9' {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func buildGeneratedMilestoneInventoryNumber(hardwareID string) string {
|
|
value := strings.ToUpper(strings.ReplaceAll(strings.TrimSpace(hardwareID), "-", ""))
|
|
|
|
if len(value) > 12 {
|
|
value = value[:12]
|
|
}
|
|
|
|
if value == "" {
|
|
value = "UNKNOWN"
|
|
}
|
|
|
|
return "MS-" + value
|
|
}
|