Added transaction feature, fixed some mistakes
This commit is contained in:
@@ -13,15 +13,20 @@ import (
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ReceiptService struct {
|
||||
client *http.Client
|
||||
repo repositories.ReceiptsRepository
|
||||
client *http.Client
|
||||
repo repositories.ReceiptsRepository
|
||||
transactionRepo repositories.TransactionRepository
|
||||
}
|
||||
|
||||
func NewReceiptService(repo repositories.ReceiptsRepository) *ReceiptService {
|
||||
func NewReceiptService(
|
||||
repo repositories.ReceiptsRepository,
|
||||
transactionRepo repositories.TransactionRepository,
|
||||
) *ReceiptService {
|
||||
return &ReceiptService{
|
||||
client: &http.Client{
|
||||
Timeout: 60 * time.Second,
|
||||
@@ -31,20 +36,20 @@ func NewReceiptService(repo repositories.ReceiptsRepository) *ReceiptService {
|
||||
},
|
||||
},
|
||||
},
|
||||
repo: repo,
|
||||
repo: repo,
|
||||
transactionRepo: transactionRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ReceiptService) GetReceipt(
|
||||
ctx context.Context,
|
||||
date string,
|
||||
number string,
|
||||
req domain.AddReceiptRequest,
|
||||
) (*domain.Receipt, error) {
|
||||
url := "https://ch.info-center.by/ajax/check1.php"
|
||||
var receipt domain.Receipt
|
||||
|
||||
body, contentType := buildMultipartBody(date, number)
|
||||
req, err := http.NewRequestWithContext(
|
||||
body, contentType := buildMultipartBody(req.Date, req.Number)
|
||||
httpReq, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
url,
|
||||
@@ -55,9 +60,9 @@ func (s *ReceiptService) GetReceipt(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
httpReq.Header.Set("Content-Type", contentType)
|
||||
|
||||
resp, err := s.client.Do(req)
|
||||
resp, err := s.client.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
return nil, err
|
||||
@@ -119,9 +124,23 @@ func (s *ReceiptService) GetReceipt(
|
||||
p.Surcharge, _ = utils.ParseFloat(p.SurchargeRaw)
|
||||
}
|
||||
|
||||
if _, err := s.repo.Create(ctx, &receipt); err != nil {
|
||||
receiptID, err := s.repo.Create(ctx, &receipt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
receipt.ID = int(receiptID)
|
||||
|
||||
if s.shouldCreateTransaction(req) {
|
||||
transaction, err := s.createTransactionForReceipt(ctx, &receipt, req, receiptID)
|
||||
if err != nil {
|
||||
if rollbackErr := s.repo.Delete(ctx, receiptID); rollbackErr != nil {
|
||||
log.Printf("failed to rollback receipt %d after transaction error: %v", receiptID, rollbackErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
receipt.TransactionID = &transaction.ID
|
||||
}
|
||||
|
||||
return &receipt, nil
|
||||
}
|
||||
|
||||
@@ -150,3 +169,61 @@ func parsePositions(raw string) ([]domain.Position, error) {
|
||||
|
||||
return positions, nil
|
||||
}
|
||||
|
||||
func (s *ReceiptService) shouldCreateTransaction(req domain.AddReceiptRequest) bool {
|
||||
return s.transactionRepo != nil && req.FamilyID != nil && req.CreatedBy != nil
|
||||
}
|
||||
|
||||
func (s *ReceiptService) createTransactionForReceipt(
|
||||
ctx context.Context,
|
||||
receipt *domain.Receipt,
|
||||
req domain.AddReceiptRequest,
|
||||
receiptID int64,
|
||||
) (*domain.Transaction, error) {
|
||||
transactionType := "expense"
|
||||
if req.Type != nil && strings.TrimSpace(*req.Type) != "" {
|
||||
transactionType = strings.TrimSpace(*req.Type)
|
||||
}
|
||||
|
||||
category := "receipt"
|
||||
if req.Category != nil && strings.TrimSpace(*req.Category) != "" {
|
||||
category = strings.TrimSpace(*req.Category)
|
||||
}
|
||||
|
||||
description := buildReceiptTransactionDescription(receipt, req.Description)
|
||||
|
||||
transaction := &domain.Transaction{
|
||||
FamilyID: *req.FamilyID,
|
||||
Description: description,
|
||||
Type: transactionType,
|
||||
DateTime: receipt.IssuedAt,
|
||||
Category: category,
|
||||
Amount: receipt.TotalAmount,
|
||||
CreatedBy: *req.CreatedBy,
|
||||
ReceiptID: &receiptID,
|
||||
}
|
||||
|
||||
if err := s.transactionRepo.Create(ctx, transaction); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return transaction, nil
|
||||
}
|
||||
|
||||
func buildReceiptTransactionDescription(receipt *domain.Receipt, explicit *string) *string {
|
||||
if explicit != nil && strings.TrimSpace(*explicit) != "" {
|
||||
value := strings.TrimSpace(*explicit)
|
||||
return &value
|
||||
}
|
||||
|
||||
if name := strings.TrimSpace(receipt.NameSPD); name != "" {
|
||||
return &name
|
||||
}
|
||||
|
||||
if number := strings.TrimSpace(receipt.ReceiptNumber); number != "" {
|
||||
value := fmt.Sprintf("Receipt %s", number)
|
||||
return &value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user