CREATE OR REPLACE VIEW public.vw_utility_trade_pnl_quantities AS
 WITH lot_current_qty AS (
         SELECT l.id AS lot_id,
            round(((COALESCE(lh.quantity, (0)::numeric) * (COALESCE(lot_uom.factor, (1)::double precision))::numeric) / NULLIF((COALESCE(line_uom.factor, (1)::double precision))::numeric, (0)::numeric)), 5) AS pnl_quantity,
            lot_uom.name AS quantity_uom
           FROM (((((lot_lot l
             LEFT JOIN lot_qt_hist lh ON (((lh.lot = l.id) AND (lh.quantity_type = l.lot_state))))
             LEFT JOIN product_uom lot_uom ON ((lot_uom.id = l.lot_unit_line)))
             LEFT JOIN purchase_line pl ON ((pl.id = l.line)))
             LEFT JOIN sale_line sl ON ((sl.id = l.sale_line)))
             LEFT JOIN product_uom line_uom ON ((line_uom.id = COALESCE(pl.unit, sl.unit))))
        ), purchase_pnl_lots AS (
         SELECT 'purchase'::text AS pnl_side,
            p.id AS purchase_id,
            p.number AS purchase_number,
            p.reference AS purchase_reference,
            pl.id AS purchase_line_id,
            pl.finished AS purchase_line_finished,
            NULL::integer AS sale_id,
            NULL::character varying AS sale_number,
            NULL::character varying AS sale_reference,
            NULL::integer AS sale_line_id,
            NULL::boolean AS sale_line_finished,
            l.id AS valued_lot_id,
            l.lot_type AS valued_lot_type,
            NULL::integer AS lot_qt_id,
            lcq.pnl_quantity,
            lcq.quantity_uom AS quantity_unit,
            pl.product AS product_id,
            COALESCE(shi.from_location, sint.from_location, sho.from_location, p.from_location) AS from_location_id,
            COALESCE(shi.to_location, sint.to_location, sho.to_location, p.to_location) AS to_location_id,
            shi.id AS shipment_id,
            shi.bl_date,
            pl.from_del AS delivery_date_from,
            pl.to_del AS delivery_date_to
           FROM ((((((purchase_line pl
             JOIN purchase_purchase p ON ((p.id = pl.purchase)))
             JOIN lot_lot l ON ((l.line = pl.id)))
             JOIN lot_current_qty lcq ON ((lcq.lot_id = l.id)))
             LEFT JOIN stock_shipment_in shi ON ((shi.id = l.lot_shipment_in)))
             LEFT JOIN stock_shipment_internal sint ON ((sint.id = l.lot_shipment_internal)))
             LEFT JOIN stock_shipment_out sho ON ((sho.id = l.lot_shipment_out)))
          WHERE (((pl.type)::text = 'line'::text) AND ((l.lot_type)::text = ANY (ARRAY[('virtual'::character varying)::text, ('physic'::character varying)::text])))
        ), sale_pnl_direct_lots AS (
         SELECT 'sale'::text AS pnl_side,
            p.id AS purchase_id,
            p.number AS purchase_number,
            p.reference AS purchase_reference,
            pl.id AS purchase_line_id,
            pl.finished AS purchase_line_finished,
            s.id AS sale_id,
            s.number AS sale_number,
            s.reference AS sale_reference,
            sl.id AS sale_line_id,
            sl.finished AS sale_line_finished,
            l.id AS valued_lot_id,
            l.lot_type AS valued_lot_type,
            NULL::integer AS lot_qt_id,
            lcq.pnl_quantity,
            lcq.quantity_uom AS quantity_unit,
            sl.product AS product_id,
            COALESCE(shi.from_location, sint.from_location, sho.from_location, s.from_location) AS from_location_id,
            COALESCE(shi.to_location, sint.to_location, sho.to_location, s.to_location) AS to_location_id,
            shi.id AS shipment_id,
            shi.bl_date,
            sl.from_del AS delivery_date_from,
            sl.to_del AS delivery_date_to
           FROM ((((((((purchase_line pl
             JOIN purchase_purchase p ON ((p.id = pl.purchase)))
             JOIN lot_lot l ON (((l.line = pl.id) AND (l.sale_line IS NOT NULL))))
             JOIN sale_line sl ON ((sl.id = l.sale_line)))
             JOIN sale_sale s ON ((s.id = sl.sale)))
             JOIN lot_current_qty lcq ON ((lcq.lot_id = l.id)))
             LEFT JOIN stock_shipment_in shi ON ((shi.id = l.lot_shipment_in)))
             LEFT JOIN stock_shipment_internal sint ON ((sint.id = l.lot_shipment_internal)))
             LEFT JOIN stock_shipment_out sho ON ((sho.id = l.lot_shipment_out)))
          WHERE (((pl.type)::text = 'line'::text) AND ((l.lot_type)::text = 'physic'::text))
        ), sale_pnl_matched_virtual_lots AS (
         SELECT 'sale'::text AS pnl_side,
            p.id AS purchase_id,
            p.number AS purchase_number,
            p.reference AS purchase_reference,
            pl.id AS purchase_line_id,
            pl.finished AS purchase_line_finished,
            s.id AS sale_id,
            s.number AS sale_number,
            s.reference AS sale_reference,
            sl.id AS sale_line_id,
            sl.finished AS sale_line_finished,
            sale_lot.id AS valued_lot_id,
            sale_lot.lot_type AS valued_lot_type,
            lqt.id AS lot_qt_id,
            lcq.pnl_quantity,
            lcq.quantity_uom AS quantity_unit,
            sl.product AS product_id,
            COALESCE(shi.from_location, sint.from_location, sho.from_location, s.from_location) AS from_location_id,
            COALESCE(shi.to_location, sint.to_location, sho.to_location, s.to_location) AS to_location_id,
            shi.id AS shipment_id,
            shi.bl_date,
            sl.from_del AS delivery_date_from,
            sl.to_del AS delivery_date_to
           FROM ((((((((((purchase_line pl
             JOIN purchase_purchase p ON ((p.id = pl.purchase)))
             JOIN lot_lot purchase_lot ON (((purchase_lot.line = pl.id) AND ((purchase_lot.lot_type)::text = 'virtual'::text) AND (purchase_lot.sale_line IS NULL))))
             JOIN lot_qt lqt ON (((lqt.lot_p = purchase_lot.id) AND (lqt.lot_s IS NOT NULL) AND (lqt.lot_quantity > (0)::numeric))))
             JOIN lot_lot sale_lot ON (((sale_lot.id = lqt.lot_s) AND ((sale_lot.lot_type)::text = 'virtual'::text))))
             JOIN sale_line sl ON ((sl.id = sale_lot.sale_line)))
             JOIN sale_sale s ON ((s.id = sl.sale)))
             JOIN lot_current_qty lcq ON ((lcq.lot_id = sale_lot.id)))
             LEFT JOIN stock_shipment_in shi ON ((shi.id = lqt.lot_shipment_in)))
             LEFT JOIN stock_shipment_internal sint ON ((sint.id = lqt.lot_shipment_internal)))
             LEFT JOIN stock_shipment_out sho ON ((sho.id = lqt.lot_shipment_out)))
          WHERE ((pl.type)::text = 'line'::text)
        ), sale_pnl_unmatched_lots AS (
         SELECT 'sale'::text AS pnl_side,
            NULL::integer AS purchase_id,
            NULL::character varying AS purchase_number,
            NULL::character varying AS purchase_reference,
            NULL::integer AS purchase_line_id,
            NULL::boolean AS purchase_line_finished,
            s.id AS sale_id,
            s.number AS sale_number,
            s.reference AS sale_reference,
            sl.id AS sale_line_id,
            sl.finished AS sale_line_finished,
            l.id AS valued_lot_id,
            l.lot_type AS valued_lot_type,
            NULL::integer AS lot_qt_id,
            lcq.pnl_quantity,
            lcq.quantity_uom AS quantity_unit,
            sl.product AS product_id,
            COALESCE(shi.from_location, sint.from_location, sho.from_location, s.from_location) AS from_location_id,
            COALESCE(shi.to_location, sint.to_location, sho.to_location, s.to_location) AS to_location_id,
            shi.id AS shipment_id,
            shi.bl_date,
            sl.from_del AS delivery_date_from,
            sl.to_del AS delivery_date_to
           FROM ((((((sale_line sl
             JOIN sale_sale s ON ((s.id = sl.sale)))
             JOIN lot_lot l ON (((l.sale_line = sl.id) AND (l.line IS NULL) AND ((l.lot_type)::text = ANY (ARRAY[('virtual'::character varying)::text, ('physic'::character varying)::text])))))
             JOIN lot_current_qty lcq ON ((lcq.lot_id = l.id)))
             LEFT JOIN stock_shipment_in shi ON ((shi.id = l.lot_shipment_in)))
             LEFT JOIN stock_shipment_internal sint ON ((sint.id = l.lot_shipment_internal)))
             LEFT JOIN stock_shipment_out sho ON ((sho.id = l.lot_shipment_out)))
          WHERE (((sl.type)::text = 'line'::text) AND (NOT (EXISTS ( SELECT 1
                   FROM lot_qt lqt
                  WHERE ((lqt.lot_s = l.id) AND (lqt.lot_p IS NOT NULL) AND (lqt.lot_quantity > (0)::numeric))))))
        ), pnl_lot_rows AS (
         SELECT purchase_pnl_lots.pnl_side,
            purchase_pnl_lots.purchase_id,
            purchase_pnl_lots.purchase_number,
            purchase_pnl_lots.purchase_reference,
            purchase_pnl_lots.purchase_line_id,
            purchase_pnl_lots.purchase_line_finished,
            purchase_pnl_lots.sale_id,
            purchase_pnl_lots.sale_number,
            purchase_pnl_lots.sale_reference,
            purchase_pnl_lots.sale_line_id,
            purchase_pnl_lots.sale_line_finished,
            purchase_pnl_lots.valued_lot_id,
            purchase_pnl_lots.valued_lot_type,
            purchase_pnl_lots.lot_qt_id,
            purchase_pnl_lots.pnl_quantity,
            purchase_pnl_lots.quantity_unit,
            purchase_pnl_lots.product_id,
            purchase_pnl_lots.from_location_id,
            purchase_pnl_lots.to_location_id,
            purchase_pnl_lots.shipment_id,
            purchase_pnl_lots.bl_date,
            purchase_pnl_lots.delivery_date_from,
            purchase_pnl_lots.delivery_date_to
           FROM purchase_pnl_lots
        UNION ALL
         SELECT sale_pnl_direct_lots.pnl_side,
            sale_pnl_direct_lots.purchase_id,
            sale_pnl_direct_lots.purchase_number,
            sale_pnl_direct_lots.purchase_reference,
            sale_pnl_direct_lots.purchase_line_id,
            sale_pnl_direct_lots.purchase_line_finished,
            sale_pnl_direct_lots.sale_id,
            sale_pnl_direct_lots.sale_number,
            sale_pnl_direct_lots.sale_reference,
            sale_pnl_direct_lots.sale_line_id,
            sale_pnl_direct_lots.sale_line_finished,
            sale_pnl_direct_lots.valued_lot_id,
            sale_pnl_direct_lots.valued_lot_type,
            sale_pnl_direct_lots.lot_qt_id,
            sale_pnl_direct_lots.pnl_quantity,
            sale_pnl_direct_lots.quantity_unit,
            sale_pnl_direct_lots.product_id,
            sale_pnl_direct_lots.from_location_id,
            sale_pnl_direct_lots.to_location_id,
            sale_pnl_direct_lots.shipment_id,
            sale_pnl_direct_lots.bl_date,
            sale_pnl_direct_lots.delivery_date_from,
            sale_pnl_direct_lots.delivery_date_to
           FROM sale_pnl_direct_lots
        UNION ALL
         SELECT sale_pnl_matched_virtual_lots.pnl_side,
            sale_pnl_matched_virtual_lots.purchase_id,
            sale_pnl_matched_virtual_lots.purchase_number,
            sale_pnl_matched_virtual_lots.purchase_reference,
            sale_pnl_matched_virtual_lots.purchase_line_id,
            sale_pnl_matched_virtual_lots.purchase_line_finished,
            sale_pnl_matched_virtual_lots.sale_id,
            sale_pnl_matched_virtual_lots.sale_number,
            sale_pnl_matched_virtual_lots.sale_reference,
            sale_pnl_matched_virtual_lots.sale_line_id,
            sale_pnl_matched_virtual_lots.sale_line_finished,
            sale_pnl_matched_virtual_lots.valued_lot_id,
            sale_pnl_matched_virtual_lots.valued_lot_type,
            sale_pnl_matched_virtual_lots.lot_qt_id,
            sale_pnl_matched_virtual_lots.pnl_quantity,
            sale_pnl_matched_virtual_lots.quantity_unit,
            sale_pnl_matched_virtual_lots.product_id,
            sale_pnl_matched_virtual_lots.from_location_id,
            sale_pnl_matched_virtual_lots.to_location_id,
            sale_pnl_matched_virtual_lots.shipment_id,
            sale_pnl_matched_virtual_lots.bl_date,
            sale_pnl_matched_virtual_lots.delivery_date_from,
            sale_pnl_matched_virtual_lots.delivery_date_to
           FROM sale_pnl_matched_virtual_lots
        UNION ALL
         SELECT sale_pnl_unmatched_lots.pnl_side,
            sale_pnl_unmatched_lots.purchase_id,
            sale_pnl_unmatched_lots.purchase_number,
            sale_pnl_unmatched_lots.purchase_reference,
            sale_pnl_unmatched_lots.purchase_line_id,
            sale_pnl_unmatched_lots.purchase_line_finished,
            sale_pnl_unmatched_lots.sale_id,
            sale_pnl_unmatched_lots.sale_number,
            sale_pnl_unmatched_lots.sale_reference,
            sale_pnl_unmatched_lots.sale_line_id,
            sale_pnl_unmatched_lots.sale_line_finished,
            sale_pnl_unmatched_lots.valued_lot_id,
            sale_pnl_unmatched_lots.valued_lot_type,
            sale_pnl_unmatched_lots.lot_qt_id,
            sale_pnl_unmatched_lots.pnl_quantity,
            sale_pnl_unmatched_lots.quantity_unit,
            sale_pnl_unmatched_lots.product_id,
            sale_pnl_unmatched_lots.from_location_id,
            sale_pnl_unmatched_lots.to_location_id,
            sale_pnl_unmatched_lots.shipment_id,
            sale_pnl_unmatched_lots.bl_date,
            sale_pnl_unmatched_lots.delivery_date_from,
            sale_pnl_unmatched_lots.delivery_date_to
           FROM sale_pnl_unmatched_lots
        ), pnl_lot_rows_with_finished AS (
         SELECT pnl_lot_rows.pnl_side,
            pnl_lot_rows.purchase_id,
            pnl_lot_rows.purchase_number,
            pnl_lot_rows.purchase_reference,
            pnl_lot_rows.purchase_line_id,
            pnl_lot_rows.purchase_line_finished,
            pnl_lot_rows.sale_id,
            pnl_lot_rows.sale_number,
            pnl_lot_rows.sale_reference,
            pnl_lot_rows.sale_line_id,
            pnl_lot_rows.sale_line_finished,
            pnl_lot_rows.valued_lot_id,
            pnl_lot_rows.valued_lot_type,
            pnl_lot_rows.lot_qt_id,
            pnl_lot_rows.pnl_quantity,
            pnl_lot_rows.quantity_unit,
            pnl_lot_rows.product_id,
            pnl_lot_rows.from_location_id,
            pnl_lot_rows.to_location_id,
            pnl_lot_rows.shipment_id,
            pnl_lot_rows.bl_date,
            pnl_lot_rows.delivery_date_from,
            pnl_lot_rows.delivery_date_to,
                CASE
                    WHEN (pnl_lot_rows.pnl_side = 'purchase'::text) THEN pnl_lot_rows.purchase_line_finished
                    WHEN (pnl_lot_rows.pnl_side = 'sale'::text) THEN pnl_lot_rows.sale_line_finished
                    ELSE false
                END AS valued_line_finished,
                CASE
                    WHEN (((pnl_lot_rows.valued_lot_type)::text = 'virtual'::text) AND (((pnl_lot_rows.pnl_side = 'purchase'::text) AND (pnl_lot_rows.purchase_line_finished IS TRUE)) OR ((pnl_lot_rows.pnl_side = 'sale'::text) AND (pnl_lot_rows.sale_line_finished IS TRUE)))) THEN true
                    ELSE false
                END AS ignored_by_finished_rule
           FROM pnl_lot_rows
        )
 SELECT pnl_side,
    purchase_id,
    purchase_number,
    purchase_reference,
    purchase_line_id,
    purchase_line_finished,
    sale_id,
    sale_number,
    sale_reference,
    sale_line_id,
    sale_line_finished,
    valued_lot_id,
    valued_lot_type,
    valued_line_finished,
    ignored_by_finished_rule,
    sum(pnl_quantity) AS pnl_quantity_raw,
    sum(
        CASE
            WHEN ignored_by_finished_rule THEN (0)::numeric
            ELSE pnl_quantity
        END) AS pnl_quantity_after_finished_rule,
    quantity_unit,
    product_id,
    from_location_id,
    to_location_id,
    shipment_id,
    bl_date,
    delivery_date_from,
    delivery_date_to
   FROM pnl_lot_rows_with_finished
  GROUP BY pnl_side, purchase_id, purchase_number, purchase_reference, purchase_line_id, purchase_line_finished, sale_id, sale_number, sale_reference, sale_line_id, sale_line_finished, valued_lot_type, valued_lot_id, valued_line_finished, ignored_by_finished_rule, quantity_unit, product_id, from_location_id, to_location_id, shipment_id, bl_date, delivery_date_from, delivery_date_to;;
