#ifdef RES /* RES_PAC.SRC * * $Revision: 74 $ * $Modtime: 14-03-12 16:23 $ */ CREATE OR REPLACE PACKAGE res AS FUNCTION res_copy_deelres (prsv_ruimte_key IN NUMBER, newdate IN DATE, puserkey NUMBER) 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_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); 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, palg_ruimte_key IN NUMBER) RETURN BOOLEAN; FUNCTION res_artikel_in_scope (pres_artikel_key IN NUMBER, palg_ruimte_key IN NUMBER) RETURN BOOLEAN; FUNCTION getalg_ruimte_key (pres_rsv_ruimte_key IN NUMBER) RETURN NUMBER; FUNCTION getruimteprijs (pres_rsv_ruimte_key IN NUMBER) 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 ; END res; / CREATE OR REPLACE PACKAGE BODY res AS FUNCTION res_copy_deelres (prsv_ruimte_key IN NUMBER, newdate IN DATE, puserkey NUMBER) 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; 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; 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, 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 ) SELECT nextkey, res_reservering_key, nextvolg, res_rsv_ruimte_omschrijving, res_rsv_ruimte_opmerking, alg_ruimte_key, res_ruimte_opstel_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, res_status_fo_key, destatus, res_rsv_ruimte_kosten_klant, res_rsv_ruimte_contact_key, res_rsv_ruimte_bezoekers, res_rsv_ruimte_cvab_mode, res_rsv_ruimte_telefoon 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 + 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-8191) -- 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 -- 4096 Naam -- 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, 8191) = 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 := -- nieuwe datum + orginele tijdstip 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; -- 1..127 zijn directe updates. Ik kijk eerst of ze allemaal moeten, dan doen we dat in 1 keer, -- zo niet, dan kijken we per bitje IF BITAND (flags, 127) = 127 THEN UPDATE res_rsv_ruimte SET res_rsv_ruimte_omschrijving = rsv_from.res_rsv_ruimte_omschrijving, res_rsv_ruimte_opmerking = rsv_from.res_rsv_ruimte_opmerking, res_rsv_ruimte_kosten_klant = rsv_from.res_rsv_ruimte_kosten_klant, res_rsv_ruimte_van = new_ruimte_van, res_rsv_ruimte_tot = new_ruimte_tot, res_ruimte_opstel_key = rsv_from.res_ruimte_opstel_key, alg_ruimte_key = rsv_from.alg_ruimte_key, res_rsv_ruimte_bezoekers = rsv_from.res_rsv_ruimte_bezoekers, res_rsv_ruimte_host_key = rsv_from.res_rsv_ruimte_host_key, 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; ELSE -- 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; -- 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; -- 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; 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 ) 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)) 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; -- en 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 ) SELECT ra.res_artikel_key, ra.res_rsv_artikel_aantal, prsv_ruimte_key_to, ra.res_rsv_artikel_prijs, new_ruimte_van 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; 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 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')); INSERT INTO res_kenmerkwaarde (res_rsv_ruimte_key, res_kenmerk_key, res_kenmerkreservering_waarde ) SELECT prsv_ruimte_key_to, w.res_kenmerk_key, w.res_kenmerkreservering_waarde 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_from AND w.res_kenmerkwaarde_verwijder IS NULL AND sk.res_srtkenmerk_kenmerktype NOT IN ('F', 'M', 'E'); 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; -- Moeten wijzelf misschien dirty worden (door overlap met anderen) -- of schoon worden PROCEDURE set_ruimte_dirty (prsv_ruimte_key IN NUMBER) AS preposttime res_disc_params.res_disc_params_preposttime%TYPE; my_res_ruimte_key res_ruimte.res_ruimte_key%TYPE; n_overlap NUMBER (10); CURSOR prsv_ruimtecur IS SELECT alg_ruimte_key, res_ruimte_opstel_key, res_status_fo_key, res_rsv_ruimte_van, res_rsv_ruimte_tot FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte_key FOR UPDATE OF res_rsv_ruimte_dirtlevel; prsv_ruimte prsv_ruimtecur%ROWTYPE; BEGIN OPEN prsv_ruimtecur; FETCH prsv_ruimtecur INTO prsv_ruimte; IF prsv_ruimte.alg_ruimte_key IS NOT NULL THEN NULL; -- CV reserveringen 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_key INTO preposttime, 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; END IF; -- Oke, hoeveel overlappende alg_ruimte hebben we nu SELECT COUNT (DISTINCT rb.res_ruimte_key) INTO n_overlap FROM res_alg_ruimte rb, -- ikzelf res_v_rsv_ruimte_2_alg_ruimte rr -- de andere WHERE rr.alg_ruimte_key = rb.alg_ruimte_key AND rb.res_ruimte_key = my_res_ruimte_key -- Redundant maar z??r goed voor performance -- VOORKENNIS: Geen meerdaagse reserveringen AND rb.res_alg_ruimte_verwijder IS NULL AND rr.res_rsv_ruimte_van BETWEEN TRUNC (prsv_ruimte.res_rsv_ruimte_van) AND prsv_ruimte.res_rsv_ruimte_tot -- Er is overlap als -- A) de andere ruimte begint voor ons einde -- B) en eindigt na ons begin AND CASE rr.res_status_fo_key WHEN 3 THEN rr.res_rsv_ruimte_van + preposttime ELSE rr.res_rsv_ruimte_van END < prsv_ruimte.res_rsv_ruimte_tot + preposttime AND CASE rr.res_status_fo_key WHEN 3 THEN rr.res_rsv_ruimte_tot - preposttime ELSE rr.res_rsv_ruimte_tot END > prsv_ruimte.res_rsv_ruimte_van - preposttime 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 BEGIN FOR prsv_ruimte IN (SELECT res_rsv_ruimte_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_dirtlevel <> 0 AND res_rsv_ruimte_van BETWEEN TRUNC (checkdate) AND TRUNC (checkdate + 1)) loop set_ruimte_dirty (prsv_ruimte.res_rsv_ruimte_key); -- 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) 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) 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 deze alg_ruimte_key gereserveerd worden FUNCTION res_deel_in_scope (pres_deel_key IN NUMBER, palg_ruimte_key IN NUMBER) RETURN BOOLEAN IS result BOOLEAN; n_inscope INTEGER; BEGIN DBMS_OUTPUT.put_line ('res_deel_in_scope(' || pres_deel_key || ',' || palg_ruimte_key || ')'); 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 = palg_ruimte_key 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_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 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; 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); lres_deel_key res_rsv_deel.res_deel_key%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 res_deel_key, 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, lres_rsv_deel_verwijder INTO lres_deel_key,lrsv_ruimte_key,lrsv_deel_key,lrsv_deel_van,lrsv_deel_tot, lruimtevan,lruimtetot,lres_rsv_deel_verwijder FROM res_rsv_deel d, res_rsv_ruimte r WHERE d.res_rsv_ruimte_key = r.res_rsv_ruimte_key AND res_rsv_deel_key = prsv_deel_key; END; 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 WHERE rad.res_deel_key = lres_deel_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 AND res_rsv_deel_tot > lrsv_deel_van 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 NOT res_deel_in_scope (lres_deel_key, getalg_ruimte_key (lrsv_ruimte_key)) THEN newdirtlevel := newdirtlevel + 256; -- OutOfScope 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 BEGIN 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 AND res_rsv_deel_tot > checkdate_van) 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 deze alg_ruimte_key gereserveerd worden FUNCTION res_artikel_in_scope (pres_artikel_key IN NUMBER, palg_ruimte_key IN NUMBER) RETURN BOOLEAN IS result BOOLEAN; n_inscope INTEGER; BEGIN DBMS_OUTPUT.put_line ('res_artikel_in_scope(' || pres_artikel_key || ',' || palg_ruimte_key || ')'); SELECT COUNT ( * ) INTO n_inscope FROM res_v_alg_ruimte_gegevens rg, res_v_aanwezigartikel a WHERE rg.alg_ruimte_key IS NOT NULL AND res_artikel_key = pres_artikel_key AND rg.alg_ruimte_key = palg_ruimte_key AND (rg.alg_locatie_key IN (SELECT DISTINCT sao.alg_onrgoed_key FROM res_srtartikel_onrgoed sao WHERE a.res_discipline_key = sao.res_discipline_key AND alg_onrgoed_niveau = 'L') OR rg.alg_gebouw_key IN (SELECT DISTINCT sao.alg_onrgoed_key FROM res_srtartikel_onrgoed sao WHERE a.res_discipline_key = sao.res_discipline_key AND alg_onrgoed_niveau = 'G') OR rg.alg_verdieping_key IN (SELECT DISTINCT sao.alg_onrgoed_key FROM res_srtartikel_onrgoed sao WHERE a.res_discipline_key = sao.res_discipline_key AND alg_onrgoed_niveau = 'V') OR rg.alg_ruimte_key IN (SELECT DISTINCT sao.alg_onrgoed_key FROM res_srtartikel_onrgoed sao WHERE a.res_discipline_key = sao.res_discipline_key AND alg_onrgoed_niveau = 'R')); 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_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_artikel_key, getalg_ruimte_key (prsv_artikel.res_rsv_ruimte_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) 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; BEGIN SELECT res_rsv_ruimte_van, res_rsv_ruimte_tot INTO newvan,newtot FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = prsv_ruimte_key; IF oldvan <> newvan OR oldtot <> newtot THEN -- alleen aanpassen indien de tijden zijn veranderd 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); END IF; -- now (re)set the dirty marks FOR prsv_artikel IN prsv_artikelcur loop set_artikel_dirty (prsv_artikel.res_rsv_artikel_key); 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; bezremark bez_afspraak.bez_afspraak_opmerking%TYPE; lremarkfilled BOOLEAN; CURSOR ckenmerk IS SELECT lcl.x('t.res_srtkenmerk_omschrijving', t.res_srtkenmerk_key, t.res_srtkenmerk_omschrijving) kenmerk_omschrijving, v.res_kenmerkreservering_waarde kenmerk_waarde FROM res_srtkenmerk t, res_kenmerk k, res_kenmerkwaarde v WHERE v.res_rsv_ruimte_key = prsv_ruimte_key AND v.res_kenmerk_key = k.res_kenmerk_key AND k.res_kenmerk_verwijder IS NULL AND k.res_srtkenmerk_key = t.res_srtkenmerk_key AND t.res_srtkenmerk_verwijder IS NULL AND t.res_srtkenmerk_kenmerktype NOT IN ('X', 'M', 'F', 'E') ORDER BY k.RES_kenmerk_volgnummer, UPPER(lcl.x('t.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; ruimtekey := getalg_ruimte_key (prsv_ruimte_key); SELECT g.alg_locatie_key INTO locatiekey 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 = ruimtekey; 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 FOR ck IN ckenmerk LOOP IF lremarkfilled THEN bezremark := bezremark || chr(13) || chr(10); -- Carriage Return + Linefeed (CR + LF) toevoegen ELSE lremarkfilled := TRUE; END IF; bezremark := bezremark || ck.kenmerk_omschrijving || ': ' || ck.kenmerk_waarde; 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 = bezremark 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 FROM bez_bezoekers b, res_rsv_deel rd WHERE res_rsv_deel_verwijder IS NULL AND rd.bez_bezoekers_key = b.bez_bezoekers_key AND b.bez_afspraak_key = afspraak_key) LOOP DELETE FROM res_rsv_deel WHERE bez_bezoekers_key = rpark.bez_bezoekers_key; bez.claim_parking(rpark.bez_bezoekers_key, null); -- opnieuw claimen END LOOP; END IF; END; -- Levert de ALG_RUIMTE_KEY uit res_rsv_ruimte CV -- of de ALG_RUIMTE_KEY van de eerste opstelling/ruimte FUNCTION getalg_ruimte_key (pres_rsv_ruimte_key IN NUMBER) RETURN NUMBER IS alg_ruimte_key alg_ruimte.alg_ruimte_key%TYPE; lres_ruimte_opstel_key res_ruimte_opstelling.res_ruimte_opstel_key%TYPE; BEGIN SELECT alg_ruimte_key, res_ruimte_opstel_key INTO alg_ruimte_key, lres_ruimte_opstel_key FROM res_rsv_ruimte WHERE res_rsv_ruimte_key = pres_rsv_ruimte_key; IF alg_ruimte_key IS NULL THEN SELECT MIN (ra.alg_ruimte_key) INTO alg_ruimte_key FROM res_ruimte_opstelling ro, res_alg_ruimte ra WHERE ro.res_ruimte_opstel_key = lres_ruimte_opstel_key AND ro.res_ruimte_key = ra.res_ruimte_key AND ra.res_alg_ruimte_verwijder IS NULL; END IF; RETURN alg_ruimte_key; END; FUNCTION getruimteprijs (pres_rsv_ruimte_key IN NUMBER) RETURN NUMBER IS 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; room_price_total res_rsv_ruimte.res_rsv_ruimte_prijs%TYPE; res_ruimte_length NUMBER; res_ruimte_begin NUMBER; res_ruimte_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; 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 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; -- 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; lres_t_middag := fac.safe_to_number (fac.getsetting ('res_t_middag')); lres_t_avond := fac.safe_to_number (fac.getsetting ('res_t_avond')); BEGIN SELECT COALESCE (ru.res_ruimte_prijs, 0), COALESCE (ru.res_ruimte_prijs_vast, 0), COALESCE (ru.res_ruimte_prijs_ochtend, 0), COALESCE (ru.res_ruimte_prijs_middag, 0), ru.res_ruimte_prijs_avond, fac.safe_to_number (TO_CHAR (rr.res_rsv_ruimte_tot - rr.res_rsv_ruimte_van)) * 24, fac.safe_to_number (TO_CHAR (rr.res_rsv_ruimte_van, 'HH24')) + fac.safe_to_number (TO_CHAR (rr.res_rsv_ruimte_van, 'MI')) / 60, fac.safe_to_number (TO_CHAR (rr.res_rsv_ruimte_tot, 'HH24')) + fac.safe_to_number (TO_CHAR (rr.res_rsv_ruimte_tot, 'MI')) / 60 INTO room_price, room_price_fixed, price_morning, price_afternoon, price_evening, res_ruimte_length, res_ruimte_begin, res_ruimte_end FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_ruimte ru WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key AND ro.res_ruimte_key = ru.res_ruimte_key AND rr.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; IF (lres_t_middag > 0 AND lres_t_middag < 24 AND lres_t_avond > 0 AND lres_t_avond < 24) THEN -- Prijsbepaling per dagdeel? -- 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 room_price_fixed = 1 THEN 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; room_price_total := 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; room_price_total := room_price * res_ruimte_length; END IF; RETURN room_price_total * doorbelasting / 100; END; 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), COALESCE (d.res_deel_prijs_vast, 0), 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; 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 IS NULL); RETURN artikel_price_total * doorbelasting / 100; 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; RETURN artikel_price_total * doorbelasting / 100; 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; 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 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; 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; BEGIN s := ps; -- TODO We support substitution of placeholders in the messages -- ##DESC## = res_rsv_ruimte_omschrijving -- ##KEY## = res_reservering_nr SELECT TO_CHAR (res_reservering_key) || '/' || TO_CHAR (rr.res_rsv_ruimte_volgnr), rr.res_rsv_ruimte_omschrijving INTO nr, omschrijving FROM res_rsv_ruimte rr WHERE rr.res_rsv_ruimte_key = pres_rsv_ruimte_key; s := REPLACE (REPLACE (s, '##DESC##', omschrijving), '##KEY##', nr); s := REPLACE (s, ' ()', ''); RETURN s; END; END res; / REGISTERRUN('$Workfile: RES_PAC.SRC $','$Revision: 74 $') #endif // RES