IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI]') AND type in (N'P', N'PC'))
DROP PROCEDURE [ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI]
GO
CREATE PROCEDURE st.sp_ROZPISZ_UMORZENIE_NA_CZESCI
@idSrodka INT, @idOperacji INT
AS
declare
@rozbijPoBrutto		bit,
@dataUmorzenia	datetime,
@sumaBruttoBil	money,
@sumaBruttoPod	money,
@sumaNettoBil	money,
@sumaNettoPod	money,
@umorzenieBil	money,
@umorzeniePod	money,
@iloscCzesci	int,
@usunieta_i_netto  int,
@czyJuzRozbite	int,
@roznUmorzBil	money,
@roznUmorzPod	money,
@gorkaUmorzBil		money,
@gorkaUmorzPod	money,
@WartCzesciZGorkaBil	money,
@WartCzesciZGorkaPod money,
@idPoprzUmorz	int
set @idOperacji = IsNull(@idOperacji,0)
set @idPoprzUmorz = 0
set @rozbijPoBrutto = IsNull((select top 1 flUmCzSklPoBrutto from tblSRODKI where id = @idSrodka), 0)
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
kolejny:
select top 1 @dataUmorzenia = DataUmorzenia, @umorzenieBil = UmorzenieBil, @umorzeniePod = UmorzeniePod, @idPoprzUmorz = id from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz order by id
if IsNull(@idPoprzUmorz, 0) = 0  return 1 -- brak rekordu umorzenia
if IsNull(@umorzenieBil, 0) = 0 and IsNull(@umorzeniePod, 0) = 0 -- zerowe umorzenia, nie ma co rozbijac (moze sie zdarzyc przy um historycznym gdy cale um w biez roku)
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
    return 0  -- ok
  end
select @czyJuzRozbite = count(1) from tblCZESCIumorz where IsNull(IdOperacji,0) = @idOperacji and DataUmorzenia = @dataUmorzenia and IdCzesci in (select id from tblSRODKIczesci where IdSrodka = @idSrodka)
if IsNull(@czyJuzRozbite, 0) > 0 -- juz rozbite
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny else return 2 -- juz rozbite
  end
select @sumaNettoBil = sum(WartoscBil - NiePodlegaUmBil - CalkUmorzBil), @sumaNettoPod = sum(WartoscPod - NiePodlegaUmPod - CalkUmorzPod), @iloscCzesci = count(1), @usunieta_i_netto = count(case when round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) <> 0 or round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod,2) <> 0 then 1 else 0 end)
from tblSRODKIczesci
where /*flUsunieta = 0 and*/ IdSrodka = @idSrodka -- zgodnie z nowa strategia usuniete/przeniesione tez sie licza bo czesc ich wartosci, ktora juz sie umozyla zostaje
if IsNull(@iloscCzesci, 0) = 0  return 3  -- brak czesci
if IsNull(@usunieta_i_netto, 0) = 0  return 5  -- czesci usuniete maja niezerowa wartosc netto
if IsNull(@sumaNettoBil, 0) < IsNull(@umorzenieBil, 0) or IsNull(@sumaNettoPod, 0) < IsNull(@umorzeniePod, 0)  return 4  -- zle netto czesci
if @rozbijPoBrutto <> 0 or IsNull(@sumaNettoBil, 0) <= 0 or IsNull(@sumaNettoPod, 0) <= 0 -- jesli srodek ma adekwatna flage lub czesci sa zamortyzowane to trzeba rozbijac po brutto (dotyczy korekt umorz na minus)
  begin
    select @sumaBruttoBil = sum(WartoscBil - NiePodlegaUmBil), @sumaBruttoPod = sum(WartoscPod - NiePodlegaUmPod)
    from tblSRODKIczesci
    where flUsunieta = 0 and IdSrodka = @idSrodka
  end
