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 }