Restructured project
- backend moved to backend directory - added and initialized frontend with vue - moved infrastructure files to infra directory
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const issuedAtLayout = "02/01/2006, 15:04:05"
|
||||
|
||||
var knownDateFormats = []string{
|
||||
"02.01.2006", // 21.01.2026
|
||||
"02.01.06", // 21.01.2026
|
||||
"02-01-2006", // 21-01-2026
|
||||
"02/01/2006", // 21/01/2026
|
||||
//"2006/01/02", // 2026/01/21
|
||||
//"2006-01-02", // 2026-01-21
|
||||
//"2006.01.02", // 2026.01.21
|
||||
}
|
||||
|
||||
func NormalizeDateToISO(input string) (string, error) {
|
||||
input = strings.TrimSpace(input)
|
||||
for _, layout := range knownDateFormats {
|
||||
if t, err := time.Parse(layout, input); err == nil {
|
||||
return t.Format("2006-01-02"), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("unsupported date format")
|
||||
}
|
||||
|
||||
func ParseIssuedAt(value string) (time.Time, error) {
|
||||
return time.Parse(issuedAtLayout, value)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type JWTManager struct {
|
||||
secret string
|
||||
}
|
||||
|
||||
func NewJWTManager(secret string) *JWTManager {
|
||||
return &JWTManager{secret: secret}
|
||||
}
|
||||
|
||||
func (j *JWTManager) Generate(userID int64) (string, error) {
|
||||
claims := jwt.MapClaims{
|
||||
"user_id": userID,
|
||||
"exp": time.Now().Add(time.Hour * 24 * 7).Unix(),
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(j.secret))
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseFloat(value string) (float64, error) {
|
||||
value = strings.ReplaceAll(value, ",", ".")
|
||||
return strconv.ParseFloat(value, 64)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package utils
|
||||
|
||||
import "regexp"
|
||||
|
||||
type ReceiptMeta struct {
|
||||
Date string
|
||||
ReceiptID string
|
||||
}
|
||||
|
||||
func ExtractReceiptMeta(text string) ReceiptMeta {
|
||||
result := ReceiptMeta{}
|
||||
|
||||
// --- ДАТА ---
|
||||
datePatterns := []string{
|
||||
`(\d{2}[./-]\d{2}[./-]\d{4})`, // 25.01.2026
|
||||
`(\d{2}[./-]\d{2}[./-]\d{2})`, // 25.01.26
|
||||
`(\d{4}[./-]\d{2}[./-]\d{2})`, // 2026-01-25
|
||||
}
|
||||
|
||||
for _, pattern := range datePatterns {
|
||||
re := regexp.MustCompile(pattern)
|
||||
if match := re.FindString(text); match != "" {
|
||||
result.Date = match
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// --- НОМЕР ЧЕКА (24 символа) ---
|
||||
receiptRe := regexp.MustCompile(`\b[A-Za-z0-9]{24}\b`)
|
||||
result.ReceiptID = receiptRe.FindString(text)
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
||||
"github.com/liyue201/goqr"
|
||||
)
|
||||
|
||||
func DecodeQR(imageBytes []byte) ([]string, error) {
|
||||
img, _, err := image.Decode(bytes.NewReader(imageBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
codes, err := goqr.Recognize(img)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
println(codes)
|
||||
|
||||
var result []string
|
||||
for _, code := range codes {
|
||||
result = append(result, string(code.Payload))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user