mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
3001-фух.это был сильный спринт.
сервис стал сильно лучше черновики сохраняются одним запросом дто черновиков вынесен отдельно
This commit is contained in:
@@ -958,3 +958,205 @@ func (s *Service) ReorderItems(draftID uuid.UUID, items []struct {
|
||||
// Вызываем метод репозитория для обновления порядка
|
||||
return s.draftRepo.ReorderItems(draftID, items)
|
||||
}
|
||||
|
||||
// SaveDraftFull обновляет черновик (шапку и позиции) пакетно в одной транзакции
|
||||
func (s *Service) SaveDraftFull(draftID, userID uuid.UUID, req drafts.UpdateDraftRequest) error {
|
||||
// Получаем черновик для проверки прав доступа
|
||||
draft, err := s.GetDraft(draftID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Проверяем, что черновик не завершен
|
||||
if draft.Status == drafts.StatusCompleted {
|
||||
return errors.New("черновик уже отправлен")
|
||||
}
|
||||
|
||||
// Обновляем шапку черновика, если переданы поля
|
||||
headerUpdated := false
|
||||
|
||||
// 1. Дата (Обязательное поле, не может быть nil)
|
||||
if req.DateIncoming != nil && *req.DateIncoming != "" {
|
||||
parsedDate, err := time.Parse("2006-01-02", *req.DateIncoming)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid date format: %w", err)
|
||||
}
|
||||
draft.DateIncoming = &parsedDate
|
||||
headerUpdated = true
|
||||
}
|
||||
|
||||
// 2. Склад (Может быть nil/сброшен)
|
||||
if req.StoreID != nil {
|
||||
if *req.StoreID == "" {
|
||||
draft.StoreID = nil
|
||||
} else {
|
||||
uid, err := uuid.Parse(*req.StoreID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid store_id: %w", err)
|
||||
}
|
||||
draft.StoreID = &uid
|
||||
}
|
||||
headerUpdated = true
|
||||
}
|
||||
|
||||
// 3. Поставщик (Может быть nil/сброшен)
|
||||
if req.SupplierID != nil {
|
||||
if *req.SupplierID == "" {
|
||||
draft.SupplierID = nil
|
||||
} else {
|
||||
uid, err := uuid.Parse(*req.SupplierID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid supplier_id: %w", err)
|
||||
}
|
||||
draft.SupplierID = &uid
|
||||
}
|
||||
headerUpdated = true
|
||||
}
|
||||
|
||||
// 4. Комментарий
|
||||
if req.Comment != nil {
|
||||
draft.Comment = *req.Comment
|
||||
headerUpdated = true
|
||||
}
|
||||
|
||||
// 5. Входящий номер
|
||||
if req.IncomingDocumentNumber != nil {
|
||||
draft.IncomingDocumentNumber = *req.IncomingDocumentNumber
|
||||
headerUpdated = true
|
||||
}
|
||||
|
||||
// Если были изменения в шапке — сохраняем
|
||||
if headerUpdated {
|
||||
if err := s.draftRepo.Update(draft); err != nil {
|
||||
return fmt.Errorf("failed to update draft header: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Обновляем позиции, если переданы
|
||||
if len(req.Items) > 0 {
|
||||
for _, itemReq := range req.Items {
|
||||
if itemReq.ID == nil || *itemReq.ID == "" {
|
||||
return errors.New("item id is required")
|
||||
}
|
||||
|
||||
itemID, err := uuid.Parse(*itemReq.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid item id: %s", *itemReq.ID)
|
||||
}
|
||||
|
||||
// Получаем текущую позицию
|
||||
currentItem, err := s.draftRepo.GetItemByID(itemID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("item not found: %s", itemID.String())
|
||||
}
|
||||
|
||||
// Проверяем, что позиция принадлежит черновику
|
||||
if currentItem.DraftID != draftID {
|
||||
return fmt.Errorf("item %s does not belong to draft %s", itemID.String(), draftID.String())
|
||||
}
|
||||
|
||||
// Обновляем поля позиции
|
||||
if itemReq.ProductID != nil {
|
||||
if *itemReq.ProductID == "" {
|
||||
currentItem.ProductID = nil
|
||||
currentItem.IsMatched = false
|
||||
currentItem.ContainerID = nil // Если убрали товар, фасовку тоже надо обнулить
|
||||
} else {
|
||||
parsedID, err := uuid.Parse(*itemReq.ProductID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid product_id for item %s", itemID.String())
|
||||
}
|
||||
currentItem.ProductID = &parsedID
|
||||
currentItem.IsMatched = true
|
||||
}
|
||||
}
|
||||
|
||||
if itemReq.ContainerID != nil {
|
||||
if *itemReq.ContainerID == "" {
|
||||
// Сброс фасовки
|
||||
currentItem.ContainerID = nil
|
||||
} else {
|
||||
parsedID, err := uuid.Parse(*itemReq.ContainerID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container_id for item %s", itemID.String())
|
||||
}
|
||||
currentItem.ContainerID = &parsedID
|
||||
}
|
||||
}
|
||||
|
||||
// Определяем, какое поле редактируется
|
||||
editedField := itemReq.EditedField
|
||||
if editedField == "" {
|
||||
if itemReq.Sum != nil {
|
||||
editedField = "sum"
|
||||
} else if itemReq.Price != nil {
|
||||
editedField = "price"
|
||||
} else if itemReq.Quantity != nil {
|
||||
editedField = "quantity"
|
||||
}
|
||||
}
|
||||
|
||||
// Обновляем числовые поля
|
||||
qty := decimal.Zero
|
||||
if itemReq.Quantity != nil {
|
||||
qty = decimal.NewFromFloat(*itemReq.Quantity)
|
||||
} else {
|
||||
qty = currentItem.Quantity
|
||||
}
|
||||
|
||||
price := decimal.Zero
|
||||
if itemReq.Price != nil {
|
||||
price = decimal.NewFromFloat(*itemReq.Price)
|
||||
} else {
|
||||
price = currentItem.Price
|
||||
}
|
||||
|
||||
sum := decimal.Zero
|
||||
if itemReq.Sum != nil {
|
||||
sum = decimal.NewFromFloat(*itemReq.Sum)
|
||||
} else {
|
||||
sum = currentItem.Sum
|
||||
}
|
||||
|
||||
// Применяем изменения в зависимости от редактируемого поля
|
||||
field := drafts.EditedField(editedField)
|
||||
switch field {
|
||||
case drafts.FieldQuantity:
|
||||
currentItem.Quantity = qty
|
||||
case drafts.FieldPrice:
|
||||
currentItem.Price = price
|
||||
case drafts.FieldSum:
|
||||
currentItem.Sum = sum
|
||||
}
|
||||
|
||||
// Пересчитываем поля
|
||||
s.RecalculateItemFields(currentItem, field)
|
||||
|
||||
// Обновляем статус черновика, если он был отменен
|
||||
if draft.Status == drafts.StatusCanceled {
|
||||
draft.Status = drafts.StatusReadyToVerify
|
||||
if err := s.draftRepo.Update(draft); err != nil {
|
||||
return fmt.Errorf("failed to update draft status: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Сохраняем обновленную позицию
|
||||
updates := map[string]interface{}{
|
||||
"product_id": currentItem.ProductID,
|
||||
"container_id": currentItem.ContainerID,
|
||||
"quantity": currentItem.Quantity,
|
||||
"price": currentItem.Price,
|
||||
"sum": currentItem.Sum,
|
||||
"last_edited_field1": currentItem.LastEditedField1,
|
||||
"last_edited_field2": currentItem.LastEditedField2,
|
||||
"is_matched": currentItem.IsMatched,
|
||||
}
|
||||
|
||||
if err := s.draftRepo.UpdateItem(itemID, updates); err != nil {
|
||||
return fmt.Errorf("failed to update item %s: %w", itemID.String(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user