· 6 years ago · Oct 30, 2019, 01:00 PM
1--Funcoes de apoio
2CREATE OR REPLACE FUNCTION is_cadivend_saida(rede INTEGER, filial INTEGER, nota INTEGER) RETURNS boolean AS $$
3SELECT tip_venda IN ('V', 'O') AND flg_sitcaixa IS NOT NULL FROM cadcvend cv WHERE (cv.cod_rede, cv.cod_filial, cv.num_nota) = (rede, filial, nota)
4$$ LANGUAGE SQL IMMUTABLE;
5
6CREATE OR REPLACE FUNCTION is_lote_saida(rede INTEGER, filial INTEGER, nota INTEGER, sequencial_item INTEGER) RETURNS boolean AS $$
7SELECT tip_venda IN ('V', 'O') AND cv.flg_sitcaixa IS NOT NULL AND iv.flg_estoque = 'S' AND COALESCE(cv.flg_excluido, 'N') = 'N' AND COALESCE(iv.flg_excluido, 'N') = 'N' FROM cadcvend cv
8 JOIN cadivend iv USING (cod_rede, cod_filial, num_nota) WHERE (iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial) = (rede, filial, nota, sequencial_item)
9$$ LANGUAGE SQL IMMUTABLE;
10
11CREATE OR REPLACE FUNCTION is_cadivend_devolucao(rede INTEGER, filial INTEGER, nota INTEGER) RETURNS boolean AS $$
12SELECT tip_venda = 'D' FROM cadcvend cv WHERE (cv.cod_rede, cv.cod_filial, cv.num_nota) = (rede, filial, nota)
13$$ LANGUAGE SQL IMMUTABLE;
14
15CREATE OR REPLACE FUNCTION is_cadccomp_conferido(rede INTEGER, filial INTEGER, fornecedor INTEGER, nota INTEGER, sequencial_nota INTEGER) RETURNS boolean AS $$
16SELECT COALESCE(flg_estoque, 'S') = 'S' FROM cadccomp cc WHERE (cc.cod_rede, cc.cod_filial, cc.cod_fornec, cc.num_nota, cc.num_seqnota) = (rede, filial, fornecedor, nota, sequencial_nota)
17$$ LANGUAGE SQL IMMUTABLE;
18
19CREATE OR REPLACE FUNCTION estornar_operacao_saida(op_saida operacao_saida) RETURNS VOID AS $$
20INSERT INTO public.operacao_saida(
21 cod_operacao, qtd_operacao, cod_rede, cod_filial, cod_reduzido, num_nota, num_sequencial, num_lote, cod_local_armazenagem, flg_estorno)
22VALUES (op_saida.cod_operacao_estorno, op_saida.qtd_operacao * (-1), op_saida.cod_rede, op_saida.cod_filial, op_saida.cod_reduzido,
23 op_saida.num_nota, op_saida.num_sequencial, op_saida.num_lote, op_saida.cod_local_armazenagem, TRUE);
24$$ LANGUAGE SQL;
25
26CREATE OR REPLACE FUNCTION estornar_operacao_entrada(op_entrada operacao_entrada) RETURNS VOID AS $$
27INSERT INTO public.operacao_entrada(
28 cod_operacao, qtd_operacao, cod_rede, cod_filial, cod_reduzido,
29 num_nota_ivend, num_sequencial_ivend, cod_fornec_icomp, num_nota_icomp,
30 num_seqnota_icomp, num_sequencial_icomp, qtd_fator, num_lote, cod_local_armazenagem, flg_estorno)
31VALUES (op_entrada.cod_operacao_estorno, op_entrada.qtd_operacao * (-1), op_entrada.cod_rede, op_entrada.cod_filial,
32 op_entrada.cod_reduzido, op_entrada.num_nota_ivend, op_entrada.num_sequencial_ivend, op_entrada.cod_fornec_icomp, op_entrada.num_nota_icomp,
33 op_entrada.num_seqnota_icomp, op_entrada.num_sequencial_icomp, op_entrada.qtd_fator, op_entrada.num_lote, op_entrada.cod_local_armazenagem, TRUE);
34$$ LANGUAGE SQL;
35
36CREATE OR REPLACE FUNCTION public.compensar_item_devolucao(item cadivend) RETURNS VOID AS
37$BODY$
38DECLARE
39 total_operacoes NUMERIC;
40BEGIN
41
42 SELECT SUM(abs(qtd_operacao)) INTO total_operacoes FROM operacao_entrada
43 WHERE (cod_rede, cod_filial, num_nota_ivend, num_sequencial_ivend) = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial)
44 AND cod_operacao_estorno IS NULL
45 AND flg_estorno IS FALSE;
46
47 IF item.qtd_produto > coalesce(total_operacoes, 0) THEN
48 PERFORM efetivar_devolucao_estoque(item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, item.qtd_produto-coalesce(total_operacoes, 0));
49 END IF;
50
51END
52$BODY$ LANGUAGE plpgsql;
53
54CREATE OR REPLACE FUNCTION public.compensar_item_saida(item cadivend) RETURNS VOID AS
55$BODY$
56DECLARE
57 total_operacoes NUMERIC;
58BEGIN
59
60 SELECT SUM(abs(qtd_operacao)) INTO total_operacoes FROM operacao_saida
61 WHERE (cod_rede, cod_filial, num_nota, num_sequencial) = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial)
62 AND cod_operacao_estorno IS NULL
63 AND flg_estorno IS FALSE;
64
65 IF item.qtd_produto > coalesce(total_operacoes, 0) THEN
66 PERFORM efetivar_saida_estoque(item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, (item.qtd_produto-coalesce(total_operacoes, 0)) * -1);
67 END IF;
68
69END
70$BODY$ LANGUAGE plpgsql;
71
72CREATE OR REPLACE FUNCTION public.compensar_item_entrada(item cadicomp) RETURNS VOID AS
73$BODY$
74DECLARE
75 total_item NUMERIC := item.qtd_produto * COALESCE(item.qtd_fator, 1);
76 total_operacoes NUMERIC;
77BEGIN
78
79 SELECT SUM(qtd_operacao) INTO total_operacoes FROM operacao_entrada
80 WHERE (cod_rede, cod_filial, cod_fornec_icomp, num_nota_icomp, num_seqnota_icomp, num_sequencial_icomp) = (item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial)
81 AND cod_operacao_estorno IS NULL
82 AND flg_estorno IS FALSE;
83
84 IF total_item > COALESCE(total_operacoes, 0) THEN
85 PERFORM efetivar_entrada_estoque(item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, total_item - COALESCE(total_operacoes, 0), 1);
86 END IF;
87
88END
89$BODY$ LANGUAGE plpgsql;
90
91CREATE OR REPLACE FUNCTION public.compensar_lote_devolucao(lote cadlvend) RETURNS VOID AS
92$BODY$
93DECLARE
94 total_item NUMERIC;
95 total_operacoes NUMERIC;
96BEGIN
97
98 SELECT qtd_produto INTO total_item FROM cadivend iv WHERE (cod_rede, cod_filial, num_nota, num_sequencial) = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend);
99 SELECT SUM(abs(qtd_operacao)) INTO total_operacoes FROM operacao_entrada
100 WHERE (cod_rede, cod_filial, num_nota_ivend, num_sequencial_ivend) = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend)
101 AND cod_operacao_estorno IS NULL
102 AND flg_estorno IS FALSE;
103
104 IF total_item > coalesce(total_operacoes, 0) THEN
105 PERFORM efetivar_devolucao_estoque(lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, '[SEM_LOTE]', 1, total_item-coalesce(total_operacoes, 0));
106 END IF;
107
108END
109$BODY$ LANGUAGE plpgsql;
110
111CREATE OR REPLACE FUNCTION public.compensar_lote_saida(lote cadlvend) RETURNS VOID AS
112$BODY$
113DECLARE
114 total_item NUMERIC;
115 total_operacoes NUMERIC;
116BEGIN
117
118 SELECT qtd_produto INTO total_item FROM cadivend iv WHERE (cod_rede, cod_filial, num_nota, num_sequencial) = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend);
119 SELECT SUM(abs(qtd_operacao)) INTO total_operacoes FROM operacao_saida
120 WHERE (cod_rede, cod_filial, num_nota, num_sequencial) = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend)
121 AND cod_operacao_estorno IS NULL
122 AND flg_estorno IS FALSE;
123
124 IF total_item > coalesce(total_operacoes, 0) THEN
125 PERFORM efetivar_saida_estoque(lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, '[SEM_LOTE]', 1, (total_item-coalesce(total_operacoes, 0)) * -1);
126 END IF;
127
128END
129$BODY$ LANGUAGE plpgsql;
130
131CREATE OR REPLACE FUNCTION public.compensar_lote_entrada(lote cadlentd) RETURNS VOID AS
132$BODY$
133DECLARE
134 total_item NUMERIC;
135 total_operacoes NUMERIC;
136BEGIN
137
138 SELECT qtd_produto * COALESCE(qtd_fator, 1) INTO total_item FROM cadicomp ic
139 WHERE (ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota, ic.num_sequencial) = (lote.cod_rede, lote.cod_filial, lote.cod_fornec, lote.num_nota, lote.num_seqnota, lote.num_seqcadicomp);
140 SELECT SUM(qtd_operacao) INTO total_operacoes FROM operacao_entrada
141 WHERE (cod_rede, cod_filial, cod_fornec_icomp, num_nota_icomp, num_seqnota_icomp, num_sequencial_icomp) = (lote.cod_rede, lote.cod_filial, lote.cod_fornec, lote.num_nota, lote.num_seqnota, lote.num_seqcadicomp)
142 AND cod_operacao_estorno IS NULL
143 AND flg_estorno IS FALSE;
144
145 IF total_item > COALESCE(total_operacoes, 0) THEN
146 PERFORM efetivar_entrada_estoque(lote.cod_rede, lote.cod_filial, lote.cod_fornec, lote.num_nota, lote.num_seqnota, lote.num_seqcadicomp, lote.cod_reduzido, '[SEM_LOTE]', 1, total_item - COALESCE(total_operacoes, 0), 1);
147 END IF;
148
149END
150$BODY$ LANGUAGE plpgsql;
151
152--Controle de devolucoes
153CREATE OR REPLACE FUNCTION public.efetivar_devolucao_estoque(rede INTEGER, filial INTEGER, nota INTEGER, sequencial INTEGER, produto INTEGER, lote varchar, local_armazenagem INTEGER, quantidade NUMERIC(16,4))
154 RETURNS void AS
155$BODY$
156DECLARE
157 error_detail TEXT;
158BEGIN
159
160 IF quantidade < 0 THEN
161 RAISE invalid_parameter_value USING MESSAGE = format('Operacao de devolucao nao pode registrar uma quantidade menor que zero: %s', quantidade);
162 END IF;
163
164 INSERT INTO public.operacao_entrada(qtd_operacao, cod_rede, cod_filial, cod_reduzido, num_nota_ivend, num_sequencial_ivend, num_lote, cod_local_armazenagem)
165 VALUES (quantidade, rede, filial, produto, nota, sequencial, lote, local_armazenagem);
166
167 RAISE DEBUG 'Efetivando devolucao. Op: %; Prod.: %; Filial: %-%; Qtde.: %',
168 CURRVAL('operacao_entrada_seq'), produto, rede, filial, quantidade;
169
170EXCEPTION
171 WHEN unique_violation THEN
172 GET STACKED DIAGNOSTICS error_detail = PG_EXCEPTION_DETAIL;
173 RAISE unique_violation USING MESSAGE = 'Operacao de devolucao ja efetivada anteriormente',
174 DETAIL = error_detail,
175 HINT = 'Considere estornar o movimento';
176END;
177$BODY$
178 LANGUAGE plpgsql VOLATILE;
179
180CREATE OR REPLACE FUNCTION public.efetivar_movimento_devolucao(item cadivend)
181 RETURNS VOID AS
182$BODY$
183DECLARE
184 lote cadlvend%rowtype;
185BEGIN
186 --Realiza a movimentacao via lotes
187 FOR lote IN
188 SELECT * FROM cadlvend lv where
189 (lv.cod_rede, lv.cod_filial, lv.num_nota, lv.num_seqcadivend, lv.cod_reduzido) = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido) LOOP
190 if EXISTS(
191 SELECT
192 op.*
193 FROM
194 operacao_entrada op
195 WHERE
196 (op.cod_rede, op.cod_filial, op.num_nota_ivend, op.num_sequencial_ivend, op.cod_reduzido, op.num_lote)
197 = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, lote.num_lote)
198 AND op.cod_operacao_estorno IS NULL
199 AND op.flg_estorno IS FALSE
200 ) THEN
201 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: %. Ignorando...', lote.cod_reduzido, lote.num_lote;
202 CONTINUE;
203 END IF;
204
205 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: % Qtde: %', lote.cod_reduzido, lote.num_lote, lote.qtd_lote;
206 PERFORM efetivar_devolucao_estoque(lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, lote.num_lote, 1, lote.qtd_lote);
207 END LOOP;
208
209 --Realiza a movimentacao atraves do proprio item se nao houverem lotes
210 IF NOT FOUND THEN
211
212 RAISE DEBUG 'Lotes não encontrados, aplicando movimentacao por item';
213
214 if EXISTS(
215 SELECT
216 op.*
217 FROM
218 operacao_entrada op
219 WHERE
220 (op.cod_rede, op.cod_filial, op.num_nota_ivend, op.num_sequencial_ivend, op.cod_reduzido)
221 = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido)
222 AND op.cod_operacao_estorno IS NULL
223 AND op.flg_estorno IS FALSE
224 AND op.num_lote = '[SEM_LOTE]'
225 ) THEN
226 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: ''[SEM_LOTE]''. Ignorando...', item.cod_reduzido;
227 RETURN;
228 END IF;
229
230 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: ''[SEM_LOTE]'' Qtde: %', item.cod_reduzido, item.qtd_produto;
231 PERFORM efetivar_devolucao_estoque(item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, item.qtd_produto);
232 END IF;
233
234 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
235 PERFORM compensar_item_devolucao(item);
236
237END;
238$BODY$
239 LANGUAGE plpgsql VOLATILE;
240
241CREATE OR REPLACE FUNCTION public.efetivar_movimento_devolucao_item()
242 RETURNS trigger AS
243$BODY$
244BEGIN
245
246 PERFORM efetivar_movimento_devolucao(NEW);
247 RETURN NULL;
248
249END;
250$BODY$
251 LANGUAGE plpgsql VOLATILE;
252
253CREATE OR REPLACE FUNCTION public.efetivar_estorno_devolucao_estoque_item()
254 RETURNS trigger AS
255$BODY$
256DECLARE
257 movimento cadivend;
258 operacao operacao_entrada;
259BEGIN
260
261 IF TG_OP = 'DELETE' THEN
262 movimento := OLD;
263 ELSE
264 movimento := NEW;
265 END IF;
266
267 FOR operacao IN
268 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
269 cod_rede = movimento.cod_rede AND
270 cod_filial = movimento.cod_filial AND
271 cod_reduzido = movimento.cod_reduzido AND
272 num_nota_ivend = movimento.num_nota AND
273 num_sequencial_ivend = movimento.num_sequencial AND
274 cod_operacao_estorno IS NULL AND
275 flg_estorno IS FALSE RETURNING *
276 LOOP
277
278 PERFORM estornar_operacao_entrada(operacao);
279
280 RAISE DEBUG 'Efetivando estorno de devolucao. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
281 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
282
283 END LOOP;
284
285 RETURN NULL;
286END;
287$BODY$
288 LANGUAGE plpgsql VOLATILE;
289
290DROP TRIGGER IF EXISTS efetivar_movimento_devolucao_update_tg ON cadivend;
291
292CREATE CONSTRAINT TRIGGER efetivar_movimento_devolucao_update_tg
293 AFTER UPDATE ON public.cadivend INITIALLY DEFERRED FOR EACH ROW
294 WHEN
295 (((NEW.flg_estoque = 'S' AND NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque AND COALESCE(NEW.flg_excluido, 'N') = 'N')
296 OR (COALESCE(NEW.flg_excluido, 'N') = 'N' AND OLD.flg_excluido = 'S')
297 OR (NEW.flg_estoque = 'S' AND NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto AND COALESCE(NEW.flg_excluido, 'N') = 'N'))
298 AND is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
299EXECUTE PROCEDURE public.efetivar_movimento_devolucao_item();
300
301DROP TRIGGER IF EXISTS efetivar_movimento_devolucao_insert_tg ON cadivend;
302
303CREATE CONSTRAINT TRIGGER efetivar_movimento_devolucao_insert_tg
304 AFTER INSERT ON public.cadivend INITIALLY DEFERRED FOR EACH ROW
305 WHEN
306 (NEW.flg_estoque = 'S' AND COALESCE(NEW.flg_excluido, 'N') = 'N' AND is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
307EXECUTE PROCEDURE public.efetivar_movimento_devolucao_item();
308
309DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_estoque_update_tg ON cadivend;
310
311CREATE TRIGGER efetivar_estorno_devolucao_estoque_update_tg
312 AFTER UPDATE ON public.cadivend FOR EACH ROW
313 WHEN (
314 ((NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque AND OLD.flg_estoque = 'S')
315 OR (NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto AND OLD.flg_estoque = 'S')
316 OR (NEW.flg_excluido IS DISTINCT FROM OLD.flg_excluido AND NEW.flg_excluido = 'S')) AND is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
317EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_item();
318
319DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_estoque_delete_tg ON cadivend;
320
321CREATE TRIGGER efetivar_estorno_devolucao_estoque_delete_tg
322 AFTER DELETE ON public.cadivend FOR EACH ROW
323 WHEN (is_cadivend_devolucao(OLD.cod_rede, OLD.cod_filial, OLD.num_nota))
324EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_item();
325
326---------------------- cadcvend --------------------------
327CREATE OR REPLACE FUNCTION public.efetivar_devolucao(devolucao cadcvend)
328 RETURNS VOID AS
329$BODY$
330DECLARE
331 item cadivend%rowtype;
332BEGIN
333
334 FOR item IN
335 SELECT * FROM cadivend iv WHERE
336 (iv.cod_rede, iv.cod_filial, iv.num_nota) = (devolucao.cod_rede, devolucao.cod_filial, devolucao.num_nota)
337 AND iv.flg_estoque = 'S' AND COALESCE(iv.flg_excluido, 'N') = 'N' LOOP
338 PERFORM efetivar_movimento_devolucao(item);
339 END LOOP;
340
341END;
342$BODY$
343 LANGUAGE plpgsql VOLATILE;
344
345CREATE OR REPLACE FUNCTION public.efetivar_movimento_devolucao_cabecalho()
346 RETURNS trigger AS
347$BODY$
348
349BEGIN
350
351 PERFORM public.efetivar_devolucao(NEW);
352
353 RETURN NULL;
354
355END;
356$BODY$
357 LANGUAGE plpgsql VOLATILE;
358
359DROP TRIGGER IF EXISTS efetivar_devolucao_estoque_update_tg ON cadcvend;
360
361CREATE CONSTRAINT TRIGGER efetivar_devolucao_estoque_update_tg
362 AFTER UPDATE ON public.cadcvend INITIALLY DEFERRED FOR EACH ROW
363 WHEN (
364 ((COALESCE(NEW.flg_excluido, 'N') = 'N' AND OLD.flg_excluido = 'S')
365 OR NEW.flg_sitcaixa = '2' AND NEW.flg_sitcaixa IS DISTINCT FROM OLD.flg_sitcaixa)
366 AND NEW.tip_venda = 'D')
367EXECUTE PROCEDURE public.efetivar_movimento_devolucao_cabecalho();
368
369---------ESTORNO CABECALHO
370CREATE OR REPLACE FUNCTION public.efetivar_estorno_devolucao(devolucao cadcvend)
371 RETURNS VOID AS
372$BODY$
373DECLARE
374 operacao operacao_entrada;
375BEGIN
376
377 FOR operacao IN
378 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
379 cod_rede = devolucao.cod_rede AND
380 cod_filial = devolucao.cod_filial AND
381 num_nota_ivend = devolucao.num_nota AND
382 cod_operacao_estorno IS NULL AND
383 flg_estorno IS FALSE RETURNING *
384 LOOP
385
386 PERFORM estornar_operacao_entrada(operacao);
387
388 RAISE DEBUG 'Efetivando estorno de devolucao. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
389 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
390
391 END LOOP;
392
393END;
394$BODY$
395 LANGUAGE plpgsql VOLATILE;
396
397CREATE OR REPLACE FUNCTION public.efetivar_estorno_devolucao_estoque_cabecalho()
398 RETURNS trigger AS
399$BODY$
400DECLARE
401 movimento cadcvend;
402BEGIN
403
404 IF TG_OP = 'DELETE' THEN
405 movimento := OLD;
406 ELSE
407 movimento := NEW;
408 END IF;
409
410 PERFORM public.efetivar_estorno_devolucao(movimento);
411
412 RETURN NEW;
413END;
414$BODY$
415 LANGUAGE plpgsql VOLATILE;
416
417DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_estoque_update_tg ON cadcvend;
418
419CREATE TRIGGER efetivar_estorno_devolucao_estoque_update_tg
420 AFTER UPDATE ON public.cadcvend FOR EACH ROW
421 WHEN (NEW.flg_excluido = 'S' AND NEW.flg_excluido IS DISTINCT FROM OLD.flg_excluido AND NEW.tip_venda = 'D')
422EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_cabecalho();
423
424DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_estoque_delete_tg ON cadcvend;
425
426CREATE TRIGGER efetivar_estorno_devolucao_estoque_delete_tg
427 AFTER DELETE ON public.cadcvend FOR EACH ROW
428 WHEN (OLD.tip_venda = 'D')
429EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_cabecalho();
430
431---------------------- cadlvend --------------------------
432CREATE OR REPLACE FUNCTION public.efetivar_movimento_devolucao_item_lote()
433 RETURNS trigger AS
434$BODY$
435DECLARE
436 operacao operacao_entrada;
437BEGIN
438
439 --Se a operacao for de insercao e existir lotes do tipo [SEM_LOTE] entao o sistema deve estornar todas as movimentacoes para que o usuario informe os lotes corretos
440 IF (TG_OP = 'INSERT') THEN
441 FOR operacao IN
442 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
443 cod_rede = NEW.cod_rede AND
444 cod_filial = NEW.cod_filial AND
445 num_nota_ivend = NEW.num_nota AND
446 num_lote = '[SEM_LOTE]' AND
447 cod_operacao_estorno IS NULL AND
448 flg_estorno IS FALSE RETURNING *
449 LOOP
450
451 PERFORM estornar_operacao_entrada(operacao);
452
453 RAISE DEBUG 'Efetivando estorno de devolucao. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
454 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
455
456 END LOOP;
457 END IF;
458
459 --Efetiva o lote atual
460 PERFORM efetivar_devolucao_estoque(it.cod_rede, it.cod_filial, it.num_nota, it.num_seqcadivend, it.cod_reduzido, it.num_lote, it.cod_local_armazenagem, it.qtd_lote) FROM
461 (SELECT
462 NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend, NEW.cod_reduzido, NEW.num_lote, 1 AS cod_local_armazenagem, NEW.qtd_lote
463
464 EXCEPT
465
466 SELECT
467 cod_rede, cod_filial, num_nota_ivend, num_sequencial_ivend, cod_reduzido, num_lote, cod_local_armazenagem, qtd_operacao
468 FROM
469 operacao_entrada
470 WHERE
471 (cod_rede, cod_filial, num_nota_ivend, num_sequencial_ivend) = (NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend)
472 AND cod_operacao_estorno IS NULL
473 AND flg_estorno IS FALSE
474 ORDER BY num_seqcadivend) AS it;
475
476 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
477 PERFORM compensar_lote_devolucao(NEW);
478
479 RETURN NULL;
480
481END;
482$BODY$
483 LANGUAGE plpgsql VOLATILE;
484
485CREATE OR REPLACE FUNCTION public.efetivar_estorno_devolucao_estoque_item_lote()
486 RETURNS trigger AS
487$BODY$
488DECLARE
489 lote cadlvend;
490 operacao operacao_entrada;
491BEGIN
492
493 IF TG_OP = 'DELETE' THEN
494 lote := OLD;
495 ELSE
496 lote := NEW;
497 END IF;
498
499 FOR operacao IN
500 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
501 cod_rede = lote.cod_rede AND
502 cod_filial = lote.cod_filial AND
503 cod_reduzido = lote.cod_reduzido AND
504 num_nota_ivend = lote.num_nota AND
505 num_sequencial_ivend = lote.num_seqcadivend AND
506 (num_lote = lote.num_lote OR num_lote = '[SEM_LOTE]') AND
507 cod_operacao_estorno IS NULL AND
508 flg_estorno IS FALSE RETURNING *
509 LOOP
510
511 PERFORM estornar_operacao_entrada(operacao);
512
513 RAISE DEBUG 'Efetivando estorno de devolucao. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
514 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
515
516 END LOOP;
517
518 IF TG_OP = 'DELETE' THEN
519 PERFORM compensar_lote_devolucao(lote);
520 END IF;
521
522 RETURN NULL;
523END;
524$BODY$ LANGUAGE plpgsql;
525
526DROP TRIGGER IF EXISTS efetivar_movimento_devolucao_update_item_lote_tg ON cadlvend;
527
528CREATE CONSTRAINT TRIGGER efetivar_movimento_devolucao_update_item_lote_tg
529 AFTER UPDATE ON public.cadlvend INITIALLY DEFERRED FOR EACH ROW
530 WHEN (NEW.qtd_lote IS DISTINCT FROM OLD.qtd_lote AND is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
531EXECUTE PROCEDURE public.efetivar_movimento_devolucao_item_lote();
532
533DROP TRIGGER IF EXISTS efetivar_movimento_devolucao_insert_item_lote_tg ON cadlvend;
534
535CREATE CONSTRAINT TRIGGER efetivar_movimento_devolucao_insert_item_lote_tg
536 AFTER INSERT ON public.cadlvend INITIALLY DEFERRED FOR EACH ROW
537 WHEN (is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
538EXECUTE PROCEDURE public.efetivar_movimento_devolucao_item_lote();
539
540DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_update_item_lote_tg ON cadlvend;
541
542CREATE TRIGGER efetivar_estorno_devolucao_update_item_lote_tg
543 AFTER UPDATE ON public.cadlvend FOR EACH ROW
544 WHEN (NEW.qtd_lote IS DISTINCT FROM OLD.qtd_lote AND is_cadivend_devolucao(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
545EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_item_lote();
546
547DROP TRIGGER IF EXISTS efetivar_estorno_devolucao_estoque_delete_item_lote_tg ON cadlvend;
548
549CREATE TRIGGER efetivar_estorno_devolucao_estoque_delete_item_lote_tg
550 AFTER DELETE ON public.cadlvend FOR EACH ROW
551 WHEN (is_cadivend_devolucao(OLD.cod_rede, OLD.cod_filial, OLD.num_nota))
552EXECUTE PROCEDURE public.efetivar_estorno_devolucao_estoque_item_lote();
553
554--Controle de compras
555CREATE OR REPLACE FUNCTION public.efetivar_entrada_estoque(rede INTEGER, filial INTEGER, fornecedor INTEGER, nota INTEGER, sequencial_nota INTEGER,
556 sequencial INTEGER, produto INTEGER, lote varchar, local_armazenagem INTEGER, quantidade NUMERIC(16,4), fator INTEGER)
557 RETURNS void AS
558$BODY$
559DECLARE
560 error_detail TEXT;
561BEGIN
562
563 IF quantidade < 0 THEN
564 RAISE invalid_parameter_value USING MESSAGE = format('Operacao de entrada nao pode registrar uma quantidade menor que zero: %s', quantidade);
565 END IF;
566
567 INSERT INTO lote (cod_rede, cod_reduzido, num_lote) VALUES (rede, produto, lote) ON CONFLICT DO NOTHING;
568
569 INSERT INTO public.operacao_entrada(qtd_operacao, qtd_fator, cod_rede, cod_filial, cod_reduzido, cod_fornec_icomp, num_nota_icomp,
570 num_seqnota_icomp, num_sequencial_icomp, num_lote, cod_local_armazenagem)
571 VALUES (quantidade * fator, fator, rede, filial, produto, fornecedor, nota, sequencial_nota, sequencial, lote, local_armazenagem);
572
573 RAISE DEBUG 'Efetivando entrada. Op: %; Prod.: %; Filial: %-%; Qtde.: %',
574 CURRVAL('operacao_entrada_seq'), produto, rede, filial, quantidade;
575
576EXCEPTION
577 WHEN unique_violation THEN
578 GET STACKED DIAGNOSTICS error_detail = PG_EXCEPTION_DETAIL;
579 RAISE unique_violation USING MESSAGE = 'Operacao de entrada ja efetivada anteriormente',
580 DETAIL = error_detail,
581 HINT = 'Considere estornar o movimento';
582END;
583$BODY$
584 LANGUAGE plpgsql VOLATILE;
585
586CREATE OR REPLACE FUNCTION public.efetivar_movimento_entrada(item cadicomp) RETURNS VOID AS
587$BODY$
588DECLARE
589 lote cadlentd%rowtype;
590BEGIN
591
592 --Realiza a movimentacao via lotes
593 FOR lote IN
594 SELECT ld.* FROM cadlentd ld where
595 (ld.cod_rede, ld.cod_filial, ld.cod_fornec, ld.num_nota, ld.num_seqnota, ld.num_seqcadicomp)
596 = (item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial) LOOP
597
598 if EXISTS(
599 SELECT
600 op.*
601 FROM
602 operacao_entrada op
603 WHERE
604 (op.cod_rede, op.cod_filial, op.cod_fornec_icomp, op.num_nota_icomp, op.num_seqnota_icomp, op.num_sequencial_icomp, op.num_lote)
605 = (lote.cod_rede, lote.cod_filial, lote.cod_fornec, lote.num_nota, lote.num_seqnota, lote.num_seqcadicomp, lote.num_lote)
606 AND op.cod_operacao_estorno IS NULL
607 AND op.flg_estorno IS FALSE
608 ) THEN
609 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: %. Ignorando...', lote.cod_reduzido, lote.num_lote;
610 CONTINUE;
611 END IF;
612
613 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: % Qtde: % Fator: %', lote.cod_reduzido, lote.num_lote, lote.qtd_entrada, lote.qtd_fator;
614 PERFORM efetivar_entrada_estoque(
615 lote.cod_rede, lote.cod_filial, lote.cod_fornec, lote.num_nota, lote.num_seqnota, lote.num_seqcadicomp, lote.cod_reduzido, lote.num_lote, 1, lote.qtd_entrada, coalesce(lote.qtd_fator, 1));
616
617 END LOOP;
618
619 --Realiza a movimentacao atraves do proprio item se nao houverem lotes
620 IF NOT FOUND THEN
621
622 RAISE DEBUG 'Lotes não encontrados, aplicando movimentacao por item';
623
624 if EXISTS(
625 SELECT
626 *
627 FROM
628 operacao_entrada op
629 WHERE
630 (op.cod_rede, op.cod_filial, op.cod_fornec_icomp, op.num_nota_icomp, op.num_seqnota_icomp, op.num_sequencial_icomp)
631 = (item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial)
632 AND op.cod_operacao_estorno IS NULL
633 AND op.flg_estorno IS FALSE
634 AND op.num_lote = '[SEM_LOTE]'
635 ) THEN
636 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: ''[SEM_LOTE]''. Ignorando...', item.cod_reduzido;
637 RETURN;
638 END IF;
639
640 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: ''[SEM_LOTE]'' Qtde: % Fator: %', item.cod_reduzido, item.qtd_produto, coalesce(item.qtd_fator, 1);
641 PERFORM efetivar_entrada_estoque(
642 item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, item.qtd_produto, coalesce(item.qtd_fator, 1));
643
644 END IF;
645
646 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
647 PERFORM compensar_item_entrada(item);
648
649END
650$BODY$ LANGUAGE plpgsql;
651
652CREATE OR REPLACE FUNCTION public.efetivar_movimento_entrada_item()
653 RETURNS trigger AS
654$BODY$
655
656BEGIN
657 PERFORM efetivar_movimento_entrada(NEW);
658 RETURN NULL;
659
660END;
661$BODY$
662 LANGUAGE plpgsql VOLATILE;
663
664CREATE OR REPLACE FUNCTION public.efetivar_estorno_entrada_estoque_item()
665 RETURNS trigger AS
666$BODY$
667DECLARE
668 movimento cadicomp;
669 operacao operacao_entrada;
670BEGIN
671
672 IF TG_OP = 'DELETE' THEN
673 movimento := OLD;
674 ELSE
675 movimento := NEW;
676 END IF;
677
678 FOR operacao IN
679 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
680 cod_rede = movimento.cod_rede AND
681 cod_filial = movimento.cod_filial AND
682 cod_fornec_icomp = movimento.cod_fornec AND
683 cod_reduzido = movimento.cod_reduzido AND
684 num_nota_icomp = movimento.num_nota AND
685 num_seqnota_icomp = movimento.num_seqnota AND
686 num_sequencial_icomp = movimento.num_sequencial AND
687 cod_operacao_estorno IS NULL AND
688 flg_estorno IS FALSE RETURNING *
689 LOOP
690
691 PERFORM estornar_operacao_entrada(operacao);
692
693 RAISE DEBUG 'Efetivando estorno de entrada. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
694 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
695
696 END LOOP;
697
698 RETURN NULL;
699END;
700$BODY$
701 LANGUAGE plpgsql VOLATILE;
702
703DROP TRIGGER IF EXISTS efetivar_movimento_entrada_update_tg ON cadicomp;
704
705CREATE CONSTRAINT TRIGGER efetivar_movimento_entrada_update_tg
706 AFTER UPDATE ON public.cadicomp INITIALLY DEFERRED FOR EACH ROW
707 WHEN
708 (NEW.qtd_produto IS NOT NULL AND (NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto OR NEW.qtd_fator IS DISTINCT FROM OLD.qtd_fator) AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
709EXECUTE PROCEDURE public.efetivar_movimento_entrada_item();
710
711DROP TRIGGER IF EXISTS efetivar_movimento_entrada_insert_tg ON cadicomp;
712
713CREATE CONSTRAINT TRIGGER efetivar_movimento_entrada_insert_tg
714 AFTER INSERT ON public.cadicomp INITIALLY DEFERRED FOR EACH ROW
715 WHEN
716 (NEW.qtd_produto IS NOT NULL AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
717EXECUTE PROCEDURE public.efetivar_movimento_entrada_item();
718
719DROP TRIGGER IF EXISTS efetivar_estorno_entrada_estoque_update_tg ON cadicomp;
720
721CREATE TRIGGER efetivar_estorno_entrada_estoque_update_tg
722 AFTER UPDATE ON public.cadicomp FOR EACH ROW
723 WHEN ((NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto OR NEW.qtd_fator IS DISTINCT FROM OLD.qtd_fator) AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
724EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_item();
725
726DROP TRIGGER IF EXISTS efetivar_estorno_entrada_estoque_delete_tg ON cadicomp;
727
728CREATE TRIGGER efetivar_estorno_entrada_estoque_delete_tg
729 AFTER DELETE ON public.cadicomp FOR EACH ROW
730 WHEN (is_cadccomp_conferido(OLD.cod_rede, OLD.cod_filial, OLD.cod_fornec, OLD.num_nota, OLD.num_seqnota))
731EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_item();
732
733---------------------- cadccomp --------------------------
734CREATE OR REPLACE FUNCTION public.efetivar_entrada(entrada cadccomp)
735 RETURNS VOID AS
736$BODY$
737DECLARE
738 item cadicomp%rowtype;
739BEGIN
740
741 FOR item IN
742 SELECT * FROM cadicomp ic WHERE
743 (ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota) = (entrada.cod_rede, entrada.cod_filial, entrada.cod_fornec, entrada.num_nota, entrada.num_seqnota) LOOP
744 PERFORM efetivar_movimento_entrada(item);
745 END LOOP;
746
747END;
748$BODY$
749 LANGUAGE plpgsql VOLATILE;
750
751CREATE OR REPLACE FUNCTION public.efetivar_movimento_entrada_cabecalho()
752 RETURNS trigger AS
753$BODY$
754DECLARE
755 item cadicomp%rowtype;
756BEGIN
757
758 PERFORM public.efetivar_entrada(NEW);
759
760 RETURN NULL;
761
762END;
763$BODY$
764 LANGUAGE plpgsql VOLATILE;
765
766DROP TRIGGER IF EXISTS efetivar_entrada_estoque_update_tg ON cadccomp;
767
768CREATE CONSTRAINT TRIGGER efetivar_entrada_estoque_update_tg
769 AFTER UPDATE ON public.cadccomp INITIALLY DEFERRED FOR EACH ROW
770 WHEN (COALESCE(NEW.flg_estoque, 'S') = 'S' AND NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque)
771EXECUTE PROCEDURE public.efetivar_movimento_entrada_cabecalho();
772
773---------ESTORNO CABECALHO
774CREATE OR REPLACE FUNCTION public.efetivar_estorno_entrada(entrada cadccomp)
775 RETURNS VOID AS
776$BODY$
777DECLARE
778 operacao operacao_entrada;
779BEGIN
780
781 FOR operacao IN
782 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
783 cod_rede = entrada.cod_rede AND
784 cod_filial = entrada.cod_filial AND
785 cod_fornec_icomp = entrada.cod_fornec AND
786 num_nota_icomp = entrada.num_nota AND
787 num_seqnota_icomp = entrada.num_seqnota AND
788 cod_operacao_estorno IS NULL AND
789 flg_estorno IS FALSE RETURNING *
790 LOOP
791
792 PERFORM estornar_operacao_entrada(operacao);
793
794 RAISE DEBUG 'Efetivando estorno de entrada. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
795 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
796
797 END LOOP;
798
799END;
800$BODY$
801 LANGUAGE plpgsql VOLATILE;
802
803CREATE OR REPLACE FUNCTION public.efetivar_estorno_entrada_estoque_cabecalho()
804 RETURNS trigger AS
805$BODY$
806DECLARE
807 movimento cadccomp;
808BEGIN
809
810 IF TG_OP = 'DELETE' THEN
811 movimento := OLD;
812 ELSE
813 movimento := NEW;
814 END IF;
815
816 PERFORM public.efetivar_estorno_entrada(movimento);
817
818 RETURN NEW;
819END;
820$BODY$
821 LANGUAGE plpgsql VOLATILE;
822
823DROP TRIGGER IF EXISTS efetivar_estorno_entrada_estoque_update_tg ON cadccomp;
824
825CREATE TRIGGER efetivar_estorno_entrada_estoque_update_tg
826 AFTER UPDATE ON public.cadccomp FOR EACH ROW
827 WHEN (NEW.flg_estoque = 'N' AND NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque)
828EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_cabecalho();
829
830DROP TRIGGER IF EXISTS efetivar_estorno_entrada_estoque_delete_tg ON cadccomp;
831
832CREATE TRIGGER efetivar_estorno_entrada_estoque_delete_tg
833 AFTER DELETE ON public.cadccomp FOR EACH ROW
834 WHEN (COALESCE(OLD.flg_estoque, 'S') = 'S')
835EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_cabecalho();
836
837---------------------- cadlentd --------------------------
838CREATE OR REPLACE FUNCTION public.efetivar_movimento_entrada_item_lote()
839 RETURNS trigger AS
840$BODY$
841DECLARE
842 operacao operacao_entrada;
843 total_item NUMERIC;
844 total_operacoes numeric;
845BEGIN
846
847 --Se a operacao for de insercao e existir lotes do tipo [SEM_LOTE] entao o sistema deve estornar todas as movimentacoes para que o usuario informe os lotes corretos
848 IF (TG_OP = 'INSERT') THEN
849 FOR operacao IN
850 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
851 cod_rede = NEW.cod_rede AND
852 cod_filial = NEW.cod_filial AND
853 cod_reduzido = NEW.cod_reduzido AND
854 num_nota_icomp = NEW.num_nota AND
855 num_seqnota_icomp = NEW.num_seqnota AND
856 num_sequencial_icomp = NEW.num_seqcadicomp AND
857 num_lote = '[SEM_LOTE]' AND
858 cod_operacao_estorno IS NULL AND
859 flg_estorno IS FALSE RETURNING *
860 LOOP
861
862 PERFORM estornar_operacao_entrada(operacao);
863
864 RAISE DEBUG 'Efetivando estorno de entrada. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
865 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
866
867 END LOOP;
868 END IF;
869
870 --Efetiva o lote atual
871 PERFORM efetivar_entrada_estoque(it.cod_rede, it.cod_filial, it.cod_fornec, it.num_nota, it.num_seqnota, it.num_seqcadicomp, it.cod_reduzido, it.num_lote,
872 1, NEW.qtd_entrada, coalesce(NEW.qtd_fator, 1)) FROM
873 (
874 SELECT NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota, NEW.num_seqcadicomp, NEW.cod_reduzido, NEW.num_lote
875
876 EXCEPT
877
878 SELECT
879 cod_rede, cod_filial, cod_fornec_icomp, num_nota_icomp, num_seqnota_icomp, num_sequencial_icomp, cod_reduzido, num_lote
880 FROM
881 operacao_entrada
882 WHERE
883 (cod_rede, cod_filial, cod_fornec_icomp, num_nota_icomp, num_seqnota_icomp, num_sequencial_icomp)
884 = (NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota, NEW.num_seqcadicomp)
885 AND cod_operacao_estorno IS NULL
886 AND flg_estorno IS FALSE
887 ORDER BY num_seqcadicomp) AS it;
888
889 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
890 PERFORM compensar_lote_entrada(NEW);
891
892 RETURN NULL;
893
894END;
895$BODY$
896 LANGUAGE plpgsql VOLATILE;
897
898CREATE OR REPLACE FUNCTION public.efetivar_estorno_entrada_estoque_item_lote()
899 RETURNS trigger AS
900$BODY$
901DECLARE
902 lote cadlentd;
903 operacao operacao_entrada;
904BEGIN
905
906 IF TG_OP = 'DELETE' THEN
907 lote := OLD;
908 ELSE
909 lote := NEW;
910 END IF;
911
912 FOR operacao IN
913 UPDATE operacao_entrada SET cod_operacao_estorno = NEXTVAL('operacao_entrada_seq') WHERE
914 cod_rede = lote.cod_rede AND
915 cod_filial = lote.cod_filial AND
916 cod_reduzido = lote.cod_reduzido AND
917 num_nota_icomp = lote.num_nota AND
918 num_seqnota_icomp = lote.num_seqnota AND
919 num_sequencial_icomp = lote.num_seqcadicomp AND
920 (num_lote = lote.num_lote OR num_lote = '[SEM_LOTE]') AND
921 cod_operacao_estorno IS NULL AND
922 flg_estorno IS FALSE RETURNING *
923 LOOP
924
925 PERFORM estornar_operacao_entrada(operacao);
926
927 RAISE DEBUG 'Efetivando estorno de entrada. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
928 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_entrada_seq');
929
930 END LOOP;
931
932 IF TG_OP = 'DELETE' THEN
933 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
934 PERFORM compensar_lote_entrada(lote);
935 END IF;
936
937 RETURN NULL;
938END;
939$BODY$
940 LANGUAGE plpgsql VOLATILE;
941
942DROP TRIGGER IF EXISTS efetivar_movimento_entrada_update_item_lote_tg ON cadlentd;
943
944CREATE CONSTRAINT TRIGGER efetivar_movimento_entrada_update_item_lote_tg
945 AFTER UPDATE ON public.cadlentd INITIALLY DEFERRED FOR EACH ROW
946 WHEN (NEW.qtd_entrada IS NOT NULL AND (NEW.qtd_entrada IS DISTINCT FROM OLD.qtd_entrada)
947 OR (NEW.qtd_fator IS DISTINCT FROM OLD.qtd_fator) AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
948EXECUTE PROCEDURE public.efetivar_movimento_entrada_item_lote();
949
950DROP TRIGGER IF EXISTS efetivar_movimento_entrada_insert_item_lote_tg ON cadlentd;
951
952CREATE CONSTRAINT TRIGGER efetivar_movimento_entrada_insert_item_lote_tg
953 AFTER INSERT ON public.cadlentd INITIALLY DEFERRED FOR EACH ROW
954 WHEN (NEW.qtd_entrada IS NOT NULL AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
955EXECUTE PROCEDURE public.efetivar_movimento_entrada_item_lote();
956
957DROP TRIGGER IF EXISTS efetivar_estorno_entrada_update_item_lote_tg ON cadlentd;
958
959CREATE TRIGGER efetivar_estorno_entrada_update_item_lote_tg
960 AFTER UPDATE ON public.cadlentd FOR EACH ROW
961 WHEN ((NEW.qtd_entrada IS DISTINCT FROM OLD.qtd_entrada)
962 OR (NEW.qtd_fator IS DISTINCT FROM OLD.qtd_fator) AND is_cadccomp_conferido(NEW.cod_rede, NEW.cod_filial, NEW.cod_fornec, NEW.num_nota, NEW.num_seqnota))
963EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_item_lote();
964
965DROP TRIGGER IF EXISTS efetivar_estorno_entrada_estoque_delete_item_lote_tg ON cadlentd;
966
967CREATE TRIGGER efetivar_estorno_entrada_estoque_delete_item_lote_tg
968 AFTER DELETE ON public.cadlentd FOR EACH ROW
969 WHEN (is_cadccomp_conferido(OLD.cod_rede, OLD.cod_filial, OLD.cod_fornec, OLD.num_nota, OLD.num_seqnota))
970EXECUTE PROCEDURE public.efetivar_estorno_entrada_estoque_item_lote();
971
972--Controle de saidas
973CREATE OR REPLACE FUNCTION public.efetivar_saida_estoque(rede INTEGER, filial INTEGER, nota INTEGER, sequencial INTEGER, produto INTEGER, lote varchar, local_armazenagem INTEGER, quantidade NUMERIC(16,4))
974 RETURNS void AS
975$BODY$
976DECLARE
977 error_detail TEXT;
978BEGIN
979
980 IF quantidade > 0 THEN
981 RAISE invalid_parameter_value USING MESSAGE = format('Operacao de saida nao pode registrar uma quantidade maior que zero: %s', quantidade);
982 END IF;
983
984 INSERT INTO lote (cod_rede, cod_reduzido, num_lote) VALUES (rede, produto, lote) ON CONFLICT DO NOTHING;
985
986 INSERT INTO public.operacao_saida(qtd_operacao, cod_rede, cod_filial, cod_reduzido, num_nota, num_sequencial, num_lote, cod_local_armazenagem)
987 VALUES (quantidade, rede, filial, produto, nota, sequencial, lote, local_armazenagem);
988
989 RAISE DEBUG 'Efetivando saida. Op: %; Prod.: %; Filial: %-%; Qtde.: %',
990 CURRVAL('operacao_saida_seq'), produto, rede, filial, quantidade;
991
992EXCEPTION
993 WHEN unique_violation THEN
994 GET STACKED DIAGNOSTICS error_detail = PG_EXCEPTION_DETAIL;
995 RAISE unique_violation USING MESSAGE = 'Operacao de saida ja efetivada anteriormente',
996 DETAIL = error_detail,
997 HINT = 'Considere estornar o movimento';
998END;
999$BODY$
1000 LANGUAGE plpgsql VOLATILE;
1001
1002CREATE OR REPLACE FUNCTION public.efetivar_movimento_saida(item cadivend)
1003 RETURNS VOID AS
1004$BODY$
1005DECLARE
1006 lote cadlvend%rowtype;
1007BEGIN
1008
1009 --Realiza a movimentacao via lotes
1010 FOR lote IN
1011 SELECT * FROM cadlvend lv where
1012 (lv.cod_rede, lv.cod_filial, lv.num_nota, lv.num_seqcadivend, lv.cod_reduzido)
1013 = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido) LOOP
1014
1015 if EXISTS(
1016 SELECT
1017 op.*
1018 FROM
1019 operacao_saida op
1020 WHERE
1021 (op.cod_rede, op.cod_filial, op.num_nota, op.num_sequencial, op.cod_reduzido, op.num_lote)
1022 = (lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, lote.num_lote)
1023 AND op.cod_operacao_estorno IS NULL
1024 AND op.flg_estorno IS FALSE
1025 ) THEN
1026 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: %. Ignorando...', lote.cod_reduzido, lote.num_lote;
1027 CONTINUE;
1028 END IF;
1029
1030 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: % Qtde: %', lote.cod_reduzido, lote.num_lote, lote.qtd_lote;
1031 PERFORM efetivar_saida_estoque(lote.cod_rede, lote.cod_filial, lote.num_nota, lote.num_seqcadivend, lote.cod_reduzido, lote.num_lote, 1, lote.qtd_lote * -1);
1032 END LOOP;
1033
1034 --Realiza a movimentacao atraves do proprio item se nao houverem lotes
1035 IF NOT FOUND THEN
1036
1037 RAISE DEBUG 'Lotes não encontrados, aplicando movimentacao por item';
1038
1039 if EXISTS(
1040 SELECT
1041 op.*
1042 FROM
1043 operacao_saida op
1044 WHERE
1045 (op.cod_rede, op.cod_filial, op.num_nota, op.num_sequencial, op.cod_reduzido)
1046 = (item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido)
1047 AND op.cod_operacao_estorno IS NULL
1048 AND op.flg_estorno IS FALSE
1049 AND op.num_lote = '[SEM_LOTE]'
1050 ) THEN
1051 RAISE DEBUG 'Operacao encontrada para o Prod.: % Lote: ''[SEM_LOTE]''. Ignorando...', item.cod_reduzido;
1052 RETURN;
1053 END IF;
1054
1055 RAISE DEBUG 'Aplicando alteracao de estoque para o Prod.: % Lote: ''[SEM_LOTE]'' Qtde: %', item.cod_reduzido, item.qtd_produto;
1056 PERFORM efetivar_saida_estoque(item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.cod_reduzido, '[SEM_LOTE]', 1, item.qtd_produto * -1);
1057
1058 END IF;
1059
1060 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
1061 PERFORM compensar_item_saida(item);
1062
1063END;
1064$BODY$
1065 LANGUAGE plpgsql VOLATILE;
1066
1067CREATE OR REPLACE FUNCTION public.efetivar_movimento_saida_item()
1068 RETURNS trigger AS
1069$BODY$
1070BEGIN
1071 PERFORM efetivar_movimento_saida(NEW);
1072 RETURN NULL;
1073END;
1074$BODY$
1075 LANGUAGE plpgsql VOLATILE;
1076
1077CREATE OR REPLACE FUNCTION public.efetivar_estorno_saida_estoque_item()
1078 RETURNS trigger AS
1079$BODY$
1080DECLARE
1081 movimento cadivend;
1082 operacao operacao_saida;
1083BEGIN
1084
1085 IF TG_OP = 'DELETE' THEN
1086 movimento := OLD;
1087 ELSE
1088 movimento := NEW;
1089 END IF;
1090
1091 FOR operacao IN
1092 UPDATE operacao_saida SET cod_operacao_estorno = NEXTVAL('operacao_saida_seq') WHERE
1093 cod_rede = movimento.cod_rede AND
1094 cod_filial = movimento.cod_filial AND
1095 cod_reduzido = movimento.cod_reduzido AND
1096 num_nota = movimento.num_nota AND
1097 num_sequencial = movimento.num_sequencial AND
1098 cod_operacao_estorno IS NULL AND
1099 flg_estorno IS FALSE RETURNING *
1100 LOOP
1101
1102 PERFORM estornar_operacao_saida(operacao);
1103
1104 RAISE DEBUG 'Efetivando estorno de saida. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
1105 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_saida_seq');
1106
1107 END LOOP;
1108
1109 RETURN NULL;
1110END;
1111$BODY$
1112 LANGUAGE plpgsql VOLATILE;
1113
1114DROP TRIGGER IF EXISTS efetivar_movimento_saida_update_tg ON cadivend;
1115
1116CREATE CONSTRAINT TRIGGER efetivar_movimento_saida_update_tg
1117 AFTER UPDATE ON public.cadivend INITIALLY DEFERRED FOR EACH ROW
1118 WHEN
1119 (((NEW.flg_estoque = 'S' AND NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque AND COALESCE(NEW.flg_excluido, 'N') = 'N')
1120 OR (COALESCE(NEW.flg_excluido, 'N') = 'N' AND OLD.flg_excluido = 'S')
1121 OR (NEW.flg_estoque = 'S' AND NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto AND COALESCE(NEW.flg_excluido, 'N') = 'N'))
1122 AND is_cadivend_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
1123EXECUTE PROCEDURE public.efetivar_movimento_saida_item();
1124
1125DROP TRIGGER IF EXISTS efetivar_movimento_saida_insert_tg ON cadivend;
1126
1127CREATE CONSTRAINT TRIGGER efetivar_movimento_saida_insert_tg
1128 AFTER INSERT ON public.cadivend INITIALLY DEFERRED FOR EACH ROW
1129 WHEN
1130 (NEW.flg_estoque = 'S' AND COALESCE(NEW.flg_excluido, 'N') = 'N' AND is_cadivend_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
1131EXECUTE PROCEDURE public.efetivar_movimento_saida_item();
1132
1133DROP TRIGGER IF EXISTS efetivar_estorno_saida_estoque_update_tg ON cadivend;
1134
1135CREATE TRIGGER efetivar_estorno_saida_estoque_update_tg
1136 AFTER UPDATE ON public.cadivend FOR EACH ROW
1137 WHEN (
1138 ((NEW.flg_estoque IS DISTINCT FROM OLD.flg_estoque AND OLD.flg_estoque = 'S')
1139 OR (NEW.qtd_produto IS DISTINCT FROM OLD.qtd_produto AND OLD.flg_estoque = 'S')
1140 OR (NEW.flg_excluido IS DISTINCT FROM OLD.flg_excluido AND NEW.flg_excluido = 'S')) AND is_cadivend_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota))
1141EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_item();
1142
1143DROP TRIGGER IF EXISTS efetivar_estorno_saida_estoque_delete_tg ON cadivend;
1144
1145CREATE TRIGGER efetivar_estorno_saida_estoque_delete_tg
1146 AFTER DELETE ON public.cadivend FOR EACH ROW
1147 WHEN (is_cadivend_saida(OLD.cod_rede, OLD.cod_filial, OLD.num_nota))
1148EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_item();
1149
1150---------------------- cadcvend --------------------------
1151CREATE OR REPLACE FUNCTION public.efetivar_saida(saida cadcvend)
1152 RETURNS VOID AS
1153$BODY$
1154DECLARE
1155 item cadivend%rowtype;
1156BEGIN
1157
1158 FOR item IN
1159 SELECT * FROM cadivend iv WHERE
1160 (iv.cod_rede, iv.cod_filial, iv.num_nota) = (saida.cod_rede, saida.cod_filial, saida.num_nota)
1161 AND iv.flg_estoque = 'S' AND COALESCE(iv.flg_excluido, 'N') = 'N' LOOP
1162 PERFORM efetivar_movimento_saida(item);
1163 END LOOP;
1164
1165END;
1166$BODY$
1167 LANGUAGE plpgsql VOLATILE;
1168
1169CREATE OR REPLACE FUNCTION public.efetivar_movimento_saida_cabecalho()
1170 RETURNS trigger AS
1171$BODY$
1172BEGIN
1173
1174 PERFORM public.efetivar_saida(NEW);
1175
1176 RETURN NULL;
1177
1178END;
1179$BODY$
1180 LANGUAGE plpgsql VOLATILE;
1181
1182DROP TRIGGER IF EXISTS efetivar_saida_estoque_update_tg ON cadcvend;
1183
1184CREATE CONSTRAINT TRIGGER efetivar_saida_estoque_update_tg
1185 AFTER UPDATE ON public.cadcvend INITIALLY DEFERRED FOR EACH ROW
1186 WHEN (
1187 ((COALESCE(NEW.flg_excluido, 'N') = 'N' AND OLD.flg_excluido = 'S')
1188 OR NEW.flg_sitcaixa = '2' AND NEW.flg_sitcaixa IS DISTINCT FROM OLD.flg_sitcaixa)
1189 AND NEW.tip_venda IN ('V', 'O'))
1190EXECUTE PROCEDURE public.efetivar_movimento_saida_cabecalho();
1191
1192---------ESTORNO CABECALHO
1193CREATE OR REPLACE FUNCTION public.efetivar_estorno_saida(saida cadcvend)
1194 RETURNS VOID AS
1195$BODY$
1196DECLARE
1197 operacao operacao_saida;
1198BEGIN
1199
1200 FOR operacao IN
1201 UPDATE operacao_saida SET cod_operacao_estorno = NEXTVAL('operacao_saida_seq') WHERE
1202 cod_rede = saida.cod_rede AND
1203 cod_filial = saida.cod_filial AND
1204 num_nota = saida.num_nota AND
1205 cod_operacao_estorno IS NULL AND
1206 flg_estorno IS FALSE RETURNING *
1207 LOOP
1208
1209 PERFORM estornar_operacao_saida(operacao);
1210
1211 RAISE DEBUG 'Efetivando estorno de saida. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
1212 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_saida_seq');
1213
1214 END LOOP;
1215
1216END;
1217$BODY$
1218 LANGUAGE plpgsql VOLATILE;
1219
1220CREATE OR REPLACE FUNCTION public.efetivar_estorno_saida_estoque_cabecalho()
1221 RETURNS trigger AS
1222$BODY$
1223DECLARE
1224 movimento cadcvend;
1225BEGIN
1226
1227 IF TG_OP = 'DELETE' THEN
1228 movimento := OLD;
1229 ELSE
1230 movimento := NEW;
1231 END IF;
1232
1233 PERFORM public.efetivar_estorno_saida(movimento);
1234
1235 RETURN NULL;
1236END;
1237$BODY$
1238 LANGUAGE plpgsql VOLATILE;
1239
1240DROP TRIGGER IF EXISTS efetivar_estorno_saida_estoque_update_tg ON cadcvend;
1241
1242CREATE TRIGGER efetivar_estorno_saida_estoque_update_tg
1243 AFTER UPDATE ON public.cadcvend FOR EACH ROW
1244 WHEN (NEW.flg_excluido = 'S' AND NEW.flg_excluido IS DISTINCT FROM OLD.flg_excluido AND NEW.tip_venda IN ('V', 'O'))
1245EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_cabecalho();
1246
1247DROP TRIGGER IF EXISTS efetivar_estorno_saida_estoque_delete_tg ON cadcvend;
1248
1249CREATE TRIGGER efetivar_estorno_saida_estoque_delete_tg
1250 AFTER DELETE ON public.cadcvend FOR EACH ROW
1251 WHEN (OLD.tip_venda IN ('V', 'O'))
1252EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_cabecalho();
1253
1254---------------------- cadlvend --------------------------
1255CREATE OR REPLACE FUNCTION public.efetivar_movimento_saida_item_lote()
1256 RETURNS trigger AS
1257$BODY$
1258DECLARE
1259 operacao operacao_saida;
1260BEGIN
1261
1262 --Se a operacao for de insercao e existir lotes do tipo [SEM_LOTE] entao o sistema deve estornar todas as movimentacoes para que o usuario informe os lotes corretos
1263 IF (TG_OP = 'INSERT') THEN
1264 FOR operacao IN
1265 UPDATE operacao_saida SET cod_operacao_estorno = NEXTVAL('operacao_saida_seq') WHERE
1266 cod_rede = NEW.cod_rede AND
1267 cod_filial = NEW.cod_filial AND
1268 cod_reduzido = NEW.cod_reduzido AND
1269 num_nota = NEW.num_nota AND
1270 num_lote = '[SEM_LOTE]' AND
1271 num_sequencial = NEW.num_seqcadivend AND
1272 cod_operacao_estorno IS NULL AND
1273 flg_estorno IS FALSE RETURNING *
1274 LOOP
1275
1276 PERFORM estornar_operacao_saida(operacao);
1277
1278 RAISE DEBUG 'Efetivando estorno de saida. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
1279 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_saida_seq');
1280
1281 END LOOP;
1282 END IF;
1283
1284 --Efetiva o lote atual
1285 PERFORM efetivar_saida_estoque(it.cod_rede, it.cod_filial, it.num_nota, it.num_seqcadivend, it.cod_reduzido, it.num_lote, it.cod_local_armazenagem, it.qtd_lote) FROM
1286 (SELECT
1287 NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend, NEW.cod_reduzido, NEW.num_lote, 1 AS cod_local_armazenagem, (NEW.qtd_lote * -1) AS qtd_lote
1288
1289 EXCEPT
1290
1291 SELECT
1292 cod_rede, cod_filial, num_nota, num_sequencial, cod_reduzido, num_lote, cod_local_armazenagem, qtd_operacao
1293 FROM
1294 operacao_saida
1295 WHERE
1296 (cod_rede, cod_filial, num_nota, num_sequencial) = (NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend)
1297 AND cod_operacao_estorno IS NULL
1298 AND flg_estorno IS FALSE
1299 ORDER BY num_seqcadivend) AS it;
1300
1301 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
1302 PERFORM compensar_lote_saida(NEW);
1303
1304 RETURN NULL;
1305
1306END;
1307$BODY$
1308 LANGUAGE plpgsql VOLATILE;
1309
1310CREATE OR REPLACE FUNCTION public.efetivar_estorno_saida_estoque_item_lote()
1311 RETURNS trigger AS
1312$BODY$
1313DECLARE
1314 lote cadlvend;
1315 operacao operacao_saida;
1316 total_item NUMERIC;
1317 total_operacoes NUMERIC;
1318BEGIN
1319
1320 IF TG_OP = 'DELETE' THEN
1321 lote := OLD;
1322 ELSE
1323 lote := NEW;
1324 END IF;
1325
1326 FOR operacao IN
1327 UPDATE operacao_saida SET cod_operacao_estorno = NEXTVAL('operacao_saida_seq') WHERE
1328 cod_rede = lote.cod_rede AND
1329 cod_filial = lote.cod_filial AND
1330 cod_reduzido = lote.cod_reduzido AND
1331 num_nota = lote.num_nota AND
1332 num_sequencial = lote.num_seqcadivend AND
1333 (num_lote = lote.num_lote OR num_lote = '[SEM_LOTE]') AND
1334 cod_operacao_estorno IS NULL AND
1335 flg_estorno IS FALSE RETURNING *
1336 LOOP
1337
1338 PERFORM estornar_operacao_saida(operacao);
1339
1340 RAISE DEBUG 'Efetivando estorno de saida. Op: %; Prod.: %; Filial: %-%; Qtde.: %; Estorno Gerado: %',
1341 operacao.cod_operacao, operacao.cod_reduzido, operacao.cod_rede, operacao.cod_filial, operacao.qtd_operacao, CURRVAL('operacao_saida_seq');
1342
1343 END LOOP;
1344
1345 IF TG_OP = 'DELETE' THEN
1346 --Aplica a diferenca que sobrou entre o(s) lote(s) e item para assegurar que estao com a quantidade igual
1347 PERFORM compensar_lote_saida(lote);
1348 END IF;
1349
1350 RETURN NULL;
1351END;
1352$BODY$
1353 LANGUAGE plpgsql VOLATILE;
1354
1355DROP TRIGGER IF EXISTS efetivar_movimento_saida_update_item_lote_tg ON cadlvend;
1356
1357CREATE CONSTRAINT TRIGGER efetivar_movimento_saida_update_item_lote_tg
1358 AFTER UPDATE ON public.cadlvend INITIALLY DEFERRED FOR EACH ROW
1359 WHEN (NEW.qtd_lote IS DISTINCT FROM OLD.qtd_lote AND is_lote_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend))
1360EXECUTE PROCEDURE public.efetivar_movimento_saida_item_lote();
1361
1362DROP TRIGGER IF EXISTS efetivar_movimento_saida_insert_item_lote_tg ON cadlvend;
1363
1364CREATE CONSTRAINT TRIGGER efetivar_movimento_saida_insert_item_lote_tg
1365 AFTER INSERT ON public.cadlvend INITIALLY DEFERRED FOR EACH ROW
1366 WHEN (is_lote_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend))
1367EXECUTE PROCEDURE public.efetivar_movimento_saida_item_lote();
1368
1369DROP TRIGGER IF EXISTS efetivar_estorno_saida_update_item_lote_tg ON cadlvend;
1370
1371CREATE TRIGGER efetivar_estorno_saida_update_item_lote_tg
1372 AFTER UPDATE ON public.cadlvend FOR EACH ROW
1373 WHEN (NEW.qtd_lote IS DISTINCT FROM OLD.qtd_lote AND is_lote_saida(NEW.cod_rede, NEW.cod_filial, NEW.num_nota, NEW.num_seqcadivend))
1374EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_item_lote();
1375
1376DROP TRIGGER IF EXISTS efetivar_estorno_saida_estoque_delete_item_lote_tg ON cadlvend;
1377
1378CREATE TRIGGER efetivar_estorno_saida_estoque_delete_item_lote_tg
1379 AFTER DELETE ON public.cadlvend FOR EACH ROW
1380 WHEN (is_lote_saida(OLD.cod_rede, OLD.cod_filial, OLD.num_nota, OLD.num_seqcadivend))
1381EXECUTE PROCEDURE public.efetivar_estorno_saida_estoque_item_lote();
1382
1383--Validando as constraints
1384DO $$
1385 DECLARE
1386 con RECORD;
1387 BEGIN
1388
1389 FOR con IN SELECT conrelid::regclass AS tablename, conname FROM pg_constraint WHERE NOT convalidated LOOP
1390 EXECUTE format('ALTER TABLE %I VALIDATE CONSTRAINT %I', con.tablename, con.conname);
1391 RAISE DEBUG 'Validating constraint: %.%', con.tablename, con.conname;
1392 END LOOP;
1393
1394 END $$;
1395
1396--Funcoes de manipulacao de estoque
1397CREATE OR REPLACE FUNCTION manipular_estoque(operacao anyelement) RETURNS NUMERIC AS $$
1398 WITH op AS (
1399 INSERT INTO alteracoes_estoque(cod_rede, cod_filial, cod_reduzido, qtd_operacao) VALUES (operacao.cod_rede, operacao.cod_filial, operacao.cod_reduzido, operacao.qtd_operacao) RETURNING *
1400 )
1401 INSERT INTO public.estoque (cod_rede, cod_filial, cod_reduzido, qtd_estoque) SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao FROM op
1402 ON CONFLICT ON CONSTRAINT estoque_pkey DO UPDATE SET qtd_estoque = (estoque.qtd_estoque + EXCLUDED.qtd_estoque) RETURNING qtd_estoque;
1403$$ LANGUAGE SQL;
1404
1405CREATE OR REPLACE FUNCTION manipular_estoque_lote(operacao anyelement) RETURNS NUMERIC AS $$
1406INSERT INTO public.estoque_lote (cod_rede, cod_filial, cod_reduzido, num_lote, qtd_estoque) VALUES (operacao.cod_rede, operacao.cod_filial, operacao.cod_reduzido, operacao.num_lote, operacao.qtd_operacao)
1407ON CONFLICT ON CONSTRAINT estoque_lote_pkey DO UPDATE SET qtd_estoque = (estoque_lote.qtd_estoque + EXCLUDED.qtd_estoque) RETURNING qtd_estoque;
1408$$ LANGUAGE SQL;
1409
1410--Gateways
1411CREATE OR REPLACE FUNCTION public.executar_gateway_operacao_entrada()
1412 RETURNS trigger AS
1413$BODY$
1414BEGIN
1415 NEW.num_dia := date_part('day', NEW.dat_operacao);
1416 NEW.num_mes := date_part('month', NEW.dat_operacao);
1417 NEW.num_ano := date_part('year', NEW.dat_operacao);
1418 NEW.qtd_estoque_efetivado := manipular_estoque(NEW);
1419 NEW.qtd_estoque_lote_efetivado := manipular_estoque_lote(NEW);
1420 RETURN NEW;
1421END;
1422$BODY$
1423 LANGUAGE plpgsql VOLATILE;
1424
1425DO $$
1426 BEGIN
1427 CREATE TRIGGER gateway_operacao_entrada_tg
1428 BEFORE INSERT ON public.operacao_entrada FOR EACH ROW
1429 EXECUTE PROCEDURE public.executar_gateway_operacao_entrada();
1430 EXCEPTION
1431 WHEN duplicate_object THEN
1432 RAISE NOTICE 'Trigger existente detectada. Ignorando criacao...';
1433 END$$;
1434
1435
1436CREATE OR REPLACE FUNCTION public.executar_gateway_operacao_saida()
1437 RETURNS trigger AS
1438$BODY$
1439BEGIN
1440 NEW.num_dia := date_part('day', NEW.dat_operacao);
1441 NEW.num_mes := date_part('month', NEW.dat_operacao);
1442 NEW.num_ano := date_part('year', NEW.dat_operacao);
1443 NEW.qtd_estoque_efetivado := manipular_estoque(NEW);
1444 NEW.qtd_estoque_lote_efetivado := manipular_estoque_lote(NEW);
1445 RETURN NEW;
1446END;
1447$BODY$
1448 LANGUAGE plpgsql VOLATILE;
1449
1450DO $$
1451BEGIN
1452 CREATE TRIGGER gateway_operacao_saida_tg
1453 BEFORE INSERT ON public.operacao_saida FOR EACH ROW
1454 EXECUTE PROCEDURE public.executar_gateway_operacao_saida();
1455EXCEPTION
1456 WHEN duplicate_object THEN
1457 RAISE NOTICE 'Trigger existente detectada. Ignorando criacao...';
1458END$$;
1459
1460DROP FUNCTION IF EXISTS alteracoes_estoque_notify() CASCADE;
1461
1462CREATE OR REPLACE FUNCTION alteracoes_estoque_notify() RETURNS TRIGGER AS $$
1463begin
1464 NOTIFY alteracao_estoque;
1465 RETURN NEW;
1466end
1467$$ language plpgsql;
1468
1469DROP TRIGGER IF EXISTS alteracoes_estoque_notify_tg ON alteracoes_estoque;
1470CREATE TRIGGER alteracoes_estoque_notify_tg AFTER INSERT ON alteracoes_estoque FOR EACH STATEMENT EXECUTE PROCEDURE alteracoes_estoque_notify();
1471
1472--PROTECAO CADESTOQ
1473DROP FUNCTION IF EXISTS public.cadestoq_protecao_novo_estoque() CASCADE;
1474
1475CREATE OR REPLACE FUNCTION public.cadestoq_protecao_novo_estoque() RETURNS trigger AS
1476$BODY$
1477BEGIN
1478
1479 RAISE DEBUG 'Alteracao de estoque. txid: % -> %', txid_current(), fc_get_env('sgfpod1.bypass_cadestoq_protection');
1480 IF NEW.cod_filial IS NOT DISTINCT FROM (SELECT coalesce(cod_filiallogin, cod_filialreplica) FROM cadredes)
1481 AND fc_get_env('sgfpod1.bypass_cadestoq_protection') IS DISTINCT FROM CAST(txid_current() AS TEXT) THEN
1482 RAISE DEBUG 'Tentativa de alteracao de estoque bloqueada, o valor anterior será mantido. Novo: % Antigo: %', NEW.qtd_estoque, OLD.qtd_estoque;
1483 NEW.qtd_estoque := OLD.qtd_estoque;
1484 ELSE
1485 RAISE DEBUG 'Deixou atualizar estoque, de % para %. Conf: %', OLD.qtd_estoque, NEW.qtd_estoque, fc_get_env('sgfpod1.bypass_cadestoq_protection');
1486 END IF;
1487
1488 RETURN NEW;
1489END;
1490$BODY$
1491 LANGUAGE plpgsql VOLATILE;
1492
1493DROP TRIGGER IF EXISTS cadestoq_protecao_novo_estoque_tg ON public.cadestoq;
1494
1495CREATE TRIGGER cadestoq_protecao_novo_estoque_tg
1496 BEFORE UPDATE OF qtd_estoque
1497 ON public.cadestoq
1498 FOR EACH ROW
1499 EXECUTE PROCEDURE public.cadestoq_protecao_novo_estoque();
1500
1501--Views
1502DROP VIEW IF EXISTS public.extrato_estoque_vw;
1503
1504CREATE OR REPLACE VIEW extrato_estoque_vw AS
1505 SELECT
1506 cod_rede, cod_filial, cod_reduzido, num_lote, dat_operacao, qtd_operacao, qtd_estoque_efetivado, qtd_estoque_lote_efetivado
1507 FROM
1508 operacao_entrada
1509 WHERE
1510 cod_operacao_estorno IS NULL
1511 AND NOT flg_estorno
1512 UNION ALL
1513 SELECT
1514 cod_rede, cod_filial, cod_reduzido, num_lote, dat_operacao, qtd_operacao, qtd_estoque_efetivado, qtd_estoque_lote_efetivado
1515 FROM
1516 operacao_saida
1517 WHERE
1518 cod_operacao_estorno IS NULL
1519 AND NOT flg_estorno
1520 ORDER BY
1521 dat_operacao;
1522
1523DROP VIEW IF EXISTS public.diferenca_estoque_persistido_vs_calculado_vw;
1524
1525CREATE OR REPLACE VIEW diferenca_estoque_persistido_vs_calculado_vw AS
1526 WITH operacoes AS (
1527 SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao FROM operacao_entrada
1528 UNION ALL
1529 SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao FROM operacao_saida
1530 ), estoque_calculado AS (
1531 SELECT cod_rede, cod_filial, cod_reduzido, SUM(qtd_operacao) AS qtd_estoque_calculado FROM operacoes GROUP BY cod_rede, cod_filial, cod_reduzido
1532 )
1533 SELECT
1534 e.cod_rede,
1535 e.cod_filial,
1536 e.cod_reduzido,
1537 e.qtd_estoque AS qtd_estoque_persistido,
1538 c.qtd_estoque_calculado,
1539 e.qtd_estoque - c.qtd_estoque_calculado AS diferenca
1540 FROM
1541 estoque e
1542 JOIN estoque_calculado c ON (e.cod_rede, e.cod_filial, e.cod_reduzido) = (c.cod_rede, c.cod_filial, c.cod_reduzido) WHERE e.qtd_estoque <> c.qtd_estoque_calculado
1543 ORDER BY diferenca;
1544
1545DROP VIEW IF EXISTS public.diferenca_estoque_lote_persistido_vs_calculado_vw;
1546
1547CREATE OR REPLACE VIEW diferenca_estoque_lote_persistido_vs_calculado_vw AS
1548 WITH operacoes AS (
1549 SELECT cod_rede, cod_filial, cod_reduzido, num_lote, qtd_operacao FROM operacao_entrada
1550 UNION ALL
1551 SELECT cod_rede, cod_filial, cod_reduzido, num_lote, qtd_operacao FROM operacao_saida
1552 ), estoque_calculado AS (
1553 SELECT cod_rede, cod_filial, cod_reduzido, num_lote, SUM(qtd_operacao) AS qtd_estoque_calculado FROM operacoes GROUP BY cod_rede, cod_filial, cod_reduzido, num_lote
1554 )
1555 SELECT
1556 e.cod_rede,
1557 e.cod_filial,
1558 e.cod_reduzido,
1559 e.num_lote,
1560 e.qtd_estoque AS qtd_estoque_persistido,
1561 c.qtd_estoque_calculado,
1562 e.qtd_estoque - c.qtd_estoque_calculado AS diferenca
1563 FROM
1564 estoque_lote e
1565 JOIN estoque_calculado c ON (e.cod_rede, e.cod_filial, e.cod_reduzido, e.num_lote) = (c.cod_rede, c.cod_filial, c.cod_reduzido, c.num_lote) WHERE e.qtd_estoque <> c.qtd_estoque_calculado
1566 ORDER BY diferenca;
1567
1568DROP VIEW IF exists diferenca_estoque_antigo_e_novo_vw CASCADE;
1569
1570CREATE OR REPLACE view diferenca_estoque_antigo_e_novo_vw AS
1571 SELECT e1.cod_rede,
1572 e1.cod_filial,
1573 e1.cod_reduzido,
1574 e1.qtd_estoque AS qtd_estoque_antigo,
1575 e2.qtd_estoque as qtd_novo_estoque,
1576 e1.qtd_estoque - e2.qtd_estoque AS diferenca
1577 FROM cadestoq e1
1578 JOIN estoque e2 ON e1.cod_rede = e2.cod_rede AND e1.cod_filial = e2.cod_filial AND e1.cod_reduzido = e2.cod_reduzido
1579 JOIN cadprodu pr ON e1.cod_rede = pr.cod_rede AND e1.cod_reduzido = pr.cod_reduzido
1580 WHERE e1.qtd_estoque <> e2.qtd_estoque AND pr.flg_estoque = 'S'
1581 ORDER BY (e1.qtd_estoque - e2.qtd_estoque);
1582
1583--Function para verificacao de inconsistencias
1584DROP FUNCTION IF EXISTS public.verificar_inconsistencias_estoque(boolean);
1585CREATE OR REPLACE FUNCTION public.verificar_inconsistencias_estoque(autofix boolean)
1586 RETURNS boolean AS
1587$BODY$
1588DECLARE
1589 item record;
1590 encontrou_divergencias boolean := FALSE;
1591BEGIN
1592
1593 IF autofix THEN
1594 CREATE TEMP TABLE IF NOT EXISTS entradas_a_refazer(cod_rede INTEGER, cod_filial INTEGER, cod_fornec INTEGER, num_nota INTEGER, num_seqnota INTEGER);
1595 CREATE TEMP TABLE IF NOT EXISTS devolucoes_a_refazer(cod_rede INTEGER, cod_filial INTEGER, num_nota INTEGER);
1596 CREATE TEMP TABLE IF NOT EXISTS saidas_a_refazer(cod_rede INTEGER, cod_filial INTEGER, num_nota INTEGER);
1597 END IF;
1598
1599 SET client_min_messages = DEBUG;
1600
1601 RAISE DEBUG 'Iniciando validação de estoque do produto';
1602
1603 RAISE DEBUG 'Validando Saldo Inicial...';
1604
1605 FOR
1606 item IN
1607 SELECT
1608 sl.qtd_saldo, op.qtd_operacao
1609 FROM
1610 cadsldpr sl
1611 JOIN (
1612 SELECT cod_rede, cod_filial, cod_reduzido, SUM(qtd_operacao) AS qtd_operacao FROM (
1613 SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao FROM operacao_entrada ope WHERE flg_saldo_inicial
1614 UNION ALL
1615 SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao FROM operacao_saida ops WHERE flg_saldo_inicial
1616 ) AS operacoes
1617 GROUP BY cod_rede, cod_filial, cod_reduzido
1618 ) op ON (op.cod_rede = sl.cod_rede AND op.cod_filial = sl.cod_filial AND op.cod_reduzido = sl.cod_reduzido)
1619 JOIN cadredes r ON (r.cod_rede = sl.cod_rede AND COALESCE(r.cod_filiallogin, r.cod_filialreplica) = sl.cod_filial)
1620 WHERE
1621 op.qtd_operacao IS DISTINCT FROM sl.qtd_saldo
1622 LOOP
1623
1624 encontrou_divergencias := TRUE;
1625 RAISE WARNING 'Saldo Inicial incorreto (possivelmente foi alterado após a implantação do novo estoque): (cadsldpr: %; operacoes: %)', item.qtd_saldo, item.qtd_operacao;
1626
1627 END LOOP;
1628
1629 RAISE DEBUG 'Validando Compras...';
1630
1631 FOR
1632 item IN
1633 SELECT
1634 ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota, ic.num_sequencial, (ic.qtd_produto * COALESCE(qtd_fator, 1)) as qtd_entrada, operacao.qtd_operacao, lote.qtd_lote
1635 FROM
1636 cadccomp cc
1637 JOIN cadicomp ic ON (cc.cod_rede, cc.cod_filial, cc.cod_fornec, cc.num_nota, cc.num_seqnota) =
1638 (ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota)
1639 JOIN cadredes r ON (r.cod_rede = cc.cod_rede AND COALESCE(r.cod_filiallogin, r.cod_filialreplica) = cc.cod_filial)
1640 LEFT JOIN LATERAL (
1641 SELECT
1642 sum(qtd_operacao) AS qtd_operacao
1643 FROM
1644 operacao_entrada ope
1645 WHERE (ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota, ic.num_sequencial) =
1646 (ope.cod_rede, ope.cod_filial, ope.cod_fornec_icomp, ope.num_nota_icomp, ope.num_seqnota_icomp, ope.num_sequencial_icomp)) AS operacao ON TRUE
1647 LEFT JOIN LATERAL (
1648 SELECT
1649 sum(qtd_entrada * coalesce(qtd_fator, 1)) AS qtd_lote
1650 FROM
1651 cadlentd ld
1652 WHERE (ic.cod_rede, ic.cod_filial, ic.cod_fornec, ic.num_nota, ic.num_seqnota, ic.num_sequencial, ic.cod_reduzido) =
1653 (ld.cod_rede, ld.cod_filial, ld.cod_fornec, ld.num_nota, ld.num_seqnota, ld.num_seqcadicomp, ld.cod_reduzido)
1654 ) AS lote ON TRUE
1655 WHERE
1656 COALESCE(cc.flg_estoque, 'S') = 'S'
1657 AND (
1658 (lote.qtd_lote IS NOT NULL AND operacao.qtd_operacao IS DISTINCT FROM lote.qtd_lote)
1659 OR operacao.qtd_operacao IS DISTINCT FROM (ic.qtd_produto * COALESCE(qtd_fator, 1))
1660 )
1661
1662 LOOP
1663
1664 encontrou_divergencias := TRUE;
1665 RAISE WARNING 'Item de compra com valor divergente no novo estoque:'
1666 ' (cod_rede = % AND cod_filial = % AND cod_fornec = % AND num_nota = % AND num_seqnota = % AND num_sequencial = %). Icomp: % Oper.: % Lote: % ',
1667 item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota, item.num_sequencial, item.qtd_entrada, item.qtd_operacao, item.qtd_lote;
1668
1669 IF autofix THEN
1670 INSERT INTO entradas_a_refazer VALUES (item.cod_rede, item.cod_filial, item.cod_fornec, item.num_nota, item.num_seqnota);
1671 END IF;
1672
1673 END LOOP;
1674
1675 RAISE DEBUG 'Validando Devolucoes...';
1676
1677 FOR
1678 item IN
1679 SELECT
1680 iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial
1681 FROM cadcvend cv
1682 INNER JOIN cadivend iv ON (cv.cod_rede, cv.cod_filial, cv.num_nota) = (iv.cod_rede, iv.cod_filial, iv.num_nota)
1683 JOIN cadredes r ON (r.cod_rede = cv.cod_rede AND COALESCE(r.cod_filiallogin, r.cod_filialreplica) = cv.cod_filial)
1684 LEFT JOIN operacao_entrada ope ON (iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial) =
1685 (ope.cod_rede, ope.cod_filial, ope.num_nota_ivend, ope.num_sequencial_ivend)
1686 WHERE
1687 iv.flg_estoque = 'S'
1688 AND COALESCE(cv.flg_excluido, 'N') <> 'S'
1689 AND COALESCE(iv.flg_excluido, 'N') <> 'S'
1690 AND cv.tip_venda = 'D'
1691 AND ope.num_nota_ivend IS NULL
1692
1693 LOOP
1694
1695 encontrou_divergencias := TRUE;
1696 RAISE WARNING 'Item de devolucao sem operacao de entrada correspondente: (cod_rede = % AND cod_filial = % AND num_nota = % AND num_sequencial = %)',
1697 item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial;
1698
1699 IF autofix THEN
1700 INSERT INTO devolucoes_a_refazer VALUES (item.cod_rede, item.cod_filial, item.num_nota);
1701 END IF;
1702
1703 END LOOP;
1704
1705 RAISE DEBUG 'Validando Saidas...';
1706
1707 FOR
1708 item IN
1709 SELECT
1710 iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial, iv.qtd_produto, abs(ops.qtd_operacao) as qtd_operacao, lote.qtd_lote
1711 FROM cadcvend cv
1712 INNER JOIN cadivend iv ON (cv.cod_rede, cv.cod_filial, cv.num_nota) = (iv.cod_rede, iv.cod_filial, iv.num_nota)
1713 JOIN cadredes r ON (r.cod_rede = cv.cod_rede AND COALESCE(r.cod_filiallogin, r.cod_filialreplica) = cv.cod_filial)
1714 LEFT JOIN LATERAL (
1715 SELECT
1716 sum(qtd_operacao) as qtd_operacao
1717 FROM
1718 operacao_saida ops
1719 WHERE
1720 (iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial) = (ops.cod_rede, ops.cod_filial, ops.num_nota, ops.num_sequencial)
1721 ) AS ops ON TRUE
1722 LEFT JOIN LATERAL (
1723 SELECT
1724 sum(qtd_lote) AS qtd_lote
1725 FROM
1726 cadlvend lv
1727 WHERE (iv.cod_rede, iv.cod_filial, iv.num_nota, iv.num_sequencial, iv.cod_reduzido)
1728 = (lv.cod_rede, lv.cod_filial, lv.num_nota, lv.num_seqcadivend, lv.cod_reduzido)
1729 ) AS lote ON TRUE
1730 WHERE
1731 iv.flg_estoque = 'S'
1732 AND COALESCE(cv.flg_excluido, 'N') <> 'S'
1733 AND COALESCE(iv.flg_excluido, 'N') <> 'S'
1734 AND (cv.tip_venda IN ('O') OR (cv.tip_venda = 'V' AND cv.flg_sitcaixa IS NOT NULL))
1735 AND ((lote.qtd_lote IS NOT NULL AND iv.qtd_produto IS DISTINCT FROM lote.qtd_lote)
1736 OR iv.qtd_produto IS DISTINCT FROM abs(ops.qtd_operacao)
1737 )
1738
1739 LOOP
1740
1741 encontrou_divergencias := TRUE;
1742 RAISE WARNING 'Item de venda/outras saidas com valor divergente no novo estoque: (cod_rede = % AND cod_filial = % AND num_nota = % AND num_sequencial = %). Cadivend: % Op.: % Lote: %',
1743 item.cod_rede, item.cod_filial, item.num_nota, item.num_sequencial, item.qtd_produto, item.qtd_operacao, item.qtd_lote;
1744
1745 IF autofix THEN
1746 INSERT INTO saidas_a_refazer VALUES (item.cod_rede, item.cod_filial, item.num_nota);
1747 END IF;
1748
1749 END LOOP;
1750
1751 RAISE DEBUG 'Finalizando validacao. %.', (CASE encontrou_divergencias WHEN TRUE THEN 'Divergencias encontradas' ELSE 'Nenhuma divergencia encontrada' END);
1752
1753 IF autofix AND encontrou_divergencias THEN
1754 RAISE DEBUG 'Tentando corrigir automaticamente as divergencias encontradas...';
1755 PERFORM public.refazer_devolucao(cadcvend) FROM cadcvend WHERE (cod_rede, cod_filial, num_nota) = (SELECT DISTINCT cod_rede, cod_filial, num_nota FROM devolucoes_a_refazer);
1756 PERFORM public.refazer_entrada(cadccomp) FROM cadccomp WHERE (cod_rede, cod_filial, cod_fornec, num_nota, num_seqnota) = (SELECT DISTINCT cod_rede, cod_filial, cod_fornec, num_nota, num_seqnota FROM entradas_a_refazer);
1757 PERFORM public.refazer_saida(cadcvend) from cadcvend WHERE (cod_rede, cod_filial, num_nota) = (SELECT DISTINCT cod_rede, cod_filial, num_nota FROM saidas_a_refazer);
1758 RAISE DEBUG 'Processo de correcao finalizado. Verifique as movimentacoes.';
1759 END IF;
1760
1761 RESET client_min_messages;
1762
1763 RETURN encontrou_divergencias;
1764
1765END $BODY$
1766 LANGUAGE plpgsql;
1767
1768DROP FUNCTION IF EXISTS verificar_inconsistencias_estoque();
1769CREATE OR REPLACE FUNCTION public.verificar_inconsistencias_estoque()
1770 RETURNS boolean AS
1771$BODY$
1772 SELECT public.verificar_inconsistencias_estoque(FALSE)
1773$BODY$
1774 LANGUAGE sql;
1775
1776--Triggers temporarias para preenchimento automatico das novas tabelas
1777CREATE OR REPLACE FUNCTION public.insere_lote_atraves_da_cadloted()
1778 RETURNS trigger AS
1779$BODY$
1780BEGIN
1781 INSERT INTO lote (cod_rede, cod_reduzido, num_lote, dat_fabricacao, dat_vencimento)
1782 VALUES (NEW.cod_rede, NEW.cod_reduzido, NEW.num_lote, NEW.dat_fabric, NEW.dat_valid) ON CONFLICT DO NOTHING;
1783 RETURN NEW;
1784END;
1785$BODY$
1786 LANGUAGE plpgsql VOLATILE;
1787
1788DO $$
1789BEGIN
1790 CREATE TRIGGER insere_lote_atraves_da_cadloted_tg
1791 AFTER INSERT ON public.cadloted FOR EACH ROW
1792 EXECUTE PROCEDURE public.insere_lote_atraves_da_cadloted();
1793EXCEPTION
1794 WHEN duplicate_object THEN
1795 RAISE NOTICE 'Trigger existente detectada. Ignorando criacao...';
1796END$$;
1797
1798COMMENT ON FUNCTION public.insere_lote_atraves_da_cadloted() IS '[TEMP] Controle de estoque 2.0';
1799COMMENT ON TRIGGER insere_lote_atraves_da_cadloted_tg ON cadloted IS '[TEMP] Controle de estoque 2.0';
1800
1801CREATE OR REPLACE FUNCTION public.insere_lote_padrao_cadprodu()
1802 RETURNS trigger AS
1803$BODY$
1804BEGIN
1805 INSERT INTO lote (cod_rede, cod_reduzido, num_lote) VALUES (NEW.cod_rede, NEW.cod_reduzido, '[SEM_LOTE]') ON CONFLICT DO NOTHING;
1806 RETURN NEW;
1807END;
1808$BODY$
1809 LANGUAGE plpgsql VOLATILE;
1810
1811DO $$
1812BEGIN
1813 CREATE TRIGGER insere_lote_padrao_cadprodu_tg
1814 AFTER INSERT ON public.cadprodu FOR EACH ROW
1815 EXECUTE PROCEDURE public.insere_lote_padrao_cadprodu();
1816EXCEPTION
1817 WHEN duplicate_object THEN
1818 RAISE NOTICE 'Trigger existente detectada. Ignorando criacao...';
1819END$$;
1820
1821COMMENT ON FUNCTION public.insere_lote_padrao_cadprodu() IS '[TEMP] Controle de estoque 2.0';
1822COMMENT ON TRIGGER insere_lote_padrao_cadprodu_tg ON cadprodu IS '[TEMP] Controle de estoque 2.0';
1823
1824CREATE OR REPLACE FUNCTION public.insere_local_armazenagem_padrao_cadfilia()
1825 RETURNS trigger AS
1826$BODY$
1827BEGIN
1828 INSERT INTO local_armazenagem (cod_rede, cod_filial, cod_local_armazenagem, nom_local_armazenagem) VALUES (NEW.cod_rede, NEW.cod_filial, 1, 'Local Padrao') ON CONFLICT DO NOTHING;
1829 RETURN NEW;
1830END;
1831$BODY$
1832 LANGUAGE plpgsql VOLATILE;
1833
1834DO $$
1835 BEGIN
1836 CREATE TRIGGER insere_local_armazenagem_padrao_cadfilia_tg
1837 AFTER INSERT ON public.cadfilia FOR EACH ROW
1838 EXECUTE PROCEDURE public.insere_local_armazenagem_padrao_cadfilia();
1839 EXCEPTION
1840 WHEN duplicate_object THEN
1841 RAISE NOTICE 'Trigger existente detectada. Ignorando criacao...';
1842 END$$;
1843
1844COMMENT ON FUNCTION public.insere_local_armazenagem_padrao_cadfilia() IS '[TEMP] Controle de estoque 2.0';
1845COMMENT ON TRIGGER insere_local_armazenagem_padrao_cadfilia_tg ON cadfilia IS '[TEMP] Controle de estoque 2.0';
1846
1847--View para análise da implantação
1848DROP VIEW IF EXISTS public.acerto_implantacao_estoque_vw;
1849
1850CREATE OR REPLACE VIEW acerto_implantacao_estoque_vw AS
1851 SELECT cod_rede, cod_filial, cod_reduzido, qtd_operacao AS acerto_entrada, 0 AS acerto_saida FROM operacao_entrada WHERE num_lote = '[ACERTO_IMPLANTACAO]'
1852 UNION ALL
1853 SELECT cod_rede, cod_filial, cod_reduzido, 0, qtd_operacao FROM operacao_saida WHERE num_lote = '[ACERTO_IMPLANTACAO]' order by 1, 2, 3;
1854
1855--Functions para refazer a movimentação
1856CREATE OR REPLACE FUNCTION public.refazer_devolucao(devolucao cadcvend)
1857 RETURNS VOID AS
1858$BODY$
1859BEGIN
1860 PERFORM public.efetivar_estorno_devolucao(devolucao);
1861 PERFORM public.efetivar_devolucao(devolucao);
1862END;
1863$BODY$
1864 LANGUAGE plpgsql VOLATILE;
1865
1866CREATE OR REPLACE FUNCTION public.refazer_entrada(entrada cadccomp)
1867 RETURNS VOID AS
1868$BODY$
1869BEGIN
1870 PERFORM public.efetivar_estorno_entrada(entrada);
1871 PERFORM public.efetivar_entrada(entrada);
1872END;
1873$BODY$
1874 LANGUAGE plpgsql VOLATILE;
1875
1876CREATE OR REPLACE FUNCTION public.refazer_saida(saida cadcvend)
1877 RETURNS VOID AS
1878$BODY$
1879BEGIN
1880 PERFORM public.efetivar_estorno_saida(saida);
1881 PERFORM public.efetivar_saida(saida);
1882END;
1883$BODY$
1884 LANGUAGE plpgsql VOLATILE;