Beispiel #1
0
            /// <summary>
            /// Gets a downloading dataset of a given data group.
            /// </summary>
            /// <param name="request">The get downloading data set data request.</param>
            /// <returns>A dataset.</returns>
            public SingleEntityDataServiceResponse <DataSet> GetDownloadingDataSet(GetDownloadingDataSetDataRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.NullOrWhiteSpace(request.DataGroupName, "request.DataGroupName");

                Stopwatch processTimer = Stopwatch.StartNew();

                ParameterSet parameters = new ParameterSet();

                parameters[DatabaseAccessor.ChannelIdVariableName] = request.RequestContext.GetPrincipal().ChannelId;
                parameters["@vc_DataGroupName"] = request.DataGroupName;

                DataSet result = null;

                using (SqlServerDatabaseContext sqlServerDatabaseContext = new SqlServerDatabaseContext(request))
                {
                    result = sqlServerDatabaseContext.ExecuteStoredProcedureDataSet(GetDownloadingDataSprocName, parameters);
                }

                processTimer.Stop();
                NetTracer.Information("** timer info: GetDownloadingDataSet completed in {0} ms", processTimer.ElapsedMilliseconds);

                return(new SingleEntityDataServiceResponse <DataSet>(result));
            }
Beispiel #2
0
        private void UpdateResultList(int fromRow)
        {
            NetTracer.Information("ExtendedLogOnViewModel : UpdateResultList : Start");

            if (fromRow == 0)
            {
                this.results.Clear();
                ExecuteSelect(null);
            }

            if (isLastRowLoaded)
            {
                return;
            }

            SqlConnection connection = ApplicationSettings.Database.LocalConnection;
            string        query      = string.Format(
                @"SELECT STAFFID, NAME, ASSIGNED FROM
                    (SELECT STAFFID, P.NAME, ASSIGNED, ROW_NUMBER() OVER (ORDER BY {0} {1}) AS ROW
                        FROM RETAILSTAFFTABLE AS S
                        INNER JOIN HCMWORKER W ON W.PERSONNELNUMBER = S.STAFFID
                        INNER JOIN DIRPARTYTABLE P ON W.PERSON = P.RECID
                        INNER JOIN DIRADDRESSBOOKPARTY ABP ON P.RECID = ABP.PARTY AND ABP.VALIDFROM <= GETUTCDATE() AND GETUTCDATE() <= ABP.VALIDTO
                        INNER JOIN DIRADDRESSBOOK AB ON ABP.ADDRESSBOOK = AB.RECID
                        INNER JOIN RETAILSTOREADDRESSBOOK SAB ON AB.RECID = SAB.ADDRESSBOOK AND SAB.ADDRESSBOOKTYPE = 1
                        LEFT JOIN (SELECT STAFF, MIN(LOGONTYPE) AS ASSIGNED FROM RETAILSTAFFEXTENDEDLOGON GROUP BY STAFF) E ON E.STAFF = S.RECID
                        WHERE SAB.STORERECID = @STORERECID AND (STAFFID LIKE @SEARCHFILTER OR P.NAME LIKE @SEARCHFILTER)
                    ) RN
                    WHERE RN.ROW >= @FROMROW AND RN.ROW <= @TOROW",
                sortColumn,
                sortAsc ? "ASC" : "DESC");

            try
            {
                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    command.Parameters.AddWithValue("@STORERECID", ApplicationSettings.Terminal.StorePrimaryId);
                    command.Parameters.AddWithValue("@SEARCHFILTER", String.Format("%{0}%", this.SearchFilter));
                    command.Parameters.AddWithValue("@FROMROW", fromRow);
                    command.Parameters.AddWithValue("@TOROW", (fromRow + PAGE_SIZE));

                    if (connection.State != ConnectionState.Open)
                    {
                        connection.Open();
                    }

                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            this.results.Add(new OperatorViewModel(reader));
                        }
                    }
                }
            }
            finally
            {
                if (connection.State == ConnectionState.Open)
                {
                    connection.Close();
                }
            }

            // If we didn't get back a full page of results then we loaded everything
            if (this.Results.Count % PAGE_SIZE > 0)
            {
                isLastRowLoaded = true;
            }

            OnPropertyChanged("Results");

            NetTracer.Information("SearchViewModel : UpdateResultList : End");
        }
