private CollectionSchedule GetNewItem(
            string collectCode, string collectName,
            CollectionSchedule detail = null)
        {
            var item = new CollectionSchedule();

            item.CustomerId   = detail?.CustomerId ?? 0;
            item.CustomerCode = detail?.CustomerCode;
            item.CustomerName = detail?.CustomerName;
            item.CustomerCollectCategoryId = detail?.CustomerCollectCategoryId ?? 0;
            item.CustomerSightOfBill       = detail?.CustomerSightOfBill;
            item.ClosingDay            = detail?.ClosingDay;
            item.DepartmentCode        = detail?.DepartmentCode;
            item.DepartmentName        = detail?.DepartmentName;
            item.StaffCode             = detail?.StaffCode;
            item.StaffName             = detail?.StaffName;
            item.CollectCategoryCode   = collectCode;
            item.CollectCategoryName   = collectName;
            item.UncollectedAmountLast = 0M;
            item.UncollectedAmount0    = 0M;
            item.UncollectedAmount1    = 0M;
            item.UncollectedAmount2    = 0M;
            item.UncollectedAmount3    = 0M;
            return(item);
        }
Example #2
0
        private CollectionSchedule GetSubItem(GroupFooter footer, CollectionSchedule item)
        {
            if (footer == grfTotal)
            {
                return(item);
            }
            Func <CollectionSchedule, bool> selector = null;

            if (footer == grfStaff)
            {
                selector = x =>
                           x.RecordType == 1 &&
                           x.CollectCategoryCode == item.CollectCategoryCode &&
                           x.StaffCode == StaffCode &&
                           (!NewPagePerDepartment || x.DepartmentCode == DepartmentCode);
            }
            else if (footer == grfDepartment)
            {
                selector = x =>
                           x.RecordType == 2 &&
                           x.CollectCategoryCode == item.CollectCategoryCode &&
                           x.DepartmentCode == DepartmentCode &&
                           (!NewPagePerStaff || x.StaffCode == StaffCode);
            }
            return(OriginalSource.FirstOrDefault(selector));
        }
        /// <summary>
        /// 横縦変換処理 列をintのkeyで変換
        /// </summary>
        /// <param name="detail"></param>
        /// <returns>
        /// 0 : -1 カ月迄, 1 : 当月, 2 : 翌月, 3 : +2カ月, 4 : +3カ月以降
        /// reflection を利用して property setter を保持する案も考慮したが、
        /// 大量にreflection が発生するため、dictionary にて対応
        /// key を const で代替しても良いが、下記3つのメソッド内部のみの使用のため、別途 const は設けていない
        /// </returns>
        private Dictionary <int, decimal> Pivot(CollectionSchedule detail)
        {
            var dic = new Dictionary <int, decimal>(5);

            dic.Add(0, detail?.UncollectedAmountLast ?? 0M);
            dic.Add(1, detail?.UncollectedAmount0 ?? 0M);
            dic.Add(2, detail?.UncollectedAmount1 ?? 0M);
            dic.Add(3, detail?.UncollectedAmount2 ?? 0M);
            dic.Add(4, detail?.UncollectedAmount3 ?? 0M);
            return(dic);
        }
 private void AddValue(Dictionary <int, decimal> dic, CollectionSchedule detail)
 {
     if (dic == null)
     {
         return;
     }
     dic[0] += detail?.UncollectedAmountLast ?? 0M;
     dic[1] += detail?.UncollectedAmount0 ?? 0M;
     dic[2] += detail?.UncollectedAmount1 ?? 0M;
     dic[3] += detail?.UncollectedAmount2 ?? 0M;
     dic[4] += detail?.UncollectedAmount3 ?? 0M;
 }
        private void SetValue(CollectionSchedule detail, int key, decimal value)
        {
            switch (key)
            {
            case 0: detail.UncollectedAmountLast += value; break;

            case 1: detail.UncollectedAmount0 += value; break;

            case 2: detail.UncollectedAmount1 += value; break;

            case 3: detail.UncollectedAmount2 += value; break;

            case 4: detail.UncollectedAmount3 += value; break;
            }
        }