-- ROZBIJAMY
if (SELECT OBJECT_ID('tempdb..#tempCZESCIumorz')) is not null
	drop table [#tempCZESCIumorz]
select id as IdCzesci, @dataUmorzenia as DataUmorzenia, case when @idOperacji = 0 then NULL else @idOperacji end as IdOperacji, case when @umorzenieBil = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoBil, 0) > 0 then round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil - CalkUmorzBil) / @sumaNettoBil, 2) else round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil) / @sumaBruttoBil, 2) end as UmorzenieBil,
										   case when @umorzeniePod = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoPod, 0) > 0 then round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod - CalkUmorzPod) / @sumaNettoPod, 2) else round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod) / @sumaBruttoPod, 2) end as UmorzeniePod,
										  WartoscBil as WartoscBil, WartoscPod as WartoscPod, NiePodlegaUmBil as NiePodlegaUmBil, NiePodlegaUmPod as NiePodlegaUmPod,
										  round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) as DoUmorzBil,
										  round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod, 2) as DoUmorzPod
into #tempCZESCIumorz
from tblSRODKIczesci
where flUsunieta = 0 and IdSrodka = @idSrodka -- dla czesci usunietych/przeniesionych nie liczymy amortyzacji bo powinny miec netto = 0 (sprawdzane wyzej)
-- jesli jest roznica to trzeba wyrownac
rownanie:
select @roznUmorzBil = sum(UmorzenieBil) - @umorzenieBil, @roznUmorzPod = sum(UmorzeniePod) - @umorzeniePod from #tempCZESCIumorz
if IsNull(@roznUmorzBil, 0) <> 0 update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil - @roznUmorzBil where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzenieBil < DoUmorzBil order by cu1.UmorzenieBil desc, cu1.IdCzesci desc)
if IsNull(@roznUmorzPod, 0) <> 0 update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod - @roznUmorzPod where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzeniePod < DoUmorzPod order by cu1.UmorzeniePod desc, cu1.IdCzesci desc)
if @rozbijPoBrutto <> 0  -- w przypadku rozbijania po brutto jesli kwota umorz dla czesci wykracza poza kwote pozostala do umorzenia to trzeba obciac i przesunac do innej czesci
  begin
    select @gorkaUmorzBil = sum(UmorzenieBil - DoUmorzBil), @WartCzesciZGorkaBil = sum(WartoscBil - NiePodlegaUmBil) from #tempCZESCIumorz  where  UmorzenieBil >= DoUmorzBil
    select @gorkaUmorzPod = sum(UmorzeniePod - DoUmorzPod), @WartCzesciZGorkaPod = sum(WartoscPod - NiePodlegaUmPod) from #tempCZESCIumorz  where  UmorzeniePod >= DoUmorzPod
    if  IsNull(@gorkaUmorzBil, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzenieBil = DoUmorzBil  where  UmorzenieBil > DoUmorzBil  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil + round(@gorkaUmorzBil * (WartoscBil - NiePodlegaUmBil) / (@sumaBruttoBil-@WartCzesciZGorkaBil), 2)  where  UmorzenieBil < DoUmorzBil  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzeniePod = DoUmorzPod  where  UmorzeniePod > DoUmorzPod  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod + round(@gorkaUmorzPod * (WartoscPod - NiePodlegaUmPod) / (@sumaBruttoPod-@WartCzesciZGorkaPod), 2)  where  UmorzeniePod < DoUmorzPod  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzBil, 0) <> 0 or IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        goto rownanie  -- po przenoszeniu może się okazac, ze czesci obdarowane dodatkowym umorzeniem maja za duzo, trzeba sprawdzic i ew jeszcze raz wyrownac
      end
  end
