private void distributeRemainders(short sign, CommonTaxHelper helper, RemainderHelper remainderHelper, IEnumerable <TaxGroupForCalculations> taxGroupsForCalculations)
        {
            var     vatGroups            = taxGroupsForCalculations.Where(x => x.PositiveOrNegative == sign);
            var     sortedList           = vatGroups.OrderByDescending(o => o.Remainder).ThenByDescending(o => o.TotalForGroupBeforeDiscount);
            int     groupCounter         = 0;
            decimal howManyDistributions = Math.Abs(sign == POSITIVE_SIGN
                                               ? remainderHelper.RemainderSumPositive
                                               : remainderHelper.RemainderSumNegative) / 0.01m;

            foreach (TaxGroupForCalculations group in sortedList)
            {
                groupCounter++;
                group.TotalForGroupBeforeDiscount     = Math.Abs(group.TotalForGroupBeforeDiscount);
                group.TruncatedDiscountAmountForGroup = Math.Abs(group.TruncatedDiscountAmountForGroup);

                if (groupCounter <= howManyDistributions)
                {
                    group.DistributedRemainder = 0.01m;
                }
                group.DiscountAmountForGroupWithRemainder    = group.TruncatedDiscountAmountForGroup + group.DistributedRemainder;
                group.TotalForGroupAfterDiscountAndRemainder = group.TotalForGroupBeforeDiscount - group.DiscountAmountForGroupWithRemainder;

                group.TotalVATAfterDiscount  = Utils.GetSaleTaxDue(group.TotalForGroupAfterDiscountAndRemainder, group.TaxRate, TaxMethod);
                group.TotalVATBeforeDiscount = Utils.GetSaleTaxDue(group.TotalForGroupBeforeDiscount, group.TaxRate, TaxMethod);
            }
        }
        private decimal getRealDiscountPct(CommonTaxHelper helper)
        {
            decimal discountAmmount = helper.DiscountAmount;

            if (helper.DiscountAmount == 0 && helper.DiscountPCT != 0)
            {
                decimal bruto = TaxMethod == TaxMethods.AddTax
                    ? helper.BrutoTotals.TotalAmountWithoutTax
                    : helper.BrutoTotals.TotalAmountWithTax;
                discountAmmount = Math.Round((discountAmmount / 100) * bruto, 2);
            }

            switch (TaxMethod)
            {
            case TaxMethods.AddTax:
                if (helper.BrutoTotals.TotalAmountWithoutTax != 0)
                {
                    return(discountAmmount / helper.BrutoTotals.TotalAmountWithoutTax);
                }
                return(0);

            default:
                if (helper.BrutoTotals.TotalAmountWithTax != 0)
                {
                    return(discountAmmount / helper.BrutoTotals.TotalAmountWithTax);
                }
                return(0);
            }
        }
        public CalculationStratagyResult Calculate(CommonTaxHelper commonTaxHelper)
        {
            RemainderHelper remainderHelper = new RemainderHelper();
            Dictionary <string, TaxGroupForCalculations> taxGroupsForCalculations = createTaxGroupTable(commonTaxHelper.TransLines);

            calcTaxForEachGroup(commonTaxHelper, remainderHelper, taxGroupsForCalculations);

            distributeRemainders(POSITIVE_SIGN, commonTaxHelper, remainderHelper, taxGroupsForCalculations.Values);
            distributeRemainders(NEGATIVE_SIGN, commonTaxHelper, remainderHelper, taxGroupsForCalculations.Values);
            IEnumerable <TaxRateGroup> positiveTaxGroupedByTaxRate = getGroupedByTaxRate(taxGroupsForCalculations.Values.Where(x => x.PositiveOrNegative == POSITIVE_SIGN));
            IEnumerable <TaxRateGroup> negativeTaxGroupedByTaxRate = getGroupedByTaxRate(taxGroupsForCalculations.Values.Where(x => x.PositiveOrNegative == NEGATIVE_SIGN));
            IEnumerable <TaxCodeGroup> positiveTaxGroupedByTaxCode = getGroupedByTaxCode(taxGroupsForCalculations.Values.Where(x => x.PositiveOrNegative == POSITIVE_SIGN));
            IEnumerable <TaxCodeGroup> negativeTaxGroupedByTaxCode = getGroupedByTaxCode(taxGroupsForCalculations.Values.Where(x => x.PositiveOrNegative == NEGATIVE_SIGN));

            return(new CalculationStratagyResult(positiveTaxGroupedByTaxRate, negativeTaxGroupedByTaxRate, positiveTaxGroupedByTaxCode, negativeTaxGroupedByTaxCode));
        }
 private void calcTaxForEachGroup(CommonTaxHelper helper, RemainderHelper remainderHelper,
                                  Dictionary <string, TaxGroupForCalculations> taxGroupsForCalculations)
 {
     foreach (var group in taxGroupsForCalculations.Values)
     {
         group.DiscountAmountForGroup            = getDiscountAmount(helper, group.TotalForGroupBeforeDiscount);
         group.TruncatedDiscountAmountForGroup   = truncate(group.DiscountAmountForGroup);
         group.TotalForGroupAfterDiscount        = group.TotalForGroupBeforeDiscount - group.DiscountAmountForGroup;
         group.TotalForGroupAfterDiscountRounded = Math.Round(group.TotalForGroupAfterDiscount, 2);
         group.Remainder = group.DiscountAmountForGroup - group.TruncatedDiscountAmountForGroup;
         if (group.TotalForGroupBeforeDiscount >= 0)
         {
             remainderHelper.RemainderSumPositive += group.Remainder;
         }
         else
         {
             remainderHelper.RemainderSumNegative += group.Remainder;
         }
     }
 }
        private decimal getDiscountAmount(CommonTaxHelper helper, decimal bruto)
        {
            decimal discountPct = getRealDiscountPct(helper);

            return(Math.Round(bruto * discountPct, 8));
        }