-- allgemeine Funktionen zu Konten -- -- [ create function konto_typ_min_len() returns int4 as ' DECLARE len int4; BEGIN select INTO len bit_length(mask) from fibu.konten_typen; IF NOT FOUND THEN len := 0; END IF; RETURN len; END; ' language 'plpgsql'; create function konto_typ(text, int4) returns bit varying as ' /* * konto_typ(name, output_len) * * ermittelt den konto_typ zu einem entsprechenden namen. * * dies existierem hauptsaechlich zur besseren lesbar machung von * querys bezueglich konten, folgende query ist verstaendlicher, * wenn auch etwas laenger: * select * from konto where * konto_typ=konto_typ(''AKTIVA''); * als: * select * from konto where * konto_typ=1; * bei der ersten query sieht man intuitiv das nach allen aktiva-konten * gesucht wird, waerend das aus der zweiten nur hervorgeht wenn man * alle Kontentypen im Kopf hat. * * returns: NULL: falls der name nicht in konten_typen existiert * >0: der konten_typ zu dem namen */ DECLARE row fibu.konten_typen%ROWTYPE; min_len int4 := fibu.konto_typ_min_len(); sel text; BEGIN IF $2 < min_len THEN RAISE EXCEPTION ''len is to short''; END IF; sel := ''select mask::BIT('' || $2 || '')>>'' || $2-min_len || '' from fibu.konten_typen where name='' || quote_literal($1); FOR row IN EXECUTE sel LOOP END LOOP; IF NOT FOUND THEN RETURN NULL; ELSE RETURN row.mask; END IF; END; ' language 'plpgsql'; create function "inc_konto_ref_count" (int4) returns int4 as ' /* * inc_konto_ref_count(kto_nr) * * erhoet das Feld used in used_konten um 1, damit wird signalisiert, * das einmal mehr auf dieses Konto referenziert wird. * * returns: -1: Konto passt nicht in aktuellen kontenplan * 0: Konto noch nicht in Konten, daher kein increment * >0: Anzahl der Referenzen nach der erhoehung. */ DECLARE ref_count fibu.used_konten.used%TYPE; konto fibu.konto%ROWTYPE; BEGIN select INTO ref_count used from fibu.used_konten where kto_nr=$1; IF NOT FOUND THEN return -1; END IF; select INTO konto * from fibu.konto where kto_nr=$1; IF NOT FOUND THEN return 0; END IF; ref_count := ref_count + 1; update fibu.used_konten set used=ref_count where kto_nr=$1; RETURN ref_count; END; ' language 'plpgsql'; create function "dec_konto_ref_count" (int4) returns int4 as ' /* * dec_konto_ref_count(kto_nr) * * verringert das Feld used in used_konten um 1, damit wird * signalisiert, das einmal mehr auf dieses Konto referenziert wird. * Es existiert ein trigger, der Konto loescht, wenn keine Referenz * mehr darauf besteht, das koennte zu problemen fuehren, da Konten * fuer die Buchfuehrung auch erhalten bleiben muessen, wenn die * Kunden keinerlei Umsatz mehr produzieren, allerdings sollten dann * auch die Kundeninformationen bestehen bleiben wodurch auch die * Referenz bleibt. * * returns: -1: Konto passt nicht in aktuellen kontenplan * 0: entweder wurde used gerade auf 0 gesetzt, oder es * war bereits 0. * >0: Anzahl der Referenzen nach der verringerung. */ DECLARE ref_count fibu.used_konten.used%TYPE; konto fibu.konto%ROWTYPE; BEGIN select INTO ref_count used from fibu.used_konten where kto_nr=$1; IF NOT FOUND THEN RETURN -1; END IF; IF ref_count = 0 THEN RETURN 0; ELSE ref_count := ref_count - 1; update fibu.used_konten set used=ref_count where kto_nr=$1; END IF; RETURN ref_count; END; ' language 'plpgsql'; create function "chk_konto" (int4,text,bit varying,varchar(8),text, text) returns int4 as ' /* * chk_konto(kto_nr, name, konto_typ, blz, b_kto_nr, b_name) * * ueberpruefen ob das Konto schon in der DB gespeichert ist und * ob es in dem sinne gueltig ist, das in den existierenden * kontenplan passt. * * returns: -1: falsche Parameter * -2: Inkonsistenz endeckt. Es existiert bereits ein * Konto mit dem der Schluessel, aber nicht alle der * Parameter übereinstimmen * -3: Inkonsistenz, Konto passt nicht in den Kontenplan * 0: Konto existiert noch nicht in der DB * >0: Konto existiert bereits, gibt id_person zurück. */ DECLARE idk fibu.konto%ROWTYPE; kot fibu.konto.konto_typ%TYPE; BEGIN IF $1 IS NULL OR $1 < 0 THEN RETURN -1; END IF; select INTO kot konto_typ from fibu.used_konten where kto_nr = $1; IF NOT FOUND OR kot != $3 THEN RETURN -3; END IF; select INTO idk * from fibu.konto where kto_nr = $1; IF NOT FOUND THEN RETURN 0; ELSE IF idk.name <> $2 OR idk.konto_typ <> $3 OR idk.blz <> $4 OR idk.b_kto_nr <> $5 OR idk.b_name <> $5 THEN RETURN -2; END IF; END IF; RETURN idk.kto_nr; END; ' language 'plpgsql'; create function ins_konto(int4,text,bit varying,varchar(8),text,text) returns int4 as ' /* * ins_konto(kto_nr, name, konto_typ, blz, b_kto_nr, b_name) * * fügt eine Konto in die DB ein sofern es nicht schon existiert, * inkonsistenzen erzeugt wuerden, oder die Eingabedaten fehlerhast * sind. * Es muss nur konto_typ angegeben werden, alle anderen Werte koennen * NULL sein. * Ist kto_nr NULL, dann ermittelt die Funktion einen freie Kontonummer * aus dem zu konto_typ gehoerenden Nummernbereich. Dann wird das Konto * angelegt. * Ist sie nicht NULL so wird geprueft ob die zu dem konto_typ gehoert, * wenn das so ist, dann wird chk_konto aufgerufen um zu pruefen * ob das Konto bereits existiert, ist das nicht der Fall dann wird * es angelegt, wenn ein Konto existiert, das nicht zu den gemachten * Angeben passt, dann wird eine Fehlermeldung zurueckgegeben. * ACHTUNG: Hier wird natuerlich noch nicht inc_ref_count_erhoeht, * da noch keine referenz auf das konto existiert. * Das heißt, wenn ein naechster update auf used_konten * nicht den ref_count (used) auf mindestens eins setzt * wird das Konto wieder unmittelbar geloescht. * * returns: 0: wenn die Person nicht eingefuegt werden kann * >0: wenn die Person eingefuegt werden konnte oder bereits * existierte, gibt id_person zurück. */ DECLARE ktn fibu.konto.kto_nr%TYPE; row fibu.used_konten%ROWTYPE; BEGIN IF $1 IS NOT NULL THEN select INTO ktn fibu.chk_konto($1,$2,$3,$4,$5,$6); IF ktn < 0 THEN RETURN 0; END IF; ELSE ktn := 0; PERFORM * from fibu.konten_typen where mask=$3; IF NOT FOUND THEN RETURN 0; END IF; END IF; IF ktn = 0 THEN IF $1 IS NULL THEN select INTO row * from fibu.used_konten where konto_typ=$3 and used=0; IF NOT FOUND THEN RETURN 0; ELSE ktn := row.kto_nr; END IF; ELSE ktn := $1; END IF; insert into fibu.konto (kto_nr,name,konto_typ,blz,b_kto_nr,b_name) values (ktn,$2,$3,$4,$5,$6); END IF; RETURN ktn; END; ' language 'plpgsql'; -- ] -- Ende allgemeine Funktionen --