mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// ExpenseController handles expense-related operations
|
|
type ExpenseController struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewExpenseController creates a new expense controller
|
|
func NewExpenseController(db *gorm.DB) *ExpenseController {
|
|
return &ExpenseController{db: db}
|
|
}
|
|
|
|
// UploadReceipt handles receipt upload and OCR processing
|
|
func (ec *ExpenseController) UploadReceipt(c *gin.Context) {
|
|
// Get the uploaded file
|
|
file, header, err := c.Request.FormFile("receipt")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "No file uploaded"})
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
// Validate file type
|
|
allowedTypes := []string{"image/jpeg", "image/jpg", "image/png", "application/pdf"}
|
|
if !contains(allowedTypes, header.Header.Get("Content-Type")) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid file type. Only JPEG, PNG, and PDF files are allowed"})
|
|
return
|
|
}
|
|
|
|
// Generate unique filename
|
|
ext := filepath.Ext(header.Filename)
|
|
filename := fmt.Sprintf("receipt_%d%s", time.Now().UnixNano(), ext)
|
|
|
|
// Save file to uploads directory
|
|
filePath := filepath.Join("uploads", "receipts", filename)
|
|
if err := c.SaveUploadedFile(header, filePath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file"})
|
|
return
|
|
}
|
|
|
|
// Perform OCR processing (placeholder)
|
|
ocrData, accuracy, err := ec.performOCR(filePath)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "OCR processing failed"})
|
|
return
|
|
}
|
|
|
|
// Parse receipt data (placeholder)
|
|
parsedData := parseReceiptData(ocrData)
|
|
|
|
response := gin.H{
|
|
"file_path": filePath,
|
|
"file_name": filename,
|
|
"file_size": header.Size,
|
|
"ocr_data": ocrData,
|
|
"ocr_accuracy": accuracy,
|
|
"parsed_data": parsedData,
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"receipt": response,
|
|
})
|
|
}
|
|
|
|
// performOCR performs OCR on the uploaded file
|
|
func (ec *ExpenseController) performOCR(filePath string) (string, float64, error) {
|
|
// This is a placeholder for OCR implementation
|
|
// In a real implementation, you would use Tesseract or another OCR service
|
|
return "Sample OCR text", 95.0, nil
|
|
}
|
|
|
|
// parseReceiptData parses OCR text to extract structured data
|
|
func parseReceiptData(ocrText string) map[string]interface{} {
|
|
// This is a placeholder for receipt parsing logic
|
|
// In a real implementation, you would use regex patterns or ML to extract:
|
|
// - Merchant name
|
|
// - Date
|
|
// - Total amount
|
|
// - VAT
|
|
// - Items
|
|
|
|
parsed := map[string]interface{}{
|
|
"merchant": "",
|
|
"date": "",
|
|
"total": 0,
|
|
"vat": 0,
|
|
"items": []map[string]interface{}{},
|
|
}
|
|
|
|
return parsed
|
|
}
|
|
|
|
// Helper function to check if slice contains string
|
|
func contains(slice []string, item string) bool {
|
|
for _, s := range slice {
|
|
if s == item {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|