Files
Database/EXC/EXC_PAC.SRC
Koen Reefman fd32faa4a5 FCLT#74162 Punt 5 (Syntaxfoutje)
svn path=/Database/trunk/; revision=57246
2022-09-12 14:29:08 +00:00

1789 lines
82 KiB
Plaintext
Raw Blame History

#ifdef EXC
/*
* $Revision$
* $Id$
*/
CREATE OR REPLACE PACKAGE exc
AS
FUNCTION getOpstelling(p_room_id IN VARCHAR2)
RETURN NUMBER;
FUNCTION getActiviteit(p_room_id IN VARCHAR2)
RETURN NUMBER;
PROCEDURE set_ruimtes_clean(p_import_key IN NUMBER);
PROCEDURE import_exchange(p_import_key IN NUMBER);
PROCEDURE update_exchange(p_import_key IN NUMBER);
PROCEDURE import_exchfull(p_import_key IN NUMBER);
PROCEDURE update_exchfull(p_import_key IN NUMBER);
END exc;
/
CREATE OR REPLACE PACKAGE BODY exc
AS
-- Zoek de default (of anders oudste) opstelling bij de ruimte obv room-id
FUNCTION getOpstelling (p_room_id IN VARCHAR2)
RETURN NUMBER
IS
v_ruimte_opstel_key NUMBER (10);
BEGIN
v_ruimte_opstel_key := NULL;
SELECT COALESCE (ro1.res_ruimte_opstel_key, ro2.res_ruimte_opstel_key) res_ruimte_opstel_key
INTO v_ruimte_opstel_key
FROM res_ruimte r,
(SELECT *
FROM res_ruimte_opstelling
WHERE res_ruimte_opstel_verwijder IS NULL
AND res_ruimte_opstel_default = 1) ro1,
(SELECT *
FROM res_ruimte_opstelling
WHERE res_ruimte_opstel_verwijder IS NULL) ro2
WHERE UPPER(r.res_ruimte_extern_id) = UPPER(p_room_id)
AND r.res_ruimte_verwijder IS NULL
AND COALESCE (r.res_ruimte_vervaldatum, SYSDATE + 1) > SYSDATE
AND ro1.res_ruimte_key(+) = r.res_ruimte_key
AND ro2.res_ruimte_key = r.res_ruimte_key
AND ro2.res_ruimte_opstel_key =
(SELECT MIN (res_ruimte_opstel_key)
FROM res_ruimte_opstelling
WHERE res_ruimte_opstel_verwijder IS NULL
AND res_ruimte_key = r.res_ruimte_key);
RETURN v_ruimte_opstel_key;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN NULL;
END;
-- Zoek de activiteit (met het laagste volgnr | key) bij de ruimte obv room-id
FUNCTION getActiviteit (p_room_id IN VARCHAR2)
RETURN NUMBER
IS
v_activiteit_key NUMBER (10);
BEGIN
v_activiteit_key := NULL;
SELECT res_activiteit_key
INTO v_activiteit_key
FROM ( SELECT ra.res_activiteit_key
FROM res_ruimte rr, res_activiteitdiscipline rad, res_activiteit ra
WHERE UPPER (rr.res_ruimte_extern_id) =
UPPER (p_room_id)
AND rr.res_discipline_key = rad.res_discipline_key
AND rad.res_activiteit_key = ra.res_activiteit_key
ORDER BY res_activiteit_volgnr, res_activiteit_key)
WHERE ROWNUM = 1;
RETURN v_activiteit_key;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN NULL;
END;
-- Welbeschouwd kunnen door de Exchange-constraints ruimte reserveringen nooit overlappen
-- Als er in FACILITOR toch een overlap is ontstaan is dat eigenlijk een gebrek van
-- de synchronisatie procedure
-- Daarom veronderstellen wij dat toch degene die dirty was geworden de waarheid is
-- en de 'andere' dirty had moeten worden of sterker nog: we verwijderen de andere
PROCEDURE set_ruimtes_clean (p_import_key IN NUMBER)
IS
dirtlevel res_rsv_ruimte.res_rsv_ruimte_dirtlevel%TYPE;
v_errorhint VARCHAR2 (1000);
CURSOR c_prsv_ruimte_new IS
SELECT rr.res_rsv_ruimte_key,
r.res_ruimte_key,
res_rsv_ruimte_van,
res_reservering_key,
res_rsv_ruimte_volgnr
FROM res_ruimte r, res_ruimte_opstelling ro, res_rsv_ruimte rr
WHERE ro.res_ruimte_opstel_key = rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND res_rsv_ruimte_dirtlevel = 512 -- alleen ruimteoverlap corrigeren we
AND res_rsv_ruimte_verwijder IS NULL
AND res_ruimte_extern_id IS NOT NULL
AND res_rsv_ruimte_van > TRUNC (SYSDATE)
ORDER BY res_rsv_ruimte_key DESC
FOR UPDATE OF res_rsv_ruimte_dirtlevel;
BEGIN
FOR prsv_ruimte_new IN c_prsv_ruimte_new
LOOP
-- Wij in ieder geval niet meer dirty
v_errorhint :=
'Cleanup reservering '
|| TO_CHAR (prsv_ruimte_new.res_reservering_key)
|| '/'
|| prsv_ruimte_new.res_rsv_ruimte_volgnr
|| ' ('
|| TO_CHAR (prsv_ruimte_new.res_rsv_ruimte_key)
|| ')';
fac.imp_writelog (p_import_key,
'I',
v_errorhint,
'');
UPDATE res_rsv_ruimte
SET res_rsv_ruimte_dirtlevel = 0
WHERE CURRENT OF c_prsv_ruimte_new; -- geen tracking
-- Controleer alle andere reserveringen op die dag in die zaal om te weten welke
-- ons dirty had gemaakt
FOR prsv_ruimte_old
IN (SELECT rr.res_rsv_ruimte_key,
res_rsv_ruimte_van,
res_rsv_ruimte_tot,
res_reservering_key,
res_rsv_ruimte_volgnr
FROM res_ruimte r,
res_ruimte_opstelling ro,
res_rsv_ruimte rr
WHERE r.res_ruimte_key = prsv_ruimte_new.res_ruimte_key
AND rr.res_rsv_ruimte_key <>
prsv_ruimte_new.res_rsv_ruimte_key
AND ro.res_ruimte_opstel_key =
rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND BITAND (res_rsv_ruimte_dirtlevel, 512) = 0
AND res_rsv_ruimte_verwijder IS NULL
AND res_rsv_ruimte_van BETWEEN TRUNC (
prsv_ruimte_new.res_rsv_ruimte_van)
AND TRUNC (
prsv_ruimte_new.res_rsv_ruimte_van)
+ 1)
LOOP
-- Degene die met ons overlapte zal dirty worden nu wij vrij zijn
v_errorhint :=
'Checking reservering '
|| TO_CHAR (prsv_ruimte_old.res_reservering_key)
|| '/'
|| prsv_ruimte_old.res_rsv_ruimte_volgnr
|| ' ('
|| TO_CHAR (prsv_ruimte_old.res_rsv_ruimte_key)
|| ')';
fac.imp_writelog (p_import_key,
'D',
v_errorhint,
'');
res.set_ruimte_dirty (prsv_ruimte_old.res_rsv_ruimte_key); -- deze houdt rekening met schoonmaaak
SELECT res_rsv_ruimte_dirtlevel
INTO dirtlevel
FROM res_rsv_ruimte
WHERE res_rsv_ruimte_key = prsv_ruimte_old.res_rsv_ruimte_key;
IF BITAND (dirtlevel, 512) <> 0
THEN
v_errorhint :=
'Remove dirty reservering '
|| TO_CHAR (prsv_ruimte_old.res_reservering_key)
|| '/'
|| prsv_ruimte_old.res_rsv_ruimte_volgnr
|| ' ('
|| TO_CHAR (prsv_ruimte_old.res_rsv_ruimte_key);
fac.imp_writelog (p_import_key,
'I',
v_errorhint,
'');
UPDATE res_rsv_ruimte
SET res_status_fo_key = 1, -- nooit doorbelasten
res_rsv_ruimte_verwijder = SYSDATE
WHERE res_rsv_ruimte_key =
prsv_ruimte_old.res_rsv_ruimte_key;
fac.trackaction ('RESDEL',
prsv_ruimte_old.res_rsv_ruimte_key,
NULL,
SYSDATE,
NULL);
res.set_ruimtes_clean (prsv_ruimte_old.res_rsv_ruimte_van); -- onwaarschijnlijk
res.follow_artikel (prsv_ruimte_old.res_rsv_ruimte_key,
prsv_ruimte_old.res_rsv_ruimte_van,
prsv_ruimte_old.res_rsv_ruimte_tot);
res.follow_deel (prsv_ruimte_old.res_rsv_ruimte_key,
prsv_ruimte_old.res_rsv_ruimte_van,
prsv_ruimte_old.res_rsv_ruimte_tot);
v_errorhint := 'res_reservering verwijderen';
UPDATE res_reservering
SET res_reservering_verwijder = SYSDATE
WHERE res_reservering_key =
prsv_ruimte_old.res_reservering_key
AND NOT EXISTS
(SELECT *
FROM res_v_aanwezigrsv_ruimte
WHERE res_reservering_key =
prsv_ruimte_old.res_reservering_key);
END IF;
END LOOP;
END LOOP;
END;
-- Met behulp van imp_exchange.gelukt kunnen importregels bewaard worden, zodat mutaties
-- aan appointments die gefaald zijn, alsnog kunnen worden doorgevoerd. Betekenis waarden 'gelukt':
-- NULL = niet correct verwerkt in vorige import --> nogmaals proberen
-- 1 = succesvol verwerkt in vorige import --> importregel verwijderen
-- 2 = er is in een latere import een nieuwere status van dezelfde appointment ingelezen,
-- dus deze importregel is outdated --> regel verwijderen
PROCEDURE import_exchange (p_import_key IN NUMBER)
IS
c_fielddelimitor VARCHAR2 (1) := ';';
c_max_errors NUMBER := 100;
v_newline VARCHAR2 (1000); -- Input line
v_aanduiding VARCHAR2 (200);
v_errorhint VARCHAR2 (1000);
v_errormsg VARCHAR2 (1000);
oracle_err_num NUMBER;
oracle_err_mes VARCHAR2 (200);
header_is_valid NUMBER;
v_ongeldig NUMBER (1);
v_count_tot NUMBER (10);
v_count_error NUMBER (10);
v_count_import NUMBER (10);
v_count NUMBER;
v_import_filenaam fac_import.fac_import_filenaam%TYPE;
v_ruimte_id res_ruimte.res_ruimte_extern_id%TYPE;
-- De importvelden:
v_room_id VARCHAR2 (200);
v_subject VARCHAR2 (200);
v_starttime VARCHAR2 (100);
v_endtime VARCHAR2 (100);
v_organizer VARCHAR2 (200);
v_att_mail VARCHAR2 (200);
v_att_name VARCHAR2 (200);
v_modifier VARCHAR2 (1);
v_appt_id VARCHAR2 (500);
v_recur_id VARCHAR2 (500);
v_seq_nr VARCHAR2 (100);
d_starttime DATE;
d_endtime DATE;
n_seq_nr NUMBER (13);
CURSOR c IS
SELECT *
FROM fac_imp_file
WHERE fac_import_key = p_import_key
ORDER BY fac_imp_file_index;
BEGIN
-- AKZA#36457: de ID van de ruimte is niet meer uit de inhoud van de XML te halen.
-- Dan maar de bestandsnaam gebruiken (refkey is niet handig, want dan moeten we voor
-- elke room de import draaien).
SELECT r.res_ruimte_extern_id, i.fac_import_filenaam
INTO v_ruimte_id, v_import_filenaam
FROM res_ruimte r, fac_import i
WHERE i.fac_import_key = p_import_key
AND r.res_ruimte_verwijder IS NULL
AND r.res_ruimte_extern_id IS NOT NULL
AND UPPER (i.fac_import_filenaam) LIKE
'%' || UPPER (r.res_ruimte_extern_id) || '%';
fac.imp_writelog (p_import_key,
'S',
'Start inlezen importbestand in importtabel',
v_import_filenaam);
-- We willen mislukte regels uit eerdere imports bewaren, zodat we die nog eens kunnen proberen.
-- Alle correct verwerkte importregels krijgen een vlag, dus die gooien we weg.
DELETE FROM exc_import
WHERE gelukt IS NOT NULL;
-- We gaan uit van een geldig bestand, mogelijk verandert dat onderweg
header_is_valid := 0;
v_ongeldig := 0;
v_count_tot := 0;
v_count_error := 0;
v_count_import := 0;
FOR rec IN c
LOOP
BEGIN
v_newline := rec.fac_imp_file_line;
v_aanduiding := '';
d_starttime := NULL;
d_endtime := NULL;
v_errorhint := 'Fout bij opvragen te importeren rij';
-- Lees alle veldwaarden
-- AKZA#36457: room ID wordt voortaan opgehaald uit de bestandsnaam van de import
v_room_id := v_ruimte_id;
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 1, v_subject);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 2, v_starttime);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 3, v_endtime);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 4, v_organizer);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 5, v_att_mail);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 6, v_att_name);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 7, v_modifier);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 8, v_appt_id);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 9, v_recur_id);
fac.imp_getfield_nr (v_newline, c_fielddelimitor, 10, v_seq_nr);
v_aanduiding := '[' || v_room_id || '|' || v_starttime || '|' || v_att_mail || '] ';
-- Ik controleer of ik een geldige header heb, dat is: in de juiste kolommen
-- de juiste kolomkop. Ik controleer daarbij ALLE kolommen!
-- Ik negeer alles totdat ik een geldige header ben gepasseerd.
-- NB: doordat deze import een stylesheet gebruikt, zullen deze kolommen altijd kloppen,
-- ook al wordt een verkeerd bestand ingelezen (mits de stylesheet klopt)
IF (header_is_valid = 0)
THEN
IF UPPER (v_subject) = 'SUBJECT'
AND UPPER (v_starttime) = 'STARTTIME'
THEN
header_is_valid := 1;
END IF;
ELSE
-- Bij volgende importbestanden headerregels overslaan
IF UPPER (v_subject) = 'SUBJECT'
AND UPPER (v_starttime) = 'STARTTIME'
THEN
CONTINUE;
END IF;
v_count_tot := v_count_tot + 1;
-- Controleer tijden (delete's hebben geen tijden)
IF v_modifier <> 'D'
THEN
v_errorhint := 'Ongeldige starttijd';
v_starttime := TRIM (v_starttime);
IF (fac.safe_to_date (v_starttime,
'YYYY-MM-DD"T"HH24:MI:SS"Z"')
IS NOT NULL)
THEN
d_starttime :=
CAST (
(FROM_TZ (
CAST (
fac.safe_to_date (
v_starttime,
'YYYY-MM-DD"T"HH24:MI:SS"Z"')
AS TIMESTAMP),
'+00:00')
AT TIME ZONE 'Europe/Amsterdam') AS DATE);
ELSE
v_ongeldig := 1;
v_count_error := v_count_error + 1;
fac.imp_writelog (p_import_key,
'W',
v_aanduiding || 'Starttijd ontbreekt',
'');
END IF;
v_errorhint := 'Ongeldige eindtijd';
v_endtime := TRIM (v_endtime);
IF (fac.safe_to_date (v_endtime,
'YYYY-MM-DD"T"HH24:MI:SS"Z"')
IS NOT NULL)
THEN
d_endtime :=
CAST (
(FROM_TZ (
CAST (
fac.safe_to_date (
v_endtime,
'YYYY-MM-DD"T"HH24:MI:SS"Z"')
AS TIMESTAMP),
'+00:00')
AT TIME ZONE 'Europe/Amsterdam') AS DATE);
ELSE
v_ongeldig := 1;
v_count_error := v_count_error + 1;
fac.imp_writelog (p_import_key,
'W',
v_aanduiding || 'Eindtijd ontbreekt',
'');
END IF;
END IF;
v_errorhint := 'Opschonen naam bezoeker';
v_att_name := TRIM (BOTH '''' FROM v_att_name);
v_errorhint := 'Ongeldig sequence nr';
v_seq_nr := TRIM (v_seq_nr);
IF (fac.safe_to_number (v_seq_nr) IS NOT NULL)
THEN
n_seq_nr := fac.safe_to_number (v_seq_nr);
ELSE
v_ongeldig := 1;
v_count_error := v_count_error + 1;
fac.imp_writelog (
p_import_key,
'W',
v_aanduiding || 'Sequence nr ontbreekt',
'');
END IF;
-- Insert geformatteerde import record,
-- mits het een toekomstige appointment betreft
IF (v_ongeldig = 0 AND (v_modifier = 'D' OR d_starttime > SYSDATE))
THEN
BEGIN
v_errorhint := 'Fout bij toevoegen regel aan importtabel';
INSERT INTO exc_import (room_id,
subject,
starttime,
endtime,
organizer,
att_mail,
att_name,
modifier,
appt_id,
recur_id,
seq_nr,
fac_import_key)
VALUES (v_room_id,
v_subject,
d_starttime,
d_endtime,
v_organizer,
v_att_mail,
v_att_name,
v_modifier,
v_appt_id,
v_recur_id,
n_seq_nr,
p_import_key);
v_count_import := v_count_import + 1;
EXCEPTION
WHEN OTHERS
THEN
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
v_errorhint
|| ': ORACLE (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
v_ongeldig := 1;
fac.imp_writelog (
p_import_key,
'E',
v_aanduiding || v_errormsg,
'Ingelezen regel kan niet worden weggeschreven!');
COMMIT;
END;
END IF;
END IF;
END;
END LOOP;
IF (header_is_valid = 0)
THEN
fac.imp_writelog (
p_import_key,
'E',
'Ongeldig importbestand! Geen header of header niet volgens specificatie.',
'Heeft u wel het juiste bestand ingelezen?');
ELSIF (v_ongeldig = 1)
THEN
fac.imp_writelog (
p_import_key,
'E',
'Ongeldig importbestand! Bestand bevat een of meer ongeldige regels.',
'');
ELSE
fac.imp_writelog (
p_import_key,
'S',
'Importbestand succesvol ingelezen: '
|| TO_CHAR (v_count_import)
|| ' regels',
'');
END IF;
COMMIT;
-- import_exchange() wordt voor elk importbestand aangeroepen. Dat gebeurt steeds met dezelfde
-- fac_import_key, dus er kan achteraf niet bepaald worden welke importregels bij welk bestand (en
-- dus welke ruimte horen. Daarom fac_imp_file handmatig legen, zodat we bij het volgende bestand
-- met een schone lei beginnen.
DELETE FROM fac_imp_file
WHERE fac_import_key = p_import_key;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
'OTHERS (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
fac.imp_writelog (p_import_key,
'E',
v_aanduiding || v_errormsg,
v_errorhint);
-- AKZA#38120: ook als er iets mis gaat bij inlezen (bijvoorbeeld de extern_id bestaat niet, of
-- komt vaker voor) de importregels weggooien, anders worden ze bij de volgende ruimte ingelezen.
-- Liever niets inlezen (totdat de situatie verholpen is), dan fout inlezen.
DELETE FROM fac_imp_file
WHERE fac_import_key = p_import_key;
COMMIT;
END import_exchange;
PROCEDURE update_exchange (p_import_key IN NUMBER)
IS
v_aanduiding VARCHAR2 (200);
v_errorhint VARCHAR2 (1000);
v_errormsg VARCHAR2 (1000);
oracle_err_num NUMBER;
oracle_err_mes VARCHAR2 (200);
v_count_tot NUMBER (10);
v_count_error NUMBER (10);
v_count NUMBER (10);
v_ruimte_extern_id res_ruimte.res_ruimte_extern_id%TYPE;
v_count_wanted NUMBER (10);
v_count_all_booked NUMBER (10);
v_count_all_needed NUMBER (10);
v_ongeldig NUMBER (1);
v_debug BOOLEAN := TRUE;
sync_level fac_setting.fac_setting_pvalue%TYPE;
c_activiteit_key NUMBER (10);
v_reservering_key NUMBER (10);
v_rsv_ruimte_volgnr res_rsv_ruimte.res_rsv_ruimte_volgnr%TYPE;
v_ruimte_opstel_key NUMBER (10);
v_rsv_ruimte_key NUMBER (10);
v_perslid_key NUMBER (10);
v_kostenplaats_key NUMBER (10);
v_status_fo_key NUMBER (10);
v_discipline_key NUMBER (10);
v_code VARCHAR2 (7);
-- ANNULEREN
-- Eerst alle toekomstige reserveringen waar geen appointments meer bij zijn annuleren, zodat
-- ruimte ontstaat voor nieuwe/omgeboekte reserveringen.
-- Triggers voor het annuleren van een deelreservering:
-- - DELETE-modifier in synchro; appointment is verwijderd
-- - UPDATE-modifier in synchro, met bekend appointment-ID, maar zonder resource: de appointment
-- bestaat nog, maar is niet meer in een bekende zaal (TODO: krijgen we die dan als UPD, of als DEL?)
-- - UPDATE-modifier in synchro, met bekend appointment-ID, maar voorheen zonder recurrence-ID (= single)
-- en nu met recurrence-ID (= occurence). Die single verwijderen, daarna de occurences toevoegen.
-- NB: checken of in deze synchro een appointment niet zowel toegevoegd/bijgewerkt als verwijderd is;
-- dan hoeven we 'm natuurlijk niet meer toe te voegen / bij te werken.
-- (TODO: weet niet of dat <20>berhaupt voorkomt met EWS)
-- TODO: notificeren
CURSOR c_del IS
SELECT 'Cancelled' reden, i.*, rr.*
FROM (SELECT DISTINCT room_id,
subject,
starttime,
endtime,
organizer,
modifier,
appt_id,
recur_id
FROM exc_import
WHERE modifier = 'D'
AND gelukt IS NULL) i,
res_rsv_ruimte rr
WHERE rr.res_rsv_ruimte_externnr IS NOT NULL
AND rr.res_rsv_ruimte_externnr LIKE
i.appt_id || '|' || i.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL
UNION ALL
SELECT 'Unknown room' reden, i.*, rr.*
FROM (SELECT DISTINCT room_id,
subject,
starttime,
endtime,
organizer,
modifier,
appt_id,
recur_id
FROM exc_import
WHERE modifier = 'U'
AND starttime > SYSDATE
AND gelukt IS NULL) i,
res_rsv_ruimte rr
WHERE rr.res_rsv_ruimte_externnr LIKE
i.appt_id || '|' || i.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL
AND NOT EXISTS
(SELECT 1
FROM res_ruimte
WHERE res_ruimte_extern_id = i.room_id
AND res_ruimte_verwijder IS NULL)
UNION ALL
-- AKZA#35459: appointments die eerst single waren en nu recurring (eerst geen
-- recur_id, nu wel). Daar kan vanalles mee gebeurd zijn (andere ruimte, ander tijdstip,
-- meerdere ruimtes). Dan maar verwijderen en opnieuw aanmaken...
-- (recur_id en tijden niet ophalen, anders wordt de 'oude' single voor elke recurrence verwijderd)
SELECT 'Made recurring' reden, i.*, rr.*
FROM (SELECT DISTINCT room_id,
subject,
NULL starttime,
NULL endtime,
organizer,
modifier,
appt_id,
NULL recur_id
FROM exc_import
WHERE modifier = 'U'
AND starttime > SYSDATE
AND recur_id IS NOT NULL
AND gelukt IS NULL) i,
res_rsv_ruimte rr
WHERE rr.res_rsv_ruimte_externnr LIKE i.appt_id || '||%'
AND rr.res_rsv_ruimte_verwijder IS NULL;
-- TODO: Voor later: res_cat_t1 en res_t1 gebruiken ipv TRUNC
CURSOR c_del_doorbelast (p_rsv_ruimte_key IN NUMBER)
IS
SELECT soort,
ref_key,
oms,
van,
fac.safe_to_number (SYSDATE - TRUNC (SYSDATE)) * 24
uren,
DECODE (
exp_tijd,
NULL, van - exp_dagen,
DECODE (
SIGN (
exp_tijd
- fac.safe_to_number (SYSDATE - TRUNC (SYSDATE))
* 24),
1, TRUNC (van),
TRUNC (van) + 1))
t_expire,
exp_dagen,
exp_tijd,
cnl_dagen
FROM (SELECT 'ruimte' soort,
rr.res_rsv_ruimte_key ref_key,
r.res_ruimte_nr oms,
rr.res_rsv_ruimte_van van,
dp.res_disc_params_kosten kosten,
dp.res_disc_params_expire_dagen exp_dagen,
dp.res_disc_params_expire_tijd exp_tijd,
dp.res_disc_params_cancel_dagen cnl_dagen
FROM res_rsv_ruimte rr,
res_ruimte_opstelling ro,
res_ruimte r,
res_discipline d,
res_disc_params dp
WHERE rr.res_rsv_ruimte_key = p_rsv_ruimte_key
AND ro.res_ruimte_opstel_key =
rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND d.ins_discipline_key = r.res_discipline_key
AND dp.res_ins_discipline_key = d.ins_discipline_key
AND dp.res_disc_params_kosten > 0
UNION ALL
SELECT 'artikel' soort,
ra.res_rsv_artikel_key,
a.res_artikel_omschrijving,
ra.res_rsv_artikel_levering,
dp.res_disc_params_kosten,
dp.res_disc_params_expire_dagen,
dp.res_disc_params_expire_tijd,
dp.res_disc_params_cancel_dagen
FROM res_rsv_artikel ra,
res_artikel a,
res_discipline d,
res_disc_params dp
WHERE ra.res_rsv_ruimte_key = p_rsv_ruimte_key
AND a.res_artikel_key = ra.res_artikel_key
AND d.ins_discipline_key = a.res_discipline_key
AND dp.res_ins_discipline_key = d.ins_discipline_key
AND dp.res_disc_params_kosten > 0
UNION ALL
SELECT 'deel' soort,
rd.res_rsv_deel_key,
de.res_deel_omschrijving,
rd.res_rsv_deel_van,
dp.res_disc_params_kosten,
dp.res_disc_params_expire_dagen,
dp.res_disc_params_expire_tijd,
dp.res_disc_params_cancel_dagen
FROM res_rsv_deel rd,
res_deel de,
res_discipline d,
res_disc_params dp
WHERE rd.res_rsv_ruimte_key = p_rsv_ruimte_key
AND de.res_deel_key = rd.res_deel_key
AND d.ins_discipline_key = de.res_discipline_key
AND dp.res_ins_discipline_key = d.ins_discipline_key
AND dp.res_disc_params_kosten > 0);
-- BIJWERKEN
-- Triggers voor het bijwerken van een bestaande toekomstige deelreservering:
-- - UPDATE-modifier in synchro, met bekend appointment-ID en bekende resource(s) (zonder bekende resource
-- krijgen we 'm niet eens binnen)
-- TODO: combi van appt_id, recur_id en room_id!
-- Dan checken of het nog wel om dezelfde resources (ruimtes) gaat, tijden zijn aangepast, deelnemers gewijzigd,
-- andere omschrijving, ...
-- - Omschrijving kan zonder notificatie aangepast worden
-- - Andere ruimte --> Moet er worden doorbelast? Voorwaarden voor catering hetzelfde (van MC naar OF bijv)?
-- TODO: notificeren
-- - Deelnemers erbij / eraf --> Bezoekers toevoegen / verwijderen, deelnemerslijst bijwerken.
-- TODO: notificeren
-- NB: checken of in deze synchro een appointment niet zowel bijgewerkt als verwijderd is;
-- dan hoeven we 'm natuurlijk niet meer bij te werken (weet niet of dat <20>berhaupt voorkomt met EWS)
-- TODO: dit detecteert geen room changes, alleen mutaties aan res op dezelfde ruimte.
CURSOR c_upd IS
SELECT i.*,
rr.*,
rnew.res_ruimte_key,
rnew.res_ruimte_nr,
rnew.res_ruimte_extern_id,
rnew.res_discipline_key
FROM ( SELECT room_id,
subject,
starttime,
endtime,
organizer,
modifier,
appt_id,
recur_id,
COUNT (*) num_bez
FROM exc_import
WHERE modifier = 'U'
AND starttime > SYSDATE
AND gelukt IS NULL
AND NOT EXISTS
(SELECT 1
FROM res_ruimte
WHERE UPPER (res_ruimte_extern_id) =
UPPER (att_mail))
GROUP BY recur_id,
appt_id,
room_id,
subject,
starttime,
endtime,
organizer,
modifier) i,
res_rsv_ruimte rr,
res_ruimte rnew
WHERE rr.res_rsv_ruimte_externnr LIKE
i.appt_id || '|' || i.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL
AND rnew.res_ruimte_extern_id = i.room_id
AND rnew.res_ruimte_verwijder IS NULL;
-- TOEVOEGEN
-- Triggers voor het toevoegen van een toekomstige (deel)reservering:
-- - ADD-modifier in synchro; appointment is nieuw
-- - UPDATE-modifier in synchro, met onbekend appointment- en recurrence-ID voor deze room: dan (<28>f)
-- - appointment bestond al, maar er is nu pas een ruimte aan toegevoegd;
-- - het was een single en nu recurring.
-- - appointment met meerdere ruimtes, maar nog geen deelreservering voor deze ruimte (zal vooral
-- voorkomen bij calendarview, als we de boekingen voor alle ruimtes op dit tijdstip binnenkrijgen --
-- bij de synchro-import is dat niet gegarandeerd)
-- TODO: verwijderde deelreserveringen 'undeleten'?
CURSOR c_add IS
SELECT i.*, r.*
FROM ( SELECT room_id,
subject,
starttime,
endtime,
organizer,
modifier,
appt_id,
recur_id,
seq_nr,
COUNT (*) num_bez
FROM exc_import
WHERE modifier = 'C'
AND starttime > SYSDATE
AND gelukt IS NULL
AND NOT EXISTS
(SELECT 1
FROM res_ruimte
WHERE UPPER (res_ruimte_extern_id) =
UPPER (att_mail))
GROUP BY recur_id,
appt_id,
seq_nr,
room_id,
subject,
starttime,
endtime,
organizer,
modifier) i,
res_v_aanwezigruimte r
WHERE i.room_id = r.res_ruimte_extern_id
UNION ALL
SELECT i.*, r.*
FROM ( SELECT room_id,
subject,
starttime,
endtime,
organizer,
modifier,
appt_id,
recur_id,
seq_nr,
COUNT (*) num_bez
FROM exc_import
WHERE modifier = 'U'
AND starttime > SYSDATE
AND gelukt IS NULL
AND NOT EXISTS
(SELECT 1
FROM res_ruimte
WHERE UPPER (res_ruimte_extern_id) =
UPPER (att_mail))
GROUP BY recur_id,
appt_id,
seq_nr,
room_id,
subject,
starttime,
endtime,
organizer,
modifier) i,
res_v_aanwezigruimte r
WHERE i.room_id = r.res_ruimte_extern_id
AND NOT EXISTS
(SELECT 1
FROM res_rsv_ruimte rr,
res_ruimte_opstelling ro,
res_ruimte r
WHERE rr.res_rsv_ruimte_externnr IS NOT NULL
AND rr.res_rsv_ruimte_externnr LIKE
i.appt_id || '|' || i.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL
AND ro.res_ruimte_opstel_key =
rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND r.res_ruimte_verwijder IS NULL
AND r.res_ruimte_extern_id = i.room_id);
BEGIN
SELECT BITAND (COALESCE (fac_setting_pvalue, fac_setting_default), 4)
INTO sync_level
FROM fac_setting
WHERE fac_setting_name = 'msgraph_sync_level';
-- We doen niets met boekingen in het verleden
UPDATE exc_import i
SET gelukt = 4
WHERE endtime < SYSDATE;
-- En res_ruimtes als deelnemers, dat kan natuurlijk niet
UPDATE exc_import i
SET gelukt = 5
WHERE EXISTS
(SELECT 1
FROM res_ruimte
WHERE UPPER (res_ruimte_extern_id) = UPPER (att_mail));
-- Eerst verwijderen; dat scheelt onterechte "dirties" bij toevoegen
-- Bij verplaatsen naar een andere ruimte krijg je mogelijk een delete op de oude
-- ruimte; die voeren we niet uit. Ook deletes van niet-bekende appointments negeren we.
UPDATE exc_import i
SET gelukt = 3
WHERE modifier IN ('D')
AND EXISTS
(SELECT 1
FROM exc_import
WHERE modifier != 'D'
AND appt_id || '|' || recur_id =
i.appt_id || '|' || i.recur_id
AND seq_nr > i.seq_nr);
UPDATE exc_import i
SET gelukt = 3
WHERE modifier IN ('D')
AND NOT EXISTS
(SELECT 1
FROM res_rsv_ruimte
WHERE res_rsv_ruimte_externnr LIKE i.appt_id || '|%');
FOR rec IN c_del
LOOP
BEGIN
v_aanduiding :=
rec.res_reservering_key
|| '/'
|| rec.res_rsv_ruimte_volgnr
|| ' ('
|| rec.res_rsv_ruimte_key
|| '|'
|| rec.room_id
|| '|'
|| rec.subject
|| ')';
v_perslid_key := NULL;
v_kostenplaats_key := NULL;
v_rsv_ruimte_key := NULL;
v_status_fo_key := 1;
v_count := 0;
-- Zie ook res_delete_save.asp
IF (v_debug)
THEN
fac.imp_writelog (p_import_key,
'D',
v_aanduiding,
'VERWIJDEREN ' || v_aanduiding);
END IF;
v_errorhint := 'Doorbelasting kosten';
-- Moeten kosten worden doorbelast?
-- (I.e. zitten we binnen de expiretijd van een van de onderdelen?)
FOR rec_db IN c_del_doorbelast (rec.res_rsv_ruimte_key)
LOOP
v_count := v_count + 1;
END LOOP;
-- Minstens <20><>n onderdeel moet worden doorbelast
-- FO-status van rsv_ruimte wordt "Vervallen" (4)
IF (v_count > 0)
THEN
v_status_fo_key := 4;
FOR rec_db IN c_del_doorbelast (rec.res_rsv_ruimte_key)
LOOP
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
rec_db.oms
|| ' kosteloos annuleerbaar tot '
|| TO_CHAR (rec_db.t_expire,
'DD-MM-YYYY HH24:MI'));
END IF;
END LOOP;
END IF;
v_errorhint := 'Deelreservering verwijderen';
UPDATE res_rsv_ruimte
SET res_status_fo_key = v_status_fo_key,
res_rsv_ruimte_verwijder = SYSDATE
WHERE res_rsv_ruimte_key = rec.res_rsv_ruimte_key;
fac.trackaction ('RESDEL',
rec.res_rsv_ruimte_key,
NULL,
SYSDATE,
NULL);
res.set_ruimte_dirty (rec.res_rsv_ruimte_key);
res.set_ruimtes_clean (rec.res_rsv_ruimte_van);
res.follow_artikel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
res.follow_deel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
v_errorhint := 'res_reservering verwijderen';
UPDATE res_reservering
SET res_reservering_verwijder = SYSDATE
WHERE res_reservering_key = rec.res_reservering_key
AND NOT EXISTS
(SELECT *
FROM res_v_aanwezigrsv_ruimte
WHERE res_reservering_key =
rec.res_reservering_key);
-- Succesvol afgerond; zet vlag.
-- AKZA#35459: vlag niet zetten voor een single die recurring is geworden;
-- die recurrence moeten we straks in de add-cursor nog toevoegen.
IF NOT (rec.reden = 'Made recurring')
THEN
UPDATE exc_import
SET gelukt = 1
WHERE appt_id || '|' || recur_id =
rec.appt_id || '|' || rec.recur_id
AND gelukt IS NULL;
END IF;
fac.imp_writelog (p_import_key,
'I',
v_aanduiding,
'Deelreservering verwijderd.');
EXCEPTION
WHEN OTHERS
THEN
v_count_error := v_count_error + 1;
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
'OTHERS (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
v_errorhint || ': ' || v_errormsg);
END;
END LOOP;
COMMIT;
-- Omdat we entries die gefaald zijn 'bewaren', kan het zijn dat we voor <20><>n appointment
-- meerdere updates - of zelfs een delete - hebben. Dan zijn we alleen ge<67>nteresseerd in de
-- nieuwste, de rest kan genegeerd/weg. (Als we een nieuwere UPDate hebben, kan de originele
-- ADD/create ook weg; een update van een nog-niet-bestaande reservering zorgt voor aanmaken.)
-- Hoger seq_nr = latere mutatie in Exchange
UPDATE exc_import i
SET gelukt = 2
WHERE modifier IN ('C', 'U')
AND EXISTS
(SELECT 1
FROM exc_import
WHERE appt_id || '|' || recur_id =
i.appt_id || '|' || i.recur_id
AND fac_import_key != i.fac_import_key
AND seq_nr > i.seq_nr);
-- Hetzelfde voor deletes van niet-bestaande reserveringen
UPDATE exc_import i
SET gelukt = 2
WHERE modifier = 'D'
AND NOT EXISTS
(SELECT 1
FROM res_rsv_ruimte
WHERE res_rsv_ruimte_externnr LIKE
i.appt_id || '|' || i.recur_id || '|%');
-- Dan bestaande bijwerken, anders kan het gebeuren dat we op basis van een UPDATE
-- eerst een rsv_ruimte aanmaken en 'm daarna meteen proberen bij te werken.
-- TODO: is dat nog steeds zo met "gelukt = 1"?
FOR rec IN c_upd
LOOP
BEGIN
v_aanduiding :=
rec.room_id
|| '|'
|| rec.subject
|| '|'
|| TO_CHAR (rec.starttime, 'DD-MM-YYYY HH24:MI')
|| '-->'
|| rec.res_reservering_key
|| '/'
|| rec.res_rsv_ruimte_volgnr;
v_perslid_key := NULL;
v_kostenplaats_key := NULL;
v_rsv_ruimte_volgnr := 1;
v_rsv_ruimte_key := NULL;
v_count := NULL;
v_count_all_booked := NULL;
v_count_all_needed := NULL;
v_count_wanted := NULL;
v_ruimte_extern_id := NULL;
-- Bepalen of dit een single-room of multi-room boeking is, door te achterhalen hoeveel ruimtes er in
-- FACILITOR geboekt (count_all_booked) zijn en hoeveel we er uit EWS hebben binnengekregen (count_all_needed).
-- Als count_all_booked > 1 en/of count_all_needed > 1, dan betreft het een appointment met meerdere
-- rooms en dus meerdere rsv_ruimtes. Dan moeten we nog meer weten.
-- Als count_all_booked = 1 <20>n count_all_needed = 1, dan betreft het een single-room boeking en kunnen we
-- r<>cksichtslos bijwerken.
-- (Dat is niet correct als er een room aan een bestaande appointment is toegevoegd, waar we nu nog
-- maar <20><>n room van hebben. Maar de sync-functionaliteit van EWS biedt geen manier om die situatie te
-- achterhalen... Met de calendar view kan dit wel, omdat we dan alle gelijktijdige boekingen op de
-- verschillende ruimtes binnenkrijgen, daarom:)
-- Als we een full import doen (calendar view), kan het maar zo zijn dat we in de import meerdere
-- ruimtes in dezelfde appointment tegenkomen (count_all_needed > 1), terwijl we daar nu nog maar <20><>n
-- ruimte van kennen (count_all_booked = 1). Dan is het dus een multi-room boeking, die nog niets alszodanig
-- bekend stond.
v_errorhint := 'Totaal aantal geboekte zalen bepalen';
SELECT COUNT (*)
INTO v_count_all_booked
FROM res_rsv_ruimte rr
WHERE rr.res_rsv_ruimte_externnr LIKE
rec.appt_id || '|' || rec.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL;
v_errorhint := 'Totaal aantal benodigde zalen bepalen';
SELECT COUNT (DISTINCT room_id)
INTO v_count_all_needed
FROM exc_import i
WHERE i.modifier IN ('U', 'C')
AND i.starttime > SYSDATE
AND i.appt_id || '|' || i.recur_id || '|' LIKE
rec.appt_id || '|' || rec.recur_id || '|';
-- De cursor bevat voor iedere appointment alle rsv_ruimtes met dezelfde appt_id en recur_id.
-- Er zal hoogstens <20><>n rsv_ruimte op de betreffende room zijn.
-- Bestaat er al een rsv_ruimte voor deze room (count = 1)?
v_errorhint := 'Bepalen of zaal al geboekt is';
SELECT COUNT (*)
INTO v_count
FROM res_rsv_ruimte rr,
res_ruimte_opstelling rops,
res_ruimte r
WHERE rr.res_rsv_ruimte_externnr LIKE
rec.appt_id || '|' || rec.recur_id || '|%'
AND rr.res_rsv_ruimte_verwijder IS NULL
AND rops.res_ruimte_opstel_key = rr.res_ruimte_opstel_key
AND r.res_ruimte_key = rops.res_ruimte_key
AND r.res_ruimte_extern_id = rec.room_id;
-- Als er al een rsv_ruimte voor deze room is, is dat dan degene die we nu in de cursor hebben?
-- Zo ja, dan willen we die bijwerken.
-- Zo nee, dan doen we niets
v_errorhint := 'Bepalen zaal huidige deelreservering';
SELECT r.res_ruimte_extern_id
INTO v_ruimte_extern_id
FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_ruimte r
WHERE rr.res_rsv_ruimte_key = rec.res_rsv_ruimte_key
AND ro.res_ruimte_opstel_key = rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND r.res_ruimte_verwijder IS NULL;
-- De room is nog niet geboekt. Dan kunnen we <20>f een bestaande boeking omhangen naar deze ruimte,
-- <20>f een nieuwe boeking maken (in de ADD-cursor)
-- Daarom: kunnen we de huidige rsv_ruimte aanpassen, of is die ruimte nog gewoon geboekt in Exchange?
v_errorhint :=
'Bepalen of voor room/zaal nog een boeking gewenst is';
SELECT COUNT (DISTINCT room_id)
INTO v_count_wanted
FROM exc_import i
WHERE appt_id || '|' || recur_id || '|' =
rec.appt_id || '|' || rec.recur_id || '|'
AND room_id = v_ruimte_extern_id;
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
v_count_all_booked
|| ' deelreservering(en) bij deze appointment ('
|| v_count_all_needed
|| ' nodig), waarvan '
|| v_count
|| ' voor deze room');
END IF;
-- NB: Deze oplossing is niet waterdicht. Daarvoor moet je eigenlijk weten in welke room een appointment
-- eerst was. Het lijkt handig om daarvoor uit de EWS-XML de Location en OldLocation nodes
-- te gebruiken, omdat daarin alle uitgenodigde ruimtes uitgelijst staan, maar helaas is Location
-- aanpasbaar in Outlook...
-- Multi-room? Dan nog wat checks, anders 'gewoon' bijwerken.
IF (v_count_all_booked > 1 OR v_count_all_needed > 1)
THEN
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Deze deelres. is op '
|| v_ruimte_extern_id
|| '. Benodigde deelres.: '
|| v_count_all_needed
|| ', waarvan op deze ruimte: '
|| v_count_wanted);
END IF;
-- Hebben we al een boeking voor deze zaal?
IF (v_count = 1)
THEN
-- Met deze rsv_ruimte?
-- Zo niet, dan skippen.
-- Zo ja, dan bijwerken (hier niets doen)
IF (v_ruimte_extern_id != rec.res_ruimte_extern_id)
THEN
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Skip (boeking op deze ruimte met andere rsv_ruimte)');
END IF;
CONTINUE;
END IF;
ELSIF (v_count = 0)
THEN
-- Willen we de ruimte van deze rsv_ruimte nog?
-- Zo ja, dan skippen.
-- Zo niet, dan kunnen we deze rsv_ruimte bijwerken (hier niets doen)
IF (v_count_wanted > 0)
THEN
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Skip (deze boeking ''bewaren'')');
END IF;
CONTINUE;
END IF;
END IF;
END IF;
-- We hebben niet geskipt, dus willen we deze rsv_ruimte bijwerken
-- Basisgegevens reservering gewijzigd?
IF ( v_ruimte_extern_id != rec.res_ruimte_extern_id
OR rec.res_rsv_ruimte_omschrijving !=
SUBSTR (rec.subject, 1, 60)
OR rec.res_rsv_ruimte_bezoekers != rec.num_bez
OR rec.res_rsv_ruimte_van != rec.starttime
OR rec.res_rsv_ruimte_tot != rec.endtime)
THEN
v_errorhint := 'Opstelling ophalen';
v_ruimte_opstel_key :=
exc.getOpstelling (rec.room_id);
IF (v_ruimte_opstel_key IS NULL)
THEN
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
'Geen ruimte-opstelling gedefinieerd');
CONTINUE;
END IF;
v_errorhint := 'Basisgegevens bijwerken';
UPDATE res_rsv_ruimte
SET res_ruimte_opstel_key = v_ruimte_opstel_key,
res_rsv_ruimte_omschrijving =
SUBSTR (rec.subject, 1, 60),
res_rsv_ruimte_van = rec.starttime,
res_rsv_ruimte_tot = rec.endtime,
res_rsv_ruimte_bezoekers = rec.num_bez
WHERE res_rsv_ruimte_key = rec.res_rsv_ruimte_key;
-- Opruimen en voorzieningen en bezoekers laten volgen
v_errorhint := 'Dirty, clean, voorzieningen';
res.set_ruimte_dirty (rec.res_rsv_ruimte_key);
res.set_ruimtes_clean (rec.starttime);
res.follow_artikel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
res.follow_deel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
res.follow_afspraak (rec.res_rsv_ruimte_key, 0);
--TODO: tracking + notificatie
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'RES: '
|| rec.res_reservering_key
|| '/'
|| rec.res_rsv_ruimte_volgnr);
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Room: '
|| v_ruimte_extern_id
|| '-->'
|| rec.res_ruimte_extern_id);
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Desc: "'
|| rec.res_rsv_ruimte_omschrijving
|| '"-->"'
|| SUBSTR (rec.subject, 1, 60)
|| '"');
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Start: '
|| TO_CHAR (rec.res_rsv_ruimte_van,
'DD-MM-YYYY HH24:MI')
|| '-->'
|| TO_CHAR (rec.starttime, 'DD-MM-YYYY HH24:MI'));
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Einde: '
|| TO_CHAR (rec.res_rsv_ruimte_tot,
'DD-MM-YYYY HH24:MI')
|| '-->'
|| TO_CHAR (rec.endtime, 'DD-MM-YYYY HH24:MI'));
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'Bezoekers: '
|| rec.res_rsv_ruimte_bezoekers
|| '-->'
|| rec.num_bez);
END IF;
fac.trackaction ('RESUPD',
rec.res_rsv_ruimte_key,
NULL,
SYSDATE,
NULL);
fac.imp_writelog (p_import_key,
'I',
v_aanduiding,
'Reservering bijgewerkt');
ELSE
IF (v_debug)
THEN
fac.imp_writelog (p_import_key,
'D',
v_aanduiding,
'Geen verschil in basisgegevens');
END IF;
END IF;
-- Succesvol afgerond; zet vlag.
-- All<6C><6C>n voor nu beschouwde ruimte! (appointments kunnen op meerdere ruimtes zijn)
-- TODO: komen we hier ook als er iets mis ging met de bezoekers?
UPDATE exc_import
SET gelukt = 1
WHERE appt_id || '|' || recur_id =
rec.appt_id || '|' || rec.recur_id
AND room_id = rec.room_id
AND gelukt IS NULL;
IF (v_debug)
THEN
fac.imp_writelog (p_import_key,
'D',
v_aanduiding,
'gelukt=1');
END IF;
EXCEPTION
WHEN OTHERS
THEN
v_count_error := v_count_error + 1;
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
'OTHERS (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
v_errorhint || ': ' || v_errormsg);
END;
END LOOP;
COMMIT;
-- Ten slotte nieuwe reserveringen toevoegen
FOR rec IN c_add
LOOP
BEGIN
v_aanduiding := rec.room_id || '|' || rec.subject;
v_perslid_key := NULL;
v_kostenplaats_key := NULL;
v_reservering_key := NULL;
v_rsv_ruimte_volgnr := 1;
v_rsv_ruimte_key := NULL;
v_errorhint :=
'Host '
|| rec.organizer
|| ' onbekend, of meer personen met dit e-mailadres! Geen boeking.';
-- Kennen we deze persoon eigenlijk wel?
SELECT COUNT (*)
INTO v_count
FROM prs_v_aanwezigperslid p
WHERE UPPER (p.prs_perslid_email) = UPPER (rec.organizer);
-- Niet bekend, of niet eenduidig --> jammer dan.
IF (v_count != 1)
THEN
fac.imp_writelog (p_import_key,
'E',
v_errorhint,
v_aanduiding);
-- Eenduidig bekend --> reservering maken
ELSE
v_errorhint := 'Persoonsgegevens ophalen';
SELECT p.prs_perslid_key, a.prs_kostenplaats_key
INTO v_perslid_key, v_kostenplaats_key
FROM prs_v_aanwezigperslid p, prs_v_aanwezigafdeling a
WHERE UPPER (p.prs_perslid_email) =
UPPER (rec.organizer)
AND a.prs_afdeling_key = p.prs_afdeling_key;
v_errorhint := 'Opstelling ophalen';
v_ruimte_opstel_key :=
exc.getOpstelling (rec.room_id);
IF (v_ruimte_opstel_key IS NULL)
THEN
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
'Geen ruimte-opstelling gedefinieerd');
CONTINUE;
END IF;
-- Is dit een op zichzelf staande appointment, of onderdeel van een reeks (recurrence)?
-- (obv recur_id, die samen met appt_id in res_rsv_ruimte_externnr staat)
v_errorhint := 'Check recurrence';
SELECT COUNT (*)
INTO v_count
FROM res_rsv_ruimte
WHERE res_rsv_ruimte_externnr IS NOT NULL
AND res_rsv_ruimte_externnr LIKE rec.appt_id || '|%'
-- AND res_rsv_ruimte_externnr NOT LIKE '%|'||rec.recur_id||'|%'
AND res_rsv_ruimte_verwijder IS NULL;
-- Er bestaan al deelreserveringen voor andere occurences van deze recurring appointment
-- Deelreservering binnen de bijbehorende res_reservering aanmaken
IF (v_count > 0)
THEN
v_errorhint := 'Reservering + volgnr ophalen';
SELECT res_reservering_key,
MAX (res_rsv_ruimte_volgnr) + 1
INTO v_reservering_key, v_rsv_ruimte_volgnr
FROM res_rsv_ruimte
WHERE res_rsv_ruimte_externnr IS NOT NULL
AND res_rsv_ruimte_externnr LIKE
rec.appt_id || '|%'
-- AND res_rsv_ruimte_externnr NOT LIKE '%|'||rec.recur_id||'|%'
AND res_rsv_ruimte_verwijder IS NULL
GROUP BY res_reservering_key;
fac.imp_writelog (
p_import_key,
'I',
v_aanduiding,
'Is occurence van ' || v_reservering_key);
-- Nog geen andere occurences --> nieuwe res_reservering
ELSE
v_errorhint := 'Reservering aanmaken';
-- res_reservering aanmaken
INSERT INTO res_reservering (res_reservering_ispool)
VALUES (0)
RETURNING res_reservering_key
INTO v_reservering_key;
END IF;
v_errorhint := 'Activiteit van de nieuwe reservering opzoeken';
c_activiteit_key :=
exc.getActiviteit (rec.room_id);
IF (c_activiteit_key IS NULL)
THEN
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
'Geen activiteit te vinden via de catalogus van de reserveerbare ruimte');
CONTINUE;
END IF;
v_errorhint := 'Deelreservering aanmaken';
-- res_rsv_ruimte aanmaken voor deze appointment+resource
INSERT INTO res_rsv_ruimte (res_rsv_ruimte_omschrijving,
res_rsv_ruimte_opmerking,
res_rsv_ruimte_externnr,
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_rsv_ruimte_ordernr,
res_rsv_ruimte_kosten_klant,
res_rsv_ruimte_contact_key,
res_rsv_ruimte_bezoekers,
res_reservering_key,
res_rsv_ruimte_volgnr,
res_status_bo_key)
VALUES (
SUBSTR (rec.subject, 1, 60),
NULL,
rec.appt_id
|| '|'
|| rec.recur_id
|| '|'
|| rec.seq_nr,
v_ruimte_opstel_key,
rec.starttime,
rec.endtime,
v_kostenplaats_key,
v_perslid_key,
c_activiteit_key,
2,
NULL,
1,
v_perslid_key,
rec.num_bez,
v_reservering_key,
v_rsv_ruimte_volgnr,
2)
RETURNING res_rsv_ruimte_key
INTO v_rsv_ruimte_key;
IF (v_debug)
THEN
fac.imp_writelog (
p_import_key,
'D',
v_aanduiding,
'RESERVERING '
|| v_reservering_key
|| '/'
|| v_rsv_ruimte_volgnr
|| ' ('
|| v_rsv_ruimte_key
|| ')');
END IF;
-- Succesvol afgerond; zet vlag.
-- TODO: komen we hier ook als er iets mis ging met de bezoekers?
UPDATE exc_import
SET gelukt = 1
WHERE appt_id || '|' || recur_id =
rec.appt_id || '|' || rec.recur_id
AND gelukt IS NULL;
IF (v_debug)
THEN
fac.imp_writelog (p_import_key,
'D',
v_aanduiding,
'gelukt=1');
END IF;
-- res_discipline achterhalen; alleen tracken voor EXCO en MC zalen
v_errorhint := 'res_discipline bepalen';
SELECT r.res_discipline_key
INTO v_discipline_key
FROM res_ruimte r,
res_ruimte_opstelling ro,
res_rsv_ruimte rr
WHERE rr.res_rsv_ruimte_key = v_rsv_ruimte_key
AND ro.res_ruimte_opstel_key =
rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key;
-- Altijd tracken <20>n notificeren!
v_errorhint := 'Tracking NEW';
v_code := 'RESNEW';
fac.trackaction (
v_code,
v_rsv_ruimte_key,
NULL,
SYSDATE,
'Booking confirmation meeting room, booking ref.: '
|| v_reservering_key
|| '/'
|| v_rsv_ruimte_volgnr);
-- Is er iets dirty?
res.set_ruimte_dirty (v_rsv_ruimte_key);
fac.imp_writelog (
p_import_key,
'I',
v_reservering_key
|| '/'
|| v_rsv_ruimte_volgnr
|| '('
|| TO_CHAR (rec.starttime, 'DD-MM-YYYY HH24:MI')
|| ' - '
|| TO_CHAR (rec.endtime, 'HH24:MI')
|| ') aangemaakt',
rec.subject);
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS
THEN
v_count_error := v_count_error + 1;
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
'OTHERS (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
v_errorhint || ': ' || v_errormsg);
END;
END LOOP;
IF BITAND(sync_level, 7) = 1
THEN
-- Bij dirty ruimtes de *oudere* opruimen
v_aanduiding := 'Calling set_ruimtes_clean';
v_errorhint := '';
exc.set_ruimtes_clean (p_import_key);
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
v_count_error := v_count_error + 1;
oracle_err_num := SQLCODE;
oracle_err_mes := SUBSTR (SQLERRM, 1, 200);
v_errormsg :=
'OTHERS (error '
|| oracle_err_num
|| '/'
|| oracle_err_mes
|| ')';
fac.imp_writelog (p_import_key,
'E',
v_aanduiding,
v_errorhint || ': ' || v_errormsg);
COMMIT;
END update_exchange;
PROCEDURE import_exchfull (p_import_key IN NUMBER)
IS
BEGIN
import_exchange (p_import_key);
END;
PROCEDURE update_exchfull (p_import_key IN NUMBER)
IS
v_errorhint VARCHAR2 (1000);
BEGIN
update_exchange (p_import_key); -- Eerst de gewone import
-- Nu alle reserveringen die niet zijn aangetroffen verwijderen
-- (Alleen voor ruimtes die in de importtabel voorkomen. Normaliter zijn dat alle ruimtes,
-- maar zo voorkom je dat je alle reserveringen weggooit als een ruimte 'per ongeluk' een
-- keer niet in de import zit. Handmatig verwijderen kan altijd.)
FOR rec
IN (WITH
this_import
AS
(SELECT *
FROM exc_import
WHERE fac_import_key = p_import_key)
SELECT res_rsv_ruimte_key,
res_rsv_ruimte_van,
res_rsv_ruimte_tot,
res_reservering_key,
res_rsv_ruimte_volgnr
FROM res_rsv_ruimte rr, res_ruimte_opstelling ro, res_ruimte r
WHERE rr.res_rsv_ruimte_externnr IS NOT NULL
AND rr.res_rsv_ruimte_verwijder IS NULL
AND rr.res_rsv_ruimte_van >=
(SELECT MIN (starttime) FROM this_import)
AND rr.res_rsv_ruimte_van <=
(SELECT MAX (starttime) FROM this_import)
AND ro.res_ruimte_opstel_key = rr.res_ruimte_opstel_key
AND r.res_ruimte_key = ro.res_ruimte_key
AND r.res_ruimte_extern_id IN (SELECT DISTINCT room_id
FROM this_import)
AND NOT EXISTS
(SELECT 1
FROM this_import i
WHERE rr.res_rsv_ruimte_externnr LIKE
i.appt_id
|| '|'
|| i.recur_id
|| '|%'
AND r.res_ruimte_extern_id = i.room_id))
LOOP
v_errorhint :=
'Verwijderen reservering '
|| TO_CHAR (rec.res_reservering_key)
|| '/'
|| rec.res_rsv_ruimte_volgnr
|| ' ('
|| TO_CHAR (rec.res_rsv_ruimte_key)
|| ')';
fac.imp_writelog (p_import_key,
'I',
v_errorhint,
'');
UPDATE res_rsv_ruimte
SET res_status_fo_key = 1, -- nooit doorbelasten of v_status_fo_key?
res_rsv_ruimte_verwijder = SYSDATE
WHERE res_rsv_ruimte_key = rec.res_rsv_ruimte_key;
fac.trackaction ('RESDEL',
rec.res_rsv_ruimte_key,
NULL,
SYSDATE,
NULL);
res.set_ruimte_dirty (rec.res_rsv_ruimte_key);
res.set_ruimtes_clean (rec.res_rsv_ruimte_van);
res.follow_artikel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
res.follow_deel (rec.res_rsv_ruimte_key,
rec.res_rsv_ruimte_van,
rec.res_rsv_ruimte_tot);
v_errorhint := 'res_reservering verwijderen';
UPDATE res_reservering
SET res_reservering_verwijder = SYSDATE
WHERE res_reservering_key = rec.res_reservering_key
AND NOT EXISTS
(SELECT *
FROM res_v_aanwezigrsv_ruimte
WHERE res_reservering_key = rec.res_reservering_key);
END LOOP;
END;
END exc;
/
REGISTERRUN('$Id$')
#endif // EXC