Esempio n. 1
0
            /// <summary>
            /// Validate customer account deposit transactions.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="salesTransaction">The sales transaction.</param>
            public static void ValidateCustomerAccountDepositTransaction(RequestContext context, SalesTransaction salesTransaction)
            {
                if (salesTransaction.TransactionType != SalesTransactionType.CustomerAccountDeposit && salesTransaction.CustomerAccountDepositLines.Any())
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountDepositLinesNotAllowed, "Customer account deposit lines should be present on the transaction.");
                }

                // Make sure it is a customer account deposit transaction before applying additional validation
                if (salesTransaction.TransactionType != SalesTransactionType.CustomerAccountDeposit)
                {
                    return;
                }

                if (salesTransaction.CustomerAccountDepositLines.Any())
                {
                    context.Execute <NullResponse>(new CheckAccessServiceRequest(RetailOperation.CustomerAccountDeposit));
                }

                // Validate that the transaction status is not set on customer account deposit lines.
                if (salesTransaction.CustomerAccountDepositLines.Any(customerAccountDepositLine => customerAccountDepositLine.TransactionStatus != TransactionStatus.Normal))
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountDepositLineDoesNotAllowSettingTransactionStatus, "The income/ expense line cannot have the transaction status set.");
                }

                // Check that the cart only has a single customer account deposit line. No other lines are allowed.
                if (salesTransaction.SalesLines.Any() || salesTransaction.CustomerAccountDepositLines.HasMultiple() || salesTransaction.IncomeExpenseLines.Any())
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountDepositMultipleCartLinesNotAllowed, "Sales lines are not allowed on a customer account deposit transaction.");
                }

                // Transaction has to have customer id
                if (string.IsNullOrWhiteSpace(salesTransaction.CustomerId))
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountNumberIsNotSet, "The customer id must be set for account deposit transaction.");
                }

                // Adding cashier (or) manual discounts are not allowed.
                if (salesTransaction.TotalManualDiscountAmount != 0 || salesTransaction.TotalManualDiscountPercentage != 0)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_DiscountAmountInvalidated, "The discount is not allowed in account deposit transaction.");
                }

                // Analyze deposit cart line
                if (salesTransaction.CustomerAccountDepositLines.Any())
                {
                    CustomerAccountDepositLine depositLine = salesTransaction.CustomerAccountDepositLines.SingleOrDefault();

                    // Only positive deposit is allowed.
                    if (depositLine.Amount <= 0)
                    {
                        throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountDepositCannotBeNegative, "The customer account deposit amount must be positive.");
                    }

                    if (string.IsNullOrWhiteSpace(depositLine.CustomerAccount))
                    {
                        throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountNumberIsNotSet, "The customer id must be set for account deposit transaction.");
                    }

                    Customer customerOnTransaction = GetCustomer(context, salesTransaction.CustomerId);

                    bool   useInvoiceAccount         = !string.IsNullOrWhiteSpace(customerOnTransaction.InvoiceAccount);
                    string customerAccountForDeposit = useInvoiceAccount ? customerOnTransaction.InvoiceAccount : customerOnTransaction.AccountNumber;
                    if (!string.IsNullOrWhiteSpace(depositLine.CustomerAccount) && !depositLine.CustomerAccount.Equals(customerAccountForDeposit, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountMismatchBetweenTransactionAndDepositLine, "The customer account on the deposit line is different from the one on the cart.");
                    }
                }
            }
