Пример #1
0
        private async Task ProcessProductAsync(Product product)
        {
            CosmosListPage <LineItemDetailData> lineItemData = await GetLineItemDataAsync(product.ID);

            List <ProductDetailData> productDataList = await CreateProductDetailDataAsync(product, lineItemData?.Items);

            //Get current products in Cosmos to update/replace
            var requestOptions = BuildQueryRequestOptions();

            foreach (ProductDetailData productData in productDataList)
            {
                var queryable = _productDetailRepo.GetQueryable().Where(x => x.PartitionKey == "PartitionValue" && x.Data.SpecCombo == productData.Data.SpecCombo);

                var listOptions = BuildProductListOptions(productData.ProductID, productData.Data.SpecCombo);

                CosmosListPage <ProductDetailData> currentProductDetailListPage = await _productDetailRepo.GetItemsAsync(queryable, requestOptions, listOptions);

                var cosmosID = "";
                if (currentProductDetailListPage.Items.Count == 1)
                {
                    cosmosID = productData.id = currentProductDetailListPage.Items[0].id;
                }

                await _productDetailRepo.UpsertItemAsync(cosmosID, productData);
            }
        }
        private async Task UpsertOrderAndShipments(string orderID)
        {
            var orderWorksheet = await _oc.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, orderID);

            var shipments = await _oc.Shipments.ListAllAsync(orderID);

            foreach (var shipment in shipments)
            {
                var shipmentItems = await _oc.Shipments.ListAllItemsAsync(shipment.ID);

                foreach (var shipmentItem in shipmentItems)
                {
                    var cosmosOrderWithShipments = OrderWithShipmentsMapper.Map(orderWorksheet, shipment, shipmentItem);

                    if (cosmosOrderWithShipments.QuantityShipped != 0)
                    {
                        var queryable = _ordersAndShipmentsDataRepo.GetQueryable().Where(orderWithShipments => orderWithShipments.PartitionKey == "PartitionValue");

                        var requestOptions = BuildQueryRequestOptions();

                        var listOptions = BuildOrderWithShipmentsListOptions(orderID, shipmentItem.LineItemID, shipment.ID);

                        CosmosListPage <OrderWithShipments> currentOrderWithShipmentsListPage = await _ordersAndShipmentsDataRepo.GetItemsAsync(queryable, requestOptions, listOptions);

                        var cosmosID = "";
                        if (currentOrderWithShipmentsListPage.Items.Count() == 1)
                        {
                            cosmosID = cosmosOrderWithShipments.id = currentOrderWithShipmentsListPage.Items[0].id;
                        }

                        await _ordersAndShipmentsDataRepo.UpsertItemAsync(cosmosID, cosmosOrderWithShipments);
                    }
                }
            }
        }
