9d845c8899
- backend moved to backend directory - added and initialized frontend with vue - moved infrastructure files to infra directory
153 lines
3.2 KiB
Go
153 lines
3.2 KiB
Go
package receiptService
|
|
|
|
import (
|
|
"FamilyHub/src/domain"
|
|
"FamilyHub/src/repositories"
|
|
"FamilyHub/src/utils"
|
|
"bytes"
|
|
"context"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type ReceiptService struct {
|
|
client *http.Client
|
|
repo repositories.ReceiptsRepository
|
|
}
|
|
|
|
func NewReceiptService(repo repositories.ReceiptsRepository) *ReceiptService {
|
|
return &ReceiptService{
|
|
client: &http.Client{
|
|
Timeout: 60 * time.Second,
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
},
|
|
},
|
|
},
|
|
repo: repo,
|
|
}
|
|
}
|
|
|
|
func (s *ReceiptService) GetReceipt(
|
|
ctx context.Context,
|
|
date string,
|
|
number string,
|
|
) (*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(
|
|
ctx,
|
|
http.MethodPost,
|
|
url,
|
|
body,
|
|
)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set("Content-Type", contentType)
|
|
|
|
resp, err := s.client.Do(req)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
log.Printf("external service returned %d\n", resp.StatusCode)
|
|
return nil, fmt.Errorf("external service returned %d", resp.StatusCode)
|
|
}
|
|
|
|
var raw struct {
|
|
Message map[string]interface{} `json:"message"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&raw); err != nil {
|
|
log.Printf("external service returned %s\n", err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
bytes_, _ := json.Marshal(raw.Message)
|
|
|
|
if err := json.Unmarshal(bytes_, &receipt); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if receipt.IssuedAtRaw == "" {
|
|
return nil, errors.New("receipt not found")
|
|
}
|
|
|
|
positions, err := parsePositions(receipt.PositionsRaw)
|
|
if err != nil {
|
|
log.Printf("failed to parse positions: %s", err.Error())
|
|
return nil, err
|
|
}
|
|
receipt.IssuedAt, err = utils.ParseIssuedAt(receipt.IssuedAtRaw)
|
|
if err != nil {
|
|
log.Printf("failed to parse issued at: %s", err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
receipt.Positions = positions
|
|
|
|
for i := range receipt.Positions {
|
|
p := &receipt.Positions[i]
|
|
|
|
p.ProductCount, err = utils.ParseFloat(p.ProductCountRaw)
|
|
if err != nil {
|
|
log.Printf("failed to parse product count: %s", err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
p.Amount, err = utils.ParseFloat(p.AmountRaw)
|
|
if err != nil {
|
|
log.Printf("failed to parse amount: %s", err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
p.Discount, _ = utils.ParseFloat(p.DiscountRaw)
|
|
p.Surcharge, _ = utils.ParseFloat(p.SurchargeRaw)
|
|
}
|
|
|
|
if _, err := s.repo.Create(ctx, &receipt); err != nil {
|
|
return nil, err
|
|
}
|
|
return &receipt, nil
|
|
}
|
|
|
|
func buildMultipartBody(date, number string) (*bytes.Buffer, string) {
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
|
|
_ = writer.WriteField("orig_date", date)
|
|
_ = writer.WriteField("orig_ui", number)
|
|
|
|
_ = writer.Close()
|
|
|
|
return body, writer.FormDataContentType()
|
|
}
|
|
|
|
func parsePositions(raw string) ([]domain.Position, error) {
|
|
var positions []domain.Position
|
|
|
|
if raw == "" {
|
|
return positions, nil
|
|
}
|
|
|
|
if err := json.Unmarshal([]byte(raw), &positions); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return positions, nil
|
|
}
|