Files
Database/RES/RES_PAC.SRC
Jos Groot Lipman 7ee8c8218f Merge Branch DB26b fixes
svn path=/Database/trunk/; revision=26715
2015-10-21 09:18:05 +00:00

1664 lines
80 KiB
Plaintext
Raw Blame History

#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) 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_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, pres_rsv_ruimte_key IN NUMBER) RETURN BOOLEAN;
FUNCTION res_artikel_in_scope (pres_artikel_key IN NUMBER, pres_rsv_ruimte_key IN NUMBER) RETURN BOOLEAN;
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 ;
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) 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
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;
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);
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;
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')))
INTO fo_status
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;
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,
COALESCE(newreskey, res_reservering_key),
COALESCE(newvolgnr, 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,
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
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-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 NUMBER(5,4); -- we gaan nog delen door 24, res_disc_params.res_disc_params_preposttime%TYPE is dan te klein;
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;
-- Als *nu* gereserveerd negeren we schoonmaaktijd. Handig voor pda-reserveringen met noshow
IF prsv_ruimte.res_rsv_ruimte_van BETWEEN SYSDATE - 5/60/24 AND SYSDATE + 5/60/24
THEN
preposttime := 0;
END IF;
-- 1 Minuut marge voor afrondfouten
IF preposttime > 1/24/60 THEN
preposttime := preposttime - 1/24/60;
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<><7A>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 + 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
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_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;
BEGIN
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) -- Het kan ook een koppelruimte zijn die uit meerdere ruimten bestaat
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 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;
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_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_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_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
-- 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 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;
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_artikel_key IN NUMBER, pres_rsv_ruimte_key IN NUMBER)
RETURN BOOLEAN IS
result BOOLEAN;
n_inscope INTEGER;
BEGIN
DBMS_OUTPUT.put_line ('res_artikel_in_scope(' || pres_artikel_key || ',' || pres_rsv_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 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) -- Het kan ook een koppelruimte zijn die uit meerdere ruimten bestaat
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 sao.res_srtartikel_og_verwijder IS NULL
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 sao.res_srtartikel_og_verwijder IS NULL
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 sao.res_srtartikel_og_verwijder IS NULL
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 sao.res_srtartikel_og_verwijder IS NULL
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, 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 VARCHAR2(2100); -- bez_afspraak.bez_afspraak_opmerking%TYPE is te kort
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;
-- 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
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 = 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 getruimteprijs (pres_rsv_ruimte_key IN NUMBER, ignoretotaal IN NUMBER DEFAULT NULL)
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;
price_allday res_ruimte.res_ruimte_prijs_dag%TYPE;
room_price_total res_rsv_ruimte.res_rsv_ruimte_prijs%TYPE;
afgesprokentotaal res_rsv_ruimte.res_rsv_ruimte_totaal%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;
res_1e_dagblok NUMBER;
res_2e_dagblok NUMBER;
cost_morning NUMBER;
cost_afternoon NUMBER;
cost_evening 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;
res_roompricingmethod NUMBER;
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'
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 COALESCE (kp.prs_kostenplaats_extern, 0)
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 COALESCE (kp.prs_kostenplaats_extern, 0)
WHEN 0
THEN COALESCE (ru.res_ruimte_intprijs_ochtend, 0) -- Intern
ELSE COALESCE (ru.res_ruimte_prijs_ochtend, 0) -- Extern
END,
CASE COALESCE (kp.prs_kostenplaats_extern, 0)
WHEN 0
THEN COALESCE (ru.res_ruimte_intprijs_middag, 0) -- Intern
ELSE COALESCE (ru.res_ruimte_prijs_middag, 0) -- Extern
END,
CASE COALESCE (kp.prs_kostenplaats_extern, 0)
WHEN 0
THEN COALESCE (ru.res_ruimte_intprijs_avond, 0) -- Intern
ELSE COALESCE (ru.res_ruimte_prijs_avond, 0) -- Extern
END,
CASE COALESCE (kp.prs_kostenplaats_extern, 0)
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 (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,
price_allday,
res_ruimte_length,
res_ruimte_begin,
res_ruimte_end
FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_ruimte ru, prs_kostenplaats kp
WHERE rr.res_ruimte_opstel_key = ro.res_ruimte_opstel_key
AND rr.prs_kostenplaats_key = kp.prs_kostenplaats_key (+) -- of isdie verplicht?
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. 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;
-- 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;
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;
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('$Id$')
#endif // RES