#ifdef  BES // 03-11-2000 PF
/*  BES_PAC.SRC
 *  $Revision$
 *  $Id$
 */

-- STATUS: TESTEN
CREATE OR REPLACE PACKAGE bes
AS
   FUNCTION getsrtdeelprijsinfo (pbes_srtdeel_key IN NUMBER, pdate IN DATE, pflags IN NUMBER)
      RETURN NUMBER;

   FUNCTION getsrtdeelprijs (pbes_srtdeel_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER;
   FUNCTION getsrtdeelinkprijs (pbes_srtdeel_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER;
   FUNCTION getsrtprodprijs (pbes_srtprod_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER;

   FUNCTION calcartikelkortingsprijs (pbes_srtdeel_key IN NUMBER, pbestelaantal IN NUMBER)
      RETURN NUMBER;

   PROCEDURE calcopdrachtbedragkorting (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER,
                                        pkortingsbedrag OUT NUMBER, pkorting OUT NUMBER);

   FUNCTION calcopdrachtkorting (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER)
      RETURN NUMBER;

   FUNCTION calcopdrachtkortingbedrag (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER)
      RETURN NUMBER;

   FUNCTION calcbesartikelkortingsprijs (pbes_bestelling_item_key IN NUMBER, ppunchout IN NUMBER)
      RETURN NUMBER;

   FUNCTION calcbesopdrachtkorting (pbes_bestelopdr_key IN NUMBER, pautoupdate IN NUMBER)
      RETURN NUMBER;

   FUNCTION calcbesopdrachtkosten (pbes_bestelopdr_key IN NUMBER, pautoupdate IN NUMBER)
      RETURN NUMBER;

  PROCEDURE upsert_srtdeel_prijs (p_bes_srtdeel_key IN NUMBER, p_bes_srtdeel_prijs IN NUMBER, p_bes_srtdeel_inkprijs IN NUMBER);

  PROCEDURE upsert_srtdeel (p_ins_discipline_key          IN NUMBER,
                         p_bes_srtgroep_omschrijving   IN VARCHAR2,
                         p_bes_srtdeel_omschrijving    IN VARCHAR2,
                         p_bes_srtdeel_prijs           IN NUMBER,
                         p_bes_srtdeel_btw             IN NUMBER,
                         p_bes_srtdeel_eenheid         IN VARCHAR2,
                         p_bes_srtdeel_nr              IN VARCHAR2,
                         p_prs_bedrijf_key             IN NUMBER,
                         p_bes_srtdeel_vervaldatum     IN DATE,
                         p_bes_srtdeel_image           IN VARCHAR2,
                         p_bes_srtdeel_veelvoud        IN NUMBER,
                         p_bes_srtdeel_opmerking       IN VARCHAR2,
                         p_bes_srtdeel_details_loc     IN VARCHAR2 DEFAULT NULL
                        );

   PROCEDURE makeorders (i_userkey IN NUMBER, bes_key IN NUMBER);
   PROCEDURE changeorders (i_userkey IN NUMBER, bes_key IN NUMBER);
   PROCEDURE makecontract (bestelopdr_key IN NUMBER);
   PROCEDURE setbestellingstatus (pbestellingkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER);
   PROCEDURE setbestelopdrstatus (pbestelopdrkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER);
   PROCEDURE updatebestellingstatus (pbestelling_key IN NUMBER, user_key IN NUMBER);
   PROCEDURE updatebestelopdrstatus (pbestelopdr_key IN NUMBER, user_key IN NUMBER);
   PROCEDURE notifybackoffice (pbeskey IN NUMBER);
   PROCEDURE notifybesgoedkeurders (pbeskey IN NUMBER);
   PROCEDURE acceptopdracht (pbestelopdr_key IN NUMBER, user_key IN NUMBER, presulttext IN VARCHAR2);
   PROCEDURE rejectopdracht (pbestelopdr_key IN NUMBER, user_key IN NUMBER, presulttext IN VARCHAR2);
   FUNCTION bestelopdr_tooltip (besopdrkey IN NUMBER) RETURN VARCHAR2;
   FUNCTION bessprintf (ps IN varchar2, pbes_bestelling_key IN number, pbes_discipline IN VARCHAR2)
      RETURN varchar2;
   FUNCTION opdrsprintf (ps IN varchar2, pbes_bestelopdr_key IN number)
      RETURN varchar2;
END bes;
/

CREATE OR REPLACE PACKAGE BODY bes
AS

   -- Deze functie moet aan de hand van de flags prijsinfo leveren van het artikel op pdate
   -- en zonder pdate is dat sysdate.
   -- Gekozen voor deze generieke functie omdat het algoritme voor alle variaties gelijk is
   -- en zo kunnen we de source eenmalig houden. Wordt normaal niet van buitenaf aangeroepen.
   -- Under construction. Gedachte (bitwise flags)
   --   8: ?
   --   4: ?
   --   2: inkoopprijs
   --   1: prijs (brutoprijs)
   FUNCTION getsrtdeelprijsinfo (pbes_srtdeel_key IN NUMBER, pdate IN DATE, pflags IN NUMBER)
      RETURN NUMBER
   AS
    ldate DATE;
    lsrtdeelprijskey bes_srtdeel_prijs.bes_srtdeel_prijs_key%TYPE;
    lprijs bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
    linkprijs bes_srtdeel_prijs.bes_srtdeel_prijs_inkprijs%TYPE;
   BEGIN
      -- voor vervallen artikelen nemen we de prijs ttv vervallen
      -- we halen er iets vanaf (anderhalve minuut) om de prijs VOOR de einddatum te krijgen
      SELECT bes_srtdeel_verwijder-0.001
        INTO ldate
        FROM bes_srtdeel
       WHERE bes_srtdeel_key = pbes_srtdeel_key;

      -- voor actieve artikelen pakken we meegegeven datum of anders vandaag
      IF ldate IS NULL
      THEN
        ldate := SYSDATE;  -- default vandaag indien niet verwijderd (meestal)
      END IF;
      IF pdate IS NOT NULL
      THEN
        ldate := LEAST(pdate, ldate);  -- maar een meegegeven datum overruled alleen als artikel actueel is of datum voor de vervaldatum ligt
      END IF;

      -- Vind de meest recentste prijs. Bij meerdere records de meest recente prijs pakken
      SELECT   MAX(sdp.bes_srtdeel_prijs_key)
        INTO   lsrtdeelprijskey
        FROM   bes_srtdeel_prijs sdp
       WHERE   COALESCE (sdp.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999) > ldate AND sdp.bes_srtdeel_key = pbes_srtdeel_key
                  AND NOT EXISTS
                     (SELECT   ''
                        FROM   bes_srtdeel_prijs sdp1
                       WHERE COALESCE (sdp1.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999) > ldate
                               AND sdp1.bes_srtdeel_key = pbes_srtdeel_key
                               AND COALESCE(sdp1.bes_srtdeel_prijs_vervaldatum, SYSDATE+999) < COALESCE (sdp.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999));

      IF lsrtdeelprijskey IS NULL
      THEN
        RETURN NULL;
      END IF;


      SELECT   sdp.bes_srtdeel_prijs_prijs, sdp.bes_srtdeel_prijs_inkprijs
        INTO   lprijs, linkprijs
        FROM   bes_srtdeel_prijs sdp
       WHERE   sdp.bes_srtdeel_prijs_key = lsrtdeelprijskey;

      IF pflags = 1
      THEN
        RETURN lprijs;
      ELSE  -- kan nu nog alleen maar 2 zijn, dus
        RETURN linkprijs;
      END IF;
   END;

   -- Levert de actuele (standaard)prijs van artikel pbes_srtdeel_key op datum pdate
   -- Als pdatum leeg is, dan wordt de prijs van vandaag geleverd
   -- Als er geen geldende prijs gevonden wordt, wordt NULL opgeleverd
   -- De actuele prijs is de prijs dit het spoedigst vervalt, waarbij de prijs
   -- zonder een vervaldatum ongeveer als oneindig geldig wordt behandeld.
   -- Moeten ff kijken of we zo'n functie voor elke prijs moeten hebben, of dat we wat
   -- kunnen combineren. We willen deze liever niet 5x aan hoeven te roepen voor
   -- een artikel om alle prijzen te weten. Dus evt optimalisatie kandidaat, maar hoe?
   FUNCTION getsrtdeelprijs (pbes_srtdeel_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER
   AS
   BEGIN
     RETURN bes.getsrtdeelprijsinfo (pbes_srtdeel_key, pdate, 1);
   END;

   FUNCTION getsrtdeelinkprijs (pbes_srtdeel_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER
   AS
   BEGIN
     RETURN bes.getsrtdeelprijsinfo (pbes_srtdeel_key, pdate, 2);
   END;

   FUNCTION getsrtprodprijs (pbes_srtprod_key IN NUMBER, pdate IN DATE)
      RETURN NUMBER
   AS
    ldate DATE;
    lprijs bes_srtprod_prijs.bes_srtprod_prijs_prijs%TYPE;
   BEGIN
      ldate := SYSDATE;  -- default
      IF pdate IS NOT NULL
      THEN
        ldate := pdate;
      END IF;
      BEGIN
        SELECT   sdp.bes_srtprod_prijs_prijs
          INTO   lprijs
          FROM   bes_srtprod_prijs sdp
         WHERE   COALESCE (sdp.bes_srtprod_prijs_vervaldatum, SYSDATE + 999) > ldate AND sdp.bes_srtprod_key = pbes_srtprod_key
                    AND NOT EXISTS
                       (SELECT   ''
                          FROM   bes_srtprod_prijs sdp1
                         WHERE COALESCE (sdp1.bes_srtprod_prijs_vervaldatum, SYSDATE + 999) > ldate
                                 AND sdp1.bes_srtprod_key = pbes_srtprod_key
                                 AND COALESCE(sdp1.bes_srtprod_prijs_vervaldatum, SYSDATE+999) < COALESCE (sdp.bes_srtprod_prijs_vervaldatum, SYSDATE + 999));
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN NULL;
      END;
      RETURN lprijs;
   END;







   FUNCTION calcartikelkortingsprijs (pbes_srtdeel_key IN NUMBER, pbestelaantal IN NUMBER)
      RETURN NUMBER
   AS
      lstaffeltabelkey bes_staffeltabel.bes_staffeltabel_key%TYPE;
      lprijs bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
      lstaffeltype bes_staffeltabel.fac_typestaffel_key%TYPE;
      lstaffelkorting bes_staffel.bes_staffel_korting%TYPE;
      lkortingsprijs NUMBER;
   BEGIN
      -- Levert de stuksprijs inclusief (eventuele) korting
      ----   aantal -> srtdeel/srtgroep.staffel -> stuksprijs incl korting = bes_bestelopdr_item_prijs
      -- merk op: deze staffel is op aantallen (niet op prijs)
      -- Check of er een staffel geldt voor dit artikel
      -- Als het een groepstaffel is, tel dan de overige artikelen in deze bestelopdracht met dezelfde staffel en bepaal het toepasselijke interval
      -- Als het geen groepstaffel is, bepaal dan het toepasselijke interval

      BEGIN
         SELECT   sd.bes_staffeltabel_key,
                  bes.getsrtdeelprijs (pbes_srtdeel_key, NULL) bes_srtdeel_prijs,
                  st.fac_typestaffel_key
           INTO   lstaffeltabelkey,
                  lprijs,
                  lstaffeltype
           FROM   bes_srtdeel sd,
                  bes_staffeltabel st
          WHERE   sd.bes_staffeltabel_key = st.bes_staffeltabel_key
            AND   sd.bes_srtdeel_key = pbes_srtdeel_key;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN lprijs;
      END;

      -- Vindt staffelrecord; zie(!) opmerkingen bij prs_staffel in bes.calcopdrachtkorting.
      BEGIN
         SELECT   COALESCE(MIN(bes_staffel_korting), 0)
           INTO   lstaffelkorting
           FROM   bes_staffel s1
          WHERE   s1.bes_staffeltabel_key = lstaffeltabelkey
                  AND (s1.bes_staffel_grenswaarde > pbestelaantal OR s1.bes_staffel_grenswaarde IS NULL)
                  AND NOT EXISTS
                        (SELECT   'X'
                           FROM   bes_staffel s2
                          WHERE       s2.bes_staffeltabel_key = lstaffeltabelkey
                                  AND s2.bes_staffel_grenswaarde < s1.bes_staffel_grenswaarde
                                  AND (s2.bes_staffel_grenswaarde > pbestelaantal OR s2.bes_staffel_grenswaarde IS NULL));
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN lprijs;
      END;

      IF lstaffeltype = 1
      THEN
         lkortingsprijs := (100 - lstaffelkorting)/100 * lprijs;
      END IF;

      IF lstaffeltype = 2
      THEN
         lkortingsprijs := lprijs - lstaffelkorting / pbestelaantal;
      END IF;

      IF lstaffeltype = 3
      THEN
         lkortingsprijs := lprijs - lstaffelkorting;
      END IF;

      RETURN lkortingsprijs;
   END;

   PROCEDURE calcopdrachtbedragkorting (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER,
                                        pkortingsbedrag OUT NUMBER, pkorting OUT NUMBER)
   AS
      lkorting prs_staffel.prs_staffel_korting%TYPE;                                                       -- percentage
      lkortingsbedrag NUMBER;
   BEGIN
      -- De staffeltabel bevat intervallen waarvan de bovengrens is opgenomen
      -- bijvoorbeeld
      -- 10 -> 1%
      -- 20 -> 2%
      -- 50 -> 5%
      -- Dan is 30 (euro) tussen 20 en 50 en geldt 5% korting
      -- Je moet dus het laagste hogere record vinden. Voor de bovengrens (hooogste staffel) is de grenswaarde NULL
      -- ATTENTIE: Nu wordt de laagste *korting* gekozen indien je in de hoogste staffel zit, terwijl je
      --           de laagste grenswaarde moet pakken. Levert nu de verkeerde waarde op in het rare geval dat
      --           de korting *lager* wordt als je in de hoogste staffel komt, bijvoorbeeld
      --           bij tot10000 artikelen 30% korting, en boven10000 25%. Aanname om technische redenen, maar mocht
      --           er een verrassend probleem optreden, is dit alvast de tip.
      SELECT   COALESCE(MIN(prs_staffel_korting), 0)
        INTO   lkorting
        FROM   prs_staffel s1
       WHERE   (prs_staffel_grenswaarde > pbrutoopdrachtbedrag OR s1.prs_staffel_grenswaarde IS NULL) --s2.prs_staffel_grenswaarde IS NULL)
               AND NOT EXISTS
                     (SELECT   'X'
                        FROM   prs_staffel s2
                       WHERE       s1.prs_bedrijf_key = s2.prs_bedrijf_key
                               AND s2.prs_staffel_grenswaarde < s1.prs_staffel_grenswaarde
                               AND (s2.prs_staffel_grenswaarde > pbrutoopdrachtbedrag OR s2.prs_staffel_grenswaarde IS NULL))
               AND prs_bedrijf_key = pprs_bedrijf_key
               AND pbrutoopdrachtbedrag > 0;

      lkortingsbedrag := (lkorting / 100) * pbrutoopdrachtbedrag;

--     RETURN lkortingsbedrag;
      pkortingsbedrag := lkortingsbedrag;
      pkorting := lkorting;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
--         RETURN 0;
      pkortingsbedrag := 0;
      pkorting := 0;
   END;

   FUNCTION calcopdrachtkorting (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER)
      RETURN NUMBER
   AS
      lkorting prs_staffel.prs_staffel_korting%TYPE;                                                       -- percentage
      lkortingsbedrag NUMBER;
   BEGIN
     BES.calcopdrachtbedragkorting(pprs_bedrijf_key, pbrutoopdrachtbedrag, lkortingsbedrag, lkorting);
     RETURN lkorting;
   END;

   FUNCTION calcopdrachtkortingbedrag (pprs_bedrijf_key IN NUMBER, pbrutoopdrachtbedrag IN NUMBER)
      RETURN NUMBER
   AS
      lkorting prs_staffel.prs_staffel_korting%TYPE;                                                       -- percentage
      lkortingsbedrag NUMBER;
   BEGIN
     BES.calcopdrachtbedragkorting(pprs_bedrijf_key, pbrutoopdrachtbedrag, lkortingsbedrag, lkorting);
     RETURN lkortingsbedrag;
   END;

   FUNCTION calcbesartikelkortingsprijs (pbes_bestelling_item_key IN NUMBER, ppunchout IN NUMBER)
      RETURN NUMBER
   AS
      lstaffelgroep bes_staffeltabel.bes_staffeltabel_groep%TYPE;
      lstaffeltabelkey bes_staffeltabel.bes_staffeltabel_key%TYPE;
      laanvraagprijs  bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
      lcatalogusprijs bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
      lprijs          bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
      lstaffeltype bes_staffeltabel.fac_typestaffel_key%TYPE;
      lstaffelkorting bes_staffel.bes_staffel_korting%TYPE;
      lkortingsprijs NUMBER;
      laantalbesteld NUMBER;
   BEGIN
      -- Levert de stuksprijs inclusief (eventuele) korting
      ----   aantal -> srtdeel/srtgroep.staffel -> stuksprijs incl korting = bes_bestelopdr_item_prijs
      -- merk op: deze staffel is op aantallen (niet op prijs)
      -- Check of er een staffel geldt voor dit artikel
      -- Als het een groepstaffel is, tel dan de overige artikelen in deze bestelopdracht met dezelfde staffel en bepaal het toepasselijke interval
      -- Als het geen groepstaffel is, bepaal dan het toepasselijke interval

      BEGIN
         SELECT   st.bes_staffeltabel_groep,
                  sd.bes_staffeltabel_key,
                  st.fac_typestaffel_key,
                  bi.bes_bestelling_item_brutoprijs,
                  bes.getsrtdeelprijs (sd.bes_srtdeel_key, NULL) bes_srtdeel_prijs,
                  bi.bes_bestelling_item_aantal
           INTO   lstaffelgroep,
                  lstaffeltabelkey,
                  lstaffeltype,
                  laanvraagprijs,
                  lcatalogusprijs,
                  laantalbesteld
           FROM   bes_srtdeel sd, bes_staffeltabel st, bes_bestelling_item bi
          WHERE   sd.bes_staffeltabel_key = st.bes_staffeltabel_key
            AND   sd.bes_srtdeel_key = bi.bes_srtdeel_key
            AND   bi.bes_bestelling_item_key = pbes_bestelling_item_key;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            BEGIN
               SELECT   bi.bes_bestelling_item_brutoprijs,
                        bes.getsrtdeelprijs (sd.bes_srtdeel_key, NULL) bes_srtdeel_prijs
                 INTO   laanvraagprijs,
                        lcatalogusprijs
                 FROM   bes_srtdeel sd, bes_bestelling_item bi
                WHERE   sd.bes_srtdeel_key = bi.bes_srtdeel_key
                  AND   bi.bes_bestelling_item_key = pbes_bestelling_item_key;
               IF ppunchout = 1
               THEN
                  RETURN laanvraagprijs;
               ELSE
                  RETURN lcatalogusprijs;
               END IF;
            END;
      END;
      IF ppunchout = 1
      THEN
         lprijs := laanvraagprijs;
      ELSE
         lprijs := lcatalogusprijs;
      END IF;

      IF lstaffelgroep = 1
      THEN
         SELECT   SUM (bi.bes_bestelling_item_aantal)
           INTO   laantalbesteld
           FROM   bes_bestelling_item bi, bes_srtdeel sd
          WHERE   sd.bes_srtdeel_key = bi.bes_srtdeel_key
            AND   sd.bes_staffeltabel_key = lstaffeltabelkey
            AND   bi.bes_bestelling_item_key = pbes_bestelling_item_key;
      END IF;

      -- Vindt staffelrecord; zie(!) opmerkingen bij prs_staffel in bes.calcopdrachtkorting.
      BEGIN
         SELECT   COALESCE(MIN(bes_staffel_korting), 0)
           INTO   lstaffelkorting
           FROM   bes_staffel s1
          WHERE   s1.bes_staffeltabel_key = lstaffeltabelkey
                  AND (s1.bes_staffel_grenswaarde > laantalbesteld OR s1.bes_staffel_grenswaarde IS NULL)
                  AND NOT EXISTS
                        (SELECT   'X'
                           FROM   bes_staffel s2
                          WHERE       s2.bes_staffeltabel_key = lstaffeltabelkey
                                  AND s2.bes_staffel_grenswaarde < s1.bes_staffel_grenswaarde
                                  AND (s2.bes_staffel_grenswaarde > laantalbesteld OR s2.bes_staffel_grenswaarde IS NULL));
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN lprijs;
      END;

      IF lstaffeltype = 1
      THEN
         lkortingsprijs := (100 - lstaffelkorting)/100 * lprijs;
      END IF;

      IF lstaffeltype = 2
      THEN
         lkortingsprijs := lprijs - lstaffelkorting / laantalbesteld;
      END IF;

      IF lstaffeltype = 3
      THEN
         lkortingsprijs := lprijs - lstaffelkorting;
      END IF;

      RETURN lkortingsprijs;
   END;

   FUNCTION calcbesopdrachtkorting (pbes_bestelopdr_key IN NUMBER, pautoupdate IN NUMBER)
      RETURN NUMBER
   AS
      lbrutoopdrachtbedrag NUMBER;
      lkorting prs_staffel.prs_staffel_korting%TYPE;                                                       -- percentage
      lstaffelkortingbedrag NUMBER;
      lkortingsbedrag NUMBER;
   BEGIN
      ----   som van de bes_bestelopdr_item_prijs > bedrijf.staffel -> kortingspercentage * (sum aantal * bes_bestelopdr_item_prijs) = bes_bestelopdr_korting
      -- merk op: deze staffel is op prijs (niet op aantallen)
      SELECT   COALESCE(SUM (bes_bestelopdr_item_prijs * bes_bestelopdr_item_aantal), 0)
        INTO   lbrutoopdrachtbedrag
        FROM   bes_bestelopdr_item
       WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;

      -- De staffeltabel bevat intervallen waarvan de bovengrens is opgenomen
      -- bijvoorbeeld
      -- 10 -> 1%
      -- 20 -> 2%
      -- 50 -> 5%
      -- Dan is 30 (euro) tussen 20 en 50 en geldt 5% korting
      -- Je moet dus het laagste hogere record vinden. Voor de bovengrens (hooogste staffel) is de grenswaarde NULL
      -- ATTENTIE: Nu wordt de laagste *korting* gekozen indien je in de hoogste staffel zit, terwijl je
      --           de laagste grenswaarde moet pakken. Levert nu de verkeerde waarde op in het rare geval dat
      --           de korting *lager* wordt als je in de hoogste staffel komt, bijvoorbeeld
      --           bij tot10000 artikelen 30% korting, en boven10000 25%. Aanname om technische redenen, maar mocht
      --           er een verrassend probleem optreden, is dit alvast de tip.
      SELECT   COALESCE(MIN(prs_staffel_korting), 0)
        INTO   lkorting
        FROM   prs_staffel s1
       WHERE   (prs_staffel_grenswaarde > lbrutoopdrachtbedrag OR s1.prs_staffel_grenswaarde IS NULL)
               AND NOT EXISTS
                     (SELECT   'X'
                        FROM   prs_staffel s2
                       WHERE       s1.prs_bedrijf_key = s2.prs_bedrijf_key
                               AND s2.prs_staffel_grenswaarde < s1.prs_staffel_grenswaarde
                               AND (s2.prs_staffel_grenswaarde > lbrutoopdrachtbedrag OR s2.prs_staffel_grenswaarde IS NULL))
               AND prs_bedrijf_key = (SELECT   prs_bedrijf_key
                                        FROM   bes_bestelopdr
                                       WHERE   bes_bestelopdr_key = pbes_bestelopdr_key);

      lkortingsbedrag := (lkorting / 100) * lbrutoopdrachtbedrag;

      IF pautoupdate > 0
      THEN
         UPDATE   bes_bestelopdr
            SET   bes_bestelopdr_korting = lkortingsbedrag
          WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;
      END IF;

      RETURN lkortingsbedrag;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN 0;
   END;

   FUNCTION calcbesopdrachtkosten (pbes_bestelopdr_key IN NUMBER, pautoupdate IN NUMBER)
      RETURN NUMBER
   AS
      lbrutoopdrachtbedrag NUMBER;
      lopdrachtkorting bes_bestelopdr.bes_bestelopdr_korting%TYPE;
      lfrancogrens prs_bedrijf.prs_bedrijf_bes_limiet%TYPE;
      lverzendkosten prs_bedrijf.prs_bedrijf_bes_kosten%TYPE;
   BEGIN
      -- berekent de bijkomende kosten van een bestelopdracht, meestal de verzendkosten
      -- die alleen worden berekend onder een bepaald opdrachtbedrag (leveranciersafhankelijk, inclusief regelkortingen en opdrachtkorting)
      ----   som van de bes_bestelopdr_item_prijs > prs_bedrijf_bes_limiet -> prs_bedrijf_bes_kosten = bes_bestelopdr_levkosten
      -- als iets niet wordt gevonden, wordt 0 geleverd (geen kosten); je zou error kunnen overwegen.
      SELECT   COALESCE(SUM (bes_bestelopdr_item_prijs * bes_bestelopdr_item_aantal), 0)
        INTO   lbrutoopdrachtbedrag
        FROM   bes_bestelopdr_item
       WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;

      SELECT   COALESCE(bes_bestelopdr_korting, 0)
        INTO   lopdrachtkorting
        FROM   bes_bestelopdr
       WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;

      SELECT   COALESCE(prs_bedrijf_bes_limiet, 0), COALESCE(prs_bedrijf_bes_kosten, 0)
        INTO   lfrancogrens, lverzendkosten
        FROM   prs_bedrijf
       WHERE   prs_bedrijf_key = (SELECT   prs_bedrijf_key
                                    FROM   bes_bestelopdr
                                   WHERE   bes_bestelopdr_key = pbes_bestelopdr_key);

      IF lbrutoopdrachtbedrag - lopdrachtkorting >= lfrancogrens
      THEN
         lverzendkosten := 0;
      END IF;

      IF pautoupdate > 0
      THEN
         UPDATE   bes_bestelopdr
            SET   bes_bestelopdr_levkosten = lverzendkosten
          WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;
      END IF;

      RETURN lverzendkosten;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN 0;
   END;

   -- Zorg dat de prijs van het artikel de gegeven prijs wordt. Als dat al zo is, verandert er niets
   PROCEDURE upsert_srtdeel_prijs (p_bes_srtdeel_key        IN NUMBER,
                                   p_bes_srtdeel_prijs      IN NUMBER,
                                   p_bes_srtdeel_inkprijs   IN NUMBER
                                  )
   IS
      v_currentprijs bes_srtdeel_prijs.bes_srtdeel_prijs_prijs%TYPE;
      v_currentinkprijs bes_srtdeel_prijs.bes_srtdeel_prijs_inkprijs%TYPE;
      lneedchange BOOLEAN := FALSE;
      loldkey bes_srtdeel_prijs.bes_srtdeel_prijs_key%TYPE;
   BEGIN
      -- Is er al een vigerende prijs bekend en is dat dezelfde?
      v_currentprijs := bes.getsrtdeelprijs (p_bes_srtdeel_key, NULL);
      v_currentinkprijs := bes.getsrtdeelinkprijs (p_bes_srtdeel_key, NULL);

      IF    (v_currentprijs IS NULL AND p_bes_srtdeel_prijs IS NOT NULL)
         OR (v_currentinkprijs IS NULL AND p_bes_srtdeel_inkprijs IS NOT NULL)
         OR (v_currentprijs IS NOT NULL AND p_bes_srtdeel_prijs IS NULL)
         OR (v_currentinkprijs IS NOT NULL AND p_bes_srtdeel_inkprijs IS NULL)
         OR v_currentprijs <> p_bes_srtdeel_prijs
         OR v_currentinkprijs <> p_bes_srtdeel_inkprijs
      THEN
         lneedchange := TRUE;
      END IF;

      IF lneedchange
      THEN
         -- Er was nog geen prijs of een afwijkende prijs: vanaf nu geldt deze nieuwe prijs
         INSERT INTO bes_srtdeel_prijs (bes_srtdeel_key, bes_srtdeel_prijs_prijs, bes_srtdeel_prijs_inkprijs
                                       )
           VALUES   (p_bes_srtdeel_key, p_bes_srtdeel_prijs, p_bes_srtdeel_inkprijs
                    );                                                                                 -- geen einddatum

         IF v_currentprijs IS NOT NULL OR v_currentinkprijs IS NOT NULL
         THEN
            SELECT   MIN (bes_srtdeel_prijs_key)
              INTO   loldkey
              FROM   bes_srtdeel_prijs sdp
             WHERE       bes_srtdeel_key = p_bes_srtdeel_key
                     AND (bes_srtdeel_prijs_vervaldatum IS NULL OR bes_srtdeel_prijs_vervaldatum > SYSDATE)
                     AND COALESCE (bes_srtdeel_prijs_prijs, -99) = COALESCE (v_currentprijs, -99)
                     AND COALESCE (bes_srtdeel_prijs_inkprijs, -99) = COALESCE (v_currentinkprijs, -99)
                     AND NOT EXISTS
                           (SELECT   ''
                              FROM   bes_srtdeel_prijs sdp1
                             WHERE   COALESCE (sdp1.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999) > SYSDATE
                                     AND sdp1.bes_srtdeel_key = p_bes_srtdeel_key
                                     AND COALESCE (sdp1.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999) <
                                           COALESCE (sdp.bes_srtdeel_prijs_vervaldatum, SYSDATE + 999));

            -- Er was al een prijs geregistreerd: invalideer de oude prijs
            UPDATE   bes_srtdeel_prijs
               SET   bes_srtdeel_prijs_vervaldatum = SYSDATE - 1
             WHERE   bes_srtdeel_prijs_key = loldkey;
         END IF;
      -- ELSE de juiste prijs was al geregistreerd
      END IF;
   -- De actuele prijs is nu geregistreerd
   END;

  // was: bes_check_or_create_item
  // Maakt een artikel (bes_srtdeel) aan binnen een reeds bestaande catalogus (discipline), waarbij zonodig nog de groep
  // (srtgroep) wordt aangemaakt. Deze wordt aangeroepen bij een punchout bestelling, en om te voorkomen dat dergelijke
  // artikelen rechtstreeks worden besteld wordt direct de verwijderdatum ook gezet. Dat je het weet.
   PROCEDURE upsert_srtdeel (p_ins_discipline_key          IN NUMBER,
                             p_bes_srtgroep_omschrijving   IN VARCHAR2,                                  -- VARCHAR2(60)
                             p_bes_srtdeel_omschrijving    IN VARCHAR2,                                 -- VARCHAR2 (60)
                             p_bes_srtdeel_prijs           IN NUMBER,                                    -- NUMBER (8,2)
                             p_bes_srtdeel_btw             IN NUMBER,                                      -- NUMBER (3)
                             p_bes_srtdeel_eenheid         IN VARCHAR2,                                 -- VARCHAR2 (30)
                             p_bes_srtdeel_nr              IN VARCHAR2,                                 -- VARCHAR2 (32)
                             p_prs_bedrijf_key             IN NUMBER,
                             p_bes_srtdeel_vervaldatum     IN DATE,
                             p_bes_srtdeel_image           IN VARCHAR2,                                -- VARCHAR2 (255)
                             p_bes_srtdeel_veelvoud        IN NUMBER,                                      -- NUMBER (6)
                             p_bes_srtdeel_opmerking       IN VARCHAR2,                               -- VARCHAR2 (2000)
                             p_bes_srtdeel_details_loc     IN VARCHAR2  DEFAULT NULL                   -- VARCHAR2 (255)
                            )
   AS
      v_bes_srtgroep_key NUMBER (10);
      v_bes_srtdeel_key NUMBER (10);
      v_prs_bedrijf_key NUMBER (10);
   BEGIN
      BEGIN
         SELECT   bes_srtgroep_key
           INTO   v_bes_srtgroep_key
           FROM   bes_srtgroep
          WHERE   ins_discipline_key = p_ins_discipline_key
                  AND UPPER (bes_srtgroep_omschrijving) = UPPER (p_bes_srtgroep_omschrijving);
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            v_bes_srtgroep_key := -1;
      END;

      IF v_bes_srtgroep_key = -1
      THEN
         INSERT INTO bes_srtgroep (ins_discipline_key, bes_srtgroep_omschrijving
                                  )
           VALUES   (p_ins_discipline_key, p_bes_srtgroep_omschrijving
                    );

         SELECT   bes_srtgroep_key
           INTO   v_bes_srtgroep_key
           FROM   bes_srtgroep
          WHERE   ins_discipline_key = p_ins_discipline_key
                  AND UPPER (bes_srtgroep_omschrijving) = UPPER (p_bes_srtgroep_omschrijving);
      END IF;

      IF p_prs_bedrijf_key = -1
      THEN
         BEGIN
            SELECT   bes_disc_params_punch_bedr_key
              INTO   v_prs_bedrijf_key
              FROM   bes_disc_params
             WHERE   bes_ins_discipline_key = p_ins_discipline_key;
         EXCEPTION
            WHEN NO_DATA_FOUND
            THEN
               v_prs_bedrijf_key := -1;
         END;
      ELSE
         v_prs_bedrijf_key := p_prs_bedrijf_key;
      END IF;

      SELECT   MAX(bes_srtdeel_key)
        INTO   v_bes_srtdeel_key
        FROM   bes_srtdeel sd
       WHERE       bes_srtgroep_key = v_bes_srtgroep_key
               AND bes_srtdeel_nr = p_bes_srtdeel_nr
               AND bes_srtdeel_omschrijving = p_bes_srtdeel_omschrijving
               AND bes_srtdeel_btw = p_bes_srtdeel_btw
               AND COALESCE (bes_srtdeel_eenheid, 'Geen') = COALESCE (p_bes_srtdeel_eenheid, 'Geen')
               AND prs_bedrijf_key = v_prs_bedrijf_key
               AND bes_srtdeel_veelvoud = p_bes_srtdeel_veelvoud
               AND COALESCE (bes_srtdeel_opmerking, 'Geen') = COALESCE (p_bes_srtdeel_opmerking, 'Geen');
      IF v_bes_srtdeel_key IS NULL THEN
            v_bes_srtdeel_key := -1;
      END IF;

      COMMIT;

      IF v_bes_srtdeel_key = -1
      THEN
         SELECT   bes_s_bes_srtdeel_key.NEXTVAL INTO v_bes_srtdeel_key FROM DUAL;

         INSERT INTO bes_srtdeel (
                                     bes_srtdeel_key,
                                     bes_srtgroep_key,
                                     bes_srtdeel_omschrijving,
                                     bes_srtdeel_btw,
                                     bes_srtdeel_eenheid,
                                     bes_srtdeel_nr,
                                     prs_bedrijf_key,
                                     bes_srtdeel_vervaldatum,
                                     bes_srtdeel_image,
                                     bes_srtdeel_veelvoud,
                                     bes_srtdeel_verwijder,
                                     bes_srtdeel_opmerking,
                                     bes_srtdeel_details_loc
                    )
           VALUES   (
                        v_bes_srtdeel_key,
                        v_bes_srtgroep_key,
                        p_bes_srtdeel_omschrijving,
                        p_bes_srtdeel_btw,
                        p_bes_srtdeel_eenheid,
                        p_bes_srtdeel_nr,
                        v_prs_bedrijf_key,
                        p_bes_srtdeel_vervaldatum,
                        p_bes_srtdeel_image,
                        p_bes_srtdeel_veelvoud,
                        SYSDATE,
                        p_bes_srtdeel_opmerking,
                        p_bes_srtdeel_details_loc
                    );
      ELSE
        -- Bestaand artikel, maar de verwijdatum moet wel ververst worden
        -- Anders gaat de prijsbepaling niet goed
        UPDATE bes_srtdeel
           SET bes_srtdeel_verwijder = SYSDATE
         WHERE bes_srtdeel_key = v_bes_srtdeel_key;
      END IF;

      -- Verwerk de prijs
      bes.upsert_srtdeel_prijs (v_bes_srtdeel_key, p_bes_srtdeel_prijs, NULL);   -- TODO: waar komt die inkoopprijs vandaan?

   END;

    -- Oude opdracht verwijderen, nieuwe aanmaken
    PROCEDURE changeorders (i_userkey IN NUMBER, bes_key IN NUMBER)
    AS
     orgopdrkey   bes_bestelopdr.bes_bestelopdr_key%TYPE;
    BEGIN
        SELECT MAX (boi.bes_bestelopdr_key)
          INTO orgopdrkey
          FROM bes_bestelopdr_item boi, bes_bestelling_item bi
         WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key
               AND bi.bes_bestelling_key = bes_key;

        DELETE FROM bes_bestelopdr_item
         WHERE bes_bestelopdr_key = orgopdrkey;

        DELETE FROM bes_bestelopdr
         WHERE bes_bestelopdr_key = orgopdrkey;

        bes.makeorders (i_userkey, bes_key);
    END;

    PROCEDURE makeorders (i_userkey IN NUMBER, bes_key IN NUMBER)
    AS
      lfound                    BOOLEAN;
      niveau                    NUMBER (10);
      afd_key                   NUMBER (10);
      afd_key_temp              NUMBER (10);
      link_key                  NUMBER (10);
      lbord_key                 NUMBER (10);
      lbord_id                  bes_bestelopdr.bes_bestelopdr_id%TYPE;
      i_cnt_sum                 NUMBER (5);
      i_price_sum               NUMBER (8, 2);
      current_leverancier_key   NUMBER (10);
      aantalopdrachtregels      NUMBER;
      factura_key               mld_adres.mld_adres_key%TYPE;
      bedrijf_email             prs_bedrijf.prs_bedrijf_email%TYPE;
      bedrijf_telefoon2         prs_bedrijf.prs_bedrijf_telefoon2%TYPE;
      l_item_brutoprijs         bes_bestelopdr_item.bes_bestelopdr_item_brutoprijs%TYPE;
      l_item_prijs              bes_bestelopdr_item.bes_bestelopdr_item_prijs%TYPE;
      l_item_inkprijs           bes_bestelopdr_item.bes_bestelopdr_item_inkprijs%TYPE;
      besopdrachtkorting        NUMBER (8, 2);
      besopdrachtkosten         NUMBER (8, 2);
      bedrijfvolgnr             NUMBER (3);
      CURSOR tebestellen
      IS
        SELECT bd.prs_bedrijf_key,
               bd.prs_bedrijf_naam,
               s.bes_srtdeel_omschrijving,
               NVL (s.bes_srtdeel_eenheid, '') bes_srtdeel_eenheid,
               bi.bes_bestelling_item_brutoprijs,
               bes.getsrtdeelprijs (s.bes_srtdeel_key, NULL) bes_srtdeel_prijs,
               s.bes_srtdeel_key,
               bi.bes_bestelling_item_key,
               bi.bes_bestelling_item_aantal,
               NVL (b.mld_adres_key_lev, abd.mld_adres_key_lev) mld_adres_key_lev,
               p.prs_afdeling_key,
               abd.mld_adres_key_fac,
               bi.bes_bestelling_item_inkprijs,
               bes.getsrtdeelinkprijs (s.bes_srtdeel_key, NULL) bes_srtdeel_inkprijs,
               b.bes_bestelling_parentkey,
               b.prs_perslid_key,
               bdp.bes_disc_params_punchouturl,
               bdp.bes_disc_params_freeartikel
          FROM prs_bedrijf bd,
               bes_srtdeel s,
               bes_srtgroep g,
               bes_disc_params bdp,
               bes_bestelling_item bi,
               bes_bestelling b,
               prs_perslid p,
               prs_v_afdeling d,
               prs_bedrijf abd
         WHERE     abd.prs_bedrijf_key = d.prs_bedrijf_key
               AND p.prs_afdeling_key = d.prs_afdeling_key
               AND b.prs_perslid_key = p.prs_perslid_key
               AND bi.bes_bestelling_key = b.bes_bestelling_key
               AND g.ins_discipline_key = bdp.bes_ins_discipline_key
               AND s.bes_srtgroep_key = g.bes_srtgroep_key
               AND s.bes_srtdeel_key = bi.bes_srtdeel_key
               AND s.prs_bedrijf_key = bd.prs_bedrijf_key
               AND b.bes_bestelling_status IN (1, 2, 3, 4)   -- om dubbelen te vermijden
               AND b.bes_bestelling_key = bes_key
         ORDER BY 1, 7;
      BEGIN
        -- Maakt bestelopdrachten van bestelaanvragen
        current_leverancier_key := -1;
        bedrijfvolgnr := 0;
        FOR rec1 IN tebestellen
        LOOP
          --DBMS_OUTPUT.put_line ('Een regel');
          -- Moeten we van leverancier wisselen?
          IF current_leverancier_key <> rec1.prs_bedrijf_key
          THEN
            BEGIN
              --DBMS_OUTPUT.put_line ('Een nieuwe leverancier:' || TO_CHAR (rec1.prs_bedrijf_key));
              -- Bepaal het factuuradres. Deze kan binnen 1 aanvraag verschillen als er meerdere leveranciers betrokken zijn.
              -- Dit is het factuuradres van de leverancier indien gedefinieerd,
              -- en zo niet, dan het factuuradres van de afdeling (daarbij zover omhoog zoeken tot gevonden)
              -- van de aanvrager. Is die er niet, dan is het het factuuradres van het bedrijf van de aanvrager.
              -- Er zou geen factuuraders gevonden kunnen worden, dan blijft die gewoon leeg.
              -- Van de aanvrager:
              factura_key := rec1.mld_adres_key_fac;
              -- Van de leverancier:
              SELECT mld_adres_key_fac, prs_bedrijf_email, prs_bedrijf_telefoon2
                INTO factura_key, bedrijf_email, bedrijf_telefoon2
                FROM prs_bedrijf
               WHERE prs_bedrijf_key = rec1.prs_bedrijf_key AND mld_adres_key_fac IS NOT NULL;
            EXCEPTION
              WHEN NO_DATA_FOUND
              THEN
                -- Van de afdeling:
                SELECT a.niveau, a.prs_afdeling_key
                  INTO niveau, afd_key
                  FROM prs_v_aanwezigafdeling a
                 WHERE a.prs_afdeling_key = rec1.prs_afdeling_key;
                lfound := FALSE;
                WHILE (niveau >= 1 AND NOT lfound)
                LOOP
                  -- zoek kenmerk
                  BEGIN
                    SELECT prs_kenmerklink_waarde
                      INTO link_key
                      FROM prs_kenmerklink kl, prs_kenmerk k
                     WHERE kl.prs_kenmerk_key = k.prs_kenmerk_key
                       AND kl.prs_link_key = afd_key
                       AND k.prs_kenmerk_key = 6
                       AND kl.prs_kenmerklink_waarde IS NOT NULL;
                  EXCEPTION
                    WHEN NO_DATA_FOUND
                    THEN
                      link_key := NULL;
                  END;
                  IF link_key IS NULL
                  THEN   -- -- kenmerk factuuradres niet aanwezig, zoek parent afdeling
                    BEGIN
                      SELECT a.prs_afdeling_parentkey
                        INTO afd_key_temp
                        FROM prs_afdeling a
                       WHERE a.prs_afdeling_key = afd_key;
                      IF niveau != 1
                      THEN
                        afd_key := afd_key_temp;    -- als niveau=1 en geen kenmerk gevonden dan nog afd_key van niveau=1 nodig
                      END IF;
                      niveau := niveau - 1;
                    END;
                  ELSE
                    lfound := TRUE;     -- kenmerk aanwezig
                  END IF;
                END LOOP;
                IF link_key IS NOT NULL
                THEN
                  factura_key := link_key;
                END IF;
            END;
            -- factuuradres is bepaald, maak nu de opdracht aan
            IF current_leverancier_key <> -1
            THEN
               -- Afronden vorige opdracht
               UPDATE bes_bestelopdr
                  SET bes_bestelopdr_status = 3 -- JGL: stond hij hier nog niet op dan?
                WHERE bes_bestelopdr_key = lbord_key;
               fac.trackaction ('BES2NE',
                        lbord_key,
                        i_userkey,
                        NULL,
                        '');
               -- Bepaal opdrachtkorting en opdrachtkosten en sla deze op
               -- Met parameter 1 geven we aan dat de berekende waarde automaisch ook word opgeslagen
               besopdrachtkorting := bes.calcbesopdrachtkorting(lbord_key, 1);
               besopdrachtkosten := bes.calcbesopdrachtkosten(lbord_key, 1);
               UPDATE bes_bestelopdr
                  SET bes_bestelopdr_levkosten = besopdrachtkosten
                    , bes_bestelopdr_korting = besopdrachtkorting
                WHERE bes_bestelopdr_key = lbord_key;
            END IF;
            -- Op naar de volgende
            current_leverancier_key := rec1.prs_bedrijf_key;
            bedrijfvolgnr := bedrijfvolgnr + 1;
            SELECT bes_s_bes_bestelopdr_key.NEXTVAL
              INTO lbord_key
              FROM DUAL;
            -- UWVA#13420, als zichtbaar opdrachtnummer wordt het aanvraagnummer gebruikt
            -- Indien dit ooit anders moet, bv bundeling, dan moet alleen dit anders
            -- Met UWVA#21074 hanteren we voor mutaties toch hetzelfde opdrachtnummer, zodat
            -- de leverancier de link met het origineel kan vinden.
            lbord_id := TO_CHAR(COALESCE(rec1.bes_bestelling_parentkey, bes_key))||'/'|| bedrijfvolgnr;
            --DBMS_OUTPUT.put_line ('Bestelopdracht maken: ' || TO_CHAR (lbord_key));
            INSERT INTO bes_bestelopdr
                (bes_bestelopdr_key, bes_bestelopdr_status, prs_bedrijf_key,
                 bes_bestelopdr_datum, mld_adres_key_lev, mld_adres_key_fac,
                 prs_perslid_key,
                 bes_bestelopdr_id
                )
            VALUES (lbord_key, 3, rec1.prs_bedrijf_key,
                 SYSDATE, rec1.mld_adres_key_lev, factura_key,
                 rec1.prs_perslid_key,
                 lbord_id
                );
            aantalopdrachtregels := 0;
          END IF;
          --DBMS_OUTPUT.put_line ('Bestelregel maken: ' || TO_CHAR (aantalopdrachtregels + 1));
          -- Voor punchout gebruiken we de aanvraagprijzen, anders de catalogusprijzen (as was) voor
          -- bes_bestelling_item_brutoprijs / bes_bestelopdr_item_brutoprijs
          -- bes_bestelling_item_prijs      / bes_bestelopdr_item_prijs
          -- bes_bestelling_item_inkprijs   / bes_bestelopdr_item_inkprijs
          IF (rec1.bes_disc_params_punchouturl IS NOT NULL AND rec1.bes_disc_params_freeartikel = 0)
          THEN
            -- punchout
            --DBMS_OUTPUT.put_line ('Punchoutprijzen');
            l_item_brutoprijs  := rec1.bes_bestelling_item_brutoprijs;
            l_item_prijs       := bes.calcbesartikelkortingsprijs(rec1.bes_bestelling_item_key, 1);
            l_item_inkprijs    := rec1.bes_bestelling_item_inkprijs;
          ELSE
            --DBMS_OUTPUT.put_line ('Catalogusprijzen');
            l_item_brutoprijs  := rec1.bes_srtdeel_prijs;
            l_item_prijs       := bes.calcbesartikelkortingsprijs(rec1.bes_bestelling_item_key, 0);
            l_item_inkprijs    := rec1.bes_srtdeel_inkprijs;
          END IF;

          INSERT INTO bes_bestelopdr_item
              (bes_bestelopdr_item_key, bes_bestelopdr_item_posnr, bes_bestelopdr_key,
               bes_bestelopdr_item_aantal, bes_bestelopdr_item_aantalontv, bes_bestelopdr_item_omschrijv,
               bes_bestelopdr_item_brutoprijs, bes_bestelopdr_item_ontvangen, bes_bestelopdr_item_inkprijs,
               bes_bestelopdr_item_prijs
              )
          VALUES (bes_s_bes_bestelopdr_item_key.NEXTVAL, aantalopdrachtregels + 1, lbord_key,
               rec1.bes_bestelling_item_aantal, NULL, rec1.bes_srtdeel_omschrijving,
               l_item_brutoprijs, NULL, l_item_inkprijs,
               l_item_prijs
              );
          aantalopdrachtregels := aantalopdrachtregels + 1;
          UPDATE bes_bestelling_item
             SET bes_bestelopdr_item_key = bes_s_bes_bestelopdr_item_key.CURRVAL
           WHERE bes_bestelling_item_key = rec1.bes_bestelling_item_key;
        END LOOP;
        IF current_leverancier_key <> -1
        THEN
          -- Afronden vorige opdracht
          UPDATE bes_bestelopdr
             SET bes_bestelopdr_status = 3
           WHERE bes_bestelopdr_key = lbord_key;
          fac.trackaction ('BES2NE',
                    lbord_key,
                    i_userkey,
                    NULL,
                    '');
          -- Bepaal opdrachtkorting en opdrachtkosten en sla deze op
          -- Met parameter 1 geven we aan dat de berekende waarde automaisch ook word opgeslagen
          besopdrachtkorting := bes.calcbesopdrachtkorting(lbord_key, 1);
          besopdrachtkosten := bes.calcbesopdrachtkosten(lbord_key, 1);
          UPDATE bes_bestelopdr
             SET bes_bestelopdr_levkosten = besopdrachtkosten
               , bes_bestelopdr_korting = besopdrachtkorting
           WHERE bes_bestelopdr_key = lbord_key;
        END IF;
    END;

    PROCEDURE makecontract (bestelopdr_key IN NUMBER)
    AS
       cnt_rappel_abonnement     fac_setting.fac_setting_default%TYPE;
       bes_bestelling_prefix     fac_setting.fac_setting_default%TYPE;
       lbeschrijving             VARCHAR2 (50);
       lomschrijving             VARCHAR2 (2048);
       lopmerking                VARCHAR2 (4000);
       lcnt_nummer               VARCHAR2 (30);
       lcnt_disckey              bes_disc_params.bes_disc_params_cnt_disckey%TYPE;
       lprs_afdeling_key         prs_afdeling.prs_afdeling_key%TYPE;
       lprs_perslid_key          prs_perslid.prs_perslid_key%TYPE;
       lprs_perslid_key_voor     prs_perslid.prs_perslid_key%TYPE;
       lprs_contactpersoon_key   prs_contactpersoon.prs_contactpersoon_key%TYPE;
       lcnt_opzegtermijn         bes_disc_params.bes_disc_params_cnt_opzegterm%TYPE;
       lbedr_key                 NUMBER(10);
       ltotaal                   NUMBER(11,2);
       lprs_kostenplaats_key     prs_kostenplaats.prs_kostenplaats_key%TYPE;
       lcnt_key                  cnt_contract.cnt_contract_key%TYPE;
       looptijd_van              DATE;
       looptijd_tot              DATE;
       lfirst                    NUMBER;
       llast                     NUMBER;
       date_boolean              BOOLEAN;

       CURSOR artikelregels
       IS
           SELECT b.bes_bestelling_key,
                  bdp.bes_disc_params_cnt_disckey,
                  bdp.bes_disc_params_cnt_termijn,
                  bdp.bes_disc_params_cnt_opzegterm,
                  bsd.bes_srtdeel_nr,
                  bsd.bes_srtdeel_omschrijving,
                  p.prs_afdeling_key,
                  bsd.bes_srtdeel_opmerking,
                  bsd.prs_bedrijf_key,
                  b.bes_bestelling_leverdatum,
                  b.prs_kostenplaats_key,
                  b.prs_perslid_key,
                  b.prs_perslid_key_voor,
                  bi.bes_bestelling_item_prijs
                  * bi.bes_bestelling_item_aantal
                    totaal,
                  (SELECT MAX (pc.prs_contactpersoon_key) -- Neem de nieuwste contactpersoon
                     FROM prs_contactpersoon pc
                    WHERE pc.prs_bedrijf_key = bsd.prs_bedrijf_key
                      AND pc.prs_contactpersoon_verwijder IS NULL)
                    prs_contactpersoon
             FROM bes_bestelling b,
                  bes_bestelling_item bi,
                  bes_srtdeel bsd,
                  bes_srtgroep bsg,
                  bes_disc_params bdp,
                  prs_perslid p,
                  bes_bestelopdr_item boi
            WHERE b.bes_bestelling_key = bi.bes_bestelling_key
              AND bi.bes_srtdeel_key = bsd.bes_srtdeel_key
              AND bsd.bes_srtgroep_key = bsg.bes_srtgroep_key
              AND bsg.ins_discipline_key = bdp.bes_ins_discipline_key
              AND p.prs_perslid_key = b.prs_perslid_key
              AND bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key
              AND boi.bes_bestelopdr_key = bestelopdr_key
              ORDER BY bes_bestelling_item_key;
    BEGIN
      -- Maakt een contract aan bij een abonnement bestelling

      cnt_rappel_abonnement := fac.getsetting ('cnt_rappel_abonnement');
      bes_bestelling_prefix := fac.getsetting ('bes_bestelling_prefix');
      lbeschrijving := NULL;
      lomschrijving := NULL;
      lopmerking    := NULL;
      lfirst := 0;
      llast := 0;

      FOR artikel_rec IN artikelregels
      LOOP
         IF lfirst = 0
         THEN
            BEGIN
               -- Voor het aan te maken contract de gegevens van het eerste artikel pakken.
               lbeschrijving := substr(artikel_rec.bes_srtdeel_omschrijving, 1, 50);
               lomschrijving := lcl.L('lcl_bes_srtdeel_nr') || ': ' || artikel_rec.bes_srtdeel_nr;
               lopmerking := artikel_rec.bes_srtdeel_opmerking;
               lcnt_nummer := bes_bestelling_prefix || TO_CHAR(artikel_rec.bes_bestelling_key);
               lcnt_disckey := artikel_rec.bes_disc_params_cnt_disckey;
               lprs_afdeling_key := artikel_rec.prs_afdeling_key;
               lprs_perslid_key := artikel_rec.prs_perslid_key;
               lprs_perslid_key_voor := artikel_rec.prs_perslid_key_voor;
               lprs_contactpersoon_key := artikel_rec.prs_contactpersoon;
               looptijd_van := artikel_rec.bes_bestelling_leverdatum;
               -- De looptijd komt uit de bes_disc_params
               looptijd_tot := cnt.cnt_getTermijndatum(artikel_rec.bes_bestelling_leverdatum, artikel_rec.bes_disc_params_cnt_termijn, 1);
               lcnt_opzegtermijn := artikel_rec.bes_disc_params_cnt_opzegterm;
               lbedr_key := artikel_rec.prs_bedrijf_key;
               ltotaal := artikel_rec.totaal;
               lprs_kostenplaats_key := artikel_rec.prs_kostenplaats_key;

               lfirst := 1;
            END;
         ELSE
            IF llast = 0
            THEN
               IF ((LENGTH (lbeschrijving) + LENGTH (artikel_rec.bes_srtdeel_omschrijving) < (50 - 5)) AND
                   (LENGTH (lomschrijving) + LENGTH (artikel_rec.bes_srtdeel_nr) < (2048 - 5)) AND
                   (LENGTH (lopmerking) + LENGTH (artikel_rec.bes_srtdeel_opmerking) < (2048 - 5)))
               THEN
                  lbeschrijving := lbeschrijving || ', ' || artikel_rec.bes_srtdeel_omschrijving;
                  lomschrijving := lomschrijving || CHR (10) || artikel_rec.bes_srtdeel_nr;
                  lopmerking := lopmerking || CHR (10) || artikel_rec.bes_srtdeel_opmerking;
               ELSE
                  lbeschrijving := lbeschrijving || ', ' || '...';
                  lomschrijving := lomschrijving || CHR (10) || '...';
                  lopmerking := lopmerking || CHR (10) || '...';
                  llast := 1;
               END IF;
            END IF;
         END IF;
      END LOOP;

      -- Is er al een contract aanwezig?
      BEGIN
         SELECT c.cnt_contract_key
           INTO lcnt_key
           FROM cnt_contract c
          WHERE c.bes_bestelopdr_key = bestelopdr_key;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
           lcnt_key := -1;
      END;
      IF lcnt_key > 0
      THEN
        -- Abonnement contract wijzigen
        UPDATE cnt_contract
           SET cnt_contract_nummer_intern = lcnt_nummer,
               ins_discipline_key = lcnt_disckey,
               cnt_contract_omschrijving = lbeschrijving,
               cnt_contract_document = lomschrijving,
               prs_afdeling_key_eig = lprs_afdeling_key,
               prs_perslid_key_eig = lprs_perslid_key_voor,
               prs_perslid_key_beh = lprs_perslid_key,
               cnt_contract_opmerking = lopmerking,
               cnt_contract_looptijd_van = looptijd_van,
               cnt_contract_looptijd_tot = looptijd_tot,
               cnt_contract_opzegtermijn = lcnt_opzegtermijn,
               cnt_contract_rappeltermijn = cnt_rappel_abonnement,
               cnt_prs_bedrijf_key = lbedr_key,
               prs_contactpersoon_key = lprs_contactpersoon_key,
               cnt_contract_kosten = ltotaal,
               prs_kostenplaats_key = lprs_kostenplaats_key,
               cnt_contract_verlenging = NULL,
               bes_bestelopdr_key = bestelopdr_key
         WHERE cnt_contract_key = lcnt_key;
        fac.trackaction ('CNTUPD', lcnt_key, NULL, NULL, NULL);
      ELSE
        -- Er moet een abonnement contract aangemaakt worden.
        -- Abonnement contract toevoegen
        SELECT cnt_s_cnt_contract_key.NEXTVAL INTO lcnt_key FROM DUAL;
        INSERT INTO cnt_contract (cnt_contract_key,
                                  cnt_contract_nummer_intern,
                                  ins_discipline_key,
                                  cnt_contract_omschrijving,
                                  cnt_contract_document,
                                  prs_afdeling_key_eig,
                                  prs_perslid_key_eig,
                                  prs_perslid_key_beh,
                                  cnt_contract_opmerking,
                                  cnt_contract_looptijd_van,
                                  cnt_contract_looptijd_tot,
                                  cnt_contract_opzegtermijn,
                                  cnt_contract_rappeltermijn,
                                  cnt_prs_bedrijf_key,
                                  prs_contactpersoon_key,
                                  cnt_contract_kosten,
                                  prs_kostenplaats_key,
                                  cnt_contract_verlenging,
                                  bes_bestelopdr_key,
                                  cnt_contract_status)
                          VALUES (lcnt_key,
                                  lcnt_nummer,
                                  lcnt_disckey,
                                  lbeschrijving,
                                  lomschrijving,
                                  lprs_afdeling_key,
                                  lprs_perslid_key_voor,
                                  lprs_perslid_key,
                                  lopmerking,
                                  looptijd_van,
                                  looptijd_tot,
                                  lcnt_opzegtermijn,
                                  cnt_rappel_abonnement,
                                  lbedr_key,
                                  lprs_contactpersoon_key,
                                  ltotaal,
                                  lprs_kostenplaats_key,
                                  NULL,
                                  bestelopdr_key,
                                  0);              -- Status zou eigenlijk afhankelijk moeten zijn van het approval mechanisme of deze wel of niet actief is (Setting cnt_contract_approval). Voor nu nog niet. TODO...
        fac.trackaction ('CNTNEW', lcnt_key, NULL, NULL, lcl.L ('lcl_bes_cnt_insert') || lcnt_nummer);
      END IF;
    END;

   -- Geef bestellingkey, gewenste status en userkey, en de status wordt
   -- gezet, waarbij zonodig (indien verandering) een trackrecord wordt gemaakt
   -- Als de status niet wijzigt, wordt ook geen trackrecord gemaakt
   -- ZIE schema StateDiagramBestellingen.vsd
   PROCEDURE setbestellingstatus (pbestellingkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER)
   AS
      currentstatus bes_bestelling.bes_bestelling_status%TYPE;
      newstatus bes_bestelling.bes_bestelling_status%TYPE;
      eventcode VARCHAR2(10);  -- tabelsize is 6
   BEGIN
      SELECT   COALESCE (bes_bestelling_status, -1)
        INTO   currentstatus
        FROM   bes_bestelling
       WHERE   bes_bestelling_key = pbestellingkey;

      CASE pstatus
         WHEN 1                                                                                            -- Afgewezen
         THEN
            IF currentstatus <> 1
            THEN
               eventcode := 'BESREJ';
            END IF;
         WHEN 2                              -- Nieuw. Dit is de default, dus leeg kan niet; we rekenen 2>2 ook goed
         THEN
            eventcode := 'BESAP2';
         WHEN 3                                                    -- Gefiatteerd (voor de eerste keer, voordat acceptatie)
         THEN
            IF currentstatus <> 3
            THEN
               eventcode := 'BESFIT';
            END IF;
         WHEN 4                                                                                            -- Geaccepteerd
         THEN
            IF currentstatus <> 4
            THEN
               eventcode := 'BESACP';
            END IF;
         WHEN 5                                                                                            -- Besteld
         THEN
            IF currentstatus <> 5
            THEN
               eventcode := 'BESBES';
            END IF;
         WHEN 6                                                                                            -- Geleverd
         THEN
            IF currentstatus <> 6
            THEN
               eventcode := 'BESOTV';
            END IF;
         WHEN 7                                                                                            -- Verwerkt
         THEN
            IF currentstatus <> 7
            THEN
               eventcode := 'BESVER';
            END IF;
         WHEN 8                                                                                            -- Geannuleerd
         THEN
            IF currentstatus <> 8
            THEN
               eventcode := 'BESCAN';
            END IF;
         WHEN 9                                                                                            -- Ontvangen
         THEN
            IF currentstatus <> 9
            THEN
               eventcode := '#BESOT2'; -- Alleen tracken en geen notificatie omdat die bij het ontvangen(6) wordt verstuurd.
            END IF;
         ELSE
            -- Invalid statuschange or no change
            eventcode := NULL;
      END CASE;

      IF eventcode IS NOT NULL
      THEN
         UPDATE   bes_bestelling
            SET   bes_bestelling_status = pstatus
          WHERE   bes_bestelling_key = pbestellingkey;

         -- We know that trackaction doesnt do tracking if eventcode is null
         fac.trackaction (eventcode, pbestellingkey, puserkey, NULL, NULL);
      END IF;
   END;

   PROCEDURE setbestelopdrstatus (pbestelopdrkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER)
   AS
      currentstatus bes_bestelling.bes_bestelling_status%TYPE;
      newstatus bes_bestelling.bes_bestelling_status%TYPE;
      eventcode fac_srtnotificatie.fac_srtnotificatie_code%TYPE;
   BEGIN
      SELECT   COALESCE (bes_bestelopdr_status, -1)
        INTO   currentstatus
        FROM   bes_bestelopdr
       WHERE   bes_bestelopdr_key = pbestelopdrkey;

      CASE pstatus
         WHEN 1                                                                                           -- Afgewezen
         THEN
            IF currentstatus <> 1
            THEN
               eventcode := 'BES2RE';
            END IF;
         WHEN 2                                                                                           -- Unused
         THEN
            eventcode := NULL;
         WHEN 3
         THEN
            IF currentstatus <> 3                                                                         -- In behandeling
            THEN
               eventcode := 'BES2NE';
            END IF;
         WHEN 4                                                                                           -- In Bestelling (bevestigd)
         THEN
            IF currentstatus <> 4
            THEN
               eventcode := 'BES2CO';
            END IF;
         WHEN 5                                                                                           -- Ter Bevesting
         THEN
            IF currentstatus <> 5
            THEN
               eventcode := 'BES2BE';
            END IF;
         WHEN 6                                                                                           -- Geleverd
         THEN
            IF currentstatus <> 6
            THEN
               eventcode := 'BES2AF';
            END IF;
         WHEN 7                                                                                           -- Verwerkt
         THEN
            IF currentstatus <> 7
            THEN
               eventcode := 'BES2VE';
            END IF;
         WHEN 8                                                                                           -- Geannuleerd
         THEN
            IF currentstatus <> 8
            THEN
               eventcode := 'BES2CA';
            END IF;
         ELSE
            -- Invalid statuschange or no change
            eventcode := NULL;
      END CASE;

      IF eventcode IS NOT NULL
      THEN
         UPDATE   bes_bestelopdr
            SET   bes_bestelopdr_status = pstatus
          WHERE   bes_bestelopdr_key = pbestelopdrkey;

         -- We know that trackaction doesnt do tracking if eventcode is null
         fac.trackaction (eventcode, pbestelopdrkey, puserkey, NULL, NULL);
      END IF;
   END;

   -- Werkt zonodig de status bij (als alles geleverd is met name)
   -- ATTENTIE: onderstaande checks kunnen niet in de trigger vanwege mutating-errors!
   -- Deze moeten dus op gezette tijden worden aangeroepen, na aanpassing van een
   -- bestelaanvraag of bestelopdracht.
   PROCEDURE updatebestellingstatus (pbestelling_key IN NUMBER, user_key IN NUMBER)
   AS
      regel_cnt          NUMBER;
      regel_cnt_geleverd NUMBER;
      regel_cnt_verwerkt NUMBER;
   BEGIN
      SELECT   COUNT ( * )
        INTO   regel_cnt
        FROM   bes_bestelling_item bi
       WHERE   bes_bestelling_key = pbestelling_key;

      SELECT   COUNT ( * )
        INTO   regel_cnt_geleverd
        FROM   bes_bestelling_item bi
       WHERE   bi.bes_bestelling_item_status = 6 AND bes_bestelling_key = pbestelling_key;

      SELECT   COUNT ( * )
        INTO   regel_cnt_verwerkt
        FROM   bes_bestelling_item bi
       WHERE   bi.bes_bestelling_item_status = 7 AND bes_bestelling_key = pbestelling_key;

      IF regel_cnt_geleverd = regel_cnt
      THEN
         -- alles is geleverd, dus bestelling is geleverd
         bes.setbestellingstatus (pbestelling_key, 6, user_key);
      END IF;
      IF regel_cnt_verwerkt = regel_cnt
      THEN
         -- alles is verwerkt, dus bestelling is verwerkt
         bes.setbestellingstatus (pbestelling_key, 7, user_key);
      END IF;
   END;

   PROCEDURE updatebestelopdrstatus (pbestelopdr_key IN NUMBER, user_key IN NUMBER)
   AS
      regel_cnt NUMBER;
      regel_cnt_geleverd NUMBER;
      regel_cnt_verwerkt NUMBER;
   BEGIN
      SELECT   COUNT ( * )
        INTO   regel_cnt
        FROM   bes_bestelopdr_item bi
       WHERE   bes_bestelopdr_key = pbestelopdr_key;

      SELECT   COUNT ( * )
        INTO   regel_cnt_geleverd
        FROM   bes_bestelopdr_item bi
       WHERE   bi.bes_bestelopdr_item_status = 6 AND bes_bestelopdr_key = pbestelopdr_key;

      SELECT   COUNT ( * )
        INTO   regel_cnt_verwerkt
        FROM   bes_bestelopdr_item bi
       WHERE   bi.bes_bestelopdr_item_status = 7 AND bes_bestelopdr_key = pbestelopdr_key;

      IF regel_cnt_geleverd = regel_cnt
      THEN
         -- alles is geleverd, dus opdracht is geleverd
         bes.setbestelopdrstatus (pbestelopdr_key, 6, user_key);
      END IF;

      IF regel_cnt_verwerkt = regel_cnt
      THEN
         -- alles is verwerkt, dus opdracht is verwerkt
         bes.setbestelopdrstatus (pbestelopdr_key, 7, user_key);
      END IF;
   END;


   -- Stuur alle mogelijke backofficemedewerkers een bericht als de
   -- melding NIEUW is. Naar wie, wordt reversed opgezocht op basis van
   -- toegekende autorisaties
   -- (zoals bij de lijst van BO-behandelaars in suggest/persoonfilter.inc)
   PROCEDURE notifybackoffice (pbeskey IN NUMBER)
   AS
      lloc_key   mld_adres.alg_locatie_key%TYPE;
      lafd_key   prs_perslid.prs_afdeling_key%TYPE;
      ldisc_key  bes_srtgroep.ins_discipline_key%TYPE;
      ldisc_oms  bes_discipline.ins_discipline_omschrijving%TYPE;
      loms       fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      bericht    fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      lnrreceivers   NUMBER;
      lreceivers     fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      lreceivers1    fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      ltracking      VARCHAR2(4000);  -- moet tijdelijk groter dan fac_srtnotificatie.fac_srtnotificatie_oms%TYPE kunnen zijn
   BEGIN
      BEGIN
         SELECT   DISTINCT
                  COALESCE(ma.alg_locatie_key, -1),
                  p.prs_afdeling_key,
                  bsg.ins_discipline_key,
                  bd.ins_discipline_omschrijving
           INTO   lloc_key,
                  lafd_key,
                  ldisc_key,
                  ldisc_oms
           FROM   bes_bestelling b,
                  bes_bestelling_item bi,
                  bes_srtdeel bsd,
                  bes_srtgroep bsg,
                  bes_discipline bd,
                  prs_perslid p,
                  mld_adres ma
          WHERE   b.bes_bestelling_key = bi.bes_bestelling_key
            AND   bi.bes_srtdeel_key = bsd.bes_srtdeel_key
            AND   bsd.bes_srtgroep_key = bsg.bes_srtgroep_key
            AND   bsg.ins_discipline_key = bd.ins_discipline_key
            AND   b.prs_perslid_key = p.prs_perslid_key
            AND   b.mld_adres_key_lev = ma.mld_adres_key
            AND   b.bes_bestelling_key = pbeskey;                   -- op dit moment nog alleen voor NIEUWE bestellingen

         -- Als die er niet is sprongen we al naar de exception
         -- Als die er wel is, gaan we verder
         SELECT   lcl.x('fac_srtnotificatie_oms', fac_srtnotificatie_key, fac_srtnotificatie_oms)
           INTO   loms
           FROM   fac_srtnotificatie
          WHERE   fac_srtnotificatie_code = 'BES2BO';

         bericht := bes.bessprintf (loms, pbeskey, ldisc_oms);      -- de variabelen invullen

         lnrreceivers := 0;
         lreceivers := '';
         FOR boer
            IN (SELECT   g.prs_perslid_key
                  FROM   fac_v_webgebruiker g, fac_functie f, prs_perslid p, prs_v_afdeling d
                 WHERE       g.fac_functie_key = f.fac_functie_key
                         AND g.ins_discipline_key = ldisc_key
                         AND g.prs_perslid_key = p.prs_perslid_key
                         AND d.prs_afdeling_key = p.prs_afdeling_key
                         AND (g.fac_gebruiker_prs_level_write = -1
                              OR (g.fac_gebruiker_prs_level_write = 0
                              AND d.prs_bedrijf_key = (SELECT aa.prs_bedrijf_key
                                                         FROM prs_v_afdeling aa
                                                        WHERE aa.prs_afdeling_key = lafd_key))
                              OR (g.fac_gebruiker_prs_level_write >0
                                  AND p.prs_afdeling_key IN
                                           (SELECT   prs_afdeling_key
                                              FROM   prs_v_afdeling_familie a
                                             WHERE   a.prs_afdeling_elder_key IN
                                                           (SELECT   aa.prs_afdeling_elder_key
                                                              FROM   prs_v_afdeling_familie aa
                                                             WHERE   aa.prs_afdeling_key = lafd_key
                                                                     AND aa.niveau = g.fac_gebruiker_prs_level_write))))
                         -- in ASP:  if (params.loc_key>0)
                         -- Bij bestelling wordt afleveradres ingevuld die is gekoppeld aan alg_locatie_key. Dus op locatie niveau checken is hier voldoende.
                         AND (g.fac_gebruiker_alg_level_write = -1
                              OR (g.fac_gebruiker_alg_level_write < 9
                                  AND lloc_key IN
                                           (SELECT   alg_locatie_key
                                              FROM   fac_v_my_locations
                                             WHERE   prs_perslid_key = p.prs_perslid_key
                                                     AND niveau = fac_gebruiker_alg_level_write)))
                         AND fac_functie_code = 'WEB_BESBOF')
         LOOP
            fac.putnotificationsrtprio (NULL,
                                        boer.prs_perslid_key,
                                        'BES2BO',
                                        pbeskey,
                                        bericht,
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL,
                                        2,
                                        NULL
                                       );
            IF lnrreceivers = 0 THEN
                SELECT prs_perslid_naam_friendly
                  INTO lreceivers
                  FROM prs_v_perslid_fullnames
                 WHERE prs_perslid_key = boer.prs_perslid_key;
            ELSE
                SELECT prs_perslid_naam_friendly
                  INTO lreceivers1
                  FROM prs_v_perslid_fullnames
                 WHERE prs_perslid_key = boer.prs_perslid_key;
               lreceivers := lreceivers||', '||lreceivers1;
            END IF;
            lnrreceivers := lnrreceivers+1;
         END LOOP;
         IF lnrreceivers > 0 THEN
             DBMS_OUTPUT.PUT_LINE(lnrreceivers);
             ltracking :=  lcl.l ('lcl_bes_notification_sent_to');
             --ltracking := 'Notitificatie ''{0}'' verstuurd aan {1}';
             ltracking := REPLACE (ltracking, '{0}', bericht);
             ltracking := REPLACE (ltracking, '{1}', lreceivers);
             DBMS_OUTPUT.PUT_LINE(ltracking);
             fac.trackaction ('#BESMAI', pbeskey, NULL, NULL, SUBSTR(ltracking,1,2048));  -- maxlengte van fac_srtnotificatie_oms
        END IF;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN;
      END;
   END;

   -- Stuur alle mogelijke bestelling goedkeurders een bericht als de bestelling status 3 heeft.
   -- Naar wie, wordt reversed opgezocht op basis van toegekende autorisaties.
   PROCEDURE notifybesgoedkeurders (pbeskey IN NUMBER)
   AS
      lloc_key mld_adres.alg_locatie_key%TYPE;
      lafd_key prs_perslid.prs_afdeling_key%TYPE;
      ldisc_key bes_srtgroep.ins_discipline_key%TYPE;
      loms fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      lbes_approved bes_bestelling.bes_bestelling_approved%TYPE;
      lbes_kosten NUMBER (11,2);
      lbestellimiet bes_disc_params.bes_disc_params_bestellimiet%TYPE;
      lbestellimiet2 bes_disc_params.bes_disc_params_bestellimiet2%TYPE;
      lbestellimiet3 bes_disc_params.bes_disc_params_bestellimiet3%TYPE;
      lbestellimiet4 bes_disc_params.bes_disc_params_bestellimiet4%TYPE;
      lbestellimiet5 bes_disc_params.bes_disc_params_bestellimiet5%TYPE;
      lbonotify      bes_disc_params.bes_disc_params_bonotify%TYPE;
      lfunctiecode fac_functie.fac_functie_code%TYPE;
      lsender mld_discipline.ins_discipline_email%TYPE;
      bericht fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;                         -- kan te kort zijn na substitutie
      lnrreceivers   NUMBER;
      lreceivers     fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      lreceivers1    fac_srtnotificatie.fac_srtnotificatie_oms%TYPE;
      ltracking      VARCHAR2(4000);  -- moet tijdelijk groter dan fac_srtnotificatie.fac_srtnotificatie_oms%TYPE kunnen zijn
   BEGIN
      BEGIN
         SELECT COALESCE(ma.alg_locatie_key, -1),
                p.prs_afdeling_key,
                bsg.ins_discipline_key,
                COALESCE (b.bes_bestelling_approved, -1),
                COALESCE (SUM (bi.bes_bestelling_item_aantal * bi.bes_bestelling_item_prijs) - b.bes_bestelling_korting + b.bes_bestelling_levkosten, 0),
                COALESCE (bdp.bes_disc_params_bestellimiet, 0),
                COALESCE (bdp.bes_disc_params_bestellimiet2, 0),
                COALESCE (bdp.bes_disc_params_bestellimiet3, 0),
                COALESCE (bdp.bes_disc_params_bestellimiet4, 0),
                COALESCE (bdp.bes_disc_params_bestellimiet5, 0),
                bdp.bes_disc_params_bonotify
           INTO lloc_key,
                lafd_key,
                ldisc_key,
                lbes_approved,
                lbes_kosten,
                lbestellimiet,
                lbestellimiet2,
                lbestellimiet3,
                lbestellimiet4,
                lbestellimiet5,
                lbonotify
           FROM bes_bestelling b,
                bes_bestelling_item bi,
                bes_srtdeel bsd,
                bes_srtgroep bsg,
                bes_disc_params bdp,
                prs_perslid p,
                mld_adres ma
          WHERE b.bes_bestelling_key = bi.bes_bestelling_key
            AND bi.bes_srtdeel_key = bsd.bes_srtdeel_key
            AND bsd.bes_srtgroep_key = bsg.bes_srtgroep_key
            AND bsg.ins_discipline_key = bdp.bes_ins_discipline_key
            AND b.prs_perslid_key = p.prs_perslid_key
            AND b.mld_adres_key_lev = ma.mld_adres_key
            AND bi.bes_bestelling_key = pbeskey
         GROUP BY ma.alg_locatie_key,
                  p.prs_afdeling_key,
                  bsg.ins_discipline_key,
                  b.bes_bestelling_approved,
                  b.bes_bestelling_korting,
                  b.bes_bestelling_levkosten,
                  bdp.bes_disc_params_bestellimiet,
                  bdp.bes_disc_params_bestellimiet2,
                  bdp.bes_disc_params_bestellimiet3,
                  bdp.bes_disc_params_bestellimiet4,
                  bdp.bes_disc_params_bestellimiet5,
                  bdp.bes_disc_params_bonotify;

         IF lbes_kosten <= lbestellimiet   -- Dit eerst testen i.v.m. Acceptering. Verder moet sowieso geaccepteerd worden.
         THEN
           IF lbonotify = 1
           THEN                             -- Er hoeft niet gefiatteerd te worden,
             bes.notifybackoffice(pbeskey); -- dus stuur de backoffice een bericht dat er een nieuwe bestelling is.
           END IF;
           RETURN;   -- Het bedrag is lager als de eerste limiet. De bestelling hoeft niet goed gekeurd te worden, dus een lege fiatteurs array teruggeven.
         ELSIF (((fac.getsetting ('bes_approval_all') = 0 AND lbes_kosten >= lbestellimiet) OR
                 (fac.getsetting ('bes_approval_all') = 1 AND lbes_kosten <= lbestellimiet2)) AND
                lbes_approved <= lbestellimiet)
         THEN
           lfunctiecode := 'WEB_BESBOF';
         ELSIF ((fac.getsetting ('bes_approval_all') = 0 AND lbes_kosten >= lbestellimiet2 AND lbes_approved = lbestellimiet2) OR
                (fac.getsetting ('bes_approval_all') = 1 AND lbes_kosten <= lbestellimiet3 AND lbes_approved <= lbestellimiet2))
         THEN
           lfunctiecode := 'WEB_BESGO2';
         ELSIF ((fac.getsetting ('bes_approval_all') = 0 AND lbes_kosten >= lbestellimiet3 AND lbes_approved = lbestellimiet3) OR
                (fac.getsetting ('bes_approval_all') = 1 AND lbes_kosten <= lbestellimiet4 AND lbes_approved <= lbestellimiet3))
         THEN
           lfunctiecode := 'WEB_BESGO3';
         ELSIF ((fac.getsetting ('bes_approval_all') = 0 AND lbes_kosten >= lbestellimiet4 AND lbes_approved = lbestellimiet4) OR
                (fac.getsetting ('bes_approval_all') = 1 AND lbes_kosten <= lbestellimiet5 AND lbes_approved <= lbestellimiet4))
         THEN
           lfunctiecode := 'WEB_BESGO4';
         ELSIF((fac.getsetting ('bes_approval_all') = 0 AND lbes_kosten >= lbestellimiet5 AND lbes_approved >= lbestellimiet5) OR
               (fac.getsetting ('bes_approval_all') = 1 AND lbes_kosten > lbestellimiet5 AND lbes_approved <= lbestellimiet5))
         THEN
           lfunctiecode := 'WEB_BESGO5';
         ELSE
           IF lbonotify = 1
           THEN                             -- De laatste fiatteur heeft de bestelling goedgekeurd,
             bes.notifybackoffice(pbeskey); -- dus nu mag de backoffice het bericht krijgen dat er een nieuwe bestelling is.
           END IF;
           RETURN; -- Het goedgekeurde bedrag zit al boven de limiet. Geen approval meer nodig.
         END IF;

         -- These notifications are now sent on behalf of the system, what might be the local FM organisation
         SELECT MAX (COALESCE (bd.ins_discipline_email, l.alg_locatie_email)) email
           INTO lsender
           FROM bes_bestelling b,
                bes_bestelling_item bi,
                bes_srtdeel bsd,
                bes_srtgroep bsg,
                bes_discipline bd,
                mld_adres ma,
                alg_locatie l
          WHERE b.bes_bestelling_key = bi.bes_bestelling_key
            AND bi.bes_srtdeel_key = bsd.bes_srtdeel_key
            AND bsd.bes_srtgroep_key = bsg.bes_srtgroep_key
            AND bsg.ins_discipline_key = bd.ins_discipline_key
            AND b.mld_adres_key_lev = ma.mld_adres_key
            AND ma.alg_locatie_key = l.alg_locatie_key
            AND bi.bes_bestelling_key = pbeskey;

         -- Als die er niet is sprongen we al naar de exception
         -- Als die er wel is, gaan we verder
         SELECT   lcl.x('fac_srtnotificatie_oms', fac_srtnotificatie_key, fac_srtnotificatie_oms)
           INTO   loms
           FROM   fac_srtnotificatie
          WHERE   fac_srtnotificatie_code = 'BESAP1';

         bericht := bes.bessprintf (loms, pbeskey, '');             -- de variabelen invullen

         lnrreceivers := 0;
         lreceivers := '';
         FOR boer
            IN (SELECT   g.prs_perslid_key
                  FROM   fac_v_webgebruiker g, fac_functie f, prs_perslid p
                 WHERE       g.fac_functie_key = f.fac_functie_key
                         AND g.ins_discipline_key = ldisc_key
                         AND g.prs_perslid_key = p.prs_perslid_key
                         AND (g.fac_gebruiker_prs_level_write = -1
                              OR (g.fac_gebruiker_prs_level_write < 9
                                  AND p.prs_afdeling_key IN
                                           (SELECT   prs_afdeling_key
                                              FROM   prs_v_afdeling_familie a
                                             WHERE   a.prs_afdeling_elder_key IN
                                                           (SELECT   aa.prs_afdeling_elder_key
                                                              FROM   prs_v_afdeling_familie aa
                                                             WHERE   aa.prs_afdeling_key = lafd_key
                                                                     AND aa.niveau = g.fac_gebruiker_prs_level_write))))
                         -- in ASP:  if (params.loc_key>0)
                         AND (g.fac_gebruiker_alg_level_write = -1
                              OR (g.fac_gebruiker_alg_level_write < 9
                                  AND lloc_key IN
                                           (SELECT   alg_locatie_key
                                              FROM   fac_v_my_locations
                                             WHERE   prs_perslid_key = p.prs_perslid_key
                                                     AND niveau = fac_gebruiker_alg_level_write)))
                         AND fac_functie_code = lfunctiecode)
         LOOP
            fac.putnotificationsrtprio (NULL,
                                        boer.prs_perslid_key,
                                        'BESAP1',
                                        pbeskey,
                                        bericht,
                                        NULL,
                                        NULL,
                                        NULL,
                                        NULL,
                                        2,
                                        lsender
                                       );
            IF lnrreceivers = 0 THEN
                SELECT prs_perslid_naam_friendly
                  INTO lreceivers
                  FROM prs_v_perslid_fullnames
                 WHERE prs_perslid_key = boer.prs_perslid_key;
            ELSE
                SELECT prs_perslid_naam_friendly
                  INTO lreceivers1
                  FROM prs_v_perslid_fullnames
                 WHERE prs_perslid_key = boer.prs_perslid_key;
               lreceivers := lreceivers||', '||lreceivers1;
            END IF;
            lnrreceivers := lnrreceivers+1;
         END LOOP;
         IF lnrreceivers > 0 THEN
             DBMS_OUTPUT.PUT_LINE(lnrreceivers);
             ltracking :=  lcl.l ('lcl_ord_notification_sent_to');
             --ltracking := 'Notitificatie ''{0}'' verstuurd aan {1}';
             DBMS_OUTPUT.PUT_LINE(ltracking);
             ltracking := REPLACE (ltracking, '{0}', bericht);
             ltracking := REPLACE (ltracking, '{1}', lreceivers);
             DBMS_OUTPUT.PUT_LINE(ltracking);
             fac.trackaction ('#BES2MA', pbeskey, NULL, NULL, SUBSTR(ltracking,1,2048));  -- maxlengte van fac_srtnotificatie_oms
        END IF;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN;
      END;
   END;

  -- Opdracht wordt geaccepteerd door de leverancier (of door de BO namens de leverancier)
  PROCEDURE acceptopdracht (pbestelopdr_key IN NUMBER, user_key IN NUMBER, presulttext IN VARCHAR2)
  AS
     beskey         bes_bestelling.bes_bestelling_key%TYPE;
     orgbeskey      bes_bestelling.bes_bestelling_key%TYPE;
     orgopdrkey     bes_bestelopdr.bes_bestelopdr_key%TYPE;
     opdrachtaantal bes_bestelopdr_item.bes_bestelopdr_item_aantal%TYPE;
     abonnement     bes_disc_params.bes_disc_params_contract%TYPE;
  BEGIN
     SELECT MAX (b.bes_bestelling_key),
            MAX (b.bes_bestelling_parentkey),
            MAX (bdp.bes_disc_params_contract)
       INTO beskey,
            orgbeskey,
            abonnement
       FROM bes_bestelopdr_item boi,
            bes_bestelling_item bi,
            bes_bestelling b,
            bes_srtdeel bsd,
            bes_srtgroep bsg,
            bes_disc_params bdp
      WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key
        AND bi.bes_bestelling_key = b.bes_bestelling_key
        AND bi.bes_srtdeel_key = bsd.bes_srtdeel_key
        AND bsd.bes_srtgroep_key = bsg.bes_srtgroep_key
        AND bdp.bes_ins_discipline_key = bsg.ins_discipline_key
        AND boi.bes_bestelopdr_key = pbestelopdr_key;
     -- We hebben nu alles in geval van een mutatieopdracht:
     -- orgopdrkey = de key van de oude opdracht BO1
     -- pbestelopdr_key = de key van de nieuwe opdracht BO2
     -- orgbeskey = de key van de oude aanvraag BA1
     -- beskey = de key van de nieuwe aanvraag BA2
     DBMS_OUTPUT.put_line ('orgbeskey' || orgbeskey);
     DBMS_OUTPUT.put_line ('pbestelopdr_key' || pbestelopdr_key);
     DBMS_OUTPUT.put_line ('beskey' || beskey);

     -- Ook gewoon op change-opdracht
     bes.setbestelopdrstatus (pbestelopdr_key, 4, user_key);

     IF orgbeskey IS NULL
     THEN
        -- dit is geen kopie of zo, gewoon een bestelling/opdracht
        IF abonnement = 1
        THEN
          -- Het is een abonnement bestelling/opdracht. Er moet een abonnement contract aangemaakt worden.
          bes.makecontract (pbestelopdr_key);
        END IF;
     ELSE
        -- Deze opdracht behoort bij een kopie-bestelaanvraag, waarvan de opdracht
        -- nu dus is goedgekeurd door de leverancier. Aan het werk!
        --
        SELECT MAX (boi.bes_bestelopdr_key)
          INTO orgopdrkey
          FROM bes_bestelopdr_item boi, bes_bestelling_item bi
         WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key
               AND bi.bes_bestelling_key = orgbeskey;
        DBMS_OUTPUT.put_line ('orgopdrkey' || orgopdrkey);

        -- Nieuwe tracking toevoegen aan de oude (die we straks weggooien);
        UPDATE fac_tracking
           SET fac_tracking_refkey = orgopdrkey
         WHERE fac_tracking_refkey = pbestelopdr_key
               AND fac_srtnotificatie_key IN
                        (SELECT fac_srtnotificatie_key
                           FROM fac_srtnotificatie
                          WHERE fac_srtnotificatie_xmlnode = 'bestelopdr');

        -- Als het totaal van de mutatie-opdracht 0 is, is het een annulering, die nu
        -- dus door de leverancier is goedgekeurd. Het kan echter zo zijn dat de
        -- annuleringshorizon verstreken is, en dat er toch nog betaald moet worden
        -- we moeten DAN dus de oorspronkelijke opdracht bewaren tbv de factuur later
        -- Daarom gooien we dan niet de opdracht weg, maar zetten we status op 8.

        SELECT SUM (bes_bestelopdr_item_aantal)
          INTO opdrachtaantal
          FROM bes_bestelopdr_item
         WHERE bes_bestelopdr_key = pbestelopdr_key;

        -- Misschien moet je hier nog meer conditie aan toevoegen om zeker te weten dat het een annulering is?

        IF opdrachtaantal <> 0
        THEN
           --
           -- Nu alle nieuwe gegevens aan de oorspronkelijke hangen (behoud van nummer/key)
           -- Eerst de opdracht.

           -- Let op: we *verwijderen* de originele bes_bestelling_item en bes_bestelopdr_item
           --         (en flex) maar *houden* de originele bes_bestelling en bes_bestelopdr
           --         De concept aanvraag- en opdrachtregels (en flex) worden omgezet naar de
           --         originele bes_bestelling en bes_bestelopdr
           --         Vervolgens verwijderen we de concept bes_bestelling en de concept bes_bestelopdr
           --         De flexkenmerken onder de nieuwe itemregels gaan zo vanzelf goed
           --         maar de flexkenmerken onder de nieuwe bes_bestelling moeten wel omgezet

           -- Originele bestelregels en opdrachtregels verwijderen
           -- Deze moeten eerst, anders faalt de volgende
           DELETE FROM bes_bestelling_item
                 WHERE bes_bestelling_key = orgbeskey;

           DELETE FROM bes_bestelopdr_item
                 WHERE bes_bestelopdr_key = orgopdrkey;

           DELETE FROM bes_kenmerkbestell
                 WHERE bes_bestelling_key = orgbeskey;

           UPDATE bes_bestelopdr_item -- de concept opdracht regels actueel maken
              SET bes_bestelopdr_key = orgopdrkey
            WHERE bes_bestelopdr_key = pbestelopdr_key;

           -- TODO: de kopgegevens overzetten UITWERKEN
           UPDATE bes_bestelopdr -- de originele opdracht
              SET (prs_bedrijf_key,
                   bes_bestelopdr_datum,
                   mld_adres_key_lev,
                   mld_adres_key_fac,
                   bes_bestelopdr_id
                  ) = (SELECT prs_bedrijf_key,
                              bes_bestelopdr_datum,
                              mld_adres_key_lev,
                              mld_adres_key_fac,
                              bes_bestelopdr_id
                         FROM bes_bestelopdr
                        WHERE bes_bestelopdr_key = pbestelopdr_key)
            WHERE bes_bestelopdr_key = orgopdrkey;

           -- De opdracht is weg, nu de aanvraag
           -- Merk op: bij een annuleer doen we dit niet, bestelling-tracking
           -- is niet interessant
           UPDATE fac_tracking
              SET fac_tracking_refkey = orgbeskey
            WHERE fac_tracking_refkey = beskey
                  AND fac_srtnotificatie_key IN
                           (SELECT fac_srtnotificatie_key
                              FROM fac_srtnotificatie
                             WHERE fac_srtnotificatie_xmlnode = 'bestelling');

           UPDATE bes_bestelling_item -- de concept aanvraagregels actueel maken
              SET bes_bestelling_key = orgbeskey
            WHERE bes_bestelling_key = beskey;

           UPDATE bes_kenmerkbestell -- bestelling kenmerken
              SET bes_bestelling_key = orgbeskey
            WHERE bes_bestelling_key = beskey;

           -- TODO: GOED NAGAAN WAT OVERGENOMEN MOET WORDEN EN WAT NIET. ECHT NOG DOEN HOOR!
           UPDATE bes_bestelling -- de originele bestelling
              SET
                  (bes_bestelling_datum,
                  prs_perslid_key,
                  bes_bestelling_opmerking,
                  bes_bestelling_ordernr,
                  bes_bestelling_plaats,
                  mld_adres_key_lev,
                  prs_kostenplaats_key,
                  bes_bestelling_leverdatum,
                  bes_bestelling_lev_opm
                  ) =
                     (SELECT bes_bestelling_datum,
                             prs_perslid_key,
                             bes_bestelling_opmerking,
                             bes_bestelling_ordernr,
                             bes_bestelling_plaats,
                             mld_adres_key_lev,
                             prs_kostenplaats_key,
                             bes_bestelling_leverdatum,
                             bes_bestelling_lev_opm
                        FROM bes_bestelling
                       WHERE bes_bestelling_key = beskey)
            WHERE bes_bestelling_key = orgbeskey;

           --
           bes.setbestelopdrstatus (orgopdrkey, 4, user_key);

          IF abonnement = 1
          THEN
            -- Het is een abonnement bestelling/opdracht. Abonnement contract wijzigen/toevoegen.
            bes.makecontract (orgopdrkey);
          END IF;
        -- Anders nog iets?
        ELSE
           -- Een annulering
           -- We behouden de oude opdracht/ bestelling, maar zetten die op Geannuleerd,
           -- De nieuwe gooien we weg, die heeft zijn werk gedaan
           -- Eindstand is dus BA1 en BO1

           bes.setbestelopdrstatus (orgopdrkey, 8, user_key);
           bes.setbestellingstatus (orgbeskey, 8, user_key);

           DELETE FROM bes_bestelling_item
                 WHERE bes_bestelling_key = beskey;

           DELETE FROM bes_bestelopdr_item -- de concept opdracht regels mogen weg
             WHERE bes_bestelopdr_key = pbestelopdr_key;

        END IF;
       -- De concept bestelling en bestelopdracht records mogen nu altijd weg
       DELETE FROM bes_bestelopdr
             WHERE bes_bestelopdr_key = pbestelopdr_key;

       DELETE FROM bes_bestelling
             WHERE bes_bestelling_key = beskey;
     END IF;
  END;

  -- Opdracht wordt afgewezen door de leverancier (of door de BO namens de leverancier)
  PROCEDURE rejectopdracht (pbestelopdr_key IN NUMBER, user_key IN NUMBER, presulttext IN VARCHAR2)
  AS
     beskey bes_bestelling.bes_bestelling_key%TYPE;
     orgbeskey    bes_bestelling.bes_bestelling_key%TYPE;
     orgopdrkey   bes_bestelopdr.bes_bestelopdr_key%TYPE;
  BEGIN
     SELECT MAX (b.bes_bestelling_key), MAX (b.bes_bestelling_parentkey)
       INTO beskey, orgbeskey
       FROM bes_bestelopdr_item boi, bes_bestelling_item bi, bes_bestelling b
      WHERE     bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key
            AND bi.bes_bestelling_key = b.bes_bestelling_key
            AND boi.bes_bestelopdr_key = pbestelopdr_key;

     IF orgbeskey IS NULL
     THEN
        -- dit is geen kopie of zo, gewoon een bestelling/opdracht, dus gewoon vervallen
        bes.setbestelopdrstatus (pbestelopdr_key, 1, user_key);
        bes.setbestellingstatus(beskey, 1, user_key);
     ELSE
        -- rollback
        fac.trackaction ('BESXXX',
                         orgbeskey,
                         user_key,
                         NULL,
                         presulttext);                        -- mutatie gefaalt

        DELETE FROM bes_bestelling_item
              WHERE bes_bestelling_key = beskey;

        DELETE FROM bes_bestelopdr_item
              WHERE bes_bestelopdr_key = pbestelopdr_key;

        DELETE FROM bes_bestelopdr
              WHERE bes_bestelopdr_key = pbestelopdr_key;

        DELETE FROM bes_bestelling
              WHERE bes_bestelling_key = beskey;

        DBMS_OUTPUT.put_line ('failed -3');
     END IF;
  -- rollback
  END;

    FUNCTION bestelopdr_tooltip (besopdrkey IN NUMBER)
       RETURN VARCHAR2
    IS
       lret     VARCHAR2 (512);
       lfirst   NUMBER;
       llast    NUMBER;

       CURSOR opdritems
       IS
          SELECT    TO_CHAR (boi.bes_bestelopdr_item_aantal)
                 || 'x '
                 || s.bes_srtdeel_omschrijving      /* lcl.x()?*/
                 || ' ('
                 || s.bes_srtdeel_eenheid
                 || ') ' besitemdsc
            FROM bes_bestelopdr_item boi, bes_bestelling_item bi, bes_srtdeel s
           WHERE boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key
             AND bi.bes_srtdeel_key = s.bes_srtdeel_key
             AND boi.bes_bestelopdr_key = besopdrkey;
    BEGIN
       lret := NULL;
       lfirst := 0;
       llast := 0;

       FOR besitem_rec IN opdritems
       LOOP
          IF lfirst = 0
          THEN
             BEGIN
                lret := besitem_rec.besitemdsc;
                lfirst := 1;
             END;
          ELSE
             IF llast = 0
             THEN
                IF LENGTH (lret) + LENGTH (besitem_rec.besitemdsc) < (512 - 5)
                THEN
                   lret := lret || CHR (10) || besitem_rec.besitemdsc;
                ELSE
                   lret := lret || CHR (10) || '...';
                   llast := 1;
                END IF;
             END IF;
          END IF;
       END LOOP;

       RETURN lret;
    END;

    FUNCTION bessprintf (ps IN varchar2, pbes_bestelling_key IN number, pbes_discipline IN VARCHAR2)
       RETURN varchar2
    IS
       s varchar2 (2048 CHAR);
       lbes_bestelling_datum bes_bestelling.bes_bestelling_datum%TYPE;
    BEGIN
       s := ps;
         -- We support substitution of placeholders in the messages
         -- ##KEY##    = bes_bestelling_key
         -- ##DATUM##  = bes_bestelling_datum
         -- ##DISC##   = ins_discipline_omschrijving
         IF INSTR2 (s, '#') > 0
         THEN
           SELECT   b.bes_bestelling_datum
             INTO   lbes_bestelling_datum
             FROM   bes_bestelling b
            WHERE   b.bes_bestelling_key  = pbes_bestelling_key;
           s := REPLACE( REPLACE( REPLACE( s
                       , '##KEY##',   NUMBER_TO_CHAR (pbes_bestelling_key) )
                       , '##DATUM##', DATE_TO_CHAR (lbes_bestelling_datum, 'DD-MM-YY HH24:MI') )
                       , '##DISC##',  pbes_discipline
                       );
         END IF;

       RETURN s;
    END;
   FUNCTION opdrsprintf (ps IN VARCHAR2, pbes_bestelopdr_key IN NUMBER)
      RETURN VARCHAR2
   IS
      s VARCHAR2 (2048 CHAR);
      lopdrid bes_bestelopdr.bes_bestelopdr_id%TYPE;
   BEGIN
      s := ps;

      -- We support substitution of placeholders in the messages
      -- ##KEY##    = bes_bestelopdr_id
      IF INSTR (s, '#') > 0
      THEN
         SELECT   bes_bestelopdr_id
           INTO   lopdrid
           FROM   bes_bestelopdr
          WHERE   bes_bestelopdr_key = pbes_bestelopdr_key;

         s := REPLACE (s, '##KEY##', lopdrid);
      END IF;

      RETURN s;
    END;

END bes;
/


REGISTERRUN('$Id$')

#endif // BES