Esempio n. 2
0
            private static void CalculateAmountDue(RequestContext context, SalesTransaction salesTransaction)
            {
                if (salesTransaction == null)
                {
                    throw new ArgumentNullException("salesTransaction");
                }

                ChannelConfiguration channelConfiguration = context.GetChannelConfiguration();
                string cancellationcode = channelConfiguration.CancellationChargeCode;
                string currencyCode     = channelConfiguration.Currency;

                RoundingRule roundingRule = amountToRound => RoundWithPricesRounding(context, amountToRound, currencyCode);

                SalesTransactionTotaler.ClearTotalAmounts(salesTransaction);
                salesTransaction.NumberOfItems = 0m;

                // initialize with header-level charges list
                var charges = new List <ChargeLine>();

                if (salesTransaction.ChargeLines.Any())
                {
                    charges.AddRange(salesTransaction.ChargeLines);
                }

                // Calculate totals for sale items , which might also include line-level misc charge in it.
                foreach (SalesLine saleLineItem in salesTransaction.SalesLines)
                {
                    if (saleLineItem.IsVoided == false)
                    {
                        // Calculate the sum of items
                        salesTransaction.NumberOfItems += Math.Abs(saleLineItem.Quantity);

                        // calculate the line item cost excluding charges and tax on charges.
                        SalesLineTotaller.CalculateLine(salesTransaction, saleLineItem, roundingRule);

                        UpdateTotalAmounts(salesTransaction, saleLineItem);
                    }
                    else
                    {
                        saleLineItem.PeriodicDiscountPossibilities.Clear();
                        SalesLineTotaller.CalculateLine(salesTransaction, saleLineItem, roundingRule);
                    }

                    saleLineItem.WasChanged = false;
                }

                // Add eligible charges on sales lines
                foreach (SalesLine salesLine in salesTransaction.ChargeCalculableSalesLines)
                {
                    charges.AddRange(salesLine.ChargeLines);
                }

                decimal incomeExpenseTotalAmount = 0m;

                foreach (IncomeExpenseLine incomeExpense in salesTransaction.IncomeExpenseLines)
                {
                    if (incomeExpense.AccountType != IncomeExpenseAccountType.None)
                    {
                        salesTransaction.NetAmountWithTax         += incomeExpense.Amount;
                        salesTransaction.NetAmountWithNoTax       += incomeExpense.Amount;
                        salesTransaction.GrossAmount              += incomeExpense.Amount;
                        salesTransaction.IncomeExpenseTotalAmount += incomeExpense.Amount;

                        // The total is done to calculate the payment amount.
                        incomeExpenseTotalAmount += incomeExpense.Amount;
                    }
                }

                foreach (ChargeLine charge in charges)
                {
                    AddToTaxItems(salesTransaction, charge);

                    // Calculate tax on the charge item.
                    CalculateTaxForCharge(charge);

                    if (charge.ChargeCode.Equals(cancellationcode, StringComparison.OrdinalIgnoreCase) && IsSeparateTaxInCancellationCharge(context))
                    {
                        salesTransaction.TaxOnCancellationCharge += charge.TaxAmount;
                    }
                    else
                    {
                        salesTransaction.TaxAmount += charge.TaxAmount;
                    }

                    // Later there is "TotalAmount = NetAmountWithTax + ChargeAmount", so we should add TaxAmountExclusive here
                    salesTransaction.NetAmountWithTax += charge.TaxAmountExclusive;
                }

                salesTransaction.DiscountAmount = salesTransaction.PeriodicDiscountAmount + salesTransaction.LineDiscount + salesTransaction.TotalDiscount;
                salesTransaction.ChargeAmount   = salesTransaction.ChargesTotal();

                // Subtotal is the net amount for the transaction (which includes the discounts) and optionally the tax amount if tax inclusive
                salesTransaction.SubtotalAmount = roundingRule(salesTransaction.NetAmountWithNoTax + salesTransaction.TaxAmountInclusive);

                salesTransaction.SubtotalAmountWithoutTax = context.GetChannelConfiguration().PriceIncludesSalesTax
                                                                ? salesTransaction.SubtotalAmount - salesTransaction.TaxAmount
                                                                : salesTransaction.SubtotalAmount;

                // Net amount when saved should include charges, it should be done after Subtotal amount calc because Subtotal does not include charge amount.
                salesTransaction.NetAmountWithNoTax = roundingRule(salesTransaction.NetAmountWithNoTax + salesTransaction.ChargeAmount);

                if (salesTransaction.IncomeExpenseLines.Any())
                {
                    // Setting the total amount sames as Payment amount for Income/ expense accounts.
                    salesTransaction.TotalAmount = incomeExpenseTotalAmount;
                }
                else if (salesTransaction.TransactionType == SalesTransactionType.CustomerAccountDeposit && salesTransaction.CustomerAccountDepositLines.Any())
                {
                    CustomerAccountDepositLine customerAccountDepositLine = salesTransaction.CustomerAccountDepositLines.SingleOrDefault();
                    salesTransaction.SubtotalAmountWithoutTax = customerAccountDepositLine.Amount;
                    salesTransaction.TotalAmount = customerAccountDepositLine.Amount;
                }
                else
                {
                    // NetAmountWithTax already includes the discounts
                    salesTransaction.TotalAmount = roundingRule(salesTransaction.NetAmountWithTax + salesTransaction.ChargeAmount);
                }
            }