flamingo.me/flamingo-commerce/v3@v3.11.0/cart/interfaces/controller/forms/deliveryform.go (about) 1 package forms 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "flamingo.me/flamingo/v3/framework/flamingo" 9 "flamingo.me/flamingo/v3/framework/web" 10 "flamingo.me/form/application" 11 "flamingo.me/form/domain" 12 13 cartApplication "flamingo.me/flamingo-commerce/v3/cart/application" 14 cartDomain "flamingo.me/flamingo-commerce/v3/cart/domain/cart" 15 ) 16 17 type ( 18 // DeliveryForm the form for billing address 19 DeliveryForm struct { 20 DeliveryAddress AddressForm `form:"deliveryAddress"` 21 // UseBillingAddress - the address should be taken from billing (only relevant for type address) 22 UseBillingAddress bool `form:"useBillingAddress"` 23 ShippingMethod string `form:"shippingMethod"` 24 ShippingCarrier string `form:"shippingCarrier"` 25 LocationCode string `form:"locationCode"` 26 DesiredTime time.Time `form:"desiredTime"` 27 } 28 29 // DeliveryFormService implements Form(Data)Provider interface of form package 30 DeliveryFormService struct { 31 applicationCartReceiverService *cartApplication.CartReceiverService 32 } 33 34 // DeliveryFormController the (mini) MVC 35 DeliveryFormController struct { 36 responder *web.Responder 37 applicationCartService *cartApplication.CartService 38 applicationCartReceiverService *cartApplication.CartReceiverService 39 logger flamingo.Logger 40 formHandlerFactory application.FormHandlerFactory 41 billingAddressFormProvider *BillingAddressFormService 42 } 43 ) 44 45 // MapToDeliveryInfo - updates some fields of the given DeliveryInfo with data from the form 46 func (d *DeliveryForm) MapToDeliveryInfo(currentInfo cartDomain.DeliveryInfo) cartDomain.DeliveryInfo { 47 address := d.DeliveryAddress.MapToDomainAddress() 48 currentInfo.DeliveryLocation.Address = &address 49 currentInfo.DeliveryLocation.UseBillingAddress = d.UseBillingAddress 50 currentInfo.DeliveryLocation.Code = d.LocationCode 51 currentInfo.Method = d.ShippingMethod 52 currentInfo.Carrier = d.ShippingCarrier 53 currentInfo.DesiredTime = d.DesiredTime 54 return currentInfo 55 } 56 57 // Inject - Inject 58 func (p *DeliveryFormService) Inject(applicationCartReceiverService *cartApplication.CartReceiverService) { 59 p.applicationCartReceiverService = applicationCartReceiverService 60 } 61 62 // GetFormData from data provider 63 func (p *DeliveryFormService) GetFormData(ctx context.Context, req *web.Request) (interface{}, error) { 64 65 cart, err := p.applicationCartReceiverService.ViewCart(ctx, req.Session()) 66 useBilling := false 67 method := "" 68 carrier := "" 69 locationCode := "" 70 deliveryAddress := AddressForm{} 71 deliverycode := req.Params["deliveryCode"] 72 if deliverycode != "" && err == nil { 73 if delivery, found := cart.GetDeliveryByCode(deliverycode); found { 74 if delivery.DeliveryInfo.DeliveryLocation.Address != nil { 75 deliveryAddress.LoadFromCartAddress(*delivery.DeliveryInfo.DeliveryLocation.Address) 76 } 77 useBilling = delivery.DeliveryInfo.DeliveryLocation.UseBillingAddress 78 method = delivery.DeliveryInfo.Method 79 carrier = delivery.DeliveryInfo.Carrier 80 locationCode = delivery.DeliveryInfo.DeliveryLocation.Code 81 } 82 } 83 84 return DeliveryForm{ 85 DeliveryAddress: deliveryAddress, 86 UseBillingAddress: useBilling, 87 ShippingMethod: method, 88 ShippingCarrier: carrier, 89 LocationCode: locationCode, 90 }, nil 91 } 92 93 // Validate form service 94 func (p *DeliveryFormService) Validate(ctx context.Context, req *web.Request, validatorProvider domain.ValidatorProvider, formData interface{}) (*domain.ValidationInfo, error) { 95 deliveryForm, ok := formData.(DeliveryForm) 96 if !ok { 97 return nil, errors.New("no BillingAddressForm given") 98 } 99 validationInfo := domain.ValidationInfo{} 100 if !deliveryForm.UseBillingAddress { 101 // Validate address only if no billing should be used 102 validationInfo = validatorProvider.Validate(ctx, req, deliveryForm) 103 } 104 return &validationInfo, nil 105 } 106 107 // Inject dependencies 108 func (c *DeliveryFormController) Inject(responder *web.Responder, 109 applicationCartService *cartApplication.CartService, 110 applicationCartReceiverService *cartApplication.CartReceiverService, 111 logger flamingo.Logger, 112 formHandlerFactory application.FormHandlerFactory, 113 billingAddressFormProvider *BillingAddressFormService) { 114 c.responder = responder 115 c.applicationCartReceiverService = applicationCartReceiverService 116 c.applicationCartService = applicationCartService 117 c.formHandlerFactory = formHandlerFactory 118 c.logger = logger.WithField(flamingo.LogKeyModule, "cart").WithField(flamingo.LogKeyCategory, "deliveryform") 119 c.billingAddressFormProvider = billingAddressFormProvider 120 } 121 122 // GetUnsubmittedForm returns the form with deliveryform data - without validation 123 func (c *DeliveryFormController) GetUnsubmittedForm(ctx context.Context, r *web.Request) (*domain.Form, error) { 124 formHandler, err := c.getFormHandler() 125 if err != nil { 126 return nil, err 127 } 128 return formHandler.HandleUnsubmittedForm(ctx, r) 129 } 130 131 func (c *DeliveryFormController) getFormHandler() (domain.FormHandler, error) { 132 // ## Handle the submitted form (validation etc) 133 formHandlerBuilder := c.formHandlerFactory.GetFormHandlerBuilder() 134 err := formHandlerBuilder.SetNamedFormService("commerce.cart.deliveryFormService") 135 if err != nil { 136 return nil, err 137 } 138 return formHandlerBuilder.Build(), nil 139 } 140 141 // HandleFormAction handles submitted form and saves to cart 142 func (c *DeliveryFormController) HandleFormAction(ctx context.Context, r *web.Request) (form *domain.Form, actionSuccessful bool, err error) { 143 session := web.SessionFromContext(ctx) 144 145 deliverycode := r.Params["deliveryCode"] 146 if deliverycode == "" { 147 return nil, false, errors.New("no deliverycode parameter given") 148 } 149 formHandler, err := c.getFormHandler() 150 if err != nil { 151 return nil, false, err 152 } 153 form, err = formHandler.HandleSubmittedForm(ctx, r) 154 if err != nil { 155 return nil, false, err 156 } 157 deliveryForm, ok := form.Data.(DeliveryForm) 158 if !ok { 159 return form, false, errors.New("cannot convert to deliveryForm ") 160 } 161 if !form.IsValidAndSubmitted() { 162 return form, false, nil 163 } 164 165 cart, err := c.applicationCartReceiverService.ViewCart(ctx, session) 166 if err != nil { 167 return form, false, err 168 } 169 var deliveryInfo cartDomain.DeliveryInfo 170 delivery, found := cart.GetDeliveryByCode(deliverycode) 171 if !found { 172 initialDelIfno, err := c.applicationCartService.GetInitialDelivery(deliverycode) 173 if err != nil { 174 return form, false, err 175 } 176 deliveryInfo = *initialDelIfno 177 } else { 178 deliveryInfo = delivery.DeliveryInfo 179 } 180 181 deliveryInfo = deliveryForm.MapToDeliveryInfo(deliveryInfo) 182 183 // update Cart 184 err = c.applicationCartService.UpdateDeliveryInfo(ctx, session, deliverycode, cartDomain.CreateDeliveryInfoUpdateCommand(deliveryInfo)) 185 if err != nil { 186 c.logger.WithContext(ctx).Error("UpdateDeliveryInfo Error %v", err) 187 return form, false, err 188 } 189 return form, true, nil 190 }