flamingo.me/flamingo-commerce/v3@v3.11.0/cart/infrastructure/placeorder/logger.go (about) 1 package logger 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "os" 9 "path" 10 "time" 11 12 cartDomain "flamingo.me/flamingo-commerce/v3/cart/domain/cart" 13 "flamingo.me/flamingo-commerce/v3/cart/domain/placeorder" 14 "flamingo.me/flamingo/v3/core/auth" 15 "flamingo.me/flamingo/v3/framework/flamingo" 16 "golang.org/x/mod/modfile" 17 ) 18 19 type ( 20 // PlaceOrderLoggerAdapter provides an implementation of the Service as email adapter 21 PlaceOrderLoggerAdapter struct { 22 useFlamingoLog bool 23 logAsFile bool 24 logDirectory string 25 logger flamingo.Logger 26 } 27 ) 28 29 var ( 30 _ placeorder.Service = new(PlaceOrderLoggerAdapter) 31 ) 32 33 // Inject dependencies 34 func (e *PlaceOrderLoggerAdapter) Inject(logger flamingo.Logger, 35 config *struct { 36 UseFlamingoLog bool `inject:"config:commerce.cart.placeOrderLogger.useFlamingoLog,optional"` 37 LogAsFile bool `inject:"config:commerce.cart.placeOrderLogger.logAsFile,optional"` 38 LogDirectory string `inject:"config:commerce.cart.placeOrderLogger.logDirectory,optional"` 39 }) { 40 e.logger = logger.WithField("module", "cart").WithField("category", "emailAdapter") 41 if config != nil { 42 e.useFlamingoLog = config.UseFlamingoLog 43 e.logAsFile = config.LogAsFile 44 e.logDirectory = config.LogDirectory 45 } 46 } 47 48 // PlaceGuestCart places a guest cart as order email 49 func (e *PlaceOrderLoggerAdapter) PlaceGuestCart(ctx context.Context, cart *cartDomain.Cart, payment *placeorder.Payment) (placeorder.PlacedOrderInfos, error) { 50 return e.placeCart(cart, payment) 51 } 52 53 // PlaceCustomerCart places a customer cart as order email 54 func (e *PlaceOrderLoggerAdapter) PlaceCustomerCart(ctx context.Context, auth auth.Identity, cart *cartDomain.Cart, payment *placeorder.Payment) (placeorder.PlacedOrderInfos, error) { 55 return e.placeCart(cart, payment) 56 } 57 58 // placeCart 59 func (e *PlaceOrderLoggerAdapter) placeCart(cart *cartDomain.Cart, payment *placeorder.Payment) (placeorder.PlacedOrderInfos, error) { 60 err := e.checkPayment(cart, payment) 61 if err != nil { 62 return nil, err 63 } 64 err = e.logOrder(cart, payment) 65 if err != nil { 66 return nil, err 67 } 68 var placedOrders placeorder.PlacedOrderInfos 69 for _, del := range cart.Deliveries { 70 placedOrders = append(placedOrders, placeorder.PlacedOrderInfo{ 71 OrderNumber: cart.ID, 72 DeliveryCode: del.DeliveryInfo.Code, 73 }) 74 } 75 76 return placedOrders, nil 77 } 78 79 // checkPayment 80 func (e *PlaceOrderLoggerAdapter) checkPayment(cart *cartDomain.Cart, payment *placeorder.Payment) error { 81 if payment == nil && cart.GrandTotal.IsPositive() { 82 return errors.New("no valid payment given") 83 } 84 if cart.GrandTotal.IsPositive() { 85 totalPrice, err := payment.TotalValue() 86 if err != nil { 87 return err 88 } 89 if !totalPrice.Equal(cart.GrandTotal) { 90 return errors.New("payment total does not match with grandtotal") 91 } 92 } 93 return nil 94 } 95 96 // logOrder 97 func (e *PlaceOrderLoggerAdapter) logOrder(cart *cartDomain.Cart, payment *placeorder.Payment) error { 98 if e.useFlamingoLog { 99 e.logger.WithField("placeorder", cart.ID).WithField("cart", cart).Info("Order placed and logged") 100 } 101 if e.logAsFile && e.logDirectory != "" { 102 if !modfile.IsDirectoryPath(e.logDirectory) { 103 return fmt.Errorf("%v is not a valid directory path", e.logDirectory) 104 } 105 // Create folder if not exist 106 if _, err := os.Stat(e.logDirectory); os.IsNotExist(err) { 107 err = os.MkdirAll(e.logDirectory, os.ModePerm) 108 if err != nil { 109 e.logger.Error(err) 110 return err 111 } 112 } 113 type order struct { 114 Cart cartDomain.Cart 115 Payment placeorder.Payment 116 } 117 content, err := json.Marshal(order{ 118 Cart: *cart, 119 Payment: *payment, 120 }) 121 if err != nil { 122 e.logger.Error(err) 123 return err 124 } 125 fileName := fmt.Sprintf("order-%v-%v.json", time.Now().Format(time.RFC3339), cart.ID) 126 err = os.WriteFile(path.Join(e.logDirectory, fileName), []byte(content), os.ModePerm) 127 if err != nil { 128 e.logger.WithField("placeorder", cart.ID).Error(err) 129 } 130 e.logger.WithField("placeorder", cart.ID).WithField("cart", cart).Info("Order placed") 131 } 132 return nil 133 } 134 135 // ReserveOrderID returns the reserved order id 136 func (e *PlaceOrderLoggerAdapter) ReserveOrderID(ctx context.Context, cart *cartDomain.Cart) (string, error) { 137 return cart.ID, nil 138 } 139 140 // CancelGuestOrder cancels a guest order 141 func (e *PlaceOrderLoggerAdapter) CancelGuestOrder(ctx context.Context, orderInfos placeorder.PlacedOrderInfos) error { 142 // since we don't actual place orders we just return nil here 143 return nil 144 } 145 146 // CancelCustomerOrder cancels a customer order 147 func (e *PlaceOrderLoggerAdapter) CancelCustomerOrder(ctx context.Context, orderInfos placeorder.PlacedOrderInfos, auth auth.Identity) error { 148 // since we don't actual place orders we just return nil here 149 return nil 150 }