public async Task TestSuccess() { // Arrange Guid id = new Guid("b7c2acaa-ad72-47b3-b858-26357cf14fbb"); string name = "Unit Test"; Customer customer = new Customer() { Id = id, Name = name }; Mock <IDataRepository <Customer, Guid> > mockRepository = new Mock <IDataRepository <Customer, Guid> >(); mockRepository.Setup(m => m.FindAsync(id, default)).ReturnsAsync(customer); GetCustomerRequest request = new GetCustomerRequest() { Id = id }; GetCustomerCommand sut = new GetCustomerCommand(MockHelpers.GetLogger <GetCustomerCommand>(), mockRepository.Object); // Act GetCustomerResponse result = await sut.Handle(request, default); // Assert Assert.IsNotNull(result); Assert.IsNotNull(result.Customer); Assert.AreEqual(name, result.Customer.Name); mockRepository.VerifyAll(); mockRepository.Verify(m => m.FindAsync(id, default), Times.Once); }
public AddWishlistCommand( PersistEntityPipeline persistEntityPipeline, IServiceProvider serviceProvider, GetCustomerCommand getCustomerCommand) { this._getCustomerCommand = getCustomerCommand; this._persistEntityPipeline = persistEntityPipeline; }
public UpdateCustomerCommand( PersistEntityPipeline persistEntityPipeline, FindEntityCommand findEntityCommand, IServiceProvider serviceProvider, GetCustomerCommand getCustomerCommand, GetEntityViewCommand getEntityViewCommand, DoActionCommand doActionCommand) : base(serviceProvider) { this._getCustomerCommand = getCustomerCommand; this._getEntityViewCommand = getEntityViewCommand; this._doActionCommand = doActionCommand; this._persistEntityPipeline = persistEntityPipeline; this._findEntityCommand = findEntityCommand; }
public async Task TestNotFound() { // Arrange Mock <IDataRepository <Customer, Guid> > mockRepository = new Mock <IDataRepository <Customer, Guid> >(); Guid id = new Guid("b7c2acaa-ad72-47b3-b858-26357cf14fbb"); mockRepository.Setup(m => m.FindAsync(id, default)).Returns(new ValueTask <Customer>((Customer)null)); GetCustomerRequest request = new GetCustomerRequest() { Id = id }; GetCustomerCommand sut = new GetCustomerCommand(MockHelpers.GetLogger <GetCustomerCommand>(), mockRepository.Object); // Act await Assert.ThrowsExceptionAsync <NotFoundException>(async() => await sut.Handle(request, default)); // Assert mockRepository.VerifyAll(); mockRepository.Verify(m => m.FindAsync(id, default), Times.Once); }
public async Task <Result <CustomerDto> > Handle(GetCustomerCommand request, CancellationToken cancellationToken) { var cacheKey = $"Customer-{request.Id}"; var cache = await _cacheService.GetStringAsync(cacheKey); CustomerDto customer; if (cache.TryGetValue <Customer>(out var cachedCustomer)) { customer = _mapper.Map <CustomerDto>(cachedCustomer); return(Result <CustomerDto> .Success(customer)); } var customerInDb = await _customerRepository.GetAsync(c => c.Id == request.Id); customerInDb.CheckForNull(); await _cacheService.SetCacheAsync(cacheKey, customerInDb, _customerSettings); customer = _mapper.Map <CustomerDto>(customerInDb); return(Result <CustomerDto> .Success(customer)); }
public async override Task <Order> Run(Order order, CommercePipelineExecutionContext context) { Condition.Requires(context).IsNotNull($"{this.Name}: The argument can not be null"); Condition.Requires(order).IsNotNull($"{this.Name}: The argument can not be null"); // Getting the blockchain contract address and ensuring the customer is a blockchain customer and opted in for product publishing var contactComponent = order.GetComponent <ContactComponent>(); if (contactComponent == null || !contactComponent.IsRegistered) { return(order); } var getCustomerCommand = new GetCustomerCommand(_getCustomerPipeline, _serviceProvider); var customerId = (contactComponent.CustomerId.ToLower().StartsWith("entity") ? contactComponent.CustomerId : CommerceEntity.IdPrefix <Customer>() + contactComponent.CustomerId); if (string.IsNullOrWhiteSpace(customerId)) { return(order); } var customer = await getCustomerCommand.Process(context.CommerceContext, customerId); var customerDetails = customer.GetComponent <CustomerDetailsComponent>(); if (!(customerDetails.View.ChildViews.Where(v => v.Name.ToLower() == Constants.Pipelines.Views.BlockchainInformationViewName.ToLower()).FirstOrDefault() is EntityView blockchainView)) { return(order); } var contractIdProperty = blockchainView.Properties.FirstOrDefault(p => p.Name == Constants.Pipelines.Fields.IdentityContractAddressFieldName); var publishProductsProperty = blockchainView.Properties.FirstOrDefault(p => p.Name == Constants.Pipelines.Fields.PublishProductsFieldName); // Only submit products for orders where customer have blockchain accounts and have enabled product publishing if (contractIdProperty == null || string.IsNullOrWhiteSpace(contractIdProperty.RawValue?.ToString()) || publishProductsProperty == null || publishProductsProperty.RawValue.ToString() == "false") { return(order); } var ethPolicy = context.GetPolicy <EthereumClientPolicy>(); if (ethPolicy == null) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: missing policy configuration.", context); return(order); } var web3 = new Web3(ethPolicy.NodeUrl); await Blockchain.UnlockMerchantAccountAsync(web3, context); var idContract = web3.Eth.GetContract(ethPolicy.IdentityContractABI, contractIdProperty.RawValue?.ToString()); var producIds = order.Lines.Select(o => o.GetComponent <CartProductComponent>()?.Id).ToList(); var hasPurchasedFunction = idContract.GetFunction("contactHasPurchasedProduct"); var purchasedProductFunction = idContract.GetFunction("addPurchasedProduct"); foreach (var productId in producIds) { try { // Check if the customer has purchased thisproduct in the past var hasPurchasedProduct = await hasPurchasedFunction.CallAsync <bool>(productId); if (hasPurchasedProduct) { continue; } var hash = await purchasedProductFunction.SendTransactionAsync(new TransactionInput { Gas = new HexBigInteger(200000), From = ethPolicy.MerchantAccountAddress }, productId); } catch (Exception ex) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: unable to send call contactHasPurchasedProduct or transaction addPurchasedProduct." + ex.Message, context); return(order); } Logging.Log(context.GetPolicy <KnownResultCodes>().Information, $"Ethereum: added product {productId} to {contractIdProperty.RawValue?.ToString()} purchase ledger.", context); } return(order); }
public GetWishlistCommand(IServiceProvider serviceProvider, GetCustomerCommand getCustomerCommand) { this._getCustomerCommand = getCustomerCommand; }
public async Task <IActionResult> Put([FromBody] ODataActionParameters value) { if (!this.ModelState.IsValid || value == null) { return((IActionResult) new BadRequestObjectResult((object)value)); } string id = value["customerId"].ToString(); if (!this.ModelState.IsValid || string.IsNullOrEmpty(id)) { return((IActionResult)this.NotFound()); } GetCustomerCommand command0 = this.Command <GetCustomerCommand>(); Customer customer = await command0.Process(this.CurrentContext, id); var y = customer.GetComponent <AddressComponent>(); //refactor string randoms = Guid.NewGuid().ToString().Replace("-", string.Empty).Replace("+", string.Empty); string cartId = string.Format("{0}{1}", "CUSTOM", randoms); string str = value["itemId"].ToString(); Decimal result; string q = "1"; if (!Decimal.TryParse(q, out result)) { return((IActionResult) new BadRequestObjectResult((object)q)); } AddCartLineCommand command = this.Command <AddCartLineCommand>(); CartLineComponent line = new CartLineComponent() { ItemId = str, Quantity = result }; Cart cart = await command.Process(this.CurrentContext, cartId, line); //FulfillmentComponent FulfillmentComponent fulfillment = (PhysicalFulfillmentComponent) new PhysicalFulfillmentComponent() { ShippingParty = new Party() { Address1 = y.Party.Address1, City = y.Party.City, ZipPostalCode = y.Party.ZipPostalCode, State = y.Party.State, StateCode = y.Party.StateCode, CountryCode = y.Party.CountryCode, AddressName = y.Party.AddressName, Name = y.Party.Name }, FulfillmentMethod = new EntityReference() { Name = "Ground", EntityTarget = "B146622D-DC86-48A3-B72A-05EE8FFD187A" } }; SetCartFulfillmentCommand _CartFulfillmentCommand = this.Command <SetCartFulfillmentCommand>(); Cart cart1 = await _CartFulfillmentCommand.Process(CurrentContext, cartId, fulfillment); //FederatedPaymentComponent decimal gt; Decimal.TryParse(cart1.Totals.GrandTotal.Amount.ToString(), out gt); FederatedPaymentComponent paymentComponent = new FederatedPaymentComponent(new Money() { Amount = gt }); paymentComponent.PaymentMethod = new EntityReference() { EntityTarget = "0CFFAB11-2674-4A18-AB04-228B1F8A1DEC", Name = "Federated" }; paymentComponent.PaymentMethodNonce = "fake-valid-nonce"; paymentComponent.BillingParty = new Party() { Address1 = y.Party.Address1, City = y.Party.City, ZipPostalCode = y.Party.ZipPostalCode, State = y.Party.State, StateCode = y.Party.StateCode, CountryCode = y.Party.CountryCode, AddressName = y.Party.AddressName, }; AddPaymentsCommand _PaymentsCommand = this.Command <AddPaymentsCommand>(); Cart cart2 = await _PaymentsCommand.Process(this.CurrentContext, cartId, (IEnumerable <PaymentComponent>) new List <PaymentComponent>() { (PaymentComponent)paymentComponent }); //CreateOrderCommand string email = customer.Email; CreateOrderCommand _CreateOrderCommand = this.Command <CreateOrderCommand>(); Order order = await _CreateOrderCommand.Process(this.CurrentContext, cartId, email); return((IActionResult) new ObjectResult((object)_CreateOrderCommand)); }
public async override Task <Order> Run(Order order, CommercePipelineExecutionContext context) { Condition.Requires(context).IsNotNull($"{this.Name}: The argument can not be null"); Condition.Requires(order).IsNotNull($"{this.Name}: The argument can not be null"); // Getting the blockchain contract address var contactComponent = order.GetComponent <ContactComponent>(); if (contactComponent == null || !contactComponent.IsRegistered) { return(order); } var getCustomerCommand = new GetCustomerCommand(_getCustomerPipeline, _serviceProvider); var customerId = (contactComponent.CustomerId.ToLower().StartsWith("entity") ? contactComponent.CustomerId : CommerceEntity.IdPrefix <Customer>() + contactComponent.CustomerId); if (string.IsNullOrWhiteSpace(customerId)) { return(order); } var customer = await getCustomerCommand.Process(context.CommerceContext, customerId); var customerDetails = customer.GetComponent <CustomerDetailsComponent>(); if (!(customerDetails.View.ChildViews.Where(v => v.Name.ToLower() == Constants.Pipelines.Views.BlockchainInformationViewName.ToLower()).FirstOrDefault() is EntityView blockchainView)) { return(order); } var contractIdProperty = blockchainView.Properties.FirstOrDefault(p => p.Name == Constants.Pipelines.Fields.IdentityContractAddressFieldName); // Only submit products for orders where customer have blockchain accounts and have enabled product publishing if (contractIdProperty == null || string.IsNullOrWhiteSpace(contractIdProperty.RawValue?.ToString())) { return(order); } var orderSubtotal = order.Totals.SubTotal.Amount; var ethPolicy = context.GetPolicy <EthereumClientPolicy>(); if (ethPolicy == null) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: missing policy configuration.", context); return(order); } var web3 = new Web3(ethPolicy.NodeUrl); // Unlock merch account to be able to send state change transactions await Blockchain.UnlockMerchantAccountAsync(web3, context); var idContract = web3.Eth.GetContract(ethPolicy.LoaltyContractABI, ethPolicy.LoyaltyContractAddress); var addLoyaltyPointsFunction = idContract.GetFunction("addLoyaltyPoints"); try { // TODO: this implementation uses a separate loyalty contract balance, potntial discrepancies over time with bank depletion var usdPerEth = await UpdateEthBalanceOnEntityView.GetUsdAmountAsync(1, context); var subtotalInWei = UnitConversion.Convert.ToWei((orderSubtotal / usdPerEth), UnitConversion.EthUnit.Ether); var loyaltyEstimatedAmount = UnitConversion.Convert.ToWei(((orderSubtotal / usdPerEth) / 100), UnitConversion.EthUnit.Ether); // validating the royalty contract amount by passing precalculated value (1%) var gasEstimate = await addLoyaltyPointsFunction.EstimateGasAsync(ethPolicy.MerchantAccountAddress, new HexBigInteger(200000), new HexBigInteger(loyaltyEstimatedAmount), subtotalInWei, contractIdProperty.RawValue.ToString()); var hash = await addLoyaltyPointsFunction.SendTransactionAsync(new TransactionInput { Gas = new HexBigInteger(gasEstimate), From = ethPolicy.MerchantAccountAddress, Value = new HexBigInteger(loyaltyEstimatedAmount) }, subtotalInWei, contractIdProperty.RawValue.ToString()); } catch (Exception ex) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: unable to send transaction addLoyaltyPoints. " + ex.Message, context); return(order); } Logging.Log(context.GetPolicy <KnownResultCodes>().Information, $"Ethereum: added loyalty points for the purchasein the amount of ${orderSubtotal} to {contractIdProperty.RawValue} based on the police defined in {ethPolicy.LoyaltyContractAddress}.", context); return(order); }
public async override Task <Order> Run(Order order, CommercePipelineExecutionContext context) { Condition.Requires(context).IsNotNull($"{this.Name}: The argument can not be null"); Condition.Requires(order).IsNotNull($"{this.Name}: The argument can not be null"); var ethPolicy = context.GetPolicy <EthereumClientPolicy>(); if (ethPolicy == null) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: missing policy configuration.", context); return(order); } // Getting customer id contract var contactComponent = order.GetComponent <ContactComponent>(); if (contactComponent == null || !contactComponent.IsRegistered) { return(order); } var getCustomerCommand = new GetCustomerCommand(_getCustomerPipeline, _serviceProvider); var customerId = (contactComponent.CustomerId.ToLower().StartsWith("entity") ? contactComponent.CustomerId : CommerceEntity.IdPrefix <Customer>() + contactComponent.CustomerId); if (string.IsNullOrWhiteSpace(customerId)) { return(order); } var customer = await getCustomerCommand.Process(context.CommerceContext, customerId); var customerDetails = customer.GetComponent <CustomerDetailsComponent>(); if (!(customerDetails.View.ChildViews.Where(v => v.Name.ToLower() == Constants.Pipelines.Views.BlockchainInformationViewName.ToLower()).FirstOrDefault() is EntityView blockchainView)) { return(order); } var contractIdProperty = blockchainView.Properties.FirstOrDefault(p => p.Name == Constants.Pipelines.Fields.IdentityContractAddressFieldName); if (contractIdProperty == null || string.IsNullOrWhiteSpace(contractIdProperty.RawValue?.ToString())) { return(order); } var web3 = new Web3(ethPolicy.NodeUrl); await Blockchain.UnlockMerchantAccountAsync(web3, context); var royaltyContract = web3.Eth.GetContract(ethPolicy.RoyaltyContractABI, ethPolicy.RoyaltyContractAddress); var getAssetUrlFunction = royaltyContract.GetFunction("getAssetUrl"); var assetPurchaseEvent = royaltyContract.GetEvent("AssetPurchased"); var orderLines = order.Lines; foreach (var orderLine in orderLines) { try { var token = new CancellationTokenSource(); var value = new HexBigInteger(8568000000000000); // the amount equates about $2 var product = orderLine.GetComponent <CartProductComponent>(); if (product == null) { continue; } if (!product.Tags.Any(t => t.Name == "blockchainroyalty")) { continue; } var producId = orderLine.GetComponent <CartProductComponent>()?.Id; var gasEstimate = await getAssetUrlFunction.EstimateGasAsync(ethPolicy.MerchantAccountAddress, new HexBigInteger(200000), value, producId, contractIdProperty.RawValue.ToString()); var receipt = await getAssetUrlFunction.SendTransactionAndWaitForReceiptAsync(ethPolicy.MerchantAccountAddress, gasEstimate, value, token, producId, contractIdProperty.RawValue.ToString()); var filterPurchaser = assetPurchaseEvent.CreateFilterInput(new BlockParameter(receipt.BlockNumber), BlockParameter.CreateLatest()); if (((bool)receipt.HasErrors())) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, $"Ethereum: unable to get receipt for the digital asset token retrieval. Transaction failed with status {receipt.Status}.", context); return(order); } var logs = await assetPurchaseEvent.GetAllChanges <AssetPurchaseEvent>(filterPurchaser); orderLine.SetComponent(new DigitalDownloadBlockchainTokenComponent { BlockchainDownloadToken = logs.Last().Event.Token }); } catch (Exception ex) { Logging.Log(context.GetPolicy <KnownResultCodes>().Error, "Ethereum: unable to send transaction getAssetUrl. " + ex.Message, context); return(order); } Logging.Log(context.GetPolicy <KnownResultCodes>().Information, $"Ethereum: received asset URL token from {ethPolicy.RoyaltyContractAddress}", context); } return(order); }