Advertisement
eLVik

Form2

Dec 2nd, 2021
569
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 39.54 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Objects;
  4. using System.Data;
  5. using System.Data.EntityClient;
  6. using System.Linq;
  7. using System.IO;
  8.  
  9. using GUTFIRK.Utils;
  10. using GUTFIRK.ForestManagement.Domain;
  11. using GUTFIRK.ForestManagement.Domain.ModelEntities;
  12. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface;
  13. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsDescriptions.ForestFund;
  14. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsParams;
  15.  
  16. using GUTFIRK.Utils.TemplateSystem;
  17.  
  18. namespace GUTFIRK.ForestManagement.ReportService.ReportsCreators
  19. {
  20.     /// <summary>
  21.     /// Класс, формирующий отчет "Форма №2" по инструкциям ГУЛФ 1997 года.
  22.     /// </summary>
  23.     public sealed class Form2_ReportCreator : SelectOptionsAdapter
  24.     {
  25.         #region Скрытые поля
  26.         // Количество граф в форме №2
  27.         // Графы №№16 - 17 оставляем незаполненными.
  28.         const int COLUMN_COUNT = 15;
  29.  
  30.         ForestResourcesReportParams _reportParams = null;
  31.  
  32.         static object _lockObject = new object();
  33.  
  34.         List<Form1Row> _form1RowList = new List<Form1Row>();
  35.         List<Form2Row> _form2RowList = new List<Form2Row>();
  36.  
  37.         List<short> _distinctCuttingAgesList = new List<short>();
  38.  
  39.         List<short> _distinctStocksList = new List<short>();
  40.  
  41.         List<short> _distinctNormativeDataList = new List<short>();
  42.  
  43.         // Массив для хранения результатов расчета
  44.         // Индекс 0 - код набора НСИ.
  45.         // Индекс 1 - графа (столбец) формы №2
  46.         // Индекс 2 - номер строки формы №1 (лист формы №2)
  47.         // Индекс 3 - код породы
  48.         // Индекс 4 - возраст рубки
  49.         double[, , , ,] _array = null;
  50.  
  51.         #endregion
  52.  
  53.         /// <summary>
  54.         /// Конструктор.
  55.         /// </summary>
  56.         public Form2_ReportCreator()
  57.         {
  58.             _description = new Form2_ReportDescription();
  59.         }
  60.  
  61.         /// <summary>
  62.         /// Распределяет значения площади и запасов по временному массиву.
  63.         /// Новые значения суммируются со значениями элементов массива.
  64.         /// </summary>
  65.         /// <param name="ageDataItem">Возрастная характеристика главной породы.</param>
  66.         /// <param name="area">Площадь, га.</param>
  67.         /// <param name="volume">Запас, кбм.</param>
  68.         /// <param name="form1Row">Строка формы учета №1</param>
  69.         /// <param name="nsi_index">Индекс кода НСИ</param>
  70.         private void DistributeValues(vw_QuarterAgeDataItem ageDataItem, double area, double volume, Form1Row form1Row, int nsi_index)
  71.         {
  72.             // Если строка формы учета №1 является "эксплуатируемой",
  73.             // то распределение значений производим только в случае, если сам подвыдел является эксплуатируемым.
  74.             //if (ageDataItem.IsExploitable == false && form1Row.IsExploitable)
  75.             //    return;
  76.  
  77.             double p = 0.0;
  78.  
  79.             int form1Row_index = _form1RowList.IndexOf(form1Row);
  80.             int stock_index = _distinctStocksList.IndexOf(ageDataItem.MainStock_OID.Value);
  81.             // достаем ноль из запасников в случае необходимости (если нет соответствия в CuttingAges)
  82.             int cuttingAge_index = ageDataItem.CuttingAge.HasValue ? _distinctCuttingAgesList.IndexOf(ageDataItem.CuttingAge.Value) : _distinctCuttingAgesList.IndexOf(0);
  83.  
  84.             #region Распределение по графам
  85.             for (int i = 0; i < COLUMN_COUNT; i++)
  86.             {
  87.                 // FIXME (при добавлении расчета граф №№16 - 17)
  88.                 p = i <= 7 ? area : volume;
  89.  
  90.                 try
  91.                 {
  92.                     #region switch
  93.  
  94.                     switch (i)
  95.                     {
  96.                         // Всего
  97.                         case 0: // Area
  98.                         case 8: // Volume
  99.                             _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  100.                             break;
  101.  
  102.                         // Молодняки первого класса возраста
  103.                         case 1: // Area
  104.                         case 9: // Volume
  105.                             if (ageDataItem.AgeGroup_OID == 1 && ageDataItem.AgeClass == 1)
  106.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  107.                             break;
  108.  
  109.                         // Молодняки второго класса возраста
  110.                         case 2:  // Area
  111.                         case 10: // Volume
  112.                             if (ageDataItem.AgeGroup_OID == 1 && ageDataItem.AgeClass == 2)
  113.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  114.                             break;
  115.  
  116.                         // Средневозрастные
  117.                         case 3:  // Area
  118.                         case 11: // Volume
  119.                             if (ageDataItem.AgeGroup_OID == 2)
  120.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  121.                             break;
  122.  
  123.                         // Средневозрастные, включенные в расчет
  124.                         case 4:  // Area
  125.                             if (ageDataItem.AgeGroup_OID == 2 && ageDataItem.InCalc == true)
  126.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  127.                             break;
  128.  
  129.                         // Приспевающие
  130.                         case 5:  // Area
  131.                         case 12: // Volume
  132.                             if (ageDataItem.AgeGroup_OID == 3)
  133.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  134.                             break;
  135.  
  136.                         // Спелые и перестойные
  137.                         case 6:  // Area
  138.                         case 13: // Volume
  139.                             if (ageDataItem.AgeGroup_OID == 4 || ageDataItem.AgeGroup_OID == 5)
  140.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  141.                             break;
  142.  
  143.                         // Перестойные
  144.                         case 7:  // Area
  145.                         case 14: // Volume
  146.                             if (ageDataItem.AgeGroup_OID == 5)
  147.                                 _array[nsi_index, i, form1Row_index, stock_index, cuttingAge_index] += p;
  148.                             break;
  149.                     }
  150.                     #endregion
  151.                 }
  152.                 catch (IndexOutOfRangeException ex)
  153.                 {
  154. #if DEBUG
  155.                     Program.LogSystem.Error("DistributeValues error", ex);
  156. #endif
  157.                     throw;
  158.  
  159.                 }
  160.             }
  161.             #endregion
  162.         }
  163.  
  164.         private double GetSum(int nsi_index, int column_index, int form1Row_index)
  165.         {
  166.             double result = 0.0;
  167.             for (int j = 0; j < _distinctStocksList.Count; j++)
  168.                 for (int k = 0; k < _distinctCuttingAgesList.Count; k++)
  169.                     result += _array[nsi_index, column_index, form1Row_index, j, k];
  170.  
  171.             return result;
  172.         }
  173.  
  174.  
  175.         private double GetSum(int column_index, int form1Row_index)
  176.         {
  177.             double result = 0.0;
  178.             for (int i = 0; i < _distinctNormativeDataList.Count; i++)
  179.                 for (int j = 0; j < _distinctStocksList.Count; j++)
  180.                     for (int k = 0; k < _distinctCuttingAgesList.Count; k++)
  181.                         result += _array[i, column_index, form1Row_index, j, k];
  182.             return result;
  183.         }
  184.  
  185.         private double GetSum2(int column_index, int form1Row_index, int age_index, List<short> stocksList)
  186.         {
  187.             double result = 0.0;
  188.  
  189.             if (age_index >= 0)
  190.             {
  191.                 for (int i = 0; i < _distinctNormativeDataList.Count; i++)
  192.                     for (int j = 0; j < _distinctStocksList.Count; j++)
  193.                         if (stocksList.Contains(_distinctStocksList[j]))
  194.                             result += _array[i, column_index, form1Row_index, j, age_index];
  195.             }
  196.             else
  197.             {
  198.                 for (int i = 0; i < _distinctNormativeDataList.Count; i++)
  199.                     for (int j = 0; j < _distinctStocksList.Count; j++)
  200.                     {
  201.                         if (stocksList.Contains(_distinctStocksList[j]) == false)
  202.                             continue;
  203.                         for (int k = 0; k < _distinctCuttingAgesList.Count; k++)
  204.                             result += _array[i, column_index, form1Row_index, j, k];
  205.                     }
  206.             }
  207.  
  208.             return result;
  209.         }
  210.  
  211.         private List<short> GetCuttingAges(int form1row_index, int stock_index)
  212.         {
  213.             List<short> list = new List<short>();
  214.  
  215.             for (int nsi_index = 0; nsi_index < _distinctNormativeDataList.Count; nsi_index++)
  216.             {
  217.                 for (int age_index = 0; age_index < _distinctCuttingAgesList.Count; age_index++)
  218.                 {
  219.                     if (_array[nsi_index, 0, form1row_index, stock_index, age_index] > 0 && list.Contains(_distinctCuttingAgesList[age_index]) == false)
  220.                         list.Add(_distinctCuttingAgesList[age_index]);
  221.                 }
  222.             }
  223.  
  224.             list.Sort();
  225.             return list;
  226.         }
  227.  
  228.         /// <summary>
  229.         /// В ходе выполнения этого метода инициируются и заполняются скрытые поля класса
  230.         /// </summary>
  231.         /// <param name="reportParams"></param>
  232.         /// <param name="progressCallback"></param>
  233.         public override object DoCalculations(IReportParams reportParams, Procedure<int> progressCallback)
  234.         {
  235.             CheckParams(reportParams);
  236.             #region Переменные
  237.             _reportParams = (ForestResourcesReportParams)reportParams;
  238.             //_reportParams.Identifiers.Sort();
  239.             var year = (short)_reportParams.SelectOptions.YearOfActualization;
  240.  
  241.             // Переменные для вызова callback-метода, отвечающего за вывод прогресса.
  242.             int progress_counter = 0; // счетчик
  243.             double progress_q = 0.0;  // множитель
  244.  
  245.             // Список ассоциаций НСИ за указанный год.
  246.             List<NormativeAssociation> na_list = null;
  247.  
  248.             // По этому справочнику будут определены подчиненные строки формы учета №1
  249.             List<Form1Rows_CalculationOrder> calc_list1 = null;
  250.  
  251.             // По этому справочнику будут определены подчиненные строки формы учета №2
  252.             List<Form2Rows_CalculationOrder> calc_list2 = null;
  253.  
  254.             // в списоке calcOrder_list1 порядок обработки подчиненных строк формы учета №1
  255.             List<byte> calcOrder_list1 = new List<byte>();
  256.  
  257.             // в списоке calcOrder_list2 порядок обработки подчиненных строк формы учета №2
  258.             List<byte> calcOrder_list2 = new List<byte>();
  259.  
  260.             // Здесь - соответствия между категориями защитности и строками формы №1
  261.             IEnumerable<Form1Rows_To_ProtectionCategories> form1Rows_categoriesList = new List<Form1Rows_To_ProtectionCategories>();
  262.  
  263.             // Здесь - соответствия между породами и строками формы №2
  264.             IEnumerable<Form2Rows_To_Stocks> form2Rows_stocksList = new List<Form2Rows_To_Stocks>();
  265.  
  266.             // В этот список помещаем все сущности Form1Columns с номерами граф 2 и 3, затрагиваемые наборами НСИ
  267.             IEnumerable<Form1Columns> form1ColumnsList = new List<Form1Columns>();
  268.  
  269.             progress_counter = 0;
  270.             progress_q = 0.0; //25.0 / reportParams.Identifiers.Count; // деление на ноль невозможно - отфильтровано в родителе BaseReport
  271.  
  272.             #endregion
  273.  
  274.  
  275.             using (ModelContext context = new ModelContext())
  276.             {
  277.                 #region Расчет
  278.  
  279.                 #region Загрузка справочников
  280.  
  281.                 // Инициируем скрытые поля.
  282.                 _form1RowList = context.Form1RowSet.OrderBy(a => a.PrintOrder).ToList();
  283.                 _form2RowList = context.Form2RowSet.OrderBy(a => a.PrintOrder).ToList();
  284.                 _distinctCuttingAgesList.Clear();
  285.                 // в список возрастов рубок намеренно добавляем ноль
  286.                 _distinctCuttingAgesList.Add(0);
  287.                 _distinctStocksList.Clear();
  288.                 _distinctNormativeDataList.Clear();
  289.  
  290.                 foreach (Form2Row form2Row in _form2RowList)
  291.                     form2Row.InitStockList();
  292.  
  293.                 // Загрузив данные из БД в список один раз, будем искать в нем соответствие между кварталом и набором НСИ.
  294.                 na_list = context.NormativeAssociationSet.Where("it.Year = @year", new ObjectParameter("year", year)).Include("NormativeData").Include("Forestry").ToList();
  295.  
  296.                 if (na_list.Count == 0)
  297.                     throw new ReportException(reportParams, "Список нормативных ассоциаций пуст.");
  298.  
  299.                 calc_list1 = context.Form1Rows_CalculationOrderSet.Include("Form1RowA").Include("Form1RowB").ToList<Form1Rows_CalculationOrder>();
  300.                 calc_list2 = context.Form2Rows_CalculationOrderSet.Include("Form2RowA").Include("Form2RowB").ToList<Form2Rows_CalculationOrder>();
  301.  
  302.                 calcOrder_list1.Clear();
  303.                 foreach (Form1Rows_CalculationOrder item in calc_list1)
  304.                 {
  305.                     if (calcOrder_list1.Contains(item.CalcOrder) == false)
  306.                         calcOrder_list1.Add(item.CalcOrder);
  307.                 }
  308.                 calcOrder_list1.Sort();
  309.  
  310.  
  311.                 calcOrder_list2.Clear();
  312.                 foreach (Form2Rows_CalculationOrder item in calc_list2)
  313.                 {
  314.                     if (calcOrder_list2.Contains(item.CalcOrder) == false)
  315.                         calcOrder_list2.Add(item.CalcOrder);
  316.                 }
  317.                 calcOrder_list2.Sort();
  318.  
  319.                 progressCallback(5);
  320.                 #endregion
  321.  
  322.                 #region Получение списка кварталов из списка выделов
  323.                 var qIDs = GetQuarterIDs(_reportParams.SelectOptions);
  324.                 var fullQuarterIds = GetFullQuarterIDs(_reportParams.SelectOptions);
  325.  
  326.                 progress_q = qIDs.Count > 0 ? 85.0 / qIDs.Count : 0.0;
  327.                 #endregion
  328.  
  329.  
  330.                 #region Первый обход кварталов
  331.                 // При первом обходе собираем различные возрасты рубок, идентификаторы пород и форм учета №1.
  332.                 // Заполняются списки _distinctCuttingAgesList, _distinctStocksList, _distinctNormativeDataList
  333.  
  334.                 progress_counter = 0;
  335.                 progress_q = 40.0 / qIDs.Count;
  336.                 foreach (var quarterID in qIDs)
  337.                 {
  338.                     #region CallBack
  339.                     progress_counter++;
  340.                     progressCallback(this.GetProgress(5, progress_counter, progress_q));
  341.                     #endregion
  342.  
  343.                     var quarter = context.QuarterSet.Include("DivisionalForestry.Forestry").FirstOrDefault(x => x.OID == quarterID);
  344.                     if (quarter == null)
  345.                         continue;
  346.  
  347.                     List<int> sortedIdentifiers = null;
  348.                     if (fullQuarterIds.BinarySearch(quarterID) >= 0)
  349.                     {
  350.                         quarter.Stratums.Load();
  351.                         sortedIdentifiers = quarter.Stratums.Select(x => x.OID).ToList();
  352.                     }
  353.                     else
  354.                     {
  355.                         sortedIdentifiers = GetStratumIDsFromPartialQuarter(_reportParams.SelectOptions, quarterID);
  356.                     }
  357.                     sortedIdentifiers.Sort();
  358.  
  359.                     #region Загрузка НСИ
  360.                     NormativeAssociation na = na_list.Where(a => a.Forestry.OID == quarter.GetForestry().OID).FirstOrDefault();
  361.  
  362.                     // Ошибка может возникнуть в случае, если лесничеству не сопоставлен набор НСИ в указанный год.
  363.                     if (na == null)
  364.                         throw new ReportException(reportParams, String.Format("Отсутствует набор НСИ для квартала (OID = {0})", quarter.OID));
  365.  
  366.                     // Подгружаем данные, если встретился новый набор НСИ.
  367.                     if (_distinctNormativeDataList.Contains(na.NormativeData.OID) == false)
  368.                     {
  369.                         _distinctNormativeDataList.Add(na.NormativeData.OID);
  370.                         ObjectParameter parameter = new ObjectParameter("oid", na.NormativeData.OID);
  371.                         List<Form2Rows_To_Stocks> list1 = context.Form2Rows_To_StocksSet.Where("it.NormativeData.OID = @oid", parameter).Include("Stock").Include("Form2Row").Include("NormativeData").ToList();
  372.                         form2Rows_stocksList = form2Rows_stocksList.Concat(list1);
  373.  
  374.                         List<Form1Rows_To_ProtectionCategories> list2 = context.Form1Rows_To_ProtectionCategoriesSet.Where("it.NormativeData.OID = @oid", parameter).Include("ProtectionCategory").Include("NormativeData").Include("Form1Row").ToList();
  375.                         form1Rows_categoriesList = form1Rows_categoriesList.Concat(list2);
  376.  
  377.                         List<Form1Columns> list3 = context.Form1ColumnsSet.Where("it.NormativeData.OID = @oid AND (it.ColumnNumber = 2 OR it.ColumnNumber = 3)", parameter).Include("LandCategory").Include("NormativeData").ToList();
  378.                         form1ColumnsList = form1ColumnsList.Concat(list3);
  379.                     }
  380.                     #endregion
  381.  
  382.                     #region Выполнение хранимой процедуры и обработка ошибок
  383.                     // Получаем возрастные характеристики на квартал.
  384.                     List<vw_QuarterAgeDataItem> vw_AgeDataResult = null;
  385.  
  386.                     //lock (_lockObject)
  387.                     //{
  388.                         int counter = 0;
  389.                         bool success = false;
  390.  
  391.                         //Попытка выполнить хранимые процедуры
  392.                         while (!success)
  393.                         {
  394.                             try
  395.                             {
  396.                                 counter++; // Увеличиваем значение счетчика
  397.                                 // Получаем возрастные характеристики на квартал.
  398.                                 vw_AgeDataResult = context.GetMainStockAgeDataOnQuarter(quarter.OID, na.NormativeData.OID, na.CuttingAgeKey, year).ToList();
  399.  
  400.                                 success = true; // Выполнение хранимой процедуры успешно
  401.                             }
  402.                             // В случае ошибки выполнения хранимой процедуры 10 раз подряд останавливаем формирование отчета
  403.                             catch
  404.                             {
  405.                                 if (counter >= 10) break;
  406.                             }
  407.                         }
  408.                         if (!success) throw new ReportException(reportParams, "Ошибка доступа к хранимой процедуре");
  409.                     //}
  410.                     #endregion
  411.  
  412.                     foreach (vw_QuarterAgeDataItem item in vw_AgeDataResult)
  413.                     {
  414.                         if (sortedIdentifiers.BinarySearch(item.Stratum_OID.Value) >= 0)
  415.                         {
  416.                             //if (item.ReturnCode.HasValue && item.ReturnCode == 0)
  417.                             //{
  418.                                 if (item.MainStock_OID.HasValue && _distinctStocksList.Contains(item.MainStock_OID.Value) == false)
  419.                                     _distinctStocksList.Add(item.MainStock_OID.Value);
  420.  
  421.                                 if (item.CuttingAge.HasValue && _distinctCuttingAgesList.Contains(item.CuttingAge.Value) == false)
  422.                                     _distinctCuttingAgesList.Add(item.CuttingAge.Value);
  423.                             //}
  424.                         }
  425.                     }
  426.                 }
  427.  
  428.                 #endregion
  429.  
  430.                 #region Инициализация временного массива
  431.                 // Инициализация временного массива
  432.                 // Вторая размерность (графа формы) распределяется следующим образом:
  433.                 // 0-7 - распределение площадей
  434.                 // 8-15 - распределение запасов
  435.                 _array = new double[_distinctNormativeDataList.Count, COLUMN_COUNT, _form1RowList.Count, _distinctStocksList.Count, _distinctCuttingAgesList.Count];
  436.  
  437. #if DEBUG
  438.                 Program.LogSystem.DebugFormat("array init: ndl={0}, col={1}, f1r={2}, st={3}, cta={4}", _distinctNormativeDataList.Count, COLUMN_COUNT, _form1RowList.Count, _distinctStocksList.Count, _distinctCuttingAgesList.Count);
  439. #endif
  440.                 #endregion
  441.  
  442.                 #region Второй обход кварталов
  443.                 progress_counter = 0;
  444.  
  445.                 foreach (var quarterID in qIDs)
  446.                 {
  447.                     #region CallBack
  448.                     progress_counter++;
  449.                     progressCallback(this.GetProgress(45, progress_counter, progress_q));
  450.                     #endregion
  451.  
  452.                     var quarter = context.QuarterSet.Include("DivisionalForestry.Forestry").FirstOrDefault(x => x.OID == quarterID);
  453.                     if (quarter == null)
  454.                         continue;
  455.  
  456.                     List<int> sortedIdentifiers = null;
  457.                     if (fullQuarterIds.BinarySearch(quarterID) >= 0)
  458.                     {
  459.                         quarter.Stratums.Load();
  460.                         sortedIdentifiers = quarter.Stratums.Select(x => x.OID).ToList();
  461.                     }
  462.                     else
  463.                     {
  464.                         sortedIdentifiers = GetStratumIDsFromPartialQuarter(_reportParams.SelectOptions, quarterID);
  465.                     }
  466.                     sortedIdentifiers.Sort();
  467.  
  468.                     NormativeAssociation na = na_list.Where(a => a.Forestry.OID == quarter.GetForestry().OID).FirstOrDefault();
  469.                     if (na == null)
  470.                     {
  471.                         throw new ReportException(reportParams, "Нормативная ассоциация для квартала не найдена OID = " + quarter.OID.ToString());
  472.                     }
  473.                     int nsi_index = _distinctNormativeDataList.IndexOf(na.NormativeData.OID);
  474.  
  475.                     #region Выполнение хранимой процедуры и обработка ошибок
  476.                     List<vw_QuarterAgeDataItem> vw_AgeDataResult = null;
  477.                     //lock (_lockObject)
  478.                     //{
  479.                         int counter = 0;
  480.                         bool success = false;
  481.  
  482.                         //Попытка выполнить хранимые процедуры
  483.                         while (!success)
  484.                         {
  485.                             try
  486.                             {
  487.                                 counter++; // Увеличиваем значение счетчика
  488.                                 // Получаем возрастные характеристики на квартал.
  489.                                 vw_AgeDataResult = context.GetMainStockAgeDataOnQuarter(quarter.OID, na.NormativeData.OID, na.CuttingAgeKey, year).ToList();
  490.  
  491.                                 success = true; // Выполнение хранимой процедуры успешно
  492.                             }
  493.                             // В случае ошибки выполнения хранимой процедуры 10 раз подряд останавливаем формирование отчета
  494.                             catch
  495.                             {
  496.                                 if (counter >= 10) break;
  497.                             }
  498.                         }
  499.                         if (!success) throw new ReportException(reportParams, "Ошибка доступа к хранимой процедуре");
  500.                     //}
  501.                     #endregion
  502.                     List<CommonData> commonDataList = quarter.GetCommonDataList(context, year);
  503.  
  504.                     #region Обход общих характеристик
  505.                     // Заполняем список form1RowsInQuarter, чтобы определить - какие строки формы учета необходимо просчитать.
  506.                     foreach (CommonData commonData in commonDataList)
  507.                     {
  508.                         if (commonData.LandCategoryReference.IsLoaded == false)
  509.                             commonData.LandCategoryReference.Load();
  510.  
  511.                         if (commonData.SubStratumReference.IsLoaded == false)
  512.                             commonData.SubStratumReference.Load();
  513.  
  514.                         if (commonData.SubStratum.StratumReference.IsLoaded == false)
  515.                             commonData.SubStratum.StratumReference.Load();
  516.  
  517.                         // Отсекаем подвыделы, которые не относятся к графе №2 формы учета №1
  518.                         int count = form1ColumnsList.Count(a => a.LandCategory.OID == commonData.LandCategory.OID && a.NormativeData.OID == na.NormativeData.OID);
  519.                         if (count == 0)
  520.                             continue;
  521.  
  522.                         vw_QuarterAgeDataItem item = vw_AgeDataResult.First(a => a.CommonData_OID == commonData.OID);
  523.                         if (sortedIdentifiers.BinarySearch(item.Stratum_OID.Value) >= 0)
  524.                         {
  525.                             //if (item.ReturnCode.HasValue && item.ReturnCode.Value == 0)
  526.                             //{
  527.                                 if (commonData.ProtectionCategoryReference.IsLoaded == false)
  528.                                     commonData.ProtectionCategoryReference.Load();
  529.  
  530.                                 if (commonData.ProtectionCategory.ForestGroupReference.IsLoaded == false)
  531.                                     commonData.ProtectionCategory.ForestGroupReference.Load();
  532.  
  533.                                 // Строки, соответствующие текущей категории защитности.
  534.                                 IEnumerable<Form1Rows_To_ProtectionCategories> list = form1Rows_categoriesList.Where(a => a.ProtectionCategory.OID == commonData.ProtectionCategory.OID && a.NormativeData.OID == na.NormativeData.OID);
  535.  
  536.                                 double volume = commonData.TotalVolume.GetValueOrDefault();
  537.                                 foreach (Form1Rows_To_ProtectionCategories item1 in list)
  538.                                 {
  539.                                     // Обработка строки формы учета №1
  540.                                     this.DistributeValues(item, commonData.Area, volume, item1.Form1Row, nsi_index);
  541.                                 }
  542.  
  543.                                 // "Эксплуатируемые" строки
  544.                                 if (item.IsExploitable.HasValue && item.IsExploitable.Value == true && item.ReturnCode.HasValue && item.ReturnCode == 0)
  545.                                 {
  546.                                     Form1Row row = _form1RowList.First(a => a.OID == commonData.ProtectionCategory.ForestGroup.ExploitableForm1RowOID);
  547.                                     if (row == null)
  548.                                         throw new ReportException(reportParams, String.Format("Отсутствует строка формы учета №1 (OID = {0})", commonData.ProtectionCategory.ForestGroup.ExploitableForm1RowOID));
  549.  
  550.                                     // Обработка строки формы учета №1
  551.                                     DistributeValues(item, commonData.Area, volume, row, nsi_index);
  552.                                 }
  553.                             //}
  554.                         }
  555.                         context.Detach(commonData);
  556.                     }
  557.                     #endregion
  558.  
  559.  
  560.                     foreach (vw_QuarterAgeDataItem ageDataItem in vw_AgeDataResult)
  561.                         context.Detach(ageDataItem);
  562.  
  563.  
  564.                     context.Detach(quarter);
  565.                 }
  566.                 #endregion
  567.  
  568.                 #region Расчет подчиненных строк формы учета №1
  569.                 progress_q = 5.0 / calcOrder_list1.Count;
  570.                 progress_counter = 0;
  571.                 foreach (byte calcOrder in calcOrder_list1)
  572.                 {
  573.                     #region Callback
  574.                     progress_counter++;
  575.                     progressCallback(this.GetProgress(85, progress_counter, progress_q));
  576.                     #endregion
  577.  
  578.                     IEnumerable<Form1Rows_CalculationOrder> list4 = calc_list1.Where(a => a.CalcOrder == calcOrder);
  579.                     foreach (Form1Rows_CalculationOrder item in list4)
  580.                     {
  581.                         int index_dest = _form1RowList.IndexOf(item.Form1RowA);
  582.                         int index_src = _form1RowList.IndexOf(item.Form1RowB);
  583.                         for (int n = 0; n < _distinctNormativeDataList.Count; n++)
  584.                         {
  585.                             for (int i = 0; i < COLUMN_COUNT; i++)
  586.                             {
  587.                                 for (int j = 0; j < _distinctStocksList.Count; j++)
  588.                                 {
  589.                                     for (int k = 0; k < _distinctCuttingAgesList.Count; k++)
  590.                                     {
  591.                                         _array[n, i, index_dest, j, k] += _array[n, i, index_src, j, k];
  592.                                     }
  593.                                 }
  594.                             }
  595.                         }
  596.                     }
  597.                 }
  598.                 #endregion
  599.  
  600.                 #endregion
  601.             } // ModelContext
  602.  
  603.             //reportData.Year = reportParams.Year;
  604.             //reportData.ReportName = reportParams.Name;
  605.             //reportData.DistinctCuttingAgesList = _distinctCuttingAgesList;
  606.             //reportData.Form1RowsList = _form1RowsList;
  607.             //reportData.Form2RowsList = _form2RowsList;
  608.             //reportData.DistinctStocksList = _distinctStocksList;
  609.             //reportData.DistinctNormativeDataList = _distinctNormativeDataList;
  610.             //reportData.Array = _array;
  611.  
  612.             //return reportData;
  613.             return null;
  614.         }
  615.  
  616.  
  617.         public override void CreateDocument(object obj, string formatKey, Procedure<int> progressCallback, string templateFolder, System.IO.Stream outputStream)
  618.         {
  619.             #region Печать
  620.             TemplateProcessor tprocessor = new TemplateProcessor();
  621.             //Form2_ReportData rd = (Form2_ReportData)obj;
  622.             //templateFolder += _description.Key + "\\" + formatKey + "\\";
  623.             DateTime creationDateTime = DateTime.Now;
  624.             bool nbspFlag = formatKey == Program.HTML_FORMAT_KEY; //? "&nbsp;" : String.Empty;
  625.  
  626.             #region Параметры шаблонов
  627.             tprocessor.Parameters.Add(new TemplateParameter2("R_PROPERTY", tprocessor.ReadFile(templateFolder + "rproperty.tpl")));
  628.             tprocessor.Parameters.Add(new TemplateParameter2("PAGE_BREAK", tprocessor.ProcessFile(templateFolder + "pagebreak.tpl")));
  629.             tprocessor.Parameters.Add(new TemplateParameter2("R_PROPERTY_2", tprocessor.ReadFile(templateFolder + "rproperty2.tpl")));
  630.             tprocessor.Parameters.Add(new TemplateParameter2("R_PROPERTY_2B", tprocessor.ReadFile(templateFolder + "rproperty2b.tpl")));
  631.             tprocessor.Parameters.Add(new TemplateParameter2("R_PROPERTY_H", tprocessor.ReadFile(templateFolder + "rproperty_h.tpl")));
  632.             tprocessor.Parameters.Add(new TemplateParameter2("DOCUMENT_CREATION_DATETIME", String.Format("{0}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}Z", creationDateTime.Year, creationDateTime.Month, creationDateTime.Day, creationDateTime.Hour, creationDateTime.Minute, creationDateTime.Second)));
  633.             tprocessor.Parameters.Add(new TemplateParameter2("ACTUALIZATION_DATE", String.Format("01.01.{0}", _reportParams.SelectOptions.YearOfActualization)));
  634.             tprocessor.Parameters.Add(new TemplateParameter2("DOCUMENT_CREATION_DATE", creationDateTime.ToShortDateString()));
  635.             tprocessor.Parameters.Add(new TemplateParameter2("SHEET_NUMBER"));
  636.             tprocessor.Parameters.Add(new TemplateParameter2("ROWS_CONTENT"));
  637.             tprocessor.Parameters.Add(new TemplateParameter2("BODY_CONTENT"));
  638.             for (int p = 1; p <= 17; p++)
  639.                 tprocessor.Parameters.Add(new NumericTemplateParameter2("VALUE_S" + p.ToString(), 0, nbspFlag, (byte)2, DecimalSeparator.Comma));
  640.  
  641.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("REPORT_NAME", _reportParams.Name, nbspFlag));
  642.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("GROUP_NUMBER", String.Empty, nbspFlag));
  643.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("FORM1ROW_NAME", String.Empty, nbspFlag));
  644.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("VALUE_A", String.Empty, nbspFlag));
  645.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("VALUE_B", String.Empty, nbspFlag));
  646.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter2("VALUE_C", String.Empty, nbspFlag));
  647.             #endregion
  648.  
  649.             string header_template_1 = tprocessor.ReadFile(templateFolder + "header_1.tpl");
  650.             string header_template_2 = tprocessor.ReadFile(templateFolder + "header_2.tpl");
  651.             string row_template_1 = tprocessor.ReadFile(templateFolder + "row_1.tpl");
  652.             string row_template_2 = tprocessor.ReadFile(templateFolder + "row_2.tpl");
  653.             string boldrow_template_1 = tprocessor.ReadFile(templateFolder + "boldrow_1.tpl");
  654.             string boldrow_template_2 = tprocessor.ReadFile(templateFolder + "boldrow_2.tpl");
  655.  
  656.             Dictionary<int, string> results = new Dictionary<int, string>();
  657.             int maxResult_id = 0, result_id = 0;
  658.             bool outputFlag = true;
  659.  
  660.  
  661.             List<short> stocksForForm2RowList = new List<short>();
  662.  
  663.             // Индексы строк формы №1, которые будут выведены на печать
  664.             List<int> form1RowsIndexesList = new List<int>();
  665.  
  666.             for (int i = 0; i < _form1RowList.Count; i++)
  667.             {
  668.                 if (this.GetSum(0, i) > 0.0)
  669.                     form1RowsIndexesList.Add(i);
  670.             }
  671.  
  672.             //foreach (Form1Row form1Row in _form1RowList)
  673.             //{
  674.             //    int form1RowIndex = rd.Form1RowsList.IndexOf(form1Row);
  675.             //    if (this.GetSum(0, form1RowIndex, rd) > 0.0)
  676.             //        form1RowsIndexesList.Add(form1RowIndex);
  677.             //}
  678.  
  679.             // Формирование фрагментов документа производим в две итерации.
  680.             // 1-ая итерация: распределение площадей.
  681.             // 2-ая итерация: распределение запасов.
  682.             for (int iteration = 1; iteration <= 2; iteration++)
  683.             {
  684.                 int sheetNumber = 0;
  685.  
  686.                 for (int index = 0; index < form1RowsIndexesList.Count; index++)
  687.                 {
  688.                     int form1RowIndex = form1RowsIndexesList[index];
  689.                     Form1Row form1Row = _form1RowList[form1RowIndex];
  690.  
  691.                     // В заголовке листа выводим наименование строки формы + идентификатор группы лесов.
  692.                     tprocessor.Parameters["GROUP_NUMBER"].Value = form1Row.Form2_ForestGroupValue;
  693.                     tprocessor.Parameters["FORM1ROW_NAME"].Value = form1Row.Name;
  694.  
  695.                     System.Text.StringBuilder contentBuilder = new System.Text.StringBuilder();
  696.  
  697.                     sheetNumber++;
  698.                     tprocessor.Parameters["SHEET_NUMBER"].Value = sheetNumber.ToString();
  699.  
  700.                     #region Перебор строк формы №2
  701.  
  702.                     for (int form2RowIndex = 0; form2RowIndex < _form2RowList.Count; form2RowIndex++)
  703.                     {
  704.                         // Будем выводить в документ только те строки формы учета №2,
  705.                         // для которых есть соответствующая порода в списке _distinctStocksList.
  706.                         List<Stock> stockList = _form2RowList[form2RowIndex].GetStocks();
  707.  
  708.                         stocksForForm2RowList.Clear();
  709.  
  710.                         foreach (Stock stock in stockList)
  711.                             if (_distinctStocksList.Contains(stock.OID))
  712.                                 stocksForForm2RowList.Add(stock.OID);
  713.  
  714.                         if (stocksForForm2RowList.Count == 0)
  715.                             continue;
  716.  
  717.                         #region О свойстве PrintType...
  718.                         // Все строки формы учета №2 условно делим на 4 типа (свойство PrintType)
  719.  
  720.                         // 1 - "Раздел"
  721.                         // Выводится жирным шрифтом.
  722.                         // Заполняется только графа "А" с наименованием строки
  723.  
  724.                         // 2 - "Строка данных"
  725.                         // Заполняются все графы. Графа "В" (возраст рубки) заполняется,
  726.                         // только если признак вывода Form2_MinCuttingAgeFlag = true
  727.  
  728.                         // 3 - "Итоговая строка с последующим выводом пустой строки"
  729.                         // Заполняются все графы кроме графы "В"
  730.  
  731.                         // 4 - "Итоговая строка"
  732.                         // Заполняются все графы кроме графы "В"
  733.                         #endregion
  734.  
  735.                         // Вывод наименования строки в первой графе.
  736.                         tprocessor.Parameters["VALUE_A"].Value = _form2RowList[form2RowIndex].Name;
  737.  
  738.                         switch (_form2RowList[form2RowIndex].PrintType)
  739.                         {
  740.                             case 1:
  741.                                 tprocessor.Parameters["VALUE_B"].Value = null;
  742.                                 tprocessor.Parameters["VALUE_C"].Value = null;
  743.                                 if (iteration == 1)
  744.                                     contentBuilder.Append(tprocessor.ProcessString(boldrow_template_1));
  745.                                 else
  746.                                     contentBuilder.Append(tprocessor.ProcessString(boldrow_template_2));
  747.  
  748.                                 break;
  749.                             case 2:
  750.                                 tprocessor.Parameters["VALUE_B"].Value = _form2RowList[form2RowIndex].External_ID;
  751.                                 if (form1Row.Form2_MinCuttingAgeFlag == false)
  752.                                 {
  753.                                     outputFlag = this.SetTemplateParameters(tprocessor, iteration, form1RowIndex, stocksForForm2RowList, -1);
  754.                                     switch (iteration)
  755.                                     {
  756.                                         case 1:
  757.                                             if (outputFlag)
  758.                                                 contentBuilder.Append(tprocessor.ProcessString(row_template_1));
  759.                                             break;
  760.                                         case 2:
  761.                                             if (outputFlag)
  762.                                                 contentBuilder.Append(tprocessor.ProcessString(row_template_2));
  763.                                             break;
  764.                                     }
  765.                                 }
  766.                                 else
  767.                                 {
  768.                                     // Необходимо сгруппировать строки данных по возрастам рубки.
  769.                                     // Для строк данных (PrintType = 2) при правильном заполнении справочников
  770.                                     // список stocksForForm2RowList будет содержать единственный идентификатор породы.
  771.                                     if (stocksForForm2RowList.Count > 0)
  772.                                     {
  773.                                         int stock_index = _distinctStocksList.IndexOf(stocksForForm2RowList[0]);
  774.                                         List<short> cuttingAgesList = this.GetCuttingAges(form1RowIndex, stock_index);
  775.                                         foreach (short age in cuttingAgesList)
  776.                                         {
  777.                                             this.SetTemplateParameters(tprocessor, iteration, form1RowIndex, stocksForForm2RowList, _distinctCuttingAgesList.IndexOf(age));
  778.                                             if (iteration == 1)
  779.                                                 contentBuilder.Append(tprocessor.ProcessString(row_template_1));
  780.                                             else
  781.                                                 contentBuilder.Append(tprocessor.ProcessString(row_template_2));
  782.                                         }
  783.                                     }
  784.  
  785.                                 }
  786.                                 break;
  787.                             case 3:
  788.                             case 4:
  789.                                 tprocessor.Parameters["VALUE_B"].Value = _form2RowList[form2RowIndex].External_ID;
  790.                                 tprocessor.Parameters["VALUE_C"].Value = null;
  791.                                 outputFlag = this.SetTemplateParameters(tprocessor, iteration, form1RowIndex, stocksForForm2RowList, -1);
  792.                                 switch (iteration)
  793.                                 {
  794.                                     case 1:
  795.                                         if (outputFlag)
  796.                                             contentBuilder.Append(tprocessor.ProcessString(row_template_1));
  797.                                         break;
  798.                                     case 2:
  799.                                         if (outputFlag)
  800.                                             contentBuilder.Append(tprocessor.ProcessString(row_template_2));
  801.                                         break;
  802.                                 }
  803.                                 break;
  804.                         }
  805.  
  806.                         // Вывод пустой строки.
  807.                         if (_form2RowList[form2RowIndex].PrintType == 3)
  808.                         {
  809.                             tprocessor.Parameters["VALUE_A"].Value = null;
  810.                             tprocessor.Parameters["VALUE_B"].Value = null;
  811.                             tprocessor.Parameters["VALUE_C"].Value = null;
  812.  
  813.                             for (int p = 1; p <= 15; p++)
  814.                                 tprocessor.Parameters["VALUE_S" + p.ToString()].Value = null;
  815.  
  816.                             if (iteration == 1)
  817.                                 contentBuilder.Append(tprocessor.ProcessString(row_template_1));
  818.                             else
  819.                                 contentBuilder.Append(tprocessor.ProcessString(row_template_2));
  820.                         }
  821.                     }
  822.                     #endregion
  823.  
  824.                     tprocessor.Parameters["ROWS_CONTENT"].Value = contentBuilder.ToString();
  825.  
  826.                     string pageContent = String.Empty;
  827.  
  828.                     if (iteration == 1)
  829.                     {
  830.                         pageContent = tprocessor.ProcessString(header_template_1);
  831.                         result_id = 2 * sheetNumber - 1;
  832.                     }
  833.                     else
  834.                     {
  835.                         pageContent = tprocessor.ProcessString(header_template_2);
  836.                         result_id = 2 * sheetNumber;
  837.                         // Для всех четных страниц кроме последней в конец добавляем разрыв страницы.
  838.                         if (index + 1 != form1RowsIndexesList.Count)
  839.                             pageContent += tprocessor.Parameters["PAGE_BREAK"].Value;
  840.                     }
  841.  
  842.                     results.Add(result_id, pageContent);
  843.                     if (maxResult_id < result_id)
  844.                         maxResult_id = result_id;
  845.                 }
  846.             } // iteration
  847.  
  848.  
  849.             for (int id = 1; id <= maxResult_id; id++)
  850.             {
  851.                 tprocessor.Parameters["BODY_CONTENT"].Value += results[id];
  852.             }
  853.  
  854.             tprocessor.ProcessFileToStream(outputStream, templateFolder + "document.tpl");
  855.             #endregion
  856.         }
  857.  
  858.         private int GetProgress(int progressBase, int progress_counter, double progress_q)
  859.         {
  860.             return progressBase + (int)(progress_q * progress_counter);
  861.         }
  862.  
  863.         /// <summary>
  864.         /// Выполняет установку параметров шаблонизатора (TemplateProcessor), содержащих
  865.         /// значения строки формы №2 (графы А, Б, В, значения площадей и запасов).
  866.         /// Возвращает TRUE, если строку нужно вывести в результирующий документ и FALSE,
  867.         /// если вывод не требуется.
  868.         /// </summary>
  869.         /// <param name="templateProcessor">Шаблонизатор.</param>
  870.         /// <param name="iteration">Номер итерации (1 или 2)</param>
  871.         /// <param name="form1Row_index">Индекс строки формы учета №1</param>
  872.         /// <param name="stocks">Породы, соответствующие выводимой строке формы №2</param>
  873.         /// <param name="age_index">Индекс возраста рубки.</param>
  874.         /// <returns></returns>
  875.         private bool SetTemplateParameters(TemplateProcessor templateProcessor, int iteration, int form1Row_index, List<short> stocks, int age_index)
  876.         {
  877.             int min_index = iteration == 1 ? 0 : 8;
  878.             int max_index = iteration == 1 ? 7 : 14; // FIXME (графы №№16-17)
  879.             bool result = true;
  880.  
  881.  
  882.             if (age_index >= 0)
  883.             {
  884.                 if (_distinctCuttingAgesList[age_index] == 0) // выводим прочерк напротив записей, для которых нет соответствия в CuttingAges
  885.                     templateProcessor.Parameters["VALUE_C"].Value = "-";
  886.                 else
  887.                     templateProcessor.Parameters["VALUE_C"].Value = _distinctCuttingAgesList[age_index].ToString();
  888.             }
  889.             else
  890.                 templateProcessor.Parameters["VALUE_C"].Value = null;
  891.  
  892.             for (int columnIndex = min_index; columnIndex <= max_index; columnIndex++)
  893.             {
  894.                 double value = this.GetSum2(columnIndex, form1Row_index, age_index, stocks);
  895.  
  896.                 // Параметры не заполняются и строка не выводится,
  897.                 // если общая площадь (для первой итерации) или общий запас (для второй итерации)
  898.                 // равны нулю.
  899.  
  900.                 if (columnIndex == min_index && value == 0.0)
  901.                 {
  902.                     result = false;
  903.                     break;
  904.                 }
  905.  
  906.                 if (iteration == 2)
  907.                     value /= 1000; // Вывод запасов в тыс. кбм.
  908.  
  909.                 string param = String.Format("VALUE_S{0}", columnIndex + 1);
  910.                 if (value > 0)
  911.                 {
  912.                     templateProcessor.Parameters[param].Value = value;
  913.                 }
  914.                 else
  915.                 {
  916.                     templateProcessor.Parameters[param].Value = null;
  917.                 }
  918.             }
  919.  
  920.             return result;
  921.         }
  922.     }
  923. }
  924.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement