2025-06-29 20:37:45 +02:00

154 lines
4.0 KiB
Go

package database
import (
"context"
"database/sql"
"fmt"
"os"
"strconv"
"strings"
"sync"
"time"
_ "github.com/go-sql-driver/mysql"
"gittea.marcokittel.de/elio/eliotools/eliofile"
"gittea.marcokittel.de/elio/eliotools/logger"
)
type DatabaseWriter struct {
wg *sync.WaitGroup
mu sync.Mutex
log logger.Logger
db *sql.DB
}
func (d *DatabaseWriter) connectDB() (*sql.DB, error) {
// Format: "username:password@tcp(host:port)/dbname?params"
//
db, err := sql.Open("mysql", "root:eliogeheim@tcp(127.0.0.1:3306)/elio?parseTime=true")
if err != nil {
return nil, err
}
// Verbindungspool konfigurieren
db.SetMaxOpenConns(40)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
return db, nil
}
func (d *DatabaseWriter) createWarehouseTableIfNotExist() error {
_, err := d.db.Exec(`
CREATE TABLE IF NOT EXISTS warehouseproducts (
id INT AUTO_INCREMENT PRIMARY KEY,
warehouse char(2) NOT NULL,
productid VARCHAR(20) NOT NULL,
amount INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT location_product_must_be_one UNIQUE (warehouse, productid)
) ENGINE=InnoDB;
`)
return err
}
func (d *DatabaseWriter) createDeliveryTableIfNotExist() error {
_, err := d.db.Exec(`
CREATE TABLE IF NOT EXISTS deliverytimes (
id INT AUTO_INCREMENT PRIMARY KEY,
fromcountry varchar(4) NOT NULL,
tocountry varchar(4) NOT NULL,
state varchar(4) NULL,
delivery INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT delivery_from_to_country_must_be_one UNIQUE (fromcountry, tocountry)
) ENGINE=InnoDB;`)
return err
}
func NewDatabaseWriter(wg *sync.WaitGroup) *DatabaseWriter {
db := DatabaseWriter{log: logger.NewMarcoLogger(),
wg: wg,
}
sql, err := db.connectDB()
if err != nil {
fmt.Printf("Datenbank nicht gefunden. %w", err)
os.Exit(1)
}
db.db = sql
err = db.createWarehouseTableIfNotExist()
if err != nil {
fmt.Printf("Warenhaus-Tabellen-Erstellung fehlgeschlagen. %w", err)
os.Exit(1)
}
err = db.createDeliveryTableIfNotExist()
if err != nil {
fmt.Printf("Delivery-Tablellen-Erstellung fehlgeschlagen. %w", err)
os.Exit(1)
}
return &db
}
func (d *DatabaseWriter) UpdateOrInsertWarehouseProduct(warehouse string, productID string, amount int) error {
_, err := d.db.Exec(`
INSERT INTO warehouseproducts (warehouse, productid, amount)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE amount = VALUES(amount)`,
warehouse, productID, amount)
if err != nil {
return fmt.Errorf("upsert failed: %w", err)
}
return nil
}
func (d *DatabaseWriter) UpdateOrInsertDelivery(fromcountry string, tocountry string, state string, delivery int) error {
_, err := d.db.Exec(`
INSERT INTO deliverytimes (fromcountry, tocountry, state, delivery)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
fromcountry = VALUES(fromcountry),
tocountry = VALUES(tocountry),
state = VALUES(state),
delivery = VALUES(delivery)`,
fromcountry, tocountry, state, delivery)
if err != nil {
return fmt.Errorf("upsert failed: %w", err)
}
return nil
}
func (db *DatabaseWriter) HandleData(ctx context.Context, data eliofile.CountryCsvData) error {
// a.log.Info("HandleData")
if strings.Contains(strings.Join(data.Data, ","), "product_id") || strings.Contains(strings.Join(data.Data, ","), "delivery_time") {
return nil
}
//Todo: Csv reparieren.
switch data.Type {
case "stock":
{
menge := strings.Split(data.Data[0], ";")
amount, err := strconv.Atoi(menge[1])
if err != nil {
fmt.Println(err)
return err
}
db.UpdateOrInsertWarehouseProduct(data.CountryID, menge[0], amount)
}
case "delivery":
{
menge := strings.Split(data.Data[0], ";")
amount, err := strconv.Atoi(menge[2])
if err != nil {
fmt.Println(err)
return err
}
db.UpdateOrInsertDelivery(data.CountryID, menge[0], menge[1], amount)
}
}
return nil
}