Marcin Niemczak

Marcin Niemczak Prokurent, APS Glass
& Bar Supply Sp. z
o.o.

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Napisałem procedurę wywołującą w pętli przeliczanie cen dla dokumentów rozchodu wycenianych w cenach zakupu (normalnie procedura działa dla jednego dokumentu a chcieliśmy ją np. za cały miesiąc puszczać automatycznie). Procedura nie otwiera własnej transakcji. Woła w pętli dla odpowiednich dokumentów PZ procedurę AP_PrzeliczRozchodyWcenachZakupu i zjada komunikat o braku dokumentów powiązanych. Zagadka jest taka że jak ją puszczę testowo spoza WF-Mag (SSMS, Squirrel Sql lub inny klient) to działa. Jak ją puszcze z Wf-Mag z operacji dodatkowych w dokumentach magazynowych to brak jest błędów jednak zmiany się nie zatwierdzają (dokumenty rozchodu się nie przeliczają). Wszelkie wskazówki mile widziane :-) Poniżej istotny fragment:

declare c_pz cursor local fast_forward for
select PZC.ID_DOK_MAGAZYNOWEGO
from DOKUMENT_MAGAZYNOWY PZC
where PZC.RODZAJ_DOKUMENTU='PZ'
and PZC.DOK_KOREKTY is null
and PZC.DATA >= @zakres_daty_od
and PZC.DATA <= @zakres_daty_do
open c_pz
while 1=1
begin
FETCH NEXT FROM c_pz INTO
@id_dok
if @@fetch_status<>0 break

begin try
EXEC AP_PrzeliczRozchodyWcenachZakupu 1, @id_dok, @id_uzytkownika
end try
begin catch
if ERROR_MESSAGE() != 'Brak dokumentów rozchodu wycenianych w cenach zakupu powiązanych z danym dokumentem.'
begin
set @errmsg = ERROR_MESSAGE()
goto Error
end
end catch

end
close c_pz
deallocate c_pz
Krzysztof Stachyra

Krzysztof Stachyra Szef Wydziału
Produkcji Systemów
Handlowo-Magazynowyc
h i ...

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Mimo wszystko chyba przydałby się kod całej procedury, nie wiadomo co do niej wchodzi i co się dzieje poza kursorem.
Marcin Niemczak

Marcin Niemczak Prokurent, APS Glass
& Bar Supply Sp. z
o.o.

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Testowane na SqlSrv 2016 (z opcjami operacji dodatkowych : z potwierdzeniem wykonania, bez potwierdzenia, z odświeżeniem listy i bez odświeżenia), poniżej cała procedura

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

if exists (select 1 from sysobjects where name = 'MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC' and type = 'P')
drop procedure MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC
go
create procedure MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC
@id_firmy numeric,
@id_uzytkownika numeric,
@zakres_daty_od int,
@zakres_daty_do int
as declare
@errmsg varchar(250),
@dataOd datetime,
@dataDo datetime,
@id_dok numeric
begin

set @dataOd = convert(datetime,@zakres_daty_od - 36163)
set @dataDo = convert(datetime,@zakres_daty_do - 36163)

set @errmsg = 'Zakres dat powinen obejmować tylko jeden miesiąc, ustaw datę od pierwszego do ostatniego dnia wybranego miesiąca !'

if MONTH(@dataOd) != MONTH(@dataDo) or DAY(@dataOd) != 1 or DAY(@dataDo) != DAY(EOMONTH(@dataOd))
begin
goto Error
end

declare c_pz cursor local fast_forward for
select PZC.ID_DOK_MAGAZYNOWEGO
from DOKUMENT_MAGAZYNOWY PZC
where PZC.RODZAJ_DOKUMENTU='PZ'
and PZC.DOK_KOREKTY is null
and PZC.DATA >= @zakres_daty_od
and PZC.DATA <= @zakres_daty_do
open c_pz
while 1=1
begin
FETCH NEXT FROM c_pz INTO
@id_dok if @@fetch_status<>0 break

begin try
EXEC AP_PrzeliczRozchodyWcenachZakupu 1, @id_dok, @id_uzytkownika -- 1 typ dokument magazynowy
end try
begin catch
if ERROR_MESSAGE() != 'Brak dokumentów rozchodu wycenianych w cenach zakupu powiązanych z danym dokumentem.'
begin
set @errmsg = ERROR_MESSAGE()
goto Error end
end catch

end
close c_pz
deallocate c_pz

goto Koniec
Error:
raiserror (@errmsg,16,1)
goto Koniec
Koniec:
return
end
go
Krzysztof Stachyra

Krzysztof Stachyra Szef Wydziału
Produkcji Systemów
Handlowo-Magazynowyc
h i ...

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

nie działa bo procedura po przeliczeniu zwraca message a Pana procedura odbiera go jako error_message() != '....'
goto error

