CREATE OR REPLACE VIEW public.vw_fx_by_maturity_by_forex AS
 WITH combined AS (
         SELECT p.number AS purchase_number,
            'contract'::text AS line_type,
            forex.number AS forex_number,
            COALESCE(sum(fcpc.amount), (0)::numeric) AS amount_covered,
            string_agg(DISTINCT (pp.code)::text, ', '::text) AS products,
            COALESCE(max((pl.quantity * (pl.unit_price)::double precision)), (0)::double precision) AS total_contract_value,
            max((cc.code)::text) AS currency,
            forex.rate,
            forex.value_date AS maturity_date,
                CASE
                    WHEN (max(forex.move) > 0) THEN 'executed'::text
                    ELSE 'not executed'::text
                END AS status
           FROM (((((purchase_purchase p
             JOIN forex_cover_physical_contract fcpc ON ((fcpc.contract = p.id)))
             JOIN forex_forex forex ON ((forex.id = fcpc.forex)))
             LEFT JOIN purchase_line pl ON ((pl.purchase = p.id)))
             LEFT JOIN product_product pp ON ((pl.product = pp.id)))
             LEFT JOIN currency_currency cc ON ((forex.buy_currency = cc.id)))
          WHERE (p.currency = 2)
          GROUP BY p.number, forex.number, forex.rate, forex.value_date
        UNION ALL
         SELECT NULL::text AS purchase_number,
            'forex'::text AS line_type,
            forex.number AS forex_number,
            COALESCE(NULL::numeric, (0)::numeric) AS amount_covered,
            NULL::text AS products,
            COALESCE(NULL::numeric, (0)::numeric) AS total_contract_value,
            cc.code AS currency,
            forex.rate,
            forex.value_date AS maturity_date,
                CASE
                    WHEN (forex.move > 0) THEN 'executed'::text
                    ELSE 'not executed'::text
                END AS status
           FROM (forex_forex forex
             LEFT JOIN currency_currency cc ON ((forex.buy_currency = cc.id)))
          WHERE (forex.buy_currency = 2)
        )
 SELECT to_char(date_trunc('month'::text, (c.maturity_date)::timestamp with time zone), 'MONYY'::text) AS maturity_period,
    max(c.maturity_date) AS maturity_date,
    c.line_type,
    c.forex_number,
    c.purchase_number,
    max(c.status) AS status,
    max(c.products) AS products,
    max(c.currency) AS currency,
    max(c.rate) AS rate,
        CASE
            WHEN (c.line_type = 'forex'::text) THEN fx.buy_amount
            ELSE NULL::numeric
        END AS forex_total_amount,
    sum(COALESCE(c.amount_covered, (0)::numeric)) AS amount_covered,
        CASE
            WHEN (c.line_type = 'forex'::text) THEN (fx.buy_amount - COALESCE(sum(fc.amount_covered), (0)::numeric))
            ELSE NULL::numeric
        END AS amount_remaining
   FROM ((combined c
     LEFT JOIN forex_forex fx ON (((fx.number)::text = (c.forex_number)::text)))
     LEFT JOIN ( SELECT forex.number AS forex_number,
            sum(fcpc.amount) AS amount_covered
           FROM (forex_forex forex
             LEFT JOIN forex_cover_physical_contract fcpc ON ((forex.id = fcpc.forex)))
          GROUP BY forex.number) fc ON (((fc.forex_number)::text = (c.forex_number)::text)))
  GROUP BY (date_trunc('month'::text, (c.maturity_date)::timestamp with time zone)), c.line_type, c.forex_number, c.purchase_number, fx.buy_amount
  ORDER BY (date_trunc('month'::text, (c.maturity_date)::timestamp with time zone)), c.forex_number, c.line_type, c.purchase_number;;