-- ZAPISUJEMY
insert into tblCZESCIumorz (IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod)
select IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod from #tempCZESCIumorz
drop table [#tempCZESCIumorz]
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
return 0
------------------------------------------------------------------------------------------------------------------------------------------
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI_1]') AND type in (N'P', N'PC'))
DROP PROCEDURE [ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI_1]
GO
CREATE PROCEDURE st.sp_ROZPISZ_UMORZENIE_NA_CZESCI_1
@idSrodka INT, @idOperacji INT, @idZmianyCzesci INT
AS
declare
@rozbijPoBrutto		bit,
@dataUmorzenia	datetime,
@sumaBruttoBil	money,
@sumaBruttoPod	money,
@sumaNettoBil	money,
@sumaNettoPod	money,
@umorzenieBil	money,
@umorzeniePod	money,
@iloscCzesci	int,
@usunieta_i_netto  int,
@czyJuzRozbite	int,
@roznUmorzBil	money,
@roznUmorzPod	money,
@gorkaUmorzBil		money,
@gorkaUmorzPod	money,
@WartCzesciZGorkaBil	money,
@WartCzesciZGorkaPod money,
@idPoprzUmorz	int
set @idOperacji = IsNull(@idOperacji,0)
set @idPoprzUmorz = 0
set @rozbijPoBrutto = IsNull((select top 1 flUmCzSklPoBrutto from tblSRODKI where id = @idSrodka), 0)
-- ROBIMY TABELE TYMCZASOWA ZE STANEM CZESCI DLA SRODKA PRZED PODANA OPERACJA (z niej bedziemy korzystac przy rozbijaniu)
-- te ktore zostaly tkniete przez operacje wczesniejsze (poprawne wartosci w tblSRODKIczesci) lub nie bylo dla nich zmian
if (SELECT OBJECT_ID('tempdb..#tblSRODKIczesci')) is not null
	drop table [#tblSRODKIczesci]
select * into #tblSRODKIczesci from (
select id, IdSrodka, Numer, Nazwa COLLATE database_default as Nazwa, NrEwidencyjny COLLATE database_default as NrEwidencyjny, WartoscBil, WartoscPod, NiePodlegaUmBil, NiePodlegaUmPod, 1 as IdOperZmianyCz, CalkUmorzBil, CalkUmorzPod, flUsunieta, flRdzenna, flDodana
 from tblSRODKIczesci
 where IdSrodka = @idSrodka
   and IsNull(IdOperZmianyCz, 0) < @idZmianyCzesci
   and flUsunieta = 0
union  -- te, ktore zostaly juz zmienione przez podana lub  pozniejsze operacje, poprawne wartosci w tblCZESCIwartosci w rekordzie tej lub bezposrednio pozniejszej operacji!
select scz.id, scz.IdSrodka, scz.Numer, scz.Nazwa COLLATE database_default as Nazwa, scz.NrEwidencyjny COLLATE database_default as NrEwidencyjny, czw.WartoscBil, czw.WartoscPod, czw.NiePodlegaUmBil, czw.NiePodlegaUmPod, 2, scz.CalkUmorzBil, scz.CalkUmorzPod, czw.flUsunieta, scz.flRdzenna, scz.flDodana
 from tblCZESCIwartosci czw join tblSRODKIczesci scz on czw.IdCzesci = scz.id
 where czw.IdCzesci not in (select id from tblSRODKIczesci where IdSrodka = @idSrodka and IsNull(IdOperZmianyCz, 0) < @idZmianyCzesci) -- pomijamy te czesci, ktore sa w poprzednim (1) zapytaniu
   and scz.IdSrodka = @idSrodka  -- tylko dla podanego srodka oczywiscie
   and scz.flUsunieta = 0 -- pomijamy usuniete (nawet pozniej, nie moga juz brac udzialu w amortyzacji bo mialy by ujemne netto)
   and (czw.WartoscBil!=0 or czw.WartoscPod!=0 or czw.IdPoprzZmiany!=0) -- pomijamy dodane przez pozniejsze operacje
   and czw.IdOperacji >= @idZmianyCzesci -- czyli wartosci poprzednie dla pozniejszych operacji, ale tylko bezposrednio pozniejszych (ponizej)
   and not exists (select czw1.id from tblCZESCIwartosci czw1 where czw1.IdCzesci = czw.IdCzesci and czw1.IdOperacji >= @idZmianyCzesci and czw1.IdOperacji < czw.IdOperacji)
) as scpo
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
kolejny:
select top 1 @dataUmorzenia = DataUmorzenia, @umorzenieBil = UmorzenieBil, @umorzeniePod = UmorzeniePod, @idPoprzUmorz = id from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz order by id
if IsNull(@idPoprzUmorz, 0) = 0  return 1 -- brak rekordu umorzenia
if IsNull(@umorzenieBil, 0) = 0 and IsNull(@umorzeniePod, 0) = 0 -- zerowe umorzenia, nie ma co rozbijac (moze sie zdarzyc przy um historycznym gdy cale um w biez roku)
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
    return 0  -- ok
  end
