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  }