/// <summary>
            /// Gets the tender detail object from the client.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="tenderDetail">The tender detail object from client.</param>
            /// <returns>The tender detail object to be saved on channel database.</returns>
            internal static TenderDetail ConvertToTenderDetail(RequestContext context, TenderDetail tenderDetail)
            {
                var tender = new TenderDetail
                {
                    BankBagNumber = tenderDetail.BankBagNumber, // bankbag number
                    TenderTypeId  = tenderDetail.TenderTypeId,  // tender type identifier
                    Amount        = tenderDetail.Amount         // amount in channel currency
                };

                string channelCurrency = context.GetChannelConfiguration().Currency;
                string foreignCurrency = string.IsNullOrWhiteSpace(tenderDetail.ForeignCurrency) ? channelCurrency : tenderDetail.ForeignCurrency;

                // Check if the foreign currency of the transaction is in channel currency
                if (foreignCurrency.Equals(channelCurrency, StringComparison.OrdinalIgnoreCase))
                {
                    tender.ForeignCurrency             = channelCurrency;     // foreign currency code is same as store currency code
                    tender.AmountInForeignCurrency     = tenderDetail.Amount; // foreign amount is same as store amount
                    tender.ForeignCurrencyExchangeRate = 1m;                  // foreign to channel currency exchange rate is 1
                }
                else
                {
                    tender.ForeignCurrency             = foreignCurrency;                           // foreign currency code
                    tender.AmountInForeignCurrency     = tenderDetail.AmountInForeignCurrency;      // foreign amount
                    tender.ForeignCurrencyExchangeRate = tenderDetail.ForeignCurrencyExchangeRate;  // foreign to channel currency exchange rate
                }

                // Retrieve the amount in company currency with the exchange rate between foreign and company currency
                Tuple <decimal, decimal> companyCurrencyValues = StoreOperationServiceHelper.GetCompanyCurrencyValues(context, tender.AmountInForeignCurrency, tender.ForeignCurrency);

                tender.AmountInCompanyCurrency     = companyCurrencyValues.Item1;   // amount MST
                tender.CompanyCurrencyExchangeRate = companyCurrencyValues.Item2;   // exchange rate MST

                return(tender);
            }
