====== 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