#ifdef  BEZ // 03-11-2000 PF
/*
 * $Revision$
 * $Id$
 *
 */
CREATE OR REPLACE PACKAGE bez AS
  PROCEDURE copy_afspraak (pkey IN NUMBER, newdate IN DATE, puserkey IN NUMBER, prsvkey_to IN NUMBER);
  PROCEDURE copy_afspraak (pkey IN NUMBER, newdate IN DATE, puserkey IN NUMBER, prsvkey_to IN NUMBER, newafspraakkey OUT NUMBER);
  PROCEDURE sync_resafspraak (presvruimtevan IN NUMBER, presvruimtenaar IN NUMBER);
  PROCEDURE claim_parking (pbez_bezoekers_key IN NUMBER, palg_gebter_key IN NUMBER);
  FUNCTION  hasparking    (pbez_bezoekers_key IN NUMBER) RETURN NUMBER;
  FUNCTION  afssprintf       (ps IN VARCHAR2 , p_afspraak_key IN NUMBER) RETURN VARCHAR2 ;
  FUNCTION  bzksprintf       (ps IN VARCHAR2 , p_bezoekers_key IN NUMBER) RETURN VARCHAR2 ;
END bez;
/

CREATE OR REPLACE PACKAGE BODY bez AS

   PROCEDURE copy_afspraak (pkey IN NUMBER, newdate IN DATE, puserkey IN NUMBER, prsvkey_to IN NUMBER)
   AS
      newafspraakkey bez_afspraak.bez_afspraak_key%TYPE;
   BEGIN
      copy_afspraak (pkey, newdate, puserkey, prsvkey_to, newafspraakkey);
   END;

   -- Variant waarbij je newafspraakkey terug krijgt
   PROCEDURE copy_afspraak (pkey IN NUMBER, newdate IN DATE, puserkey IN NUMBER, prsvkey_to IN NUMBER, newafspraakkey OUT NUMBER)
   AS
      newbezoekerskey bez_bezoekers.bez_bezoekers_key%TYPE;
      hasparking NUMBER;
      nieuwvan DATE;
      nieuwtot DATE;

      CURSOR bezoekers
      IS
         SELECT   bez_bezoekers_key,
                  bez_afspraak_naam,
                  bez_afspraak_bedrijf,
                  bez_bezoekers_opmerking,
                  prs_contactpersoon_key
           FROM   bez_bezoekers
          WHERE   bez_afspraak_key = pkey;
   BEGIN
      -- Als prsvkey_to niet null is, dan is het een afspraak bij een res_rsv_ruimte
      -- anders gewoon een losse afspraak. In beide gevallen worden de gegevens van de
      -- afspraak gebruikt trouwens, die moeten consistent zijn met die reservering
      -- Gaat er van uit dat er nog geen to-afspraakrecord is.
      IF newdate IS NOT NULL
      THEN
         SELECT   newdate + (bez_afspraak_datum - TRUNC (bez_afspraak_datum)),
                  newdate + (bez_afspraak_eind - TRUNC (bez_afspraak_eind))
           INTO   nieuwvan, nieuwtot
           FROM   bez_afspraak a
          WHERE   a.bez_afspraak_key = pkey;
      ELSE
         SELECT   res_rsv_ruimte_van, res_rsv_ruimte_tot
           INTO   nieuwvan, nieuwtot
           FROM   res_rsv_ruimte r
          WHERE   r.res_rsv_ruimte_key = prsvkey_to;
      END IF;

      SELECT   bez_s_bez_afspraak_key.NEXTVAL INTO newafspraakkey FROM DUAL;

      INSERT INTO bez_afspraak (bez_afspraak_key,
                  prs_perslid_key,
                  bez_afspraak_host_key,
                  bez_afspraak_contact_key,
                  bez_afspraak_gastheer,
                  bez_afspraak_telefoonnr,
                  bez_afspraak_datum, bez_actie_key,
                  alg_locatie_key, res_rsv_ruimte_key,
                  alg_onrgoed_keys, bez_afspraak_ruimte,
                  bez_afspraak_opmerking, bez_afspraak_eind
                               )
         SELECT   newafspraakkey,
                  puserkey,
                  a.bez_afspraak_host_key,
                  a.bez_afspraak_contact_key,
                  a.bez_afspraak_gastheer,
                  a.bez_afspraak_telefoonnr,
                  nieuwvan,
                  a.bez_actie_key,
                  a.alg_locatie_key,
                  prsvkey_to,
                  a.alg_onrgoed_keys,
                  a.bez_afspraak_ruimte,
                  a.bez_afspraak_opmerking,
                  nieuwtot
           FROM   bez_afspraak a
          WHERE   a.bez_afspraak_key = pkey;

      -- Er zijn geen flexkenmerken in het spel voor afspraak
      FOR b IN bezoekers
      LOOP
         SELECT   bez_s_bez_bezoekers_key.NEXTVAL INTO newbezoekerskey FROM DUAL;

         INSERT INTO bez_bezoekers (
                                       bez_bezoekers_key,
                                       bez_afspraak_key,
                                       bez_afspraak_naam,
                                       bez_afspraak_bedrijf,
                                       bez_bezoekers_opmerking,
                                       prs_contactpersoon_key
                    )
           VALUES   (
                        newbezoekerskey,
                        newafspraakkey,
                        b.bez_afspraak_naam,
                        b.bez_afspraak_bedrijf,
                        b.bez_bezoekers_opmerking,
                        b.prs_contactpersoon_key
                    );

         -- Als de bron een P had, dan de bestemming ook
         hasparking := bez.hasparking (b.bez_bezoekers_key);

         IF (hasparking > 0)
         THEN
            claim_parking (newbezoekerskey, null);
         -- Eventueel: controleren of de nieuwe nu ook een P heeft,
         -- en zo niet dat dan tracken; goed doordenken!
         END IF;

         -- Kopieer de flexkenmerken van de bezoekers
         INSERT INTO bez_kenmerkwaarde
                     ( bez_bezoekers_key,
                       bez_kenmerk_key,
                       bez_kenmerkwaarde_waarde
                     )
                     SELECT newbezoekerskey,
                            w.bez_kenmerk_key,
                            w.bez_kenmerkwaarde_waarde
                       FROM bez_kenmerkwaarde w,
                            bez_kenmerk k
                      WHERE w.bez_kenmerk_key = k.bez_kenmerk_key
                        AND w.bez_bezoekers_key = b.bez_bezoekers_key
                        AND w.bez_kenmerkwaarde_verwijder IS NULL;

      END LOOP;

      fac.trackaction ('BEZMUT', newafspraakkey, puserkey, NULL, NULL);
   END;

   -- Registreer precies hetzelfde bezoek als bij -van bij -naar
   PROCEDURE sync_resafspraak (presvruimtevan IN NUMBER, presvruimtenaar IN NUMBER)
   AS
      afspraak_key_from bez_afspraak.bez_afspraak_key%TYPE := -1;
      afspraak_key_to bez_afspraak.bez_afspraak_key%TYPE := -1;
   BEGIN
      BEGIN
         SELECT   bez_afspraak_key
           INTO   afspraak_key_from
           FROM   bez_afspraak
          WHERE   res_rsv_ruimte_key = presvruimtevan;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            NULL;
      END;

      BEGIN
         SELECT   bez_afspraak_key
           INTO   afspraak_key_to
           FROM   bez_afspraak
          WHERE   res_rsv_ruimte_key = presvruimtenaar;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            NULL;
      END;

      IF afspraak_key_to = -1 AND afspraak_key_from = -1
      THEN
         RETURN;
      END IF;

      IF afspraak_key_to <> -1
      THEN
         -- Bestaande verwijderen
         DELETE FROM   bez_afspraak
               WHERE   bez_afspraak_key = afspraak_key_to;
      END IF;

      IF afspraak_key_from <> -1
      THEN
         bez.copy_afspraak (afspraak_key_from, NULL, NULL, presvruimtenaar);
      END IF;
   END;

   PROCEDURE claim_parking (pbez_bezoekers_key IN NUMBER, palg_gebter_key IN NUMBER)
   AS
      lafspraakkey bez_afspraak.bez_afspraak_key%TYPE;
      ldeelreskey res_rsv_ruimte.res_rsv_ruimte_key%TYPE;
      llocatiekey bez_afspraak.alg_locatie_key%TYPE;
      lbegin bez_afspraak.bez_afspraak_datum%TYPE;
      leinde bez_afspraak.bez_afspraak_eind%TYPE;
      topstel res_rsv_ruimte.res_ruimte_opstel_key%TYPE;
      talgruimte res_rsv_ruimte.alg_ruimte_key%TYPE;
      lparkeerkey res_deel.res_deel_key%TYPE;
      bez_parkingdiscipline_key NUMBER;
      lpreposttime NUMBER(5,4); -- we gaan nog delen door 24, res_disc_params.res_disc_params_preposttime%TYPE is dan te klein;
   BEGIN
      -- Claim een (nieuwe) parkeerplaats voor de gegeven bezoeker
      -- Reserveer voor de tijden van de bijbehorende afspraak cq. res_rsv_ruimte
      -- een parkeerplaats binnen de locatie van die afspraak/reservering.
      -- We moeten dan wel de parkeerplaats discipline weten, die moet dan dus in de DB worden
      -- geconfigureerd
      -- ?Tracking bij afspraak toevoegen als wel/niet gelukt? (parkeerplts voor A niet/wel gereserveerd)
      -- Pas op: bezoekers worden regelmatig vervangen (delete+insert ipv update)
      -- De claim kan falen als er niets vrij is! Dat merkt niemand
      -- De aanroeper kan dit controleren met bez.hasparking()

      -- Een bezoeker hoort bij een afspraak, die op zichzelf staat of bij een deelreservering hoort
      SELECT   a.bez_afspraak_key,
               a.res_rsv_ruimte_key,
               a.alg_locatie_key,
               a.bez_afspraak_datum,
               a.bez_afspraak_eind
        INTO   lafspraakkey,
               ldeelreskey,
               llocatiekey,
               lbegin,
               leinde
        FROM   bez_bezoekers b, bez_afspraak a
       WHERE   a.bez_afspraak_key = b.bez_afspraak_key AND bez_bezoekers_key = pbez_bezoekers_key;

      IF ldeelreskey IS NOT NULL
      THEN
         -- Zoek de noodzakelijke gegevens op
         SELECT   r.res_ruimte_opstel_key, r.alg_ruimte_key
           INTO   topstel, talgruimte
           FROM   res_rsv_ruimte r
          WHERE   res_rsv_ruimte_key = ldeelreskey;

         -- Begin- en eindtijd zouden al bekend moeten zijn via afspraak (zal eigenlijk altijd gevuld zijn)
         -- Zo niet, dan nog ophalen uit rsv_ruimte
         IF lbegin IS NULL OR leinde IS NULL
         THEN
            SELECT   r.res_rsv_ruimte_van, r.res_rsv_ruimte_tot
              INTO   lbegin, leinde
              FROM   res_rsv_ruimte r
             WHERE   res_rsv_ruimte_key = ldeelreskey;
         END IF;

         IF talgruimte IS NOT NULL
         THEN
            SELECT   g.alg_locatie_key
              INTO   llocatiekey
              FROM   alg_ruimte r, alg_verdieping v, alg_gebouw g
             WHERE       r.alg_verdieping_key = v.alg_verdieping_key
                     AND v.alg_gebouw_key = g.alg_gebouw_key
                     AND r.alg_ruimte_key = talgruimte;
         ELSE
            SELECT   MIN (g.alg_locatie_key)                                                        -- tegen koppelzalen
              INTO   llocatiekey
              FROM   res_ruimte_opstelling ro, res_alg_ruimte rag, alg_ruimte r, alg_verdieping v, alg_gebouw g
             WHERE       ro.res_ruimte_key = rag.res_ruimte_key
                     AND rag.alg_ruimte_key = r.alg_ruimte_key
                     AND res_alg_ruimte_verwijder IS NULL
                     AND r.alg_verdieping_key = v.alg_verdieping_key
                     AND v.alg_gebouw_key = g.alg_gebouw_key
                     AND ro.res_ruimte_opstel_key = topstel;
         END IF;
      END IF;

      -- ik weet genoeg, behalve: de discipline_key van parkeerplaatsen en de pre/post tijden van deze discipline!
      bez_parkingdiscipline_key := fac.safe_to_number (fac.getsetting ('vis_parking_key'));

      SELECT COALESCE(rdp.res_disc_params_preposttime, 0) / 24
        INTO lpreposttime
        FROM res_disc_params rdp
       WHERE rdp.res_ins_discipline_key = bez_parkingdiscipline_key;

      -- lpreposttime is nu in dagen (in uren / 24 = in dagen).
      -- In de query wordt rekening gehouden met 1 minuut marge voor afrondfouten (+/- 1 / 1440).
      -- Heb ik een gebouwkey of terreinkey meegekregen?
      IF palg_gebter_key IS NULL
      THEN
        -- Wat is een vrije parkeerplaats
        SELECT   MIN (res_deel_key)                                                                    -- logischer maken?
          INTO   lparkeerkey
          FROM   (  SELECT   d.res_deel_key,
                             (SELECT   MIN (rd.res_deel_key)
                                FROM   res_v_aanwezigrsv_deel rd
                               WHERE       d.res_deel_key = rd.res_deel_key
                                       AND rd.res_rsv_deel_van BETWEEN TRUNC (lbegin) AND leinde - 1 / 1440 + lpreposttime
                                       AND rd.res_rsv_deel_tot BETWEEN lbegin + 1 / 1440 - lpreposttime AND TRUNC (lbegin) + 1
                                       AND rd.res_rsv_deel_van < leinde - 1 / 1440 + lpreposttime
                                       AND rd.res_rsv_deel_tot > lbegin + 1 / 1440 - lpreposttime
                                       AND d.res_discipline_key = bez_parkingdiscipline_key)
                                aantal
                      FROM   res_v_aanwezigdeel d, ins_deel id, alg_v_aanwezigterreinsector t
                     WHERE       d.res_ins_deel_key = id.ins_deel_key
                             AND id.ins_alg_locatie_key = llocatiekey
                             AND d.res_discipline_key = bez_parkingdiscipline_key
                             AND id.ins_alg_ruimte_key = t.alg_terreinsector_key(+)
                             -- outer join mag hier niet en dit filter is niet nodig? AND id.ins_alg_ruimte_type = 'T'(+)
                             AND t.prs_afdeling_key IS  NULL -- Alleen 'gewone' parkeerplaatsen
                             -- Is de parkeerplaats reserveerbaar op de begindag. Meerdaagse parkeerplaatsen worden niet ondersteund.
                             -- (bits & (2^(dow-1))) = (2^(dow-1))
                             AND BITAND(d.res_deel_beschikbaar_bits,
                                        POWER(2,
                                              (fac.getweekdaynum(TRUNC(lbegin)) - 1))) =
                                 POWER(2, (fac.getweekdaynum(TRUNC (lbegin)) - 1))
                             AND (   d.res_deel_vervaldatum IS NULL
                                  OR d.res_deel_vervaldatum > lbegin)
                  ORDER BY   id.ins_deel_upper)
         WHERE   aantal IS NULL;
      ELSE
        -- Wat is een vrije parkeerplaats
        -- Er is een gebouwkey of terreinkey meegegeven. Hierbinnen moet de parkeerplaats gereserveerd worden.
        SELECT   MIN (res_deel_key)                                                                    -- logischer maken?
          INTO   lparkeerkey
          FROM   (  SELECT   d.res_deel_key,
                             (SELECT   MIN (rd.res_deel_key)
                                FROM   res_v_aanwezigrsv_deel rd
                               WHERE       d.res_deel_key = rd.res_deel_key
                                       AND rd.res_rsv_deel_van BETWEEN TRUNC (lbegin) AND leinde - 1 / 1440 + lpreposttime
                                       AND rd.res_rsv_deel_tot BETWEEN lbegin + 1 / 1440 - lpreposttime AND TRUNC (lbegin) + 1
                                       AND rd.res_rsv_deel_van < leinde - 1 / 1440 + lpreposttime
                                       AND rd.res_rsv_deel_tot > lbegin + 1 / 1440 - lpreposttime
                                       AND d.res_discipline_key = bez_parkingdiscipline_key)
                                aantal
                      FROM   res_v_aanwezigdeel d, ins_deel id, alg_v_allonroerendgoed og
                     WHERE       d.res_ins_deel_key = id.ins_deel_key
                             AND id.ins_alg_locatie_key = llocatiekey
                             AND d.res_discipline_key = bez_parkingdiscipline_key
                             AND (id.ins_alg_ruimte_key = og.alg_ruimte_key
                               OR id.ins_alg_ruimte_key = og.alg_terreinsector_key)
                             AND (og.alg_gebouw_key = palg_gebter_key
                               OR og.alg_terreinsector_key = palg_gebter_key)
                             AND id.ins_alg_ruimte_type IN ('R', 'T')
                             -- Is de parkeerplaats reserveerbaar op de begindag. Meerdaagse parkeerplaatsen worden niet ondersteund.
                             -- (bits & (2^(dow-1))) = (2^(dow-1))
                             AND BITAND(d.res_deel_beschikbaar_bits,
                                        POWER(2,
                                              (fac.getweekdaynum(TRUNC(lbegin)) - 1))) =
                                 POWER(2, (fac.getweekdaynum(TRUNC (lbegin)) - 1))
                             AND (   d.res_deel_vervaldatum IS NULL
                                  OR d.res_deel_vervaldatum > lbegin)
                  ORDER BY   id.ins_deel_upper)
         WHERE   aantal IS NULL;
      END IF;

      IF lparkeerkey IS NOT NULL
      THEN
         INSERT INTO res_rsv_deel (
                                      res_deel_key,
                                      res_rsv_deel_aantal,
                                      res_status_bo_key,
                                      res_rsv_deel_van,
                                      res_rsv_deel_tot,
                                      bez_bezoekers_key,
                                      res_rsv_ruimte_key
                    )
           VALUES   (lparkeerkey, 1, 2, lbegin, leinde, pbez_bezoekers_key, ldeelreskey
                    );
      ELSE
        -- Geen vrije parkeerplaats beschikbaar
        NULL;
      END IF;
   END;

   FUNCTION hasparking (pbez_bezoekers_key IN NUMBER)
      RETURN NUMBER
   IS
      aantal NUMBER;
   BEGIN
      SELECT   COUNT ( * )
        INTO   aantal
        FROM   res_rsv_deel
       WHERE   bez_bezoekers_key = pbez_bezoekers_key;

      RETURN aantal;
   END;


  FUNCTION afssprintf (ps IN VARCHAR2, p_afspraak_key IN NUMBER) RETURN VARCHAR2 IS
    lafspraak_datum  bez_afspraak.bez_afspraak_datum%TYPE;
    lbezoek          VARCHAR2 (200);
    s varchar2 (2048 CHAR);
  BEGIN
   s :=  ps;
    -- We support substitution of placeholders in the messages
   -- ##KEY##    afspraaknummer
   -- ##NAAM##   volledige naam van de (eerst opgeslagen) bezoeker
   IF INSTR (s, '#') > 0
   THEN
    SELECT bez_afspraak_datum
    INTO lafspraak_datum
    FROM bez_afspraak
    WHERE bez_afspraak_key = p_afspraak_key;

    SELECT MIN(bez_afspraak_naam) || DECODE (COUNT (*), 1, '', '...')
      INTO lbezoek
      FROM bez_bezoekers
     WHERE bez_afspraak_key = p_afspraak_key
     GROUP BY bez_afspraak_key;

       s :=
          REPLACE (REPLACE (REPLACE (s, '##NAAM##', lbezoek), '##KEY##', NUMBER_TO_CHAR (p_afspraak_key)),
                   '##DATUM##',
                   DATE_TO_CHAR (lafspraak_datum, 'DD-MM-YY HH24:MI')
                  );
   END IF;
   RETURN s;

  END;

  FUNCTION  bzksprintf (ps IN VARCHAR2 , p_bezoekers_key IN NUMBER) RETURN VARCHAR2 IS
    lafspraak_datum  bez_afspraak.bez_afspraak_datum%TYPE;
    lafspraak_key    bez_afspraak.bez_afspraak_key%TYPE;
    lbezoek          bez_bezoekers.bez_afspraak_naam%TYPE;
    lbedrijf         bez_bezoekers.bez_afspraak_bedrijf%TYPE;
    lbadgenr         bez_bezoekers.bez_bezoekers_pasnr%TYPE;
    s varchar2 (2048 CHAR);
  BEGIN
   s :=  ps;
    -- We support substitution of placeholders in the messages
   -- ##KEY##    afspraaknummer
   -- ##NAAM##   volledige naam van de bezoeker
   -- ##BEDRIJF##   naam van het bedrijf van de bezoeker
   -- ##PASNR##   pasnr (badgenr)
   IF INSTR (s, '#') > 0
   THEN
    SELECT a.bez_afspraak_datum, b.bez_afspraak_key, b.bez_afspraak_naam, b.bez_afspraak_bedrijf, b.bez_bezoekers_pasnr
      INTO lafspraak_datum, lafspraak_key, lbezoek, lbedrijf, lbadgenr
      FROM bez_afspraak a, bez_bezoekers b
     WHERE a.bez_afspraak_key = b.bez_afspraak_key
       AND bez_bezoekers_key = p_bezoekers_key;

       s :=
          REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (s, '##NAAM##', lbezoek), '##KEY##', NUMBER_TO_CHAR (lafspraak_key)),
                   '##DATUM##',
                   DATE_TO_CHAR (lafspraak_datum, 'DD-MM-YY HH24:MI')
                  ), '##BEDRIJF##', lbedrijf), '##PASNR##', lbadgenr);
   END IF;
   RETURN s;

  END;



END bez;
/

REGISTERRUN('$Id$')

#endif // BEZ
