mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-05 03:12:34 -06:00
Перевел на multi-tenant
Добавил поставщиков Накладные успешно создаются из фронта
This commit is contained in:
@@ -21,9 +21,11 @@ func NewRepository(db *gorm.DB) ocr.Repository {
|
||||
return &pgRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *pgRepository) SaveMatch(rawName string, productID uuid.UUID, quantity decimal.Decimal, containerID *uuid.UUID) error {
|
||||
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,
|
||||
@@ -31,31 +33,40 @@ func (r *pgRepository) SaveMatch(rawName string, productID uuid.UUID, quantity d
|
||||
}
|
||||
|
||||
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{
|
||||
Columns: []clause.Column{{Name: "raw_name"}},
|
||||
// Указываем оба поля, входящие в 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
|
||||
}
|
||||
|
||||
if err := tx.Where("raw_name = ?", normalized).Delete(&ocr.UnmatchedItem{}).Error; err != nil {
|
||||
// Удаляем из 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(rawName string) error {
|
||||
func (r *pgRepository) DeleteMatch(serverID uuid.UUID, rawName string) error {
|
||||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||||
return r.db.Where("raw_name = ?", normalized).Delete(&ocr.ProductMatch{}).Error
|
||||
return r.db.Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).Delete(&ocr.ProductMatch{}).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) FindMatch(rawName string) (*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
|
||||
|
||||
// Preload Container на случай, если нам сразу нужна инфа
|
||||
err := r.db.Preload("Container").Where("raw_name = ?", normalized).First(&match).Error
|
||||
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
|
||||
@@ -65,35 +76,33 @@ func (r *pgRepository) FindMatch(rawName string) (*ocr.ProductMatch, error) {
|
||||
return &match, nil
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetAllMatches() ([]ocr.ProductMatch, error) {
|
||||
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
|
||||
}
|
||||
|
||||
// UpsertUnmatched увеличивает счетчик встречаемости
|
||||
func (r *pgRepository) UpsertUnmatched(rawName string) error {
|
||||
func (r *pgRepository) UpsertUnmatched(serverID uuid.UUID, rawName string) error {
|
||||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||||
if normalized == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Используем сырой SQL или GORM upsert expression
|
||||
// PostgreSQL: INSERT ... ON CONFLICT DO UPDATE SET count = count + 1
|
||||
item := ocr.UnmatchedItem{
|
||||
RawName: normalized,
|
||||
Count: 1,
|
||||
LastSeen: time.Now(),
|
||||
RMSServerID: serverID,
|
||||
RawName: normalized,
|
||||
Count: 1,
|
||||
LastSeen: time.Now(),
|
||||
}
|
||||
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "raw_name"}},
|
||||
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(),
|
||||
@@ -101,13 +110,16 @@ func (r *pgRepository) UpsertUnmatched(rawName string) error {
|
||||
}).Create(&item).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetTopUnmatched(limit int) ([]ocr.UnmatchedItem, error) {
|
||||
func (r *pgRepository) GetTopUnmatched(serverID uuid.UUID, limit int) ([]ocr.UnmatchedItem, error) {
|
||||
var items []ocr.UnmatchedItem
|
||||
err := r.db.Order("count DESC, last_seen DESC").Limit(limit).Find(&items).Error
|
||||
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(rawName string) error {
|
||||
func (r *pgRepository) DeleteUnmatched(serverID uuid.UUID, rawName string) error {
|
||||
normalized := strings.ToLower(strings.TrimSpace(rawName))
|
||||
return r.db.Where("raw_name = ?", normalized).Delete(&ocr.UnmatchedItem{}).Error
|
||||
return r.db.Where("rms_server_id = ? AND raw_name = ?", serverID, normalized).Delete(&ocr.UnmatchedItem{}).Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user