Example #6
0
        private decimal GetFieldValue(CollectionSchedule item, eTextBox field)
        {
            switch (field)
            {
            case eTextBox.KinZ: return(item?.UncollectedAmountLast ?? 0M);

            case eTextBox.Kin0: return(item?.UncollectedAmount0 ?? 0M);

            case eTextBox.Kin1: return(item?.UncollectedAmount1 ?? 0M);

            case eTextBox.Kin2: return(item?.UncollectedAmount2 ?? 0M);

            case eTextBox.Kin3: return(item?.UncollectedAmount3 ?? 0M);

            case eTextBox.KinK: return(item?.UncollectedAmountTotal ?? 0M);
            }
            return(0M);
        }
        /// <summary>回収予定表 データ抽出/整形</summary>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        /// <remarks>
        /// 得意先 回収区分の情報をどのように取り扱うか ビジネスロジックはここに寄せる
        /// </remarks>
        public async Task <IEnumerable <CollectionSchedule> > GetAsync(CollectionScheduleSearch searchOption, CancellationToken token, IProgressNotifier notifier)
        {
            var initializeResult = searchOption.InitializeYearMonth();

            var schedules = (await collectionScheduleQueryProcessor.GetAsync(searchOption, token, notifier))
                            .Where(x => x.HasAnyValue).ToList();

            if (!(schedules?.Any() ?? false))
            {
                notifier?.UpdateState();
                return(Enumerable.Empty <CollectionSchedule>());
            }

            const int    collectCategoryType = 3;
            const string ContractCode        = "00";
            var          categories          = (await categoryByCodeQueryProcessor.GetAsync(new CategorySearch {
                CompanyId = searchOption.CompanyId, CategoryType = collectCategoryType
            }, token)).ToList();
            var contractId  = categories.FirstOrDefault(x => x.Code == ContractCode)?.Id ?? 0;
            var customerIds = schedules.Where(x => x.CustomerCollectCategoryId == contractId)
                              .Select(x => x.CustomerId).Distinct().ToArray();
            var contracts = await customerPaymentContractQueryProcessor.GetAsync(customerIds, token);


            var result     = new List <CollectionSchedule>();
            var groupCount = 0;

            var subtotal = new Dictionary <string, Dictionary <int, decimal> >();
            var subDpt   = new Dictionary <string, Dictionary <int, decimal> >();
            var subStf   = new Dictionary <string, Dictionary <int, decimal> >();
            var deptBuf  = string.Empty;
            var stafBuf  = string.Empty;
            var requireDepartmentSubtotal = searchOption.IsPrint && searchOption.NewPagePerDepartment;
            var requireStaffSubtotal      = searchOption.IsPrint && searchOption.NewPagePerStaff;

            foreach (var group in schedules.GroupBy(x => x.CustomerId))
            {
                var detail       = group.First();
                var category     = categories.FirstOrDefault(x => x.Id != contractId && x.Id == detail.CustomerCollectCategoryId);
                var contract     = contracts.FirstOrDefault(x => x.CustomerId == detail.CustomerId);
                var customerInfo = GetCustomerInfo(detail, category, contract);

                if (requireStaffSubtotal &&
                    !string.IsNullOrEmpty(stafBuf) && stafBuf != detail.StaffCode)
                {
                    result.AddRange(GetSubtotalRecords(subStf, categories, deptBuf, stafBuf, 1, "担当者計", ref groupCount));
                }

                if (requireDepartmentSubtotal &&
                    !string.IsNullOrEmpty(deptBuf) && deptBuf != detail.DepartmentCode)
                {
                    result.AddRange(GetSubtotalRecords(subDpt, categories, deptBuf, stafBuf, 2, "部門計", ref groupCount));
                }

                var list = new List <CollectionSchedule>();

                CollectionSchedule contractPayment = null;
                foreach (var item in group)
                {
                    if (item.CollectCategoryCode == ContractCode)
                    {
                        contractPayment = item;
                        continue;
                    }
                    list.Add(item);
                }

                if (contractPayment != null && contract != null)
                {
                    foreach (var divided in Divide(contractPayment, contract))
                    {
                        var index = list.FindIndex(x => x.CollectCategoryCode == divided.CollectCategoryCode);
                        if (index < 0)
                        {
                            list.Add(divided);
                            continue;
                        }
                        list[index].UncollectedAmountLast += divided.UncollectedAmountLast;
                        list[index].UncollectedAmount0    += divided.UncollectedAmount0;
                        list[index].UncollectedAmount1    += divided.UncollectedAmount1;
                        list[index].UncollectedAmount2    += divided.UncollectedAmount2;
                        list[index].UncollectedAmount3    += divided.UncollectedAmount3;
                    }
                    list.Sort((x, y) => string.Compare(x.CollectCategoryCode, y.CollectCategoryCode));
                }

                for (var i = 0; i < list.Count; i++)
                {
                    if (i == 0)
                    {
                        list[i].RowId = ++groupCount;
                    }
                    else
                    {
                        list[i].DepartmentName = string.Empty;
                        list[i].StaffName      = string.Empty;
                        list[i].ClosingDay     = null;
                    }

                    var code = list[i].CollectCategoryCode;
                    if (!subtotal.ContainsKey(code))
                    {
                        subtotal.Add(code, Pivot(null));
                    }
                    if (requireDepartmentSubtotal && !subDpt.ContainsKey(code))
                    {
                        subDpt.Add(code, Pivot(null));
                    }
                    if (requireStaffSubtotal && !subStf.ContainsKey(code))
                    {
                        subStf.Add(code, Pivot(null));
                    }

                    if (!list[i].HasAnyValue)
                    {
                        continue;
                    }

                    AddValue(subtotal[code], list[i]);
                    if (requireDepartmentSubtotal)
                    {
                        AddValue(subDpt[code], list[i]);
                    }
                    if (requireStaffSubtotal)
                    {
                        AddValue(subStf[code], list[i]);
                    }
                }

                for (var i = 0; i < customerInfo.Count; i++)
                {
                    if (list.Count <= i)
                    {
                        var item = new CollectionSchedule();
                        item.CustomerId     = detail.CustomerId;
                        item.StaffCode      = detail.StaffCode;
                        item.DepartmentCode = detail.DepartmentCode;
                        list.Add(item);
                    }
                    list[i].CustomerInfo = customerInfo[i];
                }
                result.AddRange(list);

                deptBuf = detail.DepartmentCode;
                stafBuf = detail.StaffCode;
            }

            if (requireStaffSubtotal)
            {
                result.AddRange(GetSubtotalRecords(subStf, categories, deptBuf, stafBuf, 1, "担当者計", ref groupCount));
            }

            if (requireDepartmentSubtotal)
            {
                result.AddRange(GetSubtotalRecords(subDpt, categories, deptBuf, stafBuf, 2, "部門計", ref groupCount));
            }

            // grand total
            {
                // category total
                result.AddRange(GetSubtotalRecords(new Dictionary <string, Dictionary <int, decimal> >(subtotal), categories, "", "", 3, "合計", ref groupCount));

                var item = GetNewItem(string.Empty, string.Empty);
                item.CustomerInfo = "総合計";
                item.RowId        = ++groupCount;
                item.RecordType   = 4;
                foreach (var key in subtotal.Keys)
                {
                    foreach (var field in subtotal[key].Keys)
                    {
                        SetValue(item, field, subtotal[key][field]);
                    }
                }

                result.Add(item);
            }

            if (searchOption.UnitPrice != 1M)
            {
                foreach (var item in result)
                {
                    item.Truncate(searchOption.UnitPrice);
                }
            }
            notifier?.UpdateState();
            return(result);
        }
        /// <summary>
        /// 明細一行を約定条件によって分割する処理
        /// </summary>
        /// <param name="detail">分割対象の 約定の行</param>
        /// <param name="contract">約定条件</param>
        /// <returns>
        /// 列ごとの約定金額判定を実施するため、dic に 横縦変換して保持する
        /// </returns>
        private List <CollectionSchedule> Divide(CollectionSchedule detail,
                                                 CustomerPaymentContract contract)
        {
            var list = new List <CollectionSchedule>();
            var dic  = Pivot(detail);

            if (dic.Values.Any(x => x != 0M && x < contract.ThresholdValue))
            {
                list.Add(GetNewItem(contract.LessThanCode, contract.LessThanName, detail));
            }
            if (dic.Values.Any(x => x >= contract.ThresholdValue))
            {
                if (!list.Any(x => x.CollectCategoryCode == contract.GreaterThanCode1))
                {
                    list.Add(GetNewItem(contract.GreaterThanCode1, contract.GreaterThanName1, detail));
                }
                if ((contract.GreaterThanCollectCategoryId2 ?? 0) != 0 &&
                    !list.Any(x => x.CollectCategoryCode == contract.GreaterThanCode2))
                {
                    list.Add(GetNewItem(contract.GreaterThanCode2, contract.GreaterThanName2, detail));
                }
                if ((contract.GreaterThanCollectCategoryId3 ?? 0) != 0 &&
                    !list.Any(x => x.CollectCategoryCode == contract.GreaterThanCode3))
                {
                    list.Add(GetNewItem(contract.GreaterThanCode3, contract.GreaterThanName3, detail));
                }
            }

            foreach (var key in dic.Keys)
            {
                if (dic[key] == 0M)
                {
                    continue;
                }
                if (dic[key] < contract.ThresholdValue)
                {
                    var index = list.FindIndex(x => x.CollectCategoryCode == contract.LessThanCode);
                    SetValue(list[index], key, dic[key]);
                    continue;
                }

                var remainingIndex = -1;
                var remaining      = dic[key];

                {
                    var index = list.FindIndex(x => x.CollectCategoryCode == contract.GreaterThanCode1);
                    var mode  = contract.GreaterThanRoundingMode1.Value;
                    if (mode == 0)
                    {
                        remainingIndex = index;
                    }
                    var scale = GetScale(mode);
                    var value = decimal.Truncate(dic[key] * contract.GreaterThanRate1.Value / 100M / scale) * scale;
                    SetValue(list[index], key, value);
                    remaining -= value;
                }

                if ((contract.GreaterThanCollectCategoryId2 ?? 0) != 0)
                {
                    var index = list.FindIndex(x => x.CollectCategoryCode == contract.GreaterThanCode2);
                    var mode  = contract.GreaterThanRoundingMode2.Value;
                    if (mode == 0)
                    {
                        remainingIndex = index;
                    }
                    var scale = GetScale(mode);
                    var value = decimal.Truncate(dic[key] * contract.GreaterThanRate2.Value / 100M / scale) * scale;
                    SetValue(list[index], key, value);
                    remaining -= value;
                }

                if ((contract.GreaterThanCollectCategoryId3 ?? 0) != 0)
                {
                    var index = list.FindIndex(x => x.CollectCategoryCode == contract.GreaterThanCode3);
                    var mode  = contract.GreaterThanRoundingMode3.Value;
                    if (mode == 0)
                    {
                        remainingIndex = index;
                    }
                    var scale = GetScale(mode);
                    var value = decimal.Truncate(dic[key] * contract.GreaterThanRate3.Value / 100M / scale) * scale;
                    SetValue(list[index], key, value);
                    remaining -= value;
                }
                if (remaining != 0M && remainingIndex != -1)
                {
                    SetValue(list[remainingIndex], key, remaining);
                }
            }
            return(list);
        }
        /// <summary>
        /// 得意先情報 および 得意先マスター設定の 回収区分情報取得
        /// </summary>
        /// <param name="detail"></param>
        /// <param name="category"></param>
        /// <param name="contract"></param>
        /// <returns></returns>
        private List <string> GetCustomerInfo(CollectionSchedule detail,
                                              Category category,
                                              CustomerPaymentContract contract)
        {
            var list = new List <string>();

            list.Add($"{detail.CustomerCode} {detail.CustomerName}");
            if (category != null)
            {
                list.Add(detail.CustomerSightOfBill.HasValue ?
                         $" {category.Name} {detail.CustomerSightOfBill}日" :
                         $" {category.Name}");
                return(list);
            }
            if (contract == null)
            {
                return(list);
            }
            list.Add($" {contract.ThresholdValue:#,##0}円未満 {contract.LessThanName}");

            {
                var item = new List <string>();
                item.Add(" 以上");
                item.Add($"{contract.GreaterThanRate1}%");
                item.Add(contract.GreaterThanName1);
                if (contract.GreaterThanSightOfBill1 != 0)
                {
                    item.Add($"{contract.GreaterThanSightOfBill1}日");
                }
                if (contract.GreaterThanRoundingMode1 == 0)
                {
                    item.Add("端数");
                }
                list.Add(string.Join(" ", item.ToArray()));
            }

            if (contract.GreaterThanCollectCategoryId2.HasValue)
            {
                var item = new List <string>();
                item.Add(" 以上");
                item.Add($"{contract.GreaterThanRate2}%");
                item.Add(contract.GreaterThanName2);
                if ((contract.GreaterThanSightOfBill2 ?? 0) != 0)
                {
                    item.Add($"{contract.GreaterThanSightOfBill2}日");
                }
                if (contract.GreaterThanRoundingMode2 == 0)
                {
                    item.Add("端数");
                }
                list.Add(string.Join(" ", item.ToArray()));
            }
            if (contract.GreaterThanCollectCategoryId3.HasValue)
            {
                var item = new List <string>();
                item.Add(" 以上");
                item.Add($"{contract.GreaterThanRate3}%");
                item.Add(contract.GreaterThanName3);
                if ((contract.GreaterThanSightOfBill3 ?? 0) != 0)
                {
                    item.Add($"{contract.GreaterThanSightOfBill3}日");
                }
                if (contract.GreaterThanRoundingMode3 == 0)
                {
                    item.Add("端数");
                }
                list.Add(string.Join(" ", item.ToArray()));
            }
            return(list);
        }