Пример #3
0
        public async Task <List <HSLineItemOrder> > BuyerLineItemDetail(ListArgs <HSOrder> args, BuyerReportViewContext viewContext, string userID, string locationID, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = new List <ListFilter>();

            filters.Add(ApplyBuyerLineContext(viewContext, userID, locationID, decodedToken));

            foreach (var filter in args.Filters)
            {
                filters.Add(ApplyBuyerLineFilter(filter));
            }

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "OrderID",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <LineItemDetailData> queryable = _lineItemDetail.GetQueryable()
                                                        .Where(order =>
                                                               order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <LineItemDetailData> lineItemDataResponse = await _lineItemDetail.GetItemsAsync(queryable, requestOptions, listOptions);

            List <LineItemDetailData> lineItemData = lineItemDataResponse.Items;

            listOptions.ContinuationToken = lineItemDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <LineItemDetailData> responseWithToken = await _lineItemDetail.GetItemsAsync(queryable, requestOptions, listOptions);

                lineItemData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var lineItems = new List <HSLineItemOrder>();

            foreach (LineItemDetailData detailData in lineItemData)
            {
                foreach (HSLineItem lineDetail in detailData.Data.LineItems)
                {
                    lineItems.Add(new HSLineItemOrder
                    {
                        HSOrder    = detailData.Data.Order,
                        HSLineItem = lineDetail
                    });
                }
            }

            return(lineItems);
        }
Пример #4
0
        public async Task <CosmosListPage <RMA> > ListBuyerRMAs(CosmosListOptions listOptions, string buyerID)
        {
            IQueryable <RMA> queryable = _rmaRepo.GetQueryable().Where(rma => rma.FromBuyerID == buyerID);

            CosmosListPage <RMA> rmas = await GenerateRMAList(queryable, listOptions);

            return(rmas);
        }
Пример #5
0
        public async Task <CosmosListPage <RMA> > ListBuyerRMAs(CosmosListOptions listOptions, VerifiedUserContext verifiedUser)
        {
            IQueryable <RMA> queryable = _rmaRepo.GetQueryable().Where(rma => rma.FromBuyerID == verifiedUser.Buyer.ID);

            CosmosListPage <RMA> rmas = await GenerateRMAList(queryable, listOptions);

            return(rmas);
        }
Пример #6
0
        private async Task <CosmosListPage <RMA> > GenerateRMAList(IQueryable <RMA> queryable, CosmosListOptions listOptions)
        {
            QueryRequestOptions requestOptions = new QueryRequestOptions();

            requestOptions.MaxItemCount = listOptions.PageSize;

            CosmosListPage <RMA> rmas = await _rmaRepo.GetItemsAsync(queryable, requestOptions, listOptions);

            return(rmas);
        }
Пример #7
0
        public async Task <List <OrderWithShipments> > ShipmentDetail(string templateID, ListArgs <ReportAdHocFilters> args, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = await BuildFilters(templateID, args, decodedToken, "DateSubmitted", "SupplierID");

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "OrderID",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <OrderWithShipments> queryable = _ordersAndShipments.GetQueryable()
                                                        .Where(order =>
                                                               order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <OrderWithShipments> ordersWithShipmentsDataResponse = await _ordersAndShipments.GetItemsAsync(queryable, requestOptions, listOptions);

            List <OrderWithShipments> orderWithShipmentsData = ordersWithShipmentsDataResponse.Items;

            listOptions.ContinuationToken = ordersWithShipmentsDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <OrderWithShipments> responseWithToken = await _ordersAndShipments.GetItemsAsync(queryable, requestOptions, listOptions);

                orderWithShipmentsData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var ordersWithShipments = new List <OrderWithShipments>();

            var supplierFilter = args.Filters.FirstOrDefault(filter => filter.PropertyName == "SupplierID");

            var me = await _oc.Me.GetAsync(decodedToken.AccessToken);

            foreach (OrderWithShipments detailData in orderWithShipmentsData)
            {
                if (supplierFilter == null || supplierFilter.FilterExpression == detailData.SupplierID)
                {
                    if (decodedToken.CommerceRole == CommerceRole.Seller || me.Supplier.ID == detailData.SupplierID)
                    {
                        ordersWithShipments.Add(detailData);
                    }
                }
            }

            return(ordersWithShipments);
        }
Пример #8
0
        private async Task <RMA> GetRMA(string rmaNumber, DecodedToken decodedToken)
        {
            var currentRMAFilter = new ListFilter("RMANumber", rmaNumber);
            CosmosListOptions currentRMAListOptions = new CosmosListOptions()
            {
                PageSize = 1, ContinuationToken = null, Filters = { currentRMAFilter }
            };
            CosmosListPage <RMA> currentRMAListPage = await ListRMAs(currentRMAListOptions, decodedToken);

            RMA currentRMA = currentRMAListPage.Items[0];

            return(currentRMA);
        }
Пример #9
0
        public async Task <RMAWithLineItemStatusByQuantity> ProcessRefund(string rmaNumber, DecodedToken decodedToken)
        {
            var me = await _oc.Me.GetAsync(accessToken : decodedToken.AccessToken);

            RMA rma = await GetRMA(rmaNumber, decodedToken);

            ValidateRMA(rma, me.Supplier.ID);

            decimal initialAmountRefunded = rma.TotalCredited;

            IEnumerable <RMALineItem> rmaLineItemsToUpdate = rma.LineItems
                                                             .Where(li => !li.IsRefunded &&
                                                                    (li.Status == RMALineItemStatus.Approved || li.Status == RMALineItemStatus.PartialQtyApproved)).ToList();

            HSOrderWorksheet worksheet = await _oc.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, rma.SourceOrderID);

            CosmosListPage <RMA> allRMAsOnThisOrder = await ListRMAsByOrderID(worksheet.Order.ID, decodedToken.CommerceRole, me, true);

            CalculateAndUpdateLineTotalRefund(rmaLineItemsToUpdate, worksheet, allRMAsOnThisOrder, rma.SupplierID);

            // UPDATE RMA LINE ITEM STATUSES
            SetRMALineItemStatusesToComplete(rmaLineItemsToUpdate);

            // UPDATE RMA STATUS
            UpdateRMAStatus(rma);

            await HandleRefund(rma, allRMAsOnThisOrder, worksheet, decodedToken);

            MarkRMALineItemsAsRefunded(rmaLineItemsToUpdate);

            decimal totalRefundedForThisTransaction = rma.TotalCredited - initialAmountRefunded;
            RMALog  log = new RMALog()
            {
                Status = rma.Status, Date = DateTime.Now, AmountRefunded = totalRefundedForThisTransaction, FromUserID = me.ID
            };

            rma.Logs.Insert(0, log);

            List <LineItemStatusChanges> lineItemStatusChangesList = BuildLineItemStatusChanges(rmaLineItemsToUpdate, worksheet, rma.Type, false);

            // SAVE RMA
            ItemResponse <RMA> updatedRMA = await _rmaRepo.ReplaceItemAsync(rma.id, rma);

            RMAWithLineItemStatusByQuantity rmaWithStatusByQuantityChanges = new RMAWithLineItemStatusByQuantity()
            {
                SupplierOrderID = $"{rma.SourceOrderID}-{rma.SupplierID}", RMA = updatedRMA.Resource, LineItemStatusChangesList = lineItemStatusChangesList
            };

            return(rmaWithStatusByQuantityChanges);
        }
Пример #10
0
        public async Task <CosmosListPage <RMA> > ListRMAs(CosmosListOptions listOptions, DecodedToken decodedToken)
        {
            IQueryable <RMA> queryable = _rmaRepo.GetQueryable().Where(rma => rma.PartitionKey == "PartitionValue");

            if (decodedToken.CommerceRole == CommerceRole.Supplier)
            {
                var me = await _oc.Me.GetAsync(accessToken : decodedToken.AccessToken);

                queryable = queryable.Where(rma => rma.SupplierID == me.Supplier.ID);
            }

            CosmosListPage <RMA> rmas = await GenerateRMAList(queryable, listOptions);

            return(rmas);
        }
Пример #11
0
        private bool ShouldIssueFullLineItemRefund(RMALineItem rmaLineItem, CosmosListPage <RMA> allRMAsOnThisOrder, HSOrderWorksheet orderWorksheet, string supplierID)
        {
            TransactionLineModel orderWorksheetLineItem = orderWorksheet.OrderCalculateResponse.xp.TaxResponse.lines.FirstOrDefault(li => li.lineNumber == rmaLineItem.ID);
            var rmasFromThisSupplier = allRMAsOnThisOrder.Items.Where(r => r.SupplierID == supplierID);

            // If this is the only RMA for this line item and all requested RMA quantity are approved, and the quantity equals the original order quantity, issue a full refund (line item cost + tax).
            if (rmaLineItem.Status == RMALineItemStatus.Approved && rmaLineItem.QuantityProcessed == orderWorksheetLineItem.quantity && rmasFromThisSupplier.Count() == 1)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #12
0
        public async Task <List <OrderDetailData> > PurchaseOrderDetail(string templateID, ListArgs <ReportAdHocFilters> args, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = await BuildFilters(templateID, args, decodedToken, "DateSubmitted", "xp.SupplierIDs", "ShippingAddressID");

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "OrderID",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <OrderDetailData> queryable = _purchaseOrderDetail.GetQueryable()
                                                     .Where(order =>
                                                            order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <OrderDetailData> purchaseOrderDataResponse = await _purchaseOrderDetail.GetItemsAsync(queryable, requestOptions, listOptions);

            List <OrderDetailData> purchaseOrderData = purchaseOrderDataResponse.Items;

            listOptions.ContinuationToken = purchaseOrderDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <OrderDetailData> responseWithToken = await _purchaseOrderDetail.GetItemsAsync(queryable, requestOptions, listOptions);

                purchaseOrderData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var purchaseOrders = new List <OrderDetailData>();

            foreach (OrderDetailData purchaseOrder in purchaseOrderData)
            {
                purchaseOrder.ShipFromAddressID = purchaseOrder.Data.xp.SelectedShipMethodsSupplierView != null ? purchaseOrder.Data.xp.SelectedShipMethodsSupplierView[0].ShipFromAddressID : null;
                purchaseOrder.ShipMethod        = purchaseOrder.Data.xp.SelectedShipMethodsSupplierView != null ? purchaseOrder.Data.xp.SelectedShipMethodsSupplierView[0].Name : null;
                purchaseOrders.Add(purchaseOrder);
            }

            return(purchaseOrders);
        }
Пример #13
0
        public async Task <List <OrderDetailData> > SalesOrderDetail(string templateID, ListArgs <ReportAdHocFilters> args, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = await BuildFilters(templateID, args, decodedToken, "DateSubmitted", "xp.SupplierIDs", "FromCompanyID");

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "OrderID",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <OrderDetailData> queryable = _salesOrderDetail.GetQueryable()
                                                     .Where(order =>
                                                            order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <OrderDetailData> salesOrderDataResponse = await _salesOrderDetail.GetItemsAsync(queryable, requestOptions, listOptions);

            List <OrderDetailData> salesOrderData = salesOrderDataResponse.Items;

            listOptions.ContinuationToken = salesOrderDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <OrderDetailData> responseWithToken = await _salesOrderDetail.GetItemsAsync(queryable, requestOptions, listOptions);

                salesOrderData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var salesOrders = new List <OrderDetailData>();

            foreach (OrderDetailData salesOrder in salesOrderData)
            {
                salesOrders.Add(salesOrder);
            }

            return(salesOrders);
        }
Пример #14
0
        public async Task <CosmosListPage <RMA> > ListRMAsForOrder(string orderID, DecodedToken decodedToken)
        {
            var me = await _oc.Me.GetAsync(accessToken : decodedToken.AccessToken);

            HSOrder order = await _oc.Orders.GetAsync <HSOrder>(OrderDirection.Incoming, orderID);

            await EnsureUserCanAccessOrder(order, decodedToken);

            var listFilter = new ListFilter("SourceOrderID", orderID);
            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize = 100, ContinuationToken = null, Filters = { listFilter }
            };

            CosmosListPage <RMA> rmasOnOrder = await _rmaCommand.ListBuyerRMAs(listOptions, me.Buyer.ID);

            return(rmasOnOrder);
        }
Пример #15
0
        private async Task UpsertLineItemDetail(string orderID)
        {
            var orderWorksheet = await _oc.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, orderID);

            var lineItems = await _oc.LineItems.ListAllAsync <HSLineItem>(OrderDirection.Incoming, orderID);

            var buyer = await _oc.Buyers.GetAsync <HSBuyer>(orderWorksheet.Order.FromCompanyID);

            var lineItemsWithMiscFields = await BuildLineItemsMiscFields(lineItems, orderWorksheet, buyer.Name);

            var lineItemsWithPurchaseOrders = await BuildLineItemsWithPurchaseOrders(orderID);

            var orderLineItemData = new HSOrderLineItemData()
            {
                Order     = orderWorksheet.Order,
                LineItems = lineItems,
                LineItemsWithMiscFields          = lineItemsWithMiscFields,
                LineItemsWithPurchaseOrderFields = lineItemsWithPurchaseOrders
            };

            var queryable = _lineItemDetailDataRepo.GetQueryable().Where(order => order.PartitionKey == "PartitionValue");

            var requestOptions = BuildQueryRequestOptions();

            var cosmosLineItemOrder = new LineItemDetailData()
            {
                PartitionKey = "PartitionValue",
                OrderID      = orderID,
                Data         = orderLineItemData
            };

            var listOptions = BuildListOptions(orderID);

            CosmosListPage <LineItemDetailData> currentLineItemListPage = await _lineItemDetailDataRepo.GetItemsAsync(queryable, requestOptions, listOptions);

            var cosmosID = "";

            if (currentLineItemListPage.Items.Count() == 1)
            {
                cosmosID = cosmosLineItemOrder.id = currentLineItemListPage.Items[0].id;
            }

            await _lineItemDetailDataRepo.UpsertItemAsync(cosmosID, cosmosLineItemOrder);
        }
Пример #16
0
        private async Task <CosmosListPage <LineItemDetailData> > GetLineItemDataAsync(string productID)
        {
            var queryable = _lineItemDetailDataRepo
                            .GetQueryable()
                            .Where(order => order.Data.LineItems.Any(lineItem => lineItem.ProductID == productID) && order.Data.Order.DateCreated > DateTime.Now.AddMonths(-12));

            var requestOptions = new QueryRequestOptions()
            {
                MaxItemCount = 1
            };

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize = 100, ContinuationToken = null
            };

            CosmosListPage <LineItemDetailData> currentLineItemListPage = await _lineItemDetailDataRepo.GetItemsAsync(queryable, requestOptions, listOptions);

            return(currentLineItemListPage);
        }
Пример #17
0
        private async Task <string> BuildRMANumber(HSOrder order)
        {
            var args = new CosmosListOptions()
            {
                PageSize = 100,
                Filters  = new List <ListFilter>()
                {
                    new ListFilter("SourceOrderID", order.ID)
                }
            };

            CosmosListPage <RMA> existingRMAsOnOrder = await ListBuyerRMAs(args, order.FromCompanyID);

            int lastRMANumber = existingRMAsOnOrder.Items
                                .OrderBy(rma => rma.RMANumber)
                                .Select(rma => int.Parse(rma.RMANumber.Substring(rma.RMANumber.LastIndexOf("-") + 1)))
                                .LastOrDefault();
            string rmaSuffix = $"{lastRMANumber + 1}".PadLeft(2, '0');
            string rmaNumber = $"{order.ID}-RMA-{rmaSuffix}";

            return(rmaNumber);
        }
Пример #18
0
        private async Task UpsertSalesOrderDetail(string orderID)
        {
            var order = await _oc.Orders.GetAsync <HSOrder>(OrderDirection.Incoming, orderID);

            var brand = await _oc.Buyers.GetAsync <HSBuyer>(order.FromCompanyID);

            var promos = await _oc.Orders.ListPromotionsAsync(OrderDirection.Incoming, orderID);

            var cosmosSalesOrder = new OrderDetailData()
            {
                PartitionKey = "PartitionValue",
                OrderID      = orderID,
                Data         = order,
                BrandName    = brand.Name
            };

            if (promos.Items.Count > 0)
            {
                cosmosSalesOrder.Promos = ReportPromoBuilder.BuildPromoFields(promos, ReportTypeEnum.SalesOrderDetail);
            }

            var queryable = _salesOrderDetailDataRepo.GetQueryable().Where(order => order.PartitionKey == "PartitionValue");

            var requestOptions = BuildQueryRequestOptions();

            var listOptions = BuildListOptions(orderID);

            CosmosListPage <OrderDetailData> currentOrderListPage = await _salesOrderDetailDataRepo.GetItemsAsync(queryable, requestOptions, listOptions);

            var cosmosID = "";

            if (currentOrderListPage.Items.Count() == 1)
            {
                cosmosID = cosmosSalesOrder.id = currentOrderListPage.Items[0].id;
            }

            await _salesOrderDetailDataRepo.UpsertItemAsync(cosmosID, cosmosSalesOrder);
        }
Пример #19
0
        public virtual async Task <CosmosListPage <RMA> > ListRMAsByOrderID(string orderID, CommerceRole commerceRole, MeUser me, bool accessAllRMAsOnOrder = false)
        {
            string sourceOrderID = orderID.Split("-")[0];

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize = 100
            };

            IQueryable <RMA> queryable = _rmaRepo.GetQueryable()
                                         .Where(rma =>
                                                rma.PartitionKey == "PartitionValue" &&
                                                rma.SourceOrderID == sourceOrderID);

            if (commerceRole == CommerceRole.Supplier && !accessAllRMAsOnOrder)
            {
                queryable = QueryOnlySupplierRMAs(queryable, me.Supplier.ID);
            }

            CosmosListPage <RMA> rmas = await GenerateRMAList(queryable, listOptions);

            return(rmas);
        }