select @czyJuzRozbite = count(1) from tblCZESCIumorz where IsNull(IdOperacji,0) = @idOperacji and DataUmorzenia = @dataUmorzenia and IdCzesci in (select id from #tblSRODKIczesci where IdSrodka = @idSrodka)
if IsNull(@czyJuzRozbite, 0) > 0 -- juz rozbite
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny else return 2 -- juz rozbite
  end
select @sumaNettoBil = sum(WartoscBil - NiePodlegaUmBil - CalkUmorzBil), @sumaNettoPod = sum(WartoscPod - NiePodlegaUmPod - CalkUmorzPod), @iloscCzesci = count(1), @usunieta_i_netto = count(case when round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) <> 0 or round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod,2) <> 0 then 1 else 0 end)
from #tblSRODKIczesci
where /*flUsunieta = 0 and*/ IdSrodka = @idSrodka -- zgodnie z nowa strategia usuniete/przeniesione tez sie licza bo czesc ich wartosci, ktora juz sie umozyla zostaje
if IsNull(@iloscCzesci, 0) = 0  return 3  -- brak czesci
if IsNull(@usunieta_i_netto, 0) = 0  return 5  -- czesci usuniete maja niezerowa wartosc netto
if IsNull(@sumaNettoBil, 0) < IsNull(@umorzenieBil, 0) or IsNull(@sumaNettoPod, 0) < IsNull(@umorzeniePod, 0)  return 4  -- zle netto czesci
if @rozbijPoBrutto <> 0 or IsNull(@sumaNettoBil, 0) <= 0 or IsNull(@sumaNettoPod, 0) <= 0 -- jesli srodek ma adekwatna flage lub czesci sa zamortyzowane to trzeba rozbijac po brutto (dotyczy korekt umorz na minus)
  begin
    select @sumaBruttoBil = sum(WartoscBil - NiePodlegaUmBil), @sumaBruttoPod = sum(WartoscPod - NiePodlegaUmPod)
    from #tblSRODKIczesci
    where flUsunieta = 0 and IdSrodka = @idSrodka
  end
-- ROZBIJAMY
if (SELECT OBJECT_ID('tempdb..#tempCZESCIumorz')) is not null
	drop table [#tempCZESCIumorz]
select id as IdCzesci, @dataUmorzenia as DataUmorzenia, case when @idOperacji = 0 then NULL else @idOperacji end as IdOperacji, case when @umorzenieBil = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoBil, 0) > 0 then round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil - CalkUmorzBil) / @sumaNettoBil, 2) else round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil) / @sumaBruttoBil, 2) end as UmorzenieBil,
										   case when @umorzeniePod = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoPod, 0) > 0 then round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod - CalkUmorzPod) / @sumaNettoPod, 2) else round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod) / @sumaBruttoPod, 2) end as UmorzeniePod,
										  WartoscBil as WartoscBil, WartoscPod as WartoscPod, NiePodlegaUmBil as NiePodlegaUmBil, NiePodlegaUmPod as NiePodlegaUmPod,
										  round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) as DoUmorzBil,
										  round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod, 2) as DoUmorzPod
into #tempCZESCIumorz
from #tblSRODKIczesci
where flUsunieta = 0 and IdSrodka = @idSrodka -- dla czesci usunietych/przeniesionych nie liczymy amortyzacji bo powinny miec netto = 0 (sprawdzane wyzej)
-- jesli jest roznica to trzeba wyrownac
rownanie:
select @roznUmorzBil = sum(UmorzenieBil) - @umorzenieBil, @roznUmorzPod = sum(UmorzeniePod) - @umorzeniePod from #tempCZESCIumorz
if IsNull(@roznUmorzBil, 0) <> 0 update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil - @roznUmorzBil where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzenieBil < DoUmorzBil order by cu1.UmorzenieBil desc, cu1.IdCzesci desc)
if IsNull(@roznUmorzPod, 0) <> 0 update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod - @roznUmorzPod where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzeniePod < DoUmorzPod order by cu1.UmorzeniePod desc, cu1.IdCzesci desc)
if @rozbijPoBrutto <> 0  -- w przypadku rozbijania po brutto jesli kwota umorz dla czesci wykracza poza kwote pozostala do umorzenia to trzeba obciac i przesunac do innej czesci
  begin
    select @gorkaUmorzBil = sum(UmorzenieBil - DoUmorzBil), @WartCzesciZGorkaBil = sum(WartoscBil - NiePodlegaUmBil) from #tempCZESCIumorz  where  UmorzenieBil >= DoUmorzBil
    select @gorkaUmorzPod = sum(UmorzeniePod - DoUmorzPod), @WartCzesciZGorkaPod = sum(WartoscPod - NiePodlegaUmPod)  from #tempCZESCIumorz  where  UmorzeniePod >= DoUmorzPod
    if  IsNull(@gorkaUmorzBil, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzenieBil = DoUmorzBil  where  UmorzenieBil > DoUmorzBil  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil + round(@gorkaUmorzBil * (WartoscBil - NiePodlegaUmBil) / (@sumaBruttoBil-@WartCzesciZGorkaBil), 2)  where  UmorzenieBil < DoUmorzBil  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzeniePod = DoUmorzPod  where  UmorzeniePod > DoUmorzPod  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod + round(@gorkaUmorzPod * (WartoscPod - NiePodlegaUmPod) / (@sumaBruttoPod-@WartCzesciZGorkaPod), 2)  where  UmorzeniePod < DoUmorzPod  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzBil, 0) <> 0 or IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        goto rownanie  -- po przenoszeniu może się okazac, ze czesci obdarowane dodatkowym umorzeniem maja za duzo, trzeba sprawdzic i ew jeszcze raz wyrownac
      end
  end
