Advertisement
Valik888

Untitled

Jan 26th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 98.43 KB | None | 0 0
  1. CREATE OR REPLACE PROCEDURE Nachislenie(AccID k_Accounts.ID%TYPE, Data_Start n_Accruals.Data%TYPE, Prm NUMBER)
  2. -- Начисление для Л/С начиная с указанной даты.
  3. AS
  4.   DebugModeEnabled CONSTANT BOOLEAN := FALSE;
  5.  
  6.   -- Начисления и сверки.
  7.   TYPE TAccrual IS RECORD (
  8.     Data n_Accruals.Data%TYPE,
  9.     Vid n_Accruals.Vid%TYPE,
  10.     Service_ID n_Accruals.Service_ID%TYPE,
  11.     Privil_ID n_Accruals.Privil_ID%TYPE,
  12.     Peopl_ID n_Accruals.Peopl_ID%TYPE,
  13.     Volume NUMBER,
  14.     Summ NUMBER,                
  15.     Dotacya NUMBER,
  16.     Volume100 NUMBER,
  17.     Tarif NUMBER);
  18.   TYPE TAccruals IS TABLE OF TAccrual INDEX BY BINARY_INTEGER;
  19.   Accruals TAccruals;
  20.   AccrualNo BINARY_INTEGER;
  21.   SverkaNo BINARY_INTEGER;
  22.  
  23.   -- Льготы.
  24.   TYPE TPrivil IS RECORD (
  25.     Privil_ID n_AccountPrivil.Privil_ID%TYPE,
  26.     Peopl_ID n_AccountPrivil.Peopl_ID%TYPE,
  27.     Count_Prvl n_AccountPrivil.Count_Prvl%TYPE);
  28.   tmpPrivil TPrivil;
  29.   TYPE TPrivils IS TABLE OF TPrivil INDEX BY BINARY_INTEGER;
  30.   Privils TPrivils; -- Список льгот у Л/С.  
  31.   SortedPrivils TPrivils; -- Список льгот, отсортированных по % на нужную услугу.
  32.   PrivilNo BINARY_INTEGER;    
  33.   -- Услуги.
  34.   TYPE TService IS RECORD (Formula spr_Services.Formula%TYPE, Params n_AccountService.Params%TYPE, Norm_ID n_AccountService.Norm_ID%TYPE, State_Srv n_HouseService.State_Srv%TYPE);
  35.   TYPE TServices IS TABLE OF TService INDEX BY BINARY_INTEGER;
  36.   Services TServices;
  37.   -- Нормы.
  38.   TYPE TNorm IS RECORD (Norm spr_Norms.Norm%TYPE, Norm_Social spr_Norms.Norm_Social%TYPE, Norm_Slave_Persons spr_Norms.Norm_Slave_Persons%TYPE, Period spr_Norms.Period%TYPE);
  39.   TYPE TNorms IS TABLE OF TNorm INDEX BY BINARY_INTEGER;
  40.   Norms TNorms;
  41.   -- Тарифы общие и домовые.
  42.   TYPE TTarif IS RECORD (Tarif spr_Tarifs.Tarif%TYPE, Dotacya spr_Tarifs.Dotacya%TYPE);
  43.   TYPE TTarifs IS TABLE OF TTarif INDEX BY BINARY_INTEGER;
  44.   Tarifs TTarifs;
  45.   TarifsH TTarifs;    
  46.   -- Тарифы на электричество.
  47.   TYPE TTarifE IS RECORD (SrvNorm_ID NUMBER, Data DATE, Data_End DATE, Volume_Min NUMBER, Volume_Max NUMBER, Tarif NUMBER);
  48.   TYPE TTarifsE IS TABLE OF TTarifE INDEX BY BINARY_INTEGER;
  49.   TarifsE TTarifsE;  
  50.   -- Проценты льгот по услугам.
  51.   TYPE TPrvlSrvPrc IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
  52.   PrvlSrvPrc  TPrvlSrvPrc;
  53.   -- Количество дней отключения тепла в месяце.
  54.   TYPE TNoHeatDaysCount IS RECORD (NoHeatDays NUMBER, DaysInMonth NUMBER);
  55.   TYPE TNoHeatDaysCounts IS TABLE OF TNoHeatDaysCount INDEX BY BINARY_INTEGER;
  56.   NoHeatDaysCounts TNoHeatDaysCounts;
  57.   -- Процент уменьшения отопительной площади.
  58.   TYPE THeatedAreaDecreasePercent IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
  59.   HeatedAreaDecreasePercent THeatedAreaDecreasePercent;
  60.   -- Понижающие коэффициенты услуг (временные отключения, некачественные услуги, 10% скидка ГИОЦ и т.п.):
  61.   TYPE TKoeff IS RECORD (MONTH n_Koeffs.Month%TYPE, Service_ID n_Koeffs.Service_ID%TYPE, Koeff n_Koeffs.Koeff%TYPE, Vid n_Koeffs.Vid%TYPE);
  62.   TYPE TKoeffs IS TABLE OF TKoeff INDEX BY BINARY_INTEGER;
  63.   Koeffs TKoeffs;
  64.  
  65.   -- Переменные.
  66.   tmp_data DATE;
  67.   tmp_data2 DATE;
  68.   tmp_numb NUMBER;
  69.   tmp_numb2 NUMBER;
  70.   tmp_numb3 NUMBER;
  71.   FinMonth      DATE;
  72.   Data_Beg_Nach DATE;
  73.   Data_End_Nach DATE;
  74.   Data_Prev     DATE;
  75.   Month_Part NUMBER;
  76.   CurrMonthNach DATE;
  77.   DayInMonthNach INTEGER;
  78.   Privil_ID spr_PrivilPrc.Privil_ID%TYPE;
  79.   AccrualNo2    BINARY_INTEGER;
  80.   PrvlSrvPrcNo  BINARY_INTEGER;
  81.   ServiceNo     BINARY_INTEGER;
  82.  
  83.   NormNo        BINARY_INTEGER;
  84.   NachislenyaNo BINARY_INTEGER;
  85.   Volume_Nach    NUMBER;
  86.   Volume_Social_Nach NUMBER;
  87.   Summ_Nach      NUMBER;
  88.   Volume_Prvl    NUMBER;
  89.   Volume_Prvl100 NUMBER;
  90.   Dotac          NUMBER;
  91.   Summ_Prvl      NUMBER;
  92.   Area_Izl       NUMBER;
  93.   AddSanCharged NUMBER(1,0);
  94.   Hs_ID      k_House.ID%TYPE;
  95.   Category   k_House.Category%TYPE := 0;
  96.   AccountState  k_Accounts.Status_ID%TYPE := 0;
  97.   Area_Polezn   k_Accounts.Area_Polezn%TYPE := 0;
  98.   Area_Obsch    k_Accounts.Area_Polezn%TYPE := 0;
  99.   Area_Gilay    k_Accounts.Area_Gilay%TYPE := 0;
  100.   Area_AddSan   k_Accounts.Area_AddSan%TYPE := 0;
  101.   Count_Inhabit k_Accounts.Count_Inhabit%TYPE := 0;
  102.   Count_Wanting k_Accounts.Count_Wanting%TYPE := 0;
  103.   ShortFamily   k_Accounts.ShortFamily%TYPE := 'N';
  104.   Surplus       k_Accounts.Surplus%TYPE := 'N';
  105.   Cgv           k_Accounts.Cgv%TYPE := 'N';
  106.   LInhabit     NUMBER;
  107.   LInhabitRest NUMBER;
  108.   LVolumeRest  NUMBER;
  109.   IsCounter BOOLEAN;  
  110.   Curr_Tarif NUMBER;
  111.   Old_SverkaSumm n_ConfirmSverka.Summ%TYPE;
  112.   New_SverkaSumm n_ConfirmSverka.Summ%TYPE;
  113.   LoggedUserID Users.ID%TYPE;
  114.   DataChangeRow DATE;
  115.   NoNachisl System.NoNachisl%TYPE;
  116.    
  117.   -- Информация о состоянии счетчиков.
  118.   TYPE TCAccount IS TABLE OF c_Account%ROWTYPE INDEX BY BINARY_INTEGER;
  119.   CAccount TCAccount;
  120.   -- Начисленый по счетчикам объем.
  121.   TYPE TIndication IS RECORD (
  122.     ServiceID NUMBER,
  123.     MONTH DATE,
  124.     Volume NUMBER,
  125.     Data_prev DATE,
  126.     Data_curr DATE,
  127.     Vid_prev NUMBER(1,0));
  128.   TYPE TIndications IS TABLE OF TIndication INDEX BY BINARY_INTEGER;
  129.   Indications TIndications;
  130.   IndicationNo BINARY_INTEGER;
  131.   IndicationNo2 BINARY_INTEGER;  
  132.   TarifENo NUMBER;
  133.   Prcnt NUMBER;
  134.   Indication_No NUMBER;                                
  135.   Indication_Part NUMBER;
  136.   Indication_KolDay NUMBER;                
  137.   Indication_KolDayOut NUMBER;
  138.   LastDayInCurrDiapason DATE;
  139.   MonthNach_Sch DATE;
  140.   Volume_Nach_Sch NUMBER;
  141.   Summ_Nach_Sch   NUMBER;
  142.   LVolumeRest_Sch NUMBER;
  143.  
  144.   AccrualsDescription27Str LONG := '';
  145.  
  146.   PROCEDURE print(str VARCHAR2)
  147.   AS
  148.   BEGIN
  149.     IF DebugModeEnabled THEN
  150.       DBMS_OUTPUT.put_line(CHR(9)||str);
  151.     END IF;
  152.   END;
  153.  
  154.   PROCEDURE AccrualsDescription27(str VARCHAR2)
  155.   AS
  156.   BEGIN
  157.     AccrualsDescription27Str := AccrualsDescription27Str || str || CHR(13)||CHR(10);    
  158.   END;
  159.  
  160.   FUNCTION ServiceIsCounter(Service_ID spr_Services.ID%TYPE) RETURN BOOLEAN
  161.   AS
  162.   BEGIN
  163.     RETURN Service_ID IN (
  164.       10, -- Электроэнергия.
  165.       25, -- Газ.
  166.       44, -- Отопление.
  167.       28, -- Хол. вода.
  168.       35, -- Гор. вода.
  169.       53  -- Водоотведение гор. воды.
  170.     );
  171.   END ServiceIsCounter;
  172.  
  173.   FUNCTION GetAccrualNo(AddNewRow BOOLEAN, Data n_Accruals.Data%TYPE, Vid n_Accruals.Vid%TYPE, Service_ID n_Accruals.Service_ID%TYPE, Privil_ID n_Accruals.Privil_ID%TYPE, Peopl_ID n_Accruals.Peopl_ID%TYPE) RETURN BINARY_INTEGER
  174.   AS
  175.     i BINARY_INTEGER;
  176.     Result BINARY_INTEGER := NULL;
  177.   BEGIN
  178.     i := Accruals.FIRST;
  179.     WHILE i IS NOT NULL LOOP
  180.       IF (Accruals(i).Data = Data) AND (Accruals(i).Vid = Vid) AND (Accruals(i).Service_ID = Service_ID) AND (NVL(Accruals(i).Privil_ID,0) = NVL(Privil_ID,0)) AND (NVL(Accruals(i).Peopl_ID,0) = NVL(Peopl_ID,0)) THEN
  181.         Result := i;
  182.         EXIT;
  183.       END IF;
  184.       i := Accruals.NEXT(i);
  185.     END LOOP;
  186.     IF Result IS NULL AND AddNewRow THEN
  187.       Result := NVL(Accruals.LAST,0) + 1;
  188.       Accruals(Result).Data := Data;
  189.       Accruals(Result).Vid := Vid;
  190.       Accruals(Result).Service_ID := Service_ID;
  191.       Accruals(Result).Privil_ID := Privil_ID;
  192.       Accruals(Result).Peopl_ID := Peopl_ID;
  193.       Accruals(Result).Volume := 0;
  194.       IF Vid IN (2,4) THEN Accruals(Result).Volume100 := 0; ELSE Accruals(Result).Volume100 := NULL; END IF;
  195.       Accruals(Result).Summ := 0;
  196.       Accruals(Result).Dotacya := 0;
  197.     END IF;
  198.     RETURN Result;
  199.   END GetAccrualNo;
  200.  
  201.   FUNCTION GetIndicationNo(ServiceID NUMBER, MONTH DATE, Data_prev DATE, Data_curr DATE, Vid_prev NUMBER) RETURN BINARY_INTEGER
  202.   AS
  203.     i BINARY_INTEGER;
  204.     PROCEDURE RaiseError(ErrMsg VARCHAR2)
  205.     AS
  206.       adres VARCHAR2(1000);
  207.     BEGIN
  208.       SELECT Street_Name||', '||House_FullNomer||', '||Apart_FullNomer INTO adres FROM vw_adresa WHERE Account_ID = LPAD(AccID, 12, '0');
  209.       RAISE_APPLICATION_ERROR(-20100, adres||' (ID='||AccID||'): '||ErrMsg);
  210.     END;
  211.   BEGIN        
  212.     i := Indications.FIRST;
  213.     WHILE i IS NOT NULL LOOP
  214.       IF Indications(i).ServiceID = ServiceID THEN
  215.         IF Data_prev = Indications(i).Data_prev AND Data_curr = Indications(i).Data_curr THEN
  216.           IF Indications(i).MONTH = MONTH THEN
  217.             RETURN i;
  218.           ELSE
  219.             RaiseError('покази лiчильникiв з дiапазоном дат ['||Data_prev||' - '||Data_curr||'] мають рiзнi дати внесення: '||Indications(i).MONTH||' та '||MONTH||'!');
  220.           END IF;
  221.         ELSE
  222.           IF Data_prev < Indications(i).Data_curr AND Data_curr > Indications(i).Data_prev THEN
  223.             RaiseError('у показах лiчильникiв перетинаються дiапазони дат: ['||Indications(i).Data_prev||' - '||Indications(i).Data_curr||'] та ['||Data_prev||' - '||Data_curr||']!');
  224.           END IF;  
  225.         END IF;
  226.       END IF;
  227.       i := Indications.NEXT(i);
  228.     END LOOP;
  229.     IF i IS NULL THEN
  230.       i := NVL(Indications.LAST,0) + 1;
  231.       Indications(i).ServiceID := ServiceID;
  232.       Indications(i).MONTH := MONTH;
  233.       Indications(i).Volume := 0;
  234.       Indications(i).Data_prev := Data_prev;
  235.       Indications(i).Data_curr := Data_curr;
  236.       Indications(i).Vid_prev := Vid_prev;
  237.       RETURN i;
  238.     END IF;    
  239.   END GetIndicationNo;
  240.  
  241.   PROCEDURE AddAccrual(AccrualNo BINARY_INTEGER, Volume NUMBER, Summ NUMBER, Dotacya NUMBER, Volume100 NUMBER)
  242.   AS
  243.   BEGIN
  244.     Accruals(AccrualNo).Volume := Accruals(AccrualNo).Volume + Volume;
  245.     Accruals(AccrualNo).Summ := Accruals(AccrualNo).Summ + Summ;
  246.     Accruals(AccrualNo).Dotacya := Accruals(AccrualNo).Dotacya + Dotacya;
  247.     Accruals(AccrualNo).Volume100 := Accruals(AccrualNo).Volume100 + Volume100;
  248.   END AddAccrual;
  249.  
  250.   PROCEDURE UpdateAccrual(
  251.     Param /*ROWID<>NULL: 1-Values only, 2-rValues only, 3-all values; ROWID=NULL: 5-Update values, 6-Add values*/ NUMBER,
  252.     RID ROWID, Account_ID n_Accruals.Account_ID%TYPE, Data n_Accruals.Data%TYPE, Vid n_Accruals.Vid%TYPE, Service_ID n_Accruals.Service_ID%TYPE, Privil_ID n_Accruals.Privil_ID%TYPE, Peopl_ID n_Accruals.Peopl_ID%TYPE,
  253.     Volume n_Accruals.Volume%TYPE, Summ n_Accruals.Summ%TYPE, Dotacya n_Accruals.Dotacya%TYPE, Volume100 n_Accruals.Volume100%TYPE, DataBegRevis n_Accruals.DataBegRevis%TYPE, Tarif n_Accruals.Tarif%TYPE,  
  254.     RVolume n_Accruals.RVolume%TYPE, RSumm n_Accruals.RSumm%TYPE, RDotacya n_Accruals.RDotacya%TYPE, RVolume100 n_Accruals.RVolume100%TYPE)    
  255.   AS
  256.   BEGIN
  257.     IF RID IS NULL THEN
  258.       IF Param    = 5 THEN
  259.         UPDATE n_Accruals SET
  260.           Volume = UpdateAccrual.Volume, Summ = UpdateAccrual.Summ, Dotacya = UpdateAccrual.Dotacya, Volume100 = UpdateAccrual.Volume100, DataBegRevis = UpdateAccrual.DataBegRevis, ByHouseCounter = NULL, Tarif = UpdateAccrual.Tarif,
  261.           RVolume = UpdateAccrual.RVolume, RSumm = UpdateAccrual.RSumm, RDotacya = UpdateAccrual.RDotacya, RVolume100 = UpdateAccrual.RVolume100,
  262.           UserID = LoggedUserID, DataChange = DataChangeRow
  263.         WHERE Account_ID = UpdateAccrual.Account_ID
  264.           AND Data = UpdateAccrual.Data
  265.           AND Vid = UpdateAccrual.Vid
  266.           AND Service_ID = UpdateAccrual.Service_ID
  267.           AND NVL(Privil_ID,0) = NVL(UpdateAccrual.Privil_ID,0)
  268.           AND NVL(Peopl_ID,0) = NVL(UpdateAccrual.Peopl_ID,0);
  269.       ELSIF Param = 6 THEN
  270.         UPDATE n_Accruals SET
  271.           Volume = Volume + UpdateAccrual.Volume, Summ = Summ + UpdateAccrual.Summ, Dotacya = Dotacya + UpdateAccrual.Dotacya, Volume100 = Volume100 + UpdateAccrual.Volume100, DataBegRevis = UpdateAccrual.DataBegRevis,  
  272.           RVolume = RVolume + UpdateAccrual.RVolume, RSumm = RSumm + UpdateAccrual.RSumm, RDotacya = RDotacya + UpdateAccrual.RDotacya, RVolume100 = RVolume100 + UpdateAccrual.RVolume100,
  273.           UserID = LoggedUserID, DataChange = DataChangeRow
  274.         WHERE Account_ID = UpdateAccrual.Account_ID
  275.           AND Data = UpdateAccrual.Data
  276.           AND Vid = UpdateAccrual.Vid
  277.           AND Service_ID = UpdateAccrual.Service_ID
  278.           AND NVL(Privil_ID,0) = NVL(UpdateAccrual.Privil_ID,0)
  279.           AND NVL(Peopl_ID,0) = NVL(UpdateAccrual.Peopl_ID,0);
  280.       END IF;
  281.       IF SQL%NOTFOUND THEN
  282.         IF NVL(Volume,0) <> 0 OR NVL(Summ,0) <> 0 OR NVL(Dotacya,0) <> 0 OR NVL(Volume100,0) <> 0 OR
  283.            NVL(RVolume,0) <> 0 OR NVL(RSumm,0) <> 0 OR NVL(RDotacya,0) <> 0 OR NVL(RVolume100,0) <> 0 OR
  284.            (ServiceIsCounter(Service_ID) AND Vid = 1 AND Data = FinMonth) -- нулевое показание в отчетном месяце по счетчику (может быть, если услуга включена, а показаний еще не было).  
  285.         THEN    
  286.           INSERT
  287.             INTO n_Accruals (
  288.               ID, Account_ID, Data, Vid, Service_ID, Privil_ID, Peopl_ID,
  289.               Volume, Summ, Dotacya, Volume100, DataBegRevis, ByHouseCounter, Tarif,
  290.               RVolume, RSumm, RDotacya, RVolume100,
  291.               UserID, DataChange)    
  292.             VALUES (
  293.               sAccruals.NEXTVAL, Account_ID, Data, Vid, Service_ID, Privil_ID, Peopl_ID,
  294.               Volume, Summ, Dotacya, Volume100, DataBegRevis, NULL, Tarif,
  295.               RVolume, RSumm, RDotacya, RVolume100,
  296.               LoggedUserID, DataChangeRow);
  297.         END IF;    
  298.       END IF;
  299.     ELSE
  300.       IF Param    = 1 THEN
  301.         UPDATE n_Accruals SET
  302.           Volume = UpdateAccrual.Volume, Summ = UpdateAccrual.Summ, Dotacya = UpdateAccrual.Dotacya, Volume100 = UpdateAccrual.Volume100, DataBegRevis = UpdateAccrual.DataBegRevis, ByHouseCounter = NULL, Tarif = UpdateAccrual.Tarif,
  303.           UserID = LoggedUserID, DataChange = DataChangeRow
  304.         WHERE ROWID = UpdateAccrual.RID;
  305.       ELSIF Param = 2 THEN
  306.         UPDATE n_Accruals SET
  307.           RVolume = UpdateAccrual.RVolume, RSumm = UpdateAccrual.RSumm, RDotacya = UpdateAccrual.RDotacya, RVolume100 = UpdateAccrual.RVolume100,    
  308.           UserID = LoggedUserID, DataChange = DataChangeRow
  309.         WHERE ROWID = UpdateAccrual.RID;
  310.       ELSIF Param = 3 THEN
  311.         UPDATE n_Accruals SET
  312.           Volume = UpdateAccrual.Volume, Summ = UpdateAccrual.Summ, Dotacya = UpdateAccrual.Dotacya, Volume100 = UpdateAccrual.Volume100, DataBegRevis = UpdateAccrual.DataBegRevis, ByHouseCounter = NULL, Tarif = UpdateAccrual.Tarif,
  313.           RVolume = UpdateAccrual.RVolume, RSumm = UpdateAccrual.RSumm, RDotacya = UpdateAccrual.RDotacya, RVolume100 = UpdateAccrual.RVolume100,    
  314.           UserID = LoggedUserID, DataChange = DataChangeRow
  315.         WHERE ROWID = UpdateAccrual.RID;
  316.       END IF;
  317.     END IF;
  318.   END UpdateAccrual;
  319.  
  320.   FUNCTION GetPrivilNo(AddNewRow BOOLEAN, Privil_ID n_AccountPrivil.Privil_ID%TYPE, Peopl_ID n_AccountPrivil.Peopl_ID%TYPE) RETURN BINARY_INTEGER
  321.   AS
  322.     i BINARY_INTEGER;
  323.     Result BINARY_INTEGER := NULL;
  324.   BEGIN
  325.     i := Privils.FIRST;
  326.     WHILE i IS NOT NULL LOOP
  327.       IF (Privils(i).Privil_ID = Privil_ID) AND (Privils(i).Peopl_ID = NVL(Peopl_ID,Privils(i).Peopl_ID)) THEN
  328.         Result := i;
  329.         EXIT;
  330.       END IF;
  331.       i := Privils.NEXT(i);
  332.     END LOOP;
  333.     IF Result IS NULL AND AddNewRow THEN
  334.       Result := NVL(Privils.LAST,0) + 1;
  335.       Privils(Result).Privil_ID := Privil_ID;
  336.       Privils(Result).Peopl_ID := Peopl_ID;
  337.     END IF;
  338.     RETURN Result;
  339.   END GetPrivilNo;
  340.  
  341.   FUNCTION Tarif(ServiceNo BINARY_INTEGER, SrvNorm_ID BINARY_INTEGER, OnlyHouseTarif BOOLEAN DEFAULT FALSE) RETURN spr_Tarifs.Tarif%TYPE  -- Для услуги вернуть тариф (домовой или общий).
  342.   AS Rslt NUMBER;
  343.   BEGIN
  344.     -- Взять тариф из домовых тарифов.
  345.     BEGIN
  346.       Rslt := TarifsH(ServiceNo*1000000 + NVL(SrvNorm_ID,0)*100).Tarif;
  347.     EXCEPTION
  348.       WHEN NO_DATA_FOUND THEN
  349.       BEGIN
  350.         IF NOT OnlyHouseTarif THEN
  351.           Rslt := Tarifs(ServiceNo*1000000 + NVL(SrvNorm_ID,0)*100 + Category).Tarif;
  352.         ELSE      
  353.           Rslt := 0;
  354.         END IF;
  355.       EXCEPTION
  356.         WHEN NO_DATA_FOUND THEN -- Если тарифа для услуги среди общегородских нет.
  357.           Rslt := 0;
  358.       END;
  359.     END;
  360.     RETURN Rslt;
  361.   EXCEPTION
  362.     WHEN NO_DATA_FOUND THEN RETURN 0;
  363.   END;
  364.  
  365.   FUNCTION Dotacya(ServiceNo BINARY_INTEGER, SrvNorm_ID BINARY_INTEGER, OnlyHouseTarif BOOLEAN DEFAULT FALSE) RETURN spr_Tarifs.Dotacya%TYPE  -- Для услуги вернуть дотацию.
  366.   AS Rslt NUMBER;
  367.   BEGIN
  368.     -- Взять тариф из домовых тарифов.
  369.     BEGIN
  370.       Rslt := NVL(TarifsH(ServiceNo*1000000 + NVL(SrvNorm_ID,0)*100).Dotacya,0);
  371.     EXCEPTION
  372.       WHEN NO_DATA_FOUND THEN -- Если тарифа для услуги среди домовых нет.
  373.       BEGIN
  374.         IF NOT OnlyHouseTarif THEN
  375.           Rslt := NVL(Tarifs(ServiceNo*1000000 + NVL(SrvNorm_ID,0)*100 + Category).Dotacya, 0);
  376.         ELSE
  377.           Rslt := 0;
  378.         END IF;
  379.       EXCEPTION
  380.         WHEN NO_DATA_FOUND THEN -- Если тарифа для услуги среди общегородских нет.
  381.           Rslt := 0;
  382.       END;
  383.     END;
  384.     RETURN Rslt;
  385.   END;  
  386.  
  387.   FUNCTION CalcSummByTarifsE(Data DATE, NormNo NUMBER, Volume NUMBER, MonthsPart NUMBER) RETURN NUMBER
  388.   AS
  389.     Result NUMBER;
  390.     No NUMBER;
  391.   BEGIN              
  392.     Result := 0;              
  393.     No := TarifsE.FIRST;
  394.     WHILE No IS NOT NULL LOOP
  395.       IF TarifsE(No).SrvNorm_ID = NormNo AND
  396.          TarifsE(No).Data <= Data AND Data <= TarifsE(No).Data_End AND
  397.          Volume > TarifsE(No).Volume_Min*MonthsPart
  398.       THEN
  399.         IF Volume >= TarifsE(No).Volume_Max*MonthsPart THEN
  400.           Result := Result + (TarifsE(No).Volume_Max - TarifsE(No).Volume_Min)*MonthsPart * TarifsE(No).Tarif;
  401.         ELSE
  402.           Result := Result + (Volume - TarifsE(No).Volume_Min*MonthsPart) * TarifsE(No).Tarif;
  403.         END IF;
  404.       END IF;  
  405.       No := TarifsE.NEXT(No);                    
  406.     END LOOP;
  407.     RETURN Result;                        
  408.   END;
  409.  
  410.   FUNCTION ServiceDependsOnHeat(Service_ID spr_Services.ID%TYPE) RETURN BOOLEAN
  411.   AS
  412.   BEGIN
  413.     RETURN Service_ID IN (
  414.       27, -- Отопление
  415.       44  -- Тепло по счетчику
  416.     );
  417.   END ServiceDependsOnHeat;
  418.  
  419.   PROCEDURE FillNoHeatDaysCountVariable(Hs_ID k_House.ID%TYPE)
  420.   AS
  421.     Indx BINARY_INTEGER;
  422.   BEGIN
  423.     FOR d IN (
  424.       SELECT MONTH, SUM(DaysOff) NoHeatDaysTotalCount
  425.       FROM n_NoHeatDaysCount
  426.       WHERE CityStructure_ID IN
  427.           (
  428.             SELECT CityStructure_ID
  429.             FROM spr_CityStructure
  430.             START WITH ID IN
  431.               (
  432.                 SELECT CityStructure_ID
  433.                 FROM k_House_CityStructure
  434.                 WHERE House_ID = Hs_ID
  435.               )
  436.             CONNECT BY PRIOR Parent_ID = ID
  437.           )
  438.         OR House_ID = Hs_ID
  439.       GROUP BY MONTH
  440.     ) LOOP
  441.       Indx := CAST(TO_CHAR(d.MONTH, 'YYYYMM') AS INT);
  442.       NoHeatDaysCounts(Indx).DaysInMonth := EXTRACT(DAY FROM LAST_DAY(d.MONTH));
  443.  
  444.       IF d.NoHeatDaysTotalCount <= NoHeatDaysCounts(Indx).DaysInMonth THEN        
  445.         NoHeatDaysCounts(Indx).NoHeatDays := d.NoHeatDaysTotalCount;
  446.       ELSE
  447.         NoHeatDaysCounts(Indx).NoHeatDays := NoHeatDaysCounts(Indx).DaysInMonth;
  448.       END IF;
  449.     END LOOP;
  450.   END;
  451.  
  452.   FUNCTION GetHeatReductionFactor(MONTH DATE) RETURN NUMBER
  453.   AS
  454.     result NUMBER;
  455.     Indx BINARY_INTEGER;
  456.   BEGIN
  457.     Indx := CAST(TO_CHAR(MONTH, 'YYYYMM') AS INT);
  458.     IF NoHeatDaysCounts.EXISTS(Indx) THEN
  459.       result := (NoHeatDaysCounts(Indx).DaysInMonth - NoHeatDaysCounts(Indx).NoHeatDays) / NoHeatDaysCounts(Indx).DaysInMonth;
  460.     ELSE
  461.       result := 1;
  462.     END IF;
  463.     RETURN result;
  464.   END;
  465.  
  466.   PROCEDURE FillHeatedAreaDecreasePercent
  467.   AS
  468.     Indx BINARY_INTEGER;
  469.   BEGIN
  470.     FOR d IN (
  471.       SELECT MONTH, Percent
  472.       FROM n_HeatedAreaDecreasePercents
  473.       WHERE Account_ID = AccID
  474.     ) LOOP
  475.       Indx := CAST(TO_CHAR(d.MONTH, 'YYYYMM') AS INT);
  476.       HeatedAreaDecreasePercent(Indx) := d.Percent/100;
  477.     END LOOP;
  478.   END;
  479.  
  480.   FUNCTION GetHeatedAreaDecreasePercent(MONTH DATE) RETURN NUMBER
  481.   AS
  482.     result NUMBER;
  483.     Indx BINARY_INTEGER;
  484.   BEGIN
  485.     Indx := CAST(TO_CHAR(MONTH, 'YYYYMM') AS INT);
  486.     IF HeatedAreaDecreasePercent.EXISTS(Indx) THEN
  487.       result := HeatedAreaDecreasePercent(Indx);
  488.     ELSE
  489.       result := 1;
  490.     END IF;
  491.     RETURN result;
  492.   END;
  493.  
  494.   FUNCTION GetTemperatKoeff(MONTH DATE) RETURN NUMBER
  495.   AS
  496.     result NUMBER;
  497.   BEGIN
  498.     SELECT Koeff INTO result
  499.       FROM spr_Temperat_Koeff
  500.       WHERE MONTH = TRUNC(GetTemperatKoeff.MONTH, 'MM');
  501.     RETURN result;
  502.   EXCEPTION
  503.     WHEN NO_DATA_FOUND THEN
  504.       RETURN 1;  
  505.   END;
  506.  
  507.   PROCEDURE LoadKoeffs(date_from DATE, date_to DATE)
  508.   AS
  509.   BEGIN
  510.     SELECT MONTH, Service_ID, Koeff, Vid
  511.     BULK COLLECT INTO Koeffs
  512.     FROM n_Koeffs
  513.     WHERE Account_ID = AccID
  514.       AND MONTH BETWEEN date_from AND date_to
  515.       AND Koeff IS NOT NULL;
  516.   END;
  517.  
  518.   FUNCTION GetKoeff(data DATE, Service_ID INTEGER, Vid INTEGER) RETURN NUMBER
  519.   AS
  520.     KoeffNo INTEGER;
  521.     result NUMBER;
  522.   BEGIN
  523.     result := 1;
  524.     KoeffNo := Koeffs.FIRST;
  525.     WHILE KoeffNo IS NOT NULL LOOP
  526.       IF Koeffs(KoeffNo).MONTH = TRUNC(data, 'MM') AND Koeffs(KoeffNo).Service_ID = Service_ID AND Koeffs(KoeffNo).Vid = Vid THEN
  527.         result := result * Koeffs(KoeffNo).Koeff;
  528.       END IF;
  529.       KoeffNo := Koeffs.NEXT(KoeffNo);
  530.     END LOOP;
  531.     RETURN result;
  532.   END;
  533.  
  534. BEGIN
  535.   print('Acc_ID = '||AccID||';');
  536.   AccrualsDescription27('ID Л/С: '||AccID||';');
  537.  
  538.   -- Некоторые участки всегда расчитываются, остальные - по признаку в таблице.
  539.   SELECT District_ID INTO tmp_numb FROM k_Accounts WHERE ID = LPAD(TRIM(AccID), 12, '0');
  540.   IF tmp_numb NOT IN (112001,112002,112003) THEN
  541.     -- Возможность отключить перерасчет.
  542.     SELECT NoNachisl INTO NoNachisl FROM System;
  543.     IF NVL(NoNachisl,0) = 1 THEN
  544.  
  545.       RETURN;
  546.     END IF;
  547.   END IF;  
  548.  
  549.   --raise_application_error(-20100, 'Nicht arbeiten!');  
  550.  
  551.   LoggedUserID := LoggedUser();
  552.   DataChangeRow := SYSDATE;
  553.   SELECT FinMonth INTO FinMonth FROM System;
  554.   print('FinMonth = '||FinMonth||';');
  555.   AccrualsDescription27('Отчетный месяц: '||FinMonth||';');
  556.  
  557.   -- Заполнение процентов льгот.
  558.   FOR p IN (SELECT Privil_ID*100000+Service_ID PrvlSrvNo, Percent/100 Percent FROM spr_PrivilPrc) LOOP
  559.     PrvlSrvPrc(p.PrvlSrvNo) := p.Percent;
  560.   END LOOP;                    
  561.   -- Даты начала/конца перерасчета.
  562.   Data_Beg_Nach := TRUNC(Data_Start, 'MM');
  563.   Data_End_Nach := LAST_DAY(FinMonth);
  564.  
  565.   -- ИЗМЕНИТЬ ДАТУ НАЧАЛА ПЕРЕРАСЧЕТА: откатиться на более раннюю дату
  566.   -- при наличии показаний счетчиков или
  567.   -- если есть сверка с более ранней датой начала
  568.   LOOP                
  569.     -- Минимальная дата по сверкам.
  570.     SELECT MIN(DataBegRevis)
  571.       INTO tmp_data
  572.       FROM n_Accruals
  573.       WHERE Account_ID = LPAD(AccID, 12, '0')
  574.         AND Data >= Data_Beg_Nach AND Data <= FinMonth
  575.         AND Vid IN (3,4/*сверка по начислению/льготе*/);
  576.     -- Минимальная дата по показаниям.
  577.     SELECT MIN(TRUNC(i.Data_old+DECODE(i.Vid_old, 1,0, 1),'MM'))
  578.       INTO tmp_data2
  579.       FROM n_Indications i
  580.       WHERE i.Counter_ID IN (SELECT DISTINCT Counter_ID FROM c_Account WHERE Account_ID = LPAD(AccID, 12, '0'))
  581.         AND i.Data_ins BETWEEN Data_Beg_Nach AND Data_End_Nach
  582.         AND i.Vid IN (2/*ктр*/);
  583.     -- Изменить дату.
  584.     IF tmp_data < Data_Beg_Nach OR tmp_data2 < Data_Beg_Nach THEN
  585.       IF tmp_data < Data_Beg_Nach THEN
  586.         Data_Beg_Nach := tmp_data;
  587.       END IF;
  588.       IF tmp_data2 < Data_Beg_Nach THEN
  589.         Data_Beg_Nach := tmp_data2;
  590.       END IF;
  591.     ELSE
  592.       EXIT;
  593.     END IF;
  594.   END LOOP;
  595.  
  596.   print('Data_Beg_Nach = '||Data_Beg_Nach||'; Data_End_Nach = '||Data_End_Nach||';');
  597.   AccrualsDescription27('Дата начала расчета = '||Data_Beg_Nach||'; дата окончания расчета = '||Data_End_Nach||';');
  598.            
  599.   -- Номер дома.
  600.   SELECT k_Apart.House_ID
  601.     INTO Hs_ID
  602.     FROM k_Accounts, k_Apart
  603.     WHERE k_Accounts.ID = LPAD(AccID, 12, '0')
  604.       AND k_Apart.ID = k_Accounts.Apart_ID;
  605.   print('Hs_ID = '||Hs_ID||';');
  606.   AccrualsDescription27('ID дома: '||Hs_ID||';');
  607.        
  608.   -- Норма для нулевой услуги.
  609.   Norms(0).Norm := 1;
  610.   Norms(0).Norm_Social := Norms(0).Norm;
  611.   Norms(0).Period := 2;
  612.   -- Посчитать общее количество дней без тепла по дому помесячно.
  613.   FillNoHeatDaysCountVariable(Hs_ID);
  614.   -- Взять возможные проценты уменьшения площади отопления.
  615.   FillHeatedAreaDecreasePercent();
  616.   -- Загрузить уменьшающие коэффициенты.
  617.   LoadKoeffs(Data_Beg_Nach, Data_End_Nach);
  618.  
  619.   -------------------------------------------------------------------------------------------------------------
  620.   --  /---\ /---\ |  |   /| /--\   /| |   | |   | /---\    /--\ |  | |--\ /---\ |  | |   | |  | /---\ |---\  --  
  621.   --  |   | |   | | /  /  |    | /  | |   | |  /| |   |    |    |  | |      |   |  | |  /| | /  |   | |   |  --
  622.   --  |   | |   | |<   |  |  -<  |  | |---| | / | \-->     |     \_| |--    |    \_| | / | |<   |   | |--<   --
  623.   --  |   | |   | | \  |--|    | |--| |   | |/  |  /  |    |       | |      |      | |/  | | \  |   | |   |  --
  624.   --  |   | \---/ |  | |  | \--/ |  | |   | |   | /   |    \--/    | |--/   |      | |   | |  | \---/ |---/  --
  625.   -------------------------------------------------------------------------------------------------------------
  626.  
  627.   -- Данные по счетчикам.
  628.   SELECT * BULK COLLECT INTO CAccount FROM c_Account WHERE Account_ID = LPAD(AccID, 12, '0') ORDER BY Counter_ID, Data ASC;
  629.   -- Показания по дате внесения.
  630.   FOR i IN (    
  631.     SELECT i.Counter_ID, i.Data+1 Data, i.Data_ins, i.Data_old+DECODE(i.Vid_old, 1,0, 1) Data_old, i.Vid, i.Vid_old, i.Volume, DECODE(s.Vid, 1,28, 2,35, 3,44, 4,25, 5,10 ) Service
  632.     FROM n_Indications i, k_Counters k, spr_Counters s
  633.     WHERE i.Counter_ID IN (SELECT DISTINCT Counter_ID FROM c_Account WHERE Account_ID = LPAD(AccID, 12, '0'))      
  634.       AND i.Data_ins BETWEEN Data_Beg_Nach AND Data_End_Nach -- AND Data_Beg_Nach <= i.Data_old AND i.Data <= Data_End_Nach
  635.       AND i.Vid IN (2/*ктр*/)
  636.       AND k.ID = i.Counter_ID
  637.       AND s.ID = k.Counter_ID
  638.   )LOOP
  639.     -- Определить процент и состояние счетчика на дату снятия показания.              
  640.     Prcnt := 0;
  641.     FOR j IN REVERSE NVL(CAccount.FIRST,0)..NVL(CAccount.LAST,-1) LOOP
  642.       IF CAccount(j).Counter_ID = i.Counter_ID THEN -- Отобрать нужный счетчик.
  643.         IF CAccount(j).Data < i.Data THEN -- Дата ктр больше, чем текущая дата состояния...
  644.           Prcnt := CAccount(j).Percent; -- ... значит для ктр действует это состояние счетчика (т.к. состояния отсортированы по возрастанию, а список просматривается от большего к меньшему).
  645.           EXIT;
  646.         ELSIF CAccount(j).Data = i.Data THEN -- Дата ктр совпадает с датой изменения счетчиков...
  647.           IF CAccount.EXISTS(j-1) AND CAccount(j-1).Counter_ID = i.Counter_ID THEN -- ... и существует предыдущее (более раннее по дате) состояние счетчика...
  648.             Prcnt := CAccount(j-1).Percent; -- ... значит для ктр действует предыдущее состояние счетчика.
  649.           END IF;
  650.           EXIT;
  651.         END IF;
  652.       END IF;
  653.     END LOOP;
  654.     -- Добавить показание в массив.
  655.     IndicationNo := GetIndicationNo(i.Service, TRUNC(i.Data_ins,'MM'), i.Data_old, i.Data, i.Vid_old);
  656.     Indications(IndicationNo).Volume := Indications(IndicationNo).Volume + i.Volume*(Prcnt/100);
  657.     -- Продублировать гор.воду для водоотведения.
  658.     IF i.Service = 35 THEN
  659.       IndicationNo2 := GetIndicationNo(53, TRUNC(i.Data_ins,'MM'), i.Data_old, i.Data, i.Vid_old);
  660.       Indications(IndicationNo2).Volume := Indications(IndicationNo).Volume;
  661.     END IF;  
  662.   END LOOP;
  663.  
  664.   /*
  665.   Indication_No := Indications.FIRST;
  666.   WHILE Indication_No IS NOT NULL LOOP
  667.     print('Indications('||Indication_No||'): ServiceID = '||Indications(Indication_No).ServiceID||'; Month = '||Indications(Indication_No).Month||'; Data_prev = '||Indications(Indication_No).Data_prev||'; Data_curr = '||Indications(Indication_No).Data_curr||'; Volume = '||Indications(Indication_No).Volume);
  668.     Indication_No := Indications.NEXT(Indication_No);
  669.   END LOOP;
  670.   */
  671.  
  672.   ----------------------------------------------------------
  673.   --  /---\ |--\ \   /    |--\   /| /--\ |  | |--\ /---\  --
  674.   --    |   |     \ /     |  | /  | |    |  | |      |    --
  675.   --    |   |--    |      |--/ |  | |     \_| |--    |    --
  676.   --    |   |     / \     |    |--| |       | |      |    --
  677.   --    |   |--/ /   \ *  |    |  | \--/    | |--/   |    --
  678.   ----------------------------------------------------------
  679.   Data_Prev := Data_Beg_Nach;
  680.   -- РАСЧЕТ НАЧИСЛЕНИЙ - цикл по всем событиям в период начисления.
  681.   FOR ist IN (
  682.     SELECT *
  683.     FROM
  684.       (
  685.       SELECT -- Изменения Л/С.
  686.         'L' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  687.         Status_ID, Area_Obsch, Area_Polezn, Area_Gilay, Area_AddSan, Count_Inhabit, ShortFamily, Surplus, CGV,
  688.         /*W*/TO_NUMBER(NULL)Count_W,
  689.         /*H*/TO_NUMBER(NULL)Category,
  690.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  691.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  692.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  693.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  694.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  695.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  696.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  697.       FROM a_Accounts a
  698.       WHERE Account_ID = LPAD(AccID, 12, '0')
  699.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM a_Accounts WHERE Account_ID = a.Account_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  700.       UNION
  701.       SELECT  -- Отсутствующие.
  702.         'W' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  703.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  704.         Count_W,
  705.         /*H*/TO_NUMBER(NULL)Category,
  706.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  707.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  708.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  709.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  710.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  711.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  712.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  713.       FROM n_AccountWanting w
  714.       WHERE Account_ID = LPAD(AccID, 12, '0')
  715.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountWanting WHERE Account_ID = w.Account_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  716.       UNION
  717.       SELECT -- Изменения дома.
  718.         'H' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  719.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  720.         /*W*/TO_NUMBER(NULL)Count_W,
  721.         Category,
  722.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  723.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  724.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  725.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  726.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  727.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  728.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  729.       FROM a_House a
  730.       WHERE House_ID = LPAD(Hs_ID, 12, '0')
  731.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM a_House WHERE House_ID = a.House_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  732.       UNION  
  733.       SELECT -- Изменения льгот Л/С.
  734.         'P' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  735.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  736.         /*W*/TO_NUMBER(NULL)Count_W,
  737.         /*H*/TO_NUMBER(NULL)Category,
  738.         Privil_ID, Peopl_ID, Count_Prvl, State_Prvl,
  739.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  740.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  741.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  742.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  743.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  744.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  745.       FROM n_AccountPrivil p, spr_Privils sp
  746.       WHERE Account_ID = LPAD(AccID, 12, '0')
  747.         AND p.Privil_ID = sp.ID
  748.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountPrivil WHERE Account_ID = p.Account_ID AND Privil_ID = p.Privil_ID AND Peopl_ID = p.Peopl_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  749.       UNION
  750.       SELECT -- Изменения услуг.
  751.         'S' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  752.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  753.         /*W*/TO_NUMBER(NULL)Count_W,
  754.         /*H*/TO_NUMBER(NULL)Category,
  755.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  756.         Service_ID, Formula, State_Srv, Params, Norm_ID,
  757.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  758.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  759.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  760.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  761.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  762.       FROM n_AccountService s, spr_Services
  763.       WHERE s.Account_ID = LPAD(AccID, 12, '0')
  764.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountService WHERE Account_ID = s.Account_ID AND Service_ID = s.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  765.         AND (Data > Data_Beg_Nach OR s.State_Srv = 1)  -- Отбросить закрытые на начало расчета услуги.
  766.         AND spr_Services.ID = Service_ID
  767.       UNION
  768.       SELECT -- Временное отключение услуг дому.
  769.         'O' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  770.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  771.         /*W*/TO_NUMBER(NULL)Count_W,
  772.         /*H*/TO_NUMBER(NULL)Category,
  773.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  774.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  775.         Service_ID Service_ID_O, State_Srv State_Srv_O,
  776.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  777.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  778.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  779.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  780.       FROM n_HouseService o
  781.       WHERE House_ID = LPAD(Hs_ID, 12 , '0')
  782.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_HouseService WHERE House_ID = o.House_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  783.       UNION
  784.       SELECT -- Изменения норм.
  785.         'N' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  786.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  787.         /*W*/TO_NUMBER(NULL)Count_W,
  788.         /*H*/TO_NUMBER(NULL)Category,
  789.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  790.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  791.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  792.         SrvNorm_ID, Norm, Norm_Social, Norm_Slave_Persons, Period,
  793.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  794.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  795.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  796.       FROM spr_Norms m
  797.       WHERE SrvNorm_ID IN
  798.             (
  799.             SELECT Norm_ID
  800.             FROM n_AccountService s
  801.             WHERE s.Account_ID = LPAD(AccID, 12, '0')
  802.               AND s.Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountService WHERE Account_ID = s.Account_ID AND Service_ID = s.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  803.               AND (Data > Data_Beg_Nach OR s.State_Srv = 1)  -- Отбросить закрытые на начало расчета услуги.
  804.             UNION
  805.             SELECT ID
  806.             FROM spr_SrvNorms
  807.             WHERE Service_ID = 0
  808.             )
  809.         AND Data >= (SELECT NVL(MAX(Data),data_beg_nach) FROM spr_Norms WHERE SrvNorm_ID = m.SrvNorm_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  810.       UNION
  811.       SELECT -- Изменение общих тарифов.
  812.         'T' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  813.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  814.         /*W*/TO_NUMBER(NULL)Count_W,
  815.         /*H*/TO_NUMBER(NULL)Category,
  816.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  817.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  818.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  819.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  820.         TrSchema, Service_ID Service_ID_T, NVL(SrvNorm_ID,0) SrvNorm_ID_T, Tarif, Dotacya,
  821.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  822.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  823.       FROM spr_Tarifs t
  824.       WHERE TrSchema IN
  825.           (
  826.             SELECT DISTINCT Category
  827.             FROM a_House a
  828.             WHERE House_ID = Hs_ID
  829.               AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM a_House WHERE House_ID = a.House_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  830.           )
  831.         AND Service_ID IN
  832.           (
  833.             SELECT Service_ID
  834.             FROM n_AccountService s
  835.             WHERE s.Account_ID = LPAD(AccID, 12, '0')
  836.               AND s.Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountService WHERE Account_ID = s.Account_ID AND Service_ID = s.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  837.               AND (Data > Data_Beg_Nach OR s.State_Srv = 1)  -- Отбросить закрытые на начало расчета услуги.
  838.           )
  839.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM spr_Tarifs WHERE TrSchema = t.TrSchema AND Service_ID = t.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  840.       UNION      
  841.       SELECT -- Изменение тарифов на электричество.
  842.         'E' Vid, GREATEST(NVL(Data, TO_DATE('01.01.0001','DD.MM.YYYY')), Data_Beg_Nach) Data,
  843.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  844.         /*W*/TO_NUMBER(NULL)Count_W,
  845.         /*H*/TO_NUMBER(NULL)Category,
  846.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  847.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  848.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  849.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  850.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  851.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  852.         SrvNorm_ID SrvNorm_ID_E, NVL(Data_End, TO_DATE('31.12.9999','DD.MM.YYYY')) Data_End, NVL(Volume_Min, 0) Volume_Min, NVL(Volume_Max, 999999999999) Volume_Max, NVL(Tarif, 0) Tarif_E
  853.       FROM spr_Tarifs_E  
  854.       WHERE SrvNorm_ID IN
  855.           (
  856.             SELECT s.Norm_ID
  857.             FROM n_AccountService s
  858.             WHERE s.Account_ID = LPAD(AccID, 12, '0')          
  859.               AND Service_ID IN (10)
  860.               AND s.Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountService WHERE Account_ID = s.Account_ID AND Service_ID = s.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  861.               AND (Data > Data_Beg_Nach OR s.State_Srv = 1)  -- Отбросить закрытые на начало расчета услуги.
  862.           )
  863.         AND Data_Beg_Nach <= NVL(Data_End, TO_DATE('31.12.9999','DD.MM.YYYY')) AND Data_End_Nach >= NVL(Data, TO_DATE('01.01.0001','DD.MM.YYYY'))
  864.       UNION
  865.       SELECT -- Изменение домовых тарифов.
  866.         'J' Vid, GREATEST(Data, Data_Beg_Nach) Data,
  867.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  868.         /*W*/TO_NUMBER(NULL)Count_W,
  869.         /*H*/TO_NUMBER(NULL)Category,
  870.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  871.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  872.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  873.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  874.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  875.         Service_ID Service_ID_J, NVL(SrvNorm_ID,0) SrvNorm_ID_J, Tarif TarifH, Dotacya DotacyaH,
  876.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  877.       FROM spr_TarifsH t
  878.       WHERE House_ID = Hs_ID
  879.         AND ( (Service_ID IN
  880.           (
  881.             SELECT Service_ID
  882.             FROM n_AccountService s
  883.             WHERE s.Account_ID = LPAD(AccID, 12, '0')            
  884.               AND Service_ID NOT BETWEEN 101 AND 150
  885.               AND s.Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM n_AccountService WHERE Account_ID = s.Account_ID AND Service_ID = s.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  886.               AND (Data > Data_Beg_Nach OR s.State_Srv = 1)  -- Отбросить закрытые на начало расчета услуги.
  887.           )) OR (Service_ID BETWEEN 101 AND 150) )
  888.         AND Data >= (SELECT NVL(MAX(Data),Data_Beg_Nach) FROM spr_TarifsH WHERE House_ID = t.House_ID AND Service_ID = t.Service_ID AND Data <= Data_Beg_Nach) AND Data <= Data_End_Nach
  889.       UNION      
  890.       SELECT
  891.         'K' Vid, data_sch Data,
  892.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  893.         /*W*/TO_NUMBER(NULL)Count_W,
  894.         /*H*/TO_NUMBER(NULL)Category,
  895.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  896.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  897.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  898.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  899.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  900.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  901.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  902.       FROM
  903.       (
  904.         SELECT i.Data_old+DECODE(i.Vid_old, 1,0, 1) data_sch
  905.           FROM n_Indications i
  906.           WHERE i.Counter_ID IN (SELECT DISTINCT Counter_ID FROM c_Account WHERE Account_ID = LPAD(AccID, 12, '0'))
  907.             AND i.Data_ins BETWEEN Data_Beg_Nach AND Data_End_Nach
  908.             AND i.Vid IN (2/*ктр*/)
  909.         UNION ALL
  910.         SELECT i.Data+1 data_sch
  911.           FROM n_Indications i
  912.           WHERE i.Counter_ID IN (SELECT DISTINCT Counter_ID FROM c_Account WHERE Account_ID = LPAD(AccID, 12, '0'))
  913.             AND i.Data_ins BETWEEN Data_Beg_Nach AND Data_End_Nach
  914.             AND i.Vid IN (2/*ктр*/)
  915.       )              
  916.       UNION
  917.       SELECT
  918.         'X' Vid, Data_End_Nach + 1 Data,
  919.         /*L*/TO_NUMBER(NULL)Status_ID, TO_NUMBER(NULL)Area_Obsch, TO_NUMBER(NULL)Area_Polezn, TO_NUMBER(NULL)Area_Gilay, TO_NUMBER(NULL)Area_AddSan, TO_NUMBER(NULL)Count_Inhabit, TO_CHAR(NULL)ShortFamily, TO_CHAR(NULL)Surplus, TO_CHAR(NULL)Cgv,
  920.         /*W*/TO_NUMBER(NULL)Count_W,
  921.         /*H*/TO_NUMBER(NULL)Category,
  922.         /*P*/TO_NUMBER(NULL)Privil_ID, TO_CHAR(NULL)Peopl_ID, TO_NUMBER(NULL)Count_Prvl, TO_NUMBER(NULL)State_Prvl,
  923.         /*S*/TO_NUMBER(NULL)Service_ID, TO_NUMBER(NULL)Formula, TO_NUMBER(NULL)State_Srv, TO_NUMBER(NULL)Params, TO_NUMBER(NULL)Norm_ID,
  924.         /*O*/TO_NUMBER(NULL)Service_ID_O, TO_NUMBER(NULL)State_Srv_O,
  925.         /*N*/TO_NUMBER(NULL)SrvNorm_ID, TO_NUMBER(NULL)Norm, TO_NUMBER(NULL)Norm_Social, TO_NUMBER(NULL) Norm_Slave_Persons, TO_NUMBER(NULL) Period,
  926.         /*T*/TO_NUMBER(NULL)TrSchema, TO_NUMBER(NULL)Service_ID_T, TO_NUMBER(NULL) SrvNorm_ID_T, TO_NUMBER(NULL)Tarif, TO_NUMBER(NULL)Dotacya,
  927.         /*J*/TO_NUMBER(NULL)Service_ID_J, TO_NUMBER(NULL)SrvNorm_ID_J, TO_NUMBER(NULL)TarifH, TO_NUMBER(NULL)DotacyaH,
  928.         /*E*/TO_NUMBER(NULL)SrvNorm_ID_E, TO_DATE(NULL)Data_End, TO_NUMBER(NULL)Volume_Min, TO_NUMBER(NULL)Volume_Max, TO_NUMBER(NULL)Tarif_E
  929.       FROM DUAL
  930.       )
  931.     ORDER BY Data
  932.   ) LOOP
  933.     IF Data_Prev < ist.Data THEN
  934.       WHILE Data_prev < ist.Data LOOP
  935.         print('Data_prev = '||Data_prev||'; ist.Data = '||ist.Data||';');
  936.         AccrualsDescription27('начало сегмента расчета = '||Data_prev||'; конец сегмента расчета = '||ist.Data||';');
  937.  
  938.         CurrMonthNach := TRUNC(Data_Prev, 'MM');
  939.         DayInMonthNach := EXTRACT(DAY FROM LAST_DAY(Data_Prev));
  940.         -- Расчет части месяца, за которую проводится начисление.
  941.         IF TRUNC(Data_prev, 'MM') < TRUNC(ist.Data, 'MM') THEN
  942.           Month_Part := (TO_CHAR(LAST_DAY(Data_prev) - Data_prev) + 1) / TO_CHAR(LAST_DAY(Data_prev),'DD');
  943.         ELSE
  944.           Month_Part := (TO_CHAR(ist.Data - Data_prev)) / TO_CHAR(LAST_DAY(Data_prev),'DD');
  945.         END IF;
  946.         print('  Month_Part = '||Month_Part||';');
  947.         AccrualsDescription27('  часть месяца в сегменте расчета = '||Month_Part||';');
  948.         -- Начисление по всем услугам за промежуток.
  949.         ServiceNo := Services.FIRST;
  950.         WHILE ServiceNo IS NOT NULL LOOP
  951.           print('  ServiceNo = '||ServiceNo||';');
  952.           AccrualsDescription27('  код услуги = '||ServiceNo||';');
  953.          
  954.           -- Тариф по услуге.
  955.           Curr_Tarif := Tarif(ServiceNo, Services(ServiceNo).Norm_ID);
  956.           print('    Curr_Tarif = '||Curr_Tarif||';');
  957.           AccrualsDescription27('    тариф = '||Curr_Tarif||';');
  958.           -- Для Тепла применить к тарифу Температурный коэффициент:
  959.           IF ServiceNo = 27 THEN -- Тепло
  960.             tmp_numb := GetTemperatKoeff(ist.Data-1);
  961.             Curr_Tarif := Curr_Tarif * tmp_numb;
  962.             print('    Curr_Tarif = [Curr_Tarif] * '||tmp_numb||'[TemperatKoeff] = '||Curr_Tarif||';');
  963.             AccrualsDescription27('    тариф = [тариф] * '||tmp_numb||'[температурный коеффициент] = '||Curr_Tarif||';');
  964.           END IF;      
  965.           -- Применить к тарифу понижающий коэффициент:
  966.           tmp_numb3 := ServiceNo;
  967.           IF tmp_numb3 BETWEEN 101 AND 126 THEN
  968.             tmp_numb3 := 100;
  969.           END IF;
  970.           tmp_numb := GetKoeff(Data_prev, tmp_numb3, 1);
  971.           IF tmp_numb < 1 THEN
  972.             tmp_numb2 := Curr_Tarif;
  973.             Curr_Tarif := tmp_numb2 * tmp_numb;
  974.             print('    Curr_Tarif = '||tmp_numb2||'[Curr_Tarif] * '||tmp_numb||'[GetKoeff('||Data_prev||', '||tmp_numb3||', 1)] = '||Curr_Tarif);
  975.             AccrualsDescription27('    тариф = '||tmp_numb2||'[тариф] * '||tmp_numb||'[коэффициент понижения тарифа] = '||Curr_Tarif);
  976.           END IF;              
  977.  
  978.           -- ВЫЧИСЛЕНИЕ ОБЪЕМА УСЛУГИ.
  979.           IF Services(ServiceNo).Formula = 0 THEN  -- Услуга не подходит под формулу.
  980.             IF ServiceNo = 4 AND NVL(Services(ServiceNo).State_Srv,1) = 1 THEN  -- АГВ.
  981.               NormNo := NVL(Services(ServiceNo).Norm_ID,0);
  982.               Volume_Nach := Area_Polezn * Norms(NormNo).Norm * Month_Part;
  983.               Volume_Social_Nach := Area_Polezn * Norms(NormNo).Norm_Social * Month_Part;
  984.               IF Norms(NormNo).Period = 1 THEN  -- Норма в сутки, а не в месяц.
  985.                 Volume_Nach := Volume_Nach * DayInMonthNach;
  986.                 Volume_Social_Nach := Volume_Social_Nach * DayInMonthNach;
  987.               END IF;
  988.               Summ_Nach := Volume_Nach * Curr_Tarif;
  989.               Area_Izl := Area_Polezn - (Count_Inhabit*Norms(1).Norm/*Норма площади на человека*/ + Area_AddSan + Norms(2).Norm/*Норма площади на семью*/);
  990.               IF Area_Izl > 0 AND Surplus = 'Y' THEN  -- Есть излишки по площади и они учитываются.
  991.                 IF Area_Polezn <> 0 THEN
  992.                   tmp_numb := Summ_Nach*(Area_Izl/Area_Polezn);
  993.                 ELSE          
  994.                   tmp_numb := 0;
  995.                 END IF;
  996.                 Summ_Nach := Summ_Nach - tmp_numb + tmp_numb * Norms(21).Norm;
  997.               END IF;
  998.             ELSIF ServiceNo = 41 AND NVL(Services(ServiceNo).State_Srv,1) = 1 THEN  -- ГАЗОВАЯ ПЛИТА.
  999.               IF Cgv = 'Y' /*AND Services.EXISTS(6) AND NVL(Services(6).State_Srv,1) = 1*/ THEN  -- Есть неотключенное ЦГВ.
  1000.                 NormNo := 31;
  1001.               ELSE -- ЦГВ нет или отключено.
  1002.                 NormNo := 32;
  1003.               END IF;
  1004.               Volume_Nach := Count_Inhabit * Norms(NormNo).Norm * Month_Part;
  1005.               Volume_Social_Nach := Count_Inhabit * Norms(NormNo).Norm_Social * Month_Part;
  1006.               Summ_Nach := Volume_Nach * Curr_Tarif;
  1007.             ELSIF ServiceNo = 5 AND NVL(Services(ServiceNo).State_Srv,1) = 1 THEN  -- ХОЛОДНАЯ ВОДА И КАНАЛИЗАЦИЯ.
  1008.               NormNo := NVL(Services(ServiceNo).Norm_ID,0);
  1009.               Volume_Nach := GREATEST((Count_Inhabit - Count_Wanting),1) * Norms(NormNo).Norm * Month_Part;
  1010.               Volume_Social_Nach := GREATEST((Count_Inhabit - Count_Wanting),1) * Norms(NormNo).Norm_Social * Month_Part;
  1011.               IF Norms(NormNo).Period = 1 THEN  -- Норма в сутки, а не в месяц.
  1012.                 Volume_Nach := Volume_Nach * DayInMonthNach;
  1013.                 Volume_Social_Nach := Volume_Social_Nach * DayInMonthNach;
  1014.               END IF;
  1015.               Summ_Nach := Volume_Nach * Curr_Tarif;
  1016.             ELSE  -- Неизвестная услуга.
  1017.               Volume_Nach := 0;
  1018.               Volume_Social_Nach := 0;
  1019.               Summ_Nach := 0;
  1020.             END IF;
  1021.           ELSE  -- Услуга подходит под одну из формул.
  1022.             IF    Services(ServiceNo).Formula = 10 THEN  -- Количество - единица.
  1023.               Volume_Nach := 1;
  1024.               print('    Volume_Nach = '||Volume_Nach||'[const];');
  1025.             ELSIF Services(ServiceNo).Formula = 11 THEN  -- Количество - индивидуальное значение.
  1026.               Volume_Nach := TO_NUMBER(Services(ServiceNo).Params);
  1027.               print('    Volume_Nach = '||Volume_Nach||'[Services(ServiceNo).Params];');
  1028.             ELSIF Services(ServiceNo).Formula = 20 THEN  -- Люди - проживающие.
  1029.               Volume_Nach := Count_Inhabit;
  1030.               print('    Volume_Nach = '||Volume_Nach||'[Count_Inhabit];');
  1031.             ELSIF Services(ServiceNo).Formula = 21 THEN  -- Люди - проживающие минус отсутствующие.
  1032.               Volume_Nach := GREATEST(Count_Inhabit - Count_Wanting,1);
  1033.               print('    Volume_Nach = '||Volume_Nach||'[MAX(Count_Inhabit - Count_Wanting,1)];');
  1034.             ELSIF Services(ServiceNo).Formula = 30 THEN  -- Площадь - обшая.
  1035.               Volume_Nach := Area_Obsch;
  1036.               print('    Volume_Nach = '||Volume_Nach||'[Area_Obsch];');
  1037.             ELSIF Services(ServiceNo).Formula = 31 THEN  -- Площадь - полезная.
  1038.               Volume_Nach := Area_Polezn;
  1039.               print('    Volume_Nach = '||Volume_Nach||'[Area_Polezn];');
  1040.               AccrualsDescription27('    объем услуги = '||Volume_Nach||'[отапливаемая площадь];');
  1041.             ELSIF Services(ServiceNo).Formula = 32 THEN  -- Площадь - жилая.
  1042.               Volume_Nach := Area_Gilay;
  1043.               print('    Volume_Nach = '||Volume_Nach||'[Area_Gilay];');
  1044.             END IF;
  1045.                        
  1046.             -- Если услуга зависит от тепла, то учесть его возможное отключение и возможный коэффициент уменьшения отопительной площади:
  1047.             IF ServiceDependsOnHeat(ServiceNo) THEN
  1048.               tmp_numb2 := GetHeatReductionFactor(Data_prev);
  1049.               tmp_numb3 := GetHeatedAreaDecreasePercent(Data_prev);
  1050.               Volume_Nach := Volume_Nach * tmp_numb2 * tmp_numb3;
  1051.               print('    Volume_Nach = [Volume_Nach] * '||tmp_numb2||'[HeatReductionFactor] * '||tmp_numb3||'[HeatedAreaDecreasePercent] = '||Volume_Nach||';');
  1052.               AccrualsDescription27('    объем услуги = [объем услуги] * '||tmp_numb2||'[часть месяца подачи тепла] * '||tmp_numb3||'[коэффициент уменьшения отапливаемой площади] = '||Volume_Nach||';');
  1053.             END IF;
  1054.                        
  1055.             -- Применить норму к вычисленному объему услуги.
  1056.             NormNo := NVL(Services(ServiceNo).Norm_ID,0);
  1057.             BEGIN    
  1058.               IF ServiceNo = 10 THEN -- Электричество: первому человеку одна норма, всем последующим - друая, но не больше социаьнгой норммы.
  1059.                 Volume_Social_Nach := (Norms(NormNo).Norm + CASE WHEN Volume_Nach > 1 THEN (Volume_Nach-1)*Norms(NormNo).Norm_Slave_Persons ELSE 0 END) * Month_Part;
  1060.                 IF Volume_Social_Nach > Norms(NormNo).Norm_Social * Month_Part THEN
  1061.                   Volume_Social_Nach := Norms(NormNo).Norm_Social * Month_Part;
  1062.                 END IF;
  1063.               ELSIF ServiceNo = 27 THEN -- Тепло - не применять соц. норму по техрасчету.
  1064.                 Volume_Social_Nach := Volume_Nach * Month_Part;
  1065.                 print('    Volume_Social_Nach = '||Volume_Nach||'[Volume_Nach] * '||Month_Part||'[Month_Part] = '||Volume_Social_Nach||';');
  1066.                 AccrualsDescription27('    социальный объем = '||Volume_Nach||'[объем услуги] * '||Month_Part||'[часть месяца в сегменте расчета] = '||Volume_Social_Nach||';');
  1067.               ELSE                                      
  1068.                 Volume_Social_Nach := Volume_Nach * Norms(NormNo).Norm_Social * Month_Part;
  1069.                 print('    Volume_Social_Nach = '||Volume_Nach||'[Volume_Nach] * '||Norms(NormNo).Norm_Social||'[Norm_Social] * '||Month_Part||'[Month_Part] = '||Volume_Social_Nach||';');
  1070.               END IF;
  1071.               Volume_Nach := Volume_Nach * Norms(NormNo).Norm * Month_Part;
  1072.               print('    Volume_Nach = [Volume_Nach] * '||Norms(NormNo).Norm||'[Norm] * '||Month_Part||'[Month_Part] = '||Volume_Nach);
  1073.               AccrualsDescription27('    объем услуги = [объем услуги] * '||Norms(NormNo).Norm||'[норма услуги] * '||Month_Part||'[часть месяца в сегменте расчета] = '||Volume_Nach);
  1074.              
  1075.               IF Norms(NormNo).Period = 1 THEN  -- Норма в сутки, а не в месяц.
  1076.                 Volume_Nach := Volume_Nach * DayInMonthNach;
  1077.                 Volume_Social_Nach := Volume_Social_Nach * DayInMonthNach;
  1078.               END IF;
  1079.             EXCEPTION
  1080.               WHEN NO_DATA_FOUND THEN
  1081.                 Volume_Nach := 0;
  1082.                 Volume_Social_Nach := 0;
  1083.             END;      
  1084.            
  1085.             -- Расчет суммы.
  1086.             IF ServiceNo = 10 THEN -- "Электроэнергия по счетчику".
  1087.               Summ_Nach := CalcSummByTarifsE(ist.Data-1, NormNo, Volume_Nach, Month_Part);
  1088.               IF Volume_Nach <> 0 THEN
  1089.                 Curr_Tarif := Summ_Nach / Volume_Nach;
  1090.               ELSE            
  1091.                 Curr_Tarif := 0;
  1092.               END IF;
  1093.             ELSIF ServiceNo = 17 THEN -- "Подсобка".
  1094.               -- Для Подсобки тариф равен 50% от СДПТ в случае, если домовой тариф на подсобку <> 0 (Тоня, 18.10.2010).
  1095.               Curr_Tarif := Tarif(ServiceNo, Services(ServiceNo).Norm_ID, TRUE);
  1096.               IF Curr_Tarif = 0 THEN
  1097.                 Curr_Tarif := NULL;
  1098.                 -- Тариф на СДПТ.
  1099.                 FOR i IN 101..150 LOOP
  1100.                   IF Services.EXISTS(i) AND NVL(Services(i).State_Srv,1) = 1 THEN
  1101.                     Curr_Tarif := NVL(Curr_Tarif,0) + Tarif(i, Services(ServiceNo).Norm_ID) - Tarif(i, Services(ServiceNo).Norm_ID)*Dotacya(i, Services(ServiceNo).Norm_ID);
  1102.                   END IF;
  1103.                 END LOOP;
  1104.                 -- Если нет СДПТ - то ВЭР.
  1105.                 IF Curr_Tarif IS NULL AND (Services.EXISTS(11) AND NVL(Services(11).State_Srv,1) = 1) THEN
  1106.                   Curr_Tarif := Tarif(11, Services(ServiceNo).Norm_ID);
  1107.                 END IF;                  
  1108.                 -- Если и ВЭРа нет - то Квартплата.
  1109.                 IF Curr_Tarif IS NULL AND (Services.EXISTS(1) AND NVL(Services(1).State_Srv,1) = 1) THEN
  1110.                   Curr_Tarif := Tarif(1, Services(ServiceNo).Norm_ID);
  1111.                 END IF;
  1112.                 -- Если ничего нет - взять половину домового тарифа СДПТ.
  1113.                 IF Curr_Tarif IS NULL THEN
  1114.                   FOR i IN 101..150 LOOP
  1115.                     Curr_Tarif := NVL(Curr_Tarif,0) + Tarif(i, Services(ServiceNo).Norm_ID, TRUE) - Tarif(i, Services(ServiceNo).Norm_ID, TRUE)*Dotacya(i, Services(ServiceNo).Norm_ID, TRUE);
  1116.                   END LOOP;
  1117.                 END IF;
  1118.                 Curr_Tarif := Curr_Tarif * 0.5;
  1119.               END IF;            
  1120.               Summ_Nach := Volume_Nach * Curr_Tarif;              
  1121.             ELSE
  1122.               Summ_Nach := Volume_Nach * Curr_Tarif;
  1123.               print('    Summ_Nach = '||Volume_Nach||'[Volume_Nach] * '||Curr_Tarif||'[Curr_Tarif] = '||Summ_Nach);
  1124.               AccrualsDescription27('    сумма начисления = '||Volume_Nach||'[объем услуги] * '||Curr_Tarif||'[тариф] = '||Summ_Nach);
  1125.             END IF;                                                        
  1126.           END IF; -- Выбор формулы вычисления для услуги.
  1127.          
  1128.           -- Применить к сумме понижающий стоимость коэффициент:
  1129.           tmp_numb3 := ServiceNo;
  1130.           IF tmp_numb3 BETWEEN 101 AND 126 THEN
  1131.             tmp_numb3 := 100;
  1132.           END IF;
  1133.           tmp_numb := GetKoeff(Data_prev, tmp_numb3, 2);
  1134.           IF tmp_numb < 1 THEN
  1135.             tmp_numb2 := Summ_Nach;
  1136.             Summ_Nach := tmp_numb2 * tmp_numb;
  1137.             print('    Summ_Nach = '||tmp_numb2||'[Summ_Nach] * '||tmp_numb||'[GetKoeff('||Data_prev||', '||tmp_numb3||', 2)] = '||Summ_Nach);
  1138.             AccrualsDescription27('    сумма начисления = '||tmp_numb2||'[сумма начисления] * '||tmp_numb||'[коэффициент понижения стоимости] = '||Summ_Nach);
  1139.           END IF;              
  1140.          
  1141.                        
  1142.           -- ДОТАЦИЯ.
  1143.           tmp_numb := Dotacya(ServiceNo, Services(ServiceNo).Norm_ID)/100;            
  1144.           Dotac := Summ_Nach * tmp_numb;
  1145.           print('    Dotac = '||Summ_Nach||'[Summ_Nach] * '||tmp_numb||'[Dotacya(ServiceNo,Norm_ID)/100] = '||Dotac);
  1146.                    
  1147.           -- ПОКАЗАНИЯ СЧЕТЧИКОВ.
  1148.           MonthNach_Sch := NULL;  
  1149.           Volume_Nach_Sch := 0;
  1150.           Summ_Nach_Sch := 0;
  1151.           LastDayInCurrDiapason := LAST_DAY(data_prev) + 1;
  1152.           IF LastDayInCurrDiapason > ist.Data THEN
  1153.             LastDayInCurrDiapason := ist.Data;
  1154.           END IF;
  1155.           IF ServiceIsCounter(ServiceNo) THEN -- Счетчик.
  1156.             Indication_No := Indications.FIRST;
  1157.             WHILE Indication_No IS NOT NULL LOOP
  1158.               IF Indications(Indication_No).ServiceID = ServiceNo AND
  1159.                 LastDayInCurrDiapason >= Indications(Indication_No).Data_prev AND
  1160.                 data_prev < Indications(Indication_No).Data_curr
  1161.               THEN  
  1162.                 -- Кол-во дней в показаниях.
  1163.                 Indication_KolDay := Indications(Indication_No).Data_curr - Indications(Indication_No).Data_prev;
  1164.                 -- Кол-во дней показаний, выходящих за границу текущего "окна" начислений.
  1165.                 Indication_KolDayOut := 0;
  1166.                 IF data_prev > Indications(Indication_No).Data_prev THEN
  1167.                   Indication_KolDayOut := Indication_KolDayOut + (data_prev - Indications(Indication_No).Data_prev);
  1168.                 END IF;    
  1169.                 IF LastDayInCurrDiapason < Indications(Indication_No).Data_curr THEN
  1170.                   Indication_KolDayOut := Indication_KolDayOut + (Indications(Indication_No).Data_curr - LastDayInCurrDiapason);  
  1171.                 END IF;
  1172.                 -- Часть объема счетчика, приходящаяся на текущее "окно" начисления.
  1173.                 IF Indication_KolDay <> 0 THEN
  1174.                   Indication_part := (Indication_KolDay - Indication_KolDayOut)/Indication_KolDay;
  1175.                 ELSE
  1176.                   Indication_part := 0;
  1177.                 END IF;        
  1178.                 -- Месяц, в который запишутся показания (может не совпадать с текущим или отчетным!).
  1179.                 MonthNach_Sch := Indications(Indication_No).MONTH;
  1180.                 -- Объем.
  1181.                 Volume_Nach_Sch := Indications(Indication_No).Volume * Indication_part;
  1182.                 IF ServiceNo = 10 THEN -- Электричество.
  1183.                   Summ_Nach_Sch := CalcSummByTarifsE(LastDayInCurrDiapason-1, NormNo, Volume_Nach_Sch, Month_Part);
  1184.                 ELSE
  1185.                   Summ_Nach_Sch := Volume_Nach_Sch * Curr_Tarif;
  1186.                 END IF;    
  1187.                 -- Добавить вычисленные значения в список.
  1188.                 AccrualNo := GetAccrualNo(TRUE, MonthNach_Sch, 1, ServiceNo, NULL, NULL);
  1189.                 Accruals(AccrualNo).Volume  := Accruals(AccrualNo).Volume  + Volume_Nach_Sch;
  1190.                 Accruals(AccrualNo).Summ    := Accruals(AccrualNo).Summ    + Summ_Nach_Sch;
  1191.                 Accruals(AccrualNo).Tarif   := Curr_Tarif;
  1192.                 -- Прекратить перебор показаний, т.к. в один период по одной услуге могут быть только одни показания.
  1193.                 EXIT;
  1194.               END IF;
  1195.               Indication_No := Indications.NEXT(Indication_No);
  1196.             END LOOP;
  1197.           END IF;
  1198.                  
  1199.           -- Если Л/С открыт и услуга действительна.
  1200.           IF AccountState = 1 AND NVL(Services(ServiceNo).State_Srv,1) = 1 THEN        
  1201.             -- Добавить вычисленные значения в список.  
  1202.             IF NOT ServiceIsCounter(ServiceNo) THEN -- Техрасчет.
  1203.               AccrualNo := GetAccrualNo(TRUE, CurrMonthNach, 1, ServiceNo, NULL, NULL);
  1204.               Accruals(AccrualNo).Volume  := Accruals(AccrualNo).Volume  + Volume_Nach;
  1205.               Accruals(AccrualNo).Summ    := Accruals(AccrualNo).Summ    + Summ_Nach;
  1206.               Accruals(AccrualNo).Dotacya := Accruals(AccrualNo).Dotacya + Dotac;
  1207.               Accruals(AccrualNo).Tarif   := Curr_Tarif;
  1208.             ELSE -- Счетчик.
  1209.               -- Добавить нулевые значения для открытой услуги без показаний, чтобы выгружалось в ГЕРЦ.
  1210.               AccrualNo := GetAccrualNo(TRUE, CurrMonthNach, 1, ServiceNo, NULL, NULL);
  1211.             END IF;
  1212.  
  1213.             -- ЛЬГОТЫ.
  1214.             -- Отсортировать льготы по % для текущей услуги.
  1215.             SortedPrivils.DELETE;
  1216.             PrivilNo := Privils.FIRST;
  1217.             WHILE PrivilNo IS NOT NULL LOOP
  1218.               PrvlSrvPrcNo := Privils(PrivilNo).Privil_ID * 100000 + ServiceNo;
  1219.               IF PrvlSrvPrc.EXISTS(PrvlSrvPrcNo) AND PrvlSrvPrc(PrvlSrvPrcNo) > 0 THEN
  1220.                 SortedPrivils(NVL(SortedPrivils.COUNT,0)+1) := Privils(PrivilNo);
  1221.                 FOR i IN REVERSE 2..SortedPrivils.COUNT LOOP
  1222.                   IF (PrvlSrvPrc(SortedPrivils(i).Privil_ID*100000+ServiceNo) > PrvlSrvPrc(SortedPrivils(i-1).Privil_ID*100000+ServiceNo)) OR
  1223.                      (PrvlSrvPrc(SortedPrivils(i).Privil_ID*100000+ServiceNo) = PrvlSrvPrc(SortedPrivils(i-1).Privil_ID*100000+ServiceNo) AND SortedPrivils(i).Count_Prvl > SortedPrivils(i-1).Count_Prvl) OR
  1224.                      (PrvlSrvPrc(SortedPrivils(i).Privil_ID*100000+ServiceNo) = PrvlSrvPrc(SortedPrivils(i-1).Privil_ID*100000+ServiceNo) AND SortedPrivils(i).Count_Prvl = SortedPrivils(i-1).Count_Prvl AND SortedPrivils(i).Peopl_ID < SortedPrivils(i-1).Peopl_ID)
  1225.                   THEN
  1226.                     tmpPrivil := SortedPrivils(i-1);
  1227.                     SortedPrivils(i-1) := SortedPrivils(i);
  1228.                     SortedPrivils(i) := tmpPrivil;
  1229.                   ELSE
  1230.                     EXIT;
  1231.                   END IF;
  1232.                 END LOOP;
  1233.               END IF;
  1234.               PrivilNo := Privils.NEXT(PrivilNo);
  1235.             END LOOP;
  1236.            
  1237.             Volume_Prvl := 0;
  1238.             LInhabitRest := Count_Inhabit;
  1239.             LVolumeRest := Volume_Social_Nach;            
  1240.             LVolumeRest_Sch := Volume_Social_Nach; --Volume_Nach_Sch;
  1241.             AddSanCharged := 1;            
  1242.            
  1243.             print('    Volume_Prvl = '||Volume_Prvl||'[const]; LInhabitRest = '||LInhabitRest||'[Count_Inhabit]; LVolumeRest = '||LVolumeRest||'[Volume_Social_Nach];');
  1244.             AccrualsDescription27('    объем по льготе = '||Volume_Prvl||'[const]; количество проживающих, для которых доступна льгота = '||LInhabitRest||'[количество проживающих]; объем, доступный для льготной компенсации = '||LVolumeRest||'[начисленный социальный объем];');
  1245.            
  1246.             -- Перебрать уже отсортированные льготы.
  1247.             PrivilNo := SortedPrivils.FIRST;
  1248.             WHILE PrivilNo IS NOT NULL LOOP -- Цикл по всем льготам абонента.            
  1249.               print('    PrivilNo = '||PrivilNo||';');
  1250.               AccrualsDescription27('    Номер льготы = '||PrivilNo||';');
  1251.              
  1252.               PrvlSrvPrcNo := SortedPrivils(PrivilNo).Privil_ID * 100000 + ServiceNo;
  1253.               -- Ограничить количество льготников при необходимости.
  1254.               IF SortedPrivils(PrivilNo).Count_Prvl > LInhabitRest THEN
  1255.                 LInhabit := LInhabitRest;
  1256.                 LInhabitRest := 0;
  1257.               ELSE
  1258.                 LInhabit := SortedPrivils(PrivilNo).Count_Prvl;
  1259.                 LInhabitRest := LInhabitRest - LInhabit;
  1260.               END IF;
  1261.               print('      LInhabit = '||LInhabit||'; LInhabitRest = '||LInhabitRest||';');
  1262.               AccrualsDescription27('      количество льготников  = '||LInhabit||'; остаток проживающих = '||LInhabitRest||';');
  1263.              
  1264.               -- Вычисление льготного объема услуги.
  1265.               IF ServiceIsCounter(ServiceNo) THEN  
  1266.                 -- 23.05.2012 Для счетчиков не начислять льгот больше нормы.
  1267.                 --tmp_numb := Volume_Nach; -- Volume_Nach_Sch;    
  1268.                 -- tmp_numb := Volume_Nach_Sch;
  1269.                 IF Volume_Nach > Volume_Nach_Sch THEN
  1270.                    tmp_numb := Volume_Nach_Sch;
  1271.                    print('      Volume_Prvl100 = [Volume_Nach_Sch] = '||tmp_numb||';');
  1272.                  ELSE
  1273.                    tmp_numb := Volume_Nach;
  1274.                    print('      Volume_Prvl100 = [Volume_Nach] = '||tmp_numb||';');
  1275.                  END IF;
  1276.               ELSE                    
  1277.                 tmp_numb := Volume_Nach;
  1278.                 print('      Volume_Prvl100 = [Volume_Nach] = '||tmp_numb||';');
  1279.               END IF;
  1280.               IF ServiceNo = 10 THEN -- Электричество: первому человеку одна норма, всем последующим - друая, но не больше социаьнгой норммы.
  1281.                 tmp_numb :=
  1282.                   (
  1283.                     CASE WHEN PrivilNo = 1 THEN Norms(NormNo).Norm ELSE Norms(NormNo).Norm_Slave_Persons END +  
  1284.                     CASE WHEN LInhabit > 1 THEN (LInhabit-1)*Norms(NormNo).Norm_Slave_Persons ELSE 0 END
  1285.                   ) * Month_Part;
  1286.                 IF Volume_Social_Nach > Norms(NormNo).Norm_Social * Month_Part THEN
  1287.                   Volume_Social_Nach := Norms(NormNo).Norm_Social * Month_Part;
  1288.                 END IF;
  1289.               ELSIF Services(ServiceNo).Formula IN (20,21) OR ServiceNo IN (41,5,28,53) THEN  -- Льгота зависит от льготников или это плита либо вода.
  1290.                 tmp_numb := tmp_numb / GREATEST((Count_Inhabit - Count_Wanting),1) * LInhabit;
  1291.                 print('      Volume_Prvl100 = [Volume_Prvl100]/MAX(('||Count_Inhabit||'[Count_Inhabit] - '||Count_Wanting||'[Count_Wanting]),1) * '||LInhabit||'[LInhabit] = '||tmp_numb||';');
  1292.                 tmp_numb2 := Volume_Social_Nach / GREATEST((Count_Inhabit - Count_Wanting),1) * LInhabit;  -- Социальный объем с точностью до количества льготников
  1293.                 IF tmp_numb > tmp_numb2 THEN
  1294.                   print('      Volume_Social_Nach_by_Privil = '||Volume_Social_Nach||'[Volume_Social_Nach]/MAX(('||Count_Inhabit||'[Count_Inhabit] - '||Count_Wanting||'[Count_Wanting]),1) * '||LInhabit||'[LInhabit] = '||tmp_numb2||';');
  1295.                   print('      Volume_Prvl100 = '||tmp_numb2||'[Volume_Social_Nach_by_Privil] (поскольку '||tmp_numb||'[Volume_Prvl100] > '||tmp_numb2||'[Volume_Social_Nach_by_Privil]);');
  1296.                   tmp_numb := tmp_numb2;
  1297.                 END IF;
  1298.               ELSIF Services(ServiceNo).Formula IN (30,31,32) OR ServiceNo IN (4) THEN  -- Льгота зависит от сан.нормы площади или это АГВ.
  1299.                 --tmp_numb := (LInhabit*Norms(1).Norm_Social/*Норма площади на человека*/ + AddSanCharged*/*Учесть только для одной льготы*/(Area_AddSan + Norms(2).Norm_Social/*Норма площади на семью*/)) * Norms(NormNo).Norm_Social * Month_Part;
  1300.                 tmp_numb := (LInhabit*Norms(1).Norm_Social/*Норма площади на человека*/ + AddSanCharged*/*Учесть только для одной льготы*/(Area_AddSan + Norms(2).Norm_Social/*Норма площади на семью*/));
  1301.                 print('      Volume_Prvl100 = ('||LInhabit||'[LInhabit] * '||Norms(1).Norm_Social||'[Norms(1).Norm_Social] + '||AddSanCharged||'[AddSanCharged] * ('||Area_AddSan||'[Area_AddSan] + '||Norms(2).Norm_Social||'[Norms(2).Norm_Social])) = '||tmp_numb||';');
  1302.                 AccrualsDescription27('      объем по льготе = ('||LInhabit||'[количество льготников] * '||Norms(1).Norm_Social||'[социальная норма] + '||AddSanCharged||'[только на одну льготу] * ('||Area_AddSan||'[доп.сан.площадь] + '||Norms(2).Norm_Social||'[социальная норма])) = '||tmp_numb||';');
  1303.                 IF ServiceNo = 27 THEN
  1304.                   tmp_numb := LEAST(tmp_numb, Area_Obsch);
  1305.                   print('      Volume_Prvl100 = MIN([Volume_Prvl100], '||Area_Obsch||'[Area_Obsch]) = '||tmp_numb||';');
  1306.                   AccrualsDescription27('      объем по льготе = MIN([объем по льготе], '||Area_Obsch||'[общая площадь]) = '||tmp_numb||';');
  1307.                   tmp_numb := tmp_numb * Norms(NormNo).Norm * Month_Part; --LEAST(Norms(NormNo).Norm, Norms(NormNo).Norm_Social) * Month_Part;
  1308.                   print('      Volume_Prvl100 = [Volume_Prvl100] * '||Norms(NormNo).Norm||'[Norms(NormNo).Norm] * '||Month_Part||'[Month_Part] = '||tmp_numb||';');
  1309.                   AccrualsDescription27('      объем по льготе = [объем по льготе] * '||Norms(NormNo).Norm||'[норма услуги] * '||Month_Part||'[часть месяца в сегменте расчета] = '||tmp_numb||';');
  1310.                   tmp_numb2 := GetHeatReductionFactor(Data_prev);
  1311.                   tmp_numb := tmp_numb * tmp_numb2;
  1312.                   print('      Volume_Prvl100 = [Volume_Prvl100] * '||tmp_numb2||'[HeatReductionFactor] = '||tmp_numb||';');
  1313.                   AccrualsDescription27('      объем по льготе = [объем по льготе] * '||tmp_numb2||'[часть месяца подачи тепла] = '||tmp_numb||';');
  1314.                 ELSE
  1315.                   tmp_numb := tmp_numb * Norms(NormNo).Norm_Social * Month_Part;
  1316.                   print('      Volume_Prvl100 = [Volume_Prvl100] * '||Norms(NormNo).Norm_Social||'[Norms(NormNo).Norm_Social] * '||Month_Part||'[Month_Part] = '||tmp_numb||';');
  1317.                 END IF;
  1318.                 AddSanCharged := 0;
  1319.               END IF;
  1320.               -- Ограничить льготный объем при необходимости.
  1321.               IF ServiceIsCounter(ServiceNo) THEN
  1322.                 IF tmp_numb > LVolumeRest_Sch THEN
  1323.                   tmp_numb := LVolumeRest_Sch;
  1324.                   LVolumeRest_Sch := 0;
  1325.                 ELSE
  1326.                   LVolumeRest_Sch := LVolumeRest_Sch - tmp_numb;
  1327.                 END IF;    
  1328.                 print('      LVolumeRest_Sch = '||LVolumeRest_Sch||';');
  1329.               ELSE
  1330.                 IF tmp_numb > LVolumeRest THEN
  1331.                   tmp_numb := LVolumeRest;
  1332.                   print('      Volume_Prvl100 = '||LVolumeRest||'[LVolumeRest] (поскольку [Volume_Prvl100] > [LVolumeRest]);');
  1333.                   LVolumeRest := 0;
  1334.                 ELSE
  1335.                   LVolumeRest := LVolumeRest - tmp_numb;
  1336.                 END IF;
  1337.                 print('      LVolumeRest = '||LVolumeRest||';');
  1338.               END IF;
  1339.               AccrualsDescription27('      объем, доступный для льготной компенсации = '||LVolumeRest||';');
  1340.                  
  1341.               Volume_Prvl100 := tmp_numb;  -- Льготный объем без процента льготы.
  1342.               tmp_numb2 := PrvlSrvPrc(PrvlSrvPrcNo);
  1343.               Volume_Prvl := tmp_numb * tmp_numb2;
  1344.               print('      Volume_Prvl = '||tmp_numb||'[Volume_Prvl100] * '||tmp_numb2||'[PrvlSrvPrc] = '||Volume_Prvl||';');
  1345.               AccrualsDescription27('      объем по льготе с учетом % = '||tmp_numb||'[объем по льготе] * '||tmp_numb2||'[процент льготы] = '||Volume_Prvl||';');
  1346.              
  1347.               IF ServiceNo = 10 THEN -- Электричество.
  1348.                 Summ_Prvl := CalcSummByTarifsE(ist.Data-1, NormNo, Volume_Prvl, Month_Part);
  1349.               ELSE
  1350.                 tmp_numb2 := Dotacya(ServiceNo, Services(ServiceNo).Norm_ID);
  1351.                 Summ_Prvl := Volume_Prvl * Curr_Tarif * (1 - tmp_numb2/100);
  1352.                 print('      Summ_Prvl = '||Volume_Prvl||'[Volume_Prvl] * '||Curr_Tarif||'[Curr_Tarif] * (1 - '||tmp_numb2||'[Dotacya]/100) = '||Summ_Prvl||';');
  1353.                 AccrualsDescription27('      сумма льготной компенсации = '||Volume_Prvl||'[объем по льготе с учетом %] * '||Curr_Tarif||'[тариф] * (1 - '||tmp_numb2||'[дотация])/100 = '||Summ_Prvl||';');
  1354.               END IF;    
  1355.  
  1356.               -- Добавить вычисленную льготу в список.
  1357.               IF ServiceIsCounter(ServiceNo) THEN
  1358.                 AccrualNo := GetAccrualNo(TRUE, MonthNach_Sch, 2, ServiceNo, SortedPrivils(PrivilNo).Privil_ID, SortedPrivils(PrivilNo).Peopl_ID);
  1359.               ELSE
  1360.                 AccrualNo := GetAccrualNo(TRUE, CurrMonthNach, 2, ServiceNo, SortedPrivils(PrivilNo).Privil_ID, SortedPrivils(PrivilNo).Peopl_ID);
  1361.               END IF;
  1362.              
  1363.               Accruals(AccrualNo).Volume    := Accruals(AccrualNo).Volume    + Volume_Prvl;
  1364.               Accruals(AccrualNo).Volume100 := Accruals(AccrualNo).Volume100 + Volume_Prvl100;
  1365.               Accruals(AccrualNo).Summ      := Accruals(AccrualNo).Summ      + Summ_Prvl;
  1366.               Accruals(AccrualNo).Tarif     := Curr_Tarif;              
  1367.               PrivilNo := SortedPrivils.NEXT(PrivilNo);
  1368.             END LOOP; -- Цикл по всем льготам абонента.
  1369.           END IF; -- Л/С открыт и услуга действительна.                          
  1370.           ServiceNo := Services.NEXT(ServiceNo);
  1371.         END LOOP;  -- Цикл по всем услугам.
  1372.         -- Перейти к следующей дате.
  1373.         IF TRUNC(Data_prev, 'MM') < TRUNC(ist.Data, 'MM') THEN
  1374.           Data_prev := LAST_DAY(Data_prev) + 1;
  1375.         ELSE
  1376.           Data_Prev := ist.Data;
  1377.         END IF;        
  1378.       END LOOP;  -- Помесячный цикл в промежутке между двумя датами.
  1379.     END IF;  -- Если текущая дата больше предыдущей.
  1380.     /* 04.11.2011 Вроде как лишняя строчка?
  1381.     Data_Prev := ist.Data;
  1382.     */
  1383.     -- ИЗМЕНЕНИЕ ПАРАМЕТРОВ, ВЛИЯЮЩИХ НА НАЧИСЛЕНИЕ.
  1384.     IF    ist.Vid = 'L' THEN  -- Изменение Л/С.
  1385.       AccountState  := NVL(ist.Status_ID,0);
  1386.       Area_Obsch    := NVL(ist.Area_Obsch ,0);
  1387.       Area_Polezn   := NVL(ist.Area_Polezn,0);
  1388.       Area_Gilay    := NVL(ist.Area_Gilay,0);
  1389.       Area_AddSan   := NVL(ist.Area_AddSan,0);
  1390.       Count_Inhabit := GREATEST(NVL(ist.Count_Inhabit,0),1);
  1391.       ShortFamily   := NVL(ist.ShortFamily,'N');
  1392.       Surplus       := NVL(ist.Surplus,'N');
  1393.       Cgv           := NVL(ist.Cgv,'N');
  1394.     ELSIF ist.Vid = 'W' THEN  -- Отсутствующие.
  1395.       Count_Wanting := NVL(ist.Count_W,0);
  1396.     ELSIF ist.Vid = 'H' THEN  -- Изменения дома.
  1397.        Category   := NVL(ist.Category, 0);
  1398.     ELSIF ist.Vid = 'P' THEN  -- Изменение льгот Л/С.
  1399.       IF ist.State_Prvl = 1 THEN  -- Активная льгота.
  1400.         PrivilNo := GetPrivilNo(TRUE, ist.Privil_ID, ist.Peopl_ID);
  1401.         Privils(PrivilNo).Count_Prvl := ist.Count_Prvl;
  1402.       ELSE  -- Закрытая льгота.
  1403.         PrivilNo := GetPrivilNo(FALSE, ist.Privil_ID, ist.Peopl_ID);
  1404.         IF PrivilNo IS NOT NULL THEN
  1405.           Privils.DELETE(PrivilNo);
  1406.         END IF;
  1407.       END IF;
  1408.     ELSIF ist.Vid = 'S' THEN  -- Изменение услуг у Л/С.
  1409.       IF ist.State_Srv = 1 THEN  -- Открытие услуги.
  1410.         Services(ist.Service_ID).Formula := ist.Formula;
  1411.         Services(ist.Service_ID).Params  := NVL(ist.Params,0);
  1412.         Services(ist.Service_ID).Norm_ID := ist.Norm_ID;
  1413.       ELSE  -- Закрытие услуги.
  1414.         Services.DELETE(ist.Service_ID);
  1415.       END IF;
  1416.     ELSIF ist.Vid = 'O' THEN  -- Временное закрытие услуги у дома.
  1417.       IF Services.EXISTS(ist.Service_ID_O) THEN
  1418.         Services(ist.Service_ID_O).State_Srv := ist.State_Srv_O;
  1419.       END IF;
  1420.     ELSIF ist.Vid = 'N' THEN  -- Изменение значений норм.
  1421.       Norms(ist.SrvNorm_ID).Norm := ist.Norm;
  1422.       Norms(ist.SrvNorm_ID).Norm_Social := ist.Norm_Social;
  1423.       Norms(ist.SrvNorm_ID).Norm_Slave_Persons := ist.Norm_Slave_Persons;
  1424.       Norms(ist.SrvNorm_ID).Period := ist.Period;
  1425.     ELSIF ist.Vid = 'T' THEN  -- Изменение значений общих тарифов.
  1426.       Tarifs(ist.Service_ID_T*1000000 + ist.SrvNorm_ID_T*100 + ist.TrSchema).Tarif := NVL(ist.Tarif,0);
  1427.       Tarifs(ist.Service_ID_T*1000000 + ist.SrvNorm_ID_T*100 + ist.TrSchema).Dotacya := NVL(ist.Dotacya,0);
  1428.     ELSIF ist.Vid = 'E' THEN  -- Изменение тарифов на электричество.
  1429.       tmp_numb := NVL(TarifsE.LAST,0) + 1;
  1430.       TarifsE(tmp_numb).SrvNorm_ID := ist.SrvNorm_ID_E;
  1431.       TarifsE(tmp_numb).Data := ist.Data;
  1432.       TarifsE(tmp_numb).Data_End := ist.Data_End;
  1433.       TarifsE(tmp_numb).Volume_Min := ist.Volume_Min;
  1434.       TarifsE(tmp_numb).Volume_Max := ist.Volume_Max;
  1435.       TarifsE(tmp_numb).Tarif := ist.Tarif_E;
  1436.     ELSIF ist.Vid = 'J' THEN  -- Изменение значений домовых тарифов.
  1437.       TarifsH(ist.Service_ID_J*1000000 + ist.SrvNorm_ID_J*100).Tarif := NVL(ist.TarifH,0);
  1438.       TarifsH(ist.Service_ID_J*1000000 + ist.SrvNorm_ID_J*100).Dotacya := NVL(ist.DotacyaH,0);
  1439.     END IF;  -- Изменение параметров начисления.
  1440.   END LOOP; -- Конец цикла по всем событиям в период начисления.
  1441.  
  1442.   --------------------------------------------------------------------------------------
  1443.   --  /--\ |  / |--\ |  | |--\   /| |--\ |  | |  | |--\     /--\   /--|  |---| /---\  --
  1444.   --  |  | | /  |  | |  | |     / | |    |  | |  | |        |      |  |  |   |   |    --
  1445.   --  |  | |<   |--/ \--| |    |  | |--  |--| | /| |--      |      |  |  |   |   |    --
  1446.   --  |  | | \  |       | |    |  | |    |  | |/ | |        |     /----\ |   |   |    --
  1447.   --  \--/ |  \ |    \--/ |    |  | |--/ |  | |  | |--/ 9   \--/  |    | |   |   |    --
  1448.   --------------------------------------------------------------------------------------
  1449.   AccrualNo := Accruals.FIRST;
  1450.   WHILE AccrualNo IS NOT NULL LOOP
  1451.     IF Accruals(AccrualNo).Service_ID BETWEEN 101 AND 150 THEN -- ИД услуги между 101 и 150 (составляющие СДПТ).
  1452.       Accruals(AccrualNo).Summ    := TRUNC(Accruals(AccrualNo).Summ,   4);
  1453.       Accruals(AccrualNo).Dotacya := TRUNC(Accruals(AccrualNo).Dotacya,4);
  1454.       -- Составляющие СДПТ.
  1455.       AccrualNo2 := GetAccrualNo(TRUE, Accruals(AccrualNo).Data, Accruals(AccrualNo).Vid, 100, Accruals(AccrualNo).Privil_ID, Accruals(AccrualNo).Peopl_ID);
  1456.       IF Accruals(AccrualNo).Volume <> 0 AND Accruals(AccrualNo2).Volume = 0 THEN -- Объем по 100 услуге равен объемы первой встреченной составляющей.
  1457.         Accruals(AccrualNo2).Volume := Accruals(AccrualNo).Volume;                                      
  1458.         Accruals(AccrualNo2).Volume100 := Accruals(AccrualNo).Volume100;
  1459.       END IF;
  1460.       Accruals(AccrualNo2).Summ    := Accruals(AccrualNo2).Summ    + Accruals(AccrualNo).Summ;
  1461.       Accruals(AccrualNo2).Dotacya := Accruals(AccrualNo2).Dotacya + Accruals(AccrualNo).Dotacya;
  1462.     ELSIF Accruals(AccrualNo).Service_ID = 100 THEN  -- СДПТ не трогать, т.к. это сумма уже усеченных составляющих.
  1463.       NULL;
  1464.     ELSIF Accruals(AccrualNo).Service_ID = 14 THEN  -- Лифт также, как и СДПТ, усекать до 4-х знаков, а не округлять.
  1465.       Accruals(AccrualNo).Summ := TRUNC(Accruals(AccrualNo).Summ, 4);    
  1466.     ELSE
  1467.       Accruals(AccrualNo).Summ := ROUND(Accruals(AccrualNo).Summ, 2);
  1468.     END IF;
  1469.     AccrualNo := Accruals.NEXT(AccrualNo);
  1470.   END LOOP;
  1471.                    
  1472.   -------------------------------------------------------------------------------------------------
  1473.   --  /--\    /|  |---| |   | /--\ |       |  |   /| |  | |   | /--\   /| |--\ |  | |   |   -    --
  1474.   --     /  /  |  |   | |   | |    |       |  | /  | |  | |   | |    /  | |    |  | |   | |   |  --
  1475.   --    -   |  |  |   | |  /| |    |--\    |--| |  |  \_| |  /| |    |  | |--  |--| |  /| |  /|  --
  1476.   --     \  |--|  |   | |/  | |    |  |    |  | |--|    | |/  | |    |  | |    |  | |/  | |/  |  --
  1477.   --  \--/  |  |  |   | |   | \--/ \--/    |  | |  |    | |   | \--/ |  | |--/ |  | |   | |   |  --
  1478.   -------------------------------------------------------------------------------------------------
  1479.   /*
  1480.   AccrualNo := Accruals.FIRST;
  1481.   WHILE AccrualNo IS NOT NULL LOOP  
  1482.     if Accruals(AccrualNo).Service_ID = 28 then
  1483.       dbms_output.put_line(AccrualNo||': Service_ID='||Accruals(AccrualNo).Service_ID||'; Data='||Accruals(AccrualNo).Data||'; Vid='||Accruals(AccrualNo).Vid||
  1484.         '; Volume='||Accruals(AccrualNo).Volume||'; Summ='||Accruals(AccrualNo).Summ||'; Dotacya='||Accruals(AccrualNo).Dotacya||
  1485.         '; Privil_ID='||Accruals(AccrualNo).Privil_ID||'; Peopl_ID='||Accruals(AccrualNo).Peopl_ID||'; Volume100='||Accruals(AccrualNo).Volume100);
  1486.     end if;
  1487.     AccrualNo := Accruals.NEXT(AccrualNo);    
  1488.   END LOOP;
  1489.   */
  1490.  
  1491.   Old_SverkaSumm := GetSverkaSumm(LPAD(AccID, 12, '0')); -- Запомнить сумму сверок до перерасчета.
  1492.  
  1493.   -- Перебрать все уже существующие в базе начисления.
  1494.   FOR a IN (
  1495.     SELECT ROWID, a.*
  1496.     FROM n_Accruals a
  1497.     WHERE Account_ID = LPAD(AccID, 12, '0')
  1498.       AND Data BETWEEN Data_Beg_Nach AND Data_End_Nach
  1499.       AND Vid IN (1,2,3,4)
  1500.   )LOOP              
  1501.     IF a.Data < FinMonth THEN  -- Дата меньше отчетного месяца.
  1502.       -- Для начисленного по домовым счетчикам сверки не формировать,
  1503.       -- т.к. автоматический перерасчет задним числом по домовому счетчику невозможен!
  1504.       IF NVL(a.ByHouseCounter,0) <> 1 THEN
  1505.         IF a.Vid IN (1,2) THEN -- Начисление.
  1506.           AccrualNo := GetAccrualNo(FALSE, a.Data, a.Vid, a.Service_ID, a.Privil_ID, a.Peopl_ID);
  1507.           SverkaNo := GetAccrualNo(TRUE, FinMonth, a.Vid + 2, a.Service_ID, a.Privil_ID, a.Peopl_ID);
  1508.           AddAccrual(SverkaNo, -NVL(a.Volume,0), -NVL(a.Summ,0), -NVL(a.Dotacya,0), -NVL(a.Volume100,0));
  1509.           IF AccrualNo IS NOT NULL THEN
  1510.             AddAccrual(SverkaNo, Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1511.             UpdateAccrual(2/*обновить только реальную половину*/, a.ROWID, NULL, NULL, NULL, NULL, NULL, NULL,
  1512.               NULL, NULL, NULL, NULL, NULL, NULL,
  1513.               Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1514.             Accruals.DELETE(AccrualNo);
  1515.           ELSE
  1516.             UpdateAccrual(2/*обновить только реальную половину*/, a.ROWID, NULL, NULL, NULL, NULL, NULL, NULL,
  1517.               NULL, NULL, NULL, NULL, NULL, NULL,
  1518.               0, 0, 0, 0);
  1519.           END IF;
  1520.         ELSIF a.Vid IN (3,4) THEN -- Сверка.
  1521.           SverkaNo := GetAccrualNo(TRUE, FinMonth, a.Vid, a.Service_ID, a.Privil_ID, a.Peopl_ID);
  1522.           AddAccrual(SverkaNo, -a.Volume, -a.Summ, -a.Dotacya, -a.Volume100);
  1523.         END IF;
  1524.       END IF;
  1525.     ELSIF a.Data = FinMonth THEN -- Дата в отчетном месяце.
  1526.       IF a.Vid IN (1,2) THEN -- Начисление.
  1527.         AccrualNo := GetAccrualNo(FALSE, a.Data, a.Vid, a.Service_ID, a.Privil_ID, a.Peopl_ID);
  1528.         IF AccrualNo IS NOT NULL THEN -- В списке есть начисление, соответствующее найденному в БД.
  1529.           UpdateAccrual(3/*обновить все - и начислено, и реально*/, a.ROWID, NULL, NULL, NULL, NULL, NULL, NULL,
  1530.             Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100, NULL, Accruals(AccrualNo).Tarif,
  1531.             Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1532.           Accruals.DELETE(AccrualNo);
  1533.         ELSE -- В списке нет начисления, соответствующего найденному в БД.
  1534.           DELETE FROM n_Accruals WHERE ROWID = a.ROWID;
  1535.         END IF;
  1536.       ELSIF a.Vid IN (3,4) THEN -- Сверка.
  1537.         SverkaNo := GetAccrualNo(TRUE, a.Data, a.Vid, a.Service_ID, a.Privil_ID, a.Peopl_ID);
  1538.         AddAccrual(SverkaNo, -a.Volume, -a.Summ, -a.Dotacya, -a.Volume100);
  1539.       END IF;      
  1540.     END IF;
  1541.   END LOOP;
  1542.  
  1543.   -- Перебрать все оставшиеся начисления (для которых не было записей в базе).
  1544.   AccrualNo := Accruals.FIRST;
  1545.   WHILE AccrualNo IS NOT NULL LOOP
  1546.     IF Accruals(AccrualNo).Vid IN (1,2) THEN -- Начисления.
  1547.       IF Accruals(AccrualNo).Data < FinMonth THEN -- Неотчетный месяц.
  1548.         SverkaNo := GetAccrualNo(TRUE, FinMonth, Accruals(AccrualNo).Vid + 2, Accruals(AccrualNo).Service_ID, Accruals(AccrualNo).Privil_ID, Accruals(AccrualNo).Peopl_ID);
  1549.         AddAccrual(SverkaNo, Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1550.         UpdateAccrual(5/*перезаписать, а не добавлять*/, NULL, AccID, Accruals(AccrualNo).Data, Accruals(AccrualNo).Vid, Accruals(AccrualNo).Service_ID, Accruals(AccrualNo).Privil_ID, Accruals(AccrualNo).Peopl_ID,
  1551.           NULL, NULL, NULL, NULL, NULL, NULL,
  1552.           Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1553.       ELSIF Accruals(AccrualNo).Data = FinMonth THEN -- Отчетный период.
  1554.         UpdateAccrual(5/*перезаписать, а не добавлять*/, NULL, AccID, Accruals(AccrualNo).Data, Accruals(AccrualNo).Vid, Accruals(AccrualNo).Service_ID, Accruals(AccrualNo).Privil_ID, Accruals(AccrualNo).Peopl_ID,
  1555.           Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100, NULL,  Accruals(AccrualNo).Tarif,
  1556.           Accruals(AccrualNo).Volume, Accruals(AccrualNo).Summ, Accruals(AccrualNo).Dotacya, Accruals(AccrualNo).Volume100);
  1557.       END IF;
  1558.       Accruals.DELETE(AccrualNo);
  1559.     END IF;
  1560.     AccrualNo := Accruals.NEXT(AccrualNo);
  1561.   END LOOP;
  1562.  
  1563.   -- ЗАПИСАТЬ РАССЧИТАННЫЕ СВЕРКИ.
  1564.   SverkaNo := Accruals.FIRST;  
  1565.   WHILE SverkaNo IS NOT NULL LOOP    
  1566.     UpdateAccrual(6/*добавить, а не обновить*/, NULL, AccID, Accruals(SverkaNo).Data, Accruals(SverkaNo).Vid, Accruals(SverkaNo).Service_ID, Accruals(SverkaNo).Privil_ID, Accruals(SverkaNo).Peopl_ID,
  1567.       Accruals(SverkaNo).Volume, Accruals(SverkaNo).Summ, Accruals(SverkaNo).Dotacya, Accruals(SverkaNo).Volume100, Data_Beg_Nach, Accruals(AccrualNo).Tarif,
  1568.       NULL, NULL, NULL, NULL);
  1569.     Accruals.DELETE(SverkaNo);
  1570.     SverkaNo := Accruals.NEXT(SverkaNo);
  1571.   END LOOP;
  1572.                
  1573.   --------------------------------------------------------------------------
  1574.   --  |--\   /| /--\ |  | |--\ /---\     /--\   /|   /| |     |--|  /--\  --
  1575.   --  |  |  / | |    |  | |      |       |     / |  / | |     |  |  |  |  --
  1576.   --  |--/ /  | |    \--| |--    |       |    /  | /  | |--\  |  |  |  |  --
  1577.   --  |    |--| |       | |      |       |    |--| |  | |  |  |  |  |  |  --
  1578.   --  |    |  | \--/    | |--/   |       \--/ |  | |  | |--/ /----\ \--/  --
  1579.   ------------ ПЕРЕСЧИТАТЬ САЛЬДО С УЧЕТОМ ВНЕСЕННЫХ ИЗМЕНЕНИЙ -------------
  1580.   RaschetSaldo(LPAD(AccID, 12, '0'), FinMonth);
  1581.  
  1582.   -- Записать при необходимости сумму изменения сверок для подтверждения.
  1583.   New_SverkaSumm := GetSverkaSumm(LPAD(AccID, 12, '0')); -- Сумма сверок после перерасчета.
  1584.   IF New_SverkaSumm <> Old_SverkaSumm THEN
  1585.     AddSverkaToConfirmation(AccID, New_SverkaSumm - Old_SverkaSumm);
  1586.   END IF;
  1587.  
  1588.   -- Записать подробности по начислению 27 услуги:
  1589.   BEGIN
  1590.     INSERT INTO n_AccrualsDescr(Account_ID, MONTH, Description)
  1591.       VALUES (AccID, FinMonth, AccrualsDescription27Str);
  1592.   EXCEPTION
  1593.     WHEN DUP_VAL_ON_INDEX THEN
  1594.       UPDATE n_AccrualsDescr SET Description = AccrualsDescription27Str
  1595.         WHERE Account_ID = AccID AND MONTH = FinMonth;  
  1596.   END;
  1597.  
  1598. END Nachislenie;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement