mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-05 03:12:34 -06:00
Перевел на multi-tenant
Добавил поставщиков Накладные успешно создаются из фронта
This commit is contained in:
@@ -16,12 +16,17 @@ func NewRepository(db *gorm.DB) catalog.Repository {
|
||||
return &pgRepository{db: db}
|
||||
}
|
||||
|
||||
// --- Запись (Save) ---
|
||||
// При сохранении мы предполагаем, что serverID уже проставлен в Entity в слое Service.
|
||||
// Но для надежности можно передавать serverID в метод Save, однако Service должен это контролировать.
|
||||
// Оставим контракт Save(products []Product), где внутри products уже заполнен RMSServerID.
|
||||
|
||||
func (r *pgRepository) SaveMeasureUnits(units []catalog.MeasureUnit) error {
|
||||
if len(units) == 0 {
|
||||
return nil
|
||||
}
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
Columns: []clause.Column{{Name: "id"}}, // ID глобально уникален (UUID), конфликтов между серверами не будет
|
||||
UpdateAll: true,
|
||||
}).CreateInBatches(units, 100).Error
|
||||
}
|
||||
@@ -29,7 +34,7 @@ func (r *pgRepository) SaveMeasureUnits(units []catalog.MeasureUnit) error {
|
||||
func (r *pgRepository) SaveProducts(products []catalog.Product) error {
|
||||
sorted := sortProductsByHierarchy(products)
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 1. Сохраняем продукты (без контейнеров, чтобы ускорить и не дублировать)
|
||||
// 1. Продукты
|
||||
if err := tx.Omit("Containers").Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
UpdateAll: true,
|
||||
@@ -37,13 +42,12 @@ func (r *pgRepository) SaveProducts(products []catalog.Product) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. Собираем все контейнеры в один слайс
|
||||
// 2. Контейнеры
|
||||
var allContainers []catalog.ProductContainer
|
||||
for _, p := range products {
|
||||
allContainers = append(allContainers, p.Containers...)
|
||||
}
|
||||
|
||||
// 3. Сохраняем контейнеры
|
||||
if len(allContainers) > 0 {
|
||||
if err := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
@@ -56,13 +60,66 @@ func (r *pgRepository) SaveProducts(products []catalog.Product) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *pgRepository) SaveContainer(container catalog.ProductContainer) error {
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
UpdateAll: true,
|
||||
}).Create(&container).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) SaveStores(stores []catalog.Store) error {
|
||||
if len(stores) == 0 {
|
||||
return nil
|
||||
}
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
UpdateAll: true,
|
||||
}).CreateInBatches(stores, 100).Error
|
||||
}
|
||||
|
||||
// --- Чтение (Read) с фильтрацией по ServerID ---
|
||||
|
||||
func (r *pgRepository) GetAll() ([]catalog.Product, error) {
|
||||
// Этот метод был legacy и грузил всё. Теперь он опасен без serverID.
|
||||
// Оставляем заглушку или удаляем. Лучше удалить из интерфейса, но пока вернем пустой список
|
||||
// чтобы не ломать сборку, пока не почистим вызовы.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetActiveGoods(serverID uuid.UUID) ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
err := r.db.Preload("MainUnit").Find(&products).Error
|
||||
err := r.db.
|
||||
Preload("MainUnit").
|
||||
Preload("Containers").
|
||||
Where("rms_server_id = ? AND is_deleted = ? AND type IN ?", serverID, false, []string{"GOODS"}).
|
||||
Order("name ASC").
|
||||
Find(&products).Error
|
||||
return products, err
|
||||
}
|
||||
|
||||
// Вспомогательная функция сортировки (оставляем как была)
|
||||
func (r *pgRepository) GetActiveStores(serverID uuid.UUID) ([]catalog.Store, error) {
|
||||
var stores []catalog.Store
|
||||
err := r.db.Where("rms_server_id = ? AND is_deleted = ?", serverID, false).Order("name ASC").Find(&stores).Error
|
||||
return stores, err
|
||||
}
|
||||
|
||||
func (r *pgRepository) Search(serverID uuid.UUID, query string) ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
q := "%" + query + "%"
|
||||
|
||||
err := r.db.
|
||||
Preload("MainUnit").
|
||||
Preload("Containers").
|
||||
Where("rms_server_id = ? AND is_deleted = ? AND type = ?", serverID, false, "GOODS").
|
||||
Where("name ILIKE ? OR code ILIKE ? OR num ILIKE ?", q, q, q).
|
||||
Order("name ASC").
|
||||
Limit(20).
|
||||
Find(&products).Error
|
||||
|
||||
return products, err
|
||||
}
|
||||
|
||||
// sortProductsByHierarchy - вспомогательная функция, оставляем как есть (копипаст из старого файла)
|
||||
func sortProductsByHierarchy(products []catalog.Product) []catalog.Product {
|
||||
if len(products) == 0 {
|
||||
return products
|
||||
@@ -104,58 +161,18 @@ func sortProductsByHierarchy(products []catalog.Product) []catalog.Product {
|
||||
return result
|
||||
}
|
||||
|
||||
// GetActiveGoods возвращает только активные товары c подгруженной единицей измерения
|
||||
// GetActiveGoods оптимизирован: подгружаем Units и Containers
|
||||
func (r *pgRepository) GetActiveGoods() ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
err := r.db.
|
||||
Preload("MainUnit").
|
||||
Preload("Containers"). // <-- Подгружаем фасовки
|
||||
Where("is_deleted = ? AND type IN ?", false, []string{"GOODS"}).
|
||||
Order("name ASC").
|
||||
Find(&products).Error
|
||||
return products, err
|
||||
func (r *pgRepository) CountGoods(serverID uuid.UUID) (int64, error) {
|
||||
var count int64
|
||||
err := r.db.Model(&catalog.Product{}).
|
||||
Where("rms_server_id = ? AND type IN ? AND is_deleted = ?", serverID, []string{"GOODS"}, false).
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (r *pgRepository) SaveStores(stores []catalog.Store) error {
|
||||
if len(stores) == 0 {
|
||||
return nil
|
||||
}
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
UpdateAll: true,
|
||||
}).CreateInBatches(stores, 100).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetActiveStores() ([]catalog.Store, error) {
|
||||
var stores []catalog.Store
|
||||
err := r.db.Where("is_deleted = ?", false).Order("name ASC").Find(&stores).Error
|
||||
return stores, err
|
||||
}
|
||||
|
||||
// SaveContainer сохраняет или обновляет одну фасовку
|
||||
func (r *pgRepository) SaveContainer(container catalog.ProductContainer) error {
|
||||
return r.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "id"}},
|
||||
UpdateAll: true,
|
||||
}).Create(&container).Error
|
||||
}
|
||||
|
||||
// Search ищет товары по названию, артикулу или коду (ILIKE)
|
||||
func (r *pgRepository) Search(query string) ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
|
||||
// Оборачиваем в проценты для поиска подстроки
|
||||
q := "%" + query + "%"
|
||||
|
||||
err := r.db.
|
||||
Preload("MainUnit").
|
||||
Preload("Containers"). // Обязательно грузим фасовки, они нужны для выбора
|
||||
Where("is_deleted = ? AND type = ?", false, "GOODS").
|
||||
Where("name ILIKE ? OR code ILIKE ? OR num ILIKE ?", q, q, q).
|
||||
Order("name ASC").
|
||||
Limit(20). // Ограничиваем выдачу, чтобы не перегружать фронт
|
||||
Find(&products).Error
|
||||
|
||||
return products, err
|
||||
func (r *pgRepository) CountStores(serverID uuid.UUID) (int64, error) {
|
||||
var count int64
|
||||
err := r.db.Model(&catalog.Store{}).
|
||||
Where("rms_server_id = ? AND is_deleted = ?", serverID, false).
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user