Beispiel #3
0
        internal static CustomerOrderTransaction GetTransactionFromInfo(CustomerOrderInfo orderInfo, SalesOrder salesOrderService)
        {
            CustomerOrderTransaction transaction = (CustomerOrderTransaction)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateCustomerOrderTransaction(
                ApplicationSettings.Terminal.StoreId,
                ApplicationSettings.Terminal.StoreCurrency,
                ApplicationSettings.Terminal.TaxIncludedInPrice,
                SalesOrder.InternalApplication.Services.Rounding,
                salesOrderService);

            // Get all the defaults
            SalesOrder.InternalApplication.BusinessLogic.TransactionSystem.LoadTransactionStatus(transaction);

            // General header properties
            transaction.OrderId   = orderInfo.Id;
            transaction.OrderType = orderInfo.OrderType;

            if (orderInfo.OrderType == CustomerOrderType.Quote)
            {
                transaction.QuotationId = orderInfo.Id;
            }

            transaction.OriginalOrderType = orderInfo.OrderType;

            switch (orderInfo.OrderType)
            {
            case CustomerOrderType.Quote:
                transaction.OrderStatus = GetSalesStatus((SalesQuotationStatus)orderInfo.Status);
                break;

            case CustomerOrderType.SalesOrder:
                transaction.OrderStatus = GetSalesStatus((SalesOrderStatus)orderInfo.Status, (DocumentStatus)orderInfo.DocumentStatus);
                break;

            default:
                transaction.OrderStatus = SalesStatus.Unknown;
                NetTracer.Information("SalesOrder::CustomerOrderTransaction: CustomerOrderInfo OrderType is unknown: {0}", orderInfo.OrderType);
                break;
            }

            transaction.LockPrices = true;

            transaction.ExpirationDate = ParseDateString(orderInfo.ExpiryDateString, DateTime.Today);

            // RequestedDeliveryDate is directly input from user. It is stored in the local timezone
            transaction.RequestedDeliveryDate = ParseDateString(orderInfo.RequestedDeliveryDateString, DateTime.Today);

            // CreationDate is stored in UTC. It needs to be converted to local time zone where order is accessed.
            ((IPosTransactionV2)transaction).BeginDateTime = ParseDateString(orderInfo.CreationDateString, DateTime.UtcNow, DateTimeStyles.AdjustToUniversal).ToLocalTime();
            transaction.LocalHourOfDay = orderInfo.LocalHourOfDay;

            ((IPosTransactionV2)transaction).Comment = orderInfo.Comment;

            // Header delivery
            DM.StoreDataManager storeDataManager = new DM.StoreDataManager(
                SalesOrder.InternalApplication.Settings.Database.Connection,
                SalesOrder.InternalApplication.Settings.Database.DataAreaID);

            transaction.WarehouseId  = orderInfo.WarehouseId;
            transaction.DeliveryMode = storeDataManager.GetDeliveryMode(orderInfo.DeliveryMode);
            transaction.CurrencyCode = orderInfo.CurrencyCode;

            foreach (var code in orderInfo.DiscountCodes)
            {
                transaction.DiscountCodes.AddLast(code);
            }

            // Header affiliation
            DM.AffiliationDataManager affiliationDataManager = new DM.AffiliationDataManager(
                SalesOrder.InternalApplication.Settings.Database.Connection,
                SalesOrder.InternalApplication.Settings.Database.DataAreaID);

            if (orderInfo.Affiliations != null && orderInfo.Affiliations.Any())
            {
                foreach (AffiliationInfo affiliationInfo in orderInfo.Affiliations)
                {
                    transaction.AffiliationLines.AddLast(
                        new AffiliationItem()
                    {
                        RecId           = affiliationInfo.AffiliationId,
                        LoyaltyTier     = affiliationInfo.LoyaltyTierId,
                        AffiliationType = affiliationInfo.AffiliationType
                    });
                }
            }

            // Customer info
            ICustomerSystem customerSystem = SalesOrder.InternalApplication.BusinessLogic.CustomerSystem;

            DM.CustomerDataManager customerDataManager = new DM.CustomerDataManager(
                SalesOrder.InternalApplication.Settings.Database.Connection,
                SalesOrder.InternalApplication.Settings.Database.DataAreaID);

            DE.ICustomer customer = customerSystem.GetCustomerInfo(orderInfo.CustomerAccount);

            // try to get the customer from transaction service
            if (customer == null || customer.IsEmptyCustomer())
            {
                DE.ICustomer tempCustomer = SalesOrder.GetCustomerFromAX(orderInfo.CustomerAccount, customerSystem, customerDataManager);
                if (tempCustomer != null)
                {
                    customer = tempCustomer;
                }
            }

            DE.ICustomer invoicedCustomer = customerSystem.GetCustomerInfo(customer.InvoiceAccount);

            // try to get the invoicedCustomer from transaction service
            if (invoicedCustomer == null || invoicedCustomer.IsEmptyCustomer())
            {
                DE.ICustomer tempinvoicedCustomer = SalesOrder.GetCustomerFromAX(customer.InvoiceAccount, customerSystem, customerDataManager);
                if (tempinvoicedCustomer != null)
                {
                    invoicedCustomer = tempinvoicedCustomer;
                }
            }

            // If InvoiceCustomer is *still* blank/empty then fallback to Customer so that the UI fields are populated.
            if (invoicedCustomer == null || invoicedCustomer.IsEmptyCustomer())
            {
                invoicedCustomer = customer;
            }

            customerSystem.SetCustomer(transaction, customer, invoicedCustomer);

            if (transaction.DeliveryMode != null && !string.IsNullOrWhiteSpace(orderInfo.AddressRecordId))
            {
                DE.IAddress shippingAddress = customerDataManager.GetAddress(Int64.Parse(orderInfo.AddressRecordId));
                customerSystem.SetShippingAddress(transaction, shippingAddress);
            }

            if (!string.IsNullOrEmpty(orderInfo.SalespersonStaffId))
            {
                // Sets the sales person id and name according to AX values
                // This is done because we do not know whether the sales person information is available on this store
                transaction.SalesPersonId   = orderInfo.SalespersonStaffId;
                transaction.SalesPersonName = orderInfo.SalespersonName;

                DM.EmployeeDataManager employees = new DM.EmployeeDataManager(
                    SalesOrder.InternalApplication.Settings.Database.Connection,
                    SalesOrder.InternalApplication.Settings.Database.DataAreaID);

                Employee employee = employees.GetEmployee(ApplicationSettings.Terminal.StoreId, orderInfo.SalespersonStaffId);
                if (employee != null)
                {
                    transaction.SalesPersonId            = employee.StaffId;
                    transaction.SalesPersonName          = employee.Name;
                    transaction.SalesPersonNameOnReceipt = employee.NameOnReceipt;
                }
            }

            transaction.ChannelReferenceId = orderInfo.ChannelReferenceId;
            if (transaction.LoyaltyItem != null && !string.IsNullOrEmpty(orderInfo.LoyaltyCardId))
            {
                transaction.LoyaltyItem.LoyaltyCardNumber = orderInfo.LoyaltyCardId;
            }

            transaction.ReceiptEmailAddress = orderInfo.Email;

            transaction.TotalManualDiscountAmount = orderInfo.TotalManualDiscountAmount;
            transaction.TotalManualPctDiscount    = orderInfo.TotalManualDiscountPercentage;

            DateTime earliestDeliveryDate = DateTime.MaxValue;

            // Items
            foreach (ItemInfo item in orderInfo.Items)
            {
                Collection <Tax.MiscellaneousCharge> lineCharges = new Collection <Tax.MiscellaneousCharge>();
                foreach (ChargeInfo charge in item.Charges)
                {
                    Tax.MiscellaneousCharge lineCharge = (Tax.MiscellaneousCharge)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateMiscellaneousCharge(
                        charge.Amount, charge.SalesTaxGroup, charge.TaxGroup, charge.Code, string.Empty, transaction);
                    lineCharges.Add(lineCharge);
                }

                // add item
                SaleLineItem lineItem = (SaleLineItem)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateSaleLineItem(
                    ApplicationSettings.Terminal.StoreCurrency,
                    SalesOrder.InternalApplication.Services.Rounding,
                    transaction);

                lineItem.Found                        = true;
                lineItem.OrderLineRecordId            = item.RecId;
                lineItem.ItemId                       = item.ItemId;
                lineItem.Quantity                     = item.Quantity;
                lineItem.ReturnQtyAllowed             = item.Quantity;
                lineItem.SalesOrderUnitOfMeasure      = item.Unit;
                lineItem.Price                        = item.Price;
                lineItem.NetAmount                    = item.NetAmount;
                lineItem.QuantityOrdered              = item.Quantity;
                lineItem.QuantityPickedUp             = item.QuantityPicked;
                lineItem.DeliveryMode                 = storeDataManager.GetDeliveryMode(item.DeliveryMode);
                lineItem.DeliveryDate                 = ParseDateString(item.RequestedDeliveryDateString, DateTime.Today);
                lineItem.DeliveryStoreNumber          = item.StoreId;
                lineItem.DeliveryWarehouse            = item.WarehouseId;
                lineItem.SerialId                     = item.SerialId;
                lineItem.BatchId                      = item.BatchId;
                lineItem.HasBeenRecalled              = true;
                lineItem.SalesMarkup                  = item.SalesMarkup;
                lineItem.Comment                      = string.IsNullOrEmpty(item.Comment) ? string.Empty : item.Comment;
                lineItem.LineStatus                   = GetSalesStatus((SalesOrderStatus)item.Status);
                lineItem.LineDiscount                 = item.LineDscAmount;
                lineItem.PeriodicDiscount             = item.PeriodicDiscount;
                lineItem.PeriodicPctDiscount          = item.PeriodicPercentageDiscount;
                lineItem.LineManualDiscountAmount     = item.LineManualDiscountAmount;
                lineItem.LineManualDiscountPercentage = item.LineManualDiscountPercentage;
                lineItem.TotalDiscount                = item.TotalDiscount;
                lineItem.TotalPctDiscount             = item.TotalPctDiscount;

                foreach (Tax.MiscellaneousCharge charge in lineCharges)
                {
                    lineItem.MiscellaneousCharges.Add(charge);
                }

                if (lineItem.DeliveryMode != null && !string.IsNullOrWhiteSpace(item.AddressRecordId))
                {
                    lineItem.ShippingAddress = customerDataManager.GetAddress(Int64.Parse(item.AddressRecordId));
                }

                lineItem.Dimension.VariantId  = item.VariantId;
                lineItem.Dimension.ColorId    = item.ColorId;
                lineItem.Dimension.StyleId    = item.StyleId;
                lineItem.Dimension.SizeId     = item.SizeId;
                lineItem.Dimension.ConfigId   = item.ConfigId;
                lineItem.Dimension.ColorName  = item.ColorName;
                lineItem.Dimension.StyleName  = item.StyleName;
                lineItem.Dimension.SizeName   = item.SizeName;
                lineItem.Dimension.ConfigName = item.ConfigName;

                if (!string.IsNullOrEmpty(lineItem.Dimension.VariantId))
                {
                    Dimensions dimension = (Dimensions)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateDimension();
                    dimension.VariantId = lineItem.Dimension.VariantId;
                    SalesOrder.InternalApplication.Services.Dimension.GetDimensionForVariant(dimension);
                    lineItem.Dimension = dimension;
                }

                if (item.Discounts.Count > 0)
                {
                    lineItem.QuantityDiscounted = item.Quantity;
                    lineItem.LinePctDiscount    = lineItem.CalculateLinePercentDiscount();
                }

                // create discount line from discount info object
                foreach (DiscountInfo discountInfo in item.Discounts)
                {
                    DiscountItem discountItem = ConvertToDiscountItem(
                        discountInfo.DiscountOriginType,
                        discountInfo.ManualDiscountType,
                        discountInfo.CustomerDiscountType,
                        discountInfo.EffectiveAmount,
                        discountInfo.DealPrice,
                        discountInfo.DiscountAmount,
                        discountInfo.Percentage,
                        discountInfo.PeriodicDiscountOfferId,
                        discountInfo.OfferName,
                        discountInfo.DiscountCode);

                    SalesOrder.InternalApplication.Services.Discount.AddDiscountLine(lineItem, discountItem);
                }

                // Set other default properties for this item
                SalesOrder.InternalApplication.Services.Item.ProcessItem(lineItem, bypassSerialNumberEntry: true);

                // Set tax info after defaults, as it may have been overridden.
                lineItem.SalesTaxGroupId         = item.SalesTaxGroup;
                lineItem.SalesTaxGroupIdOriginal = item.SalesTaxGroup;
                lineItem.TaxGroupId         = item.ItemTaxGroup;
                lineItem.TaxGroupIdOriginal = item.ItemTaxGroup;

                // Add it to the transaction
                transaction.Add(lineItem);

                if (lineItem.DeliveryDate < earliestDeliveryDate)
                {
                    earliestDeliveryDate = lineItem.DeliveryDate.HasValue ? lineItem.DeliveryDate.Value : earliestDeliveryDate;
                }
            }

            // Once Items are populated - Reset Customer Tax Group
            //GRW Linea comentada para poder recoger la orden de venta en una tienda distinta a la configurada en AX
            //customerSystem.ResetCustomerTaxGroup(transaction);

            // The order can be created through some other channel other than POS which has set header delivery date as NoDate.
            // This must not be interpreted as a valid date. Instead the earliestDeliveryDate is used.
            if (transaction.RequestedDeliveryDate == NoDate)
            {
                transaction.RequestedDeliveryDate = earliestDeliveryDate;
            }

            // Charges
            foreach (ChargeInfo charge in orderInfo.Charges)
            {
                // add charges
                Tax.MiscellaneousCharge newCharge = (Tax.MiscellaneousCharge)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateMiscellaneousCharge(
                    charge.Amount, charge.SalesTaxGroup, charge.TaxGroup, charge.Code, string.Empty, transaction);
                transaction.Add(newCharge);
            }

            SalesOrder.InternalApplication.BusinessLogic.ItemSystem.CalculatePriceTaxDiscount(transaction);
            transaction.CalculateAmountDue();

            // Payments
            // - total up amounts
            // - add history entries
            transaction.PrepaymentAmountPaid     = decimal.Zero;
            transaction.PrepaymentAmountInvoiced = decimal.Zero;
            decimal nonPrepayments = decimal.Zero;

            PaymentInfo pinfo = new PaymentInfo();

            pinfo.Amount   = -111;
            pinfo.Currency = "MXN";
            orderInfo.Payments.Add(pinfo);

            foreach (PaymentInfo payment in orderInfo.Payments)
            {
                // sum up payments
                decimal amount = (string.IsNullOrWhiteSpace(payment.Currency))
                    ? payment.Amount
                    : (SalesOrder.InternalApplication.Services.Currency.CurrencyToCurrency(
                           payment.Currency,
                           ApplicationSettings.Terminal.StoreCurrency,
                           payment.Amount));

                if (payment.Prepayment)
                {
                    // Sum prepayments to track total deposits paid
                    transaction.PrepaymentAmountPaid += amount;
                }
                else
                {
                    // Sum non-prepayments as base for calculating deposits applied to pickups
                    nonPrepayments += amount;
                }

                CustomerOrderPaymentHistory paymentHistory = (CustomerOrderPaymentHistory)SalesOrder.InternalApplication.BusinessLogic.Utility.CreateCustomerOrderPaymentHistory();
                paymentHistory.Amount   = payment.Amount;
                paymentHistory.Currency = payment.Currency;
                paymentHistory.Date     = ParseDateString(payment.DateString, DateTime.MinValue);
                paymentHistory.Balance  = transaction.NetAmountWithTaxAndCharges - transaction.PrepaymentAmountPaid;

                transaction.PaymentHistory.Add(paymentHistory);
            }

            // Prepayment/Deposit override info
            transaction.PrepaymentAmountOverridden = orderInfo.PrepaymentAmountOverridden;
            if (transaction.PrepaymentAmountOverridden)
            {
                transaction.PrepaymentAmountRequired = transaction.PrepaymentAmountPaid;
            }

            // Amount that has been previously invoiced (picked-up)
            transaction.PreviouslyInvoicedAmount = orderInfo.PreviouslyInvoicedAmount;

            // Portion of the prepayment that has been applied to invoices.
            // If .PrepaymentAmountApplied is non-NULL then use the explicit amount, otherwise fall back to computing the amount based on payment history.
            transaction.PrepaymentAmountInvoiced = orderInfo.PrepaymentAmountApplied
                                                   ?? (transaction.PreviouslyInvoicedAmount - nonPrepayments);

            transaction.HasLoyaltyPayment = orderInfo.HasLoyaltyPayment;

            return(transaction);
        }
