package database import ( "fmt" "log" "time" ) type ProductService struct { dbr *DatabaseReader } type Container struct { Products map[string]int `json:"products"` Context Context `json:"context"` } type Product struct { Warehouse string `json:"warehouse"` Quantity int `json:"quantity"` Delivery int `json:"delivery_time"` WhdId int `json:"-"` DeliveryId int `json:"-"` } type OutgoingProducts struct { Products map[string][]Product `json:"products"` } type OutgoingReservationProducts struct { Id UUID `json:"id"` Products map[string][]Product `json:"products"` } func NewOutgoingProducts() *OutgoingProducts { op := OutgoingProducts{ Products: make(map[string][]Product), } return &op } func NewOutgoingReservationsProducts(groupId UUID) *OutgoingReservationProducts { op := OutgoingReservationProducts{ Id: groupId, Products: make(map[string][]Product), } return &op } type Context struct { Country string `json:"country"` State string `json:"state"` } func NewProductService(connectionString string) *ProductService { dbr := NewDatabaseReader(connectionString) p := ProductService{dbr: dbr} return &p } func (p *ProductService) Autorelease() { //Das müsste saubererer sein. Spare ich mir aber, weil der Webserver alles blockiert. //Besser wäre das Arbeiten mit Context. Gefahr ist aber minimal go func() { for { fmt.Println("Prüfe nach Registrierungen die Freigegeben werden können. (Älter als 24 Stunden)") err := p.dbr.ReleaseReservierungenAfterOneDay() if err != nil { log.Printf("Fehler beim Ausführen von Autorelease() des Logs. %s", err) } time.Sleep(30 * time.Second) } }() } func (p *ProductService) ReserviereBestellungen(op []OutgoingReservationProducts, groupId UUID) (*[]UUID, error) { var uuids []UUID for _, hsmp := range op { for _, prod := range hsmp.Products { for _, concreteProduct := range prod { deliveryId := concreteProduct.DeliveryId warehouseId := concreteProduct.WhdId amount := concreteProduct.Quantity // Todo: Handler Injection wäre hier interessant uuid, err := p.dbr.ReserveReservationItem(deliveryId, warehouseId, amount, groupId) if err != nil { return nil, err } uuids = append(uuids, uuid) } } } return &uuids, nil } func (p *ProductService) ConfirmBestellung(groudId UUID) error { return p.dbr.ConfirmReservationGroup(groudId) } func (p *ProductService) AbortBestellung(groudId UUID) error { return p.dbr.AbortReservationGroup(groudId) } func (p *ProductService) ReleaseBestellung(groudId UUID) error { return p.dbr.ReleaseReservationGroup(groudId) } func (p *ProductService) FetchData(payload *Container) ([]OutgoingProducts, error) { result := []OutgoingProducts{} for key, item := range payload.Products { //Checken ob die Felder leer sind / Validitätsprüfung einbauen products, err := p.dbr.GetProductByProductIdDeliveryCountryAndState(key, payload.Context.Country, payload.Context.State) if err != nil { return nil, err } if len(products) == 0 { continue } gebrauchteProduktAnzahl := item op := NewOutgoingProducts() for _, db_products := range products { if gebrauchteProduktAnzahl <= 0 { continue } if db_products.Amount >= gebrauchteProduktAnzahl { newProduct := Product{Delivery: db_products.DeliveryDays, Quantity: gebrauchteProduktAnzahl, Warehouse: db_products.Warehouse, WhdId: db_products.Id, DeliveryId: db_products.DeliveryId} gebrauchteProduktAnzahl = 0 op.Products[key] = append(op.Products[key], newProduct) } else if db_products.Amount < gebrauchteProduktAnzahl { newProduct := Product{Delivery: db_products.DeliveryDays, Quantity: db_products.Amount, Warehouse: db_products.Warehouse, WhdId: db_products.Id, DeliveryId: db_products.DeliveryId} gebrauchteProduktAnzahl -= db_products.Amount op.Products[key] = append(op.Products[key], newProduct) } } result = append(result, *op) } return result, nil } func (p *ProductService) FetchReservationData(payload *Container, groupId UUID) ([]OutgoingReservationProducts, error) { result := []OutgoingReservationProducts{} for key, item := range payload.Products { //Checken ob die Felder leer sind / Validitätsprüfung einbauen products, err := p.dbr.GetProductByProductIdDeliveryCountryAndState(key, payload.Context.Country, payload.Context.State) if err != nil { return nil, err } if len(products) == 0 { continue } gebrauchteProduktAnzahl := item op := NewOutgoingReservationsProducts(groupId) for _, db_products := range products { if gebrauchteProduktAnzahl <= 0 { continue } if db_products.Amount >= gebrauchteProduktAnzahl { newProduct := Product{Delivery: db_products.DeliveryDays, Quantity: gebrauchteProduktAnzahl, Warehouse: db_products.Warehouse, WhdId: db_products.Id, DeliveryId: db_products.DeliveryId} gebrauchteProduktAnzahl = 0 op.Products[key] = append(op.Products[key], newProduct) } else if db_products.Amount < gebrauchteProduktAnzahl { newProduct := Product{Delivery: db_products.DeliveryDays, Quantity: db_products.Amount, Warehouse: db_products.Warehouse, WhdId: db_products.Id, DeliveryId: db_products.DeliveryId} gebrauchteProduktAnzahl -= db_products.Amount op.Products[key] = append(op.Products[key], newProduct) } } result = append(result, *op) } return result, nil }