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

     1  package fake
     2  
     3  import (
     4  	"context"
     5  	_ "embed"
     6  	"encoding/json"
     7  	"os"
     8  
     9  	cartDomain "flamingo.me/flamingo-commerce/v3/cart/domain/cart"
    10  	"flamingo.me/flamingo-commerce/v3/cart/domain/decorator"
    11  	productDomain "flamingo.me/flamingo-commerce/v3/product/domain"
    12  	commerceSourcingDomain "flamingo.me/flamingo-commerce/v3/sourcing/domain"
    13  )
    14  
    15  type (
    16  	SourcingService struct {
    17  		fakeSource *fakeSource
    18  	}
    19  
    20  	fakeSource struct {
    21  		DeliveryCodes map[string]int
    22  		Products      map[string]int
    23  	}
    24  )
    25  
    26  var _ commerceSourcingDomain.SourcingService = &SourcingService{}
    27  
    28  func (s *SourcingService) Inject(
    29  	cfg *struct {
    30  		FakeSourceData string `inject:"config:commerce.sourcing.fake.jsonPath,optional"`
    31  	},
    32  ) {
    33  	if cfg.FakeSourceData == "" {
    34  		panic("fake sourcing service enabled but jsonPath was not set")
    35  	}
    36  
    37  	fileBytes, err := os.ReadFile(cfg.FakeSourceData)
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  
    42  	fakeSource := &fakeSource{}
    43  	err = json.Unmarshal(fileBytes, fakeSource)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  
    48  	s.fakeSource = fakeSource
    49  }
    50  
    51  func (s *SourcingService) AllocateItems(ctx context.Context, decoratedCart *decorator.DecoratedCart) (commerceSourcingDomain.ItemAllocations, error) {
    52  	var (
    53  		itemAllocations = commerceSourcingDomain.ItemAllocations{}
    54  		overallError    error
    55  	)
    56  	for _, decoratedDelivery := range decoratedCart.DecoratedDeliveries {
    57  		for _, decoratedItem := range decoratedDelivery.DecoratedItems {
    58  			if decoratedItem.Item.ID == "" {
    59  				continue
    60  			}
    61  
    62  			availableSources, err := s.GetAvailableSources(ctx, decoratedItem.Product, &decoratedDelivery.Delivery.DeliveryInfo, decoratedCart)
    63  			availableSourcesForProduct := availableSources[commerceSourcingDomain.ProductID(decoratedItem.Product.GetIdentifier())]
    64  
    65  			itemAllocation := commerceSourcingDomain.ItemAllocation{
    66  				AllocatedQtys: map[commerceSourcingDomain.ProductID]commerceSourcingDomain.AllocatedQtys{
    67  					commerceSourcingDomain.ProductID(decoratedItem.Product.GetIdentifier()): commerceSourcingDomain.AllocatedQtys(availableSourcesForProduct),
    68  				},
    69  				Error: err,
    70  			}
    71  
    72  			itemAllocations[commerceSourcingDomain.ItemID(decoratedItem.Item.ID)] = itemAllocation
    73  		}
    74  	}
    75  
    76  	return itemAllocations, overallError
    77  }
    78  
    79  func (s *SourcingService) GetAvailableSources(_ context.Context, product productDomain.BasicProduct, deliveryInfo *cartDomain.DeliveryInfo, _ *decorator.DecoratedCart) (commerceSourcingDomain.AvailableSourcesPerProduct, error) {
    80  	if product.Type() == productDomain.TypeBundle || product.Type() == productDomain.TypeConfigurable {
    81  		return nil, commerceSourcingDomain.ErrUnsupportedProductType
    82  	}
    83  
    84  	productId := product.GetIdentifier()
    85  
    86  	if productId == "" {
    87  		return nil, commerceSourcingDomain.ErrEmptyProductIdentifier
    88  	}
    89  
    90  	allocationQty, found := s.fakeSource.Products[productId]
    91  	if found {
    92  		return commerceSourcingDomain.AvailableSourcesPerProduct{
    93  			commerceSourcingDomain.ProductID(productId): s.makeAvailableSources(allocationQty, productId),
    94  		}, nil
    95  	}
    96  
    97  	if deliveryInfo.Code != "" {
    98  		allocationQty, found := s.fakeSource.DeliveryCodes[deliveryInfo.Code]
    99  		if found {
   100  			return commerceSourcingDomain.AvailableSourcesPerProduct{
   101  				commerceSourcingDomain.ProductID(productId): s.makeAvailableSources(allocationQty, deliveryInfo.Code),
   102  			}, nil
   103  		}
   104  	}
   105  
   106  	return nil, commerceSourcingDomain.ErrNoSourceAvailable
   107  }
   108  
   109  func (s *SourcingService) makeAvailableSources(qty int, id string) commerceSourcingDomain.AvailableSources {
   110  	return map[commerceSourcingDomain.Source]int{
   111  		commerceSourcingDomain.Source{
   112  			LocationCode:         id,
   113  			ExternalLocationCode: id,
   114  		}: qty,
   115  	}
   116  }