Exemple #2
0
            /// <summary>
            /// Invoke the method to get non sale tender transaction list for the given non sale tender type.
            /// </summary>
            /// <param name="request">Request for non sale tender service.</param>
            /// <returns>Returns the response for non sale tender operation get request.</returns>
            private static GetNonSaleTenderServiceResponse GetNonSaleTenderTransactions(GetNonSaleTenderServiceRequest request)
            {
                NonSalesTransaction tenderTransaction = StoreOperationServiceHelper.ConvertToNonSalesTenderTransaction(request.RequestContext, request.ShiftId, request.ShiftTerminalId, request.TransactionType);
                var getCurrentShiftNonSalesTransactionsdataServiceRequest = new GetCurrentShiftNonSalesTransactionsDataRequest(tenderTransaction, request.TransactionId);

                PagedResult <NonSalesTransaction> nonSaleOperationList = request.RequestContext.Runtime.Execute <EntityDataServiceResponse <NonSalesTransaction> >(getCurrentShiftNonSalesTransactionsdataServiceRequest, request.RequestContext).PagedEntityCollection;

                return(new GetNonSaleTenderServiceResponse(nonSaleOperationList));
            }
            /// <summary>
            /// Gets the object of non sales tender operation.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="shiftId">The shift identifier.</param>
            /// <param name="shiftTerminalId">The shift terminal identifier.</param>
            /// <param name="tenderType">The non sale tender type.</param>
            /// <returns>The non sales tender operation object.</returns>
            internal static NonSalesTransaction ConvertToNonSalesTenderTransaction(RequestContext context, string shiftId, string shiftTerminalId, TransactionType tenderType)
            {
                var transaction = new NonSalesTransaction
                {
                    ShiftId         = shiftId,
                    TransactionType = tenderType,
                    TenderTypeId    = StoreOperationServiceHelper.GetCashTenderTypeIdentifier(context), // Default it to cash.
                    StoreId         = context.GetOrgUnit().OrgUnitNumber,
                    StaffId         = context.GetPrincipal().UserId,
                    TerminalId      = context.GetTerminal().TerminalId,
                    ShiftTerminalId = string.IsNullOrWhiteSpace(shiftTerminalId) ? context.GetPrincipal().ShiftTerminalId : shiftTerminalId
                };

                return(transaction);
            }
            /// <summary>
            /// Validates the counting difference for tender declaration operation.
            /// </summary>
            /// <param name="request">Drop and declare service request.</param>
            internal static void ValidateTenderDeclarationCountingDifference(SaveDropAndDeclareServiceRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.NullOrWhiteSpace(request.ShiftId, "request.ShiftId");

                if (request.TransactionType == TransactionType.TenderDeclaration)
                {
                    // Retrieves the tender types info
                    Dictionary <string, TenderType> tenderTypeDict = StoreOperationServiceHelper.GetChannelTenderTypes(request.RequestContext);

                    // Check if tender declaration recount is needed
                    bool isRecountNeeded = request.TenderDetails.All(t => tenderTypeDict.ContainsKey(t.TenderTypeId)) && request.TenderDetails.Any(t => t.TenderRecount < tenderTypeDict[t.TenderTypeId].MaxRecount);

                    if (isRecountNeeded)
                    {
                        // Retrieves the expected shift tender amounts per tender type
                        Dictionary <string, ShiftTenderLine> expectedShiftTenderAmounts = StoreOperationServiceHelper.GetShiftRequiredAmountsPerTender(request.RequestContext, request.ShiftTerminalId, request.ShiftId);

                        // Validates the counting amount in tender declaration lines
                        foreach (TenderDetail declartionLine in request.TenderDetails)
                        {
                            string  tenderTypeId = declartionLine.TenderTypeId;
                            decimal countingDifferenceAllowed = tenderTypeDict[tenderTypeId].MaxCountingDifference;
                            decimal expectedShiftTenderAmount = expectedShiftTenderAmounts.ContainsKey(tenderTypeId) ? expectedShiftTenderAmounts[tenderTypeId].TenderedAmountOfStoreCurrency : 0M;
                            int     maxRecountAllowed         = tenderTypeDict[tenderTypeId].MaxRecount;
                            string  tenderName = tenderTypeDict[tenderTypeId].Name;

                            // Checks if current number of recount exceeds the permissible recount
                            if (declartionLine.TenderRecount < maxRecountAllowed)
                            {
                                // Checks if the difference between current tender delcartion amount with expected tender amounts
                                // exceeds the permissible counting difference for that tender type
                                if (Math.Abs(declartionLine.Amount - expectedShiftTenderAmount) > countingDifferenceAllowed)
                                {
                                    throw new TenderValidationException(
                                              tenderTypeId,
                                              DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_MaxCountingDifferenceExceeded,
                                              string.Format("The counted amount differs from the total sales amount for the {0} tender type.", tenderName))
                                          {
                                              LocalizedMessageParameters = new object[] { tenderName }
                                          };
                                }
                            }
                        }
                    }
                }
            }
Exemple #5
0
            /// <summary>
            /// Invoke the method to save non sale tender type transactions.
            /// </summary>
            /// <param name="request">Request for non sale tender transactions.</param>
            /// <returns>Returns the non sale tender transactions.</returns>
            private static SaveNonSaleTenderServiceResponse SaveNonSaleTenderTransactions(SaveNonSaleTenderServiceRequest request)
            {
                NonSalesTransaction nonSalesTransaction = StoreOperationServiceHelper.ConvertToNonSalesTenderTransaction(request.RequestContext, request);

                // If the previously created tender transaction response did not get received due to network connection issue.
                // On client retry, check if it was already saved. If true, returns saved object.
                var getCurrentShiftNonSalesTransactionsdataServiceRequest = new GetCurrentShiftNonSalesTransactionsDataRequest(nonSalesTransaction, request.TransactionId);
                NonSalesTransaction savedNonSalesTransaction = request.RequestContext.Runtime.Execute <EntityDataServiceResponse <NonSalesTransaction> >(getCurrentShiftNonSalesTransactionsdataServiceRequest, request.RequestContext).PagedEntityCollection.FirstOrDefault();

                if (savedNonSalesTransaction == null)
                {
                    var saveNonSalesTransactionsdataServiceRequest = new SaveNonSalesTransactionDataRequest(nonSalesTransaction);
                    savedNonSalesTransaction = request.RequestContext.Runtime.Execute <SingleEntityDataServiceResponse <NonSalesTransaction> >(saveNonSalesTransactionsdataServiceRequest, request.RequestContext).Entity;
                }

                return(new SaveNonSaleTenderServiceResponse(savedNonSalesTransaction));
            }
            /// <summary>
            /// Gets the object of non sales tender operation.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="nonSaleTenderServiceRequest">The non-sale shift tender operation request.</param>
            /// <returns>The non sales tender operation object.</returns>
            internal static NonSalesTransaction ConvertToNonSalesTenderTransaction(RequestContext context, SaveNonSaleTenderServiceRequest nonSaleTenderServiceRequest)
            {
                string channelCurrency = context.GetChannelConfiguration().Currency;
                var    transaction     = new NonSalesTransaction
                {
                    Id                          = nonSaleTenderServiceRequest.TransactionId,
                    ShiftId                     = nonSaleTenderServiceRequest.ShiftId,
                    ShiftTerminalId             = string.IsNullOrWhiteSpace(nonSaleTenderServiceRequest.ShiftTerminalId) ? context.GetPrincipal().ShiftTerminalId : nonSaleTenderServiceRequest.ShiftTerminalId,
                    Description                 = nonSaleTenderServiceRequest.Description,
                    TransactionType             = nonSaleTenderServiceRequest.TransactionType,
                    TenderTypeId                = StoreOperationServiceHelper.GetCashTenderTypeIdentifier(context), // Default it to cash.
                    StoreId                     = context.GetOrgUnit().OrgUnitNumber,
                    StaffId                     = context.GetPrincipal().UserId,
                    TerminalId                  = context.GetTerminal().TerminalId,
                    ChannelCurrencyExchangeRate = StoreOperationServiceHelper.GetExchangeRate(context),
                    Amount                      = nonSaleTenderServiceRequest.Amount,        // amount in store currency
                    ForeignCurrency             = string.IsNullOrWhiteSpace(nonSaleTenderServiceRequest.Currency) ? channelCurrency : nonSaleTenderServiceRequest.Currency,
                    ChannelCurrency             = context.GetChannelConfiguration().Currency // channel currency code
                };

                // Retrieve the amount in foreign currency with the exchange rate between foreign and channel currency
                Tuple <decimal, decimal> foreignCurrencyValues = StoreOperationServiceHelper.GetForeignCurrencyValues(context, transaction.Amount, transaction.ForeignCurrency);

                transaction.AmountInForeignCurrency     = foreignCurrencyValues.Item1;      // foreign currency amount
                transaction.ForeignCurrencyExchangeRate = foreignCurrencyValues.Item2;      // foreign currency exchange rate

                // Retrieve the amount in company currency with the exchange rate between foreign and company currency
                Tuple <decimal, decimal> companyCurrencyValues = StoreOperationServiceHelper.GetCompanyCurrencyValues(context, transaction.AmountInForeignCurrency, transaction.ForeignCurrency);

                transaction.AmountInCompanyCurrency     = companyCurrencyValues.Item1;  // amount MST
                transaction.CompanyCurrencyExchangeRate = companyCurrencyValues.Item2;  // exchange rate MST

                if (nonSaleTenderServiceRequest.ReasonCodeLines != null && nonSaleTenderServiceRequest.ReasonCodeLines.Any())
                {
                    // Read reason code details from service request for open drawer operation
                    transaction.ReasonCodeLines = new Collection <ReasonCodeLine>();
                    foreach (var reasonCodeLine in nonSaleTenderServiceRequest.ReasonCodeLines)
                    {
                        transaction.ReasonCodeLines.Add(reasonCodeLine);
                    }
                }

                return(transaction);
            }
            /// <summary>
            /// Gets the object of tender drop and declare operation.
            /// </summary>
            /// <param name="request">The SaveDropAndDeclareServiceRequest object.</param>
            /// <returns>The tender drop and declare operation object.</returns>
            internal static DropAndDeclareTransaction ConvertTenderDropAndDeclareTransaction(SaveDropAndDeclareServiceRequest request)
            {
                RequestContext context     = request.RequestContext;
                var            transaction = new DropAndDeclareTransaction
                {
                    Id                          = request.TransactionId,
                    ShiftId                     = request.ShiftId,
                    ShiftTerminalId             = string.IsNullOrWhiteSpace(request.ShiftTerminalId) ? context.GetPrincipal().ShiftTerminalId : request.ShiftTerminalId,
                    TransactionType             = request.TransactionType,
                    ChannelCurrencyExchangeRate = StoreOperationServiceHelper.GetExchangeRate(context),
                    StoreId                     = context.GetOrgUnit().OrgUnitNumber,
                    StaffId                     = context.GetPrincipal().UserId,
                    TerminalId                  = context.GetTerminal().TerminalId,
                    ChannelCurrency             = context.GetChannelConfiguration().Currency, // channel currency code
                    Description                 = request.Description
                };

                transaction.TenderDetails = new Collection <TenderDetail>();
                foreach (var tenderDetail in request.TenderDetails)
                {
                    TenderDetail tender = ConvertToTenderDetail(context, tenderDetail);
                    transaction.TenderDetails.Add(tender);
                }

                if (request.ReasonCodeLines != null && request.ReasonCodeLines.Any())
                {
                    // Read reason code details from request for [Tender Declaration] store operation
                    transaction.ReasonCodeLines = new Collection <ReasonCodeLine>();
                    foreach (var reasonCodeLine in request.ReasonCodeLines)
                    {
                        transaction.ReasonCodeLines.Add(reasonCodeLine);
                    }
                }

                return(transaction);
            }
