82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package storage
|
||
|
||
import (
|
||
"context"
|
||
|
||
"dana/internal/domain"
|
||
)
|
||
|
||
// PriceList возвращает прайс деревом разделов с позициями.
|
||
// Если задан sectionSlug, отдаётся только этот раздел с потомками.
|
||
func (s *Storage) PriceList(ctx context.Context, sectionSlug string) ([]*domain.PriceSection, error) {
|
||
rows, err := s.pool.Query(ctx, `
|
||
SELECT id, parent_id, slug, name
|
||
FROM price_sections
|
||
WHERE published
|
||
ORDER BY sort, name`)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
byID := map[int64]*domain.PriceSection{}
|
||
var all []*domain.PriceSection
|
||
for rows.Next() {
|
||
sec := &domain.PriceSection{}
|
||
if err := rows.Scan(&sec.ID, &sec.ParentID, &sec.Slug, &sec.Name); err != nil {
|
||
return nil, err
|
||
}
|
||
byID[sec.ID] = sec
|
||
all = append(all, sec)
|
||
}
|
||
if err := rows.Err(); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
itemRows, err := s.pool.Query(ctx, `
|
||
SELECT id, section_id, service_id, name, price, unit, price_from
|
||
FROM price_items
|
||
WHERE published
|
||
ORDER BY sort, name`)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer itemRows.Close()
|
||
|
||
for itemRows.Next() {
|
||
var it domain.PriceItem
|
||
var sectionID int64
|
||
if err := itemRows.Scan(&it.ID, §ionID, &it.ServiceID, &it.Name,
|
||
&it.Price, &it.Unit, &it.From); err != nil {
|
||
return nil, err
|
||
}
|
||
if sec, ok := byID[sectionID]; ok {
|
||
sec.Items = append(sec.Items, it)
|
||
}
|
||
}
|
||
if err := itemRows.Err(); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var roots []*domain.PriceSection
|
||
for _, sec := range all {
|
||
if sec.ParentID == nil {
|
||
roots = append(roots, sec)
|
||
continue
|
||
}
|
||
if parent, ok := byID[*sec.ParentID]; ok {
|
||
parent.Children = append(parent.Children, sec)
|
||
}
|
||
}
|
||
|
||
if sectionSlug != "" {
|
||
for _, sec := range all {
|
||
if sec.Slug == sectionSlug {
|
||
return []*domain.PriceSection{sec}, nil
|
||
}
|
||
}
|
||
return nil, ErrNotFound
|
||
}
|
||
return roots, nil
|
||
}
|