-- ZAPISUJEMY
insert into tblCZESCIumorz (IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod)
select IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod from #tempCZESCIumorz
drop table [#tempCZESCIumorz]
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
return 0
------------------------------------------------------------------------------------------------------------------------------------------
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI_2]') AND type in (N'P', N'PC'))
DROP PROCEDURE [ST].[sp_ROZPISZ_UMORZENIE_NA_CZESCI_2]
GO
CREATE PROCEDURE st.sp_ROZPISZ_UMORZENIE_NA_CZESCI_2
@idSrodka INT, @idOperacji INT, @idZmianyCzesciBil INT, @idZmianyCzesciPod INT
AS
declare
@rozbijPoBrutto		bit,
@dataUmorzenia	datetime,
@sumaBruttoBil	money,
@sumaBruttoPod	money,
@sumaNettoBil	money,
@sumaNettoPod	money,
@umorzenieBil	money,
@umorzeniePod	money,
@iloscCzesci	int,
@usunieta_i_netto  int,
@czyJuzRozbite	int,
@roznUmorzBil	money,
@roznUmorzPod	money,
@gorkaUmorzBil		money,
@gorkaUmorzPod	money,
@WartCzesciZGorkaBil	money,
@WartCzesciZGorkaPod money,
@idPoprzUmorz	int
set @idOperacji = IsNull(@idOperacji,0)
set @idPoprzUmorz = 0
set @rozbijPoBrutto = IsNull((select top 1 flUmCzSklPoBrutto from tblSRODKI where id = @idSrodka), 0)
set @idZmianyCzesciBil = IsNull(@idZmianyCzesciBil, 0)
set @idZmianyCzesciPod = IsNull(@idZmianyCzesciPod, 0)
-- ROBIMY TABELE TYMCZASOWA ZE STANEM CZESCI DLA SRODKA PRZED PODANA OPERACJA (z niej bedziemy korzystac przy rozbijaniu)
-- oddzielnie dla bilansowej i podatkowej a potem laczymy w jedna tabele
-- te ktore zostaly tkniete przez operacje wczesniejsze (poprawne wartosci w tblSRODKIczesci) lub nie bylo dla nich zmian
if (SELECT OBJECT_ID('tempdb..#tblSRODKIczesciB')) is not null
	drop table [#tblSRODKIczesciB]
select * into #tblSRODKIczesciB from (
  select id, WartoscBil, NiePodlegaUmBil, 1 as IdOperZmianyCz, CalkUmorzBil
   from tblSRODKIczesci
   where IdSrodka = @idSrodka
     and (@idZmianyCzesciBil=0 or IsNull(IdOperZmianyCz, 0) < @idZmianyCzesciBil)
     and flUsunieta = 0
  union  -- te, ktore zostaly juz zmienione przez podana lub  pozniejsze operacje, poprawne wartosci w tblCZESCIwartosci w rekordzie tej lub bezposrednio pozniejszej operacji!
  select scz.id, czw.WartoscBil, czw.NiePodlegaUmBil, 2, scz.CalkUmorzBil
   from tblCZESCIwartosci czw join tblSRODKIczesci scz on czw.IdCzesci = scz.id
   where @idZmianyCzesciBil<>0
     and czw.IdCzesci not in (select id from tblSRODKIczesci where IdSrodka = @idSrodka and IsNull(IdOperZmianyCz, 0) < @idZmianyCzesciBil) -- pomijamy te czesci, ktore sa w poprzednim (1) zapytaniu
     and scz.IdSrodka = @idSrodka  -- tylko dla podanego srodka oczywiscie
     and scz.flUsunieta = 0 -- pomijamy usuniete (nawet pozniej, nie moga juz brac udzialu w amortyzacji bo mialy by ujemne netto)
     and (czw.WartoscBil!=0 or czw.WartoscPod!=0 or czw.IdPoprzZmiany!=0) -- pomijamy dodane przez pozniejsze operacje
     and czw.IdOperacji >= @idZmianyCzesciBil -- czyli wartosci poprzednie dla pozniejszych operacji, ale tylko bezposrednio pozniejszych (ponizej)
     and not exists (select czw1.id from tblCZESCIwartosci czw1 where czw1.IdCzesci = czw.IdCzesci and czw1.IdOperacji >= @idZmianyCzesciBil and czw1.IdOperacji < czw.IdOperacji)
) as scpob
-- stan czesci oddzielnie dla podatkowej
if (SELECT OBJECT_ID('tempdb..#tblSRODKIczesciP')) is not null
	drop table [#tblSRODKIczesciP]
select * into #tblSRODKIczesciP from (
  select id, WartoscPod, NiePodlegaUmPod, 1 as IdOperZmianyCz, CalkUmorzPod
   from tblSRODKIczesci
   where IdSrodka = @idSrodka
     and (@idZmianyCzesciPod=0 or IsNull(IdOperZmianyCz, 0) < @idZmianyCzesciPod)
     and flUsunieta = 0
  union  -- te, ktore zostaly juz zmienione przez podana lub  pozniejsze operacje, poprawne wartosci w tblCZESCIwartosci w rekordzie tej lub bezposrednio pozniejszej operacji!
  select scz.id, czw.WartoscPod, czw.NiePodlegaUmBil, 2, scz.CalkUmorzPod
   from tblCZESCIwartosci czw join tblSRODKIczesci scz on czw.IdCzesci = scz.id
   where @idZmianyCzesciPod<>0
     and czw.IdCzesci not in (select id from tblSRODKIczesci where IdSrodka = @idSrodka and IsNull(IdOperZmianyCz, 0) < @idZmianyCzesciPod) -- pomijamy te czesci, ktore sa w poprzednim (1) zapytaniu
     and scz.IdSrodka = @idSrodka  -- tylko dla podanego srodka oczywiscie
     and scz.flUsunieta = 0 -- pomijamy usuniete (nawet pozniej, nie moga juz brac udzialu w amortyzacji bo mialy by ujemne netto)
     and (czw.WartoscBil!=0 or czw.WartoscPod!=0 or czw.IdPoprzZmiany!=0) -- pomijamy dodane przez pozniejsze operacje
     and czw.IdOperacji >= @idZmianyCzesciPod -- czyli wartosci poprzednie dla pozniejszych operacji, ale tylko bezposrednio pozniejszych (ponizej)
     and not exists (select czw1.id from tblCZESCIwartosci czw1 where czw1.IdCzesci = czw.IdCzesci and czw1.IdOperacji >= @idZmianyCzesciPod and czw1.IdOperacji < czw.IdOperacji)
) as scpop
-- skladamy tabelke do kupy posilkujac sie oginalna tabela czesci
if (SELECT OBJECT_ID('tempdb..#tblSRODKIczesci')) is not null
	drop table [#tblSRODKIczesci]
select scz.id, scz.IdSrodka, scz.Numer, scz.Nazwa COLLATE database_default as Nazwa, scz.NrEwidencyjny COLLATE database_default as NrEwidencyjny, IsNull(scb.WartoscBil, 0.0) as WartoscBil, IsNull(scp.WartoscPod, 0.0) as WartoscPod, IsNull(scb.NiePodlegaUmBil, 0.0) as NiePodlegaUmBil, IsNull(scp.NiePodlegaUmPod, 0.0) as NiePodlegaUmPod, 3 as IdOperZmianyCz, IsNull(scb.CalkUmorzBil,0.0) as CalkUmorzBil, IsNull(scp.CalkUmorzPod,0.0) as CalkUmorzPod, scz.flUsunieta, scz.flRdzenna, scz.flDodana
 into #tblSRODKIczesci
 from tblSRODKIczesci scz left join #tblSRODKIczesciB scb on scz.id = scb.id left join #tblSRODKIczesciP scp on scz.id = scp.id
 where IdSrodka = @idSrodka
   and flUsunieta = 0
delete from #tblSRODKIczesci where WartoscBil=0.0 and WartoscPod=0.0
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
kolejny:
select top 1 @dataUmorzenia = DataUmorzenia, @umorzenieBil = UmorzenieBil, @umorzeniePod = UmorzeniePod, @idPoprzUmorz = id from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz order by id
if IsNull(@idPoprzUmorz, 0) = 0  return 1 -- brak rekordu umorzenia
if IsNull(@umorzenieBil, 0) = 0 and IsNull(@umorzeniePod, 0) = 0 -- zerowe umorzenia, nie ma co rozbijac (moze sie zdarzyc przy um historycznym gdy cale um w biez roku)
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
    return 0  -- ok
  end
select @czyJuzRozbite = count(1) from tblCZESCIumorz where IsNull(IdOperacji,0) = @idOperacji and DataUmorzenia = @dataUmorzenia and IdCzesci in (select id from #tblSRODKIczesci where IdSrodka = @idSrodka)
if IsNull(@czyJuzRozbite, 0) > 0 -- juz rozbite
  begin
    if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny else return 2 -- juz rozbite
  end
select @sumaNettoBil = sum(WartoscBil - NiePodlegaUmBil - CalkUmorzBil), @sumaNettoPod = sum(WartoscPod - NiePodlegaUmPod - CalkUmorzPod), @iloscCzesci = count(1), @usunieta_i_netto = count(case when round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) <> 0 or round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod,2) <> 0 then 1 else 0 end)
from #tblSRODKIczesci
where /*flUsunieta = 0 and*/ IdSrodka = @idSrodka -- zgodnie z nowa strategia usuniete/przeniesione tez sie licza bo czesc ich wartosci, ktora juz sie umozyla zostaje
if IsNull(@iloscCzesci, 0) = 0  return 3  -- brak czesci
if IsNull(@usunieta_i_netto, 0) = 0  return 5  -- czesci usuniete maja niezerowa wartosc netto
if IsNull(@sumaNettoBil, 0) < IsNull(@umorzenieBil, 0) or IsNull(@sumaNettoPod, 0) < IsNull(@umorzeniePod, 0)  return 4  -- zle netto czesci
if @rozbijPoBrutto <> 0 or IsNull(@sumaNettoBil, 0) <= 0 or IsNull(@sumaNettoPod, 0) <= 0 -- jesli srodek ma adekwatna flage lub czesci sa zamortyzowane to trzeba rozbijac po brutto (dotyczy korekt umorz na minus)
  begin
    select @sumaBruttoBil = sum(WartoscBil - NiePodlegaUmBil), @sumaBruttoPod = sum(WartoscPod - NiePodlegaUmPod)
    from #tblSRODKIczesci
    where flUsunieta = 0 and IdSrodka = @idSrodka
  end
