mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
добавил архив фото, откуда можно удалить и посмотреть
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"rmser/internal/domain/catalog"
|
||||
"rmser/internal/domain/drafts"
|
||||
"rmser/internal/domain/ocr"
|
||||
"rmser/internal/domain/photos"
|
||||
"rmser/internal/infrastructure/ocr_client"
|
||||
)
|
||||
|
||||
@@ -22,6 +24,7 @@ type Service struct {
|
||||
catalogRepo catalog.Repository
|
||||
draftRepo drafts.Repository
|
||||
accountRepo account.Repository
|
||||
photoRepo photos.Repository
|
||||
pyClient *ocr_client.Client
|
||||
storagePath string
|
||||
}
|
||||
@@ -31,6 +34,7 @@ func NewService(
|
||||
catalogRepo catalog.Repository,
|
||||
draftRepo drafts.Repository,
|
||||
accountRepo account.Repository,
|
||||
photoRepo photos.Repository,
|
||||
pyClient *ocr_client.Client,
|
||||
storagePath string,
|
||||
) *Service {
|
||||
@@ -39,6 +43,7 @@ func NewService(
|
||||
catalogRepo: catalogRepo,
|
||||
draftRepo: draftRepo,
|
||||
accountRepo: accountRepo,
|
||||
photoRepo: photoRepo,
|
||||
pyClient: pyClient,
|
||||
storagePath: storagePath,
|
||||
}
|
||||
@@ -58,37 +63,56 @@ func (s *Service) checkWriteAccess(userID, serverID uuid.UUID) error {
|
||||
|
||||
// ProcessReceiptImage - Доступно всем (включая Операторов)
|
||||
func (s *Service) ProcessReceiptImage(ctx context.Context, userID uuid.UUID, imgData []byte) (*drafts.DraftInvoice, error) {
|
||||
// 1. Получаем активный сервер для UserID
|
||||
server, err := s.accountRepo.GetActiveServer(userID)
|
||||
if err != nil || server == nil {
|
||||
return nil, fmt.Errorf("no active server for user")
|
||||
}
|
||||
serverID := server.ID
|
||||
|
||||
// 2. Создаем черновик
|
||||
draft := &drafts.DraftInvoice{
|
||||
UserID: userID,
|
||||
RMSServerID: serverID,
|
||||
Status: drafts.StatusProcessing,
|
||||
StoreID: server.DefaultStoreID,
|
||||
}
|
||||
// 1. Создаем ID для фото и черновика
|
||||
photoID := uuid.New()
|
||||
draftID := uuid.New()
|
||||
|
||||
draft.ID = uuid.New()
|
||||
|
||||
fileName := fmt.Sprintf("receipt_%s.jpg", draft.ID.String())
|
||||
fileName := fmt.Sprintf("receipt_%s.jpg", photoID.String())
|
||||
filePath := filepath.Join(s.storagePath, fileName)
|
||||
|
||||
// 2. Сохраняем файл
|
||||
if err := os.WriteFile(filePath, imgData, 0644); err != nil {
|
||||
return nil, fmt.Errorf("failed to save image: %w", err)
|
||||
}
|
||||
fileURL := "/uploads/" + fileName
|
||||
|
||||
draft.SenderPhotoURL = "/uploads/" + fileName
|
||||
// 3. Создаем запись ReceiptPhoto
|
||||
photo := &photos.ReceiptPhoto{
|
||||
ID: photoID,
|
||||
RMSServerID: serverID,
|
||||
UploadedBy: userID,
|
||||
FilePath: filePath,
|
||||
FileURL: fileURL,
|
||||
FileName: fileName,
|
||||
FileSize: int64(len(imgData)),
|
||||
DraftID: &draftID, // Сразу связываем с будущим черновиком
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if err := s.photoRepo.Create(photo); err != nil {
|
||||
return nil, fmt.Errorf("failed to create photo record: %w", err)
|
||||
}
|
||||
|
||||
// 4. Создаем черновик
|
||||
draft := &drafts.DraftInvoice{
|
||||
ID: draftID,
|
||||
UserID: userID,
|
||||
RMSServerID: serverID,
|
||||
Status: drafts.StatusProcessing,
|
||||
StoreID: server.DefaultStoreID,
|
||||
SenderPhotoURL: fileURL, // Оставляем для совместимости, но теперь есть ReceiptPhoto
|
||||
}
|
||||
|
||||
if err := s.draftRepo.Create(draft); err != nil {
|
||||
return nil, fmt.Errorf("failed to create draft: %w", err)
|
||||
}
|
||||
|
||||
// 3. Отправляем в Python OCR
|
||||
// 5. Отправляем в Python OCR
|
||||
rawResult, err := s.pyClient.ProcessImage(ctx, imgData, "receipt.jpg")
|
||||
if err != nil {
|
||||
draft.Status = drafts.StatusError
|
||||
@@ -96,9 +120,8 @@ func (s *Service) ProcessReceiptImage(ctx context.Context, userID uuid.UUID, img
|
||||
return nil, fmt.Errorf("python ocr error: %w", err)
|
||||
}
|
||||
|
||||
// 4. Матчинг (с учетом ServerID)
|
||||
// 6. Матчинг и сохранение позиций
|
||||
var draftItems []drafts.DraftInvoiceItem
|
||||
|
||||
for _, rawItem := range rawResult.Items {
|
||||
item := drafts.DraftInvoiceItem{
|
||||
DraftID: draft.ID,
|
||||
@@ -111,23 +134,19 @@ func (s *Service) ProcessReceiptImage(ctx context.Context, userID uuid.UUID, img
|
||||
}
|
||||
|
||||
match, _ := s.ocrRepo.FindMatch(serverID, rawItem.RawName)
|
||||
|
||||
if match != nil {
|
||||
item.IsMatched = true
|
||||
item.ProductID = &match.ProductID
|
||||
item.ContainerID = match.ContainerID
|
||||
} else {
|
||||
s.ocrRepo.UpsertUnmatched(serverID, rawItem.RawName) // <-- ServerID
|
||||
s.ocrRepo.UpsertUnmatched(serverID, rawItem.RawName)
|
||||
}
|
||||
|
||||
draftItems = append(draftItems, item)
|
||||
}
|
||||
|
||||
// 5. Сохраняем
|
||||
draft.Status = drafts.StatusReadyToVerify
|
||||
s.draftRepo.Update(draft)
|
||||
s.draftRepo.CreateItems(draftItems)
|
||||
|
||||
draft.Items = draftItems
|
||||
|
||||
return draft, nil
|
||||
|
||||
Reference in New Issue
Block a user