#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 importBezoekers(p_import_key IN NUMBER, p_appt_id IN VARCHAR2, p_recur_id IN VARCHAR2, p_rsv_ruimte_key IN NUMBER, date_interval_start IN DATE, date_interval_end IN DATE);

    PROCEDURE import_exchange(p_import_key IN NUMBER, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90);
    PROCEDURE update_exchange(p_import_key IN NUMBER, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90);

    PROCEDURE import_exchfull(p_import_key IN NUMBER, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90);
    PROCEDURE update_exchfull(p_import_key IN NUMBER, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90);

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;

    PROCEDURE importBezoekers (p_import_key IN NUMBER, p_appt_id IN VARCHAR2, p_recur_id IN VARCHAR2, p_rsv_ruimte_key IN NUMBER, date_interval_start IN DATE, date_interval_end IN DATE)
    IS
        v_afspraak_key  bez_afspraak.bez_afspraak_key%TYPE := -1;

        CURSOR bezoekers IS
            SELECT subject,
                   starttime,
                   endtime,
                   organizer,
                   att_name,
                   att_mail,
                   appt_id,
                   recur_id
              FROM exc_import
             WHERE     starttime <= date_interval_end
                   AND endtime >= date_interval_start
                   AND appt_id || '|' || recur_id = p_appt_id || '|' || p_recur_id
                   AND gelukt IS NULL
                   AND NOT REGEXP_LIKE (att_mail, (SELECT COALESCE (fac_setting_pvalue, fac_setting_default)
                                                     FROM fac_setting
                                                    WHERE fac_setting_name = 'exchange_internal_email_regexp'));
    BEGIN
        FOR exc_bez IN bezoekers
        LOOP
            IF v_afspraak_key = -1
            THEN
                SELECT bez_s_bez_afspraak_key.NEXTVAL INTO v_afspraak_key FROM DUAL;
                INSERT INTO bez_afspraak (bez_afspraak_key,
                                          prs_perslid_key,
                                          bez_afspraak_datum,
                                          bez_actie_key,
                                          bez_afspraak_ruimte,
                                          bez_afspraak_opmerking,
                                          bez_afspraak_eind,
                                          alg_locatie_key,
                                          alg_onrgoed_keys,
                                          bez_afspraak_host_key,
                                          bez_afspraak_contact_key,
                                          res_rsv_ruimte_key)
                      SELECT v_afspraak_key,
                             rr.res_rsv_ruimte_contact_key,
                             rr.res_rsv_ruimte_van,
                             r.bez_actie_key,
                             SUBSTR (r.res_ruimte_nr, 1, 30),
                             SUBSTR ('Overgenomen uit Exchange', 1, 320),
                             rr.res_rsv_ruimte_tot,
                             g.alg_locatie_key,
                             MIN (rar.alg_ruimte_key),
                             rr.res_rsv_ruimte_host_key,
                             rr.res_rsv_ruimte_contact_key,
                             p_rsv_ruimte_key
                        FROM res_rsv_ruimte       rr,
                             res_ruimte_opstelling ro,
                             res_ruimte           r,
                             res_alg_ruimte       rar,
                             alg_v_aanwezigruimte ar,
                             alg_verdieping       v,
                             alg_gebouw           g
                       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 rar.res_ruimte_key = r.res_ruimte_key
                             AND rar.res_alg_ruimte_verwijder IS NULL
                             AND ar.alg_ruimte_key = rar.alg_ruimte_key
                             AND v.alg_verdieping_key = ar.alg_verdieping_key
                             AND g.alg_gebouw_key = v.alg_gebouw_key
                    GROUP BY rr.res_rsv_ruimte_contact_key,
                             rr.res_rsv_ruimte_van,
                             r.bez_actie_key,
                             r.res_ruimte_nr,
                             rr.res_rsv_ruimte_tot,
                             g.alg_locatie_key,
                             rr.res_rsv_ruimte_host_key,
                             rr.res_rsv_ruimte_contact_key;
            END IF;

            INSERT INTO bez_bezoekers (bez_afspraak_key,
                                       bez_afspraak_naam,
                                       bez_bezoekers_email)
                 VALUES (v_afspraak_key,
                         SUBSTR (exc_bez.att_name, 1, 60),
                         exc_bez.att_mail);
        END LOOP;
    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,
                                  'I',
                                  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, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90)
    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;
        date_interval_start DATE := TRUNC (SYSDATE) - p_days_from;
        date_interval_end   DATE := TRUNC (SYSDATE) + p_days_to;

        -- 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 (100);
        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.
        -- Deletes die al deleted zijn, zijn schijnbaar al gelukt
        DELETE FROM exc_import
              WHERE gelukt IS NOT NULL
                    OR (    modifier = 'D'
                        AND EXISTS
                                (SELECT 1
                                   FROM res_rsv_ruimte
                                  WHERE     res_rsv_ruimte_verwijder IS NOT NULL
                                        AND res_rsv_ruimte_externnr = appt_id || '|' || recur_id));

        -- 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 <= date_interval_end
                                AND d_endtime >= date_interval_start)))
                    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, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90)
    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 := FALSE;
        sync_level            fac_setting.fac_setting_pvalue%TYPE;
        date_interval_start   DATE := TRUNC (SYSDATE) - p_days_from;
        date_interval_end     DATE := TRUNC (SYSDATE) + p_days_to;

        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);

        -- ANNULEREN
        -- Eerst alle 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: 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 = 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 <= date_interval_end
                           AND endtime >= date_interval_start
                           AND gelukt IS NULL) i,
                   res_rsv_ruimte  rr
             WHERE     rr.res_rsv_ruimte_externnr = 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 <= date_interval_end
                           AND endtime >= date_interval_start
                           AND recur_id IS NOT NULL
                           AND gelukt IS NULL) i,
                   res_rsv_ruimte  rr
             WHERE     rr.res_rsv_ruimte_externnr = 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 ü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
                        FROM exc_import
                       WHERE     modifier = 'U'
                             AND starttime <= date_interval_end
                             AND endtime >= date_interval_start
                             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 = 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 (ó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 <= date_interval_end
                             AND endtime >= date_interval_start
                             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 <= date_interval_end
                             AND endtime >= date_interval_start
                             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 = 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)
            ORDER BY 9;
    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 die buiten het geconfigureerde interval vallen
        UPDATE exc_import i
           SET gelukt = 4
         WHERE starttime > date_interval_end
            OR endtime < date_interval_start;

        -- 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 INSTR(res_rsv_ruimte_externnr, i.appt_id || '|') = 1);

        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,
                                      'I',
                                      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 éé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,
                                'I',
                                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 één appointment
        -- meerdere updates - of zelfs een delete - hebben. Dan zijn we alleen geï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 = 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 é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 éé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 éé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 = 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 <= date_interval_end
                       AND i.endtime >= date_interval_end
                       AND i.appt_id || '|' || i.recur_id || '|' =
                               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 éé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 = 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 óf een bestaande boeking omhangen naar deze ruimte,
                -- ó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,
                        'I',
                        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,
                            'I',
                            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,
                                    'I',
                                    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,
                                    'I',
                                    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_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
                     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,
                            'I',
                            v_aanduiding,
                               'RES: '
                            || rec.res_reservering_key
                            || '/'
                            || rec.res_rsv_ruimte_volgnr);
                        fac.imp_writelog (
                            p_import_key,
                            'I',
                            v_aanduiding,
                               'Room: '
                            || v_ruimte_extern_id
                            || '-->'
                            || rec.res_ruimte_extern_id);
                        fac.imp_writelog (
                            p_import_key,
                            'I',
                            v_aanduiding,
                               'Desc: "'
                            || rec.res_rsv_ruimte_omschrijving
                            || '"-->"'
                            || SUBSTR (rec.subject, 1, 60)
                            || '"');
                        fac.imp_writelog (
                            p_import_key,
                            'I',
                            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,
                            'I',
                            v_aanduiding,
                               'Einde: '
                            || TO_CHAR (rec.res_rsv_ruimte_tot,
                                        'DD-MM-YYYY HH24:MI')
                            || '-->'
                            || TO_CHAR (rec.endtime, 'DD-MM-YYYY HH24:MI'));
                    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,
                                          'I',
                                          v_aanduiding,
                                          'Geen verschil in basisgegevens');
                    END IF;
                END IF;

                -- Succesvol afgerond; zet vlag.
                -- Alléé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,
                                      'I',
                                      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 INSTR(res_rsv_ruimte_externnr, rec.appt_id || '|') = 1
                           --               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     INSTR(res_rsv_ruimte_externnr,
                                           rec.appt_id || '|') = 1
                                 --                  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';

                    BEGIN
                        -- 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,
                                 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;
                    EXCEPTION
                        WHEN DUP_VAL_ON_INDEX
                        THEN  -- Er bestaat al een reservering met dit externnr
                            IF NOT (v_count > 0) -- Verwijder dan ook het zojuist aangemaakte res_reservering-record weer
                            THEN
                                DELETE FROM res_reservering WHERE res_reservering_key = v_reservering_key;
                            END IF;
                            -- Pas het 'gelukt' bitje aan zodat we hem later niet weer opnieuw proberen
                            UPDATE exc_import
                               SET gelukt = 2
                             WHERE     appt_id || '|' || recur_id =
                                       rec.appt_id || '|' || rec.recur_id
                                   AND gelukt IS NULL;

                            fac.imp_writelog (p_import_key,
                                              'I',
                                              v_aanduiding,
                                              'Deze exacte reservering is al bekend in Facilitor -> Geen boeking.');
                            CONTINUE;
                    END;

                    IF (v_debug)
                    THEN
                        fac.imp_writelog (
                            p_import_key,
                            'I',
                            v_aanduiding,
                               'RESERVERING '
                            || v_reservering_key
                            || '/'
                            || v_rsv_ruimte_volgnr
                            || ' ('
                            || v_rsv_ruimte_key
                            || ')');
                    END IF;

                    v_errorhint := 'Toevoegen bezoekers';
                    exc.importBezoekers(p_import_key, rec.appt_id, rec.recur_id, v_rsv_ruimte_key, date_interval_start, date_interval_end);

                    -- 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,
                                          'I',
                                          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 én notificeren!
                    v_errorhint := 'Tracking NEW';
                    fac.trackaction ('RESNEW',
                                     v_rsv_ruimte_key,
                                     NULL,
                                     SYSDATE,
                                     NULL);

                    -- 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, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90)
    IS
    BEGIN
        import_exchange (p_import_key, p_days_from, p_days_to);
    END;

    PROCEDURE update_exchfull (p_import_key IN NUMBER, p_days_from IN NUMBER DEFAULT 0, p_days_to IN NUMBER DEFAULT 90)
    IS
        v_errorhint   VARCHAR2 (1000);
    BEGIN
        update_exchange (p_import_key, p_days_from, p_days_to);    -- 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 (   (SELECT BITAND ( COALESCE (fac_setting_pvalue, fac_setting_default), 6)
                                  FROM fac_setting
                                 WHERE fac_setting_name = 'msgraph_sync_level') = 4
                            OR (    rr.res_rsv_ruimte_externnr IS NOT NULL
                                AND rr.res_rsv_ruimte_externnr2 IS NULL
                                AND rr.res_rsv_ruimte_externsyncdate 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 = 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