-- ROZBIJAMY
if (SELECT OBJECT_ID('tempdb..#tempCZESCIumorz')) is not null
	drop table [#tempCZESCIumorz]
select id as IdCzesci, @dataUmorzenia as DataUmorzenia, case when @idOperacji = 0 then NULL else @idOperacji end as IdOperacji, case when @umorzenieBil = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoBil, 0) > 0 then round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil - CalkUmorzBil) / @sumaNettoBil, 2) else round(@umorzenieBil * (WartoscBil - NiePodlegaUmBil) / @sumaBruttoBil, 2) end as UmorzenieBil,
										   case when @umorzeniePod = 0 then 0 when @rozbijPoBrutto = 0 and IsNull(@sumaNettoPod, 0) > 0 then round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod - CalkUmorzPod) / @sumaNettoPod, 2) else round(@umorzeniePod * (WartoscPod - NiePodlegaUmPod) / @sumaBruttoPod, 2) end as UmorzeniePod,
										  WartoscBil as WartoscBil, WartoscPod as WartoscPod, NiePodlegaUmBil as NiePodlegaUmBil, NiePodlegaUmPod as NiePodlegaUmPod,
										  round(WartoscBil - NiePodlegaUmBil - CalkUmorzBil, 2) as DoUmorzBil,
										  round(WartoscPod - NiePodlegaUmPod - CalkUmorzPod, 2) as DoUmorzPod
