mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-05 03:12:34 -06:00
126 lines
3.8 KiB
Go
126 lines
3.8 KiB
Go
package ocr
|
||
|
||
import (
|
||
"strings"
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
"gorm.io/gorm/clause"
|
||
|
||
"rmser/internal/domain/ocr"
|
||
|
||
"github.com/google/uuid"
|
||
"github.com/shopspring/decimal"
|
||
)
|
||
|
||
type pgRepository struct {
|
||
db *gorm.DB
|
||
}
|
||
|
||
func NewRepository(db *gorm.DB) ocr.Repository {
|
||
return &pgRepository{db: db}
|
||
}
|
||
|
||
func (r *pgRepository) SaveMatch(serverID uuid.UUID, rawName string, productID uuid.UUID, quantity decimal.Decimal, containerID *uuid.UUID) error {
|
||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||
|
||
match := ocr.ProductMatch{
|
||
RMSServerID: serverID,
|
||
RawName: normalized,
|
||
ProductID: productID,
|
||
Quantity: quantity,
|
||
ContainerID: containerID,
|
||
}
|
||
|
||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||
// Используем OnConflict по составному индексу (raw_name, rms_server_id)
|
||
// Но GORM может потребовать названия ограничения.
|
||
// Проще сделать через Where().Assign().FirstOrCreate() или явно указать Columns если индекс есть.
|
||
// В Entity мы указали `uniqueIndex:idx_raw_server`.
|
||
|
||
if err := tx.Clauses(clause.OnConflict{
|
||
// Указываем оба поля, входящие в unique index
|
||
Columns: []clause.Column{{Name: "raw_name"}, {Name: "rms_server_id"}},
|
||
DoUpdates: clause.AssignmentColumns([]string{"product_id", "quantity", "container_id", "updated_at"}),
|
||
}).Create(&match).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
// Удаляем из Unmatched для этого сервера
|
||
if err := tx.Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).Delete(&ocr.UnmatchedItem{}).Error; err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
})
|
||
}
|
||
|
||
func (r *pgRepository) DeleteMatch(serverID uuid.UUID, rawName string) error {
|
||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||
return r.db.Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).Delete(&ocr.ProductMatch{}).Error
|
||
}
|
||
|
||
func (r *pgRepository) FindMatch(serverID uuid.UUID, rawName string) (*ocr.ProductMatch, error) {
|
||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||
var match ocr.ProductMatch
|
||
|
||
err := r.db.Preload("Container").
|
||
Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).
|
||
First(&match).Error
|
||
|
||
if err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
return &match, nil
|
||
}
|
||
|
||
func (r *pgRepository) GetAllMatches(serverID uuid.UUID) ([]ocr.ProductMatch, error) {
|
||
var matches []ocr.ProductMatch
|
||
err := r.db.
|
||
Preload("Product").
|
||
Preload("Product.MainUnit").
|
||
Preload("Container").
|
||
Where("rms_server_id = ?", serverID).
|
||
Order("updated_at DESC").
|
||
Find(&matches).Error
|
||
return matches, err
|
||
}
|
||
|
||
func (r *pgRepository) UpsertUnmatched(serverID uuid.UUID, rawName string) error {
|
||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||
if normalized == "" {
|
||
return nil
|
||
}
|
||
|
||
item := ocr.UnmatchedItem{
|
||
RMSServerID: serverID,
|
||
RawName: normalized,
|
||
Count: 1,
|
||
LastSeen: time.Now(),
|
||
}
|
||
|
||
return r.db.Clauses(clause.OnConflict{
|
||
Columns: []clause.Column{{Name: "raw_name"}, {Name: "rms_server_id"}},
|
||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||
"count": gorm.Expr("unmatched_items.count + 1"),
|
||
"last_seen": time.Now(),
|
||
}),
|
||
}).Create(&item).Error
|
||
}
|
||
|
||
func (r *pgRepository) GetTopUnmatched(serverID uuid.UUID, limit int) ([]ocr.UnmatchedItem, error) {
|
||
var items []ocr.UnmatchedItem
|
||
err := r.db.Where("rms_server_id = ?", serverID).
|
||
Order("count DESC, last_seen DESC").
|
||
Limit(limit).
|
||
Find(&items).Error
|
||
return items, err
|
||
}
|
||
|
||
func (r *pgRepository) DeleteUnmatched(serverID uuid.UUID, rawName string) error {
|
||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||
return r.db.Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).Delete(&ocr.UnmatchedItem{}).Error
|
||
}
|