Obsah

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)

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

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

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:

  1. nejprve se zavola GetCenikCena (ta bere defaultne sloupec Cena z tabulky a pak vola retezove GetCenikCena eventy)
  2. zavola retezove v poradi registrace fce GetCena
  3. pokud GetCena vraci nil, neni hodnota ceny zmenena
  4. 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

  1. ChangeFieldValue pro nastavovné sloupce (ID apod.)
  2. Counter.UserDefined

Eventy Middle

Seznam

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)

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("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