Beispiel #4
0
            /// <summary>
            /// Initiates a catalog publishing.
            /// </summary>
            /// <param name="catalogPublisher">Instance of the object which implements ICatalogPublisher.</param>
            /// <returns>True if changed products were found in CRT, False otherwise.</returns>
            /// <remarks>Retrieves the channel's catalogs from CRT and then checks whether CRT contains changed products for each of the catalogs. If changed products are found then
            /// ICatalogPublisher's callbacks are executed to let the caller's code process changed products.</remarks>
            public bool PublishCatalog(ICatalogPublisher catalogPublisher)
            {
                if (catalogPublisher == null)
                {
                    throw new ArgumentNullException(nameof(catalogPublisher));
                }

                List <long> productCatalogIds = new List <long>(1);

                // If catalogs were published to this channel, a given product will be published into SP for each catalog
                // in which it appears, so catalogless publishing would not yield different results for those products.
                // If, however, a product was published directly from the assortment, that product will only be detected
                // and published to SP if the ForceCataloglessPublishing flag is set to 'true' (1) in the job configuration file.
                // The semantics of forcing catalogless publishing as strict, in that catalog-less products will be published
                // if and only if the flag is set. That means, for instance, that if the flag is not set and there are no
                // catalogs published to this channel, the SP job will not detect/publish any products to SP.
                if (this.publishingConfig.ForceNoCatalogPublishing)
                {
                    NetTracer.Information(Resources.ProductCatalogToPublish, 0, "unspecified", "(not a proper catalog)");
                    productCatalogIds.Add(0);
                }

                IReadOnlyCollection <ProductCatalog> productCatalogs = this.GetCatalogs();

                bool deletesFound = this.DeleteProducts(productCatalogs, catalogPublisher);

                foreach (ProductCatalog productCatalog in productCatalogs)
                {
                    productCatalogIds.Add(productCatalog.RecordId);
                }

                ChangedProductsSearchCriteria searchCriteria = new ChangedProductsSearchCriteria
                {
                    DataLevel = CommerceEntityDataLevel.Complete
                };

                searchCriteria.Context.ChannelId = this.onlineChannel.RecordId;

                bool isInitialSync;

                QueryResultSettings productsQuerySettings = this.CreateGetListingsCriteria(
                    this.onlineChannel.ChannelProperties,
                    searchCriteria,
                    out isInitialSync);

                bool changesFound = false;

                try
                {
                    Stopwatch readChangedProductsWatch = Stopwatch.StartNew();
                    searchCriteria.Session = this.productManager.BeginReadChangedProducts(searchCriteria);
                    readChangedProductsWatch.Stop();
                    this.LogTimingMessage(Resources.Duration_ReadChangedProducts, readChangedProductsWatch.Elapsed, searchCriteria.Session.TotalNumberOfProducts);

                    if (searchCriteria.Session.TotalNumberOfProducts > 0)
                    {
                        changesFound = true;
                        int totalProductsCount = 0;

                        Stopwatch timerCummulativeListingRetrieval = new Stopwatch();

                        // loop through the product catalogs, retrieving products.
                        foreach (long productCatalogId in productCatalogIds)
                        {
                            NetTracer.Information(Resources.StartReadProductsFromCatalog, productCatalogId);

                            // set the catalog id on the search criteria
                            searchCriteria.Context.CatalogId = productCatalogId;
                            searchCriteria.Session.ResetNumberOfProductsRead();

                            int pageNumberForCatalog = 0;
                            int catalogProductsCount = 0;

                            // inner loop: load changes, page by page, up to catalog max size
                            do
                            {
                                timerCummulativeListingRetrieval.Start();
                                ChangedProductsSearchResult getProductsResults = this.LoadChangedProducts(searchCriteria, productsQuerySettings);
                                timerCummulativeListingRetrieval.Stop();

                                int numberOfReadProducts = getProductsResults.Results.Count;
                                totalProductsCount   += numberOfReadProducts;
                                catalogProductsCount += numberOfReadProducts;
                                this.LogTimingMessage(Resources.NumberOfReadProductsInPageSummary, productCatalogId, catalogProductsCount, totalProductsCount, timerCummulativeListingRetrieval.Elapsed);

                                catalogPublisher.OnChangedProductsFound(getProductsResults, pageNumberForCatalog, productCatalogId);
                                pageNumberForCatalog++;
                            }while (searchCriteria.Session.NumberOfProductsRead < searchCriteria.Session.TotalNumberOfProducts);

                            this.LogTimingMessage(Resources.CatalogReadCompleted, productCatalogId, catalogProductsCount, totalProductsCount, timerCummulativeListingRetrieval.Elapsed);

                            catalogPublisher.OnCatalogReadCompleted(productCatalogId, this);
                        }   // for each product catalog

                        this.LogTimingMessage(Resources.AllCatalogsReadCompleted, totalProductsCount, timerCummulativeListingRetrieval.Elapsed);
                    } // if changed products were found
                }
                finally
                {
                    this.productManager.EndReadChangedProducts(searchCriteria.Session);
                }

                ChannelProperty channelProperty = new ChannelProperty
                {
                    Name  = KeySyncAnchor,
                    Value = new string(searchCriteria.Session.NextSynchronizationToken)
                };

                this.channelManager.UpdateChannelProperties(new ChannelProperty[] { channelProperty });

                return(changesFound || deletesFound);
            }
Beispiel #5
0
            /// <summary>
            /// Initiates a channel publishing process.
            /// </summary>
            /// <param name="channelPublisher">Instance of the object which implements IChannelPublisher.</param>
            /// <returns>Return publishing parameters.</returns>
            /// <remarks>Retrieves the channel info from the CRT, then executes callbacks for the supplied IChannelPublisher and finally updates the channel publishing status in CRT/AX.</remarks>
            public PublishingParameters PublishChannel(IChannelPublisher channelPublisher)
            {
                if (channelPublisher == null)
                {
                    throw new ArgumentNullException(nameof(channelPublisher));
                }

                if (this.onlineChannel.PublishStatus != OnlineChannelPublishStatusType.Published &&
                    this.onlineChannel.PublishStatus != OnlineChannelPublishStatusType.InProgress)
                {
                    throw new ChannelNotPublishedException(Resources.ErrorChannelNotInPublishedState, this.onlineChannel.PublishStatus, this.onlineChannel.PublishStatusMessage);
                }

                IEnumerable <Category> categories;
                Dictionary <long, IEnumerable <AttributeCategory> > categoriesAttributes;

                // always load the categories but process them only if the channel is not published yet.
                try
                {
                    this.LoadCategories(out categories, out categoriesAttributes);
                    int categoriesCount = categories.Count();
                    NetTracer.Information(Resources.NumberOfReadCategoriesAndTheirAttributes, categoriesCount, categoriesAttributes.Count());
                    if (categoriesCount == 0)
                    {
                        throw new InvalidDataException(string.Format(
                                                           "Navigation categories count returned is '{0}'. Error details {1}",
                                                           categoriesCount,
                                                           Resources.ErrorNoNavigationCategories));
                    }

                    // Loading product attributes schema from CRT
                    IEnumerable <AttributeProduct> productAttributes = this.LoadProductAttributes();
                    channelPublisher.OnValidateProductAttributes(productAttributes);

                    int listingAttributesCount = productAttributes.Count();
                    NetTracer.Information(Resources.NumberOfReadAttributes, listingAttributesCount);
                    if (listingAttributesCount == 0)
                    {
                        throw new InvalidDataException(string.Format(
                                                           "Listing Attributes Count returned is '{0}'. Error details '{1}'",
                                                           listingAttributesCount,
                                                           Resources.ErrorNoSchemaAttributes));
                    }

                    ChannelLanguage language = this.onlineChannel.ChannelLanguages.Single(l => l.IsDefault);
                    CultureInfo     culture  = new CultureInfo(language.LanguageId);

                    PublishingParameters parameters = new PublishingParameters
                    {
                        Categories            = categories,
                        CategoriesAttributes  = categoriesAttributes,
                        ProductsAttributes    = productAttributes,
                        ChannelDefaultCulture = culture,
                        GiftCartItemId        = this.channelManager.GetChannelConfiguration().GiftCardItemId
                    };

                    if (this.onlineChannel.PublishStatus == OnlineChannelPublishStatusType.InProgress)
                    {
                        channelPublisher.OnChannelInformationAvailable(parameters, true);
                        this.channelManager.UpdateOnlineChannelPublishStatus(OnlineChannelPublishStatusType.Published, null);
                    }
                    else
                    {
                        channelPublisher.OnChannelInformationAvailable(parameters, false);
                    }

                    return(parameters);
                }
                catch (Exception ex)
                {
                    RetailLogger.Log.EcommercePlatformChannelPublishFailure(ex);
                    string error = string.Format(CultureInfo.InvariantCulture, Resources.ErrorChannelPublishingFailed, ex.Message, DateTime.Now);
                    this.channelManager.UpdateOnlineChannelPublishStatus(OnlineChannelPublishStatusType.Failed, error);
                    throw;
                }
            }
