flamingo.me/flamingo-commerce/v3@v3.11.0/sourcing/domain/restrictor/restrictor.go (about)

     1  package restrictors
     2  
     3  import (
     4  	"context"
     5  
     6  	"flamingo.me/flamingo-commerce/v3/cart/domain/cart"
     7  	"flamingo.me/flamingo-commerce/v3/cart/domain/validation"
     8  	productDomain "flamingo.me/flamingo-commerce/v3/product/domain"
     9  	"flamingo.me/flamingo-commerce/v3/sourcing/application"
    10  	"flamingo.me/flamingo-commerce/v3/sourcing/domain"
    11  
    12  	"flamingo.me/flamingo/v3/framework/flamingo"
    13  	"flamingo.me/flamingo/v3/framework/web"
    14  
    15  	"go.opencensus.io/trace"
    16  )
    17  
    18  type (
    19  	// Restrictor restricts qty based on available stock
    20  	Restrictor struct {
    21  		logger          flamingo.Logger
    22  		sourcingService application.SourcingApplication
    23  	}
    24  )
    25  
    26  var _ validation.MaxQuantityRestrictor = new(Restrictor)
    27  
    28  // Inject dependencies
    29  func (r *Restrictor) Inject(
    30  	l flamingo.Logger,
    31  	sourcingService application.SourcingApplication,
    32  ) *Restrictor {
    33  	r.logger = l.WithField(flamingo.LogKeyCategory, "SourceAvailableRestrictor")
    34  	r.sourcingService = sourcingService
    35  
    36  	return r
    37  }
    38  
    39  // Name returns the code of the restrictor
    40  func (r *Restrictor) Name() string {
    41  	return "SourceAvailableRestrictor"
    42  }
    43  
    44  // Restrict qty based on product data
    45  func (r *Restrictor) Restrict(ctx context.Context, session *web.Session, product productDomain.BasicProduct, _ *cart.Cart, deliveryCode string) *validation.RestrictionResult {
    46  	ctx, span := trace.StartSpan(ctx, "sourcing/restrictors/SourceAvailableRestrictor")
    47  	defer span.End()
    48  
    49  	availableSourcesPerProduct, err := r.sourcingService.GetAvailableSources(ctx, session, product, deliveryCode)
    50  	if err != nil {
    51  		return r.unrestricted()
    52  	}
    53  
    54  	availableSources, ok := availableSourcesPerProduct[domain.ProductID(product.GetIdentifier())]
    55  	if !ok {
    56  		return r.unrestricted()
    57  	}
    58  
    59  	if product.Type() == productDomain.TypeBundleWithActiveChoices {
    60  		availableSources = availableSourcesPerProduct.FindSourcesWithLeastAvailableQty()
    61  	}
    62  
    63  	restrictedByNotDeductedSources := &validation.RestrictionResult{
    64  		IsRestricted:        true,
    65  		MaxAllowed:          availableSources.QtySum(),
    66  		RemainingDifference: availableSources.QtySum(),
    67  		RestrictorName:      r.Name(),
    68  	}
    69  
    70  	availableSourcesPerProductDeducted, err := r.sourcingService.GetAvailableSourcesDeductedByCurrentCart(ctx, session, product, deliveryCode)
    71  	if err != nil {
    72  		r.logger.Error(err)
    73  		return restrictedByNotDeductedSources
    74  	}
    75  
    76  	availableSourcesDeducted, ok := availableSourcesPerProductDeducted[domain.ProductID(product.GetIdentifier())]
    77  	if !ok {
    78  		return restrictedByNotDeductedSources
    79  	}
    80  
    81  	if product.Type() == productDomain.TypeBundleWithActiveChoices {
    82  		availableSourcesDeducted = availableSourcesPerProductDeducted.FindSourcesWithLeastAvailableQty()
    83  	}
    84  
    85  	return &validation.RestrictionResult{
    86  		IsRestricted:        true,
    87  		MaxAllowed:          availableSources.QtySum(),
    88  		RemainingDifference: availableSourcesDeducted.QtySum(),
    89  		RestrictorName:      r.Name(),
    90  	}
    91  }
    92  
    93  func (r *Restrictor) unrestricted() *validation.RestrictionResult {
    94  	return &validation.RestrictionResult{
    95  		IsRestricted:        false,
    96  		MaxAllowed:          0,
    97  		RemainingDifference: 0,
    98  		RestrictorName:      r.Name(),
    99  	}
   100  }