eLVik

SortimentStruct_ReportCreator

Dec 2nd, 2021
767
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Objects;
  4. using System.IO;
  5. using System.Linq;
  6. using GUTFIRK.ForestManagement.Domain;
  7. using GUTFIRK.ForestManagement.Domain.ModelEntities;
  8. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface;
  9. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsDescriptions.ForestFund;
  10. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsParams;
  11. using GUTFIRK.Utils;
  12. using GUTFIRK.Utils.TemplateSystem;
  13.  
  14. namespace GUTFIRK.ForestManagement.ReportService.ReportsCreators
  15. {
  16.     /// <summary>
  17.     /// Класс, созающий отчет "Сортиментная структура насаждений"
  18.     /// </summary>
  19.     public sealed class SortimentStruct_ReportCreator : SelectOptionsAdapter
  20.     {
  21.         #region Private members
  22.  
  23.         const short HEIGHTRANK_KEY = 1;
  24.         object _lockObject = new object();
  25.  
  26.         #endregion
  27.  
  28.         public SortimentStruct_ReportCreator()
  29.         {
  30.             _description = new SortimentStruct_ReportDescription();
  31.         }
  32.  
  33.         /// <summary>
  34.         /// Вспомогательный класс для передачи результатов расчетов
  35.         /// </summary>
  36.         public class SortimentStruct_ReportData
  37.         {
  38.             //Список значений
  39.             public Dictionary<short, SortimentCalculatorItem> Dictionary { get; set; }
  40.  
  41.             //Список пород
  42.             public List<Stock> StockList { get; set; }
  43.  
  44.             //Площадь
  45.             public double Area { get; set; }
  46.  
  47.             //Год актуализации
  48.             public short Year { get; set; }
  49.  
  50.             //Название отчета
  51.             public string ReportName { get; set; }
  52.         }
  53.  
  54.  
  55.         public override void CreateDocument(object obj, string formatKey, Procedure<int> progressCallback, string templateFolder, System.IO.Stream outputStream)
  56.         {
  57.             #region Создание документа
  58.             SortimentStruct_ReportData rd = (SortimentStruct_ReportData)obj;
  59.             TemplateProcessor tprocessor = new TemplateProcessor();
  60.             //templateFolder += _description.Key + "\\" + formatKey + "\\";
  61.             DateTime creationDateTime = DateTime.Now;
  62.             string emptyValue = formatKey == Program.HTML_FORMAT_KEY ? "&nbsp;" : String.Empty;
  63.  
  64.             tprocessor.Parameters.Add(new TemplateParameter("R_PROPERTY", tprocessor.ReadFile(templateFolder + "rproperty.tpl")));
  65.             tprocessor.Parameters.Add(new TemplateParameter("R_PROPERTY_2", tprocessor.ReadFile(templateFolder + "rproperty2.tpl")));
  66.             tprocessor.Parameters.Add(new TemplateParameter("R_PROPERTY_H", tprocessor.ReadFile(templateFolder + "rproperty_h.tpl")));
  67.             tprocessor.Parameters.Add(new TemplateParameter("PAGE_BREAK", tprocessor.ProcessFile(templateFolder + "pagebreak.tpl")));
  68.             tprocessor.Parameters.Add(new TemplateParameter("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)));
  69.             // Год учета лесного фонда - на единицу меньше года актуализации данных.
  70.             tprocessor.Parameters.Add(new TemplateParameter("YEAR", String.Format("{0}", rd.Year - 1)));
  71.             tprocessor.Parameters.Add(new TemplateParameter("DOCUMENT_CREATION_DATE", creationDateTime.ToShortDateString()));
  72.             tprocessor.Parameters.Add(new TemplateParameter("ROWS_CONTENT"));
  73.             tprocessor.Parameters.Add(new TemplateParameter("BODY_CONTENT"));
  74.             tprocessor.Parameters.Add(new NumberTemplateParameter("AREA", emptyValue, rd.Area));
  75.  
  76.             for (int i = 1; i <= 14; i++)
  77.             {
  78.                 tprocessor.Parameters.Add(new NumberTemplateParameter(String.Format("P{0}", i), emptyValue));
  79.                 tprocessor.Parameters.Add(new NumberTemplateParameter(String.Format("P{0}_P", i), emptyValue));
  80.             }
  81.  
  82.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter("REPORT_NAME", emptyValue, rd.ReportName));
  83.             tprocessor.Parameters.Add(new HtmlEncodedTemplateParameter("STOCK_NAME", emptyValue, rd.ReportName));
  84.  
  85.             short[] keys = new short[rd.Dictionary.Keys.Count];
  86.             rd.Dictionary.Keys.CopyTo(keys, 0);
  87.             double q = 0.0;
  88.  
  89.             // Суммирующий массив под итоговую строку
  90.             double[] sum = new double[15];
  91.  
  92.             // ПЕЧАТЬ ПЕРВОГО ЛИСТА
  93.             foreach (short key in keys)
  94.             {
  95.                 Stock stock = rd.StockList.First(a => a.OID == key);
  96.                 tprocessor.Parameters["STOCK_NAME"].Value = stock.Name;
  97.                 tprocessor.Parameters["P1"].Value = rd.Dictionary[key].PIL_12;
  98.                 tprocessor.Parameters["P2"].Value = rd.Dictionary[key].PIL_34;
  99.                 tprocessor.Parameters["P3"].Value = rd.Dictionary[key].PIL;
  100.                 tprocessor.Parameters["P4"].Value = rd.Dictionary[key].BAL_12;
  101.                 tprocessor.Parameters["P5"].Value = rd.Dictionary[key].BAL_34;
  102.                 tprocessor.Parameters["P6"].Value = rd.Dictionary[key].BAL;
  103.                 tprocessor.Parameters["P7"].Value = rd.Dictionary[key].DELOV;
  104.                 tprocessor.Parameters["P8"].Value = rd.Dictionary[key].TEX;
  105.                 tprocessor.Parameters["P9"].Value = rd.Dictionary[key].DROV;
  106.                 tprocessor.Parameters["P10"].Value = rd.Dictionary[key].OTX;
  107.                 tprocessor.Parameters["P11"].Value = rd.Dictionary[key].VSEGO;
  108.                 tprocessor.Parameters["P12"].Value = rd.Dictionary[key].SORT_PIL;
  109.                 tprocessor.Parameters["P13"].Value = rd.Dictionary[key].SORT_BAL;
  110.                 tprocessor.Parameters["P14"].Value = rd.Dictionary[key].SORT_FAN;
  111.  
  112.                 sum[1] += rd.Dictionary[key].PIL_12;
  113.                 sum[2] += rd.Dictionary[key].PIL_34;
  114.                 sum[3] += rd.Dictionary[key].PIL;
  115.                 sum[4] += rd.Dictionary[key].BAL_12;
  116.                 sum[5] += rd.Dictionary[key].BAL_34;
  117.                 sum[6] += rd.Dictionary[key].BAL;
  118.                 sum[7] += rd.Dictionary[key].DELOV;
  119.                 sum[8] += rd.Dictionary[key].TEX;
  120.                 sum[9] += rd.Dictionary[key].DROV;
  121.                 sum[10] += rd.Dictionary[key].OTX;
  122.                 sum[11] += rd.Dictionary[key].VSEGO;
  123.                 sum[12] += rd.Dictionary[key].SORT_PIL;
  124.                 sum[13] += rd.Dictionary[key].SORT_BAL;
  125.                 sum[14] += rd.Dictionary[key].SORT_FAN;
  126.  
  127.                 if (rd.Dictionary[key].VSEGO == 0.0)
  128.                     q = 0;
  129.                 else
  130.                     q = 100.0 / rd.Dictionary[key].VSEGO;
  131.  
  132.                 tprocessor.Parameters["P1_P"].Value = (q * rd.Dictionary[key].PIL_12);
  133.                 tprocessor.Parameters["P2_P"].Value = (q * rd.Dictionary[key].PIL_34);
  134.                 tprocessor.Parameters["P3_P"].Value = (q * rd.Dictionary[key].PIL);
  135.                 tprocessor.Parameters["P4_P"].Value = (q * rd.Dictionary[key].BAL_12);
  136.                 tprocessor.Parameters["P5_P"].Value = (q * rd.Dictionary[key].BAL_34);
  137.                 tprocessor.Parameters["P6_P"].Value = (q * rd.Dictionary[key].BAL);
  138.                 tprocessor.Parameters["P7_P"].Value = (q * rd.Dictionary[key].DELOV);
  139.                 tprocessor.Parameters["P8_P"].Value = (q * rd.Dictionary[key].TEX);
  140.                 tprocessor.Parameters["P9_P"].Value = (q * rd.Dictionary[key].DROV);
  141.                 tprocessor.Parameters["P10_P"].Value = (q * rd.Dictionary[key].OTX);
  142.                 tprocessor.Parameters["P12_P"].Value = (q * rd.Dictionary[key].SORT_PIL);
  143.                 tprocessor.Parameters["P13_P"].Value = (q * rd.Dictionary[key].SORT_BAL);
  144.                 tprocessor.Parameters["P14_P"].Value = (q * rd.Dictionary[key].SORT_FAN);
  145.  
  146.                 tprocessor.Parameters["ROWS_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "row1.tpl");
  147.             }
  148.  
  149.             // Итоговая строка
  150.             for (int i = 1; i <= 14; i++)
  151.             {
  152.                 string param_name = String.Format("P{0}", i);
  153.                 tprocessor.Parameters[param_name].Value = sum[i];
  154.                 sum[i] = 0.0;
  155.             }
  156.             tprocessor.Parameters["ROWS_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "row2.tpl");
  157.  
  158.             tprocessor.Parameters["BODY_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "header1.tpl");
  159.  
  160.             // ПЕЧАТЬ ВТОРОГО ЛИСТА
  161.  
  162.             tprocessor.Parameters["ROWS_CONTENT"].Value = String.Empty;
  163.  
  164.             foreach (short key in keys)
  165.             {
  166.                 Stock stock = rd.StockList.First(a => a.OID == key);
  167.                 tprocessor.Parameters["STOCK_NAME"].Value = stock.Name;
  168.                 tprocessor.Parameters["P1"].Value = rd.Dictionary[key].TEX_DR;
  169.                 tprocessor.Parameters["P2"].Value = rd.Dictionary[key].DROV_DR;
  170.                 tprocessor.Parameters["P3"].Value = rd.Dictionary[key].OTX_DR;
  171.                 tprocessor.Parameters["P4"].Value = rd.Dictionary[key].VSEGO_DR;
  172.  
  173.                 sum[1] += rd.Dictionary[key].TEX_DR;
  174.                 sum[2] += rd.Dictionary[key].DROV_DR;
  175.                 sum[3] += rd.Dictionary[key].OTX_DR;
  176.                 sum[4] += rd.Dictionary[key].VSEGO_DR;
  177.  
  178.                 if (rd.Dictionary[key].VSEGO_DR == 0.0)
  179.                     q = 0;
  180.                 else
  181.                     q = 100.0 / rd.Dictionary[key].VSEGO_DR;
  182.  
  183.                 tprocessor.Parameters["P1_P"].Value = (q * rd.Dictionary[key].TEX_DR);
  184.                 tprocessor.Parameters["P2_P"].Value = (q * rd.Dictionary[key].DROV_DR);
  185.                 tprocessor.Parameters["P3_P"].Value = (q * rd.Dictionary[key].OTX_DR);
  186.  
  187.                 tprocessor.Parameters["ROWS_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "row3.tpl");
  188.             }
  189.  
  190.             // Итоговая строка
  191.             tprocessor.Parameters["P1"].Value = sum[1];
  192.             tprocessor.Parameters["P2"].Value = sum[2];
  193.             tprocessor.Parameters["P3"].Value = sum[3];
  194.             tprocessor.Parameters["P4"].Value = sum[4];
  195.             tprocessor.Parameters["ROWS_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "row4.tpl");
  196.  
  197.             tprocessor.Parameters["BODY_CONTENT"].Value += tprocessor.ProcessFile(templateFolder + "header2.tpl");
  198.  
  199.             tprocessor.ProcessFileToStream(outputStream, templateFolder + "document.tpl");
  200.  
  201.             #endregion
  202.         }
  203.  
  204.         public override object DoCalculations(IReportParams _reportParams, Procedure<int> progressCallback)
  205.         {
  206.             CheckParams(_reportParams);
  207.             #region Переменные
  208.             var reportParams = (ForestResourcesReportParams)_reportParams;// as ForestResourcesReportParams;
  209.             var year = (short)reportParams.SelectOptions.YearOfActualization;
  210.             SortimentStruct_ReportData reportData = new SortimentStruct_ReportData();
  211.             List<NormativeAssociation> _normativeAssociationList = null;
  212.             Dictionary<short, SortimentCalculatorItem> _dictionary = new Dictionary<short, SortimentCalculatorItem>();
  213.             List<Stock> _stockList = new List<Stock>();
  214.             double _area = 0.0;
  215.  
  216.             // Переменные для вызова callback-метода, отвечающего за вывод прогресса.
  217.             var qIDs = GetQuarterIDs(reportParams.SelectOptions);
  218.             var fullQuarterIds = GetFullQuarterIDs(reportParams.SelectOptions);
  219.             double _progress_q = 90.0 / qIDs.Count;  // множитель
  220.             int _progress_counter = 0; // счетчик
  221.  
  222.             #endregion
  223.             using (ModelContext context = new ModelContext())
  224.             {
  225.                 _normativeAssociationList = context.NormativeAssociationSet.Where("it.Year = @year", new ObjectParameter("year", year)).Include("NormativeData").Include("Forestry").ToList<NormativeAssociation>();
  226.  
  227.                 foreach (var quarterID in qIDs)
  228.                 {
  229.                     #region Callback
  230.                     _progress_counter++;
  231.                     progressCallback(Convert.ToInt32(_progress_counter * _progress_q));
  232.                     #endregion
  233.  
  234.                     var quarter = context.QuarterSet.Include("DivisionalForestry.Forestry").FirstOrDefault(x => x.OID == quarterID);
  235.                     if (quarter == null)
  236.                         continue;
  237.  
  238.                     List<int> sortedIdentifiers = null;
  239.                     if (fullQuarterIds.BinarySearch(quarterID) >= 0)
  240.                     {
  241.                         quarter.Stratums.Load();
  242.                         sortedIdentifiers = quarter.Stratums.Select(x => x.OID).ToList();
  243.                     }
  244.                     else
  245.                     {
  246.                         sortedIdentifiers = GetStratumIDsFromPartialQuarter(reportParams.SelectOptions, quarterID);
  247.                     }
  248.                     sortedIdentifiers.Sort();
  249.  
  250.                     NormativeAssociation na = _normativeAssociationList.Where<NormativeAssociation>(a => a.Forestry.OID == quarter.GetForestry().OID).First();
  251.                     // Ошибка может возникнуть в случае, если лесничеству не сопоставлен набор НСИ в указанный год.
  252.                     if (na == null)
  253.                         throw new ReportException(reportParams, String.Format("Отсутствует набор НСИ для квартала (OID = {0})", quarter.OID));
  254.  
  255.                     #region Выполнение хранимых процедур и обработка ошибок
  256.                     List<vw_QuarterAgeDataItem> vw_AgeDataResult = null; //Список возрастных характеристик
  257.                     List<vw_QuarterSortimentItem> vw_SortimentResult = null; //Список распределений сортиментов
  258.  
  259.                     // Блокировка вызова хранимых процедур
  260.                     lock (_lockObject)
  261.                     {
  262.                         int counter = 0;
  263.                         bool success = false;
  264.  
  265.                         //Попытка выполнить хранимые процедуры
  266.                         while (!success)
  267.                         {
  268.                             try
  269.                             {
  270.                                 counter++; // Увеличиваем значение счетчика
  271.                                 // Получаем возрастные характеристики на квартал.
  272.                                 vw_AgeDataResult = context.GetMainStockAgeDataOnQuarter(quarter.OID, na.NormativeData.OID, na.CuttingAgeKey, year).ToList();
  273.  
  274.                                 // Получаем распределение сортиментов на квартал
  275.                                 vw_SortimentResult = context.GetSortimentItemOnQuarter(quarter.OID, na.Year, na.CommodityTableKey, HEIGHTRANK_KEY).ToList();
  276.                                 success = true; // Выполнение хранимой процедуры успешно
  277.                             }
  278.                             // В случае ошибки выполнения хранимой процедуры 10 раз подряд останавливаем формирование отчета
  279.                             catch
  280.                             {
  281.                                 if (counter >= 10) break;
  282.                             }
  283.                         }
  284.                         if (!success) throw new ReportException(reportParams, "Ошибка доступа к хранимой процедуре");
  285.                     }
  286.                     #endregion
  287.  
  288.                     // Список таксационных характеристик
  289.                     List<TaxData> taxDataList = quarter.GetTaxDataList(context, year);
  290.  
  291.                     // Общие характеристики на квартал
  292.                     List<CommonData> commonDataList = quarter.GetCommonDataList(context, na.Year);
  293.  
  294.                     foreach (vw_QuarterAgeDataItem ageDataItem in vw_AgeDataResult)
  295.                     {
  296.                         // 0 в ReturnCode - все поля заполнены
  297.                         // Рассматриваем только покрытые лесом земли, возможные для эксплуатации (с возрастом главной породы, превышающим возраст рубки) относящиеся к спелым и перестойным лесам
  298.  
  299.                         // TODO: Добавить поддержку приспевающих
  300.  
  301.                         //if (ageDataItem.ReturnCode.HasValue && ageDataItem.ReturnCode.Value == 0 && ageDataItem.IsExploitable.Value == true && ageDataItem.Age.Value >= ageDataItem.CuttingAge.Value)
  302.                         if (context.BinarySearch(sortedIdentifiers, Convert.ToInt32(ageDataItem.Stratum_OID)))
  303.                         {
  304.                             if (ageDataItem.ReturnCode.HasValue && ageDataItem.ReturnCode.Value == 0 && ageDataItem.IsExploitable.Value == true && ageDataItem.AgeGroup_OID.Value >= 4)
  305.                             {
  306.                                 CommonData commonData = commonDataList.First(a => a.OID == ageDataItem.CommonData_OID);
  307.                                 //List<CommonData> _commonDataList = commonDataList.Where(a=>a.GetStratum().OID == ageDataItem.Stratum_OID).ToList();
  308.                                 //foreach (CommonData commonData in _commonDataList)
  309.                                 //{
  310.                                 _area += commonData.Area;
  311.  
  312.                                 List<TaxData> tax_list = new List<TaxData>();
  313.                                 tax_list = taxDataList.Where(a => a.GetCommonData().OID == commonData.OID).ToList();
  314.  
  315.                                 foreach (TaxData taxData in tax_list)
  316.                                 {
  317.                                     if (taxData.Volume == 0.0 || taxData.Stock == null)
  318.                                     {
  319.                                         //   context.Detach(taxData);
  320.                                         continue;
  321.                                     }
  322.  
  323.                                     // элемент сортиментной таблицы
  324.                                     vw_QuarterSortimentItem sortimentItem = vw_SortimentResult.First(a => a.TaxData_OID == taxData.OID);
  325.                                     if (sortimentItem == null || sortimentItem.ReturnCode.Value != 0)
  326.                                     {
  327.                                         //  context.Detach(taxData);
  328.                                         continue;
  329.                                     }
  330.  
  331.                                     short stock_oid = sortimentItem.SortimentStock_OID.Value;
  332.  
  333.                                     if (_dictionary.ContainsKey(stock_oid) == false)
  334.                                     {
  335.                                         _dictionary.Add(stock_oid, new SortimentCalculatorItem());
  336.                                         object stockObj = context.GetObjectByKey(EdmUtils.CreateEntityKey(context, "Stock", stock_oid));
  337.                                         _stockList.Add((Stock)stockObj);
  338.                                     }
  339.  
  340.                                     _dictionary[stock_oid].PIL_12 += sortimentItem.PIL_12;
  341.                                     _dictionary[stock_oid].PIL_34 += sortimentItem.PIL_34;
  342.                                     _dictionary[stock_oid].BAL_12 += sortimentItem.BAL_12;
  343.                                     _dictionary[stock_oid].BAL_34 += sortimentItem.BAL_34;
  344.                                     _dictionary[stock_oid].TEX += sortimentItem.TEX;
  345.                                     _dictionary[stock_oid].DROV += sortimentItem.DROV;
  346.                                     _dictionary[stock_oid].OTX += sortimentItem.OTX;
  347.                                     _dictionary[stock_oid].SORT_BAL += sortimentItem.SORT_BAL;
  348.                                     _dictionary[stock_oid].SORT_FAN += sortimentItem.SORT_FAN;
  349.                                     _dictionary[stock_oid].SORT_PIL += sortimentItem.SORT_PIL;
  350.                                     _dictionary[stock_oid].TEX_DR += sortimentItem.TEX_DR;
  351.                                     _dictionary[stock_oid].DROV_DR += sortimentItem.DROV_DR;
  352.                                     _dictionary[stock_oid].OTX_DR += sortimentItem.OTX_DR;
  353.  
  354.                                     //context.Detach(taxData);
  355.                                 }
  356.  
  357.                                 //}
  358.                             }
  359.                         }
  360.                     }
  361.  
  362.                     #region Detaching
  363.                     foreach (TaxData taxData in taxDataList)
  364.                         context.Detach(taxData);
  365.  
  366.                     foreach (CommonData commonData in commonDataList)
  367.                         context.Detach(commonData);
  368.  
  369.                     foreach (vw_QuarterAgeDataItem ageDataItem in vw_AgeDataResult)
  370.                         context.Detach(ageDataItem);
  371.  
  372.                     foreach (vw_QuarterSortimentItem sortimentItem in vw_SortimentResult)
  373.                         context.Detach(sortimentItem);
  374.  
  375.                     context.Detach(quarter);
  376.                     #endregion
  377.                 }
  378.             }
  379.  
  380.             #region Проверка заполнения и передача значений внутреннего класса
  381.             if (_dictionary.Keys.Count == 0)
  382.                 throw new ReportException(reportParams, "Отсутствует содержание отчета.");
  383.  
  384.             if (_area == 0.0)
  385.                 throw new ReportException(reportParams, "Площадь равна нулю.");
  386.  
  387.             reportData.ReportName = reportParams.Name;
  388.             reportData.Year = year;
  389.             reportData.Dictionary = _dictionary;
  390.             reportData.StockList = _stockList;
  391.             reportData.Area = _area;
  392.             #endregion
  393.  
  394.             return reportData;
  395.         }
  396.     }
  397. }
  398.  
RAW Paste Data