Exemple #8
0
            /// <summary>
            /// Invoke the method to save drop and declare transactions.
            /// </summary>
            /// <param name="request">Request context.</param>
            /// <returns>Returns response for save drop and declare.</returns>
            private static SaveDropAndDeclareServiceResponse SaveDropAndDeclareTransactions(SaveDropAndDeclareServiceRequest request)
            {
                StoreOperationServiceHelper.ValidateTenderDeclarationCountingDifference(request);

                DropAndDeclareTransaction tenderDropAndDeclare = StoreOperationServiceHelper.ConvertTenderDropAndDeclareTransaction(request);

                // If the previously created drop transaction response did not get received due to network connection issue.
                // On client retry, check if it was already saved. If true, returns saved object.
                var getDropAndDeclareTransactionDataRequest = new GetDropAndDeclareTransactionDataRequest(tenderDropAndDeclare.Id, QueryResultSettings.SingleRecord);
                DropAndDeclareTransaction transaction       = request.RequestContext.Runtime.Execute <EntityDataServiceResponse <DropAndDeclareTransaction> >(getDropAndDeclareTransactionDataRequest, request.RequestContext).PagedEntityCollection.FirstOrDefault();

                if (transaction != null)
                {
                    var getDropAndDeclareTransactionTenderDetailsDataRequest = new GetDropAndDeclareTransactionTenderDetailsDataRequest(tenderDropAndDeclare.Id, QueryResultSettings.AllRecords);
                    transaction.TenderDetails = request.RequestContext.Runtime.Execute <EntityDataServiceResponse <TenderDetail> >(getDropAndDeclareTransactionTenderDetailsDataRequest, request.RequestContext).PagedEntityCollection.Results;
                }
                else
                {
                    var saveDropAndDeclareTransactionDataRequest = new SaveDropAndDeclareTransactionDataRequest(tenderDropAndDeclare);
                    transaction = request.RequestContext.Runtime.Execute <SingleEntityDataServiceResponse <DropAndDeclareTransaction> >(saveDropAndDeclareTransactionDataRequest, request.RequestContext).Entity;
                }

                return(new SaveDropAndDeclareServiceResponse(transaction));
            }