Files
Database/FIN/FIN_PAC.SRC
Peter Feij 766af780de FSN#18275
svn path=/Database/trunk/; revision=10391
2010-09-06 13:11:52 +00:00

451 lines
17 KiB
Plaintext

#ifdef FIN
/* FIN_PAC.SRC
* $Revision: 5 $
* $Modtime: 6-09-10 15:33 $
*/
/* Formatted on 16-7-2010 17:57:48 (QP5 v5.136.908.31019) */
CREATE OR REPLACE PACKAGE fin
AS
PROCEDURE setfactuurstatus (pfactuurkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER);
FUNCTION matchfactuur (pfactuur_key IN NUMBER)
RETURN NUMBER;
PROCEDURE matchandsetfactuur (pfactuur_key IN NUMBER, prejecttoo IN BOOLEAN);
PROCEDURE autoapprovefactuur (pfactuur_key IN NUMBER);
END fin;
/
/* Formatted on 16-7-2010 18:17:24 (QP5 v5.136.908.31019) */
CREATE OR REPLACE PACKAGE BODY fin
AS
-- Geef meldingkey, gewenste status en userkey, en de status wortdt
-- gezet, waarbij zonodig (indien verandering) een trackrecord wordt gemaakt
-- Als de status niet wijzigt, wordt ook geen trackrecord gemaakt
-- ZIE schema StateDiagramOpdrachten.vsd
PROCEDURE setfactuurstatus (pfactuurkey IN NUMBER, pstatus IN NUMBER, puserkey IN NUMBER)
AS
currentstatus fin_factuur.fin_factuur_statuses_key%TYPE;
newstatus fin_factuur.fin_factuur_statuses_key%TYPE;
eventcode fac_srtnotificatie.fac_srtnotificatie_code%TYPE;
BEGIN
SELECT fin_factuur_statuses_key
INTO currentstatus
FROM fin_factuur
WHERE fin_factuur_key = pfactuurkey;
CASE pstatus
WHEN 1 -- Afgewezen
THEN
IF currentstatus IS NULL OR currentstatus = 2
THEN
newstatus := pstatus;
eventcode := 'FINFNO';
END IF;
WHEN 2 -- Ingevoerd
THEN
IF currentstatus IS NULL
THEN
newstatus := pstatus;
eventcode := 'FINNEW';
ELSIF currentstatus = 1 OR currentstatus = 6
THEN
newstatus := pstatus;
eventcode := 'FINFUN';
END IF;
WHEN 6 -- Verwerkt
THEN
IF currentstatus = 2
THEN
newstatus := pstatus;
eventcode := 'FINFOK';
END IF;
WHEN 7 -- Uitgegeven
THEN
IF currentstatus = 6
THEN
newstatus := pstatus;
eventcode := 'FINVER';
END IF;
ELSE
-- Invalid statuschange or no change
newstatus := NULL;
END CASE;
IF newstatus IS NOT NULL
THEN
-- vooralsnog lopen de notificaties 1-op-1 met de tracking
-- noticode := eventcode;
UPDATE fin_factuur
SET fin_factuur_statuses_key = newstatus
WHERE fin_factuur_key = pfactuurkey;
-- We know that trackaction doesnt do tracking if eventcode is null
fac.trackaction (eventcode, pfactuurkey, puserkey, NULL, NULL);
END IF;
END;
-- Gegeven de 2 referentiekeys, lever het type 'B', 'O' of 'C' op
-- Interne functie in de package vooralsnog
FUNCTION getreferentietype (po_key IN NUMBER, pc_key IN NUMBER, pb_key IN NUMBER)
RETURN VARCHAR2
IS
rtype VARCHAR2 (1) := '?';
BEGIN
IF po_key IS NOT NULL
THEN
rtype := 'O';
DBMS_OUTPUT.put_line ('opdrachtkey: ' || po_key);
ELSIF pc_key IS NOT NULL
THEN
rtype := 'C';
DBMS_OUTPUT.put_line ('contractkey: ' || pc_key);
ELSIF pb_key IS NOT NULL
THEN
rtype := 'B';
DBMS_OUTPUT.put_line ('besteloprachtkey: ' || pb_key);
END IF;
RETURN rtype;
END;
FUNCTION matchfactuur (pfactuur_key IN NUMBER)
RETURN NUMBER
IS
-- controleert deze nieuwe factuur, en levert een oordeel op:
-- -1 factuur niet (automatisch) goed
-- 0 niks van te zeggen of reeds goed-/afgekeurd/verwerkt
-- 1 factuur okay
ftype VARCHAR2 (1);
c_key fin_factuur.cnt_contract_key%TYPE;
b_key fin_factuur.bes_bestelopdr_key%TYPE;
o_key fin_factuur.mld_opdr_key%TYPE;
factuurstatus fin_factuur.fin_factuur_statuses_key%TYPE;
factuurdatum fin_factuur.fin_factuur_datum%TYPE;
discipline ins_tab_discipline.ins_discipline_key%TYPE;
korting bes_bestelopdr.bes_bestelopdr_korting%TYPE;
levkosten bes_bestelopdr.bes_bestelopdr_levkosten%TYPE;
contracttermijnkosten cnt_contract.cnt_contract_termijnkosten%TYPE;
contractkosten cnt_contract.cnt_contract_kosten%TYPE;
opdrachtkosten mld_opdr.mld_opdr_kosten%TYPE;
matchtype mld_typeopdr.mld_typeopdr_matchtype%TYPE;
factuurbedrag NUMBER (12, 2);
bestelbedrag NUMBER (12, 2); -- van de opdracht waar deze factuur over gaat
totaalgefactureerd NUMBER (12, 2); -- met deze factuur erbij eerder gefactureerd van dezelfde B(R)OC
retval NUMBER := 0;
-- Bepaal te tolerantie van de vakgroep
-- waarschijnlijk in procenten of zo?
-- of geven we de factuurwaarde mee en leveren we true/false op?
FUNCTION tolerantiematch (pdisckey IN NUMBER, pftype IN VARCHAR2, pfactbedrag IN NUMBER, pbestelbedrag IN NUMBER)
RETURN BOOLEAN
IS
discpct NUMBER;
discmarge NUMBER;
upperlimit NUMBER;
BEGIN
CASE
WHEN pftype = 'B'
THEN
SELECT p.bes_disc_params_factuurpct, p.bes_disc_params_factuurmarge
INTO discpct, discmarge
FROM bes_disc_params p
WHERE p.bes_ins_discipline_key = pdisckey;
WHEN pftype = 'C'
THEN
SELECT p.cnt_disc_params_factuurpct, p.cnt_disc_params_factuurmarge
INTO discpct, discmarge
FROM cnt_disc_params p
WHERE p.cnt_ins_discipline_key = pdisckey;
WHEN pftype = 'O'
THEN
SELECT p.mld_disc_params_factuurpct, p.mld_disc_params_factuurmarge
INTO discpct, discmarge
FROM mld_disc_params p
WHERE p.mld_ins_discipline_key = pdisckey;
ELSE
discpct := 0;
discmarge := 0;
END CASE;
IF discpct IS NULL AND discmarge IS NULL
THEN
upperlimit := pbestelbedrag;
ELSIF discpct IS NULL
THEN
upperlimit := pbestelbedrag + discmarge;
ELSE
upperlimit := pbestelbedrag * (100 + discpct) / 100;
END IF;
DBMS_OUTPUT.put_line ('discipline: ' || pdisckey);
DBMS_OUTPUT.put_line ('tolerantie%: ' || discpct);
DBMS_OUTPUT.put_line ('tolerantie-abs: ' || discmarge);
DBMS_OUTPUT.put_line ('bestel/opdracht/contactbedrag: ' || pbestelbedrag);
DBMS_OUTPUT.put_line ('bovengrens ' || upperlimit);
DBMS_OUTPUT.put_line ('factuurbedrag: ' || pfactbedrag);
RETURN pfactbedrag <= upperlimit;
END;
BEGIN
--------------------------------------------
------------ START MAIN ROUTINE ------------
--------------------------------------------
---
--- Over wat voor soort factuur hebben we het?
---
IF pfactuur_key IS NULL
THEN
DBMS_OUTPUT.put_line ('STOP, factuurkey: NULL');
RETURN 0;
END IF;
DBMS_OUTPUT.put_line ('\nfactuurkey: ' || pfactuur_key);
SELECT mld_opdr_key,
cnt_contract_key,
bes_bestelopdr_key,
fin_factuur_totaal,
fin_factuur_statuses_key,
fin_factuur_datum
INTO o_key,
c_key,
b_key,
factuurbedrag,
factuurstatus,
factuurdatum
FROM fin_factuur
WHERE fin_factuur_key = pfactuur_key;
IF factuurstatus <> 2 -- is al verwerkt, matching zinloos
THEN
DBMS_OUTPUT.put_line ('STOP, factuurstatus: ' || factuurstatus);
RETURN 0;
END IF;
ftype := fin.getreferentietype (o_key, c_key, b_key);
DBMS_OUTPUT.put_line ('>opdrachttype: ' || ftype);
--
-- Ga maar eens matchen
--
CASE
--
-- BESTELLING
--
WHEN ftype = 'B'
THEN
-- Factuur ok als binnen de toleranties van de bestelcatalogus
-- en het totaal met de eerder bestellingfacturen ook
SELECT SUM (boi.bes_bestelopdr_item_aantal * boi.bes_bestelopdr_item_prijs),
MAX (isg.ins_discipline_key),
MAX (COALESCE (bo.bes_bestelopdr_korting, 0)),
MAX (COALESCE (bo.bes_bestelopdr_levkosten, 0))
INTO bestelbedrag, discipline, korting, levkosten
FROM bes_bestelopdr_item boi,
bes_bestelling_item bbi,
ins_srtdeel isd,
ins_srtgroep isg,
bes_bestelopdr bo
WHERE boi.bes_bestelopdr_item_key = bbi.bes_bestelopdr_item_key
AND bo.bes_bestelopdr_key = boi.bes_bestelopdr_key
AND bbi.ins_srtdeel_key = isd.ins_srtdeel_key
AND isd.ins_srtgroep_key = isg.ins_srtgroep_key
AND boi.bes_bestelopdr_key = b_key;
bestelbedrag := bestelbedrag - korting + levkosten;
SELECT SUM (fin_factuur_totaal) -- is excl BTW
INTO totaalgefactureerd
FROM fin_factuur
WHERE bes_bestelopdr_key = b_key AND fin_factuur_statuses_key <> 1 AND fin_factuur_datum <= factuurdatum;
IF tolerantiematch (discipline, ftype, totaalgefactureerd, bestelbedrag)
THEN
retval := 1;
ELSE
retval := -1;
END IF;
--
-- CONTRACT
--
WHEN ftype = 'C'
THEN
-- controle op termijn bedrag en totaal (later ook factuurschema)
SELECT c.cnt_contract_termijnkosten, c.cnt_contract_kosten, c.ins_discipline_key
INTO contracttermijnkosten, contractkosten, discipline
FROM cnt_contract c
WHERE cnt_contract_key = c_key;
IF contracttermijnkosten IS NULL OR contractkosten IS NULL
THEN
retval := 0;
END IF;
SELECT SUM (fin_factuur_totaal)
INTO totaalgefactureerd
FROM fin_factuur
WHERE cnt_contract_key = c_key AND fin_factuur_statuses_key <> 1 AND fin_factuur_datum <= factuurdatum;
IF tolerantiematch (discipline, ftype, totaalgefactureerd, contractkosten)
AND tolerantiematch (discipline, ftype, factuurbedrag, contracttermijnkosten)
THEN
retval := 1;
ELSE
retval := -1;
END IF;
--
-- OPDRACHT
--
WHEN ftype = 'O'
THEN
-- controleer op basis van typeopdr.matchtype
SELECT o.mld_opdr_kosten, m.mld_ins_discipline_key, top.mld_typeopdr_matchtype
INTO opdrachtkosten, discipline, matchtype
FROM mld_opdr o, mld_melding m, mld_typeopdr top
WHERE o.mld_melding_key = m.mld_melding_key
AND o.mld_typeopdr_key = top.mld_typeopdr_key
AND mld_opdr_key = o_key;
DBMS_OUTPUT.put_line ('opdrachtkosten: ' || opdrachtkosten);
DBMS_OUTPUT.put_line ('matchtype: ' || matchtype);
IF opdrachtkosten IS NULL -- niks van te zeggen
THEN
RETURN 0;
END IF;
IF matchtype = 0 -- altijd goed
THEN
retval := 1;
ELSIF matchtype = 1 -- 1 factuur moet matchen met opdracht
THEN
IF tolerantiematch (discipline, ftype, factuurbedrag, opdrachtkosten)
THEN
retval := 1;
ELSE
retval := -1;
END IF;
ELSIF matchtype = 2 -- 2 termijnfactuur
THEN
SELECT SUM (fin_factuur_totaal)
INTO totaalgefactureerd
FROM fin_factuur
WHERE mld_opdr_key = o_key AND fin_factuur_statuses_key <> 1 AND fin_factuur_datum <= factuurdatum;
IF tolerantiematch (discipline, ftype, totaalgefactureerd, opdrachtkosten)
THEN
retval := 1;
ELSE
retval := -1;
END IF;
ELSE --IF matchtype = 3 THEN
DBMS_OUTPUT.put_line ('matchtype unsupported yet!');
RETURN 0;
END IF;
SELECT SUM (fin_factuur_totaal)
INTO totaalgefactureerd
FROM fin_factuur
WHERE mld_opdr_key = o_key AND fin_factuur_statuses_key <> 1 AND fin_factuur_datum <= factuurdatum;
IF tolerantiematch (discipline, ftype, totaalgefactureerd, opdrachtkosten)
THEN
retval := 1;
ELSE
retval := -1;
END IF;
ELSE
retval := 0;
END CASE;
RETURN retval;
END;
-- Keurt een ingevoerde factuur (onvoorwaardelijk) goed of (als rejecttoo) af op basis van de matchingscriteria
PROCEDURE matchandsetfactuur (pfactuur_key IN NUMBER, prejecttoo IN BOOLEAN)
IS
BEGIN
CASE fin.matchfactuur (pfactuur_key)
WHEN 1
THEN
fin.setfactuurstatus (pfactuur_key, 6, NULL);
WHEN -1
THEN
IF prejecttoo
THEN
fin.setfactuurstatus (pfactuur_key, 1, NULL);
END IF;
ELSE NULL;
END CASE;
END;
-- Behandelt een ingevoerde factuur conform settings en matchingscriteria
PROCEDURE autoapprovefactuur (pfactuur_key IN NUMBER)
IS
ftype VARCHAR2 (1);
c_key fin_factuur.cnt_contract_key%TYPE;
b_key fin_factuur.bes_bestelopdr_key%TYPE;
o_key fin_factuur.mld_opdr_key%TYPE;
factuurappr bes_disc_params.bes_disc_params_factuurappr%TYPE;
BEGIN
SELECT mld_opdr_key, cnt_contract_key, bes_bestelopdr_key
INTO o_key, c_key, b_key
FROM fin_factuur
WHERE fin_factuur_key = pfactuur_key;
ftype := fin.getreferentietype (o_key, c_key, b_key);
-- Jammer dat ik ook hier nog eens de discipline moet bepalen
CASE
WHEN ftype = 'B'
THEN
SELECT p.bes_disc_params_factuurappr
INTO factuurappr
FROM bes_disc_params p
WHERE p.bes_ins_discipline_key =
(SELECT MAX (isg.ins_discipline_key)
FROM bes_bestelopdr_item boi, bes_bestelling_item bbi, ins_srtdeel isd, ins_srtgroep isg
WHERE boi.bes_bestelopdr_item_key = bbi.bes_bestelopdr_item_key
AND bbi.ins_srtdeel_key = isd.ins_srtdeel_key
AND isd.ins_srtgroep_key = isg.ins_srtgroep_key
AND boi.bes_bestelopdr_key = b_key);
WHEN ftype = 'C'
THEN
SELECT p.cnt_disc_params_factuurappr
INTO factuurappr
FROM cnt_disc_params p
WHERE p.cnt_ins_discipline_key = (SELECT c.ins_discipline_key
FROM cnt_contract c
WHERE cnt_contract_key = c_key);
WHEN ftype = 'O'
THEN
SELECT p.mld_disc_params_factuurappr
INTO factuurappr
FROM mld_disc_params p
WHERE p.mld_ins_discipline_key =
(SELECT m.mld_ins_discipline_key
FROM mld_opdr o, mld_melding m, mld_typeopdr top
WHERE o.mld_melding_key = m.mld_melding_key
AND o.mld_typeopdr_key = top.mld_typeopdr_key
AND mld_opdr_key = o_key);
ELSE
factuurappr := 0;
END CASE;
IF factuurappr = 1
THEN
matchandsetfactuur (pfactuur_key, FALSE);
END IF;
END;
END fin;
/
REGISTERRUN('$Workfile: fin_pac.src $','$Revision: 5 $')
#endif // FIN