mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
Настройки работают
Иерархия групп работает Полностью завязано на пользователя и серверы
This commit is contained in:
@@ -100,9 +100,11 @@ func (r *pgRepository) GetActiveServer(userID uuid.UUID) (*account.RMSServer, er
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
// GetAllServers возвращает ВСЕ серверы пользователя, чтобы можно было переключаться
|
||||
func (r *pgRepository) GetAllServers(userID uuid.UUID) ([]account.RMSServer, error) {
|
||||
var servers []account.RMSServer
|
||||
err := r.db.Where("user_id = ? AND is_active = ?", userID, true).Find(&servers).Error
|
||||
// Убрали фильтр AND is_active = true, теперь возвращает весь список
|
||||
err := r.db.Where("user_id = ?", userID).Find(&servers).Error
|
||||
return servers, err
|
||||
}
|
||||
|
||||
|
||||
@@ -86,14 +86,25 @@ func (r *pgRepository) GetAll() ([]catalog.Product, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetActiveGoods(serverID uuid.UUID) ([]catalog.Product, error) {
|
||||
func (r *pgRepository) GetActiveGoods(serverID uuid.UUID, rootGroupID *uuid.UUID) ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
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
|
||||
db := r.db.Preload("MainUnit").Preload("Containers").
|
||||
Where("rms_server_id = ? AND is_deleted = ? AND type IN ?", serverID, false, []string{"GOODS"})
|
||||
|
||||
if rootGroupID != nil && *rootGroupID != uuid.Nil {
|
||||
// Используем Recursive CTE для поиска всех дочерних элементов папки
|
||||
subQuery := r.db.Raw(`
|
||||
WITH RECURSIVE subnodes AS (
|
||||
SELECT id FROM products WHERE id = ?
|
||||
UNION ALL
|
||||
SELECT p.id FROM products p INNER JOIN subnodes s ON p.parent_id = s.id
|
||||
)
|
||||
SELECT id FROM subnodes
|
||||
`, rootGroupID)
|
||||
db = db.Where("id IN (?)", subQuery)
|
||||
}
|
||||
|
||||
err := db.Order("name ASC").Find(&products).Error
|
||||
return products, err
|
||||
}
|
||||
|
||||
@@ -103,19 +114,27 @@ func (r *pgRepository) GetActiveStores(serverID uuid.UUID) ([]catalog.Store, err
|
||||
return stores, err
|
||||
}
|
||||
|
||||
func (r *pgRepository) Search(serverID uuid.UUID, query string) ([]catalog.Product, error) {
|
||||
func (r *pgRepository) Search(serverID uuid.UUID, query string, rootGroupID *uuid.UUID) ([]catalog.Product, error) {
|
||||
var products []catalog.Product
|
||||
q := "%" + query + "%"
|
||||
|
||||
err := r.db.
|
||||
Preload("MainUnit").
|
||||
Preload("Containers").
|
||||
db := 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
|
||||
Where("(name ILIKE ? OR code ILIKE ? OR num ILIKE ?)", q, q, q)
|
||||
|
||||
if rootGroupID != nil && *rootGroupID != uuid.Nil {
|
||||
subQuery := r.db.Raw(`
|
||||
WITH RECURSIVE subnodes AS (
|
||||
SELECT id FROM products WHERE id = ?
|
||||
UNION ALL
|
||||
SELECT p.id FROM products p INNER JOIN subnodes s ON p.parent_id = s.id
|
||||
)
|
||||
SELECT id FROM subnodes
|
||||
`, rootGroupID)
|
||||
db = db.Where("id IN (?)", subQuery)
|
||||
}
|
||||
|
||||
err := db.Order("name ASC").Limit(20).Find(&products).Error
|
||||
return products, err
|
||||
}
|
||||
|
||||
@@ -176,3 +195,12 @@ func (r *pgRepository) CountStores(serverID uuid.UUID) (int64, error) {
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (r *pgRepository) GetGroups(serverID uuid.UUID) ([]catalog.Product, error) {
|
||||
var groups []catalog.Product
|
||||
// iiko присылает группы с типом "GROUP"
|
||||
err := r.db.Where("rms_server_id = ? AND type = ? AND is_deleted = ?", serverID, "GROUP", false).
|
||||
Order("name ASC").
|
||||
Find(&groups).Error
|
||||
return groups, err
|
||||
}
|
||||
|
||||
@@ -60,6 +60,14 @@ func (r *pgRepository) CreateItems(items []drafts.DraftInvoiceItem) error {
|
||||
return r.db.CreateInBatches(items, 100).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) CreateItem(item *drafts.DraftInvoiceItem) error {
|
||||
return r.db.Create(item).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) DeleteItem(itemID uuid.UUID) error {
|
||||
return r.db.Delete(&drafts.DraftInvoiceItem{}, itemID).Error
|
||||
}
|
||||
|
||||
func (r *pgRepository) UpdateItem(itemID uuid.UUID, productID *uuid.UUID, containerID *uuid.UUID, qty, price decimal.Decimal) error {
|
||||
sum := qty.Mul(price)
|
||||
isMatched := productID != nil
|
||||
|
||||
@@ -557,13 +557,26 @@ func (c *Client) FetchStoreOperations(presetID string, from, to time.Time) ([]St
|
||||
// CreateIncomingInvoice отправляет накладную в iiko
|
||||
func (c *Client) CreateIncomingInvoice(inv invoices.Invoice) (string, error) {
|
||||
// 1. Маппинг Domain -> XML DTO
|
||||
|
||||
// Статус по умолчанию NEW, если не передан
|
||||
status := inv.Status
|
||||
if status == "" {
|
||||
status = "NEW"
|
||||
}
|
||||
|
||||
// Комментарий по умолчанию, если пустой
|
||||
comment := inv.Comment
|
||||
if comment == "" {
|
||||
comment = "Loaded via RMSER OCR"
|
||||
}
|
||||
|
||||
reqDTO := IncomingInvoiceImportXML{
|
||||
DocumentNumber: inv.DocumentNumber,
|
||||
DateIncoming: inv.DateIncoming.Format("02.01.2006"),
|
||||
DefaultStore: inv.DefaultStoreID.String(),
|
||||
Supplier: inv.SupplierID.String(),
|
||||
Status: "NEW",
|
||||
Comment: "Loaded via RMSER OCR",
|
||||
Status: status,
|
||||
Comment: comment,
|
||||
}
|
||||
|
||||
if inv.ID != uuid.Nil {
|
||||
@@ -758,6 +771,49 @@ func (c *Client) UpdateProduct(product ProductFullDTO) (*ProductFullDTO, error)
|
||||
return result.Response, nil
|
||||
}
|
||||
|
||||
// GetServerInfo пытается получить информацию о сервере (имя, версия) без авторизации.
|
||||
// Использует endpoint /resto/getServerMonitoringInfo.jsp
|
||||
func GetServerInfo(baseURL string) (*ServerMonitoringInfoDTO, error) {
|
||||
// Формируем URL. Убираем слэш в конце, если есть.
|
||||
url := strings.TrimRight(baseURL, "/") + "/resto/getServerMonitoringInfo.jsp"
|
||||
|
||||
logger.Log.Info("RMS: Requesting server info", zap.String("url", url))
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
logger.Log.Error("RMS: Monitoring connection failed", zap.Error(err))
|
||||
return nil, fmt.Errorf("connection error: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read body error: %w", err)
|
||||
}
|
||||
|
||||
logger.Log.Info("RMS: Monitoring Response",
|
||||
zap.Int("status", resp.StatusCode),
|
||||
zap.String("body", string(bodyBytes)))
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var info ServerMonitoringInfoDTO
|
||||
|
||||
// Пробуем JSON (так как в логе пришел JSON)
|
||||
if err := json.Unmarshal(bodyBytes, &info); err != nil {
|
||||
// Если вдруг JSON не прошел, можно попробовать XML как фоллбек (для старых версий)
|
||||
logger.Log.Warn("RMS: JSON decode failed, trying XML...", zap.Error(err))
|
||||
if xmlErr := xml.Unmarshal(bodyBytes, &info); xmlErr != nil {
|
||||
return nil, fmt.Errorf("decode error (json & xml failed): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// FetchSuppliers загружает список поставщиков через XML API
|
||||
func (c *Client) FetchSuppliers() ([]suppliers.Supplier, error) {
|
||||
// Endpoint /resto/api/suppliers
|
||||
|
||||
@@ -244,6 +244,13 @@ type ErrorDTO struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// ServerMonitoringInfoDTO используется для парсинга ответа мониторинга
|
||||
// iiko может отдавать JSON, поэтому ставим json теги.
|
||||
type ServerMonitoringInfoDTO struct {
|
||||
ServerName string `json:"serverName" xml:"serverName"`
|
||||
Version string `json:"version" xml:"version"`
|
||||
}
|
||||
|
||||
// --- Suppliers XML (Legacy API /resto/api/suppliers) ---
|
||||
|
||||
type SuppliersListXML struct {
|
||||
|
||||
Reference in New Issue
Block a user