Costing Recalculation Project Cloudempiere
INTRO
our solution designed allow run on scheduler server, without any touch-intelligent way found when to re-calculate costing records. we have users with habit backdating and re-activating documents, which make quite huge issue with processing order. in worst case, we can run eg 1 month for all material transactions.
example
company period is definitely closed till 31.12.2022. jan, feb closed for document level, the users re-activate or backdating documents to feb 10. so the product cost issue known the scope, and a nightly scheduler convert them by process to product cost queue, take them delete facts, costing from feb 10 to now() then re-submit by accounting engine (invoked by costing recalculation process). the documents are posted sequentially based on view ordering by document processing date or regular document date.
components
- window product cost issue - collect by re-activation, backdating documents which are broke average - driven by event handler
- window product cost queue - when process running, able to collect products eg. all products, un-posted document products, product cost issues, can be extended, they are postgres procedures.
- process costing recalculation. this process when starting . First check period statuses when, closed or not document control closed, then exit. Load all products to hasmap, collect all related products from same documents, then uses rv_document_costing view to take all documents as input.
parameters
- date column: document date/docunent processing date
- schema
- Cost Queue Insert Type> none, all products, un-posted document products, product cost issues
some significant changes affect the core
- schema includes: inventory method: Only Costing (no facts), Periodic (no material facts), Perpetual (costing, accounting - this is legacy)
- we are calculating based on costing records instead of posting (because inventory method). this allow run costing in companies where no posting persisted.
- movementdate field added added to m_costdetail - used for calculate costamt to date
- we added m_transaction_id to m_costdetail_id - allow easier work (not sure required
- we also implement document close level allowing recalculate costing backward in running or previous not audited period.
- product without cost report: IMPORTANT. most of problems coming from this issue.
- report inventory valuation - improved for Average PO.
required changes (IMPORTANT)
- refactor costing and posting classes. atm our process has copy of costing recalculation
We have still lot of questions, mainly what is easier, make a complex costing documentation, make refactor in core, instead developing very complex recalculation process - however this solution is still LIFESAVER.
1 DROP VIEW IF EXISTS rv_document_costing CASCADE;
2
3CREATE OR REPLACE VIEW rv_document_costing
4(
5 ad_client_id,
6 ad_org_id,
7 created,
8 updated,
9 createdby,
10 updatedby,
11 isactive,
12 issotrx,
13 record_id,
14 m_inout_id,
15 c_order_id,
16 c_invoice_id,
17 qty,
18 movementqty,
19 m_product_id,
20 c_uom_id,
21 documentno,
22 datedoc,
23 processingdate,
24 daysdiff,
25 nextprocessingdate,
26 m_attributesetinstance_id,
27 m_movement_id,
28 m_inventory_id,
29 m_inoutline_id,
30 c_orderline_id,
31 c_invoiceline_id,
32 m_matchinv_id,
33 m_inventoryline_id,
34 m_movementline_id,
35 m_matchpo_id,
36 m_productionline_id,
37 ad_table_id,
38 ad_table_line_id,
39 amount,
40 movementtype,
41 processingorder,
42 docbasetype,
43 docsubtype,
44 c_doctype_id,
45 posted,
46 backdated,
47 docdatesseq,
48 creatingseq,
49 procdateseq,
50 dbegbal_qty,
51 dendbal_qty,
52 cbegbal_qty,
53 cendbal_qty,
54 pbegbal_qty,
55 pendbal_qty
56)
57AS
58 SELECT dcc.ad_client_id,
59 dcc.ad_org_id,
60 dcc.created,
61 dcc.updated,
62 dcc.createdby,
63 dcc.updatedby,
64 dcc.isactive,
65 dcc.issotrx,
66 dcc.record_id,
67 dcc.m_inout_id,
68 dcc.c_order_id,
69 dcc.c_invoice_id,
70 dcc.qty,
71 dcc.movementqty,
72 dcc.m_product_id,
73 dcc.c_uom_id,
74 dcc.documentno,
75 dcc.datedoc,
76 dcc.processingdate::timestamp without time zone AS processingdate,
77 dcc.daysdiff,
78 lead(dcc.processingdate::timestamp without time zone) OVER (PARTITION BY dcc.m_product_id ORDER BY dcc.procdateseq) AS nextprocessingdate,
79 dcc.m_attributesetinstance_id,
80 dcc.m_movement_id,
81 dcc.m_inventory_id,
82 dcc.m_inoutline_id,
83 dcc.c_orderline_id,
84 dcc.c_invoiceline_id,
85 dcc.m_matchinv_id,
86 dcc.m_inventoryline_id,
87 dcc.m_movementline_id,
88 dcc.m_matchpo_id,
89 dcc.m_productionline_id,
90 dcc.ad_table_id,
91 dcc.ad_table_line_id,
92 dcc.amount,
93 dcc.movementtype,
94 dcc.processingorder,
95 dcc.docbasetype,
96 dcc.docsubtype,
97 dcc.c_doctype_id,
98 dcc.posted,
99 dcc.backdated,
100 dcc.docdatesseq,
101 dcc.creatingseq,
102 row_number() OVER (PARTITION BY dcc.m_product_id ORDER BY (dcc.processingdate::date), dcc.processingorder, dcc.record_id) AS procdateseq,
103 dcc.dbegbal_qty,
104 dcc.dendbal_qty,
105 dcc.cbegbal_qty,
106 dcc.cendbal_qty,
107 sum(dcc.movementqty) OVER (PARTITION BY dcc.m_product_id ORDER BY (dcc.processingdate::date), dcc.processingorder, dcc.record_id) - dcc.movementqty AS pbegbal_qty,
108 sum(dcc.movementqty) OVER (PARTITION BY dcc.m_product_id ORDER BY (dcc.processingdate::date), dcc.processingorder, dcc.record_id) AS pendbal_qty
109 FROM ( SELECT dcf.ad_client_id,
110 dcf.ad_org_id,
111 dcf.created,
112 dcf.updated,
113 dcf.createdby,
114 dcf.updatedby,
115 dcf.isactive,
116 dcf.issotrx,
117 dcf.record_id,
118 dcf.m_inout_id,
119 dcf.c_order_id,
120 dcf.c_invoice_id,
121 dcf.qty,
122 dcf.movementqty,
123 dcf.m_product_id,
124 dcf.c_uom_id,
125 dcf.documentno,
126 dcf.datedoc,
127 CASE
128 WHEN dcf.pendbal_qty < 0::numeric THEN
129 CASE
130 WHEN lead(dcf.pendbal_qty) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) >= 0::numeric THEN lead(dcf.processingdate) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
131 WHEN lead(dcf.pendbal_qty, 2) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) >= 0::numeric THEN lead(dcf.processingdate, 2) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
132 WHEN lead(dcf.pendbal_qty, 3) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) >= 0::numeric THEN lead(dcf.processingdate, 3) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
133 WHEN lead(dcf.pendbal_qty, 4) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) >= 0::numeric THEN lead(dcf.processingdate, 4) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
134 WHEN lead(dcf.pendbal_qty, 5) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) >= 0::numeric THEN lead(dcf.processingdate, 5) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
135 ELSE lead(dcf.processingdate, 6) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq)
136 END
137 ELSE dcf.processingdate
138 END AS processingdate,
139 dcf.daysdiff,
140 lead(dcf.processingdate) OVER (PARTITION BY dcf.m_product_id ORDER BY dcf.procdateseq) AS nextprocessingdate,
141 dcf.m_attributesetinstance_id,
142 dcf.m_movement_id,
143 dcf.m_inventory_id,
144 dcf.m_inoutline_id,
145 dcf.c_orderline_id,
146 dcf.c_invoiceline_id,
147 dcf.m_matchinv_id,
148 dcf.m_inventoryline_id,
149 dcf.m_movementline_id,
150 dcf.m_matchpo_id,
151 dcf.m_productionline_id,
152 dcf.ad_table_id,
153 dcf.ad_table_line_id,
154 dcf.amount,
155 dcf.movementtype,
156 dcf.processingorder,
157 dcf.docbasetype,
158 dcf.docsubtype,
159 dcf.c_doctype_id,
160 dcf.posted,
161 dcf.backdated,
162 dcf.docdatesseq,
163 dcf.creatingseq,
164 dcf.procdateseq,
165 dcf.dbegbal_qty,
166 dcf.dendbal_qty,
167 dcf.cbegbal_qty,
168 dcf.cendbal_qty,
169 dcf.pendbal_qty
170 FROM ( SELECT dc.ad_client_id,
171 dc.ad_org_id,
172 dc.created,
173 dc.updated,
174 dc.createdby,
175 dc.updatedby,
176 dc.isactive,
177 dc.issotrx,
178 dc.record_id,
179 dc.m_inout_id,
180 dc.c_order_id,
181 dc.c_invoice_id,
182 dc.qty,
183 dc.movementqty,
184 dc.m_product_id,
185 dc.c_uom_id,
186 dc.documentno,
187 dc.datedoc,
188 dc.processingdate,
189 dc.daysdiff,
190 dc.m_attributesetinstance_id,
191 dc.m_movement_id,
192 dc.m_inventory_id,
193 dc.m_inoutline_id,
194 dc.c_orderline_id,
195 dc.c_invoiceline_id,
196 dc.m_matchinv_id,
197 dc.m_inventoryline_id,
198 dc.m_movementline_id,
199 dc.m_matchpo_id,
200 dc.m_productionline_id,
201 dc.ad_table_id,
202 dc.ad_table_line_id,
203 dc.amount,
204 dc.movementtype,
205 dc.processingorder,
206 dc.docbasetype,
207 dc.docsubtype,
208 dc.c_doctype_id,
209 dc.posted,
210 dc.backdated,
211 row_number() OVER (PARTITION BY dc.m_product_id ORDER BY (dc.datedoc::date), dc.processingorder, dc.record_id) AS docdatesseq,
212 row_number() OVER (PARTITION BY dc.m_product_id ORDER BY (dc.created::date), dc.processingorder, dc.record_id) AS creatingseq,
213 row_number() OVER (PARTITION BY dc.m_product_id ORDER BY (dc.processingdate::date), dc.processingorder, dc.record_id) AS procdateseq,
214 sum(dc.movementqty) OVER (PARTITION BY dc.m_product_id ORDER BY (dc.created::date), dc.processingorder, dc.record_id) - dc.movementqty AS cbegbal_qty,
215 sum(dc.movementqty) OVER (PARTITION BY dc.m_product_id ORDER BY (dc.created::date), dc.processingorder, dc.record_id) AS cendbal_qty,
216 sum(dc.movementqty) OVER (PARTITION BY dc.m_product_id ORDER BY (dc.datedoc::date), dc.processingorder, dc.record_id) AS dendbal_qty,
217 sum(dc.movementqty) OVER (PARTITION BY dc.m_product_id ORDER BY (dc.datedoc::date), dc.processingorder, dc.record_id) - dc.movementqty AS dbegbal_qty,
218 sum(dc.movementqty) OVER (PARTITION BY dc.m_product_id ORDER BY (dc.processingdate::date), dc.processingorder, dc.record_id) AS pendbal_qty
219 FROM ( SELECT iol.ad_client_id,
220 io.ad_org_id,
221 io.created,
222 io.updated,
223 io.createdby,
224 io.updatedby,
225 io.isactive,
226 io.issotrx,
227 iol.m_inoutline_id AS record_id,
228 iol.m_inout_id,
229 0 AS c_order_id,
230 0 AS c_invoice_id,
231 iol.movementqty AS qty,
232 CASE
233 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty >= 0::numeric THEN iol.movementqty
234 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty >= 0::numeric THEN iol.movementqty
235 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty < 0::numeric THEN iol.movementqty
236 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty < 0::numeric THEN iol.movementqty
237 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty >= 0::numeric THEN - iol.movementqty
238 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty >= 0::numeric THEN - iol.movementqty
239 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty < 0::numeric THEN - iol.movementqty
240 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty < 0::numeric THEN - iol.movementqty
241 ELSE iol.movementqty
242 END AS movementqty,
243 iol.m_product_id,
244 iol.c_uom_id,
245 io.documentno,
246 io.movementdate AS datedoc,
247 CASE
248 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty >= 0::numeric THEN io.movementdate::timestamp with time zone
249 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty >= 0::numeric THEN io.movementdate::timestamp with time zone
250 ELSE trunc(to_timestamp((io.processedon / 1000::numeric)::double precision), 'DD'::character varying)
251 END AS processingdate,
252 to_char(trunc(to_timestamp((io.processedon / 1000::numeric)::double precision), 'DD'::character varying) - io.movementdate::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
253 iol.m_attributesetinstance_id,
254 0 AS m_movement_id,
255 0 AS m_inventory_id,
256 iol.m_inoutline_id,
257 0 AS c_orderline_id,
258 0 AS c_invoiceline_id,
259 0 AS m_matchinv_id,
260 0 AS m_inventoryline_id,
261 0 AS m_movementline_id,
262 0 AS m_matchpo_id,
263 0 AS m_productionline_id,
264 319 AS ad_table_id,
265 320 AS ad_table_line_id,
266 0::numeric AS amount,
267 CASE
268 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar THEN 'V+'::text
269 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar THEN 'V-'::text
270 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'Y'::bpchar THEN 'C-'::text
271 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'N'::bpchar THEN 'C+'::text
272 ELSE NULL::text
273 END AS movementtype,
274 CASE
275 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty >= 0::numeric THEN 10
276 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty >= 0::numeric THEN 30
277 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty >= 0::numeric THEN 60
278 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty >= 0::numeric THEN 100
279 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty < 0::numeric THEN 80
280 WHEN d.docbasetype = 'MMS'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty < 0::numeric THEN 110
281 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'Y'::bpchar AND iol.movementqty < 0::numeric THEN 130
282 WHEN d.docbasetype = 'MMR'::bpchar AND io.issotrx = 'N'::bpchar AND iol.movementqty < 0::numeric THEN 140
283 ELSE NULL::integer
284 END AS processingorder,
285 d.docbasetype,
286 ''::text AS docsubtype,
287 io.c_doctype_id,
288 io.posted,
289 CASE
290 WHEN trunc(to_timestamp((io.processedon / 1000::numeric)::double precision), 'DD'::character varying) > io.movementdate::date THEN 'B'::text
291 WHEN trunc(to_timestamp((io.processedon / 1000::numeric)::double precision), 'DD'::character varying) < io.movementdate::date THEN 'F'::text
292 ELSE 'N'::text
293 END AS backdated
294 FROM m_inout io
295 JOIN m_inoutline iol ON io.m_inout_id = iol.m_inout_id
296 JOIN c_doctype d ON io.c_doctype_id = d.c_doctype_id
297 WHERE (io.docstatus::text = ANY (ARRAY['CO'::text, 'CL'::text, 'RE'::text, 'VO'::text])) AND (d.docbasetype::text = ANY (ARRAY['MMR'::text, 'MMS'::text]))
298 UNION ALL
299 SELECT il.ad_client_id,
300 il.ad_org_id,
301 il.created,
302 il.updated,
303 il.createdby,
304 il.updatedby,
305 il.isactive,
306 'Y'::character(1) AS issotrx,
307 il.m_inventoryline_id AS record_id,
308 0 AS m_inout_id,
309 0 AS c_order_id,
310 0 AS c_invoice_id,
311 CASE
312 WHEN d.docsubtypeinv::text = 'PI'::text THEN il.qtycount - il.qtybook
313 WHEN d.docsubtypeinv::text = 'CA'::text AND il.qtyinternaluse = 0::numeric THEN 0::numeric
314 WHEN d.docsubtypeinv::text = 'IU'::text AND il.qtyinternaluse > 0::numeric THEN il.qtyinternaluse
315 ELSE NULL::numeric
316 END AS qty,
317 CASE
318 WHEN d.docsubtypeinv::text = 'PI'::text THEN il.qtycount - il.qtybook
319 WHEN d.docsubtypeinv::text = 'CA'::text AND il.qtyinternaluse = 0::numeric THEN 0::numeric
320 WHEN d.docsubtypeinv::text = 'IU'::text AND il.qtyinternaluse > 0::numeric THEN - il.qtyinternaluse
321 ELSE NULL::numeric
322 END AS movementqty,
323 il.m_product_id,
324 p.c_uom_id,
325 inv.documentno,
326 inv.movementdate AS datedoc,
327 CASE
328 WHEN inv.movementdate::date < inv.created::date AND il.qtyinternaluse > 0::numeric OR (il.qtycount - il.qtybook) < 0::numeric THEN inv.created::date
329 ELSE inv.movementdate::date
330 END AS processingdate,
331 to_char(trunc(to_timestamp((inv.processedon / 1000::numeric)::double precision), 'DD'::character varying) - inv.movementdate::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
332 il.m_attributesetinstance_id,
333 0 AS m_movement_id,
334 inv.m_inventory_id,
335 0 AS m_inoutline_id,
336 0 AS c_orderline_id,
337 0 AS c_invoiceline_id,
338 0 AS m_matchinv_id,
339 il.m_inventoryline_id,
340 0 AS m_movementline_id,
341 0 AS m_matchpo_id,
342 0 AS m_productionline_id,
343 321 AS ad_table_id,
344 322 AS ad_table_line_id,
345 il.newcostprice AS amount,
346 CASE
347 WHEN d.docsubtypeinv::text = 'PI'::text AND (il.qtycount - il.qtybook) < 0::numeric THEN 'I-'::text
348 WHEN d.docsubtypeinv::text = 'PI'::text AND (il.qtycount - il.qtybook) >= 0::numeric THEN 'I+'::text
349 WHEN d.docsubtypeinv::text = 'CA'::text AND il.qtyinternaluse = 0::numeric THEN 'I'::text
350 WHEN d.docsubtypeinv::text = 'IU'::text AND il.qtyinternaluse > 0::numeric THEN 'I-'::text
351 ELSE NULL::text
352 END AS movementtype,
353 CASE
354 WHEN d.docsubtypeinv::text = 'PI'::text AND (il.qtycount - il.qtybook) >= 0::numeric THEN 25
355 WHEN d.docsubtypeinv::text = 'CA'::text AND il.qtyinternaluse = 0::numeric THEN 20
356 WHEN d.docsubtypeinv::text = 'IU'::text AND il.qtyinternaluse > 0::numeric THEN 150
357 WHEN d.docsubtypeinv::text = 'PI'::text AND (il.qtycount - il.qtybook) < 0::numeric THEN 160
358 ELSE NULL::integer
359 END AS processingorder,
360 d.docbasetype,
361 CASE
362 WHEN d.docsubtypeinv::text = 'PI'::text THEN 'Phys. Inv.'::text
363 WHEN d.docsubtypeinv::text = 'CA'::text AND il.qtyinternaluse = 0::numeric THEN 'Cost Adjustment'::text
364 WHEN d.docsubtypeinv::text = 'IU'::text AND il.qtyinternaluse > 0::numeric THEN 'Int. Use'::text
365 ELSE NULL::text
366 END AS docsubtype,
367 inv.c_doctype_id,
368 inv.posted,
369 CASE
370 WHEN trunc(to_timestamp((inv.processedon / 1000::numeric)::double precision), 'DD'::character varying) > inv.movementdate::date THEN 'B'::text
371 WHEN trunc(to_timestamp((inv.processedon / 1000::numeric)::double precision), 'DD'::character varying) < inv.movementdate::date THEN 'F'::text
372 ELSE 'N'::text
373 END AS backdated
374 FROM m_inventory inv
375 JOIN m_inventoryline il ON il.m_inventory_id = inv.m_inventory_id
376 JOIN c_doctype d ON inv.c_doctype_id = d.c_doctype_id
377 JOIN m_product p ON il.m_product_id = p.m_product_id
378 WHERE inv.docstatus::text = ANY (ARRAY['CO'::text, 'CL'::text, 'RE'::text, 'VO'::text])
379 UNION ALL
380 SELECT po.ad_client_id,
381 po.ad_org_id,
382 po.created,
383 po.updated,
384 po.createdby,
385 po.updatedby,
386 po.isactive,
387 'N'::character(1) AS issotrx,
388 po.m_matchpo_id AS record_id,
389 0 AS m_inout_id,
390 0::numeric AS c_order_id,
391 0 AS c_invoice_id,
392 po.qty,
393 NULL::numeric AS movementqty,
394 po.m_product_id,
395 ol.c_uom_id,
396 po.documentno,
397 po.dateacct AS datedoc,
398 CASE
399 WHEN po.qty > 0::numeric THEN po.dateacct::timestamp with time zone
400 ELSE trunc(to_timestamp((po.processedon / 1000::numeric)::double precision), 'DD'::character varying)
401 END AS processingdate,
402 to_char(trunc(to_timestamp((po.processedon / 1000::numeric)::double precision), 'DD'::character varying) - po.dateacct::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
403 po.m_attributesetinstance_id,
404 0 AS m_movement_id,
405 0 AS m_inventory_id,
406 0 AS m_inoutline_id,
407 po.c_orderline_id,
408 0 AS c_invoiceline_id,
409 0 AS m_matchinv_id,
410 0 AS m_inventoryline_id,
411 0 AS m_movementline_id,
412 po.m_matchpo_id,
413 0 AS m_productionline_id,
414 473 AS ad_table_id,
415 473 AS ad_table_line_id,
416 ol.priceentered AS amount,
417 'MO'::text AS movementtype,
418 5 AS processingorder,
419 NULL::bpchar AS docbasetype,
420 ''::text AS docsubtype,
421 1001564::numeric AS c_doctype_id,
422 po.posted,
423 CASE
424 WHEN trunc(to_timestamp((po.processedon / 1000::numeric)::double precision), 'DD'::character varying) > po.dateacct::date THEN 'B'::text
425 WHEN trunc(to_timestamp((po.processedon / 1000::numeric)::double precision), 'DD'::character varying) < po.dateacct::date THEN 'F'::text
426 ELSE 'N'::text
427 END AS backdated
428 FROM m_matchpo po
429 LEFT JOIN c_orderline ol ON po.c_orderline_id = ol.c_orderline_id
430 UNION ALL
431 SELECT il.ad_client_id,
432 il.ad_org_id,
433 il.created,
434 il.updated,
435 il.createdby,
436 il.updatedby,
437 il.isactive,
438 i.issotrx,
439 lca.c_landedcostallocation_id AS record_id,
440 0 AS m_inout_id,
441 0 AS c_order_id,
442 il.c_invoice_id,
443 lca.qty,
444 0 AS movementqty,
445 lca.m_product_id,
446 il.c_uom_id,
447 i.documentno,
448 i.dateinvoiced AS datedoc,
449 trunc(to_timestamp((io2.processedon / 1000::numeric)::double precision), 'DD'::character varying) AS processingdate,
450 to_char(trunc(to_timestamp((io2.processedon / 1000::numeric)::double precision), 'DD'::character varying) - io2.movementdate::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
451 lca.m_attributesetinstance_id,
452 0 AS m_movement_id,
453 0 AS m_inventory_id,
454 0 AS m_inoutline_id,
455 0 AS c_orderline_id,
456 il.c_invoiceline_id,
457 0 AS m_matchinv_id,
458 0 AS m_inventoryline_id,
459 0 AS m_movementline_id,
460 0 AS m_matchpo_id,
461 0 AS m_productionline_id,
462 318 AS ad_table_id,
463 333 AS ad_table_line_id,
464 lca.amt AS amount,
465 'L'::text AS movementtype,
466 12 AS processingorder,
467 d.docbasetype,
468 ''::text AS docsubtype,
469 i.c_doctype_id,
470 i.posted,
471 CASE
472 WHEN trunc(to_timestamp((io2.processedon / 1000::numeric)::double precision), 'DD'::character varying) > i.dateacct::date THEN 'B'::text
473 WHEN trunc(to_timestamp((io2.processedon / 1000::numeric)::double precision), 'DD'::character varying) < i.dateacct::date THEN 'F'::text
474 ELSE 'N'::text
475 END AS backdated
476 FROM c_invoiceline il
477 JOIN c_invoice i ON i.c_invoice_id = il.c_invoice_id AND i.issotrx = 'N'::bpchar AND (i.docstatus::text = ANY (ARRAY['CO'::text, 'CL'::text, 'RE'::text, 'VO'::text]))
478 JOIN c_landedcostallocation lca ON lca.c_invoiceline_id = il.c_invoiceline_id
479 JOIN c_doctype d ON d.c_doctype_id = i.c_doctype_id
480 JOIN m_inoutline iol ON lca.m_inoutline_id = iol.m_inoutline_id
481 JOIN m_inout io2 ON io2.m_inout_id = iol.m_inout_id
482 UNION ALL
483 SELECT mi.ad_client_id,
484 mi.ad_org_id,
485 mi.created,
486 mi.updated,
487 mi.createdby,
488 mi.updatedby,
489 mi.isactive,
490 'N'::character(1) AS issotrx,
491 mi.m_matchinv_id AS record_id,
492 0 AS m_inout_id,
493 0 AS c_order_id,
494 0 AS c_invoice_id,
495 mi.qty,
496 NULL::numeric AS movementqty,
497 mi.m_product_id,
498 il.c_uom_id,
499 mi.documentno,
500 mi.dateacct AS datedoc,
501 mi.dateacct::date AS processingdate,
502 to_char(trunc(to_timestamp((mi.processedon / 1000::numeric)::double precision), 'DD'::character varying) - mi.dateacct::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
503 mi.m_attributesetinstance_id,
504 0 AS m_movement_id,
505 0 AS m_inventory_id,
506 0 AS m_inoutline_id,
507 0 AS c_orderline_id,
508 0 AS c_invoiceline_id,
509 mi.m_matchinv_id,
510 0 AS m_inventoryline_id,
511 0 AS m_movementline_id,
512 0 AS m_matchpo_id,
513 0 AS m_productionline_id,
514 472 AS ad_table_id,
515 472 AS ad_table_line_id,
516 il.priceentered AS amount,
517 'MI'::text AS movementtype,
518 13 AS processingorder,
519 NULL::bpchar AS docbasetype,
520 ''::text AS docsubtype,
521 1001565::numeric AS c_doctype_id,
522 mi.posted,
523 CASE
524 WHEN trunc(to_timestamp((mi.processedon / 1000::numeric)::double precision), 'DD'::character varying) > mi.dateacct::date THEN 'B'::text
525 WHEN trunc(to_timestamp((mi.processedon / 1000::numeric)::double precision), 'DD'::character varying) > mi.dateacct::date THEN 'F'::text
526 ELSE 'N'::text
527 END AS backdated
528 FROM m_matchinv mi
529 LEFT JOIN c_invoiceline il ON il.c_invoiceline_id = mi.c_invoiceline_id
530 UNION ALL
531 SELECT ml.ad_client_id,
532 ml.ad_org_id,
533 ml.created,
534 ml.updated,
535 ml.createdby,
536 ml.updatedby,
537 ml.isactive,
538 'Y'::character(1) AS issotrx,
539 ml.m_movementline_id AS record_id,
540 0 AS m_inout_id,
541 0 AS c_order_id,
542 0 AS c_invoice_id,
543 ml.movementqty AS qty,
544 ml.movementqty,
545 ml.m_product_id,
546 NULL::numeric AS c_uom_id,
547 m.documentno,
548 m.movementdate AS datedoc,
549 trunc(to_timestamp((m.processedon / 1000::numeric)::double precision), 'DD'::character varying) AS processingdate,
550 to_char(trunc(to_timestamp((m.processedon / 1000::numeric)::double precision), 'DD'::character varying) - m.movementdate::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
551 ml.m_attributesetinstance_id,
552 m.m_movement_id,
553 0 AS m_inventory_id,
554 0 AS m_inoutline_id,
555 0 AS c_orderline_id,
556 0 AS c_invoiceline_id,
557 0 AS m_matchinv_id,
558 0 AS m_inventoryline_id,
559 ml.m_movementline_id,
560 0 AS m_matchpo_id,
561 0 AS m_productionline_id,
562 323 AS ad_table_id,
563 324 AS ad_table_line_id,
564 NULL::numeric AS amount,
565 'M-'::text AS movementtype,
566 35 AS processingorder,
567 d.docbasetype,
568 ''::text AS docsubtype,
569 m.c_doctype_id,
570 m.posted,
571 CASE
572 WHEN trunc(to_timestamp((m.processedon / 1000::numeric)::double precision), 'DD'::character varying) > m.movementdate::date THEN 'B'::text
573 WHEN trunc(to_timestamp((m.processedon / 1000::numeric)::double precision), 'DD'::character varying) < m.movementdate::date THEN 'F'::text
574 ELSE 'N'::text
575 END AS backdated
576 FROM m_movementline ml
577 JOIN m_movement m ON ml.m_movement_id = m.m_movement_id AND (m.docstatus::text = ANY (ARRAY['CO'::text, 'CL'::text, 'RE'::text, 'VO'::text]))
578 JOIN c_doctype d ON m.c_doctype_id = d.c_doctype_id
579 WHERE ml.movementqty > 0::numeric AND ml.locatororgmovetype = 'O'::bpchar
580 UNION ALL
581 SELECT pl.ad_client_id,
582 pl.ad_org_id,
583 pl.created,
584 pl.updated,
585 pl.createdby,
586 pl.updatedby,
587 pl.isactive,
588 'Y'::character(1) AS issotrx,
589 pl.m_productionline_id AS record_id,
590 0 AS m_inout_id,
591 0 AS c_order_id,
592 0 AS c_invoice_id,
593 pl.movementqty AS qty,
594 pl.movementqty,
595 pl.m_product_id,
596 NULL::numeric AS c_uom_id,
597 p.documentno,
598 p.movementdate AS datedoc,
599 trunc(to_timestamp((p.processedon / 1000::numeric)::double precision), 'DD'::character varying) AS processingdate,
600 to_char(trunc(to_timestamp((p.processedon / 1000::numeric)::double precision), 'DD'::character varying) - p.movementdate::timestamp with time zone, 'DD'::text)::integer AS daysdiff,
601 pl.m_attributesetinstance_id,
602 0 AS m_movement_id,
603 0 AS m_inventory_id,
604 0 AS m_inoutline_id,
605 0 AS c_orderline_id,
606 0 AS c_invoiceline_id,
607 0 AS m_matchinv_id,
608 0 AS m_inventoryline_id,
609 0 AS m_movementline_id,
610 0 AS m_matchpo_id,
611 pl.m_productionline_id,
612 325 AS ad_table_id,
613 326 AS ad_table_line_id,
614 NULL::numeric AS amount,
615 CASE
616 WHEN d.docbasetype = 'MMP'::bpchar AND pl.isendproduct = 'Y'::bpchar THEN 'P+'::text
617 ELSE 'P-'::text
618 END AS movementtype,
619 35 AS processingorder,
620 NULL::bpchar AS docbasetype,
621 ''::text AS docsubtype,
622 1001565::numeric AS c_doctype_id,
623 p.posted,
624 CASE
625 WHEN trunc(p.created::date::timestamp with time zone, 'DD'::character varying) > p.movementdate::date THEN 'B'::text
626 WHEN trunc(p.created::date::timestamp with time zone, 'DD'::character varying) < p.movementdate::date THEN 'F'::text
627 ELSE 'N'::text
628 END AS backdated
629 FROM m_productionline pl
630 JOIN m_production p ON pl.m_production_id = p.m_production_id AND (p.docstatus::text = ANY (ARRAY['CO'::text, 'CL'::text, 'RE'::text, 'VO'::text]))
631 JOIN c_doctype d ON p.c_doctype_id = d.c_doctype_id
632 WHERE pl.movementqty <> 0::numeric) dc) dcf) dcc;