CREATE OR REPLACE VIEW public.vw_utility_shipment_fee_allocation AS
 WITH physical_shipment_lots AS (
         SELECT l.lot_shipment_in AS shipment_id,
            l.id AS lot_id,
            l.lot_type,
            l.line AS purchase_line_id,
            l.sale_line AS sale_line_id,
            qh.quantity AS shipment_quantity,
            l.lot_unit_line AS shipment_unit_id
           FROM (lot_lot l
             LEFT JOIN lot_qt_hist qh ON (((qh.lot = l.id) AND (qh.quantity_type = l.lot_state))))
          WHERE (((l.lot_type)::text = 'physic'::text) AND (l.lot_shipment_in IS NOT NULL))
        ), virtual_shipment_lots AS (
         SELECT q.lot_shipment_in AS shipment_id,
            vp.id AS lot_id,
            vp.lot_type,
            vp.line AS purchase_line_id,
            COALESCE(vp.sale_line, ps.sale_line) AS sale_line_id,
            q.lot_quantity AS shipment_quantity,
            q.lot_unit AS shipment_unit_id
           FROM ((lot_qt q
             JOIN lot_lot vp ON (((vp.id = q.lot_p) AND ((vp.lot_type)::text = 'virtual'::text))))
             LEFT JOIN lot_lot ps ON ((ps.id = q.lot_s)))
          WHERE ((q.lot_shipment_in IS NOT NULL) AND (NOT (EXISTS ( SELECT 1
                   FROM physical_shipment_lots pl
                  WHERE ((pl.shipment_id = q.lot_shipment_in) AND (pl.purchase_line_id = vp.line) AND ((pl.sale_line_id = COALESCE(vp.sale_line, ps.sale_line)) OR (COALESCE(vp.sale_line, ps.sale_line) IS NULL)))))))
        ), shipment_lots AS (
         SELECT physical_shipment_lots.shipment_id,
            physical_shipment_lots.lot_id,
            physical_shipment_lots.lot_type,
            physical_shipment_lots.purchase_line_id,
            physical_shipment_lots.sale_line_id,
            physical_shipment_lots.shipment_quantity,
            physical_shipment_lots.shipment_unit_id
           FROM physical_shipment_lots
        UNION ALL
         SELECT virtual_shipment_lots.shipment_id,
            virtual_shipment_lots.lot_id,
            virtual_shipment_lots.lot_type,
            virtual_shipment_lots.purchase_line_id,
            virtual_shipment_lots.sale_line_id,
            virtual_shipment_lots.shipment_quantity,
            virtual_shipment_lots.shipment_unit_id
           FROM virtual_shipment_lots
        ), shipment_context AS (
         SELECT shipment_lots.shipment_id,
            shipment_lots.lot_id,
            shipment_lots.purchase_line_id,
            shipment_lots.sale_line_id,
            shipment_lots.shipment_unit_id,
            sum(COALESCE(shipment_lots.shipment_quantity, (0)::numeric)) AS shipment_quantity
           FROM shipment_lots
          WHERE (shipment_lots.shipment_id IS NOT NULL)
          GROUP BY shipment_lots.shipment_id, shipment_lots.lot_id, shipment_lots.purchase_line_id, shipment_lots.sale_line_id, shipment_lots.shipment_unit_id
        ), shipment_base AS (
         SELECT shipment_context.shipment_id,
            sum(shipment_context.shipment_quantity) AS shipment_quantity
           FROM shipment_context
          GROUP BY shipment_context.shipment_id
        ), shipment_fee_candidates AS (
         SELECT f_1.id AS fee_id,
            'Shipment'::text AS fee_source,
            f_1.type AS fee_type,
                CASE
                    WHEN ((f_1.type)::text = 'ordered'::text) THEN 1
                    WHEN ((f_1.type)::text = 'scheduled'::text) THEN 2
                    ELSE NULL::integer
                END AS priority,
            sb.shipment_id,
            f_1.product AS product_id,
            f_1.supplier AS supplier_id,
            f_1.mode AS packaging,
            f_1.p_r AS pay_or_rec,
            f_1.state,
            f_1.weight_type,
            COALESCE(f_1.quantity, (0)::numeric) AS requested_quantity,
            sb.shipment_quantity,
            f_1.price AS fee_price,
            f_1.currency AS currency_id,
            f_1.unit AS unit_id,
                CASE
                    WHEN (upper((f_1.p_r)::text) = 'REC'::text) THEN 1
                    ELSE '-1'::integer
                END AS sign_multiplier,
            NULL::text AS forced_cost_group
           FROM (shipment_base sb
             JOIN fee_fee f_1 ON ((f_1.shipment_in = sb.shipment_id)))
          WHERE ((f_1.type)::text = ANY (ARRAY[('ordered'::character varying)::text, ('scheduled'::character varying)::text]))
        ), shipment_fee_limits AS (
         SELECT c.fee_id,
            c.fee_source,
            c.fee_type,
            c.priority,
            c.shipment_id,
            c.product_id,
            c.supplier_id,
            c.packaging,
            c.pay_or_rec,
            c.state,
            c.weight_type,
            c.requested_quantity,
            c.shipment_quantity,
            c.fee_price,
            c.currency_id,
            c.unit_id,
            c.sign_multiplier,
            c.forced_cost_group,
            LEAST(GREATEST(c.requested_quantity, (0)::numeric), GREATEST((c.shipment_quantity - COALESCE(sum(c.requested_quantity) OVER (PARTITION BY c.shipment_id, c.product_id, c.supplier_id ORDER BY c.priority, c.fee_id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), (0)::numeric)), (0)::numeric)) AS fee_allocatable_quantity
           FROM shipment_fee_candidates c
        ), shipment_fee_allocated AS (
         SELECT fl.fee_id,
            fl.fee_source,
            fl.fee_type,
            fl.priority,
            fl.shipment_id,
            sc.lot_id,
            sc.purchase_line_id,
            sc.sale_line_id,
            fl.product_id,
            fl.supplier_id,
            fl.packaging,
            fl.pay_or_rec,
            fl.state,
            fl.weight_type,
            fl.requested_quantity,
            fl.shipment_quantity,
            fl.fee_price,
            fl.currency_id,
            COALESCE(fl.unit_id, sc.shipment_unit_id) AS unit_id,
            fl.sign_multiplier,
            fl.forced_cost_group,
            LEAST(sc.shipment_quantity, GREATEST((fl.fee_allocatable_quantity - COALESCE(sum(sc.shipment_quantity) OVER (PARTITION BY fl.fee_id ORDER BY sc.lot_id, sc.purchase_line_id, sc.sale_line_id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), (0)::numeric)), (0)::numeric)) AS allocated_quantity
           FROM (shipment_fee_limits fl
             JOIN shipment_context sc ON ((sc.shipment_id = fl.shipment_id)))
        ), shipment_fee_coverage AS (
         SELECT shipment_fee_allocated.shipment_id,
            shipment_fee_allocated.product_id,
            shipment_fee_allocated.supplier_id,
            max(shipment_fee_allocated.shipment_quantity) AS shipment_quantity,
            sum(shipment_fee_allocated.allocated_quantity) AS allocated_quantity
           FROM shipment_fee_allocated
          GROUP BY shipment_fee_allocated.shipment_id, shipment_fee_allocated.product_id, shipment_fee_allocated.supplier_id
        ), contract_budgeted_fee_candidates AS (
         SELECT f_1.id AS fee_id,
            'Purchase Contract'::text AS fee_source,
            f_1.type AS fee_type,
            3 AS priority,
            sc.shipment_id,
            sc.lot_id,
            sc.purchase_line_id,
            sc.sale_line_id,
            f_1.product AS product_id,
            f_1.supplier AS supplier_id,
            f_1.mode AS packaging,
            f_1.p_r AS pay_or_rec,
            f_1.state,
            f_1.weight_type,
            sc.shipment_quantity,
            f_1.price AS fee_price,
            f_1.currency AS currency_id,
            COALESCE(f_1.unit, sc.shipment_unit_id) AS unit_id,
                CASE
                    WHEN (upper((f_1.p_r)::text) = 'REC'::text) THEN '-1'::integer
                    ELSE 1
                END AS sign_multiplier,
            NULL::text AS forced_cost_group
           FROM (shipment_context sc
             JOIN fee_fee f_1 ON ((f_1.line = sc.purchase_line_id)))
          WHERE (((f_1.type)::text = 'budgeted'::text) AND (sc.purchase_line_id IS NOT NULL))
        UNION ALL
         SELECT f_1.id AS fee_id,
            'Sale Contract'::text AS fee_source,
            f_1.type AS fee_type,
            3 AS priority,
            sc.shipment_id,
            sc.lot_id,
            sc.purchase_line_id,
            sc.sale_line_id,
            f_1.product AS product_id,
            f_1.supplier AS supplier_id,
            f_1.mode AS packaging,
            f_1.p_r AS pay_or_rec,
            f_1.state,
            f_1.weight_type,
            sc.shipment_quantity,
            f_1.price AS fee_price,
            f_1.currency AS currency_id,
            COALESCE(f_1.unit, sc.shipment_unit_id) AS unit_id,
                CASE
                    WHEN (upper((f_1.p_r)::text) = 'REC'::text) THEN 1
                    ELSE '-1'::integer
                END AS sign_multiplier,
            NULL::text AS forced_cost_group
           FROM (shipment_context sc
             JOIN fee_fee f_1 ON ((f_1.sale_line = sc.sale_line_id)))
          WHERE (((f_1.type)::text = 'budgeted'::text) AND (sc.sale_line_id IS NOT NULL))
        ), contract_budgeted_allocated AS (
         SELECT c.fee_id,
            c.fee_source,
            c.fee_type,
            c.priority,
            c.shipment_id,
            c.lot_id,
            c.purchase_line_id,
            c.sale_line_id,
            c.product_id,
            c.supplier_id,
            c.packaging,
            c.pay_or_rec,
            c.state,
            c.weight_type,
            c.shipment_quantity,
            c.fee_price,
            c.currency_id,
            c.unit_id,
            c.sign_multiplier,
            c.forced_cost_group,
            LEAST(c.shipment_quantity, GREATEST(((sum(c.shipment_quantity) OVER (PARTITION BY c.shipment_id, c.product_id, c.supplier_id, c.fee_id) - COALESCE(fc.allocated_quantity, (0)::numeric)) - COALESCE(sum(c.shipment_quantity) OVER (PARTITION BY c.shipment_id, c.product_id, c.supplier_id, c.fee_id ORDER BY c.lot_id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), (0)::numeric)), (0)::numeric)) AS allocated_quantity
           FROM (contract_budgeted_fee_candidates c
             LEFT JOIN shipment_fee_coverage fc ON (((fc.shipment_id = c.shipment_id) AND (fc.product_id = c.product_id) AND (fc.supplier_id = c.supplier_id))))
        ), price_rows AS (
         SELECT NULL::integer AS fee_id,
            'Purchase Price'::text AS fee_source,
            'price'::text AS fee_type,
            4 AS priority,
            sc.shipment_id,
            sc.lot_id,
            sc.purchase_line_id,
            sc.sale_line_id,
            pl.product AS product_id,
            NULL::integer AS supplier_id,
            NULL::character varying AS packaging,
            NULL::character varying AS pay_or_rec,
            NULL::character varying AS state,
            NULL::character varying AS weight_type,
            sc.shipment_quantity AS allocated_quantity,
            pl.unit_price AS fee_price,
            pl.currency_ AS currency_id,
            COALESCE(pl.unit, sc.shipment_unit_id) AS unit_id,
            1 AS sign_multiplier,
            'PurchasePrice'::text AS forced_cost_group
           FROM (shipment_context sc
             JOIN purchase_line pl ON ((pl.id = sc.purchase_line_id)))
          WHERE (sc.purchase_line_id IS NOT NULL)
        UNION ALL
         SELECT NULL::integer AS fee_id,
            'Sale Price'::text AS fee_source,
            'price'::text AS fee_type,
            5 AS priority,
            sc.shipment_id,
            sc.lot_id,
            sc.purchase_line_id,
            sc.sale_line_id,
            sl.product AS product_id,
            NULL::integer AS supplier_id,
            NULL::character varying AS packaging,
            NULL::character varying AS pay_or_rec,
            NULL::character varying AS state,
            NULL::character varying AS weight_type,
            sc.shipment_quantity AS allocated_quantity,
            sl.unit_price AS fee_price,
            ss.currency AS currency_id,
            COALESCE(sl.unit, sc.shipment_unit_id) AS unit_id,
            '-1'::integer AS sign_multiplier,
            'SalePrice'::text AS forced_cost_group
           FROM ((shipment_context sc
             JOIN sale_line sl ON ((sl.id = sc.sale_line_id)))
             JOIN sale_sale ss ON ((ss.id = sl.sale)))
          WHERE (sc.sale_line_id IS NOT NULL)
        ), final_fees AS (
         SELECT shipment_fee_allocated.fee_id,
            shipment_fee_allocated.fee_source,
            shipment_fee_allocated.fee_type,
            shipment_fee_allocated.priority,
            shipment_fee_allocated.shipment_id,
            shipment_fee_allocated.lot_id,
            shipment_fee_allocated.purchase_line_id,
            shipment_fee_allocated.sale_line_id,
            shipment_fee_allocated.product_id,
            shipment_fee_allocated.supplier_id,
            shipment_fee_allocated.packaging,
            shipment_fee_allocated.pay_or_rec,
            shipment_fee_allocated.state,
            shipment_fee_allocated.weight_type,
            shipment_fee_allocated.allocated_quantity AS fee_quantity,
            shipment_fee_allocated.fee_price,
            shipment_fee_allocated.currency_id,
            shipment_fee_allocated.unit_id,
            shipment_fee_allocated.sign_multiplier,
            shipment_fee_allocated.forced_cost_group
           FROM shipment_fee_allocated
          WHERE (shipment_fee_allocated.allocated_quantity > (0)::numeric)
        UNION ALL
         SELECT contract_budgeted_allocated.fee_id,
            contract_budgeted_allocated.fee_source,
            contract_budgeted_allocated.fee_type,
            contract_budgeted_allocated.priority,
            contract_budgeted_allocated.shipment_id,
            contract_budgeted_allocated.lot_id,
            contract_budgeted_allocated.purchase_line_id,
            contract_budgeted_allocated.sale_line_id,
            contract_budgeted_allocated.product_id,
            contract_budgeted_allocated.supplier_id,
            contract_budgeted_allocated.packaging,
            contract_budgeted_allocated.pay_or_rec,
            contract_budgeted_allocated.state,
            contract_budgeted_allocated.weight_type,
            contract_budgeted_allocated.allocated_quantity AS fee_quantity,
            contract_budgeted_allocated.fee_price,
            contract_budgeted_allocated.currency_id,
            contract_budgeted_allocated.unit_id,
            contract_budgeted_allocated.sign_multiplier,
            contract_budgeted_allocated.forced_cost_group
           FROM contract_budgeted_allocated
          WHERE (contract_budgeted_allocated.allocated_quantity > (0)::numeric)
        UNION ALL
         SELECT price_rows.fee_id,
            price_rows.fee_source,
            price_rows.fee_type,
            price_rows.priority,
            price_rows.shipment_id,
            price_rows.lot_id,
            price_rows.purchase_line_id,
            price_rows.sale_line_id,
            price_rows.product_id,
            price_rows.supplier_id,
            price_rows.packaging,
            price_rows.pay_or_rec,
            price_rows.state,
            price_rows.weight_type,
            price_rows.allocated_quantity AS fee_quantity,
            price_rows.fee_price,
            price_rows.currency_id,
            price_rows.unit_id,
            price_rows.sign_multiplier,
            price_rows.forced_cost_group
           FROM price_rows
          WHERE (price_rows.allocated_quantity > (0)::numeric)
        )
 SELECT f.shipment_id AS "intShipmentId",
    f.lot_id AS "intLotId",
    COALESCE(f.fee_id, 0) AS "intFeeId",
    f.fee_source AS "strFeeSource",
    f.fee_type AS "strFeeType",
    f.priority AS "intPriority",
    COALESCE(f.purchase_line_id, 0) AS "intPurchaseLineId",
    COALESCE(f.sale_line_id, 0) AS "intSaleLineId",
    COALESCE(f.product_id, 0) AS "intProductId",
    COALESCE(p.code, ''::character varying) AS "strFee",
    COALESCE(f.supplier_id, 0) AS "intSupplierId",
    COALESCE(sup.name, ''::character varying) AS "strSupplier",
    COALESCE(f.packaging, ''::character varying) AS "strPackaging",
    COALESCE(f.pay_or_rec, ''::character varying) AS "strPayOrRec",
    COALESCE(f.state, ''::character varying) AS "strState",
        CASE
            WHEN (upper((f.weight_type)::text) = 'BRUT'::text) THEN 'Gross'::text
            ELSE 'Net'::text
        END AS "strWeighingType",
    f.fee_quantity AS "dblQuantity",
    f.fee_price AS "dblPrice",
    COALESCE(cur.name, ''::character varying) AS "strCurrency",
    COALESCE(uom.name, 'Mt'::character varying) AS "strUnit",
    (f.fee_quantity * f.fee_price) AS "dblAmount",
    COALESCE(f.forced_cost_group,
        CASE
            WHEN (upper((p.code)::text) ~~ '%FREIGHT%'::text) THEN 'Freight'::text
            WHEN (upper((p.code)::text) ~~ '%PROFIT SHARING%'::text) THEN 'Profit Sharing'::text
            ELSE 'Other Costs'::text
        END) AS "strCostGroup",
        CASE
            WHEN ((f.pay_or_rec)::text = 'pay'::text) THEN (- (1)::numeric)
            WHEN ((f.pay_or_rec)::text = 'rec'::text) THEN (1)::numeric
            WHEN ((f.fee_source = 'Purchase Price'::text) AND ((f.fee_type)::text = 'price'::text)) THEN (- (1)::numeric)
            WHEN ((f.fee_source = 'Sale Price'::text) AND ((f.fee_type)::text = 'price'::text)) THEN (1)::numeric
            ELSE (- (1)::numeric)
        END AS "intSignMultiplier"
   FROM ((((final_fees f
     JOIN product_product p ON ((p.id = f.product_id)))
     LEFT JOIN party_party sup ON ((sup.id = f.supplier_id)))
     LEFT JOIN currency_currency cur ON ((cur.id = f.currency_id)))
     LEFT JOIN product_uom uom ON ((uom.id = f.unit_id)));;
