mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
пофиксил неправильный пересчет фасовок в накладной
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -27,6 +28,7 @@ type Service struct {
|
||||
catalogRepo catalog.Repository
|
||||
accountRepo account.Repository
|
||||
supplierRepo suppliers.Repository
|
||||
invoiceRepo invoices.Repository
|
||||
rmsFactory *rms.Factory
|
||||
billingService *billing.Service
|
||||
}
|
||||
@@ -37,6 +39,7 @@ func NewService(
|
||||
catalogRepo catalog.Repository,
|
||||
accountRepo account.Repository,
|
||||
supplierRepo suppliers.Repository,
|
||||
invoiceRepo invoices.Repository,
|
||||
rmsFactory *rms.Factory,
|
||||
billingService *billing.Service,
|
||||
) *Service {
|
||||
@@ -46,6 +49,7 @@ func NewService(
|
||||
catalogRepo: catalogRepo,
|
||||
accountRepo: accountRepo,
|
||||
supplierRepo: supplierRepo,
|
||||
invoiceRepo: invoiceRepo,
|
||||
rmsFactory: rmsFactory,
|
||||
billingService: billingService,
|
||||
}
|
||||
@@ -220,6 +224,7 @@ func (s *Service) UpdateItem(draftID, itemID uuid.UUID, productID *uuid.UUID, co
|
||||
return s.draftRepo.UpdateItem(itemID, productID, containerID, qty, price)
|
||||
}
|
||||
|
||||
// CommitDraft отправляет накладную
|
||||
// CommitDraft отправляет накладную
|
||||
func (s *Service) CommitDraft(draftID, userID uuid.UUID) (string, error) {
|
||||
// 1. Получаем сервер и права
|
||||
@@ -285,11 +290,39 @@ func (s *Service) CommitDraft(draftID, userID uuid.UUID) (string, error) {
|
||||
sum = dItem.Quantity.Mul(dItem.Price)
|
||||
}
|
||||
|
||||
// Инициализируем значениями из черновика (по умолчанию для базовых единиц)
|
||||
amountToSend := dItem.Quantity
|
||||
priceToSend := dItem.Price
|
||||
|
||||
// ЛОГИКА ПЕРЕСЧЕТА ДЛЯ ФАСОВОК (СОГЛАСНО ДОКУМЕНТАЦИИ IIKO)
|
||||
// Если указан ContainerID, iiko требует:
|
||||
// <amount> = кол-во упаковок * вес упаковки (итоговое кол-во в базовых единицах)
|
||||
// <price> = цена за упаковку / вес упаковки (цена за базовую единицу)
|
||||
// <containerId> = ID фасовки
|
||||
if dItem.ContainerID != nil && *dItem.ContainerID != uuid.Nil {
|
||||
// Проверяем, что Container загружен (Preload в репозитории)
|
||||
if dItem.Container != nil {
|
||||
if !dItem.Container.Count.IsZero() {
|
||||
// 1. Пересчитываем кол-во: 5 ящиков * 10 кг = 50 кг
|
||||
amountToSend = dItem.Quantity.Mul(dItem.Container.Count)
|
||||
|
||||
// 2. Пересчитываем цену: 1000 руб/ящ / 10 кг = 100 руб/кг
|
||||
priceToSend = dItem.Price.Div(dItem.Container.Count)
|
||||
}
|
||||
} else {
|
||||
// Если фасовка есть в ID, но не подгрузилась структура - это ошибка данных.
|
||||
// Логируем варнинг, но пробуем отправить как есть (iiko может отвергнуть или посчитать криво)
|
||||
logger.Log.Warn("Container struct is nil for item with ContainerID",
|
||||
zap.String("item_id", dItem.ID.String()),
|
||||
zap.String("container_id", dItem.ContainerID.String()))
|
||||
}
|
||||
}
|
||||
|
||||
invItem := invoices.InvoiceItem{
|
||||
ProductID: *dItem.ProductID,
|
||||
Amount: dItem.Quantity,
|
||||
Price: dItem.Price,
|
||||
Sum: sum,
|
||||
Amount: amountToSend, // Отправляем ПЕРЕСЧИТАННЫЙ вес/объем
|
||||
Price: priceToSend, // Отправляем ПЕРЕСЧИТАННУЮ цену за базовую ед.
|
||||
Sum: sum, // Сумма остается неизменной (Total)
|
||||
ContainerID: dItem.ContainerID,
|
||||
}
|
||||
inv.Items = append(inv.Items, invItem)
|
||||
@@ -424,3 +457,99 @@ func (s *Service) CreateProductContainer(userID uuid.UUID, productID uuid.UUID,
|
||||
|
||||
return createdID, nil
|
||||
}
|
||||
|
||||
// Добавим новый DTO для единого списка (Frontend Contract)
|
||||
type UnifiedInvoiceDTO struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Type string `json:"type"` // "DRAFT" или "SYNCED"
|
||||
DocumentNumber string `json:"document_number"`
|
||||
IncomingNumber string `json:"incoming_number"`
|
||||
DateIncoming time.Time `json:"date_incoming"`
|
||||
Status string `json:"status"`
|
||||
TotalSum float64 `json:"total_sum"`
|
||||
StoreName string `json:"store_name"`
|
||||
ItemsCount int `json:"items_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
IsAppCreated bool `json:"is_app_created"`
|
||||
}
|
||||
|
||||
func (s *Service) GetUnifiedList(userID uuid.UUID, from, to time.Time) ([]UnifiedInvoiceDTO, error) {
|
||||
server, err := s.accountRepo.GetActiveServer(userID)
|
||||
if err != nil || server == nil {
|
||||
return nil, errors.New("активный сервер не выбран")
|
||||
}
|
||||
|
||||
// 1. Получаем черновики (их обычно немного, берем все активные)
|
||||
draftsList, err := s.draftRepo.GetActive(server.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. Получаем синхронизированные накладные за период
|
||||
invoicesList, err := s.invoiceRepo.GetByPeriod(server.ID, from, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]UnifiedInvoiceDTO, 0, len(draftsList)+len(invoicesList))
|
||||
|
||||
// Маппим черновики
|
||||
for _, d := range draftsList {
|
||||
var sum decimal.Decimal
|
||||
for _, it := range d.Items {
|
||||
if !it.Sum.IsZero() {
|
||||
sum = sum.Add(it.Sum)
|
||||
} else {
|
||||
sum = sum.Add(it.Quantity.Mul(it.Price))
|
||||
}
|
||||
}
|
||||
|
||||
val, _ := sum.Float64()
|
||||
date := time.Now()
|
||||
if d.DateIncoming != nil {
|
||||
date = *d.DateIncoming
|
||||
}
|
||||
|
||||
result = append(result, UnifiedInvoiceDTO{
|
||||
ID: d.ID,
|
||||
Type: "DRAFT",
|
||||
DocumentNumber: d.DocumentNumber,
|
||||
IncomingNumber: "", // В черновиках пока не разделяем
|
||||
DateIncoming: date,
|
||||
Status: d.Status,
|
||||
TotalSum: val,
|
||||
StoreName: "", // Можно подгрузить из d.Store.Name если сделан Preload
|
||||
ItemsCount: len(d.Items),
|
||||
CreatedAt: d.CreatedAt,
|
||||
IsAppCreated: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Маппим проведенные
|
||||
for _, inv := range invoicesList {
|
||||
var sum decimal.Decimal
|
||||
for _, it := range inv.Items {
|
||||
sum = sum.Add(it.Sum)
|
||||
}
|
||||
val, _ := sum.Float64()
|
||||
|
||||
isOurs := strings.Contains(strings.ToUpper(inv.Comment), "RMSER")
|
||||
|
||||
result = append(result, UnifiedInvoiceDTO{
|
||||
ID: inv.ID,
|
||||
Type: "SYNCED",
|
||||
DocumentNumber: inv.DocumentNumber,
|
||||
IncomingNumber: inv.IncomingDocumentNumber,
|
||||
DateIncoming: inv.DateIncoming,
|
||||
Status: inv.Status,
|
||||
TotalSum: val,
|
||||
ItemsCount: len(inv.Items),
|
||||
CreatedAt: inv.CreatedAt,
|
||||
IsAppCreated: isOurs,
|
||||
})
|
||||
}
|
||||
|
||||
// Сортировка по дате накладной (desc)
|
||||
// (Здесь можно добавить библиотеку sort или оставить как есть, если БД уже отсортировала части)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user