Beispiel #6
0
 void ReaderController.ReaderStateChangedListener.onGetKsnCompleted(string ksn)
 {
     NetTracer.Information(string.Format("The Ksn is completed with device info: {0}", ksn));
 }
Beispiel #7
0
        /// <summary>
        /// Closes the current shift and print it as Z-Report.
        /// </summary>
        /// <param name="transaction">The current transaction instance.</param>
        public void CloseShift(IPosTransaction transaction)
        {
            if (transaction == null)
            {
                NetTracer.Warning("transaction parameter is null");
                throw new ArgumentNullException("transaction");
            }

            Batch batch = null;

            // Are you sure you want to close the shift ?
            if (this.Application.Services.Dialog.ShowMessage(51302, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                batch = new Batch(transaction.Shift);

                // Verify if all offline transacitons has been uploaded.
                if (!batch.VerifyOfflineTransactions())
                {
                    batch = null;
                    this.Application.Services.Dialog.ShowMessage(51341);
                }
            }

            // Calculate and verify amounts.
            if (batch != null)
            {
                // Calculate batch in background
                POSFormsManager.ShowPOSMessageWithBackgroundWorker(51303, delegate { batch.Calculate(); });

                Action <decimal, int, int> verifyAmount = delegate(decimal amount, int errorMsg, int warningMsg)
                {
                    if (amount == 0)
                    {
                        // Warning or error based on configration in HQ.
                        if ((Functions.RequireAmountDeclaration &&
                             this.Application.Services.Dialog.ShowMessage(errorMsg, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) == DialogResult.OK) ||
                            (this.Application.Services.Dialog.ShowMessage(warningMsg, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No))
                        {
                            batch = null;
                        }
                    }
                };

                // Verify starting amounts.
                if (batch != null)
                {
                    verifyAmount(batch.StartingAmountTotal, 51344, 51343);
                }

                // Verify tender delcartion.
                if (batch != null)
                {
                    verifyAmount(batch.DeclareTenderAmountTotal, 51346, 51345);
                }
            }

            // Close the batch and Print Z report if everything is ok.
            if (batch != null)
            {
                batch.Status           = PosBatchStatus.Closed;
                batch.CloseDateTime    = DateTime.Now;
                batch.ClosedAtTerminal = ApplicationSettings.Terminal.TerminalId;

                BatchData batchData = new BatchData(Application.Settings.Database.Connection, Application.Settings.Database.DataAreaID);
                batchData.CloseBatch(batch);
                transaction.Shift.Status = PosBatchStatus.Closed;
                ShiftUsersCache.Remove(transaction.Shift);

                // Print Z report if user has permissions.
                IUserAccessSystem userAccessSystem = Application.BusinessLogic.UserAccessSystem;

                if (userAccessSystem.UserHasAccess(ApplicationSettings.Terminal.TerminalOperator.OperatorId, PosisOperations.PrintZ))
                {
                    POSFormsManager.ShowPOSMessageWithBackgroundWorker(99, delegate { batch.Print(ReportType.ZReport); });
                }

                this.Application.Services.Dialog.ShowMessage(51342); // Operation complete
            }
            else
            {
                NetTracer.Information("Setting status of the transaction to 'cancelled'");
                ((PosTransaction)transaction).EntryStatus = PosTransaction.TransactionStatus.Cancelled;
            }
        }
        public decimal FindTenderRestriction(IRetailTransaction retailTransaction, ICardInfo cardInfo)
        {
            NetTracer.Information("TenderRestriction::FindTenderRestriction - Start");
            RetailTransaction transaction = retailTransaction as RetailTransaction;

            if (transaction == null)
            {
                throw new ArgumentNullException("retailTransaction");
            }

            if (cardInfo == null)
            {
                throw new ArgumentNullException("cardInfo");
            }

            decimal    payableAmount = 0; //the return value of total amount payd with tender id
            ItemStatus itemStatus;        //is the item included / excluded by the tender id

            // Check if there are items in the transaction
            if (transaction.SaleItems.Count == 0)
            {
                POSFormsManager.ShowPOSMessageDialog(50251); //"There are no sales items to check."
                return(payableAmount);
            }

            // Calclulating how much amount of the original amount can be paid.
            foreach (ISaleLineItem lineItem in transaction.SaleItems)
            {
                if (string.IsNullOrEmpty(lineItem.TenderRestrictionId) && (!lineItem.Voided))
                {
                    itemStatus = CheckTenderRestriction(cardInfo.RestrictionCode, cardInfo.TenderTypeId, lineItem.ItemId, lineItem.ItemGroupId);

                    if (itemStatus == ItemStatus.INCLUDE)
                    {
                        lineItem.TenderRestrictionId = cardInfo.RestrictionCode;
                        lineItem.FleetCardNumber     = cardInfo.CardNumber;
                        lineItem.PaymentIndex        = transaction.TenderLines.Count;
                        payableAmount += lineItem.NetAmountWithTax;
                    }
                }
            }

            if (payableAmount != retailTransaction.NetAmountWithTax)
            {
                // If nothing can be paid, then it can be concluded that this card is prohibited
                if (payableAmount == 0)
                {
                    using (LSRetailPosis.POSProcesses.frmMessage dialog = new LSRetailPosis.POSProcesses.frmMessage(50253))
                    {
                        this.Application.ApplicationFramework.POSShowForm(dialog);
                    }
                }
                else
                {
                    string message = string.Format(
                        LSRetailPosis.ApplicationLocalizer.Language.Translate(50151),
                        this.Application.Services.Rounding.Round(payableAmount, false));

                    using (frmTenderRestriction frmExcluded = new frmTenderRestriction(transaction))
                    {
                        frmExcluded.DisplayMsg = message;
                        this.Application.ApplicationFramework.POSShowForm(frmExcluded);

                        if (frmExcluded.DialogResult == DialogResult.No)
                        {
                            ClearTenderRestriction(retailTransaction);
                            return(0);
                        }
                    }
                }
            }

            NetTracer.Information("TenderRestriction::FindTenderRestriction - End");
            return(payableAmount);
        }
            private void FPE_ReceivedVariableValue(string strVariableName, string strVariableValue)
            {
                // NOTE: Can not read or set variables in this event handler.  Device API does not support
                switch (strVariableName)
                {
                case "cnum":
                    // This is for Credit Card Number - as we don't need value disregard result.
                    break;

                case "Track1Data":
                    this.track1 = strVariableValue;
                    break;

                case "Track2Data":
                    // Get previous event data sent and then clear them out
                    var swipeArgs = new CardSwipeEventArgs {
                        Track1 = this.track1, Track2 = strVariableValue, Track3 = string.Empty
                    };
                    this.CardSwipeEvent(this, swipeArgs);
                    break;

                case "RetailCardType":
                    var typeArgs = new ButtonPressEventArgs();
                    typeArgs.ButtonName = strVariableValue;
                    typeArgs.IsCanceled = false;
                    this.ButtonPressEvent(this, typeArgs);
                    break;

                case "CashBackAmt":
                case "AmountOk":
                    var cashBackArgs = new ButtonPressEventArgs();
                    cashBackArgs.ButtonName = strVariableValue;
                    cashBackArgs.IsCanceled = false;
                    this.ButtonPressEvent(this, cashBackArgs);
                    break;

                case "AdditionalSecurityInformation":
                    this.additionalSecInfo = strVariableValue;
                    break;

                case "EncryptedPIN":
                    PinDataEventArgs pinArg = new PinDataEventArgs();
                    pinArg.IsCanceled         = false;
                    pinArg.EncryptedPin       = strVariableValue;
                    pinArg.AdditionalSecurity = this.additionalSecInfo;
                    this.PinDataEvent(this, pinArg);
                    this.additionalSecInfo = string.Empty;
                    break;

                case "PinPadEntry":
                    // PIN entry "Cancel" or "TMO"
                    // PIN entry "Request" is set upon form entry (but no fire event)
                    PinDataEventArgs pinPadArg = new PinDataEventArgs();
                    pinPadArg.IsCanceled         = true;
                    pinPadArg.EncryptedPin       = string.Empty;
                    pinPadArg.AdditionalSecurity = string.Empty;
                    this.PinDataEvent(this, pinPadArg);
                    break;

                case "sig":
                    string signature           = string.Empty;
                    HydraSignatureEnhanced sig = new HydraSignatureEnhanced(Convert.FromBase64String(strVariableValue));
                    signature = Convert.ToBase64String(sig.ToByteArray());

                    SignatureEventArgs sigArgs = new SignatureEventArgs()
                    {
                        SignatureData = signature
                    };
                    this.SignatureEvent(this, sigArgs);
                    break;

                default:
                    NetTracer.Information("L5300Terminal variable {0} not set to {1}", strVariableName, strVariableValue);
                    break;
                }
            }
Beispiel #10
0
        protected virtual ReadOnlyCollection <TaxCode> GetTaxCodes(ITaxableItem taxableItem)
        {
            if (taxableItem == null)
            {
                throw new ArgumentNullException("taxableItem");
            }

            RetailTransaction transaction = (RetailTransaction)taxableItem.RetailTransaction;
            string            customerId  = string.Empty;

            // If the line has an EndDate specified (usually because it's a Returned line),
            // then use that value to calculate taxes, otherwise use BeginDate
            DateTime itemSaleDateTime = (taxableItem.EndDateTime <= NoDate) ? taxableItem.BeginDateTime : taxableItem.EndDateTime;

            if (transaction != null && transaction.Customer != null)
            {
                customerId = transaction.Customer.CustomerId;
            }

            CacheKey cacheKey = new CacheKey(taxableItem.ItemId,
                                             customerId,
                                             taxableItem.TaxGroupId,
                                             taxableItem.SalesTaxGroupId,
                                             itemSaleDateTime);

            if (taxCodeCache.ContainsKey(cacheKey))
            {
                List <TaxCode> taxCodes = taxCodeCache[cacheKey];

                // Update the lineItem object in cached Taxcode object (Everytime we get new SalesLine Object)
                taxCodes.ForEach(t => t.LineItem = taxableItem);

                return(SortCodes(taxCodes));
            }

            NetTracer.Information("TaxCodeProvider::GetTaxCodes(): Quering database.");

            SqlConnection connection = Application.Settings.Database.Connection;
            string        dataAreaId = Application.Settings.Database.DataAreaID;

            try
            {
                Dictionary <string, TaxCode> codes = new Dictionary <string, TaxCode>();

                bool useDefaultTaxGroups = (cacheKey.TaxGroupID == null) || (cacheKey.SalesTaxGroupID == null);

                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;

                    string sb = string.Format(@"SELECT DISTINCT {0}    FROM TAXGROUPHEADING  ", TaxSelectSqlText);

                    if (useDefaultTaxGroups)
                    {
                        // #1 Look in the DB for the default Customer/Store tax group mapping
                        if (String.IsNullOrWhiteSpace(cacheKey.CustomerID))
                        {
                            sb += @"INNER JOIN RETAILSTORETABLE ON 
                                TAXGROUPHEADING.TAXGROUP = RETAILSTORETABLE.TAXGROUP 
                                AND  RETAILSTORETABLE.STORENUMBER = @STOREID ";

                            command.Parameters.AddWithValue("@STOREID", ApplicationSettings.Terminal.StoreId);
                        }
                        else
                        {
                            sb += @"INNER JOIN CUSTTABLE ON 
                                TAXGROUPHEADING.TAXGROUP = CUSTTABLE.TAXGROUP 
                                AND CUSTTABLE.DATAAREAID = @DATAAREAID 
                                AND CUSTTABLE.ACCOUNTNUM = @CUSTOMERID ";

                            command.Parameters.AddWithValue("@CUSTOMERID", cacheKey.CustomerID);
                        }
                    }

                    sb += @"INNER JOIN TAXGROUPDATA ON 
                        TAXGROUPDATA.DATAAREAID = @DATAAREAID 
                        AND TAXGROUPHEADING.TAXGROUP = TAXGROUPDATA.TAXGROUP 

                        INNER JOIN TAXONITEM ON 
                        TAXONITEM.DATAAREAID = @DATAAREAID 
                        AND TAXGROUPDATA.TAXCODE = TAXONITEM.TAXCODE  ";

                    if (useDefaultTaxGroups)
                    {
                        // Join against the Item's default Item tax group
                        sb += @"INNER JOIN INVENTTABLEMODULE ON 
                            INVENTTABLEMODULE.DATAAREAID = @DATAAREAID 
                            AND INVENTTABLEMODULE.TAXITEMGROUPID = TAXONITEM.TAXITEMGROUP  ";
                    }

                    sb += @"INNER JOIN TAXDATA ON 
                        TAXDATA.DATAAREAID = @DATAAREAID 
                        AND TAXONITEM.TAXCODE = TAXDATA.TAXCODE 

                        INNER JOIN TAXTABLE ON 
                        TAXTABLE.DATAAREAID = @DATAAREAID 
                        AND TAXTABLE.TAXCODE = TAXDATA.TAXCODE 

                        LEFT JOIN TAXCOLLECTLIMIT ON 
                        TAXCOLLECTLIMIT.DATAAREAID = @DATAAREAID 
                        AND TAXCOLLECTLIMIT.TAXCODE = TAXDATA.TAXCODE 
                        AND (TAXCOLLECTLIMIT.TAXFROMDATE IS NULL 
                        OR @TRANSACTIONDATE >= TAXCOLLECTLIMIT.TAXFROMDATE 
                        OR TAXCOLLECTLIMIT.TAXFROMDATE < @NODATEBOUNDRY ) 
                        AND (TAXCOLLECTLIMIT.TAXTODATE IS NULL 
                        OR @TRANSACTIONDATE < DATEADD(d, 1, TAXCOLLECTLIMIT.TAXTODATE) 
                        OR TAXCOLLECTLIMIT.TAXTODATE < @NODATEBOUNDRY) 

                        WHERE (TAXGROUPHEADING.DATAAREAID = @DATAAREAID)  ";

                    command.Parameters.AddWithValue("@DATAAREAID", dataAreaId);

                    if (useDefaultTaxGroups)
                    {
                        sb += @"AND (INVENTTABLEMODULE.ITEMID = @ITEMID) 
                            AND (INVENTTABLEMODULE.MODULETYPE = @MODULETYPE)  ";

                        command.Parameters.AddWithValue("@ITEMID", cacheKey.ItemID);
                        command.Parameters.AddWithValue("@MODULETYPE", (int)ModuleType.Sales);
                    }
                    else
                    {
                        // Filter against the item's current Item Tax Group and Customer/Store tax group
                        sb += @"AND TAXONITEM.TAXITEMGROUP = @ITEMTAXGROUP 
                            AND TAXGROUPHEADING.TAXGROUP = @SALESTAXGROUP  ";

                        command.Parameters.AddWithValue("@SALESTAXGROUP", cacheKey.SalesTaxGroupID ?? string.Empty);
                        command.Parameters.AddWithValue("@ITEMTAXGROUP", cacheKey.TaxGroupID ?? string.Empty);
                    }

                    // Currently only evaluate taxes against the current time.
                    // Note that the date value of '1900-01-01 00:00.000' is the marker for "no boundry".
                    sb += @"AND 
                        ((@TRANSACTIONDATE >= TAXDATA.TAXFROMDATE OR TAXDATA.TAXFROMDATE < @NODATEBOUNDRY ) 
                        AND (@TRANSACTIONDATE < DATEADD(d, 1, TAXDATA.TAXTODATE) OR TAXDATA.TAXTODATE < @NODATEBOUNDRY)) ";

                    command.Parameters.AddWithValue("@NODATEBOUNDRY", NoDate);
                    command.Parameters.AddWithValue("@TRANSACTIONDATE", cacheKey.SaleDateTime);

                    sb += AddTaxSelectSqlCondition(command);

                    command.CommandText = sb.ToString();

                    if (connection.State != ConnectionState.Open)
                    {
                        connection.Open();
                    }

                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        string taxCodeKey = string.Empty;

                        while (reader.Read())
                        {
                            taxCodeKey = reader["TAXCODE"] as string;

                            if (codes.ContainsKey(taxCodeKey))
                            {
                                // Add a new 'value' entry for an existing tax code
                                codes[taxCodeKey].TaxIntervals.Add(
                                    new TaxInterval(
                                        (decimal)reader["TAXLIMITMIN"],
                                        (decimal)reader["TAXLIMITMAX"],
                                        (decimal)reader["TAXVALUE"]));
                            }
                            else
                            {
                                AddTaxCode(cacheKey, reader, taxableItem, codes);
                            }
                        }
                    }
                }

                // Link any taxes which rely on other taxes
                foreach (TaxCode tax in codes.Values)
                {
                    if (!string.IsNullOrEmpty(tax.TaxOnTax) &&
                        (tax.TaxBase == TaxBase.PercentPerTax || tax.TaxBase == TaxBase.PercentPerGross) &&
                        codes.Keys.Contains(tax.TaxOnTax))
                    {
                        tax.TaxOnTaxInstance = codes[tax.TaxOnTax] as TaxCode;
                    }
                }

                return(SortCodes(codes.Values));
            }
            catch (Exception ex)
            {
                NetTracer.Error(ex, "GetTaxCodes() failed in an Exception");
                throw;
            }
            finally
            {
                if (connection.State == ConnectionState.Open)
                {
                    connection.Close();
                }
            }
        }
        /// <summary>
        /// Updates the result list.
        /// </summary>
        /// <param name="fromRow">From row.</param>
        private void UpdateResultList(int fromRow)
        {
            NetTracer.Information("SearchViewModel : UpdateResultList : Start");

            if (fromRow == 0)
            {
                this.result.Clear();
                ExecuteSelect(null);
            }

            if (isLastRowLoaded ||
                this.SearchTerms.Length < MinimumSearchTermLengh)
            {
                return;
            }

            SqlConnection connection = ApplicationSettings.Database.LocalConnection;

            try
            {
                using (SqlCommand command = new SqlCommand())
                {
                    if (SearchType == SearchType.Category)
                    {
                        GetCategoryQuery(command);

                        // Cagegory mode automatically switchs to items when executed.
                        this.SearchType = SearchType.Item;
                    }
                    else
                    {
                        GetDefaultQuery(command);
                    }

                    command.Connection = connection;
                    command.Parameters.AddWithValue("@FROMROW", fromRow);
                    command.Parameters.AddWithValue("@TOROW", (fromRow + PAGE_SIZE));

                    if (connection.State != ConnectionState.Open)
                    {
                        connection.Open();
                    }

                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            this.result.Add(new ResultRow(reader));
                        }
                    }
                }
            }
            finally
            {
                if (connection.State == ConnectionState.Open)
                {
                    connection.Close();
                }
            }


            // If we didn't get back a full page of results then we loaded everything
            if (this.result.Count % PAGE_SIZE > 0)
            {
                isLastRowLoaded = true;
            }

            // Get the price of the items if enabled.
            if (ItemPriceVisible)
            {
                CalculatePrice();
            }

            OnPropertyChanged("Results");

            NetTracer.Information("SearchViewModel : UpdateResultList : End");
        }