i po wykonaniu jednego po prostu leci raiserror, który wycofuje wszystko więc nie widać nawet tego efektu.

Można albo przerobić to na jedną procedurę i robić to w pętli lub wykonać swoją obsługę aktualizację cen.
Krzysztof Stachyra

Krzysztof Stachyra Szef Wydziału
Produkcji Systemów
Handlowo-Magazynowyc
h i ...

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

można też dać wyjątek na error_message() not like 'przeliczono%'
nie wiem na ile się to sprawdzi na dłuższą metę bo nie znam wszystkich wyjątków/komunikatów jakie moga wyjść z tej procedury.
Marcin Niemczak

Marcin Niemczak Prokurent, APS Glass
& Bar Supply Sp. z
o.o.

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Proszę zauważyć iż:
- tak jak napisałem wcześniej procedura działa spoza WF-Mag a nie działa po wywołaniu z operacji dodatkowych Wf-Mag (wg. mojej najlepszej wiedzy powinna działać tu i tu)
- tak jak napisałem wcześniej wywołanie procedury nie kończy się żadnym komunikatem o błędzie zarówno spoza WF-Mag jak i w Wf-Mag (jak nie było zjadania komunikatu to w WF-Mag wyskakiwało okno z info o przerwaniu wykonania)
- widzę w SSMS w output jakie są wyniki z prawidłowego wywołania procedury AP_PrzeliczRozchodyWcenachZakupu w pętli (u mnie dla miesiąca kilkanaście wyników dla przeliczonych dokumentów), faktycznie opisy te zawierają "przeliczono" jednak nie są one zwracane poprzez raiserror lub throw (są to standardowe zwroty wyniku z procedury), nie powodują one wywołania raiserror w mojej procedurze i również nie powodują wycofywania całej transakcji

Podsumowując:
- moja procedura to jedynie wywołanie AP_PrzeliczRozchodyWcenachZakupu w pętli (AP_PrzeliczRozchodyWcenachZakupu ma własną transakcję bo można ją wywołać z aplikacji dla jednego dokumentu i działa)
- moja procedura w bloku catch zjada jeden z komunikatów żeby nie przerwać pętli wywołań
- nie ma znaczenia czy moja procedura otwiera transakcję na całość wywołania, czy też na poszczególne wywołania w pętli, czy nie otwiera żadnej transakcji - efekt jest ten sam
- nawet jeżeli ograniczę wykonanie do kilku id dokumentów magazynowych tak aby AP_PrzeliczRozchodyWcenachZakupu nie rzuciło informacji o braku powiązanych dokumentów poprzez raiserror/throw - efekt jest ten sam

Jedyna upierdliwość jest taka że nie mogę przekazać funkcji do księgowej tylko muszę ją wykonywać sam. Być może pójdę w kierunku napisania małego modułu zewnętrznego wykonującego moją procedurę i wywoływanego z Wf-Mag.

Panie Krzysztofie o ile to możliwe poproszę o opinię osobę zanurzoną głębiej w czeluście dev Wf-Mag :-). Wątek nie jest trywialny, niemniej jest ciekawy od strony dev. Mi skończyły się pomysły, nie mam kodu wywołania operacji dodatkowych z aplikacji Wf-Mag.
Krzysztof Stachyra

Krzysztof Stachyra Szef Wydziału
Produkcji Systemów
Handlowo-Magazynowyc
h i ...

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Nie ma w co się zagłębiać u mnie działa przy takim kodzie - część kodu zaremowałem testowy insert można sobie zaremować

USE [WAPRO_DEMO]
GO

/****** Object: StoredProcedure [dbo].[MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC] Script Date: 2017-03-28 22:52:36 ******/
DROP PROCEDURE [dbo].[MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC]
GO

