Files
rmser/internal/infrastructure/repository/ocr/postgres.go
SERTY 310a64e3ba редактирование и удаление сопоставлений
список накладных с позициями
2025-12-29 10:46:05 +03:00

127 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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("Product.Containers").
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
}