private async Task CreateBuyers(EnvironmentSeed seed, VerifiedUserContext user) { seed.Buyers.Add(new HSBuyer { ID = "Default_HeadStart_Buyer", Name = "Default HeadStart Buyer", Active = true, xp = new BuyerXp { MarkupPercent = 0 } }); foreach (var buyer in seed.Buyers) { var superBuyer = new SuperHSBuyer() { Buyer = buyer, Markup = new BuyerMarkup() { Percent = 0 } }; await _buyerCommand.Create(superBuyer, user, isSeedingEnvironment : true); } }
public async Task <T> SaveToQueue <T>(T obj, VerifiedUserContext user, string resourceId) where T : IHSObject { try { var orch = new OrchestrationObject <T> { Token = user.AccessToken, ClientId = user.ClientID, ID = obj.ID, Model = obj }; await _blobQueue.Save(orch.BuildPath(resourceId, user.ClientID), JsonConvert.SerializeObject(orch)); return(await Task.FromResult(obj)); } catch (OrderCloudIntegrationException ex) { throw new OrderCloudIntegrationException(ex.ApiError); } catch (Exception ex) { await _log.Save(new OrchestrationLog() { Level = LogLevel.Error, Message = $"Failed to save blob to queue from API: {user.SupplierID} - {typeof(T)}: {ex.Message}", Current = JObject.FromObject(obj) }); throw new OrderCloudIntegrationException(Headstart.Models.ErrorCodes.All["WriteFailure"], obj); } }
public async Task <List <HSAddressBuyer> > BuyerLocation(string templateID, VerifiedUserContext verifiedUser) { //Get stored template from Cosmos DB container var template = await _template.Get(templateID, verifiedUser); var allBuyerLocations = new List <HSAddressBuyer>(); //Logic if no Buyer ID is supplied if (template.Filters.BuyerID.Count == 0) { var buyers = await ListAllAsync.List((page) => _oc.Buyers.ListAsync <HSBuyer>( filters: null, page: page, pageSize: 100 )); foreach (var buyer in buyers) { template.Filters.BuyerID.Add(buyer.ID); } } foreach (var buyerID in template.Filters.BuyerID) { //For every buyer included in the template filters, grab all buyer locations (exceeding 100 maximum) var buyerLocations = await ListAllAsync.List((page) => _oc.Addresses.ListAsync <HSAddressBuyer>( buyerID, filters: null, page: page, pageSize: 100 )); allBuyerLocations.AddRange(buyerLocations); } //Use reflection to determine available filters from model var filterClassProperties = template.Filters.GetType().GetProperties(); //Create dictionary of key/value pairings of filters, where provided in the template var filtersToEvaluateMap = new Dictionary <PropertyInfo, List <string> >(); foreach (var property in filterClassProperties) { //See if there are filters provided on the property. If no values supplied, do not evaluate the filter. List <string> propertyFilters = (List <string>)property.GetValue(template.Filters); if (propertyFilters != null && propertyFilters.Count > 0 && property.Name != "BuyerID") { filtersToEvaluateMap.Add(property, (List <string>)property.GetValue(template.Filters)); } } //Filter through collected records, adding only those that pass the PassesFilters check. var filteredBuyerLocations = new List <HSAddressBuyer>(); foreach (var location in allBuyerLocations) { if (PassesFilters(location, filtersToEvaluateMap)) { filteredBuyerLocations.Add(location); } } return(filteredBuyerLocations); }
public async Task <JObject> GetOrderAsync(string ID, VerifiedUserContext user) { var supplierID = ID.Split("-")[1]; Require.That(user.UsrType == "admin" || supplierID == user.SupplierID, new ErrorCode("Unauthorized", 401, $"You are not authorized view this order")); try { var type = Assembly.GetExecutingAssembly().GetTypeByAttribute <SupplierSyncAttribute>(attribute => attribute.SupplierID == supplierID) ?? Assembly.GetExecutingAssembly().GetTypeByAttribute <SupplierSyncAttribute>(attribute => attribute.SupplierID == "Generic"); if (type == null) { throw new MissingMethodException($"Command for {supplierID} is unavailable"); } var command = (ISupplierSyncCommand)Activator.CreateInstance(type, _settings); var method = command.GetType().GetMethod($"GetOrderAsync", BindingFlags.Public | BindingFlags.Instance); if (method == null) { throw new MissingMethodException($"Get Order Method for {supplierID} is unavailable"); } return(await(Task <JObject>) method.Invoke(command, new object[] { ID, user })); } catch (MissingMethodException mex) { throw new Exception(JsonConvert.SerializeObject(new ApiError() { Data = new { user, OrderID = ID }, ErrorCode = mex.Message, Message = $"Missing Method for: {supplierID ?? "Invalid Supplier"}" })); } }
private async Task EnsureUserCanAccessOrder(HSOrder order, VerifiedUserContext verifiedUser) { /* ensures user has access to order through at least 1 of 3 methods * 1) user submitted the order * 2) user has access to all orders from the location of the billingAddressID * 3) the order is awaiting approval and the user is in the approving group */ var isOrderSubmitter = order.FromUserID == verifiedUser.UserID; if (isOrderSubmitter) { return; } var isUserInLocationOrderAccessGroup = await _locationPermissionCommand.IsUserInAccessGroup(order.BillingAddressID, UserGroupSuffix.ViewAllOrders.ToString(), verifiedUser); if (isUserInLocationOrderAccessGroup) { return; } if(order.Status == OrderStatus.AwaitingApproval) { // logic assumes there is only one approving group per location var isUserInApprovalGroup = await _locationPermissionCommand.IsUserInAccessGroup(order.BillingAddressID, UserGroupSuffix.OrderApprover.ToString(), verifiedUser); if(isUserInApprovalGroup) { return; } } // if function has not been exited yet we throw an insufficient access error Require.That(false, new ErrorCode("Insufficient Access", 403, $"User cannot access order {order.ID}")); }
private async Task CreateSuppliers(VerifiedUserContext user, EnvironmentSeed seed, string token) { // Create Suppliers and necessary user groups and security profile assignments foreach (HSSupplier supplier in seed.Suppliers) { await _supplierCommand.Create(supplier, user, isSeedingEnvironment : true); } }
public async Task <BatchProcessResult> UploadShipments(IFormFile file, VerifiedUserContext userContext) { BatchProcessResult documentImportResult; documentImportResult = await GetShipmentListFromFile(file, userContext); return(documentImportResult); }
public async Task <ReportTemplate> Post(ReportTemplate reportTemplate, VerifiedUserContext verifiedUser) { var template = reportTemplate; template.SellerID = verifiedUser.SellerID; var newTemplate = await _store.AddAsync(template); return(newTemplate); }
private async Task CreateDefaultContentDocs(VerifiedUserContext userContext) { // any default created docs should be generic enough to be used by all orgs await Task.WhenAll( _cms.Documents.Create("SupplierFilterConfig", GetCountriesServicingDoc(), userContext.AccessToken), _cms.Documents.Create("SupplierFilterConfig", GetServiceCategoryDoc(), userContext.AccessToken), _cms.Documents.Create("SupplierFilterConfig", GetVendorLevelDoc(), userContext.AccessToken) ); }
public async Task PatchMeAddress(string addressID, BuyerAddress patch, VerifiedUserContext user) { var current = await new OrderCloudClientWithContext(user).Me.GetAddressAsync <BuyerAddress>(addressID); var patched = PatchHelper.PatchObject(patch, current); await ValidateAddress(patched); await new OrderCloudClientWithContext(user).Me.PatchAddressAsync(addressID, (PartialBuyerAddress)patch); }
public static VerifiedUserContext MockUserContext() { var cid = new ClaimsIdentity("OrderCloudIntegrations"); cid.AddClaim(new Claim("accesstoken", MockOrderCloudToken())); var principal = new ClaimsPrincipal(cid); var context = new VerifiedUserContext(principal); return(context); }
public async Task PatchMeAddress(string addressID, BuyerAddress patch, VerifiedUserContext user) { var current = await _oc.Me.GetAddressAsync <BuyerAddress>(addressID, user.AccessToken); var patched = PatchHelper.PatchObject(patch, current); await ValidateAddress(patched); await _oc.Me.PatchAddressAsync(addressID, (PartialBuyerAddress)patch, user.AccessToken); }
public async Task <HSOrderCalculateResponse> CalculateOrder(string orderID, VerifiedUserContext user) { var worksheet = await _oc.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, orderID, user.AccessToken); return(await this.CalculateOrder(new HSOrderCalculatePayload() { ConfigData = null, OrderWorksheet = worksheet })); }
private async Task <decimal> GetDefaultMarkupMultiplier(VerifiedUserContext user) { var buyer = await _cache.GetOrAddAsync($"buyer_{user.Buyer.ID}", TimeSpan.FromHours(1), () => _hsBuyerCommand.Get(user.Buyer.ID)); // must convert markup to decimal before division to prevent rouding error var markupPercent = (decimal)buyer.Markup.Percent / 100; var markupMultiplier = markupPercent + 1; return(markupMultiplier); }
public async Task <SuperHSBuyer> Create(SuperHSBuyer superBuyer, VerifiedUserContext user, bool isSeedingEnvironment = false) { var createdBuyer = await CreateBuyerAndRelatedFunctionalResources(superBuyer.Buyer, user, isSeedingEnvironment); var createdMarkup = await CreateMarkup(superBuyer.Markup, createdBuyer.ID, user.AccessToken); return(new SuperHSBuyer() { Buyer = createdBuyer, Markup = createdMarkup }); }
public async Task <SuperHSMeProduct> Get(string id, VerifiedUserContext user) { var _product = _oc.Me.GetProductAsync <HSMeProduct>(id, user.AccessToken); var _specs = _oc.Me.ListSpecsAsync(id, null, null, user.AccessToken); var _variants = _oc.Products.ListVariantsAsync <HSVariant>(id, null, null, null, 1, 100, null); var unconvertedSuperHsProduct = new SuperHSMeProduct { Product = await _product, PriceSchedule = (await _product).PriceSchedule, Specs = (await _specs).Items, Variants = (await _variants).Items, }; return(await ApplyBuyerPricing(unconvertedSuperHsProduct, user)); }
public async Task DeleteLineItem(string orderID, string lineItemID, VerifiedUserContext verifiedUser) { LineItem lineItem = await _oc.LineItems.GetAsync(OrderDirection.Incoming, orderID, lineItemID); await _oc.LineItems.DeleteAsync(OrderDirection.Incoming, orderID, lineItemID); List <HSLineItem> existingLineItems = await ListAllAsync.List((page) => _oc.LineItems.ListAsync <HSLineItem>(OrderDirection.Outgoing, orderID, page: page, pageSize: 100, filters: $"Product.ID={lineItem.ProductID}", accessToken: verifiedUser.AccessToken)); if (existingLineItems != null && existingLineItems.Count > 0) { var product = await _meProductCommand.Get(lineItem.ProductID, verifiedUser); await ValidateLineItemUnitCost(orderID, product, existingLineItems, null); } await _promotionCommand.AutoApplyPromotions(orderID); }
public MultiTenantOCClient(VerifiedUserContext user) : base( new OrderCloudClientConfig() { ApiUrl = user.ApiUrl, AuthUrl = user.AuthUrl, ClientId = user.ClientID, Roles = new[] { ApiRole.FullAccess } } ) { TokenResponse = new TokenResponse() { AccessToken = user.AccessToken, ExpiresUtc = user.AccessTokenExpiresUTC }; }
public async Task <TaxCertificate> GetAsync(string locationID, VerifiedUserContext verifiedUser) { await EnsureUserCanManageLocationResaleCert(locationID, verifiedUser); var buyerID = locationID.Split('-')[0]; var address = await _oc.Addresses.GetAsync <HSAddressBuyer>(buyerID, locationID); if (address.xp.AvalaraCertificateID != null) { return(await _avalara.GetCertificateAsync((int)address.xp.AvalaraCertificateID)); } else { return(new TaxCertificate()); } }
public async Task<OrderDetails> GetOrderDetails(string orderID, VerifiedUserContext verifiedUser) { var order = await _oc.Orders.GetAsync<HSOrder>(OrderDirection.Incoming, orderID); await EnsureUserCanAccessOrder(order, verifiedUser); var lineItems = ListAllAsync.List((page) => _oc.LineItems.ListAsync(OrderDirection.Incoming, orderID, page: page, pageSize: 100)); var promotions = _oc.Orders.ListPromotionsAsync(OrderDirection.Incoming, orderID, pageSize: 100); var payments = _oc.Payments.ListAsync(OrderDirection.Incoming, order.ID, pageSize: 100); var approvals = _oc.Orders.ListApprovalsAsync(OrderDirection.Incoming, orderID, pageSize: 100); return new OrderDetails { Order = order, LineItems = (await lineItems), Promotions = (await promotions).Items, Payments = (await payments).Items, Approvals = (await approvals).Items }; }
public async Task <List <ReportTemplate> > List(ReportTypeEnum reportType, VerifiedUserContext verifiedUser) { var feedOptions = new FeedOptions() { PartitionKey = new PartitionKey($"{verifiedUser.SellerID}") }; var templates = new List <ReportTemplate>(); if (verifiedUser.UsrType == "admin") { templates = await _store.Query(feedOptions).Where(x => x.ReportType == reportType).ToListAsync(); } else if (verifiedUser.UsrType == "supplier") { templates = await _store.Query(feedOptions).Where(x => x.ReportType == reportType && x.AvailableToSuppliers == true).ToListAsync(); } return(templates); }
public async Task <JObject> GetOrderAsync(string ID, VerifiedUserContext user) { //TODO: BaseUrl cannot be found here var ocAuth = await _ocSeller.AuthenticateAsync(); HSShipEstimate estimate; HSShipMethod ship_method = null; var supplierWorksheet = await _ocSeller.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Outgoing, ID, ocAuth.AccessToken); var buyerWorksheet = await _ocSeller.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, ID.Split('-')[0], ocAuth.AccessToken); var buyerLineItems = buyerWorksheet.GetBuyerLineItemsBySupplierID(supplierWorksheet.Order.ToCompanyID); if (buyerWorksheet?.ShipEstimateResponse != null && buyerWorksheet?.ShipEstimateResponse?.ShipEstimates.Count > 0) { estimate = buyerWorksheet.GetMatchingShipEstimate(supplierWorksheet?.LineItems?.FirstOrDefault()?.ShipFromAddressID); ship_method = estimate?.ShipMethods?.FirstOrDefault(m => m.ID == estimate.SelectedShipMethodID); } var returnObject = new JObject { }; if (supplierWorksheet.Order != null) { returnObject.Add(new JProperty("SupplierOrder", new JObject { { "Order", JToken.FromObject(supplierWorksheet?.Order) }, new JProperty("LineItems", JToken.FromObject(supplierWorksheet?.LineItems)) })); } if (buyerWorksheet.Order != null) { returnObject.Add(new JProperty("BuyerOrder", new JObject { { "Order", JToken.FromObject(buyerWorksheet?.Order) }, new JProperty("LineItems", JToken.FromObject(buyerLineItems)) })); } if (ship_method != null) { returnObject.Add(new JProperty("ShipMethod", JToken.FromObject(ship_method))); } return(JObject.FromObject(returnObject)); }
public async Task <HSMeKitProduct> GetMeKit(string id, VerifiedUserContext user) { var _product = await _oc.Me.GetProductAsync <HSMeProduct>(id, user.AccessToken); var _images = GetProductImages(id, user.AccessToken); var _attachments = GetProductAttachments(id, user.AccessToken); var _productAssignments = await _cms.Documents.Get <HSMeKitProductAssignment>("HSKitProductAssignment", _product.ID, user.AccessToken); var meKitProduct = new HSMeKitProduct { ID = _product.ID, Name = _product.Name, Product = _product, Images = await _images, Attachments = await _attachments, ProductAssignments = await _getMeKitDetails(_productAssignments.Doc, user.AccessToken) }; return(await _meProductCommand.ApplyBuyerPricing(meKitProduct, user)); }
public async Task <OrderDetails> GetOrderDetails(string orderID, VerifiedUserContext verifiedUser) { var order = await _oc.Orders.GetAsync <HSOrder>(OrderDirection.Incoming, orderID); await EnsureUserCanAccessOrder(order, verifiedUser); var lineItems = _oc.LineItems.ListAllAsync(OrderDirection.Incoming, orderID); var promotions = _oc.Orders.ListAllPromotionsAsync(OrderDirection.Incoming, orderID); var payments = _oc.Payments.ListAllAsync(OrderDirection.Incoming, order.ID); var approvals = _oc.Orders.ListAllApprovalsAsync(OrderDirection.Incoming, orderID); return(new OrderDetails { Order = order, LineItems = await lineItems, Promotions = await promotions, Payments = await payments, Approvals = await approvals }); }
public ListPage <ReportTypeResource> FetchAllReportTypes(VerifiedUserContext verifiedUser) { var types = ReportTypeResource.ReportTypes.ToList(); if (verifiedUser.UserType == "supplier") { types = types.Where(type => type.AvailableToSuppliers).ToList(); } var listPage = new ListPage <ReportTypeResource> { Items = types, Meta = new ListPageMeta { Page = 1, PageSize = 100, TotalCount = types.Count, TotalPages = 1 } }; return(listPage); }
private async Task CreateContentDocSchemas(VerifiedUserContext userContext) { var kitSchema = new DocSchema { ID = "HSKitProductAssignment", RestrictedAssignmentTypes = new List <ResourceType> { }, Schema = JObject.Parse(File.ReadAllText("../Headstart.Common/Assets/ContentDocSchemas/kitproduct.json")) }; var supplierFilterConfigSchema = new DocSchema { ID = "SupplierFilterConfig", RestrictedAssignmentTypes = new List <ResourceType> { }, Schema = JObject.Parse(File.ReadAllText("../Headstart.Common/Assets/ContentDocSchemas/supplierfilterconfig.json")) }; await Task.WhenAll( _cms.Schemas.Create(kitSchema, userContext.AccessToken), _cms.Schemas.Create(supplierFilterConfigSchema, userContext.AccessToken) ); }
/// <summary> /// Validates LineItemStatus Change, Updates Line Item Statuses, Updates Order Statuses, Sends Necessary Emails /// </summary> // all line item status changes should go through here public async Task <List <HSLineItem> > UpdateLineItemStatusesAndNotifyIfApplicable(OrderDirection orderDirection, string orderID, LineItemStatusChanges lineItemStatusChanges, VerifiedUserContext verifiedUser = null) { var userType = verifiedUser?.UsrType ?? "noUser"; var verifiedUserType = userType.Reserialize <VerifiedUserType>(); var buyerOrderID = orderID.Split('-')[0]; var previousLineItemsStates = await ListAllAsync.List((page) => _oc.LineItems.ListAsync <HSLineItem>(OrderDirection.Incoming, buyerOrderID, page: page, pageSize: 100)); ValidateLineItemStatusChange(previousLineItemsStates.ToList(), lineItemStatusChanges, verifiedUserType); var updatedLineItems = await Throttler.RunAsync(lineItemStatusChanges.Changes, 100, 5, (lineItemStatusChange) => { var newPartialLineItem = BuildNewPartialLineItem(lineItemStatusChange, previousLineItemsStates.ToList(), lineItemStatusChanges.Status); // if there is no verified user passed in it has been called from somewhere else in the code base and will be done with the client grant access return(verifiedUser != null ? _oc.LineItems.PatchAsync <HSLineItem>(orderDirection, orderID, lineItemStatusChange.ID, newPartialLineItem, verifiedUser.AccessToken) : _oc.LineItems.PatchAsync <HSLineItem>(orderDirection, orderID, lineItemStatusChange.ID, newPartialLineItem)); }); var buyerOrder = await _oc.Orders.GetAsync <HSOrder>(OrderDirection.Incoming, buyerOrderID); var allLineItemsForOrder = await ListAllAsync.List((page) => _oc.LineItems.ListAsync <HSLineItem>(OrderDirection.Incoming, buyerOrderID, page: page, pageSize: 100)); var lineItemsChanged = allLineItemsForOrder.Where(li => lineItemStatusChanges.Changes.Select(li => li.ID).Contains(li.ID)).ToList(); var supplierIDsRelatingToChange = lineItemsChanged.Select(li => li.SupplierID).Distinct().ToList(); var relatedSupplierOrderIDs = supplierIDsRelatingToChange.Select(supplierID => $"{buyerOrderID}-{supplierID}").ToList(); var statusSync = SyncOrderStatuses(buyerOrder, relatedSupplierOrderIDs, allLineItemsForOrder.ToList()); var notifictionSender = HandleLineItemStatusChangeNotification(verifiedUserType, buyerOrder, supplierIDsRelatingToChange, lineItemsChanged, lineItemStatusChanges); await statusSync; await notifictionSender; return(updatedLineItems.ToList()); }
public async Task <HSLineItem> UpsertLineItem(string orderID, HSLineItem liReq, VerifiedUserContext user) { // get me product with markedup prices correct currency and the existing line items in parellel var productRequest = _meProductCommand.Get(liReq.ProductID, user); var existingLineItemsRequest = ListAllAsync.List((page) => _oc.LineItems.ListAsync <HSLineItem>(OrderDirection.Outgoing, orderID, page: page, pageSize: 100, filters: $"Product.ID={liReq.ProductID}", accessToken: user.AccessToken)); var orderRequest = _oc.Orders.GetAsync(OrderDirection.Incoming, orderID); var existingLineItems = await existingLineItemsRequest; var product = await productRequest; var li = new HSLineItem(); var markedUpPrice = ValidateLineItemUnitCost(orderID, product, existingLineItems, liReq); liReq.UnitPrice = await markedUpPrice; var order = await orderRequest; Require.That(!order.IsSubmitted, new ErrorCode("Invalid Order Status", 400, "Order has already been submitted")); liReq.xp.StatusByQuantity = LineItemStatusConstants.EmptyStatuses; liReq.xp.StatusByQuantity[LineItemStatus.Open] = liReq.Quantity; var preExistingLi = ((List <HSLineItem>)existingLineItems).Find(eli => LineItemsMatch(eli, liReq)); if (preExistingLi != null) { li = await _oc.LineItems.SaveAsync <HSLineItem>(OrderDirection.Incoming, orderID, preExistingLi.ID, liReq); } else { li = await _oc.LineItems.CreateAsync <HSLineItem>(OrderDirection.Incoming, orderID, liReq); } await _promotionCommand.AutoApplyPromotions(orderID); return(li); }
public async Task <CreditCard> TokenizeAndSave(string buyerID, OrderCloudIntegrationsCreditCardToken card, VerifiedUserContext user) { var creditCard = await _oc.CreditCards.CreateAsync(buyerID, await Tokenize(card, user.AccessToken), user.AccessToken); return(creditCard); }
public async Task <BuyerCreditCard> MeTokenizeAndSave(OrderCloudIntegrationsCreditCardToken card, VerifiedUserContext user) { var buyerCreditCard = await _oc.Me.CreateCreditCardAsync(await MeTokenize(card, user.AccessToken), user.AccessToken); return(buyerCreditCard); }