cr_func_konto.sql
8.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
-- 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 --