--
-- This file is part of TALER
-- Copyright (C) 2025 Taler Systems SA
--
-- TALER is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
-- Foundation; either version 3, or (at your option) any later version.
--
-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
--

-- @file merchant-0014.sql
-- @brief Tables for statistics
-- @author Christian Grothoff


BEGIN;

-- Check patch versioning is in place.
SELECT _v.register_patch('merchant-0014', NULL, NULL);

SET search_path TO merchant;

-- Ranges given here must be supported by the date_trunc function of Postgresql!
CREATE TYPE statistic_range AS
  ENUM('century', 'decade', 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second');

CREATE TYPE statistic_type AS
  ENUM('amount', 'number');

-- -------------- Bucket statistics ---------------------

CREATE TABLE merchant_statistic_bucket_meta
  (bmeta_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
  ,slug TEXT NOT NULL
  ,description TEXT NOT NULL
  ,stype statistic_type NOT NULL
  ,ranges statistic_range[] NOT NULL
  ,ages INT4[] NOT NULL
  ,UNIQUE(slug,stype)
  ,CONSTRAINT equal_array_length
    CHECK (array_length(ranges,1) =
           array_length(ages,1))
  );
COMMENT ON TABLE merchant_statistic_bucket_meta
  IS 'meta data about a statistic with events falling into buckets we are tracking';
COMMENT ON COLUMN merchant_statistic_bucket_meta.bmeta_serial_id
  IS 'unique identifier for this type of bucket statistic we are tracking';
COMMENT ON COLUMN merchant_statistic_bucket_meta.slug
  IS 'keyword (or name) of the statistic; identifies what the statistic is about; should be a slug suitable for a URI path';
COMMENT ON COLUMN merchant_statistic_bucket_meta.description
  IS 'description of the statistic being tracked';
COMMENT ON COLUMN merchant_statistic_bucket_meta.stype
  IS 'statistic type, what kind of data is being tracked, amount or number';
COMMENT ON COLUMN merchant_statistic_bucket_meta.ranges
  IS 'size of the buckets that are being kept for this statistic';
COMMENT ON COLUMN merchant_statistic_bucket_meta.ages
  IS 'determines how long into the past we keep buckets for the range at the given index around (in generations)';


CREATE TABLE merchant_statistic_bucket_counter
  (bmeta_serial_id INT8 NOT NULL
     REFERENCES merchant_statistic_bucket_meta (bmeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,bucket_start INT8 NOT NULL
  ,bucket_range statistic_range NOT NULL
  ,cumulative_number INT8 NOT NULL
  ,UNIQUE (bmeta_serial_id,merchant_serial,bucket_start,bucket_range)
  );
COMMENT ON TABLE merchant_statistic_bucket_counter
  IS 'various numeric statistics (cumulative counters) being tracked by bucket into which they fall';
COMMENT ON COLUMN merchant_statistic_bucket_counter.bmeta_serial_id
  IS 'identifies what the statistic is about';
COMMENT ON COLUMN merchant_statistic_bucket_counter.merchant_serial
  IS 'identifies the instance for which the statistic is kept';
COMMENT ON COLUMN merchant_statistic_bucket_counter.bucket_start
  IS 'start date for the bucket in seconds since the epoch';
COMMENT ON COLUMN merchant_statistic_bucket_counter.bucket_range
  IS 'range of the bucket';
COMMENT ON COLUMN merchant_statistic_bucket_counter.cumulative_number
  IS 'aggregate (sum) of tracked by the statistic; what exactly is tracked is determined by the keyword';


CREATE TABLE merchant_statistic_bucket_amount
  (bmeta_serial_id INT8 NOT NULL
     REFERENCES merchant_statistic_bucket_meta (bmeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,bucket_start INT8 NOT NULL
  ,bucket_range statistic_range NOT NULL
  ,curr VARCHAR(12) NOT NULL
  ,cumulative_value INT8 NOT NULL
  ,cumulative_frac INT4 NOT NULL
  ,UNIQUE (bmeta_serial_id,merchant_serial,curr,bucket_start,bucket_range)
  );
COMMENT ON TABLE merchant_statistic_bucket_amount
  IS 'various amount statistics (in various currencies) being tracked';
COMMENT ON COLUMN merchant_statistic_bucket_amount.bmeta_serial_id
  IS 'identifies what the statistic is about';
COMMENT ON COLUMN merchant_statistic_bucket_amount.merchant_serial
  IS 'identifies the instance for which the statistic is kept';
COMMENT ON COLUMN merchant_statistic_bucket_amount.bucket_start
  IS 'start date for the bucket in seconds since the epoch';
COMMENT ON COLUMN merchant_statistic_bucket_amount.bucket_range
  IS 'range of the bucket';
COMMENT ON COLUMN merchant_statistic_bucket_amount.curr
  IS 'currency which this statistic is tracking the amount for';
COMMENT ON COLUMN merchant_statistic_bucket_amount.cumulative_value
  IS 'amount in the respective currency, non-fractional amount value';
COMMENT ON COLUMN merchant_statistic_bucket_amount.cumulative_frac
  IS 'amount in the respective currency, fraction in units of 1/100000000 of the base value';


-- -------------- Interval statistics ---------------------


CREATE TABLE merchant_statistic_interval_meta
  (imeta_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
  ,slug TEXT NOT NULL
  ,description TEXT NOT NULL
  ,stype statistic_type NOT NULL
  ,ranges INT8[] NOT NULL CHECK (array_length(ranges,1) > 0)
  ,precisions INT8[] NOT NULL CHECK (array_length(precisions,1) > 0)
  ,UNIQUE(slug,stype)
  ,CONSTRAINT equal_array_length
    CHECK (array_length(ranges,1) =
           array_length(precisions,1))
  );
COMMENT ON TABLE merchant_statistic_interval_meta
  IS 'meta data about an interval statistic we are tracking';
COMMENT ON COLUMN merchant_statistic_interval_meta.imeta_serial_id
  IS 'unique identifier for this type of interval statistic we are tracking';
COMMENT ON COLUMN merchant_statistic_interval_meta.slug
  IS 'keyword (or name) of the statistic; identifies what the statistic is about; should be a slug suitable for a URI path';
COMMENT ON COLUMN merchant_statistic_interval_meta.description
  IS 'description of the statistic being tracked';
COMMENT ON COLUMN merchant_statistic_interval_meta.stype
  IS 'statistic type, what kind of data is being tracked, amount or number';
COMMENT ON COLUMN merchant_statistic_interval_meta.ranges
  IS 'range of values that is being kept for this statistic, in seconds, must be monotonically increasing';
COMMENT ON COLUMN merchant_statistic_interval_meta.precisions
  IS 'determines how precisely we track which events fall into the range at the same index (allowing us to coalesce events with timestamps in proximity close to the given precision), in seconds, 0 is not allowed';

CREATE TABLE merchant_statistic_counter_event
  (nevent_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
  ,imeta_serial_id INT8
     REFERENCES merchant_statistic_interval_meta (imeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,slot INT8 NOT NULL
  ,delta INT8 NOT NULL
  ,UNIQUE (imeta_serial_id, merchant_serial, slot)
  );
COMMENT ON TABLE merchant_statistic_counter_event
  IS 'number to decrement an interval statistic by when a certain time value is reached';
COMMENT ON COLUMN merchant_statistic_counter_event.nevent_serial_id
  IS 'unique identifier for this number event';
COMMENT ON COLUMN merchant_statistic_counter_event.imeta_serial_id
  IS 'identifies what the statistic is about; must be of stype number';
COMMENT ON COLUMN merchant_statistic_counter_event.merchant_serial
  IS 'identifies which merchant instance the event is about';
COMMENT ON COLUMN merchant_statistic_counter_event.slot
  IS 'identifies the time slot at which the given event(s) happened, rounded down by the respective precisions value';
COMMENT ON COLUMN merchant_statistic_counter_event.delta
  IS 'total cumulative number that was added at the time identified by slot';

CREATE TABLE merchant_statistic_interval_counter
  (imeta_serial_id INT8 NOT NULL
     REFERENCES merchant_statistic_interval_meta (imeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,range INT8 NOT NULL
  ,event_delimiter INT8 NOT NULL
     REFERENCES merchant_statistic_counter_event (nevent_serial_id) ON DELETE RESTRICT
  ,cumulative_number INT8 NOT NULL
  ,UNIQUE (imeta_serial_id,merchant_serial,range)
  );
COMMENT ON TABLE merchant_statistic_interval_counter
  IS 'various numeric statistics (cumulative counters) being tracked';
COMMENT ON COLUMN merchant_statistic_interval_counter.imeta_serial_id
  IS 'identifies what the statistic is about';
COMMENT ON COLUMN merchant_statistic_interval_counter.merchant_serial
  IS 'identifies the instance for which the statistic is kept';
COMMENT ON COLUMN merchant_statistic_interval_counter.range
  IS 'for which range is this the counter; note that the cumulative_number excludes the values already stored in smaller ranges';
COMMENT ON COLUMN merchant_statistic_interval_counter.event_delimiter
  IS 'determines the last event currently included in the interval';
COMMENT ON COLUMN merchant_statistic_interval_counter.cumulative_number
  IS 'aggregate (sum) of tracked by the statistic; what exactly is tracked is determined by the keyword';


CREATE TABLE merchant_statistic_amount_event
  (aevent_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
  ,imeta_serial_id INT8
     REFERENCES merchant_statistic_interval_meta (imeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,slot INT8 NOT NULL
  ,delta_curr VARCHAR(12) NOT NULL
  ,delta_value INT8 NOT NULL
  ,delta_frac INT4 NOT NULL
  ,CONSTRAINT event_key UNIQUE (imeta_serial_id, merchant_serial, delta_curr, slot)
  );
COMMENT ON TABLE merchant_statistic_amount_event
  IS 'amount to decrement an interval statistic by when a certain time value is reached';
COMMENT ON COLUMN merchant_statistic_amount_event.aevent_serial_id
  IS 'unique identifier for this amount event';
COMMENT ON COLUMN merchant_statistic_amount_event.imeta_serial_id
  IS 'identifies what the statistic is about; must be of clazz interval and of stype amount';
COMMENT ON COLUMN merchant_statistic_amount_event.merchant_serial
  IS 'identifies which merchant instance the event is about';
COMMENT ON COLUMN merchant_statistic_amount_event.slot
  IS 'identifies the time slot at which the given event(s) happened';
COMMENT ON COLUMN merchant_statistic_amount_event.delta_curr
  IS 'currency of the total cumulative amount that was added at the time identified by slot';
COMMENT ON COLUMN merchant_statistic_amount_event.delta_value
  IS 'total cumulative amount (value) that was added at the time identified by slot';
COMMENT ON COLUMN merchant_statistic_amount_event.delta_frac
  IS 'total cumulative amount (fraction) that was added at the time identified by slot';


CREATE TABLE merchant_statistic_interval_amount
  (imeta_serial_id INT8 NOT NULL
     REFERENCES merchant_statistic_interval_meta (imeta_serial_id) ON DELETE CASCADE
  ,merchant_serial BIGINT NOT NULL
     REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
  ,event_delimiter INT8 NOT NULL
     REFERENCES merchant_statistic_amount_event (aevent_serial_id) ON DELETE RESTRICT
  ,range INT8 NOT NULL
  ,curr VARCHAR(12) NOT NULL
  ,cumulative_value INT8 NOT NULL
  ,cumulative_frac INT4 NOT NULL
  ,UNIQUE (imeta_serial_id,merchant_serial,curr,range)
  );
COMMENT ON TABLE merchant_statistic_interval_amount
  IS 'various amount statistics (in various currencies) being tracked';
COMMENT ON COLUMN merchant_statistic_interval_amount.imeta_serial_id
  IS 'identifies what the statistic is about';
COMMENT ON COLUMN merchant_statistic_interval_amount.merchant_serial
  IS 'identifies the instance for which the statistic is kept';
COMMENT ON COLUMN merchant_statistic_interval_amount.range
  IS 'for which range is this the counter; note that the cumulative_number excludes the values already stored in smaller ranges';
COMMENT ON COLUMN merchant_statistic_interval_amount.curr
  IS 'currency which this statistic is tracking the amount for';
COMMENT ON COLUMN merchant_statistic_interval_amount.cumulative_value
  IS 'amount in the respective currency, non-fractional amount value';
COMMENT ON COLUMN merchant_statistic_interval_amount.cumulative_frac
  IS 'amount in the respective currency, fraction in units of 1/100000000 of the base value';

CREATE TYPE merchant_statistic_interval_number_get_return_value
  AS
  (range INT8
  ,rvalue INT8
  );
COMMENT ON TYPE merchant_statistic_interval_number_get_return_value
  IS 'Return type for merchant_statistic_interval_number_get stored procedure';

CREATE TYPE merchant_statistic_interval_amount_get_return_value
  AS
  (range INT8
  ,rvalue taler_amount_currency
  );
COMMENT ON TYPE merchant_statistic_interval_amount_get_return_value
  IS 'Return type for merchant_statistic_interval_amount_get stored procedure';

-- ---------------- Actual statistics below ---------------------


CREATE FUNCTION merchant_orders_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
 CALL merchant_do_bump_number_stat
   ('orders-created'
    ,NEW.merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,1);
  RETURN NEW;
END $$;

-- Whenever an order is created, call our trigger to bump statistics
CREATE TRIGGER merchant_orders_on_insert_statistic
  AFTER INSERT
     ON merchant_orders
  FOR EACH ROW EXECUTE FUNCTION merchant_orders_insert_statistics_trigger();


CREATE FUNCTION merchant_contract_terms_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
 CALL merchant_do_bump_number_stat
   ('orders-claimed'
    ,NEW.merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,1);
  RETURN NEW;
END $$;

-- Whenever an order is created, call our trigger to bump statistics
CREATE TRIGGER merchant_contract_terms_on_insert_statistic
  AFTER INSERT
     ON merchant_contract_terms
  FOR EACH ROW EXECUTE FUNCTION merchant_contract_terms_insert_statistics_trigger();


CREATE FUNCTION merchant_contract_terms_update_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_rec RECORD;
BEGIN
  IF (NEW.wired AND NOT OLD.wired)
  THEN
    CALL merchant_do_bump_number_stat
      ('orders-settled'
       ,NEW.merchant_serial
       ,CURRENT_TIMESTAMP(0)::TIMESTAMP
       ,1);
  END IF;
  IF (NEW.paid AND NOT OLD.paid)
  THEN
    CALL merchant_do_bump_number_stat
      ('orders-paid'
       ,NEW.merchant_serial
       ,CURRENT_TIMESTAMP(0)::TIMESTAMP
       ,1);
    FOR my_rec IN
      SELECT total_without_fee
        FROM merchant_deposit_confirmations
       WHERE order_serial = NEW.order_serial
    LOOP
      CALL merchant_do_bump_amount_stat
        ('payments-received-after-deposit-fee'
         ,NEW.merchant_serial
         ,CURRENT_TIMESTAMP(0)::TIMESTAMP
         ,my_rec.total_without_fee);
    END LOOP;
    FOR my_rec IN
      SELECT deposit_fee
        FROM merchant_deposits
       WHERE deposit_confirmation_serial IN
        (SELECT deposit_confirmation_serial
           FROM merchant_deposit_confirmations
          WHERE order_serial = NEW.order_serial)
    LOOP
      CALL merchant_do_bump_amount_stat
        ('total-deposit-fees-paid'
         ,NEW.merchant_serial
         ,CURRENT_TIMESTAMP(0)::TIMESTAMP
         ,my_rec.deposit_fee);
    END LOOP;
  END IF;
  RETURN NEW;
END $$;

-- Whenever a contract is updated, call our trigger to bump statistics
CREATE TRIGGER merchant_contract_terms_on_update_statistic
  AFTER UPDATE
     ON merchant_contract_terms
  FOR EACH ROW EXECUTE FUNCTION merchant_contract_terms_update_statistics_trigger();


CREATE FUNCTION merchant_refunds_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_serial INT8;
BEGIN
 SELECT merchant_serial
   INTO my_merchant_serial
   FROM merchant_contract_terms
  WHERE order_serial = NEW.order_serial;
 CALL merchant_do_bump_amount_stat
   ('refunds-granted'
    ,my_merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,NEW.refund_amount);
  RETURN NEW;
END $$;

-- Whenever a refund is granted created, call our trigger to bump statistics
CREATE TRIGGER merchant_refunds_on_insert_statistic
  AFTER INSERT
     ON merchant_refunds
  FOR EACH ROW EXECUTE FUNCTION merchant_refunds_insert_statistics_trigger();


CREATE FUNCTION merchant_transfer_signatures_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_serial INT8;
BEGIN
 SELECT merchant_serial
   INTO my_merchant_serial
   FROM merchant_accounts
  WHERE account_serial =
    (SELECT account_serial
       FROM merchant_transfers
      WHERE credit_serial = NEW.credit_serial);
 CALL merchant_do_bump_amount_stat
   ('wire-fees-paid'
    ,my_merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,NEW.wire_fee);
  RETURN NEW;
END $$;

-- Whenever a refund is granted created, call our trigger to bump statistics
CREATE TRIGGER merchant_transfer_signatures_on_insert_statistic
  AFTER INSERT
     ON merchant_transfer_signatures
  FOR EACH ROW EXECUTE FUNCTION merchant_transfer_signatures_insert_statistics_trigger();


CREATE FUNCTION merchant_issued_tokens_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_serial INT8;
BEGIN
 SELECT merchant_serial
   INTO my_merchant_serial
   FROM merchant_token_families
  WHERE token_family_serial =
    (SELECT token_family_serial
       FROM merchant_token_family_keys
      WHERE token_family_key_serial = NEW.token_family_key_serial);
 CALL merchant_do_bump_number_stat
   ('tokens-issued'
    ,my_merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,1);
  RETURN NEW;
END $$;

-- Whenever a token is issued, call our trigger to bump statistics
CREATE TRIGGER merchant_issued_tokens_on_insert_statistic
  AFTER INSERT
     ON merchant_issued_tokens
  FOR EACH ROW EXECUTE FUNCTION merchant_issued_tokens_insert_statistics_trigger();


CREATE FUNCTION merchant_used_tokens_insert_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_serial INT8;
BEGIN
 SELECT merchant_serial
   INTO my_merchant_serial
   FROM merchant_token_families
  WHERE token_family_serial =
    (SELECT token_family_serial
       FROM merchant_token_family_keys
      WHERE token_family_key_serial = NEW.token_family_key_serial);
 CALL merchant_do_bump_number_stat
   ('tokens-used'
    ,my_merchant_serial
    ,CURRENT_TIMESTAMP(0)::TIMESTAMP
    ,1);
  RETURN NEW;
END $$;

-- Whenever a token is used, call our trigger to bump statistics
CREATE TRIGGER merchant_used_tokens_on_insert_statistic
  AFTER INSERT
     ON merchant_used_tokens
  FOR EACH ROW EXECUTE FUNCTION merchant_used_tokens_insert_statistics_trigger();

-- Enable interval statistics
INSERT INTO merchant_statistic_interval_meta
  (slug
  ,description
  ,stype
  ,ranges
  ,precisions)
VALUES
  ('orders-created'
  ,'number of orders created (but not necessarily claimed by wallets)'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  ),
  ('orders-claimed'
  ,'number of orders claimed by a wallet (but not necessarily paid)'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  ),
  ('orders-paid'
  ,'number of orders paid (but not necessarily settled by the exchange)'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  ),
  ('orders-settled'
  ,'number of orders settled'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  ),
  ('tokens-issued'
  ,'number of tokens issued to customers'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  ),
  ('tokens-used'
  ,'number of tokens used by customers'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
   || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
  ,array_fill (5, ARRAY[60]) -- precision: 5s
   || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
  );

-- Enable bucket statistics
INSERT INTO merchant_statistic_bucket_meta
  (slug
  ,description
  ,stype
  ,ranges
  ,ages)
VALUES
  ('payments-received-after-deposit-fee'
  ,'amount customers paid to us (excluded deposit fees paid by us or customers, wire fees are still deducted by the exchange)'
  ,'amount'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 14, 12, 24, 12, 10]
  ),
  ('total-deposit-fees-paid'
  ,'deposit fees we or our customers paid to the exchange (includes those waived on refunds)'
  ,'amount'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 14, 12, 24, 12, 10]
  ),
  ('total-wire-fees-paid'
  ,'wire fees we paid to the exchange'
  ,'amount'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 12, 12, 24, 12, 10]
  ),
  ('refunds-granted'
  ,'refunds granted by us to our customers'
  ,'amount'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 14, 12, 24, 12, 10]
  ),
  ('tokens-issued'
  ,'number of tokens issued to customers'
  ,'number'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 14, 12, 24, 12, 10]
  ),
  ('tokens-used'
  ,'number of tokens used by customers'
  ,'number'
  ,ARRAY['hour'::statistic_range, 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[72, 14, 12, 24, 12, 10]
  );



COMMIT;
