#ifdef RES /* RES_PAC.SRC * * $Revision$ * $Id$ */ CREATE OR REPLACE PACKAGE res AS FUNCTION res_copy_res (pres_key IN NUMBER, newdate IN DATE, puserkey NUMBER, pmetbez NUMBER DEFAULT 0, newreskey NUMBER DEFAULT NULL) RETURN NUMBER; FUNCTION res_copy_deelres (prsv_ruimte_key IN NUMBER, newdate IN DATE, puserkey NUMBER, pmetbez NUMBER DEFAULT 1, newreskey NUMBER DEFAULT NULL, newvolgnr NUMBER DEFAULT NULL) RETURN NUMBER; PROCEDURE res_sync_deelres (prsv_ruimte_key_from IN NUMBER, prsv_ruimte_key_to IN NUMBER, flags IN NUMBER, pres_copy_to_bez IN NUMBER); PROCEDURE set_catalogus_approve(prsv_ruimte_key IN NUMBER, puserkey IN NUMBER); PROCEDURE send_need_approval_noti (prsv_ruimte_key IN NUMBER, puserkey IN NUMBER); PROCEDURE set_ruimte_dirty (prsv_ruimte_key IN NUMBER); PROCEDURE set_ruimtes_clean (checkdate IN DATE); PROCEDURE set_delen_dirty (prsv_ruimte_key IN NUMBER); PROCEDURE set_deel_dirty (prsv_deel_key IN NUMBER); PROCEDURE set_artikelen_dirty (prsv_ruimte_key IN NUMBER); PROCEDURE set_artikel_dirty (prsv_artikel_key IN NUMBER); FUNCTION dirty_level_all (prsv_ruimte_key IN NUMBER) RETURN NUMBER; PROCEDURE set_delen_clean (pdeel_key IN NUMBER, checkdate_van IN DATE, checkdate_tot IN DATE); PROCEDURE follow_artikel (prsv_ruimte_key IN NUMBER, oldvan IN DATE, oldtot IN DATE, check_scope IN NUMBER DEFAULT 1); PROCEDURE follow_deel (prsv_ruimte_key IN NUMBER, oldvan IN DATE, oldtot IN DATE); PROCEDURE follow_afspraak (prsv_ruimte_key IN NUMBER, pres_copy_to_bez IN NUMBER); FUNCTION res_deel_in_scope (pres_deel_key IN NUMBER, pres_rsv_ruimte_key IN NUMBER) RETURN BOOLEAN; FUNCTION res_artikel_in_scope (pres_rsv_artikel_key IN NUMBER) RETURN BOOLEAN; FUNCTION getresruimteprijs (pres_ruimte_key IN NUMBER, pvan IN DATE DEFAULT SYSDATE, ptot IN DATE DEFAULT SYSDATE, pextern IN NUMBER DEFAULT 0) RETURN NUMBER; FUNCTION getruimteprijs (pres_rsv_ruimte_key IN NUMBER, ignoretotaal IN NUMBER DEFAULT NULL) RETURN NUMBER; FUNCTION getdeelprijs (pres_rsv_deel_key IN NUMBER) RETURN NUMBER; FUNCTION getartikelprijs (pres_rsv_artikel_key IN NUMBER) RETURN NUMBER; FUNCTION getdeelresprijs (pres_rsv_ruimte_key IN NUMBER) RETURN NUMBER; FUNCTION sprintf (ps IN VARCHAR2 , pres_rsv_ruimte_key IN NUMBER) RETURN VARCHAR2; FUNCTION notifypool (pbez_bezoeker_key IN NUMBER, pcode IN VARCHAR2) RETURN NUMBER; PROCEDURE notifybackoffice (prsvkey IN NUMBER, pcode IN VARCHAR2, ptype IN VARCHAR2 DEFAULT NULL, pkey IN NUMBER DEFAULT NULL); PROCEDURE remove(p_rsv_ruimte_key IN NUMBER); PROCEDURE notifyreserveringbedrijven (prsvkey NUMBER, ptrackingkey NUMBER, pnotidelay NUMBER DEFAULT NULL); END res; / CREATE OR REPLACE PACKAGE BODY res AS FUNCTION res_copy_res (pres_key IN NUMBER, newdate IN DATE, puserkey NUMBER, pmetbez NUMBER DEFAULT 0, newreskey NUMBER DEFAULT NULL) RETURN NUMBER AS nextkey res_reservering.res_reservering_key%TYPE; rsv_key res_rsv_ruimte.res_rsv_ruimte_key%TYPE; newvolgnr res_rsv_ruimte.res_rsv_ruimte_volgnr%TYPE; BEGIN IF newreskey IS NOT NULL THEN nextkey := newreskey; ELSE SELECT res_s_res_reservering_key.NEXTVAL INTO nextkey FROM DUAL; INSERT INTO res_reservering (res_reservering_key, res_reservering_ispool) SELECT nextkey, res_reservering_ispool FROM res_reservering WHERE res_reservering_key = pres_key; END IF; newvolgnr := 1; FOR prsv_ruimte IN (SELECT res_rsv_ruimte_key FROM res_v_aanwezigrsv_ruimte WHERE res_reservering_key = pres_key) LOOP rsv_key := res.res_copy_deelres (prsv_ruimte.res_rsv_ruimte_key, newdate, puserkey, pmetbez, nextkey, newvolgnr); res.set_catalogus_approve(rsv_key, puserkey); newvolgnr := newvolgnr + 1; END LOOP; RETURN nextkey; END; FUNCTION res_copy_deelres (prsv_ruimte_key IN NUMBER, newdate IN DATE, puserkey NUMBER, pmetbez NUMBER DEFAULT 1, newreskey NUMBER DEFAULT NULL, newvolgnr NUMBER DEFAULT NULL) RETURN NUMBER AS nextvolg res_rsv_ruimte.res_rsv_ruimte_volgnr%TYPE; nextkey res_rsv_ruimte.res_rsv_ruimte_key%TYPE; destatus res_rsv_ruimte.res_status_bo_key%TYPE; fo_status res_rsv_ruimte.res_status_fo_key%TYPE; fo_status_res res_rsv_ruimte.res_status_fo_key%TYPE; BEGIN SELECT res_s_res_rsv_ruimte_key.NEXTVAL INTO nextkey FROM DUAL; SELECT MAX (a.res_rsv_ruimte_volgnr) + 1, MAX(a.res_status_bo_key) INTO nextvolg, destatus FROM res_rsv_ruimte a, res_rsv_ruimte b WHERE a.res_reservering_key = b.res_reservering_key AND b.res_rsv_ruimte_key = prsv_ruimte_key; -- De status is NULL (als opstelkey leeg is, dus CV-reserveringen) of iets. -- Als het iets is, dan wordt de status van de kopie 2 (=nieuw) IF destatus IS NOT NULL THEN destatus := 2; END IF; -- Als de fo status van de res_ruimte NULL is of het is geen ruimtereservering, -- neem dan de waarde van de setting "res_default_fo_status_key". SELECT COALESCE(rr.res_status_fo_key, fac.safe_to_number (fac.getsetting ('res_default_fo_status_key'))) , rrr.res_status_fo_key INTO fo_status , fo_status_res FROM res_rsv_ruimte rrr, res_ruimte_opstelling rro, res_ruimte rr WHERE rrr.res_ruimte_opstel_key = rro.res_ruimte_opstel_key(+) AND rro.res_ruimte_key = rr.res_ruimte_key(+) AND rrr.res_rsv_ruimte_key = prsv_ruimte_key; -- Als status van rsv_ruimte =3 (Blokkade) dan deze overnemen. IF (fo_status_res = 3) THEN fo_status := 3; END IF; INSERT INTO res_rsv_ruimte (res_rsv_ruimte_key, res_reservering_key, res_rsv_ruimte_volgnr, res_rsv_ruimte_omschrijving, res_rsv_ruimte_opmerking, alg_ruimte_key, res_ruimte_opstel_key, mld_opdr_key, res_rsv_ruimte_van, res_rsv_ruimte_tot, prs_kostenplaats_key, res_rsv_ruimte_host_key, res_activiteit_key, res_status_fo_key, res_status_bo_key, res_rsv_ruimte_kosten_klant, res_rsv_ruimte_contact_key, res_rsv_ruimte_bezoekers, res_rsv_ruimte_cvab_mode, res_rsv_ruimte_telefoon, res_rsv_ruimte_extern_meeting ) SELECT nextkey, COALESCE(newreskey, res_reservering_key), COALESCE(newvolgnr, nextvolg), res_rsv_ruimte_omschrijving, res_rsv_ruimte_opmerking, alg_ruimte_key, res_ruimte_opstel_key, mld_opdr_key, newdate + (res_rsv_ruimte_van - TRUNC (res_rsv_ruimte_van)), newdate + (res_rsv_ruimte_tot - TRUNC (res_rsv_ruimte_van)), prs_kostenplaats_key, res_rsv_ruimte_host_key, res_activiteit_key, fo_status, destatus, res_rsv_ruimte_kosten_klant, res_rsv_ruimte_contact_key, res_rsv_ruimte_bezoekers, res_rsv_ruimte_cvab_mode, res_rsv_ruimte_telefoon, res_rsv_ruimte_extern_meeting FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte_key; -- Now make the copy have the same childeren as the original -- (all main data is already uptodate) res.res_sync_deelres (prsv_ruimte_key, nextkey, 128 + 256 + pmetbez*512 + 1024, 0); -- Het hekje voorkomt individuele notificaties fac.trackaction ('#RESNEW', nextkey, puserkey, NULL, NULL); RETURN nextkey; END; PROCEDURE res_sync_deelres (prsv_ruimte_key_from IN NUMBER, prsv_ruimte_key_to IN NUMBER, flags IN NUMBER, pres_copy_to_bez IN NUMBER) AS --flags (0-131071) -- 0 Niks -- 1 Omschrijving -- 2 Opmerking -- 4 Tijdstip (impliceert deels impact op 128, 256 en 512) -- 2048 Datum -- 8 Aantal personen -- 16 Ruimte/opstelling -- 32 Gastheer -- 64 Kostenplaats -- 128 Voorzieningen (delen) -- 256 Catering (artikelen) -- 512 Bezoekers -- 1024 Flexkenmerken -- 2048 Datum -- 4096 Naam -- 8192 Reserveringsstatus -- 16384 Afgesproken ruimteprijs -- 32768 Korting -- 65536 Flags (bolletjes) -- Neem van alles (afh. flags) van prsv_ruimte_key_from over naar prsv_ruimte_key_to -- Misschien inzetbaar bij follow_artikel met prsv_ruimte_key_from==prsv_ruimte_key_to -- Bepaal de rsv_ruimte van dezelfde reservering die verder in de toekomst liggen -- dan de meegegeven rsv_ruimte rsv_from res_rsv_ruimte%ROWTYPE; rsv_to res_rsv_ruimte%ROWTYPE; new_ruimte_van DATE; new_ruimte_tot DATE; bez_parkingdiscipline_key NUMBER; BEGIN SELECT * INTO rsv_from FROM res_rsv_ruimte rr WHERE rr.res_rsv_ruimte_key = prsv_ruimte_key_from; SELECT * INTO rsv_to FROM res_rsv_ruimte rr WHERE rr.res_rsv_ruimte_key = prsv_ruimte_key_to; -- 0 Niks IF BITAND (flags, 131071) = 0 THEN RETURN; END IF; -- Als de tijd moet worden genegeerd, dan is de nieuwe tijd dus ook de oude, -- anders bepaal ik het nieuwe tijdstip IF BITAND (flags, 4) = 4 THEN -- De tijd moet worden aangepast. De datum verandert hier niet -- De kopie moet hier net zo laat op Die datum plaatsvinden als het origineel -- Bepaling van-tijd en tot-tijd in Oracle-decimaal (12 uur middag is 0,5) new_ruimte_van := -- orginele datum + nieuwe tijdstip TRUNC (rsv_to.res_rsv_ruimte_van) + (rsv_from.res_rsv_ruimte_van - TRUNC (rsv_from.res_rsv_ruimte_van)); new_ruimte_tot := TRUNC (rsv_to.res_rsv_ruimte_tot) + (rsv_from.res_rsv_ruimte_tot - TRUNC (rsv_from.res_rsv_ruimte_tot)); ELSE new_ruimte_van := rsv_to.res_rsv_ruimte_van; new_ruimte_tot := rsv_to.res_rsv_ruimte_tot; END IF; -- vars new_ruimte_van en new_ruimte_tot zijn nu gezet IF BITAND (flags, 2048) = 2048 THEN -- De datum moet worden aangepast. De tijd verandert hier niet -- new_ruimte_van/tot = nieuwe datum + orginele tijdstip new_ruimte_van := TRUNC (rsv_from.res_rsv_ruimte_van) + (new_ruimte_van - TRUNC (new_ruimte_van)); new_ruimte_tot := TRUNC (rsv_from.res_rsv_ruimte_tot) + (new_ruimte_tot - TRUNC (new_ruimte_tot)); END IF; -- -- Nu alle velden een voor een updaten -- -- 1 Omschrijving IF BITAND (flags, 1) = 1 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_omschrijving = rsv_from.res_rsv_ruimte_omschrijving WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 2 Opmerking IF BITAND (flags, 2) = 2 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_opmerking = rsv_from.res_rsv_ruimte_opmerking WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 4 Tijdstip 2048 datum IF BITAND (flags, 4) = 4 OR BITAND (flags, 2048) = 2048 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_van = new_ruimte_van, res_rsv_ruimte_tot = new_ruimte_tot WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; res.set_ruimtes_clean(rsv_to.res_rsv_ruimte_van); res.follow_deel(prsv_ruimte_key_to, rsv_to.res_rsv_ruimte_van, rsv_to.res_rsv_ruimte_tot); res.follow_artikel(prsv_ruimte_key_to, rsv_to.res_rsv_ruimte_van, rsv_to.res_rsv_ruimte_tot); res.follow_afspraak(prsv_ruimte_key_to, 0); -- Opmerking en flex eventueel aan het eind aanpassen. Hier nog niet. END IF; -- 8 Aantal personen IF BITAND (flags, 8) = 8 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_bezoekers = rsv_from.res_rsv_ruimte_bezoekers WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 16 Ruimte+opstelling (niet: alleen opstelling) IF BITAND (flags, 16) = 16 THEN -- Dit is iets ingewikkelder: als de ruimte anders is, is de opstelkey ook anders -- Zoek dan de equivalente opstelling en gebruik dan die key -- en/of algruimte? -- TODO UPDATE res_rsv_ruimte SET res_ruimte_opstel_key = rsv_from.res_ruimte_opstel_key, alg_ruimte_key = rsv_from.alg_ruimte_key WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; res.set_ruimtes_clean(rsv_from.res_rsv_ruimte_van); END IF; -- 32 Gastheer IF BITAND (flags, 32) = 32 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_host_key = rsv_from.res_rsv_ruimte_host_key WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 64 Kostenplaats IF BITAND (flags, 64) = 64 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_kosten_klant = rsv_from.res_rsv_ruimte_kosten_klant, prs_kostenplaats_key = rsv_from.prs_kostenplaats_key, res_rsv_ruimte_ordernr = rsv_from.res_rsv_ruimte_ordernr WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 4096 Naam IF BITAND (flags, 4096) = 4096 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_contact_key = rsv_from.res_rsv_ruimte_contact_key WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 8192 Reserveringsstatus IF BITAND (flags, 8192) = 8192 THEN UPDATE res_rsv_ruimte SET res_status_fo_key = rsv_from.res_status_fo_key WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 16384 Afgesproken ruimteprijs IF BITAND (flags, 16384) = 16384 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_totaal = rsv_from.res_rsv_ruimte_totaal WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 32768 Korting IF BITAND (flags, 32768) = 32768 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_korting = rsv_from.res_rsv_ruimte_korting WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 65536 Flags (bolletjes) IF BITAND (flags, 65536) = 65536 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_flag = rsv_from.res_rsv_ruimte_flag WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- 128 Voorzieningen (delen) IF BITAND (flags, 128) = 128 THEN bez_parkingdiscipline_key := fac.safe_to_number (fac.getsetting ('vis_parking_key')); -- Verwijder de huidige artikelen voor de te wijzigen rsv_ruimte DELETE FROM res_rsv_deel WHERE res_rsv_ruimte_key = prsv_ruimte_key_to AND res_deel_key not in (select res_deel_key from res_deel where res_discipline_key = bez_parkingdiscipline_key); -- die komen straks wel -- Kopieer de delen van referentie ruimte, hanteer dezelfde tijd-offset tov de ruimte als bij het origineel BEGIN INSERT INTO res_rsv_deel (res_deel_key, res_rsv_deel_aantal, res_rsv_ruimte_key, res_rsv_deel_prijs, res_status_bo_key, res_rsv_deel_van, res_rsv_deel_tot ) SELECT ra.res_deel_key, ra.res_rsv_deel_aantal, prsv_ruimte_key_to, ra.res_rsv_deel_prijs, 2, -- ingevoerd TRUNC (rsv_to.res_rsv_ruimte_van) + (ra.res_rsv_deel_van - TRUNC (rsv_from.res_rsv_ruimte_van)), TRUNC (rsv_to.res_rsv_ruimte_van) + (ra.res_rsv_deel_tot - TRUNC (rsv_from.res_rsv_ruimte_tot)) FROM res_rsv_deel ra, res_deel rd WHERE ra.res_rsv_ruimte_key = prsv_ruimte_key_from AND ra.res_deel_key = rd.res_deel_key AND rd.res_discipline_key <> bez_parkingdiscipline_key; -- die komen straks wel END; END IF; -- 256 Catering (artikelen) IF BITAND (flags, 256) = 256 THEN -- Verwijder de huidige artikelen voor de te wijzigen rsv_ruimte DELETE FROM res_rsv_artikel WHERE res_rsv_ruimte_key = prsv_ruimte_key_to; -- Als nieuwe leveringstijd tussen ruimte_van en ruimte_tot tijden ligt dan leveringstijd nemen, -- anders rsv_ruimte_van tijd -- Kopieer de artikelen van referentie ruimte BEGIN -- behoud de oorspronkelijke artikeltijd indien deze binnen de deelreserveringstijd valt INSERT INTO res_rsv_artikel (res_artikel_key, res_rsv_artikel_aantal, res_rsv_ruimte_key, res_rsv_artikel_prijs, res_rsv_artikel_levering, res_rsv_artikel_afhalen, res_rsv_artikel_omschrijving ) SELECT ra.res_artikel_key, ra.res_rsv_artikel_aantal, prsv_ruimte_key_to, ra.res_rsv_artikel_prijs, TRUNC (rsv_to.res_rsv_ruimte_van) + (ra.res_rsv_artikel_levering - TRUNC (ra.res_rsv_artikel_levering)), ra.res_rsv_artikel_afhalen, ra.res_rsv_artikel_omschrijving FROM res_rsv_artikel ra WHERE TRUNC (rsv_to.res_rsv_ruimte_van) + (ra.res_rsv_artikel_levering - TRUNC (ra.res_rsv_artikel_levering)) BETWEEN new_ruimte_van AND new_ruimte_tot AND ra.res_rsv_ruimte_key = prsv_ruimte_key_from; -- of reset de oorspronkelijke artikeltijd naar begin van deelreservering indien deze buiten de deelreserveringstijd valt INSERT INTO res_rsv_artikel (res_artikel_key, res_rsv_artikel_aantal, res_rsv_ruimte_key, res_rsv_artikel_prijs, res_rsv_artikel_levering, res_rsv_artikel_omschrijving ) SELECT ra.res_artikel_key, ra.res_rsv_artikel_aantal, prsv_ruimte_key_to, ra.res_rsv_artikel_prijs, new_ruimte_van, ra.res_rsv_artikel_omschrijving FROM res_rsv_artikel ra WHERE NOT TRUNC (rsv_to.res_rsv_ruimte_van) + (ra.res_rsv_artikel_levering - TRUNC (ra.res_rsv_artikel_levering)) BETWEEN new_ruimte_van AND new_ruimte_tot AND ra.res_rsv_ruimte_key = prsv_ruimte_key_from; END; -- Kenmerken ook kopieren. IF BITAND (flags, 1024) = 1024 THEN -- Verwijder eerst de oude niet-file kenmerken -- Artikel kenmerken. DELETE FROM res_kenmerkartikel WHERE res_rsv_artikel_key IN (SELECT res_rsv_artikel_key FROM res_rsv_artikel WHERE res_rsv_ruimte_key = prsv_ruimte_key_to) AND res_kenmerk_key IN (SELECT k.res_kenmerk_key FROM res_kenmerkartikel w, res_kenmerk k, res_srtkenmerk sk WHERE w.res_kenmerk_key = k.res_kenmerk_key AND k.res_srtkenmerk_key = sk.res_srtkenmerk_key AND w.res_rsv_artikel_key IN (SELECT res_rsv_artikel_key FROM res_rsv_artikel WHERE res_rsv_ruimte_key = prsv_ruimte_key_to) AND sk.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E')); -- -- Artikel kenmerken. -- Artikel is al toegevoegd indien catering is aangevinkt. -- De kenmerken van de oude en nieuwe reserveringen zijn exact hetzelfde met dezelfde kenmerk keys enz. -- De kenmerken van de oude en nieuwe reservering in dezelfde volgorde zetten en dan de waarden overnemen. INSERT INTO res_kenmerkartikel (res_rsv_artikel_key, res_kenmerk_key, res_kenmerkartikel_waarde) SELECT newkenmerk.res_rsv_artikel_key, newkenmerk.res_kenmerk_key, oldkenmerk.res_kenmerkartikel_waarde FROM (SELECT ka.res_rsv_artikel_key, ka.res_kenmerk_key, ka.res_kenmerkartikel_waarde, ra.res_artikel_key, ROW_NUMBER() OVER(ORDER BY rra.res_rsv_artikel_key, k.res_kenmerk_key) AS RN FROM res_kenmerkartikel ka, res_kenmerk k, res_srtkenmerk sk, res_rsv_ruimte rr, res_rsv_artikel rra, res_artikel ra WHERE ka.res_kenmerk_key = k.res_kenmerk_key AND k.res_srtkenmerk_key = sk.res_srtkenmerk_key AND (k.res_artikel_key = rra.res_artikel_key OR k.res_discipline_key = ra.res_discipline_key) AND ra.res_artikel_key = rra.res_artikel_key AND ka.res_rsv_artikel_key = rra.res_rsv_artikel_key AND rra.res_rsv_ruimte_key = rr.res_rsv_ruimte_key --AND k.res_activiteit_key IS NULL -- Niet nodig: Als res_activiteit_key gevuld is dan is res_kenmerk_niveau 'A'. AND k.res_kenmerk_niveau IN ('C', 'D') AND k.res_kenmerk_volgnummer < 900 AND k.res_kenmerk_verwijder IS NULL AND ka.res_kenmerkartikel_verwijder IS NULL AND sk.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E') AND rr.res_rsv_ruimte_key = prsv_ruimte_key_from) oldkenmerk, (SELECT rra.res_rsv_artikel_key, k.res_kenmerk_key, ra.res_artikel_key, ROW_NUMBER() OVER(ORDER BY rra.res_rsv_artikel_key, k.res_kenmerk_key) AS rn FROM res_rsv_ruimte rr, res_rsv_artikel rra, res_artikel ra, res_kenmerk k WHERE rra.res_rsv_ruimte_key = rr.res_rsv_ruimte_key AND (k.res_artikel_key = rra.res_artikel_key OR k.res_discipline_key = ra.res_discipline_key) AND ra.res_artikel_key = rra.res_artikel_key AND rr.res_rsv_ruimte_key = prsv_ruimte_key_to) newkenmerk WHERE oldkenmerk.rn = newkenmerk.rn AND oldkenmerk.res_kenmerk_key = newkenmerk.res_kenmerk_key AND oldkenmerk.res_artikel_key = newkenmerk.res_artikel_key ORDER BY newkenmerk.res_rsv_artikel_key, newkenmerk.res_kenmerk_key; END IF; END IF; -- 512 Bezoekers IF BITAND (flags, 512) = 512 THEN bez.sync_resafspraak (prsv_ruimte_key_from, prsv_ruimte_key_to); END IF; -- flexkenmerken -- Bestandskenmerken worden NIET gesynchroniseerd, by design -- Zou meekopieren van de bestanden via het OS vereisen, en we -- achten de wenselijkheid zeldzaam IF BITAND (flags, 1024) = 1024 THEN -- Verwijder eerst de oude niet-file kenmerken -- Ruimte kenmerken. DELETE FROM res_kenmerkwaarde WHERE res_rsv_ruimte_key = prsv_ruimte_key_to AND res_kenmerk_key IN (SELECT k.res_kenmerk_key FROM res_kenmerkwaarde w, res_kenmerk k, res_srtkenmerk sk WHERE w.res_kenmerk_key = k.res_kenmerk_key AND k.res_srtkenmerk_key = sk.res_srtkenmerk_key AND w.res_rsv_ruimte_key = prsv_ruimte_key_to AND sk.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E')); -- -- Ruimte kenmerken. INSERT INTO res_kenmerkwaarde (res_rsv_ruimte_key, res_kenmerk_key, res_kenmerkreservering_waarde) SELECT prsv_ruimte_key_to , k.res_kenmerk_key , waarde_from.res_kenmerkreservering_waarde FROM res_kenmerk k , res_srtkenmerk s , res_rsv_ruimte r , ( SELECT w1.res_kenmerkreservering_waarde , k1.res_kenmerk_groep , k1.res_srtkenmerk_key , k1.res_activiteit_key , k1.res_kenmerk_key , k1.res_kenmerk_omschrijving , s1.res_srtkenmerk_omschrijving FROM res_kenmerkwaarde w1 , res_kenmerk k1 , res_srtkenmerk s1 , res_rsv_ruimte r1 WHERE w1.res_kenmerk_key = k1.res_kenmerk_key AND k1.res_srtkenmerk_key = s1.res_srtkenmerk_key AND k1.res_activiteit_key = r1.res_activiteit_key AND k1.res_artikel_key IS NULL AND w1.res_rsv_ruimte_key = r1.res_rsv_ruimte_key AND w1.res_kenmerkwaarde_verwijder IS NULL AND s1.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E') AND r1.res_rsv_ruimte_key = prsv_ruimte_key_from ) waarde_from WHERE k.res_activiteit_key = r.res_activiteit_key AND k.res_kenmerk_niveau = 'A' AND k.res_kenmerk_volgnummer < 900 AND k.res_kenmerk_verwijder IS NULL AND s.res_srtkenmerk_verwijder IS NULL AND k.res_srtkenmerk_key = s.res_srtkenmerk_key AND s.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E') AND waarde_from.res_srtkenmerk_key = k.res_srtkenmerk_key AND COALESCE(waarde_from.res_kenmerk_omschrijving, waarde_from.res_srtkenmerk_omschrijving) = COALESCE(k.res_kenmerk_omschrijving, s.res_srtkenmerk_omschrijving) AND waarde_from.res_kenmerk_groep = k.res_kenmerk_groep AND r.res_rsv_ruimte_key = prsv_ruimte_key_to; END IF; -- Opmerking en/of Flexkenmerken (2 en/of 1024) aanpassen als de setting "res_copy_to_bez" dit aangeeft IF (BITAND (flags, 2) = 2 OR BITAND (flags, 1024) = 1024) AND BITAND(pres_copy_to_bez, 4) = 4 THEN res.follow_afspraak(prsv_ruimte_key_to, pres_copy_to_bez); -- Opmerking en/of flexkenmerken van de afspraak aanpassen. END IF; -- and verify the validity res.set_ruimte_dirty (prsv_ruimte_key_to); res.set_delen_dirty (prsv_ruimte_key_to); res.set_artikelen_dirty (prsv_ruimte_key_to); END; -- Er moet aangegeven worden of de artikelregels gefiatteerd dienen te worden of direct goedgekeurd kunnen worden. PROCEDURE set_catalogus_approve (prsv_ruimte_key IN NUMBER, puserkey IN NUMBER) AS hastoapprove NUMBER := 0; -- Voor elke artikelregel het totaalbedrag en drempelbedrag van zijn catalogus opleveren. CURSOR prsv_artikel_cat_appr IS SELECT ( SELECT SUM(res.getartikelprijs(rra1.res_rsv_artikel_key)) sum_cat_artprijs FROM res_rsv_artikel rra1, res_artikel ra1 WHERE rra1.res_artikel_key = ra1.res_artikel_key AND rra1.res_rsv_artikel_dirtlevel = 0 AND rra1.res_rsv_ruimte_key = rra.res_rsv_ruimte_key AND ra1.res_discipline_key = ra.res_discipline_key GROUP BY ra1.res_discipline_key) sum_cat_artprijs, rdp.res_disc_params_threshold FROM res_rsv_artikel rra, res_artikel ra, res_v_aanwezigdiscipline rd, res_disc_params rdp WHERE rra.res_artikel_key = ra.res_artikel_key AND ra.res_discipline_key = rd.ins_discipline_key AND rd.ins_discipline_key = rdp.res_ins_discipline_key AND rra.res_rsv_ruimte_key = prsv_ruimte_key; BEGIN FOR prsv_art_cat_appr IN prsv_artikel_cat_appr LOOP -- Voor elke artikelregel bepalen of deze nog gefiatteerd dient te worden of dat de artikelregel direct goedgekeurd kan worden. IF hastoapprove = 0 AND prsv_art_cat_appr.sum_cat_artprijs > prsv_art_cat_appr.res_disc_params_threshold THEN hastoapprove := 1; END IF; END LOOP; -- De res_rsv_artikel_approved velden aanpassen. De default waarde is 1. -- Rsv artikel setting res_rsv_artikel_approved: De artikelregel is 0=Niet gefiatteerd, 1=Goedgekeurd (default), 2=Afgewezen. UPDATE res_rsv_artikel SET res_rsv_artikel_approved = CASE WHEN hastoapprove = 1 THEN 0 ELSE 1 END WHERE res_rsv_ruimte_key = prsv_ruimte_key; -- Het res_rsv_ruimte_cat_appr veld aanpassen. -- Er moet worden gefiatteerd als hastoapprove true is. Er zijn dan catalogussen met een totaal bestelbedrag die boven de drempelwaarde ligt. -- Catalogus setting res_rsv_ruimte_cat_appr: Artikelregels wel of niet fiatteren {0=Nee of 1=Ja}. UPDATE res_rsv_ruimte SET res_rsv_ruimte_cat_appr = CASE WHEN hastoapprove = 1 THEN 1 ELSE 0 END WHERE res_rsv_ruimte_key = prsv_ruimte_key; IF hastoapprove = 1 THEN res.send_need_approval_noti(prsv_ruimte_key, puserkey); END IF; END; -- Kopie van res.sendNeedApprovalNotification() PROCEDURE send_need_approval_noti (prsv_ruimte_key IN NUMBER, puserkey IN NUMBER) AS lapprover_key prs_kostenplaats.prs_perslid_key%TYPE; lres_ruimte_opstel_key res_ruimte_opstelling.res_ruimte_opstel_key%TYPE; lres_reservering_key res_reservering.res_reservering_key%TYPE; lalg_ruimte_key alg_ruimte.alg_ruimte_key%TYPE; lsender alg_locatie.alg_locatie_email%TYPE; lomsfia fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; lreceiver VARCHAR2(1000); ltracking VARCHAR2(4000); -- moet tijdelijk groter dan fac_srtnotificatie.fac_srtnotificatie_oms%TYPE kunnen zijn BEGIN BEGIN SELECT k.prs_perslid_key INTO lapprover_key FROM res_rsv_ruimte rr, prs_kostenplaats k WHERE rr.prs_kostenplaats_key = k.prs_kostenplaats_key AND rr.res_rsv_ruimte_key = prsv_ruimte_key; EXCEPTION WHEN NO_DATA_FOUND THEN -- Er is geen fiatteur RETURN; END; IF lapprover_key < 0 OR prsv_ruimte_key < 0 THEN RETURN; END IF; SELECT res_ruimte_opstel_key, res_reservering_key, alg_ruimte_key INTO lres_ruimte_opstel_key, lres_reservering_key, lalg_ruimte_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte_key; IF lres_ruimte_opstel_key IS NOT NULL AND lres_ruimte_opstel_key > 0 THEN SELECT MAX(l.alg_locatie_email) INTO lsender FROM res_ruimte_opstelling ro , res_ruimte rr , res_alg_ruimte rag , alg_ruimte r , alg_verdieping v , alg_gebouw g , alg_locatie l WHERE l.alg_locatie_key = g.alg_locatie_key AND g.alg_gebouw_key = v.alg_gebouw_key AND r.alg_verdieping_key = v.alg_verdieping_key AND r.alg_ruimte_key = rag.alg_ruimte_key AND rag.res_ruimte_key = rr.res_ruimte_key AND rr.res_ruimte_key = ro.res_ruimte_key AND ro.res_ruimte_opstel_key = lres_ruimte_opstel_key; ELSIF lalg_ruimte_key IS NOT NULL AND lalg_ruimte_key > 0 THEN SELECT MAX(l.alg_locatie_email) INTO lsender FROM alg_ruimte r , alg_verdieping v , alg_gebouw g , alg_locatie l WHERE l.alg_locatie_key = g.alg_locatie_key AND g.alg_gebouw_key = v.alg_gebouw_key AND r.alg_verdieping_key = v.alg_verdieping_key AND r.alg_ruimte_key = lalg_ruimte_key; END IF; SELECT lcl.x('fac_srtnotificatie_oms', fac_srtnotificatie_key, fac_srtnotificatie_oms) INTO lomsfia FROM fac_srtnotificatie WHERE fac_srtnotificatie_code = 'RESFIA'; -- Notificatie en tracking: Reservering ##KEY## (##DESC##) is ter fiattering aangeboden aan ##FIATTEUR##. fac.putnotificationsrtprio (NULL, lapprover_key, 'RESFIA', lres_reservering_key, res.sprintf(lomsfia, prsv_ruimte_key), NULL, NULL, NULL, prsv_ruimte_key, 2, lsender ); SELECT prs_perslid_naam_full INTO lreceiver FROM prs_v_perslid_fullnames_all WHERE prs_perslid_key = lapprover_key; -- ltracking := 'Notitificatie ''{0}'' verstuurd aan {1}'; ltracking := lcl.l('lcl_res_notification_sent_to'); ltracking := REPLACE (ltracking, '{0}', 'RESFIA'); ltracking := REPLACE (ltracking, '{1}', lreceiver); fac.trackaction ('RESFIA', prsv_ruimte_key, puserkey, NULL, SUBSTR(ltracking, 1, 2048)); -- maxlengte van fac_srtnotificatie_oms END; -- Moeten wijzelf misschien dirty worden (door overlap met anderen) -- of schoon worden PROCEDURE set_ruimte_dirty (prsv_ruimte_key IN NUMBER) AS preposttime NUMBER(5,4); -- we gaan nog delen door 24, res_disc_params.res_disc_params_preposttime%TYPE is dan te klein; ruimte_blok_van NUMBER(5,4); ruimte_blok_tot NUMBER(5,4); my_res_ruimte_key res_ruimte.res_ruimte_key%TYPE; n_overlap NUMBER (10); CURSOR prsv_ruimtecur IS SELECT rr.alg_ruimte_key, rr.res_ruimte_opstel_key, rr.mld_opdr_key, ro.res_ruimte_opstel_tijd, rr.res_status_fo_key, rr.res_rsv_ruimte_van, rr.res_rsv_ruimte_tot, ra.res_activiteit_posttime FROM res_rsv_ruimte rr, res_activiteit ra, res_ruimte_opstelling ro WHERE rr.res_rsv_ruimte_key = prsv_ruimte_key AND rr.res_activiteit_key = ra.res_activiteit_key AND rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) FOR UPDATE OF res_rsv_ruimte_dirtlevel; prsv_ruimte prsv_ruimtecur%ROWTYPE; BEGIN DBMS_OUTPUT.PUT_LINE('set_ruimte_dirty ' || prsv_ruimte_key); OPEN prsv_ruimtecur; FETCH prsv_ruimtecur INTO prsv_ruimte; IF prsv_ruimte.alg_ruimte_key IS NOT NULL OR prsv_ruimte.mld_opdr_key IS NOT NULL THEN NULL; -- CV reserveringen en opdrachten worden in de ASP code behandeld ELSE IF prsv_ruimte.res_ruimte_opstel_key IS NULL THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_dirtlevel = 256 -- Geen ruimte WHERE CURRENT OF prsv_ruimtecur; ELSE -- Is er een ander res_rsv_ruimte die nu met ons overlapt? -- Zoek schoonmaaktijd. Let wel: we nemen aan dat een eventuele -- 'andere' ruimte dezelfde schoonmaaktijd heeft SELECT res_disc_params_preposttime / 24, ru.res_ruimte_begintijdblok / 24, ru.res_ruimte_eindtijdblok / 24, ru.res_ruimte_key INTO preposttime, ruimte_blok_van, ruimte_blok_tot, my_res_ruimte_key FROM res_disc_params dp, res_ruimte ru, res_ruimte_opstelling ro WHERE ru.res_discipline_key = dp.res_ins_discipline_key AND ro.res_ruimte_key = ru.res_ruimte_key AND ro.res_ruimte_opstel_key = prsv_ruimte.res_ruimte_opstel_key; IF prsv_ruimte.res_status_fo_key = 3 -- Blokkade (van onszelf!) THEN preposttime := 0; ELSIF prsv_ruimte.res_rsv_ruimte_van BETWEEN SYSDATE - 5/60/24 AND SYSDATE + 5/60/24 THEN -- Als *nu* gereserveerd negeren we schoonmaaktijd. Handig voor pda-reserveringen met noshow preposttime := 0; END IF; -- 1 Minuut marge voor afrondfouten IF preposttime > 1/24/60 THEN preposttime := preposttime - 1/24/60; END IF; DBMS_OUTPUT.PUT_LINE('Catalogus preposttime (dagen): ' || TO_CHAR(preposttime)); DBMS_OUTPUT.PUT_LINE('Activiteit posttime (uren): ' || TO_CHAR(prsv_ruimte.res_activiteit_posttime)); -- n_overlap := 0; -- Controleer op blokkade van ruimte ivm middagpauze IF (ruimte_blok_van IS NOT NULL AND ruimte_blok_tot IS NOT NULL) THEN IF ( (prsv_ruimte.res_rsv_ruimte_van < TRUNC(prsv_ruimte.res_rsv_ruimte_van)+ruimte_blok_tot - 1/24/60) AND (prsv_ruimte.res_rsv_ruimte_tot > TRUNC(prsv_ruimte.res_rsv_ruimte_van)+ruimte_blok_van + 1/24/60) ) THEN n_overlap := 1; END IF; END IF; -- Oke, hoeveel overlappende alg_ruimte hebben we nu SELECT COUNT (DISTINCT rb.res_ruimte_key) + n_overlap INTO n_overlap FROM res_alg_ruimte rb, -- ikzelf res_v_rsv_ruimte_2_alg_ruimte rr, -- de andere (SELECT res_ruimte_key, res_disc_params_preposttime FROM res_disc_params, res_ruimte WHERE res_disc_params.res_ins_discipline_key = res_ruimte.res_discipline_key) rsv_prepost -- prepost van de ander WHERE rr.alg_ruimte_key = rb.alg_ruimte_key AND rb.res_ruimte_key = my_res_ruimte_key AND rsv_prepost.res_ruimte_key = rr.res_ruimte_key -- Redundant maar zéér goed voor performance -- ONGETEST/komt niet voor maar: meerdaagse reserveringen zou zo maar goed kunnen gaan AND rb.res_alg_ruimte_verwijder IS NULL AND rr.res_rsv_ruimte_van BETWEEN TRUNC (prsv_ruimte.res_rsv_ruimte_van) AND TRUNC (prsv_ruimte.res_rsv_ruimte_tot)+1 -- Er is overlap als -- A) de andere ruimte begint voor ons einde -- B) en eindigt na ons begin -- Let op: bij Blokkade(3) van de ander rekenen we geen schoonmaaktijd. -- Dat gebeurt ietwat getruct door te tegen-corrigeren, vandaar -- de rr.res_rsv_ruimte_van PLUS preposttime AND CASE rr.res_status_fo_key WHEN 3 THEN rr.res_rsv_ruimte_van ELSE rr.res_rsv_ruimte_van - GREATEST(preposttime, rsv_prepost.res_disc_params_preposttime / 24, prsv_ruimte.res_activiteit_posttime / 24, (SELECT CASE rr.res_ruimte_opstel_key WHEN prsv_ruimte.res_ruimte_opstel_key THEN 0 -- Geen omsteltijd bij dezelfde opstelling ELSE GREATEST (prsv_ruimte.res_ruimte_opstel_tijd, rr.res_ruimte_opstel_tijd) / 24 END FROM DUAL)) END < prsv_ruimte.res_rsv_ruimte_tot AND CASE rr.res_status_fo_key WHEN 3 THEN rr.res_rsv_ruimte_tot ELSE rr.res_rsv_ruimte_tot + GREATEST(preposttime, rsv_prepost.res_disc_params_preposttime / 24, rr.res_activiteit_posttime / 24, (SELECT CASE rr.res_ruimte_opstel_key WHEN prsv_ruimte.res_ruimte_opstel_key THEN 0 -- Geen omsteltijd bij dezelfde opstelling ELSE GREATEST (prsv_ruimte.res_ruimte_opstel_tijd, rr.res_ruimte_opstel_tijd) / 24 END FROM DUAL)) END > prsv_ruimte.res_rsv_ruimte_van AND rr.res_rsv_ruimte_key != prsv_ruimte_key AND res_rsv_ruimte_dirtlevel < 256 --And die anderen niet zwaar dirty! AND rr.res_alg_ruimte_verwijder IS NULL; -- of verwijderd IF n_overlap = 0 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_dirtlevel = 0 WHERE CURRENT OF prsv_ruimtecur; ELSE UPDATE res_rsv_ruimte SET res_rsv_ruimte_dirtlevel = 512 WHERE CURRENT OF prsv_ruimtecur; --bitor (prsv_ruimte.res_rsv_ruimte_dirtlevel, 512); END IF; END IF; END IF; CLOSE prsv_ruimtecur; END; -- Zijn door *onze* wijziging vandaag andere ruimtes 'clean' geworden? -- checkdate is op zich redundant maar heel goed voor de performance PROCEDURE set_ruimtes_clean (checkdate IN DATE) AS dirtlevel res_rsv_ruimte.res_rsv_ruimte_dirtlevel%TYPE; contact_key res_rsv_ruimte.res_rsv_ruimte_contact_key%TYPE; BEGIN FOR prsv_ruimte IN (SELECT res_rsv_ruimte_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_dirtlevel <> 0 AND res_rsv_ruimte_verwijder IS NULL AND (res_status_bo_key IS NULL OR res_status_bo_key <> 6) -- status 6 is niet bij te werken. AND res_rsv_ruimte_van BETWEEN TRUNC (checkdate) AND TRUNC (checkdate + 1)) loop set_ruimte_dirty (prsv_ruimte.res_rsv_ruimte_key); -- SELECT res_rsv_ruimte_dirtlevel, res_rsv_ruimte_contact_key INTO dirtlevel, contact_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte.res_rsv_ruimte_key; -- IF dirtlevel = 0 THEN fac.trackaction ('RESCLN', prsv_ruimte.res_rsv_ruimte_key, contact_key, NULL, NULL); END IF; -- TODO: Alle ruimtes met Dirty-bitje bekijken end loop; END; -- Moeten wijzelf misschien dirty worden -- (door overlap met andere reserveringen van hetzelfde deel) -- Of doordat we 'uit scope' zijn gevallen PROCEDURE set_delen_dirty (prsv_ruimte_key IN NUMBER) AS BEGIN FOR prsv_deel IN (SELECT res_rsv_deel_key FROM res_rsv_deel WHERE res_rsv_ruimte_key = prsv_ruimte_key AND res_rsv_deel_verwijder IS NULL) loop set_deel_dirty (prsv_deel.res_rsv_deel_key); end loop; END; -- Moeten wijzelf misschien dirty worden -- Bijv. doordat we 'uit scope' zijn gevallen PROCEDURE set_artikelen_dirty (prsv_ruimte_key IN NUMBER) AS BEGIN FOR prsv_artikel IN (SELECT res_rsv_artikel_key FROM res_rsv_artikel WHERE res_rsv_ruimte_key = prsv_ruimte_key AND res_rsv_artikel_verwijder IS NULL) loop set_artikel_dirty (prsv_artikel.res_rsv_artikel_key); end loop; END; -- Maximale dirtlevel over hele deelreservering -- merk op dat je er niet meer aan kunt zien of het over -- de ruimte dan wel delen ging! FUNCTION dirty_level_all (prsv_ruimte_key IN NUMBER) RETURN NUMBER AS dirtlevel res_rsv_ruimte.res_rsv_ruimte_dirtlevel%TYPE; BEGIN SELECT MAX (dirtlevel) INTO dirtlevel FROM (SELECT ra.res_rsv_ruimte_key, res_rsv_artikel_dirtlevel dirtlevel FROM res_rsv_artikel ra WHERE res_rsv_artikel_verwijder IS NULL UNION ALL SELECT res_rsv_ruimte_key, CASE WHEN (res_rsv_deel_dirtlevel < 256 OR res_rsv_deel_verwijder IS NOT NULL) THEN 0 ELSE res_rsv_deel_dirtlevel END dirtlevel FROM res_rsv_deel rd WHERE res_rsv_deel_verwijder IS NULL UNION ALL SELECT res_rsv_ruimte_key, CASE WHEN (res_rsv_ruimte_dirtlevel = 16) -- geen catering THEN 0 ELSE res_rsv_ruimte_dirtlevel END dirtlevel FROM res_rsv_ruimte) WHERE res_rsv_ruimte_key = prsv_ruimte_key; RETURN dirtlevel; END; -- Mag dit res_deel in de (koppel)ruimte van de reservering gereserveerd worden FUNCTION res_deel_in_scope (pres_deel_key IN NUMBER, pres_rsv_ruimte_key IN NUMBER) RETURN BOOLEAN IS result BOOLEAN; n_inscope INTEGER; l_alg_ruimte_count NUMBER (10); BEGIN SELECT COUNT (1) INTO l_alg_ruimte_count FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_alg_ruimte ra WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) AND ro.res_ruimte_key = ra.res_ruimte_key(+) AND rr.res_rsv_ruimte_key = pres_rsv_ruimte_key AND COALESCE (rr.alg_ruimte_key, ra.alg_ruimte_key) IS NOT NULL AND ra.res_alg_ruimte_verwijder IS NULL; -- Het kan ook een koppelruimte zijn die uit meerdere ruimten bestaat IF l_alg_ruimte_count = 0 THEN -- reservering onder opdracht heeft geen ALG-scope SELECT COUNT (d.ins_deel_key) INTO n_inscope FROM ins_deel d, res_v_aanwezigdeel r, res_v_deelscope ds, res_v_aanwezigdiscipline r_disc WHERE r.res_discipline_key = r_disc.ins_discipline_key AND r.res_deel_key = pres_deel_key AND r.res_ins_deel_key = d.ins_deel_key AND ds.res_deel_alg_level = -1 AND r.res_deel_key = ds.res_deel_key; ELSE SELECT COUNT (d.ins_deel_key) INTO n_inscope FROM ins_deel d, res_v_aanwezigdeel r, (SELECT d.alg_regio_key, l.alg_district_key, l.alg_locatie_key, g.alg_gebouw_key, v.alg_verdieping_key, r.alg_ruimte_key FROM alg_district d, alg_locatie l, alg_gebouw g, alg_verdieping v, alg_ruimte r WHERE r.alg_ruimte_key IN (SELECT COALESCE(rr.alg_ruimte_key, ra.alg_ruimte_key) alg_ruimte_key FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_alg_ruimte ra WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) AND ro.res_ruimte_key = ra.res_ruimte_key(+) AND rr.res_rsv_ruimte_key = pres_rsv_ruimte_key AND ra.res_alg_ruimte_verwijder IS NULL) AND r.alg_verdieping_key = v.alg_verdieping_key AND v.alg_gebouw_key = g.alg_gebouw_key AND g.alg_locatie_key = l.alg_locatie_key AND l.alg_district_key = d.alg_district_key) scope, res_v_deelscope ds, res_v_aanwezigdiscipline r_disc WHERE r.res_discipline_key = r_disc.ins_discipline_key AND r.res_deel_key = pres_deel_key AND r.res_ins_deel_key = d.ins_deel_key AND COALESCE(d.ins_alg_ruimte_type_org, d.ins_alg_ruimte_type) IN ('R', 'T') AND ( ds.alg_regio_key = scope.alg_regio_key OR ds.alg_district_key = scope.alg_district_key OR ds.alg_locatie_key = scope.alg_locatie_key OR ds.alg_gebouw_key = scope.alg_gebouw_key OR ds.alg_verdieping_key = scope.alg_verdieping_key OR ds.alg_ruimte_key = scope.alg_ruimte_key OR ds.res_deel_alg_level = -1) AND r.res_deel_key = ds.res_deel_key; END IF; DBMS_OUTPUT.put_line ('res_deel_in_scope(' || pres_deel_key || ',' || pres_rsv_ruimte_key || ') -->' || n_inscope); RETURN n_inscope > 0; END; -- Moeten wijzelf misschien dirty worden -- (door overlap met andere reserveringen van hetzelfde deel) -- of door out-of-scope geraakt PROCEDURE set_deel_dirty (prsv_deel_key IN NUMBER) AS n_overlap NUMBER (10); preposttime NUMBER(5,4); -- we gaan nog delen door 24, res_disc_params.res_disc_params_preposttime%TYPE is dan te klein; lres_deel_key res_rsv_deel.res_deel_key%TYPE; lres_ins_deel_key res_deel.res_ins_deel_key%TYPE; lres_prs_perslid_key res_deel.res_prs_perslid_key%TYPE; lres_deel_vervaldatum res_deel.res_deel_vervaldatum%TYPE; lrsv_ruimte_key res_rsv_deel.res_rsv_ruimte_key%TYPE; lrsv_deel_key res_rsv_deel.res_rsv_deel_key%TYPE; lrsv_deel_van res_rsv_deel.res_rsv_deel_van%TYPE; lrsv_deel_tot res_rsv_deel.res_rsv_deel_tot%TYPE; lres_rsv_deel_verwijder res_rsv_deel.res_rsv_deel_verwijder%TYPE; newdirtlevel res_rsv_deel.res_rsv_deel_dirtlevel%TYPE; lruimtevan res_rsv_ruimte.res_rsv_ruimte_van%TYPE; lruimtetot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; BEGIN BEGIN SELECT d.res_deel_key, rd.res_ins_deel_key, rd.res_prs_perslid_key, rd.res_deel_vervaldatum, d.res_rsv_ruimte_key, res_rsv_deel_key, res_rsv_deel_van, res_rsv_deel_tot, r.res_rsv_ruimte_van, r.res_rsv_ruimte_tot, res_rsv_deel_verwijder, res_disc_params_preposttime / 24 INTO lres_deel_key, lres_ins_deel_key, lres_prs_perslid_key, lres_deel_vervaldatum, lrsv_ruimte_key, lrsv_deel_key, lrsv_deel_van, lrsv_deel_tot, lruimtevan,lruimtetot, lres_rsv_deel_verwijder, preposttime FROM res_rsv_deel d, res_rsv_ruimte r, res_deel rd, res_disc_params dp WHERE d.res_rsv_ruimte_key = r.res_rsv_ruimte_key AND res_rsv_deel_key = prsv_deel_key AND d.res_deel_key = rd.res_deel_key AND rd.res_discipline_key = dp.res_ins_discipline_key; END; -- 1 Minuut marge voor afrondfouten IF preposttime > 1/24/60 THEN preposttime := preposttime - 1/24/60; END IF; newdirtlevel := 0; -- Begin 'Clean' IF lres_rsv_deel_verwijder IS NULL THEN -- Oke, hoeveel overlappende res_deel hebben we nu SELECT COUNT (DISTINCT res_rsv_deel_key) INTO n_overlap FROM res_v_aanwezigrsv_deel rad, -- de andere res_deel rd WHERE rd.res_deel_key = rad.res_deel_key AND (rd.res_ins_deel_key = lres_ins_deel_key -- Er kunnen meerdere res_deel-en zijn met dezelfde ins_deel_key/ prs_perslid_key OR rd.res_prs_perslid_key = lres_prs_perslid_key) -- Er is overlap als -- A) de andere ruimte begint voor ons einde -- B) en eindigt na ons begin AND res_rsv_deel_van < lrsv_deel_tot + preposttime AND res_rsv_deel_tot > lrsv_deel_van - preposttime AND res_rsv_deel_key <> lrsv_deel_key AND res_rsv_deel_dirtlevel < 256; -- And die anderen niet zwaar dirty! IF n_overlap > 0 THEN newdirtlevel := 512; -- Overlap END IF; IF lres_prs_perslid_key IS NULL THEN IF NOT res_deel_in_scope (lres_deel_key, lrsv_ruimte_key) OR lres_deel_vervaldatum <= lrsv_deel_tot THEN newdirtlevel := newdirtlevel + 256; -- OutOfScope/Not Allowed END IF; END IF; IF (lrsv_deel_van < lruimtevan OR lrsv_deel_tot > lruimtetot) THEN newdirtlevel := newdirtlevel + 1; -- Valt buiten de ruimtetijden END IF; END IF; UPDATE res_rsv_deel SET res_rsv_deel_dirtlevel = newdirtlevel WHERE res_rsv_deel_key = prsv_deel_key; END; -- Zijn door *onze* wijziging vandaag andere delen'clean' geworden? -- checkdate is op zich redundant maar heel goed voor de performance PROCEDURE set_delen_clean (pdeel_key IN NUMBER, checkdate_van IN DATE, checkdate_tot IN DATE) AS preposttime NUMBER(5,4); -- we gaan nog delen door 24, res_disc_params.res_disc_params_preposttime%TYPE is dan te klein; BEGIN BEGIN SELECT res_disc_params_preposttime / 24 INTO preposttime FROM res_deel rd, res_disc_params dp WHERE rd.res_deel_key = pdeel_key AND rd.res_discipline_key = dp.res_ins_discipline_key; END; -- 1 Minuut marge voor afrondfouten IF preposttime > 1/24/60 THEN preposttime := preposttime - 1/24/60; END IF; FOR prsv_deel IN (SELECT res_rsv_deel_key FROM res_rsv_deel WHERE res_deel_key = pdeel_key AND res_rsv_deel_dirtlevel <> 0 AND res_rsv_deel_van < checkdate_tot + preposttime AND res_rsv_deel_tot > checkdate_van - preposttime AND res_rsv_deel_verwijder IS NULL) loop set_deel_dirty (prsv_deel.res_rsv_deel_key); -- TODO: Alle ruimtes met Dirty-bitje bekijken end loop; END; -- Mag dit res_dartikel in de (koppel)ruimte van de reservering gereserveerd worden FUNCTION res_artikel_in_scope (pres_rsv_artikel_key IN NUMBER) RETURN BOOLEAN IS result BOOLEAN; n_inscope INTEGER; BEGIN DBMS_OUTPUT.put_line ('res_artikel_in_scope(' || pres_rsv_artikel_key || ')'); SELECT COUNT(DISTINCT ra.res_rsv_artikel_key) INTO n_inscope FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_alg_ruimte rar, res_v_alg_ruimte_gegevens rg, res_srtartikel_onrgoed sao, res_v_aanwezigartikel a, res_rsv_artikel ra WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) AND ro.res_ruimte_key = rar.res_ruimte_key(+) AND a.res_discipline_key = sao.res_discipline_key AND (rg.alg_locatie_key = sao.alg_onrgoed_key AND sao.alg_onrgoed_niveau = 'L' OR rg.alg_gebouw_key = sao.alg_onrgoed_key AND sao.alg_onrgoed_niveau = 'G' OR rg.alg_verdieping_key = sao.alg_onrgoed_key AND sao.alg_onrgoed_niveau = 'V' OR rg.alg_ruimte_key = sao.alg_onrgoed_key AND sao.alg_onrgoed_niveau = 'R') AND rg.alg_ruimte_key = COALESCE (rr.alg_ruimte_key, rar.alg_ruimte_key) AND rr.res_rsv_ruimte_key = ra.res_rsv_ruimte_key AND ra.res_artikel_key = a.res_artikel_key AND sao.res_srtartikel_og_verwijder IS NULL AND rg.alg_ruimte_key IS NOT NULL AND rar.res_alg_ruimte_verwijder IS NULL -- Het kan ook een koppelruimte zijn die uit meerdere ruimten bestaat AND ra.res_rsv_artikel_key = pres_rsv_artikel_key -- Levering tussen begintijd artikel en eindtijd artikel. AND ra.res_rsv_artikel_levering BETWEEN TRUNC (rr.res_rsv_ruimte_van) + COALESCE (a.res_artikel_begintijd, fac.safe_to_number (fac.getsetting ('res_t1'))) / 24 AND TRUNC (rr.res_rsv_ruimte_van) + COALESCE (a.res_artikel_eindtijd, fac.safe_to_number (fac.getsetting ('res_t2'))) / 24; RETURN n_inscope > 0; END; -- Moeten wijzelf misschien dirty worden -- door out-of-scope geraakt PROCEDURE set_artikel_dirty (prsv_artikel_key IN NUMBER) AS CURSOR prsv_artikelcur IS SELECT res_artikel_key, res_rsv_ruimte_key, res_rsv_artikel_key, res_rsv_artikel_verwijder FROM res_rsv_artikel WHERE res_rsv_artikel_key = prsv_artikel_key FOR UPDATE OF res_rsv_artikel_dirtlevel; prsv_artikel prsv_artikelcur%ROWTYPE; newdirtlevel res_rsv_artikel.res_rsv_artikel_dirtlevel%TYPE; BEGIN OPEN prsv_artikelcur; FETCH prsv_artikelcur INTO prsv_artikel; newdirtlevel := 0; -- Begin 'Clean' IF prsv_artikel.res_rsv_artikel_verwijder IS NULL AND NOT res_artikel_in_scope (prsv_artikel.res_rsv_artikel_key) THEN newdirtlevel := newdirtlevel + 256; -- OutOfScope END IF; UPDATE res_rsv_artikel SET res_rsv_artikel_dirtlevel = newdirtlevel WHERE CURRENT OF prsv_artikelcur; CLOSE prsv_artikelcur; END; -- prsv_ruimte_key is gewijzigd -- Als het artikel op het begintijdstip van de ruimte stond, -- dan wordt deze nu aangepast naar het nieuwe tijdstip -- Als het artikel op een afwijkende tijd stond, dan wordt die behouden -- mits die tijd binnen de nieuwe reserveertijd van de ruimte valt. Als dat -- niet zo is, dan wordt die alsnog op de begintijd daarvan gezet. -- Elk artikel valt hierna dus zeker in het ruimte-interval. -- Een artikel kan niet dirty worden door deze wijziging -- Een dirty artikel kan wel clean worden hierdoor, of er -- kunnen theoretisch andere reden zijn voor dirty PROCEDURE follow_artikel (prsv_ruimte_key IN NUMBER, oldvan IN DATE, oldtot IN DATE, check_scope IN NUMBER DEFAULT 1) AS CURSOR prsv_artikelcur IS SELECT * FROM res_rsv_artikel rra WHERE rra.res_rsv_ruimte_key = prsv_ruimte_key; prsv_artikel prsv_artikelcur%ROWTYPE; newvan res_rsv_ruimte.res_rsv_ruimte_van%TYPE; newtot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; oldvantijd VARCHAR2(5); oldtottijd VARCHAR2(5); newvandatum VARCHAR2(10); newvantijd VARCHAR2(5); newtottijd VARCHAR2(5); BEGIN SELECT res_rsv_ruimte_van, res_rsv_ruimte_tot, to_char(res_rsv_ruimte_van,'HH24:MI'), to_char(res_rsv_ruimte_tot,'HH24:MI') INTO newvan, newtot, newvantijd, newtottijd FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte_key; SELECT to_char(oldvan,'HH24:MI') INTO oldvantijd FROM DUAL; SELECT to_char(oldtot,'HH24:MI') INTO oldtottijd FROM DUAL; SELECT to_char(newvan,'DD-MM-YYYY') INTO newvandatum FROM DUAL; IF oldvantijd <> newvantijd OR oldtottijd <> newtottijd THEN -- alleen aanpassen indien de tijden zijn veranderd -- Als de status "Verwerkt(6)" krijg je hier een foutmelding via de trigger res_t_res_rsv_artikel_B_IU. -- Dat het artikel dan niet meer aangepast kan worden is niet erg omdat het artikel al helemaal afgehandeld is. UPDATE res_rsv_artikel rra SET rra.res_rsv_artikel_levering = newvan WHERE rra.res_rsv_ruimte_key = prsv_ruimte_key AND ( rra.res_rsv_artikel_levering = oldvan OR rra.res_rsv_artikel_levering > newtot OR rra.res_rsv_artikel_levering < newvan); ELSE -- change date-part only to keep the item-dates within the from-to date range UPDATE res_rsv_artikel rra SET rra.res_rsv_artikel_levering = TO_DATE (newvandatum || ' ' || TO_CHAR (res_rsv_artikel_levering, 'HH24:MI'), 'DD-MM-YYYY HH24:MI') WHERE rra.res_rsv_ruimte_key = prsv_ruimte_key AND ( rra.res_rsv_artikel_levering = oldvan OR rra.res_rsv_artikel_levering > newtot OR rra.res_rsv_artikel_levering < newvan); END IF; -- now (re)set the dirty marks FOR prsv_artikel IN prsv_artikelcur LOOP -- Alleen kijken naar dirty als het artikel nog niet verwerkt/afgehandeld is. Dan wordt er ook geen dirty update uitgevoerd. -- Als het artikel "Verwerkt(6)" is dan doet dirty er ook niet meer toe. IF (prsv_artikel.res_status_bo_key < 6 AND check_scope = 1) THEN set_artikel_dirty (prsv_artikel.res_rsv_artikel_key); END IF; END LOOP; END; -- prsv_ruimte_key is gewijzigd -- wijzig eventueel tijdstip delen en/of maak ze dirty -- niet de parkeerplaatsen, dat doet de afspraak PROCEDURE follow_deel (prsv_ruimte_key IN NUMBER, oldvan IN DATE, oldtot IN DATE) AS newvan res_rsv_ruimte.res_rsv_ruimte_van%TYPE; newtot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; CURSOR prsv_deelcur IS SELECT * FROM res_rsv_deel rrd WHERE rrd.res_rsv_ruimte_key = prsv_ruimte_key AND bez_bezoekers_key IS NULL FOR UPDATE OF res_rsv_deel_dirtlevel; prsv_deel prsv_deelcur%ROWTYPE; BEGIN -- Nieuwe tijden ophalen SELECT rr.res_rsv_ruimte_van, rr.res_rsv_ruimte_tot INTO newvan,newtot FROM res_rsv_ruimte rr WHERE rr.res_rsv_ruimte_key = prsv_ruimte_key; IF oldvan <> newvan OR oldtot <> newtot THEN -- alleen aanpassen indien de tijden zijn veranderd -- en de deeltijden matchten met de ruimtetijden -- begintijd UPDATE res_rsv_deel rra SET rra.res_rsv_deel_van = newvan WHERE rra.res_rsv_ruimte_key = prsv_ruimte_key AND rra.res_rsv_deel_van = oldvan; -- eindtijd UPDATE res_rsv_deel rra SET rra.res_rsv_deel_tot = newtot WHERE rra.res_rsv_ruimte_key = prsv_ruimte_key AND rra.res_rsv_deel_tot = oldtot; END IF; -- en set_deel_dirty/ set_delen_clean aan te roepen -- veronderstelt dat de cursor de zojuist bijgewerkte gegevens heeft. FOR prsv_deel IN prsv_deelcur loop set_deel_dirty (prsv_deel.res_rsv_deel_key); set_delen_clean (prsv_deel.res_deel_key, oldvan, oldtot); -- TODO: Alle ruimtes met Dirty-bitje bekijken? Lijkt me niet onze verantwoording hier end loop; END; -- Werkt de onderliggende afspraak bij na wijziging van een deelreservering -- Dit gaat maar om een deel van de gegevens PROCEDURE follow_afspraak (prsv_ruimte_key IN NUMBER, pres_copy_to_bez IN NUMBER) AS afspraak_key bez_afspraak.bez_afspraak_key%TYPE; newvan res_rsv_ruimte.res_rsv_ruimte_van%TYPE; newtot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; newopm res_rsv_ruimte.res_rsv_ruimte_opmerking%TYPE; oldvan bez_afspraak.bez_afspraak_datum%TYPE; oldtot bez_afspraak.bez_afspraak_eind%TYPE; ruimtekey alg_ruimte.alg_ruimte_key%TYPE; locatiekey alg_locatie.alg_locatie_key%TYPE; oldloc bez_afspraak.alg_locatie_key%TYPE; waarde res_kenmerkwaarde.res_kenmerkreservering_waarde%TYPE; bezremark VARCHAR2(2100); -- bez_afspraak.bez_afspraak_opmerking%TYPE is te kort lremarkfilled BOOLEAN; CURSOR ckenmerk IS SELECT k.res_kenmerk_key , t.res_srtkenmerk_kenmerktype , t.res_srtkenmerk_nmin nmin , t.res_srtkenmerk_nmax nmax , t.fac_kenmerkdomein_key , k.res_kenmerk_volgnummer , COALESCE(lcl.x ('res_kenmerk_omschrijving', k.res_kenmerk_key, k.res_kenmerk_omschrijving) , lcl.x ('res_srtkenmerk_omschrijving', t.res_srtkenmerk_key, t.res_srtkenmerk_omschrijving)) kenmerk_omschrijving , v.res_kenmerkreservering_waarde FROM res_srtkenmerk t , res_kenmerk k , res_kenmerkwaarde v WHERE v.res_kenmerk_key = k.res_kenmerk_key AND k.res_srtkenmerk_key = t.res_srtkenmerk_key AND k.res_kenmerk_verwijder IS NULL AND t.res_srtkenmerk_verwijder IS NULL AND k.res_kenmerk_niveau = 'A' AND v.res_rsv_ruimte_key = prsv_ruimte_key ORDER BY k.res_kenmerk_volgnummer , UPPER(COALESCE(lcl.x ('res_kenmerk_omschrijving', k.res_kenmerk_key, k.res_kenmerk_omschrijving) , lcl.x ('res_srtkenmerk_omschrijving', t.res_srtkenmerk_key, t.res_srtkenmerk_omschrijving))); BEGIN BEGIN SELECT bez_afspraak_key INTO afspraak_key FROM bez_afspraak WHERE res_rsv_ruimte_key = prsv_ruimte_key; EXCEPTION WHEN NO_DATA_FOUND THEN -- Er is helemaal geen afspraak RETURN; END; -- NOTE: RES-updates of host or contact "cascade" to BEZ by triggers and should not be handled here! -- Nieuwe tijden en opmerking ophalen SELECT rr.res_rsv_ruimte_van, rr.res_rsv_ruimte_tot, rr.res_rsv_ruimte_opmerking INTO newvan, newtot, newopm FROM res_rsv_ruimte rr WHERE rr.res_rsv_ruimte_key = prsv_ruimte_key; -- In geval van koppelruimten worden meerdere locatie keys opgeleverd. De locaties zullen echter toch hetzelfde zijn. -- Voor de ruimte waar de bezoeker naar toe moet kiezen we de laagste key (we kennen niet het concept van -- bezoekers naar res_ruimtes) SELECT MIN(g.alg_locatie_key), MIN(r.alg_ruimte_key) INTO locatiekey, ruimtekey FROM alg_ruimte r, alg_verdieping v, alg_gebouw g WHERE g.alg_gebouw_key = v.alg_gebouw_key AND v.alg_verdieping_key = r.alg_verdieping_key AND r.alg_ruimte_key IN (SELECT COALESCE (rr.alg_ruimte_key, ra.alg_ruimte_key) alg_ruimte_key FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_alg_ruimte ra WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) AND ro.res_ruimte_key = ra.res_ruimte_key(+) AND rr.res_rsv_ruimte_key = prsv_ruimte_key AND ra.res_alg_ruimte_verwijder IS NULL); SELECT bez_afspraak_datum, bez_afspraak_eind, alg_locatie_key INTO oldvan, oldtot, oldloc FROM bez_afspraak WHERE bez_afspraak_key = afspraak_key; bezremark := ''; lremarkfilled := FALSE; IF BITAND(pres_copy_to_bez, 4) = 4 THEN IF BITAND(pres_copy_to_bez, 1) = 1 THEN IF newopm IS NOT NULL OR newopm != '' THEN bezremark := newopm; lremarkfilled := TRUE; END IF; END IF; IF BITAND(pres_copy_to_bez, 2) = 2 THEN -- vullen opmerkingsveld bij bezoeker met flexkenmerken van de reservering IF lremarkfilled THEN bezremark := bezremark || chr(13) || chr(10); -- Carriage Return + Linefeed (CR + LF) toevoegen END IF; -- FOR ck IN ckenmerk LOOP waarde := ck.res_kenmerkreservering_waarde; IF waarde IS NOT NULL AND waarde <> '-1' -- gevuld THEN IF ck.res_srtkenmerk_kenmerktype = 'V' -- checkbox THEN IF waarde = '0' THEN waarde := lcl.l ('lcl_check_0'); ELSIF waarde = '1' THEN waarde := lcl.l ('lcl_check_1'); END IF; ELSIF ck.res_srtkenmerk_kenmerktype = 'R' OR ck.res_srtkenmerk_kenmerktype = 'r' OR ck.res_srtkenmerk_kenmerktype = 'S' -- referentie THEN waarde := flx.getdomeinwaarde (ck.fac_kenmerkdomein_key, TO_NUMBER (waarde)); END IF; -- In het zeldzame geval dat de tekst te lang zou worden slaan we sommige -- kenmerken gewoon silent over. Niet ideaal maar toch vrij theoretisch IF (COALESCE(LENGTH(bezremark),0) + LENGTH(ck.kenmerk_omschrijving) + LENGTH(waarde) < 3990) THEN IF lremarkfilled THEN bezremark := bezremark || CHR(10) || ck.kenmerk_omschrijving || ': ' || waarde; ELSE bezremark := ck.kenmerk_omschrijving || ': ' || waarde; lremarkfilled := TRUE; END IF; END IF; END IF; END LOOP; END IF; END IF; IF BITAND(pres_copy_to_bez, 7) > 4 THEN -- Opmerking ook opslaan UPDATE bez_afspraak SET bez_afspraak_datum = newvan, bez_afspraak_eind = newtot, alg_locatie_key = locatiekey, alg_onrgoed_keys = ruimtekey, bez_afspraak_opmerking = SUBSTR(bezremark, 1, 320) WHERE bez_afspraak_key = afspraak_key; ELSE -- Opmerking niet opslaan UPDATE bez_afspraak SET bez_afspraak_datum = newvan, bez_afspraak_eind = newtot, alg_locatie_key = locatiekey, alg_onrgoed_keys = ruimtekey WHERE bez_afspraak_key = afspraak_key; END IF; -- Parkeerplaatsen opnieuw claimen als locatie of tijd wijzigt IF oldvan <> newvan OR oldtot <> newtot OR oldloc <> locatiekey THEN FOR rpark IN (SELECT b.bez_bezoekers_key, COALESCE(org.alg_gebouw_key, org.alg_terreinsector_key) gebterkey FROM bez_bezoekers b, res_rsv_deel rd, res_deel d, ins_deel id, alg_v_allonrgoed_gegevens org WHERE res_rsv_deel_verwijder IS NULL AND rd.bez_bezoekers_key = b.bez_bezoekers_key AND rd.res_deel_key = d.res_deel_key AND d.res_ins_deel_key = id.ins_deel_key AND id.ins_alg_ruimte_key = org.alg_onroerendgoed_keys AND b.bez_afspraak_key = afspraak_key) LOOP DELETE FROM res_rsv_deel WHERE bez_bezoekers_key = rpark.bez_bezoekers_key; IF oldloc <> locatiekey THEN bez.claim_parking(rpark.bez_bezoekers_key, null); -- opnieuw claimen ELSE -- Tijd is gewijzigd, locatie niet bez.claim_parking(rpark.bez_bezoekers_key, rpark.gebterkey); -- opnieuw claimen in/op hetzelfde gebouw/terrein END IF; END LOOP; END IF; END; FUNCTION getresruimteprijs ( pres_ruimte_key IN NUMBER , pvan IN DATE DEFAULT SYSDATE , ptot IN DATE DEFAULT SYSDATE , pextern IN NUMBER DEFAULT 0 ) RETURN NUMBER IS res_roompricingmethod NUMBER; lres_t_middag NUMBER; lres_t_avond NUMBER; room_price res_ruimte.res_ruimte_prijs%TYPE; room_price_fixed res_ruimte.res_ruimte_prijs_vast%TYPE; price_morning res_ruimte.res_ruimte_prijs_ochtend%TYPE; price_afternoon res_ruimte.res_ruimte_prijs_middag%TYPE; price_evening res_ruimte.res_ruimte_prijs_avond%TYPE; price_allday res_ruimte.res_ruimte_prijs_dag%TYPE; res_length_morning NUMBER; res_length_afternoon NUMBER; res_length_evening NUMBER; cost_morning NUMBER; cost_afternoon NUMBER; cost_evening NUMBER; res_1e_dagblok NUMBER; res_2e_dagblok NUMBER; res_ruimte_length NUMBER; res_ruimte_begin NUMBER; res_ruimte_end NUMBER; thisroomprice NUMBER; BEGIN res_roompricingmethod := fac.safe_to_number (fac.getsetting ('res_roompricingmethod')); lres_t_middag := fac.safe_to_number (fac.getsetting ('res_t_middag')); lres_t_avond := fac.safe_to_number (fac.getsetting ('res_t_avond')); -- Wat basisgegevens BEGIN SELECT CASE pextern WHEN 0 THEN COALESCE (ru.res_ruimte_intprijs, 0) -- Intern ELSE COALESCE (ru.res_ruimte_prijs, 0) -- Extern END, ru.res_ruimte_prijs_vast, CASE pextern WHEN 0 THEN COALESCE (ru.res_ruimte_intprijs_ochtend, 0) -- Intern ELSE COALESCE (ru.res_ruimte_prijs_ochtend, 0) -- Extern END, CASE pextern WHEN 0 THEN COALESCE (ru.res_ruimte_intprijs_middag, 0) -- Intern ELSE COALESCE (ru.res_ruimte_prijs_middag, 0) -- Extern END, CASE pextern WHEN 0 THEN COALESCE (ru.res_ruimte_intprijs_avond, 0) -- Intern ELSE COALESCE (ru.res_ruimte_prijs_avond, 0) -- Extern END, CASE pextern WHEN 0 THEN COALESCE (ru.res_ruimte_intprijs_dag, 0) -- Intern ELSE COALESCE (ru.res_ruimte_prijs_dag, 0) -- Extern END, fac.safe_to_number (TO_CHAR (ptot - pvan)) * 24, fac.safe_to_number (TO_CHAR (pvan, 'HH24')) + fac.safe_to_number (TO_CHAR (pvan, 'MI')) / 60, fac.safe_to_number (TO_CHAR (ptot, 'HH24')) + fac.safe_to_number (TO_CHAR (ptot, 'MI')) / 60 INTO room_price, room_price_fixed, price_morning, price_afternoon, price_evening, price_allday, res_ruimte_length, res_ruimte_begin, res_ruimte_end FROM res_ruimte ru WHERE ru.res_ruimte_key = pres_ruimte_key; EXCEPTION WHEN NO_DATA_FOUND THEN -- Geen R-reservering maar een CV-reservering, dan kost de ruimte niks. Klaar. RETURN 0; END; -- -- Uren dagdeel ochtend: [0 - lres_t_middag] res_length_morning := LEAST (res_ruimte_end, lres_t_middag) - res_ruimte_begin; IF res_length_morning < 0 THEN res_length_morning := 0; END IF; -- Uren dagdeel middag: [lres_t_middag - lres_t_avond] res_length_afternoon := LEAST (res_ruimte_end, lres_t_avond) - GREATEST (res_ruimte_begin, lres_t_middag); IF res_length_afternoon < 0 THEN res_length_afternoon := 0; END IF; -- Uren dagdeel avond: [lres_t_avond - 24] res_length_evening := res_ruimte_end - GREATEST (res_ruimte_begin, lres_t_avond); IF res_length_evening < 0 THEN res_length_evening := 0; END IF; -- -- IF res_roompricingmethod = 1 THEN -- Zoals we het altijd deden IF (lres_t_middag > 0 AND lres_t_middag < 24 AND lres_t_avond > 0 AND lres_t_avond < 24) THEN -- Prijsbepaling per dagdeel IF room_price_fixed = 1 THEN -- Een prijs per blok (kennelijk). Tellen hoeveel blokken dan IF res_length_morning > 0 THEN res_length_morning := 1; END IF; IF res_length_afternoon > 0 THEN res_length_afternoon := 1; END IF; IF res_length_evening > 0 THEN res_length_evening := 1; END IF; END IF; thisroomprice := price_morning * res_length_morning + price_afternoon * res_length_afternoon + price_evening * res_length_evening; ELSE -- Prijsbepaling per dag IF room_price_fixed = 1 THEN res_ruimte_length := 1; END IF; thisroomprice := room_price * res_ruimte_length; END IF; ELSIF res_roompricingmethod = 2 THEN -- Lever voor de duur van de reservering de laagste prijs op: zie NYBU#25763 -- Dagprijs -> Uren uitgesplitst per dagdeel (uur van dat dagdeel x prijs) en vergelijken met dagdeelprijs, en daarvan het goedkoopste. -- Voor alle 3 dagdelen verkijgen we dan een goedkoopste gedrag (D1 + D2 +D3), die optellen en vergelijken met dagprijs, en daarvan de goedkoopste. -- room_price_fixed = 1 werkt alleen op dagdeelprijs, en NIET op uurtarief (eigenlijk zouden we 2 vinkjes moeten hebben, voor ieder 1 afzonderlijk). -- En tenslotte nog vergelijken met dagprijs, neem de goedkoopste. cost_morning := 0; cost_afternoon := 0; cost_evening := 0; -- Hieronder de uren uitsplitsen naar dagdelen en vergelijken met dagdeelprijzen, daarvan de goedkoopste. -- Net als bij res_roompricingmethod = 1, ook kijken of de middag en avond tijden zijn ingesteld, anders doen die niet mee. IF (lres_t_middag > 0 AND lres_t_middag < 24 AND lres_t_avond > 0 AND lres_t_avond < 24) THEN -- Een prijs per blok (kennelijk). Tellen hoeveel blokken dan IF res_length_morning > 0 THEN IF room_price_fixed = 1 THEN cost_morning := price_morning; ELSE cost_morning := price_morning * res_length_morning; END IF; IF (res_length_morning * room_price) < cost_morning THEN cost_morning := res_length_morning * room_price; END IF; END IF; IF res_length_afternoon > 0 THEN IF room_price_fixed = 1 THEN cost_afternoon := price_afternoon; ELSE cost_afternoon := price_afternoon * res_length_afternoon; END IF; IF (res_length_afternoon * room_price) < cost_afternoon THEN cost_afternoon := res_length_afternoon * room_price; END IF; END IF; IF res_length_evening > 0 THEN IF room_price_fixed = 1 THEN cost_evening := price_evening; ELSE cost_evening := price_evening * res_length_evening; END IF; IF (res_length_evening * room_price) < cost_evening THEN cost_evening := res_length_evening * room_price; END IF; END IF; thisroomprice := cost_morning + cost_afternoon + cost_evening; -- -- Als dagprijs = 0 (d.i. price_allday is NULL cq. is niet gevuld), dan telt die niet mee, en moet de nieuwe prijsberekening gelden. -- Of als dagprijs lager is lager is dan de nieuwe prijsberekening, dan ook. IF (price_allday <> 0) AND price_allday < thisroomprice THEN thisroomprice := price_allday; END IF; ELSE thisroomprice := price_allday; END IF; ELSIF res_roompricingmethod = 3 THEN -- Methode 3: STAFFELS van b.v. 4 en 8: zie WIBC#26163 -- uurprijs, dagdeelprijs en dagprijs volgens onderstaande methodiek (x = vergaderduur): -- x < 4 uur: duur x uurprijs -- 4 <= x < 8 uur: dagdeelprijs (ochtend) + (duur - 4) x uurprijs -- x >= 8 uur: dagprijs, (of indien dagprijs niet is ingesteld, dan dagdeelprijs (middag) + (duur - 8) x uurprijs -- Bij methode 3 wordt lres_t_middag niet als tijdsgrens tussen morgen en middag ingesteld, maar als een 'blok' van een aantal uren. -- En idem voor avond, die is het 2e blok (groter aantal) uren dan het 1e blok. -- res_1e_dagblok := lres_t_middag; res_2e_dagblok := lres_t_avond; -- MB: Overlegd met DEVELOP (PF): geconstateerd dat res_ruimte_res bij een reservering van 10:00-14:00 niet exact 4 is, maar 4.000000en-een-beetje. -- Tot dusver ook geen probleem met voorgaande price-methodes, maar nu gaan we (exact) vergelijken met een staffel, en dan kan die net de verkeerde kant (if-then-else) opvallen! -- Vandaar deze foef om af te ronden, alleen op deze plaats. res_ruimte_length := ROUND(res_ruimte_length, 2); -- IF (res_1e_dagblok > 0 AND res_1e_dagblok < 24) THEN -- Er is een 1e block gedefinieerd IF res_ruimte_length < res_1e_dagblok THEN -- Reserv. duur is kleiner dan 1e blok uren, gewoon uur x prijs. -- Ook hier doet setting room_price_fixed ook gewoon mee. IF room_price_fixed = 1 THEN res_ruimte_length := 1; END IF; thisroomprice := room_price * res_ruimte_length; ELSE -- Reserv. duur is groter dan 1e blok uren, is er een 2e blok gedefinieerd? -- Als 2e blok er is, en aantal uren is ook nog meer dan 2e blok, dan de dagprijs. -- Ook hier doet setting room_price_fixed ook gewoon mee. IF (res_2e_dagblok > 0 AND res_2e_dagblok < 24) THEN -- Er is een 2e block gedefinieerd IF res_ruimte_length >= res_2e_dagblok THEN -- Reserv. duur is GROTER dan 2e blok uren, dan geldt de dagprijs indien deze is ingesteld. -- Als de dagprijs NIET is ingesteld, dan dagdeelprijs (middag) + (duur - 8) x uurprijs IF price_allday > 0 THEN -- Er is een dagprijs voor de ruimte ingesteld, die telt dan. thisroomprice := price_allday; ELSE -- Er is geen dagprijs ingesteld, neem dan dagdeelprijs (middag) + (duur - 8) x uurprijs IF room_price_fixed = 1 AND res_ruimte_length > res_2e_dagblok THEN -- Niet 1 (zoals overal anders, maar 1 optellen bij het 2e dagblok (voor hieronder om weer 1 over te houden)!! -- En alleen indien res_ruimte_length groter is dan 2e dagblok (anders geen 1 bij optellen, dan geldt alleen dagdeelprijs) res_ruimte_length := res_2e_dagblok + 1; END IF; thisroomprice := price_afternoon + (room_price * (res_ruimte_length - res_2e_dagblok)); END IF; ELSE -- Reserv. duur is ligt tussen 1e en 2e blok uren in, -- dan geldt dagdeelprijs (ochtend) + (duur - 4) x uurprijs IF room_price_fixed = 1 AND res_ruimte_length > res_1e_dagblok THEN -- Niet 1 (zoals overal anders, maar 1 optellen bij het 1e dagblok (voor hieronder om weer 1 over te houden)!! -- En alleen indien res_ruimte_length groter is dan 1e dagblok (anders geen 1 bij optellen, dan geldt alleen dagdeelprijs) res_ruimte_length := res_1e_dagblok + 1; END IF; thisroomprice := price_morning + (room_price * (res_ruimte_length - res_1e_dagblok)); END IF; ELSE -- Er is geen 2e blok uren gedefinieerd, alleen een 1e urenblok. -- Dan gewoon dagdeelprijs (ochtend) + (duur - 4) x uurprijs IF room_price_fixed = 1 AND res_ruimte_length > res_1e_dagblok THEN -- Niet 1 (zoals overal anders, maar 1 optellen bij het 1e dagblok (voor hieronder om weer 1 over te houden)!! -- En alleen indien res_ruimte_length groter is dan 1e dagblok (anders geen 1 bij optellen, dan geldt alleen dagdeelprijs) res_ruimte_length := res_1e_dagblok + 1; END IF; thisroomprice := price_morning + (room_price * (res_ruimte_length - res_1e_dagblok)); END IF; END IF; ELSE -- Er is geen 1e blok gedefinieerd. -- Dan maar gewoon uur x prijs. -- Ook hier doet setting room_price_fixed ook gewoon mee. IF room_price_fixed = 1 THEN res_ruimte_length := 1; END IF; thisroomprice := room_price * res_ruimte_length; END IF; ELSIF res_roompricingmethod = 9 THEN -- Kost nooit wat. thisroomprice := 0; END IF; -- -- RETURN ROUND(thisroomprice, 2); END getresruimteprijs; FUNCTION getruimteprijs ( pres_rsv_ruimte_key IN NUMBER , ignoretotaal IN NUMBER DEFAULT NULL ) RETURN NUMBER IS room_price res_ruimte.res_ruimte_prijs%TYPE; afgesprokentotaal res_rsv_ruimte.res_rsv_ruimte_totaal%TYPE; verwijderdatum res_rsv_ruimte.res_rsv_ruimte_verwijder%TYPE; statusfokey res_rsv_ruimte.res_status_fo_key%TYPE; doorbelasting res_disc_params.res_disc_params_kosten%TYPE; res_ruimte_key res_ruimte_opstelling.res_ruimte_key%TYPE; kostenplaats_extern prs_kostenplaats.prs_kostenplaats_extern%TYPE; rsv_ruimte_van res_rsv_ruimte.res_rsv_ruimte_van%TYPE; rsv_ruimte_tot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; thisroomprice NUMBER; BEGIN -- Is de reservering verwijderd SELECT rrr.res_rsv_ruimte_verwijder , rrr.res_status_fo_key , res_rsv_ruimte_totaal INTO verwijderdatum , statusfokey , afgesprokentotaal FROM res_rsv_ruimte rrr WHERE rrr.res_rsv_ruimte_key = pres_rsv_ruimte_key; -- Bepaal doorbelasting IF verwijderdatum IS NULL -- Actuele reservering: 100% kosten doorberekenen. THEN doorbelasting := 100; ELSIF statusfokey = 4 -- Verwijderde reservering en FO status is vervallen: X% kosten doorberekenen THEN -- Hoeveel moet worden doorbelast BEGIN -- Hoeveel van de ruimte kosten doorberekenen SELECT rdp.res_disc_params_kosten INTO doorbelasting FROM res_rsv_ruimte rrr , res_ruimte_opstelling rro , res_ruimte rr , res_disc_params rdp WHERE rrr.res_ruimte_opstel_key = rro.res_ruimte_opstel_key AND rro.res_ruimte_key = rr.res_ruimte_key AND rr.res_discipline_key = rdp.res_ins_discipline_key AND rrr.res_rsv_ruimte_key = pres_rsv_ruimte_key; EXCEPTION WHEN NO_DATA_FOUND THEN -- Geen R-reservering maar een CV-reservering, dan kost de ruimte niks RETURN 0; END; ELSE -- Verwijderde reservering en FO status is niet vervallen: 0% kosten doorberekenen RETURN 0; END IF; IF afgesprokentotaal IS NOT NULL AND ignoretotaal IS NULL THEN return afgesprokentotaal; -- dit is simpel END IF; -- Als Uitgevoerd/verwerkt, dan is de prijs al geregistreerd en bekend BEGIN SELECT res_rsv_ruimte_prijs INTO room_price FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = pres_rsv_ruimte_key AND res_status_bo_key IN (5, 6); RETURN room_price * doorbelasting / 100; EXCEPTION WHEN OTHERS THEN NULL; END; -- Nu zijn er verschillende berekeningsmethoden om de prijs van een gereserveerde ruimte -- te bepalen. Welke methode gehanteerd wordt is bepaald door setting 'res_roompricingmethod'. -- Maar dat laten we over aan de functie getresruimteprijs(). BEGIN SELECT ro.res_ruimte_key , COALESCE(kp.prs_kostenplaats_extern, 0) , rr.res_rsv_ruimte_van , rr.res_rsv_ruimte_tot INTO res_ruimte_key , kostenplaats_extern , rsv_ruimte_van , rsv_ruimte_tot FROM res_rsv_ruimte rr , res_ruimte_opstelling ro , prs_kostenplaats kp WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key AND rr.prs_kostenplaats_key = kp.prs_kostenplaats_key(+) AND rr.res_rsv_ruimte_key = pres_rsv_ruimte_key; thisroomprice := getresruimteprijs ( res_ruimte_key , rsv_ruimte_van , rsv_ruimte_tot , kostenplaats_extern ); EXCEPTION WHEN NO_DATA_FOUND THEN -- Geen R-reservering maar een CV-reservering, dan kost de ruimte niks. Klaar. RETURN 0; END; -- Doorbelastingspercentage (bij annuleren) op het laatste moment nog. -- Voor de berekening van de doorbelasting moet gerekend worden met een op twee decimalen afgeronde ruimteprijs. thisroomprice := ROUND(thisroomprice, 2) * doorbelasting / 100; -- De uiteindelijke ruimteprijs die afgeleverd wordt (return waarde) moet een op twee decimalen afgeronde prijs zijn. Vanwege doorbelasting opnieuw afronden. RETURN ROUND(thisroomprice, 2); END getruimteprijs; FUNCTION getdeelprijs (pres_rsv_deel_key IN NUMBER) RETURN NUMBER IS deel_price res_deel.res_deel_prijs%TYPE; deel_price_fixed res_deel.res_deel_prijs_vast%TYPE; deel_price_total res_rsv_deel.res_rsv_deel_prijs%TYPE; res_deel_length NUMBER; res_deel_begin NUMBER; res_deel_end NUMBER; res_length_morning NUMBER; res_length_afternoon NUMBER; res_length_evening NUMBER; lres_t_middag NUMBER; lres_t_avond NUMBER; verwijderdatum res_rsv_ruimte.res_rsv_ruimte_verwijder%TYPE; BEGIN -- Is de reservering verwijderd SELECT rrr.res_rsv_ruimte_verwijder INTO verwijderdatum FROM res_rsv_ruimte rrr, res_rsv_deel rrd WHERE rrr.res_rsv_ruimte_key = rrd.res_rsv_ruimte_key AND rrd.res_rsv_deel_key = pres_rsv_deel_key; IF verwijderdatum IS NOT NULL -- Reserveerbare objecten worden bij een verwijderde reservering nooit doorbelast. THEN RETURN 0; END IF; -- Actuele reservering: 100% kosten doorberekenen. -- Als Uitgevoerd/verwerkt, dan is de prijs al geregistreerd en bekend BEGIN SELECT res_rsv_deel_prijs INTO deel_price FROM res_rsv_deel WHERE res_rsv_deel_key = pres_rsv_deel_key AND res_status_bo_key IN (5, 6); RETURN deel_price; EXCEPTION WHEN OTHERS THEN NULL; END; SELECT COALESCE (d.res_deel_prijs, 0), d.res_deel_prijs_vast, fac.safe_to_number (TO_CHAR (rd.res_rsv_deel_tot - rd.res_rsv_deel_van)) * 24, fac.safe_to_number (TO_CHAR (rd.res_rsv_deel_van, 'HH24')) + fac.safe_to_number (TO_CHAR (rd.res_rsv_deel_van, 'MI')) / 60, fac.safe_to_number (TO_CHAR (rd.res_rsv_deel_tot, 'HH24')) + fac.safe_to_number (TO_CHAR (rd.res_rsv_deel_tot, 'MI')) / 60 INTO deel_price, deel_price_fixed, res_deel_length, res_deel_begin, res_deel_end FROM res_rsv_deel rd, res_deel d WHERE rd.res_deel_key = d.res_deel_key AND rd.res_rsv_deel_key = pres_rsv_deel_key; IF deel_price_fixed = 1 THEN res_deel_length := 1; ELSE lres_t_middag := fac.safe_to_number (fac.getsetting ('res_t_middag')); lres_t_avond := fac.safe_to_number (fac.getsetting ('res_t_avond')); IF lres_t_middag = -1 AND lres_t_avond = -1 THEN -- real time, price is per hour res_deel_length := res_deel_length; ELSE -- day parts, price is per part res_length_morning := LEAST (res_deel_end, lres_t_middag) - res_deel_begin; res_length_afternoon := LEAST (res_deel_end, lres_t_avond) - GREATEST (res_deel_begin, lres_t_middag); res_length_evening := res_deel_end - GREATEST (res_deel_begin, lres_t_avond); res_deel_length := 0; IF res_length_morning > 0 THEN res_deel_length := res_deel_length + 1; END IF; IF res_length_afternoon > 0 THEN res_deel_length := res_deel_length + 1; END IF; IF res_length_evening > 0 THEN res_deel_length := res_deel_length + 1; END IF; END IF; END IF; -- De uiteindelijke artikelprijs die afgeleverd wordt (return waarde) moet een op twee decimalen afgeronde prijs zijn. -- Afronden op twee decimalen gaat automatisch omdat deel_price_total twee decimalen heeft. deel_price_total := deel_price * res_deel_length; RETURN deel_price_total; END; FUNCTION getartikelprijs (pres_rsv_artikel_key IN NUMBER) RETURN NUMBER IS res_artikel_aantal res_rsv_artikel.res_rsv_artikel_aantal%TYPE; artikel_price_total res_rsv_artikel.res_rsv_artikel_prijs%TYPE; verwijderdatum res_rsv_ruimte.res_rsv_ruimte_verwijder%TYPE; statusfokey res_rsv_ruimte.res_status_fo_key%TYPE; doorbelasting res_disc_params.res_disc_params_kosten%TYPE; BEGIN -- Is de reservering verwijderd SELECT rrr.res_rsv_ruimte_verwijder, rrr.res_status_fo_key INTO verwijderdatum, statusfokey FROM res_rsv_ruimte rrr, res_rsv_artikel rra WHERE rrr.res_rsv_ruimte_key = rra.res_rsv_ruimte_key AND rra.res_rsv_artikel_key = pres_rsv_artikel_key; -- Bepaal doorbelasting IF verwijderdatum IS NULL -- Actuele reservering: 100% kosten doorberekenen. THEN doorbelasting := 100; ELSIF statusfokey = 4 -- Verwijderde reservering en FO status is vervallen: X% kosten doorberekenen THEN -- Hoeveel moet worden doorbelast SELECT res_disc_params_kosten INTO doorbelasting FROM res_rsv_artikel rra, res_artikel ra, res_disc_params rdp WHERE rra.res_artikel_key = ra.res_artikel_key AND ra.res_discipline_key = rdp.res_ins_discipline_key AND res_rsv_artikel_dirtlevel = 0 AND res_rsv_artikel_key = pres_rsv_artikel_key; ELSE -- Verwijderde reservering en FO status is niet vervallen: 0% kosten doorberekenen return 0; END IF; -- Als de prijs al geregistreerd in res_rsv_artikel_prijs dan nemen we die BEGIN SELECT res_rsv_artikel_prijs INTO artikel_price_total FROM res_rsv_artikel ra, res_artikel a WHERE res_rsv_artikel_key = pres_rsv_artikel_key AND ra.res_artikel_key = a.res_artikel_key AND res_rsv_artikel_prijs IS NOT NULL AND (res_status_bo_key >= 5 OR res_artikel_prijs_vast <> 1); -- De uiteindelijke artikelprijs die afgeleverd wordt (return waarde) moet een op twee decimalen afgeronde prijs zijn. Vanwege doorbelasting opnieuw afronden. RETURN ROUND(artikel_price_total * doorbelasting / 100, 2); EXCEPTION WHEN OTHERS THEN NULL; END; -- We hebben een vaste prijs-artikel die nog niet is afgemeld -- Of een vrije prijs artikel die nog niet door de BO is bewerkt -- In beide gevallen moeten we de default prijs uit res_artikel halen SELECT COALESCE (a.res_artikel_prijs, 0) * COALESCE (ra.res_rsv_artikel_aantal, 0) INTO artikel_price_total FROM res_rsv_artikel ra, res_artikel a WHERE ra.res_artikel_key = a.res_artikel_key AND ra.res_rsv_artikel_key = pres_rsv_artikel_key; -- De uiteindelijke artikelprijs die afgeleverd wordt (return waarde) moet een op twee decimalen afgeronde prijs zijn. Vanwege doorbelasting opnieuw afronden. RETURN ROUND(artikel_price_total * doorbelasting / 100, 2); END; -- Bepaal de totaalprijs van een reservering FUNCTION getdeelresprijs (pres_rsv_ruimte_key IN NUMBER) RETURN NUMBER IS ruimteprijs NUMBER := 0; artikelprijs NUMBER := 0; deelprijs NUMBER := 0; korting res_rsv_ruimte.res_rsv_ruimte_korting%TYPE; verwijderdatum res_rsv_ruimte.res_rsv_ruimte_verwijder%TYPE; statusfokey res_rsv_ruimte.res_status_fo_key%TYPE; CURSOR cartikel IS SELECT res_rsv_artikel_key FROM res_rsv_artikel WHERE res_rsv_artikel_dirtlevel = 0 AND res_rsv_ruimte_key = pres_rsv_ruimte_key; CURSOR cdeel IS SELECT res_rsv_deel_key FROM res_rsv_deel WHERE res_rsv_deel_dirtlevel = 0 AND res_rsv_ruimte_key = pres_rsv_ruimte_key; BEGIN -- Is de reservering verwijderd SELECT rrr.res_rsv_ruimte_verwijder, rrr.res_status_fo_key, COALESCE(res_rsv_ruimte_korting, 0) INTO verwijderdatum, statusfokey, korting FROM res_rsv_ruimte rrr WHERE rrr.res_rsv_ruimte_key = pres_rsv_ruimte_key; -- Bepaal doorbelasting korting of afgesproken totaal IF verwijderdatum IS NOT NULL AND statusfokey != 4 -- Verwijderde reservering met FO status die niet is vervallen: 0% korting doorberekenen. THEN korting := 0; -- ELSE -- Actuele reservering of verwijderde reservering met FO status is vervallen: 100% korting doorberekenen END IF; ruimteprijs := res.getruimteprijs(pres_rsv_ruimte_key); FOR ca IN cartikel LOOP artikelprijs := artikelprijs + res.getartikelprijs(ca.res_rsv_artikel_key); END LOOP; FOR cd IN cdeel LOOP deelprijs := deelprijs + res.getdeelprijs(cd.res_rsv_deel_key); END LOOP; RETURN ruimteprijs + artikelprijs + deelprijs - korting; END; FUNCTION sprintf (ps IN VARCHAR2 , pres_rsv_ruimte_key IN NUMBER) RETURN VARCHAR2 IS s VARCHAR2 (2048 CHAR); nr VARCHAR2 (30); omschrijving res_rsv_ruimte.res_rsv_ruimte_omschrijving%TYPE; fiatteur prs_v_perslid_fullnames_all.prs_perslid_naam_full%TYPE; datumvan res_rsv_ruimte.res_rsv_ruimte_van%TYPE; datumtot res_rsv_ruimte.res_rsv_ruimte_tot%TYPE; BEGIN s := ps; -- TODO We support substitution of placeholders in the messages -- ##DESC## = res_rsv_ruimte_omschrijving -- ##KEY## = res_reservering_nr -- ##DATUM## = res_rsv_ruimte_van (DD-MM-YY) -- ##TIJD## = res_rsv_ruimte_van (HH24:MI) -- ##TIJD2## = res_rsv_ruimte_tot (HH24:MI) -- ##FIATTEUR## = budgethouder van de kostenplaats. SELECT TO_CHAR (res_reservering_key) || '/' || TO_CHAR (rr.res_rsv_ruimte_volgnr) , rr.res_rsv_ruimte_omschrijving , prs_perslid_naam_full , res_rsv_ruimte_van , res_rsv_ruimte_tot INTO nr , omschrijving , fiatteur , datumvan , datumtot FROM res_rsv_ruimte rr , prs_kostenplaats k , prs_v_perslid_fullnames_all WHERE rr.prs_kostenplaats_key = k.prs_kostenplaats_key(+) AND k.prs_perslid_key = prs_v_perslid_fullnames_all.prs_perslid_key(+) AND rr.res_rsv_ruimte_key = pres_rsv_ruimte_key; s := REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (s, '##DESC##', omschrijving), '##KEY##', nr), '##FIATTEUR##', fiatteur), '##DATUM##', TO_CHAR(datumvan, 'DD-MM-YY')), '##TIJD##', TO_CHAR(datumvan, 'HH24:MI')), '##TIJD2##', TO_CHAR(datumtot, 'HH24:MI')); s := REPLACE (s, ' ()', ''); RETURN s; END; FUNCTION notifypool (pbez_bezoeker_key IN NUMBER, pcode IN VARCHAR2) RETURN NUMBER IS lnrreceivers NUMBER; lcode fac_srtnotificatie.fac_srtnotificatie_code%TYPE; lreceivers fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; lreceivers1 fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; lbericht fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; lbezoeker bez_bezoekers.bez_afspraak_naam%TYPE; lmailfrom alg_locatie.alg_locatie_email%TYPE; ltracking VARCHAR2(4000); -- moet tijdelijk groter dan fac_srtnotificatie.fac_srtnotificatie_oms%TYPE kunnen zijn s NUMBER; BEGIN s := 0; IF (pcode = 'BEZDO2' OR pcode = 'BEZUNI') THEN SELECT bez_afspraak_naam INTO lbezoeker FROM bez_bezoekers WHERE bez_bezoekers_key = pbez_bezoeker_key; IF pcode = 'BEZDO2' THEN lbericht := lcl.l('lcl_bez_is_in_1') || lbezoeker || lcl.l('lcl_bez_is_in_2'); ELSIF pcode = 'BEZUNI' THEN lbericht := lcl.l('lcl_bez_is_in_1') || lbezoeker || lcl.l('lcl_bez_is_in_3'); --ELSIF pcode = 'BEZOUT' THEN -- lbericht := lcl.l('lcl_bez_is_out_1') || lbezoeker || lcl.l('lcl_bez_is_out_2'); END IF; lcode := 'BEZDO2'; -- Behandel undo_checkin als srtnotificatie checkin. lnrreceivers := 0; lreceivers := ''; SELECT l.alg_locatie_email INTO lmailfrom FROM bez_bezoekers b , bez_afspraak a , alg_locatie l WHERE b.bez_afspraak_key = a.bez_afspraak_key AND a.alg_locatie_key = l.alg_locatie_key AND b.bez_bezoekers_key = pbez_bezoeker_key; FOR hosts IN (SELECT DISTINCT k.res_rsv_ruimte_host_key FROM res_rsv_ruimte k WHERE k.res_reservering_key = ( SELECT r.res_reservering_key FROM bez_afspraak a , bez_bezoekers b , res_rsv_ruimte r , res_reservering v WHERE a.bez_afspraak_key = b.bez_afspraak_key AND a.res_rsv_ruimte_key = r.res_rsv_ruimte_key AND r.res_reservering_key = v.res_reservering_key AND v.res_reservering_ispool = 1 AND b.bez_bezoekers_key = pbez_bezoeker_key ) AND k.res_rsv_ruimte_verwijder IS NULL ) LOOP fac.putnotificationsrtprio (NULL, hosts.res_rsv_ruimte_host_key, lcode, pbez_bezoeker_key, lbericht, NULL, NULL, NULL, NULL, NULL, lmailfrom ); SELECT prs_perslid_naam_friendly INTO lreceivers1 FROM prs_v_perslid_fullnames WHERE prs_perslid_key = hosts.res_rsv_ruimte_host_key; IF lnrreceivers = 0 THEN lreceivers := lreceivers1; ELSE lreceivers := lreceivers||', '||lreceivers1; END IF; lnrreceivers := lnrreceivers+1; s := 1; END LOOP; IF lnrreceivers > 0 THEN DBMS_OUTPUT.PUT_LINE(lnrreceivers); ltracking := lcl.l ('lcl_mld_notification_sent_to'); DBMS_OUTPUT.PUT_LINE(ltracking); ltracking := REPLACE (ltracking, '{0}', lbericht); ltracking := REPLACE (ltracking, '{1}', lreceivers); DBMS_OUTPUT.PUT_LINE(ltracking); fac.trackaction ('#BEZDO2', pbez_bezoeker_key, NULL, NULL, SUBSTR(ltracking,1,2048)); -- maxlengte van fac_srtnotificatie_oms END IF; END IF; RETURN s; END; PROCEDURE notifybackoffice (prsvkey IN NUMBER, pcode IN VARCHAR2, ptype IN VARCHAR2 DEFAULT NULL, pkey IN NUMBER DEFAULT NULL) AS --lloc_key alg_locatie.alg_locatie_key%TYPE; --lroom_key alg_ruimte.alg_ruimte_key%TYPE; --lafd_key prs_perslid.prs_afdeling_key%TYPE; --ldisc_key res_disc_params.res_ins_discipline_key%TYPE; loms2bo fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; l2bomode fac_srtnotificatie.fac_srtnotificatie_mode%TYPE; lsrtnoticode fac_srtnotificatie.fac_srtnotificatie_code%TYPE; lfunctiecode fac_functie.fac_functie_code%TYPE; lnrreceivers NUMBER; bericht fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; -- kan te kort zijn na substitutie lreceivers fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; lreceivers1 fac_srtnotificatie.fac_srtnotificatie_oms%TYPE; ltracking VARCHAR2(4000); -- moet tijdelijk groter dan fac_srtnotificatie.fac_srtnotificatie_oms%TYPE kunnen zijn lref_key NUMBER; lext_key NUMBER; BEGIN BEGIN -- De discipline setting RES_DISC_PARAMS_BONOTIFY geeft aan of de notificatie moeten worden verstuurd. -- RES_DISC_PARAMS_BONOTIFY: 0=niet, 1=bof. -- SELECT lcl.x('fac_srtnotificatie_oms', fac_srtnotificatie_key, fac_srtnotificatie_oms) , fac_srtnotificatie_mode INTO loms2bo , l2bomode FROM fac_srtnotificatie WHERE fac_srtnotificatie_code = 'RES2BO'; -- IF (l2bomode > 0) AND (pcode = 'RESNEW' OR pcode = 'RESUPD') THEN lfunctiecode := 'WEB_RESBOF'; lsrtnoticode := 'RES2BO'; bericht := res.sprintf (loms2bo, prsvkey); -- de variabelen invullen ELSE -- hoeft niets te doen RETURN; END IF; -- lnrreceivers := 0; lreceivers := ''; -- FOR disc IN (SELECT x.alg_locatie_key , x.res_discipline_key , x.prs_afdeling_key , x.alg_ruimte_key , x.res_reservering_key FROM ( SELECT rg.alg_locatie_key -- RES_RUIMTE , rg.res_discipline_key , p.prs_afdeling_key , MIN(ra.alg_ruimte_key) alg_ruimte_key , rr.res_reservering_key FROM res_v_res_ruimte_gegevens rg , res_alg_ruimte ra , res_ruimte_opstelling ro , res_rsv_ruimte rr , prs_perslid p WHERE rg.res_ruimte_key = ro.res_ruimte_key AND rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key AND ra.res_ruimte_key = ro.res_ruimte_key AND rr.res_rsv_ruimte_host_key = p.prs_perslid_key AND TRUNC(rr.res_rsv_ruimte_van) = TRUNC(sysdate) AND ptype IS NULL AND rr.res_status_bo_key = 2 AND rr.res_rsv_ruimte_key = prsvkey GROUP BY rg.alg_locatie_key , rg.res_discipline_key , p.prs_afdeling_key , rr.res_reservering_key UNION SELECT g.alg_locatie_key -- RES_DEEL , d.res_discipline_key , p.prs_afdeling_key , rr.alg_ruimte_key , rr.res_reservering_key FROM res_rsv_ruimte rr , res_rsv_deel rd , res_deel d , ins_deel i , prs_perslid p , alg_v_allonroerendgoed g WHERE i.ins_alg_ruimte_key = g.alg_ruimte_key AND i.ins_alg_ruimte_type = g.alg_type AND i.ins_deel_key = d.res_ins_deel_key AND rd.res_deel_key = d.res_deel_key AND rd.res_rsv_ruimte_key = rr.res_rsv_ruimte_key AND rr.res_rsv_ruimte_host_key = p.prs_perslid_key AND TRUNC(rr.res_rsv_ruimte_van) = TRUNC(sysdate) AND ( ptype IS NULL OR (ptype = 'V' AND d.res_deel_key = pkey) ) AND rd.res_status_bo_key = 2 AND rr.res_rsv_ruimte_key = prsvkey UNION SELECT rg.alg_locatie_key -- RES_ARTIKEL , a.res_discipline_key , p.prs_afdeling_key , rar.alg_ruimte_key , rr.res_reservering_key FROM res_rsv_ruimte rr , res_rsv_artikel ra , res_artikel a , prs_perslid p , res_ruimte_opstelling ro , res_alg_ruimte rar , res_v_res_ruimte_gegevens rg WHERE rr.res_rsv_ruimte_key = ra.res_rsv_ruimte_key AND ra.res_artikel_key = a.res_artikel_key AND rr.res_rsv_ruimte_host_key = p.prs_perslid_key AND rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key(+) AND ro.res_ruimte_key = rar.res_ruimte_key(+) AND ro.res_ruimte_key = rg.res_ruimte_key(+) AND TRUNC(rr.res_rsv_ruimte_van) = TRUNC(sysdate) AND ( ptype IS NULL OR (ptype = 'C' AND a.res_artikel_key = pkey) ) AND ra.res_status_bo_key = 2 AND rr.res_rsv_ruimte_key = prsvkey ) x ) LOOP FOR boer IN (SELECT g.prs_perslid_key FROM fac_v_webgebruiker g , fac_functie f , prs_perslid p , prs_v_afdeling d WHERE g.fac_functie_key = f.fac_functie_key AND g.ins_discipline_key = disc.res_discipline_key AND g.prs_perslid_key = p.prs_perslid_key AND d.prs_afdeling_key = p.prs_afdeling_key AND ( g.fac_gebruiker_prs_level_write = -1 OR ( g.fac_gebruiker_prs_level_write = 0 AND d.prs_bedrijf_key = (SELECT aa.prs_bedrijf_key FROM prs_v_afdeling aa WHERE aa.prs_afdeling_key = disc.prs_afdeling_key ) ) OR ( g.fac_gebruiker_prs_level_write > 0 AND p.prs_afdeling_key IN (SELECT prs_afdeling_key FROM prs_v_afdeling_familie a WHERE a.prs_afdeling_elder_key IN (SELECT aa.prs_afdeling_elder_key FROM prs_v_afdeling_familie aa WHERE aa.prs_afdeling_key = disc.prs_afdeling_key AND aa.niveau = g.fac_gebruiker_prs_level_write ) ) ) ) -- in ASP: if (params.loc_key>0) -- Bij ruimte reservering wordt altijd een ruimte ingevuld die is gekoppeld aan alg_ruimte_key. Dus hier op ruimte niveau checken. AND (g.fac_gebruiker_alg_level_write = -1 OR (g.fac_gebruiker_alg_level_write < 9 AND disc.alg_ruimte_key IN (SELECT alg_ruimte_key FROM fac_v_my_rooms WHERE prs_perslid_key = p.prs_perslid_key AND niveau = fac_gebruiker_alg_level_write ) ) ) AND fac_functie_code = lfunctiecode ) LOOP IF (lsrtnoticode = 'RES2BO') THEN lref_key := disc.res_reservering_key; lext_key := prsvkey; ELSE lref_key := prsvkey; lext_key := NULL; END IF; fac.putnotificationsrtprio (NULL, boer.prs_perslid_key, lsrtnoticode, lref_key, bericht, NULL, NULL, NULL, lext_key, NULL, NULL ); SELECT prs_perslid_naam_friendly INTO lreceivers1 FROM prs_v_perslid_fullnames WHERE prs_perslid_key = boer.prs_perslid_key; -- key van bo-er -- IF lnrreceivers = 0 THEN lreceivers := lreceivers1; ELSE lreceivers := SUBSTR(lreceivers||', '||lreceivers1, 1, 2048); END IF; lnrreceivers := lnrreceivers+1; END LOOP; END LOOP; -- IF lnrreceivers > 0 THEN DBMS_OUTPUT.PUT_LINE(lnrreceivers); ltracking := lcl.l ('lcl_mld_notification_sent_to'); --ltracking := 'Notitificatie ''{0}'' verstuurd aan {1}'; DBMS_OUTPUT.PUT_LINE(ltracking); ltracking := REPLACE (ltracking, '{0}', bericht); ltracking := REPLACE (ltracking, '{1}', lreceivers); DBMS_OUTPUT.PUT_LINE(ltracking); fac.trackaction ('#RES2BO', prsvkey, NULL, NULL, SUBSTR(ltracking,1,2048)); -- maxlengte van fac_srtnotificatie_oms END IF; -- EXCEPTION WHEN NO_DATA_FOUND THEN RETURN; END; END; PROCEDURE remove(p_rsv_ruimte_key IN NUMBER) IS CURSOR c_bijlagen(p_refkey IN NUMBER) IS SELECT fac_bijlagen_key FROM fac_bijlagen b , res_rsv_ruimte r WHERE b.fac_bijlagen_refkey = r.res_rsv_ruimte_key AND b.fac_bijlagen_module = 'RES' AND b.fac_bijlagen_refkey = p_refkey; res_key res_reservering.res_reservering_key%TYPE; BEGIN -- Verwijder afspraken en de bezoekers daarvan bij deelreservering. FOR ref_afspraak IN (SELECT bez_afspraak_key FROM bez_afspraak WHERE res_rsv_ruimte_key = p_rsv_ruimte_key ) LOOP bez.remove(ref_afspraak.bez_afspraak_key); END LOOP; -- Verwijder de deelreservering. fac.remove_tracking('reservering', p_rsv_ruimte_key); fac.remove_tracking('xreservering', p_rsv_ruimte_key); SELECT res_reservering_key INTO res_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = p_rsv_ruimte_key; FOR ref_bijlagen IN c_bijlagen(p_rsv_ruimte_key) LOOP flx.deleteflexbijlage (ref_bijlagen.fac_bijlagen_key); END LOOP; DELETE FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = p_rsv_ruimte_key; -- Van de volgende tabellen worden de records die naar deze res_rsv_ruimte_key -- verwijzen met ON DELETE CASCADE ook verwijderd: -- res_kenmerkwaarde -- res_rsv_artikel -- res_rsv_deel -- In de volgende tabel wordt res_rsv_ruimte_key leeg gemaakt bij het verwijderen van res_rsv_ruimte: -- bez_afspraak -- mld_melding -- Als dit de laatste deelreservering in de reservering is mag de reservering ook weg. DELETE FROM res_reservering WHERE NOT EXISTS (SELECT 1 FROM res_rsv_ruimte WHERE res_reservering_key = res_key ) AND res_reservering_key = res_key; -- Geen tracking op res_reservering. END; PROCEDURE notifyreserveringbedrijven (prsvkey NUMBER, ptrackingkey NUMBER, pnotidelay NUMBER DEFAULT NULL) AS BEGIN FOR bedrijfrec IN (SELECT b.prs_bedrijf_key, l.alg_locatie_key, CASE WHEN b.prs_bedrijf_key = resbedrijf.prs_bedrijf_key THEN 'R' ELSE 'G' END bedrijfadres_type, rrr.res_reservering_key || '/' || rrr.res_rsv_ruimte_volgnr reference FROM prs_bedrijf b, res_rsv_ruimte rrr, alg_locatie l, alg_v_ruimte_gegevens_all ruimte_geg, ( SELECT res_ruimte_opstel_key, rr.res_ruimte_key, MIN (alg_ruimte_key) alg_ruimte_key FROM res_ruimte_opstelling rro, res_alg_ruimte rar, res_ruimte rr WHERE rro.res_ruimte_key = rar.res_ruimte_key AND rr.res_ruimte_key = rar.res_ruimte_key AND rar.res_alg_ruimte_verwijder IS NULL GROUP BY res_ruimte_opstel_key, rr.res_ruimte_key) opstelalg, (SELECT res_rsv_ruimte_key, MAX (rrd.prs_bedrijf_key) prs_bedrijf_key -- artikelen van verschillende leveranciers is unsupported FROM res_disc_params rrd, res_artikel ra, res_rsv_artikel rra WHERE rrd.res_ins_discipline_key = ra.res_discipline_key AND rra.res_artikel_key = ra.res_artikel_key GROUP BY res_rsv_ruimte_key) resbedrijf WHERE rrr.res_rsv_ruimte_key = prsvkey AND resbedrijf.res_rsv_ruimte_key = prsvkey AND rrr.res_ruimte_opstel_key = opstelalg.res_ruimte_opstel_key(+) AND ruimte_geg.alg_ruimte_key = COALESCE (rrr.alg_ruimte_key, opstelalg.alg_ruimte_key) AND ruimte_geg.alg_locatie_key = l.alg_locatie_key AND ( b.prs_bedrijf_key = resbedrijf.prs_bedrijf_key -- type 'R' OR EXISTS (SELECT 1 FROM prs_bedrijfadres ba WHERE ba.prs_bedrijf_key = b.prs_bedrijf_key AND ba.prs_bedrijfadres_startdatum <= SYSDATE AND ba.prs_bedrijfadres_type = 'G'))) LOOP fac.notifybedrijf (pbedrijf_key => bedrijfrec.prs_bedrijf_key, pbedrijfadres_type => bedrijfrec.bedrijfadres_type, prefkey => prsvkey, ptrackingkey => ptrackingkey, preference => bedrijfrec.reference, plocatie_key => bedrijfrec.alg_locatie_key, pnotidelay => pnotidelay); END LOOP; END; END res; / REGISTERRUN('$Id$') #endif // RES