/****** Object: StoredProcedure [dbo].[MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC] Script Date: 2017-03-28 22:52:36 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

create procedure [dbo].[MAGEXT_PRZELICZ_ROZCHODY_W_CENACH_ZAKUPU_MIESIAC]
@id_firmy numeric,
@id_uzytkownika numeric,
@zakres_daty_od int,
@zakres_daty_do int
as declare
@errmsg varchar(250),
@dataOd datetime,
@dataDo datetime,
@id_dok numeric
begin

set @dataOd = convert(datetime,@zakres_daty_od - 36163)
set @dataDo = convert(datetime,@zakres_daty_do - 36163)

--set @errmsg = 'Zakres dat powinen obejmować tylko jeden miesiąc, ustaw datę od pierwszego do ostatniego dnia wybranego miesiąca !'

--if MONTH(@dataOd) != MONTH(@dataDo) or DAY(@dataOd) != 1 or DAY(@dataDo) != DAY(EOMONTH(@dataOd))
--begin
--goto Error
--end

declare c_pz cursor local fast_forward for
select PZC.ID_DOK_MAGAZYNOWEGO
from DOKUMENT_MAGAZYNOWY PZC
where PZC.RODZAJ_DOKUMENTU='PZ'
and PZC.DOK_KOREKTY is null
and PZC.DATA >= @zakres_daty_od
and PZC.DATA <= @zakres_daty_do
open c_pz
while 1=1
begin
FETCH NEXT FROM c_pz INTO
@id_dok if @@fetch_status<>0 break

begin try

EXEC AP_PrzeliczRozchodyWcenachZakupu 1, @id_dok, @id_uzytkownika
insert into t1 (col1) values ('test')
end try
begin catch

if ERROR_MESSAGE() != 'Brak dokumentów rozchodu wycenianych w cenach zakupu powiązanych z danym dokumentem.'
begin
raiserror (@errmsg,16,1) set @errmsg = ERROR_MESSAGE()
goto Error
end
end catch

--begin try
-- insert into t1 values ('test')
-- EXEC AP_PrzeliczRozchodyWcenachZakupu 1, @id_dok, @id_uzytkownika -- 1 typ dokument magazynowy

--end try
--begin catch
-- raiserror('test',16,1)
-- if ERROR_MESSAGE() != 'Brak dokumentów rozchodu wycenianych w cenach zakupu powiązanych z danym dokumentem.'
-- begin
-- raiserror (@errmsg,16,1)
-- set @errmsg = ERROR_MESSAGE()
-- goto Error
-- end
--end catch

end
close c_pz
deallocate c_pz

goto Koniec
Error:
raiserror (@errmsg,16,1)
goto Koniec
Koniec:
return
end

GO
Marcin Niemczak

Marcin Niemczak Prokurent, APS Glass
& Bar Supply Sp. z
o.o.

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Proszę u siebie zapuścić poniższy prosty test składający się z dwóch procedur. Jeżeli puszczamy spoza WF-Mag to zawsze w tabeli t1 (wcześniej wyczyszczonej) mamy wynik od 0 do 99 - cała pętla się wykonuje. Jeżeli puścimy w WF-MAG to (przynajmniej u mnie Mag 8.20.2 i SqlSrv 2016) mamy w t1 wynik urwany - u mnie od 0 do 22 - wykonanie pętli po prostu się przerywa. Wywołanie z operacji dodatkowych w WF-Mag kończy się bez błędu (przynajmniej widocznego dla użytkownika). Jeżeli z procedury MAGEXT_TEST_2 usuniemy dwie poniższe linie:
select @wynik = 'Przeliczono xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
select @wynik
to wtedy działa ok zarówno z Mag jak i z zewnątrz. Wygląda tak jakby sekwencyjne wywołanie procedury która zwraca wynik przepełniało jakiś bufor wywołania z Wf-Mag co powoduje przerwanie wywołania całej procedury bez komunikatu o błędzie do użytkownika. Oczywiście w tym przypadku daje to wynik częściowy ponieważ druga procedura ma własną transakcję.

-- Testowe procedury

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

drop procedure [dbo].[MAGEXT_TEST_1]
go
create procedure [dbo].[MAGEXT_TEST_1]
as
begin
declare
@errmsg varchar(250),
@counter int
set @counter = 0
while @counter < 100
begin
begin try
exec dbo.MAGEXT_TEST_2 @counter
end try
begin catch
end catch
set @counter = @counter + 1
end return
end
go

drop procedure [dbo].[MAGEXT_TEST_2]
go
create procedure [dbo].[MAGEXT_TEST_2]
@counter int
as
set xact_abort on
declare
@wynik varchar (2500)
begin
begin transaction t
insert into t1 (col1) values (cast(@counter as varchar))
commit transaction t

select @wynik = 'Przeliczono xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
select @wynik
raiserror('Blad',16,1)
return
end
go
Marcin Niemczak

Marcin Niemczak Prokurent, APS Glass
& Bar Supply Sp. z
o.o.

Temat: Pytanie do dev - procedura działa tylko poza Wf-Mag

Znalazłem rozwiązanie. W przypadku gdy wołana procedura otwiera resultset (a w pętli otwiera ich wiele) należy coś z takim resultsetem zrobić. SSMS czy Squirrel wyświetlał mi po prostu wiele wyników i działał. W WF-Mag obsługa siłą rzeczy jest inna. Generalnie problem rozwiązałem poprzez wstawienie wyniku z procedury do zmiennej tabelarycznej. Tak więc zamiana dwóch linii w mojej procedurze powoduje poprawne wywołanie również z Wf-Mag.

Declare @Tmp Table (wynik varchar(2000))
Insert @Tmp EXEC AP_PrzeliczRozchodyWcenachZakupu 1, @id_dok, @id_uzytkownika



Wyślij zaproszenie do