Beispiel #12
0
            /// <summary>
            /// Get transactions using the request criteria.
            /// </summary>
            /// <param name="request">Request containing the criteria used to retrieve transactions.</param>
            /// <returns>SearchJournalTransactionsServiceResponse object.</returns>
            private static SearchJournalTransactionsServiceResponse SearchJournalTransactions(SearchJournalTransactionsServiceRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.Null(request.QueryResultSettings, "request.QueryResultSettings");

                NetTracer.Information("TransactionService.SearchJournalTransactions()");

                if (request.QueryResultSettings.Sorting == null)
                {
                    request.QueryResultSettings.Sorting = new SortingInfo();
                }

                if (!request.QueryResultSettings.Sorting.IsSpecified)
                {
                    request.QueryResultSettings.Sorting.Add(new SortColumn(RetailTransactionTableSchema.CreatedDateTimeColumn, isDescending: true));
                    request.QueryResultSettings.Sorting.Add(new SortColumn(RetailTransactionTableSchema.BeginDateTimeColumn, isDescending: true));
                }

                if (request.Criteria.SearchLocationType == SearchLocation.Local)
                {
                    // Search local only.
                    PagedResult <Transaction> results = SearchJournalTransactionsLocally(request.Criteria, request.QueryResultSettings, request.RequestContext);

                    return(new SearchJournalTransactionsServiceResponse(results));
                }
                else if (request.Criteria.SearchLocationType == SearchLocation.Remote)
                {
                    // Search remote only.
                    PagedResult <Transaction> results = SearchJournalTransactionsRemotely(request.Criteria, request.QueryResultSettings, request.RequestContext);

                    return(new SearchJournalTransactionsServiceResponse(results));
                }
                else
                {
                    // Search all.
                    // Adjust the paging.
                    QueryResultSettings settings       = request.QueryResultSettings;
                    PagingInfo          adjustedPaging = MultiDataSourcesPagingHelper.GetAdjustedPaging(settings.Paging);
                    QueryResultSettings adjustedQueryResultSettings = new QueryResultSettings(settings.ColumnSet, adjustedPaging, settings.Sorting, settings.ChangeTracking);

                    // Get local results.
                    IEnumerable <Transaction> localTransactions = SearchJournalTransactionsLocally(request.Criteria, adjustedQueryResultSettings, request.RequestContext).Results;

                    // Getremote results.
                    IEnumerable <Transaction> remoteTransactions = Enumerable.Empty <Transaction>();
                    try
                    {
                        remoteTransactions = SearchJournalTransactionsRemotely(request.Criteria, adjustedQueryResultSettings, request.RequestContext).Results;
                    }
                    catch (Exception e)
                    {
                        // Eats the exception since search remote is optional and log the error details as a warning.
                        RetailLogger.Log.CrtServicesStoreOperationServiceServiceRemoteTransactionSearchFailed(e);
                    }

                    // Merge results.
                    IEnumerable <Transaction> mergedTransactions = MultiDataSourcesPagingHelper.MergeResults(
                        remoteTransactions,
                        localTransactions,
                        GetTransactionMergingKey);

                    // Sorts merged transactions.
                    PagedResult <Transaction> mergedResults = MultiDataSourcesPagingHelper.GetPagedResult(mergedTransactions, settings.Paging, settings.Sorting);
                    return(new SearchJournalTransactionsServiceResponse(mergedResults));
                }
            }