into #tempCZESCIumorz
from #tblSRODKIczesci
where flUsunieta = 0 and IdSrodka = @idSrodka -- dla czesci usunietych/przeniesionych nie liczymy amortyzacji bo powinny miec netto = 0 (sprawdzane wyzej)
-- jesli jest roznica to trzeba wyrownac
rownanie:
select @roznUmorzBil = sum(UmorzenieBil) - @umorzenieBil, @roznUmorzPod = sum(UmorzeniePod) - @umorzeniePod from #tempCZESCIumorz
if IsNull(@roznUmorzBil, 0) <> 0 update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil - @roznUmorzBil where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzenieBil < DoUmorzBil order by cu1.UmorzenieBil desc, cu1.IdCzesci desc)
if IsNull(@roznUmorzPod, 0) <> 0 update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod - @roznUmorzPod where IdCzesci = (select top 1 cu1.IdCzesci from #tempCZESCIumorz cu1 where UmorzeniePod < DoUmorzPod order by cu1.UmorzeniePod desc, cu1.IdCzesci desc)
if @rozbijPoBrutto <> 0  -- w przypadku rozbijania po brutto jesli kwota umorz dla czesci wykracza poza kwote pozostala do umorzenia to trzeba obciac i przesunac do innej czesci
  begin
    select @gorkaUmorzBil = sum(UmorzenieBil - DoUmorzBil), @WartCzesciZGorkaBil = sum(WartoscBil - NiePodlegaUmBil) from #tempCZESCIumorz  where  UmorzenieBil >= DoUmorzBil
    select @gorkaUmorzPod = sum(UmorzeniePod - DoUmorzPod), @WartCzesciZGorkaPod = sum(WartoscPod - NiePodlegaUmPod)  from #tempCZESCIumorz  where  UmorzeniePod >= DoUmorzPod
    if  IsNull(@gorkaUmorzBil, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzenieBil = DoUmorzBil  where  UmorzenieBil > DoUmorzBil  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzenieBil = UmorzenieBil + round(@gorkaUmorzBil * (WartoscBil - NiePodlegaUmBil) / (@sumaBruttoBil-@WartCzesciZGorkaBil), 2)  where  UmorzenieBil < DoUmorzBil  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        update #tempCZESCIumorz set UmorzeniePod = DoUmorzPod  where  UmorzeniePod > DoUmorzPod  -- zmniejszamy umorzenie tym częściom co mają za duże
        update #tempCZESCIumorz set UmorzeniePod = UmorzeniePod + round(@gorkaUmorzPod * (WartoscPod - NiePodlegaUmPod) / (@sumaBruttoPod-@WartCzesciZGorkaPod), 2)  where  UmorzeniePod < DoUmorzPod  -- zwiększamy umorzenie tym częściom co jeszcze mogą
      end
    if  IsNull(@gorkaUmorzBil, 0) <> 0 or IsNull(@gorkaUmorzPod, 0) <> 0
      begin
        goto rownanie  -- po przenoszeniu może się okazac, ze czesci obdarowane dodatkowym umorzeniem maja za duzo, trzeba sprawdzic i ew jeszcze raz wyrownac
      end
  end
-- ZAPISUJEMY
insert into tblCZESCIumorz (IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod)
select IdCzesci, DataUmorzenia, IdOperacji, UmorzenieBil, UmorzeniePod from #tempCZESCIumorz
drop table [#tempCZESCIumorz]
-- dla operacji rozpoczecia obliczen moze byc wiecej niz jeden rekord umorzenia dlatego trzeba zasymulowac taka niby petle
if exists (select * from tblSRODKIumorz where IdSrodka = @idSrodka and IsNull(IdOperacji,0) = @idOperacji and id > @idPoprzUmorz) goto kolejny
return 0