Пример #20
0
        public async Task <RMA> Get(ListArgs <RMA> args, DecodedToken decodedToken)
        {
            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize = 100,
                Search   = args.Search,
                SearchOn = "RMANumber"
            };

            IQueryable <RMA> queryable = _rmaRepo.GetQueryable()
                                         .Where(rma =>
                                                rma.PartitionKey == "PartitionValue");

            if (decodedToken.CommerceRole == CommerceRole.Supplier)
            {
                var me = await _oc.Me.GetAsync(accessToken : decodedToken.AccessToken);

                queryable = queryable.Where(rma => rma.SupplierID == me.Supplier.ID);
            }

            CosmosListPage <RMA> rmas = await GenerateRMAList(queryable, listOptions);

            return(rmas.Items[0]);
        }
Пример #21
0
        public async Task <List <HSLineItemOrder> > LineItemDetail(string templateID, ListArgs <ReportAdHocFilters> args, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = await BuildFilters(templateID, args, decodedToken, "DateSubmitted", "xp.SupplierIDs", "FromCompanyID");

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "OrderID",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <LineItemDetailData> queryable = _lineItemDetail.GetQueryable()
                                                        .Where(order =>
                                                               order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <LineItemDetailData> lineItemDataResponse = await _lineItemDetail.GetItemsAsync(queryable, requestOptions, listOptions);

            List <LineItemDetailData> lineItemData = lineItemDataResponse.Items;

            listOptions.ContinuationToken = lineItemDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <LineItemDetailData> responseWithToken = await _lineItemDetail.GetItemsAsync(queryable, requestOptions, listOptions);

                lineItemData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var lineItems = new List <HSLineItemOrder>();

            var supplierFilter = args.Filters.FirstOrDefault(filter => filter.PropertyName == "SupplierID");

            var me = await _oc.Me.GetAsync(decodedToken.AccessToken);

            foreach (LineItemDetailData detailData in lineItemData)
            {
                foreach (HSLineItem lineDetail in detailData.Data.LineItems)
                {
                    if (supplierFilter == null || supplierFilter.FilterExpression == lineDetail.SupplierID)
                    {
                        if (decodedToken.CommerceRole == CommerceRole.Supplier)
                        {
                            //filter down to only current supplierID
                            var lineWithPOOrderFields = detailData.Data.LineItemsWithPurchaseOrderFields != null?detailData.Data.LineItemsWithPurchaseOrderFields.FirstOrDefault(line => line.SupplierID == me.Supplier.ID && line.ID == lineDetail.ID) : null;

                            if (lineWithPOOrderFields != null)
                            {
                                lineDetail.ID = lineWithPOOrderFields.ID;
                                detailData.Data.Order.Subtotal = lineWithPOOrderFields.Subtotal;
                                detailData.Data.Order.ID       = lineWithPOOrderFields.OrderID;
                                detailData.Data.Order.Total    = lineWithPOOrderFields.Total;
                                lineDetail.UnitPrice           = lineWithPOOrderFields.UnitPrice;
                            }
                        }

                        if (decodedToken.CommerceRole == CommerceRole.Seller || me.Supplier.ID == lineDetail.SupplierID)
                        {
                            var lineWithMiscFields = detailData.Data.LineItemsWithMiscFields != null?detailData.Data.LineItemsWithMiscFields.FirstOrDefault(line => line.ID == lineDetail.ID) : null;

                            lineItems.Add(new HSLineItemOrder
                            {
                                HSOrder    = detailData.Data.Order,
                                HSLineItem = lineDetail
                            });
                        }
                    }
                }
            }

            return(lineItems);
        }
Пример #22
0
        private async Task UpsertPurchaseOrderDetail(string orderID)
        {
            var orders = await _oc.Orders.ListAllAsync <HSOrder>(OrderDirection.Outgoing, filters : $"ID={orderID}-*");

            var queryable = _purchaseOrderDetailDataRepo.GetQueryable().Where(order => order.PartitionKey == "PartitionValue");

            var requestOptions = BuildQueryRequestOptions();

            var salesOrderWorksheet = await _oc.IntegrationEvents.GetWorksheetAsync <HSOrderWorksheet>(OrderDirection.Incoming, orderID);

            var promos = await _oc.Orders.ListPromotionsAsync(OrderDirection.Incoming, salesOrderWorksheet.Order.ID);

            var discountedLineItems = new List <HSLineItem>();

            if (promos.Items.Count() > 0)
            {
                var discountedLineFilter = new Dictionary <string, object>
                {
                    ["PromotionDiscount"] = ">0"
                };

                discountedLineItems = await _oc.LineItems.ListAllAsync <HSLineItem>(OrderDirection.Incoming, salesOrderWorksheet.Order.ID, filters : discountedLineFilter);
            }

            foreach (var order in orders)
            {
                order.FromUser = salesOrderWorksheet.Order.FromUser;

                order.BillingAddress = new HSAddressBuyer()
                {
                    xp = new BuyerAddressXP()
                    {
                        LocationID = salesOrderWorksheet?.Order?.BillingAddress?.xp?.LocationID
                    }
                };

                var brand = await _oc.Buyers.GetAsync <HSBuyer>(salesOrderWorksheet.Order.FromCompanyID);

                var supplier = await _oc.Suppliers.GetAsync <HSSupplier>(order.ToCompanyID);

                order.ShippingCost = GetPurchaseOrderShippingCost(salesOrderWorksheet, order.ToCompanyID);
                if (salesOrderWorksheet.Order.PromotionDiscount > 0)
                {
                    order.PromotionDiscount = GetPurchaseOrderPromotionDiscount(salesOrderWorksheet, order.ToCompanyID);
                }

                var cosmosPurchaseOrder = new OrderDetailData()
                {
                    PartitionKey = "PartitionValue",
                    OrderID      = order.ID,
                    Data         = order,
                    SupplierName = supplier.Name,
                    BrandName    = brand.Name,
                };

                if (promos.Items.Count > 0)
                {
                    cosmosPurchaseOrder.Promos = ReportPromoBuilder.BuildPromoFields(promos, ReportTypeEnum.PurchaseOrderDetail, order.ToCompanyID, discountedLineItems);
                }

                var listOptions = BuildListOptions(order.ID);

                CosmosListPage <OrderDetailData> currentOrderListPage = await _purchaseOrderDetailDataRepo.GetItemsAsync(queryable, requestOptions, listOptions);

                var cosmosID = "";
                if (currentOrderListPage.Items.Count() == 1)
                {
                    cosmosID = cosmosPurchaseOrder.id = currentOrderListPage.Items[0].id;
                }

                await _purchaseOrderDetailDataRepo.UpsertItemAsync(cosmosID, cosmosPurchaseOrder);
            }
        }
Пример #23
0
        public async Task <List <RMAWithRMALineItem> > RMADetail(string templateID, ListArgs <ReportAdHocFilters> args, DecodedToken decodedToken)
        {
            IList <ListFilter> filters = await BuildFilters(templateID, args, decodedToken, "DateCreated", "SupplierID");

            CosmosListOptions listOptions = new CosmosListOptions()
            {
                PageSize      = -1,
                Sort          = "RMANumber",
                SortDirection = SortDirection.ASC,
                Filters       = filters,
            };

            IQueryable <RMA> queryable = _rmaDetail.GetQueryable()
                                         .Where(order =>
                                                order.PartitionKey == "PartitionValue");

            QueryRequestOptions requestOptions = new QueryRequestOptions
            {
                MaxItemCount   = listOptions.PageSize,
                MaxConcurrency = -1
            };

            CosmosListPage <RMA> rmaDataResponse = await _rmaDetail.GetItemsAsync(queryable, requestOptions, listOptions);

            List <RMA> rmaData = rmaDataResponse.Items;

            listOptions.ContinuationToken = rmaDataResponse.Meta.ContinuationToken;

            while (listOptions.ContinuationToken != null)
            {
                CosmosListPage <RMA> responseWithToken = await _rmaDetail.GetItemsAsync(queryable, requestOptions, listOptions);

                rmaData.AddRange(responseWithToken.Items);
                listOptions.ContinuationToken = responseWithToken.Meta.ContinuationToken;
            }

            var rmas = new List <RMAWithRMALineItem>();

            var supplierFilter = args.Filters.FirstOrDefault(filter => filter.PropertyName == "SupplierID");

            var me = await _oc.Me.GetAsync(decodedToken.AccessToken);

            foreach (RMA detailData in rmaData)
            {
                if (supplierFilter == null || supplierFilter.FilterExpression == detailData.SupplierID)
                {
                    if (decodedToken.CommerceRole == CommerceRole.Seller || me.Supplier.ID == detailData.SupplierID)
                    {
                        foreach (RMALineItem rmaLineItem in detailData.LineItems)
                        {
                            rmas.Add(new RMAWithRMALineItem
                            {
                                RMA         = detailData,
                                RMALineItem = rmaLineItem
                            });
                        }
                    }
                }
            }

            return(rmas);
        }
Пример #24
0
        public virtual decimal GetShippingRefundIfCancellingAll(HSOrderWorksheet worksheet, RMA rma, CosmosListPage <RMA> allRMAsOnThisOrder)
        {
            // What are all the line items on this order for this supplier and their quantities?
            IEnumerable <HSLineItem> allLineItemsShippedFromThisSupplier = worksheet.LineItems
                                                                           .Where(li => li.SupplierID == rma.SupplierID && worksheet.Order.xp.PaymentMethod == "Credit Card");
            Dictionary <string, int> allLineItemsDictionary = new Dictionary <string, int>();

            foreach (HSLineItem li in allLineItemsShippedFromThisSupplier)
            {
                allLineItemsDictionary.Add(li.ID, li.Quantity);
            }

            // Including this RMA and previous RMAs for this supplier, get everything that has been refunded or is about to be refunded.
            var rmasFromThisSupplier = allRMAsOnThisOrder.Items.Where(r => r.SupplierID == rma.SupplierID);
            Dictionary <string, int> allCompleteRMALineItemsDictionary = new Dictionary <string, int>();

            foreach (RMA existingRMA in rmasFromThisSupplier)
            {
                RMA rmaToAnalyze = existingRMA.RMANumber == rma.RMANumber ? rma : existingRMA;
                foreach (RMALineItem rmaLineItem in rmaToAnalyze.LineItems)
                {
                    if (rmaLineItem.Status == RMALineItemStatus.Complete && rmaLineItem.RefundableViaCreditCard)
                    {
                        if (!allCompleteRMALineItemsDictionary.ContainsKey(rmaLineItem.ID))
                        {
                            allCompleteRMALineItemsDictionary.Add(rmaLineItem.ID, rmaLineItem.QuantityProcessed);
                        }
                        else
                        {
                            allCompleteRMALineItemsDictionary[rmaLineItem.ID] += rmaLineItem.QuantityProcessed;
                        }
                    }
                }
            }

            // If these are the same, the supplier hasn't shipped anything, and shipping should be credited back to the buyer.
            bool shouldShippingBeCanceled = allLineItemsDictionary.OrderBy(kvp => kvp.Key)
                                            .SequenceEqual(allCompleteRMALineItemsDictionary.OrderBy(kvp => kvp.Key));

            // Figure out what the buyer paid for shipping for this supplier on this order.
            if (shouldShippingBeCanceled)
            {
                string selectedShipMethodID = worksheet.ShipEstimateResponse.ShipEstimates
                                              .FirstOrDefault(estimate => estimate.xp.SupplierID == rma.SupplierID)?.SelectedShipMethodID;
                TransactionLineModel shippingLine = worksheet.OrderCalculateResponse.xp.TaxResponse.lines.FirstOrDefault(line => line.lineNumber == selectedShipMethodID);
                decimal shippingCostToRefund      = (decimal)(shippingLine.taxableAmount + shippingLine.tax + shippingLine.exemptAmount);
                rma.ShippingCredited += shippingCostToRefund;
                return(shippingCostToRefund);
            }

            return(0M);
        }
Пример #25
0
        public virtual async Task HandleRefund(RMA rma, CosmosListPage <RMA> allRMAsOnThisOrder, HSOrderWorksheet worksheet, DecodedToken decodedToken)
        {
            // Get payment info from the order
            ListPage <HSPayment> paymentResponse = await _oc.Payments.ListAsync <HSPayment>(OrderDirection.Incoming, rma.SourceOrderID);

            HSPayment creditCardPayment = paymentResponse.Items.FirstOrDefault(payment => payment.Type == OrderCloud.SDK.PaymentType.CreditCard);

            if (creditCardPayment == null)
            {
                // Items were not paid for with a credit card.  No refund to process via CardConnect.
                return;
            }
            HSPaymentTransaction creditCardPaymentTransaction = creditCardPayment.Transactions
                                                                .OrderBy(x => x.DateExecuted)
                                                                .LastOrDefault(x => x.Type == "CreditCard" && x.Succeeded);
            decimal purchaseOrderTotal = (decimal)paymentResponse.Items
                                         .Where(payment => payment.Type == OrderCloud.SDK.PaymentType.PurchaseOrder)
                                         .Select(payment => payment.Amount)
                                         .Sum();

            // Refund via CardConnect
            CardConnectInquireResponse inquiry = await _cardConnect.Inquire(new CardConnectInquireRequest
            {
                merchid  = creditCardPaymentTransaction.xp.CardConnectResponse.merchid,
                orderid  = rma.SourceOrderID,
                set      = "1",
                currency = worksheet.Order.xp.Currency.ToString(),
                retref   = creditCardPaymentTransaction.xp.CardConnectResponse.retref
            });

            decimal shippingRefund = rma.Type == RMAType.Cancellation ? GetShippingRefundIfCancellingAll(worksheet, rma, allRMAsOnThisOrder) : 0M;

            decimal lineTotalToRefund = rma.LineItems
                                        .Where(li => li.IsResolved &&
                                               !li.IsRefunded &&
                                               li.RefundableViaCreditCard &&
                                               (li.Status == RMALineItemStatus.PartialQtyComplete || li.Status == RMALineItemStatus.Complete)
                                               ).Select(li => li.LineTotalRefund)
                                        .Sum();

            decimal totalToRefund = lineTotalToRefund + shippingRefund;

            // Update Total Credited on RMA
            rma.TotalCredited += totalToRefund;

            // Transactions that are queued for capture can only be fully voided, and we are only allowing partial voids moving forward.
            if (inquiry.voidable == "Y" && inquiry.setlstat == QUEUED_FOR_CAPTURE)
            {
                throw new CatalystBaseException(new ApiError
                {
                    ErrorCode = "Payment.FailedToVoidAuthorization",
                    Message   = "This customer's credit card transaction is currently queued for capture and cannot be refunded at this time.  Please try again later."
                });
            }

            // If voidable, but not refundable, void the refund amount off the original order total
            if (inquiry.voidable == "Y")
            {
                await HandleVoidTransaction(worksheet, creditCardPayment, creditCardPaymentTransaction, totalToRefund, rma);
            }

            // If refundable, but not voidable, do a refund
            if (inquiry.voidable == "N")
            {
                await HandleRefundTransaction(worksheet, creditCardPayment, creditCardPaymentTransaction, totalToRefund, rma);
            }
        }
Пример #26
0
        public void CalculateAndUpdateLineTotalRefund(IEnumerable <RMALineItem> lineItemsToUpdate, HSOrderWorksheet orderWorksheet, CosmosListPage <RMA> allRMAsOnThisOrder, string supplierID)
        {
            IEnumerable <dynamic> orderWorksheetLines = orderWorksheet.OrderCalculateResponse.xp.TaxResponse.lines;

            foreach (RMALineItem rmaLineItem in lineItemsToUpdate)
            {
                if (!rmaLineItem.RefundableViaCreditCard)
                {
                    HSLineItem lineItemFromOrder = orderWorksheet.LineItems.FirstOrDefault(li => li.ID == rmaLineItem.ID);
                    rmaLineItem.LineTotalRefund = lineItemFromOrder.LineTotal / lineItemFromOrder.Quantity * rmaLineItem.QuantityProcessed;
                }
                else
                {
                    int     quantityToRefund       = rmaLineItem.QuantityProcessed;
                    dynamic orderWorksheetLineItem = orderWorksheetLines.FirstOrDefault(li => li.lineNumber == rmaLineItem.ID);

                    // Exempt products will have an exempt amount instead of a taxable amount.
                    decimal lineItemBaseCost = orderWorksheetLineItem.exemptAmount > 0 ? orderWorksheetLineItem.exemptAmount : orderWorksheetLineItem.taxableAmount;
                    decimal totalRefundIfReturningAllLineItems = (decimal)(lineItemBaseCost + orderWorksheetLineItem.tax);
                    double  taxableAmountPerSingleLineItem     = (double)(lineItemBaseCost / orderWorksheetLineItem.quantity);
                    double  taxPerSingleLineItem         = (double)(orderWorksheetLineItem.tax / orderWorksheetLineItem.quantity);
                    double  singleQuantityLineItemRefund = Math.Round(taxableAmountPerSingleLineItem + taxPerSingleLineItem, 2);
                    decimal expectedLineTotalRefund      = (decimal)singleQuantityLineItemRefund * quantityToRefund;

                    rmaLineItem.LineTotalRefund = ValidateExpectedLineTotalRefund(expectedLineTotalRefund, totalRefundIfReturningAllLineItems, allRMAsOnThisOrder, rmaLineItem, orderWorksheet, supplierID);
                }

                ApplyPercentToDiscount(rmaLineItem);

                rmaLineItem.Status = rmaLineItem.QuantityProcessed == rmaLineItem.QuantityRequested ? RMALineItemStatus.Complete : RMALineItemStatus.PartialQtyComplete;
            }
        }
Пример #27
0
        private decimal ValidateExpectedLineTotalRefund(decimal expectedLineTotalRefund, decimal totalRefundIfReturningAllLineItems, CosmosListPage <RMA> allRMAsOnThisOrder, RMALineItem rmaLineItem, HSOrderWorksheet orderWorksheet, string supplierID)
        {
            // If minor rounding error occurs during singleQuantityLineItemRefund calculation, ensure we don't refund more than the full line item cost on the order
            // Would only occur for full quantity cancellations/returns
            if (expectedLineTotalRefund > totalRefundIfReturningAllLineItems || ShouldIssueFullLineItemRefund(rmaLineItem, allRMAsOnThisOrder, orderWorksheet, supplierID))
            {
                return(totalRefundIfReturningAllLineItems);
            }

            // If previous RMAs on this order for the same line item
            if (allRMAsOnThisOrder.Items.Count > 1)
            {
                decimal previouslyRefundedAmountForThisLineItem = 0M;
                // Find previously refunded total for line items on this order...
                foreach (RMA previouslyRefundedRMA in allRMAsOnThisOrder.Items)
                {
                    RMALineItem previouslyRefundedLineItem = previouslyRefundedRMA.LineItems.FirstOrDefault(li => li.ID == rmaLineItem.ID);
                    if (previouslyRefundedLineItem != null)
                    {
                        if (previouslyRefundedLineItem.IsRefunded && previouslyRefundedLineItem.RefundableViaCreditCard)
                        {
                            previouslyRefundedAmountForThisLineItem += previouslyRefundedLineItem.LineTotalRefund;
                        }
                    }
                }
                // If previous total + new line total > totalRefundIfReturningAllLineItems, then totalRefundIfReturningAllLineItems - previousTotal = newLineTotal
                if (previouslyRefundedAmountForThisLineItem + expectedLineTotalRefund > totalRefundIfReturningAllLineItems)
                {
                    decimal totalAfterPossibleRoundingErrors = totalRefundIfReturningAllLineItems - previouslyRefundedAmountForThisLineItem;
                    return(totalAfterPossibleRoundingErrors);
                }
            }

            return(expectedLineTotalRefund);
        }