====== Obecné informace ======
===== Pořadí volání =====
Zaregistrované eventy se volají v pořadí, v jakém byly registrovány. Nejprve se provedou systémové, potom uživatelské.
====== Eventy DataSetItem ======
===== Seznam =====
Volání ve tvaru main(DSI)
* [[#AfterCancel]]
* [[#AfterClose]]
* [[#AfterCopy]]
* [[#AfterDelete]]
* [[#AfterEdit]]
* [[#AfterInsert]]
* [[#AfterOpen]]
* [[#AfterPost]]
* [[#AfterScroll]]
* [[#BeforeCancel]]
* [[#BeforeClose]]
* [[#BeforeCopy]]
* [[#BeforeDelete]]
* [[#BeforeEdit]]
* [[#BeforeInsert]]
* [[#BeforeOpen]]
* [[#BeforePost]]
* [[#BeforePostMasterChange]]
* [[#BeforeScroll]]
* [[#CanDelete]]
* [[#GetCena]]
* [[#GetCenikCena]]
* [[#GetNaklady]]
* [[#ChangeField]]
* [[#ChangeFieldValue]]
* [[#ChangeIndexes]]
* [[#ChangeRange]]
* [[#OnCalcFields]]
* [[#OnNewRecord]]
* [[#PrintRow]]
* [[#UserDefined]]
* [[#ShowLookupField]]
* [[#AfterPasteClipboard]]
* [[#AfterCopyDetails]]
===== Popis =====
==== AfterCancel ====
vola se po operaci Cancel (napr. tlacitko X na db navigatoru, nebo kl. Esc)
event je zavolan ve chvili, kdy je jiz radek uveden do puvodniho stavu.
==== AfterClose ====
Volá se po zavření tabulky.
==== AfterDelete ====
Proběhne po smazání řádku, v momentu po smazání už je kurzor na jiném řádku. Stav databáze je browse.
==== AfterEdit ====
Po úpravě záznamu v databázi. Tabulka je ve stavu browse.
==== AfterInsert ====
Po vložení záznamu do databáze. Tabulka je ve stavu browse. Nepřidávat zde žádné položky do detailů. Provede-li uživatel Cancel, zůstanou jako syrotci.
==== AfterOpen ====
Volá se po otevření tabulky.
==== AfterPost ====
Po uložení údaje do tabulky. Stav databáze je browse.
==== AfterScroll ====
Při posunu na další řádek.
==== BeforeCancel ====
Před zrušením operace - stav databáze může být v editu, insertu, browse.
==== BeforeClose ====
Před zavřením dabulky
==== BeforeDelete ====
Před smazáním řádku.
==== BeforeEdit ====
Před editací řádku.
==== BeforeInsert ====
Před vkládáním řádku, ještě jsem na původním řádku.
==== BeforeOpen ====
Před otevřením tabulky
==== BeforePost ====
Před zapsáním řádku do tabulky.
Ukázka kontroly editace hodnoty pouze vybranými uživateli. Pomocí řádkových práv lze zamezit editaci pouze celého řádku, tuto funkcionalitu lze také zajistit pomocí sloupcových práv k tabulce.
Výpis souboru user/lua/prost/v_prost_vykony.lua:
--nastaveni kodovani retezcu ve skriptu a lokalni funkce enc pro prekodovani
local encoding="windows-1250"
local function enc(Str) return tEnc(Str, encoding) end
--vytvori tabulku pro uzivatelske funkce datasetu v_prost_vykony.lua
cf.CreateTable("v_prost_vykony")
-- registruje Event pro middle PROSTREDKY, dataset prost_vykony na funkci v_prost_vykony.BeforePost
ClientSession:AddLUAEvent("PROSTREDKY.prost_vykony.BeforePost", "v_prost_vykony.BeforePost")
--tato funkce se aktivuje pred zapsanim zmen v datasetu prost_vykony
--a zamezi zmeny mnozstvi ve vykonech pro uzivatele, kteri nemaji priznak
--ISAdmin (v tabulce uzivatelu)
function v_prost_vykony.BeforePost(DSI)
-- kontrola pouze pro uzivatele, kteri nemaji priznak ISAdmin
if ClientSession:IsLoggedAdmin() == false then
-- pokud se lisi nova a stara hodnota v sloupci mnozstvi, zobrazi se dialog
-- cf.tonumber zajisti, ze pokud je v mnozstvi NULL prevede se na 0
if cf.tonumber(DSI:FieldByName("mn")) ~= cf.tonumber(DSI:OldFieldByName("mn")) then
--pro prekodovani je zkracena syntaxe volani funkce enc"text" tzn. enc("test")
dlg.message(enc"Nelze měnit množství")
--pokud se z funkce BeforePost vrati false nebude zapis zmeny dokoncen
return false
end
end
end
==== BeforeScroll ====
Před posunem na další řádek.
==== OnCalcFields ====
Tento event musí zajistit výpočty Calculated fieldů. Volá se 1x pro každý řádek v gridu.
ClientSession:AddLUAEvent("POHYBY_TAB.sklad_prijemky.OnCalcFields", "v_sklad_prijemky.OnCalcFields")
function v_sklad_prijemky.OnCalcFields(DSI)
DSI:SetFieldByName("v_CenaCelksDPH", cf.tonumber(DSI:FieldByName("CenaCelk"))*1.19)
end
==== OnNewRecord ====
Vola se ještě před eventy *Insert. Co se nastavi v ramci tohoto eventu, jeste neni brano jako zmena a v pripade ze neni explicitne radek postnut radek zmizi.
==== ChangeField ====
Volá se v [[#BeforePost]] v případě, že došlo ke změně zadaného fieldu.
==== CanDelete ====
Vola se pred [[#BeforeDelete]] nez se maze zaznam i s detailem.
Priklad pouziti: mam event BeforeDelete v rozpocty_rnakl, ktery se vola vzdy kdyz se maze polozka nakl.rekapitulace. Kdyz ale mazu cely rozpocet, nechci aby se BeforeDelete v rnakl volal. Pak si ho tedy v CanDelete v rozpocty_rozpocty odregistruju. A v AfterDelete v rozpocty_rozpocty zase zaregistruju.
==== UserDefined ====
* Druh - pro vložení druhu do tabulky
* Counter - pro nastavení IDFieldu dle počítadla , druh je již nastaven
-- nastaveni druhu faktury; event se zavola pri Appendu a hned se odregistruje
ClientSession:AddLUAEvent("faktury.faktury_faktury.Druh.UserDefined", "faktury_faktury.NastaveniDruhuDokladu")
function faktury_faktury.NastaveniDruhuDokladu(DSI)
DSI:SetFieldByName("idfdruh", idfdruh)
ClientSession:DeleteLUAEvent("faktury.faktury_faktury.Druh.UserDefined", "faktury_faktury.NastaveniDruhuDokladu" )
end
-- nastavení počítadla výdejky; event se zavola pri Appendu a hned se odregistruje
ClientSession:AddLUAEvent("vydejky_tab.sklad_prijemky.Counter.UserDefined", "v_sklad_sklady.CounterUserDefine")
function v_sklad_sklady.CounterUserDefine(DSI)
DSI:SetFieldByName("idprijemka",ClientSession:GetCounter(res.idpocitadlo))
ClientSession:DeleteLUAEvent("vydejky_tab.sklad_prijemky.Counter.UserDefined", "v_sklad_sklady.CounterUserDefine")
end
==== BeforeCopy ====
Provede se před zkopírováním záznamu tabulky.
==== AfterCopy ====
Provede se po zkopírování záznamu tabulky.
Příklad: zapsání aktuálního data a času do poznámky.
ClientSession:AddLUAEvent("SKLKARTY.sklad_karty.AfterCopy","v_sklad_karty.NowDoPoznamky")
function v_sklad_karty.NowDoPoznamky(DSI)
DSI:SetFieldByName("Poznamka",cf.Now())
end
==== ChangeFieldValue ====
Event se zavola pri opusteni dane bunky nebo pri ENTERu v případě, že došlo ke změně zadaného fieldu.
Databáze je v editu nebo insertu.
ClientSession:AddLUAEvent("prostredky.prost_vykony.IDZakaz.ChangeFieldValue", "v_prost_vykony.IDZakazChangeFieldValue")
ClientSession:AddLUAEvent("vykprot.prost_vykony.IDZakaz.ChangeFieldValue", "v_prost_vykony.IDZakazChangeFieldValue")
function v_prost_vykony.IDZakazChangeFieldValue(DSI, FieldName)
local idzakaz = cf.tostring(DSI:FieldByName("idzakaz"))
local sql = [[select * from zakazky_zakazky where idzakaz = ']]..idzakaz..[[' ]]
local md=ClientSession:CreateMidFromXML(sql)
local ds=md:FindDataSetItem("")
ds:LocateRange("","")
if cf.tonumber(ds:RecordCount()) == 0 and idzakaz ~= "" then
cf.ShowMsg(enc"Neexistující zakázka !!!\nNelze zapsat.")
DSI:SetFieldByName("idzakaz", DSI:OldFieldByName("idzakaz"))
elseif ds:FieldByName("stav") == "U" and idzakaz ~= "" then
cf.ShowMsg(enc"Ukončená zakázka !!!\nNelze zapsat.")
DSI:SetFieldByName("idzakaz", DSI:OldFieldByName("idzakaz"))
end
md=md:Free()
end
==== ChangeIndexes ====
==== ChangeRange ====
==== BeforePostMasterChange ====
==== PrintRow ====
Při zobrazování řádků v gridu. Zde se realizuje vlastní obarvování.
ClientSession:AddLUAEvent("CENIK.rozpocty_cenik.PrintRow", "v_rozpocty_cenik.PrintRow")
function v_rozpocty_cenik.PrintRow(DSI)
--viz. colors.lua (cerveny font na bilem pozadi tucne)
return {FontColor=clRed, FontStyle=FontStyleBold, BrushColor=clWhite}
end
=== Barva fontů ===
* viz. Colors.Show() resp. v LuaConsole menu
{{:lua:ukazka_barev_fontu.png|Ukázka barev fontů}}
==== GetCena ====
Zde se realizuje cenová politika. Zaregistrovane funkce se volaji retezove. Pokud vrati nil neni hodnota vracena predchozi registovanou funkci ovlivnena.
Postup zjisteni ceny:
- nejprve se zavola GetCenikCena (ta bere defaultne sloupec Cena z tabulky a pak vola retezove GetCenikCena eventy)
- zavola retezove v poradi registrace fce GetCena
- pokud GetCena vraci nil, neni hodnota ceny zmenena
- tj. posledni funkce GetCena ktera vrati hodnotu je pouzita
fce(SourceDSI, destDSI, tParm) return cena tParm = { IDPartner=val, CenikCena=val, Mnozstvi=val}
Ukázka cenové politiky při tvorbě výdejky. Pokud se vydáva ze skladu '01' pak se vkladá Cena1; sklad '07' = Cena2; sklad '13' = Cena3; ostatní sklady = Cena
--registrace eventu
ClientSession:AddLUAEvent("SKLKARTY.sklad_karty.GetCena", "CenovaPolitikaKarty")
function CenovaPolitikaKarty( DSI, DestDSI, Params)
--nastaveni DataSetu z hlavicky vydejky pro zjisteni cisla skladu
local SkladDS=DestDSI:OwnerMiddleDB():FindDataSetItem("sklad_prijemky")
--kontrola jestli se opravdu tvori vydejka; karty se mohou vkladat do rozpoctu - pak konec
if not SkladDS then return end
--nastaveni cisla skladu
local idsklad=SkladDS:FieldByName("idsklad")
--podminky pro vyber ceny na zaklade cisla skladu
if idsklad=="01" then return DSI:FieldByName("Cena1") end
if idsklad=="07" then return DSI:FieldByName("Cena2") end
if idsklad=="13" then return DSI:FieldByName("Cena3") end
return Params.CenikCena
end
==== GetCenikCena ====
Zde se realizuje cenová politika. Funguje podobne jako [[#GetCena]], jen nedostava posledni parametr (Params)
fce(SourceDSI, destDSI) return cena
==== GetNaklady ====
Zde se realizuje cenová politika. Funguje podobne jako [[#GetCena]], jen nedostava posledni parametr (Params)
fce(SourceDSI, destDSI) return cena
==== ShowLookupField ====
Se volá ve chvíli kdy uživatel zmáčke tlačítko se třemi tečkami.
Návratový kód funkce je vložen do Fieldu, //nil// je ignorován.
ClientSession:AddLUAEvent("REZERV.sklad_rezobjva.IDObjed.ShowLookupField", "v_sklad_rezobjva.ShowLookupField")
function v_sklad_rezobjva.ShowLookupField(DSI, FieldName)
local polozkyDS = DSI:OwnerMiddleDB():FindDataSetItem("sklad_rezerv")
local IDSkladKarta = polozkyDS:FieldByName("IDSkladKarta")
local ID = polozkyDS:FieldByName("ID")
local IDRezerv = polozkyDS:FieldByName("IDRezerv")
local tabulka = ''
if DSI:FieldByName("v_zdroj")=='O' then tabulka = "sklad_objpol"
elseif DSI:FieldByName("v_zdroj")=='R' then tabulka = "sklad_rezerv"
end
local sql = [[select * from ]]..tabulka..[[
where IDSkladKarta = ']]..IDSkladKarta..[[' AND
IDRezerv != ']]..IDRezerv..[[']]
if DEBUG_DETAIL and DEBUG_DETAIL>1 then DEBUG_WRITE({sql=sql}) end
local srcMD=ClientSession:CreateMidFromXML(sql)
local sqlDS = srcMD:FindDataSetItem("")
sqlDS:LocateRange("","")
local form=WindowsManager:CreateDetailMidDBForm(srcMD)
local outSP=WindowsManager:ShowFormSP(form, {Modal=true})
form=form:Free()
if outSP.MRCode==2 then srcMD=srcMD:Free() return end
if DEBUG_DETAIL then DEBUG_WRITE({OutSP=outSP}) end
DSI:Edit()
DSI:SetFieldByName("IDobjed",sqlDS:FieldByName("IDRezerv"))
DSI:SetFieldByName("IDO",sqlDS:FieldByName("ID"))
DSI:Post()
srcMD:Free()
end
==== SetFilter ====
Registruje se k pouze k DSI a volá se pro všechny Middle, kde se tabulka vyskytuje. Funkce dostává DSI, MDName a vrací wherestring, který se připojuje pomocí and k stávajícímu filtru.
ClientSession:AddLUAEvent("sklad_karty.SetFilter", "v_sklad_karty.SetFilter")
function v_sklad_karty.SetFilterUser(DSI, MDName)
--umozni zobrazeni karet z druhu "adm" pouze Adminum
if not ClientSession:ISLoggedAdmin() then
return [[COALESCE(IDDruh,'') != 'adm']]
end
end
==== AfterPasteClipboard ====
Volá se na konci kopírovaní CTRL+V, záznam je postnutý. Pokud se kopíruje více záznamů volá se jen jednou na konci, DSI na je posledním kopírovaném.
ClientSession:AddLUAEvent("rozpocty.rozpocty_rozpocty.AfterPasteClipboard", "rozpocty_rozpocty.AfterPasteClipboard")
function rozpocty_rozpocty.AfterPasteClipboard(DSI)
if DSI:OwnerMiddleDB():FindDataSetItem("rozpocty_rkap"):GetState()==STATE_BROWSE then
DSI:OwnerMiddleDB():FindDataSetItem("rozpocty_rkap"):Refresh() --refresh kap. aby se doplnily OnCalc fiedly, ktere se pri kopirovani nepocitaji
end
end
==== AfterCopyDetails ====
Volá se po zkopírovaní všech slave tabulek, pro každý jednotlivý RootDSI záznam, RootDSI je postnuté.
ClientSession:AddLUAEvent("ROZPOCTY.rozpocty_rozpocty.AfterCopyDetails","rozpocty_rozpocty.AfterCopyDetails")
function rozpocty_rozpocty.AfterCopyDetails(DSI)
print("AfterCopyDetails", DSI:FieldByName("IDRozp"), DSI:GetState())
end
===== Ukázky postupu volání eventů =====
==== Insert ====
- [[#BeforeInsert]]
- [[#ChangeFieldValue]] pro nastavovné sloupce (ID apod.)
- Druh.[[#UserDefined]]
- [[#OnNewRecord]]
- Counter.[[#UserDefined]]
- [[#AfterInsert]]
====== Eventy Middle ======
===== Seznam =====
* [[#BeforeActivate]]
* [[#AfterActivate]]
* [[#BeforePassivate]]
* [[#AfterPassivate]]
* [[#DataToDenik]]
* [[#BeforePrint]]
===== Popis =====
==== BeforeActivate ====
* není žádný parametr funkce
==== AfterActivate ====
==== BeforePassivate ====
==== AfterPassivate ====
==== DataToDenik ====
Event se spouští při Postu hlavičky v deníku, pokud jsou prázdné položky zaúčtování.
Funkce pak dostává zdrojové Middle a ID (číslo zdrojového dokladu).
Funkce pak vrátí Middle, které obsahuje jeden ResultDSI s rozúčtováním (datamodel odpovídá položkám rozúčtování, ale sloupec s částkou se jmenuje CenaCelkem).
Pokud nemá položka v ResultDSI vyplněnu cenu, tak se do rozúčtování nevloží.
ClientSession:AddLUAEvent("majetek.DataToDenik", "majetek_majetek.DataToDenik")
function majetek_majetek.DataToDenik(Middle, ID)
if DEBUG_DETAIL then DEBUG_WRITE({ ID=ID }) end
local IDMajetek, ID = cf.nextWord(";", ID)
local M = ClientSession:CreateMidFromXML(string.format(
[[select o.MDUcet, o.DalUcet, p.Cena as CenaCelkem, '' as IDZakaz, '' as IDStred
from common_operace o, majetek_polozky p
where o.IDOperace=p.IDOperace and p.IDMajetek='%s' and p.IDMpolP=%d]], IDMajetek, ID))
M:FindDataSetItem(""):LocateRange("", "")
return M
end
==== BeforePrint ====
parametry: middle
====== Eventy Forem ======
==== ExternalInsertLua ====
Zaregistruje se ve volání WindowsManager:ShowFormSP(Form, {ExternalInsertLua=function_name})
Volání: function_name(Form, DSI)
* Form je forma ze které se vkládá
* DSI je DatasetItem ze kterého vkládá
==== PageControlChanging ====
Volá se po přepnutí "ucha" ve formě.
Volání: function_name(Form, DSI, OldDSI)
OldDSI je DatasetItem "ucha" ze kterého se přepíná. V prvním volání je OldDSI=nil, při přepínání z "ucha" nastavení také. Pokud se prepina na nastaveni je DSI nil.
Event se registruje na Name formy z Formregistru, ktery se shoduje s name master tabulky.
ClientSession:AddLUAEvent("faktury_faktury.PageControlChanging",
"faktury_faktury.PageControlChanging")
function faktury_faktury.PageControlChanging(Form, DSI, OldDSI)
--pokud se prepina do seznamu faktur z jineho ucha s DSI je Recalc
if OldDSI and DSI and DSI:GetPrimaryIndex() == DSI:OwnerMiddleDB():FindDataSetItem(""):GetPrimaryIndex() then
faktury_faktury.Recalculate(DSI)
end
end
==== CloseQuery ====
Volá se při zavření okna. Vrati-li funkce false, okno nebude zavřeno.
Volání: function_name(Form, DSI, Button)
Button = [MR_OK|MR_CANCEL]
==== CanShow ====
* ClientSession:AddLUAEvent("form_name.CanShow", FuncName)
* FuncName(Form, DSI) return ErrMsg:string|nil
ClientSession:AddLUAEvent("partneri_partneri.CanShow", "partneri_partneri.CanShow")
function partneri_partneri.CanShow(Form, DSI)
Form:MergeLocalMenuFromXML(Form:GetMiddleDB():FindDataSetItem(""), partneri_partneri.GetRychleAkceXMLMenu("partneri_partneri_RychleAkceClick", "RychleAkce"))
end
ClientSession:AddLUAEvent("SKUPINY.CanShow", "common_skupiny.SkupinyCanShow")
function common_skupiny.SkupinyCanShow(Form, DSI)
if not ClientSession:IsLoggedAdmin() then
return enc"K tomuto modulu má přístup pouze administrátor"
end
end
===== Ukazka spousteni registrovanych eventu v LUA =====
local MD=ClientSession:ActivateMid("Faktury")
local DSI=MD:FindDataSetItem("")
DSI:LocateRange("","")
for Event, Val in pairs(DSI:GetInfo("none").Events) do
if string.find(Event, "%.PrintRow$") then
for i, v in ipairs(Val) do
print(assert(loadstring(string.format("return %s(...)", v.Function)))(DSI))
end
end
end