return: text lang: plpgsql src: | DECLARE --eco.p_stock order by date_fin desc result TEXT; BEGIN UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = null; -- initialisation des pump à première entrée ou au pu des stock selon le paramétrage UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = prix_unitaire FROM ( SELECT article_id, site_id, lieu_id, (MIN(ARRAY[CASE WHEN entree_montant > 0 and entree_quantite > 0 THEN date::text ELSE '2099-12-31' END, oid::text]))[2] as oid FROM eco.p_mouvements_articles LEFT JOIN eco.t_divers ON t_divers.code = 'FORCE_PUMP_STOCK' WHERE t_divers.valeur = '0' GROUP BY 1,2,3 ) sub WHERE p_mouvements_articles.oid = sub.oid AND p_mouvements_articles.site_id = sub.site_id AND p_mouvements_articles.lieu_id = sub.lieu_id AND p_mouvements_articles.article_id = sub.article_id ; UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = CASE WHEN pump_ttc > 0 THEN pump_ttc ELSE pump END FROM ( SELECT article_id, site_id, lieu_id, date_fin, pump, pump_ttc FROM eco.p_stock LEFT JOIN eco.t_divers ON t_divers.code = 'FORCE_PUMP_STOCK' WHERE t_divers.valeur = '1' ) sub WHERE (p_mouvements_articles.lieu_id = sub.lieu_id OR (SELECT COUNT(DISTINCT lieu_id) FROM eco.p_stock) = 1) AND p_mouvements_articles.site_id = sub.site_id AND p_mouvements_articles.article_id = sub.article_id AND sub.date_fin BETWEEN date AND p_mouvements_articles.date_fin ; -- ou si le stock est nul avant et pas après UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = prix_unitaire WHERE prix_unitaire_calcule IS NULL AND stock_quantite_debut <= 0 AND stock_quantite_fin > 0; -- pump 0 si pas de stock UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = 0 WHERE stock_quantite_fin = 0 ; ANALYSE eco.p_mouvements_articles; DROP SEQUENCE IF EXISTS s_mv_sto; CREATE TEMP SEQUENCE s_mv_sto; DROP TABLE IF EXISTS w_mvt_sto; CREATE TEMP TABLE w_mvt_sto AS SELECT nextval(' s_mv_sto'::regclass) AS sequence, *, 0::bigint AS derniere_entree FROM ( SELECT article_id, site_id, lieu_id, date, oid, stock_quantite_fin, entree_quantite, entree_montant, prix_unitaire_calcule, date_fin FROM eco.p_mouvements_articles WHERE date >= date_trunc('month', now()) - interval '3 year' ORDER BY 1,2,3,4,5 ) sub; -- sélection des mouvements d'entrée DROP TABLE IF EXISTS w_periode_sto; CREATE TEMP TABLE w_periode_sto AS SELECT article_id, site_id, lieu_id, date, oid, lead(oid,1) OVER (PARTITION BY article_id, site_id, lieu_id ORDER BY sequence) AS oid_next, lead(date,1) OVER (PARTITION BY article_id, site_id, lieu_id ORDER BY sequence) as date_fin FROM w_mvt_sto WHERE (entree_montant > 0 AND entree_quantite > 0) ORDER BY 1,2,3,4 ; UPDATE w_periode_sto SET date_fin = '2099-12-31' WHERE date_fin IS NULL; -- calcul des dernière entrées UPDATE w_mvt_sto SET derniere_entree = w_periode_sto.oid FROM w_periode_sto WHERE 1=1 AND w_mvt_sto.article_id = w_periode_sto.article_id AND w_mvt_sto.site_id = w_periode_sto.site_id AND w_mvt_sto.lieu_id = w_periode_sto.lieu_id AND (w_mvt_sto.oid = w_periode_sto.oid_next OR (w_mvt_sto.oid > w_periode_sto.oid AND w_mvt_sto.date BETWEEN w_periode_sto.date AND w_periode_sto.date_fin)) ; UPDATE w_mvt_sto SET derniere_entree = w_first_ent.oid FROM (SELECT article_id, site_id, lieu_id, (MIN(ARRAY[date::text, oid::text]))[2]::bigint as oid FROM w_periode_sto GROUP BY 1,2,3) w_first_ent WHERE 1=1 AND derniere_entree = 0 AND w_mvt_sto.article_id = w_first_ent.article_id AND w_mvt_sto.site_id = w_first_ent.site_id AND w_mvt_sto.lieu_id = w_first_ent.lieu_id ; CREATE INDEX w_mvt_article_id ON w_mvt_sto USING btree (article_id); CREATE INDEX w_mvt_site_id ON w_mvt_sto USING btree (site_id); CREATE INDEX w_mvt_lieu_id ON w_mvt_sto USING btree (lieu_id); CREATE INDEX w_mvt_oid ON w_mvt_sto USING btree (oid); ANALYSE w_mvt_sto; -- maj des pump PERFORM base.cti_execute(' UPDATE w_mvt_sto SET prix_unitaire_calcule = base.cti_division(abs(w_mvt_prev.stock_quantite_fin)*w_mvt_prev.prix_unitaire_calcule + abs(w_mvt_sto.entree_montant), abs(w_mvt_prev.stock_quantite_fin) + abs(w_mvt_sto.entree_quantite)) FROM w_mvt_sto w_mvt_prev WHERE 1=1 AND w_mvt_sto.prix_unitaire_calcule IS NULL AND w_mvt_prev.prix_unitaire_calcule IS NOT NULL AND w_mvt_sto.derniere_entree = w_mvt_prev.oid AND (w_mvt_sto.entree_montant != 0)',2000) --select article_id, lieu_id, (MIN(ARRAY[sequence::text, prix_unitaire_calcule::text]))[2] from w_mvt_sto group by 1,2 having (MIN(ARRAY[sequence::text, prix_unitaire_calcule::text]))[2] is null order by 3 desc --select * from eco.v_mouvements_articles_1 where article_id = 6634 and lieu_id = 2 order by date --select * from w_mvt_sto where article_id = 9663 and lieu_id = 2 order by sequence ; -- extension aux mouvements de sortie UPDATE w_mvt_sto SET prix_unitaire_calcule = w_mvt_prev.prix_unitaire_calcule FROM w_mvt_sto w_mvt_prev WHERE 1=1 AND w_mvt_sto.prix_unitaire_calcule IS NULL AND w_mvt_sto.derniere_entree != 0 AND w_mvt_prev.oid = w_mvt_sto.derniere_entree AND w_mvt_prev.prix_unitaire_calcule IS NOT NULL ; -- prise en compte des lieu différents au besoin UPDATE w_mvt_sto SET prix_unitaire_calcule = w_mvt_prev.prix_unitaire_calcule FROM w_mvt_sto w_mvt_prev WHERE 1=1 AND w_mvt_sto.prix_unitaire_calcule IS NULL AND w_mvt_prev.article_id = w_mvt_sto.article_id AND w_mvt_prev.prix_unitaire_calcule IS NOT NULL AND w_mvt_sto.date BETWEEN w_mvt_prev.date AND w_mvt_prev.date_fin AND w_mvt_prev.site_id != w_mvt_sto.site_id AND w_mvt_prev.lieu_id != w_mvt_sto.lieu_id ; -- maj des mouvements UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = round(w_mvt_sto.prix_unitaire_calcule,10) FROM w_mvt_sto WHERE p_mouvements_articles.oid = w_mvt_sto.oid ; -- sinon (au pire si pas d'information) pump = pu UPDATE eco.p_mouvements_articles SET prix_unitaire_calcule = prix_unitaire WHERE 1=1 AND prix_unitaire_calcule IS NULL ; RETURN 'OK'; END;