LEFT JOIN money.payment_view t ON (p.id = t.id);
CREATE TABLE money.materialized_payment_by_billing_type (
- id BIGSERIAL PRIMARY KEY,
- xact BIGINT NOT NULL,
- payment BIGINT NOT NULL,
- billing BIGINT NOT NULL,
- payment_ts TIMESTAMPTZ NOT NULL,
- billing_ts TIMESTAMPTZ NOT NULL,
- amount NUMERIC(8,2) NOT NULL,
- payment_type TEXT,
- billing_type TEXT,
- payment_ou INT,
- billing_ou INT,
+ id BIGSERIAL PRIMARY KEY,
+ xact BIGINT NOT NULL,
+ payment BIGINT NOT NULL,
+ billing BIGINT NOT NULL,
+ payment_ts TIMESTAMPTZ NOT NULL,
+ billing_ts TIMESTAMPTZ NOT NULL,
+ amount NUMERIC(8,2) NOT NULL,
+ payment_type TEXT,
+ billing_type TEXT,
+ payment_ou INT,
+ billing_ou INT,
-- Debug billing_leftover NUMERIC(8,2),
-- Debug payment_leftover NUMERIC(8,2),
- CONSTRAINT x_p_b_once UNIQUE (xact,payment,billing)
+-- Debug used_billings BIGINT[],
+-- Debug billing_l INT,
+ CONSTRAINT x_p_b_once UNIQUE (xact,payment,billing)
);
CREATE INDEX p_by_b_payment_ts_idx
) RETURNS SETOF money.materialized_payment_by_billing_type AS $$
DECLARE
- current_result money.materialized_payment_by_billing_type%ROWTYPE;
- current_payment money.payment_view%ROWTYPE;
- current_billing money.billing%ROWTYPE;
- payment_remainder NUMERIC(8,2) := 0.0;
- billing_remainder NUMERIC(8,2) := 0.0;
- payment_offset INT := 0;
- billing_offset INT := 0;
- billing_ou INT := 0;
- payment_ou INT := 0;
+ current_result money.materialized_payment_by_billing_type%ROWTYPE;
+ current_payment money.payment_view%ROWTYPE;
+ current_billing money.billing%ROWTYPE;
+ payment_remainder NUMERIC(8,2) := 0.0;
+ billing_remainder NUMERIC(8,2) := 0.0;
+ payment_offset INT := 0;
+ billing_offset INT := 0;
+ billing_ou INT := 0;
+ payment_ou INT := 0;
fast_forward BOOLEAN := FALSE;
maintain_billing_remainder BOOLEAN := FALSE;
billing_loop INT := -1;
billing_row_count INT := 0;
+ current_billing_id BIGINT := 0;
+ billing_id_used BIGINT ARRAY;
+ billing_l INT := 0;
+ continuing_payment BOOLEAN := FALSE;
+ continuing_payment_last_row BOOLEAN := FALSE;
+
BEGIN
/* This algorithm is fairly straight-forward. We take a transaction id
ORDER BY payment_ts
LOOP
- payment_remainder = current_payment.amount;
+ payment_remainder = current_payment.amount;
-- With every new payment row, we need to fast forward
-- the billing lines up to the last paid billing row
fast_forward := TRUE;
payment_ou = billing_ou;
END IF;
- -- Were we looking at a billing from a previous step in the loop?
- IF billing_remainder > 0.0 THEN
- current_result.xact = p_xact;
- current_result.payment = current_payment.id;
- current_result.billing = current_billing.id;
- current_result.payment_ts = current_payment.payment_ts;
- current_result.billing_ts = current_billing.billing_ts;
- current_result.payment_type = current_payment.payment_type;
- current_result.billing_type = current_billing.billing_type;
- current_result.payment_ou = payment_ou;
- current_result.billing_ou = billing_ou;
+ -- Were we looking at a billing from a previous step in the loop?
+ IF billing_remainder > 0.0 THEN
+ current_result.xact = p_xact;
+ current_result.payment = current_payment.id;
+ current_result.billing = current_billing.id;
+ current_result.payment_ts = current_payment.payment_ts;
+ current_result.billing_ts = current_billing.billing_ts;
+ current_result.payment_type = current_payment.payment_type;
+ current_result.billing_type = current_billing.billing_type;
+ current_result.payment_ou = payment_ou;
+ current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
- IF billing_remainder >= payment_remainder THEN
- current_result.amount = payment_remainder;
- billing_remainder = billing_remainder - payment_remainder;
- payment_remainder = 0.0;
- payment_offset = payment_offset + 1;
+ IF billing_remainder >= payment_remainder THEN
+ current_result.amount = payment_remainder;
+ billing_remainder = billing_remainder - payment_remainder;
+ payment_remainder = 0.0;
+ payment_offset = payment_offset + 1;
-- If it is equal then we need to close up the billing line and move to the next
-- This prevents 0 amounts applied to billing lines
IF billing_remainder = payment_remainder THEN
billing_remainder = 0.0;
- billing_offset = billing_offset + 1;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
ELSE
maintain_billing_remainder := TRUE;
END IF;
- ELSE
- current_result.amount = billing_remainder;
- payment_remainder = payment_remainder - billing_remainder;
- billing_remainder = 0.0;
+ ELSE
+ current_result.amount = billing_remainder;
+ payment_remainder = payment_remainder - billing_remainder;
+ billing_remainder = 0.0;
billing_offset = billing_offset + 1;
- END IF;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ continuing_payment := TRUE;
+ END IF;
- RETURN NEXT current_result;
+ RETURN NEXT current_result;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
- END IF;
-
- CONTINUE WHEN payment_remainder = 0.0;
+ EXIT WHEN array_length(billing_id_used, 1) = billing_row_count;
+ END IF;
+ CONTINUE WHEN payment_remainder = 0.0;
+
-- next billing, please
-
+ billing_loop := -1;
+
FOR current_billing IN
SELECT *
FROM money.billing
WHERE xact = p_xact
- -- AND NOT voided
-- Gotta put the voided billing rows at the bottom (last)
ORDER BY voided,billing_ts
LOOP
- -- Fast forward through the rows until we get to the billing row
- -- where we left off
- IF fast_forward THEN
- billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
- CONTINUE WHEN billing_loop <> billing_offset;
+ billing_loop = billing_loop + 1;
+
+ -- Skip billing rows that we have already paid
+ IF billing_id_used @> ARRAY[current_billing.id] THEN CONTINUE;
+ END IF;
+
+ IF maintain_billing_remainder THEN
+ CONTINUE WHEN current_billing.id <> current_billing_id;
+ -- Account adjustment - we expect to pay billing rows that are identical amounts
+ ELSE IF current_payment.payment_type = 'account_adjustment' THEN
+ -- Go ahead and allow the row through when it's the last row and we still haven't found one with equal payment amount
+ CONTINUE WHEN ( ( current_billing.amount <> current_payment.amount ) AND ( billing_loop + 1 <> billing_row_count ) );
+ END IF;
END IF;
-- Keep the old remainder if we were in the middle of a billing row
IF NOT maintain_billing_remainder THEN
- billing_remainder = current_billing.amount;
+ billing_remainder = current_billing.amount;
END IF;
- maintain_billing_remainder := FALSE;
- billing_loop := -1;
+ maintain_billing_remainder := FALSE;
fast_forward := FALSE;
+ current_billing_id := current_billing.id;
+ continuing_payment := FALSE;
current_result.xact = p_xact;
current_result.payment = current_payment.id;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
billing_remainder = billing_remainder - payment_remainder;
- IF NOT current_billing.voided THEN
- payment_remainder = 0.0;
- END IF;
+ payment_remainder = 0.0;
-- If it is equal then we need to close up the billing line and move to the next
-- This prevents 0 amounts applied to billing lines
IF billing_remainder = payment_remainder THEN
billing_remainder = 0.0;
- billing_offset = billing_offset + 1;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
END IF;
ELSE
current_result.amount = billing_remainder;
- IF NOT current_billing.voided THEN
- payment_remainder = payment_remainder - billing_remainder;
- END IF;
+ payment_remainder = payment_remainder - billing_remainder;
+ continuing_payment := TRUE;
+ IF billing_loop + 1 = billing_row_count THEN
+ -- We have a situation where we are on the last billing row and we are in the middle of a payment row
+ -- We need to start back at the beginning of the billing rows and pay
+ continuing_payment_last_row := TRUE;
+ END IF;
billing_remainder = 0.0;
billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
END IF;
RETURN NEXT current_result;
-
+ IF continuing_payment_last_row THEN
+ -- This should only occur when the account_adjustment's do not line up exactly with the billing
+ -- So we are going to pay some other type of billing row with this odd account_adjustment
+ -- And we need to stay in the current_payment row while doing so
+ billing_loop := -1;
+ FOR current_billing IN
+ SELECT *
+ FROM money.billing
+ WHERE xact = p_xact
+ ORDER BY voided,billing_ts
+ LOOP
+ billing_loop = billing_loop + 1;
+ -- Skip billing rows that we have already paid
+ IF billing_id_used @> ARRAY[current_billing.id] THEN CONTINUE; END IF;
+
+ billing_remainder = current_billing.amount;
+ current_billing_id := current_billing.id;
+ continuing_payment := FALSE;
+
+ current_result.xact = p_xact;
+ current_result.payment = current_payment.id;
+ current_result.billing = current_billing.id;
+ current_result.payment_ts = current_payment.payment_ts;
+ current_result.billing_ts = current_billing.billing_ts;
+ current_result.payment_type = current_payment.payment_type;
+ current_result.billing_type = current_billing.billing_type;
+ current_result.payment_ou = payment_ou;
+ current_result.billing_ou = billing_ou;
+-- Debug current_result.billing_leftover = billing_remainder;
+-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
+
+ IF billing_remainder >= payment_remainder THEN
+ current_result.amount = payment_remainder;
+ billing_remainder = billing_remainder - payment_remainder;
+ payment_remainder = 0.0;
+ -- If it is equal then we need to close up the billing line and move to the next
+ -- This prevents 0 amounts applied to billing lines
+ IF billing_remainder = payment_remainder THEN
+ billing_remainder = 0.0;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ END IF;
+ ELSE
+ current_result.amount = billing_remainder;
+ payment_remainder = payment_remainder - billing_remainder;
+ billing_remainder = 0.0;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ END IF;
+
+ RETURN NEXT current_result;
+ EXIT WHEN payment_remainder = 0.0;
+ END LOOP;
+
+ END IF;
EXIT WHEN payment_remainder = 0.0;
END LOOP;
payment_offset = payment_offset + 1;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN array_length(billing_id_used, 1) = billing_row_count;
END LOOP;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
current_result.amount = -current_result.amount;
RETURN NEXT current_result;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN billing_offset = billing_row_count + 1;
END IF;
CONTINUE WHEN payment_remainder = 0.0;
-- next billing, please
-
+ billing_loop := -1;
FOR current_billing IN
SELECT *
FROM money.billing
AND voided
ORDER BY billing_ts
LOOP
+ billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
-- Fast forward through the rows until we get to the billing row
-- where we left off
- IF fast_forward THEN
- billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
+ IF fast_forward THEN
CONTINUE WHEN billing_loop <> billing_offset;
END IF;
END IF;
maintain_billing_remainder := FALSE;
- billing_loop := -1;
fast_forward := FALSE;
current_result.xact = p_xact;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
payment_offset = payment_offset + 1;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN billing_offset = billing_row_count + 1;
END LOOP;
current_result money.materialized_payment_by_billing_type%ROWTYPE;
BEGIN
- -- first, we find transactions at specified locations involivng
+ -- first, we find transactions at specified locations involving
-- positve, unvoided payments within the specified range
FOR current_transaction IN
SELECT DISTINCT x.id
CREATE TABLE money.materialized_payment_by_billing_type (
- id BIGSERIAL PRIMARY KEY,
- xact BIGINT NOT NULL,
- payment BIGINT NOT NULL,
- billing BIGINT NOT NULL,
- payment_ts TIMESTAMPTZ NOT NULL,
- billing_ts TIMESTAMPTZ NOT NULL,
- amount NUMERIC(8,2) NOT NULL,
- payment_type TEXT,
- billing_type TEXT,
- payment_ou INT,
- billing_ou INT,
+ id BIGSERIAL PRIMARY KEY,
+ xact BIGINT NOT NULL,
+ payment BIGINT NOT NULL,
+ billing BIGINT NOT NULL,
+ payment_ts TIMESTAMPTZ NOT NULL,
+ billing_ts TIMESTAMPTZ NOT NULL,
+ amount NUMERIC(8,2) NOT NULL,
+ payment_type TEXT,
+ billing_type TEXT,
+ payment_ou INT,
+ billing_ou INT,
-- Debug billing_leftover NUMERIC(8,2),
-- Debug payment_leftover NUMERIC(8,2),
- CONSTRAINT x_p_b_once UNIQUE (xact,payment,billing)
+-- Debug used_billings BIGINT[],
+-- Debug billing_l INT,
+ CONSTRAINT x_p_b_once UNIQUE (xact,payment,billing)
);
CREATE INDEX p_by_b_payment_ts_idx
) RETURNS SETOF money.materialized_payment_by_billing_type AS $$
DECLARE
- current_result money.materialized_payment_by_billing_type%ROWTYPE;
- current_payment money.payment_view%ROWTYPE;
- current_billing money.billing%ROWTYPE;
- payment_remainder NUMERIC(8,2) := 0.0;
- billing_remainder NUMERIC(8,2) := 0.0;
- payment_offset INT := 0;
- billing_offset INT := 0;
- billing_ou INT := 0;
- payment_ou INT := 0;
+ current_result money.materialized_payment_by_billing_type%ROWTYPE;
+ current_payment money.payment_view%ROWTYPE;
+ current_billing money.billing%ROWTYPE;
+ payment_remainder NUMERIC(8,2) := 0.0;
+ billing_remainder NUMERIC(8,2) := 0.0;
+ payment_offset INT := 0;
+ billing_offset INT := 0;
+ billing_ou INT := 0;
+ payment_ou INT := 0;
fast_forward BOOLEAN := FALSE;
maintain_billing_remainder BOOLEAN := FALSE;
billing_loop INT := -1;
billing_row_count INT := 0;
+ current_billing_id BIGINT := 0;
+ billing_id_used BIGINT ARRAY;
+ billing_l INT := 0;
+ continuing_payment BOOLEAN := FALSE;
+ continuing_payment_last_row BOOLEAN := FALSE;
+
BEGIN
/* This algorithm is fairly straight-forward. We take a transaction id
ORDER BY payment_ts
LOOP
- payment_remainder = current_payment.amount;
+ payment_remainder = current_payment.amount;
-- With every new payment row, we need to fast forward
-- the billing lines up to the last paid billing row
fast_forward := TRUE;
payment_ou = billing_ou;
END IF;
- -- Were we looking at a billing from a previous step in the loop?
- IF billing_remainder > 0.0 THEN
- current_result.xact = p_xact;
- current_result.payment = current_payment.id;
- current_result.billing = current_billing.id;
- current_result.payment_ts = current_payment.payment_ts;
- current_result.billing_ts = current_billing.billing_ts;
- current_result.payment_type = current_payment.payment_type;
- current_result.billing_type = current_billing.billing_type;
- current_result.payment_ou = payment_ou;
- current_result.billing_ou = billing_ou;
+ -- Were we looking at a billing from a previous step in the loop?
+ IF billing_remainder > 0.0 THEN
+ current_result.xact = p_xact;
+ current_result.payment = current_payment.id;
+ current_result.billing = current_billing.id;
+ current_result.payment_ts = current_payment.payment_ts;
+ current_result.billing_ts = current_billing.billing_ts;
+ current_result.payment_type = current_payment.payment_type;
+ current_result.billing_type = current_billing.billing_type;
+ current_result.payment_ou = payment_ou;
+ current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
- IF billing_remainder >= payment_remainder THEN
- current_result.amount = payment_remainder;
- billing_remainder = billing_remainder - payment_remainder;
- payment_remainder = 0.0;
- payment_offset = payment_offset + 1;
+ IF billing_remainder >= payment_remainder THEN
+ current_result.amount = payment_remainder;
+ billing_remainder = billing_remainder - payment_remainder;
+ payment_remainder = 0.0;
+ payment_offset = payment_offset + 1;
-- If it is equal then we need to close up the billing line and move to the next
-- This prevents 0 amounts applied to billing lines
IF billing_remainder = payment_remainder THEN
billing_remainder = 0.0;
- billing_offset = billing_offset + 1;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
ELSE
maintain_billing_remainder := TRUE;
END IF;
- ELSE
- current_result.amount = billing_remainder;
- payment_remainder = payment_remainder - billing_remainder;
- billing_remainder = 0.0;
+ ELSE
+ current_result.amount = billing_remainder;
+ payment_remainder = payment_remainder - billing_remainder;
+ billing_remainder = 0.0;
billing_offset = billing_offset + 1;
- END IF;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ continuing_payment := TRUE;
+ END IF;
- RETURN NEXT current_result;
+ RETURN NEXT current_result;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
- END IF;
-
- CONTINUE WHEN payment_remainder = 0.0;
+ EXIT WHEN array_length(billing_id_used, 1) = billing_row_count;
+ END IF;
+ CONTINUE WHEN payment_remainder = 0.0;
+
-- next billing, please
-
+ billing_loop := -1;
+
FOR current_billing IN
SELECT *
FROM money.billing
WHERE xact = p_xact
- -- AND NOT voided
-- Gotta put the voided billing rows at the bottom (last)
ORDER BY voided,billing_ts
LOOP
- -- Fast forward through the rows until we get to the billing row
- -- where we left off
- IF fast_forward THEN
- billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
- CONTINUE WHEN billing_loop <> billing_offset;
+ billing_loop = billing_loop + 1;
+
+ -- Skip billing rows that we have already paid
+ IF billing_id_used @> ARRAY[current_billing.id] THEN CONTINUE;
+ END IF;
+
+ IF maintain_billing_remainder THEN
+ CONTINUE WHEN current_billing.id <> current_billing_id;
+ -- Account adjustment - we expect to pay billing rows that are identical amounts
+ ELSE IF current_payment.payment_type = 'account_adjustment' THEN
+ -- Go ahead and allow the row through when it's the last row and we still haven't found one with equal payment amount
+ CONTINUE WHEN ( ( current_billing.amount <> current_payment.amount ) AND ( billing_loop + 1 <> billing_row_count ) );
+ END IF;
END IF;
-- Keep the old remainder if we were in the middle of a billing row
IF NOT maintain_billing_remainder THEN
- billing_remainder = current_billing.amount;
+ billing_remainder = current_billing.amount;
END IF;
- maintain_billing_remainder := FALSE;
- billing_loop := -1;
+ maintain_billing_remainder := FALSE;
fast_forward := FALSE;
+ current_billing_id := current_billing.id;
+ continuing_payment := FALSE;
current_result.xact = p_xact;
current_result.payment = current_payment.id;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
billing_remainder = billing_remainder - payment_remainder;
- IF NOT current_billing.voided THEN
- payment_remainder = 0.0;
- END IF;
+ payment_remainder = 0.0;
-- If it is equal then we need to close up the billing line and move to the next
-- This prevents 0 amounts applied to billing lines
IF billing_remainder = payment_remainder THEN
billing_remainder = 0.0;
- billing_offset = billing_offset + 1;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
END IF;
ELSE
current_result.amount = billing_remainder;
- IF NOT current_billing.voided THEN
- payment_remainder = payment_remainder - billing_remainder;
- END IF;
+ payment_remainder = payment_remainder - billing_remainder;
+ continuing_payment := TRUE;
+ IF billing_loop + 1 = billing_row_count THEN
+ -- We have a situation where we are on the last billing row and we are in the middle of a payment row
+ -- We need to start back at the beginning of the billing rows and pay
+ continuing_payment_last_row := TRUE;
+ END IF;
billing_remainder = 0.0;
billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
END IF;
RETURN NEXT current_result;
-
+ IF continuing_payment_last_row THEN
+ -- This should only occur when the account_adjustment's do not line up exactly with the billing
+ -- So we are going to pay some other type of billing row with this odd account_adjustment
+ -- And we need to stay in the current_payment row while doing so
+ billing_loop := -1;
+ FOR current_billing IN
+ SELECT *
+ FROM money.billing
+ WHERE xact = p_xact
+ ORDER BY voided,billing_ts
+ LOOP
+ billing_loop = billing_loop + 1;
+ -- Skip billing rows that we have already paid
+ IF billing_id_used @> ARRAY[current_billing.id] THEN CONTINUE; END IF;
+
+ billing_remainder = current_billing.amount;
+ current_billing_id := current_billing.id;
+ continuing_payment := FALSE;
+
+ current_result.xact = p_xact;
+ current_result.payment = current_payment.id;
+ current_result.billing = current_billing.id;
+ current_result.payment_ts = current_payment.payment_ts;
+ current_result.billing_ts = current_billing.billing_ts;
+ current_result.payment_type = current_payment.payment_type;
+ current_result.billing_type = current_billing.billing_type;
+ current_result.payment_ou = payment_ou;
+ current_result.billing_ou = billing_ou;
+-- Debug current_result.billing_leftover = billing_remainder;
+-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.used_billings = billing_id_used;
+-- Debug current_result.billing_l = billing_loop;
+
+ IF billing_remainder >= payment_remainder THEN
+ current_result.amount = payment_remainder;
+ billing_remainder = billing_remainder - payment_remainder;
+ payment_remainder = 0.0;
+ -- If it is equal then we need to close up the billing line and move to the next
+ -- This prevents 0 amounts applied to billing lines
+ IF billing_remainder = payment_remainder THEN
+ billing_remainder = 0.0;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ END IF;
+ ELSE
+ current_result.amount = billing_remainder;
+ payment_remainder = payment_remainder - billing_remainder;
+ billing_remainder = 0.0;
+ billing_offset = billing_offset + 1;
+ billing_id_used = array_append( billing_id_used, current_billing_id );
+ END IF;
+
+ RETURN NEXT current_result;
+ EXIT WHEN payment_remainder = 0.0;
+ END LOOP;
+
+ END IF;
EXIT WHEN payment_remainder = 0.0;
END LOOP;
payment_offset = payment_offset + 1;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN array_length(billing_id_used, 1) = billing_row_count;
END LOOP;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
current_result.amount = -current_result.amount;
RETURN NEXT current_result;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN billing_offset = billing_row_count + 1;
END IF;
CONTINUE WHEN payment_remainder = 0.0;
-- next billing, please
-
+ billing_loop := -1;
FOR current_billing IN
SELECT *
FROM money.billing
AND voided
ORDER BY billing_ts
LOOP
+ billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
-- Fast forward through the rows until we get to the billing row
-- where we left off
- IF fast_forward THEN
- billing_loop = billing_loop + 1; -- first iteration billing_loop=0, it starts at -1
+ IF fast_forward THEN
CONTINUE WHEN billing_loop <> billing_offset;
END IF;
END IF;
maintain_billing_remainder := FALSE;
- billing_loop := -1;
fast_forward := FALSE;
current_result.xact = p_xact;
current_result.billing_ou = billing_ou;
-- Debug current_result.billing_leftover = billing_remainder;
-- Debug current_result.payment_leftover = payment_remainder;
+-- Debug current_result.billing_l = billing_loop;
IF billing_remainder >= payment_remainder THEN
current_result.amount = payment_remainder;
payment_offset = payment_offset + 1;
-- Done paying the billing rows when we run out of rows to pay (out of bounds)
- EXIT WHEN billing_offset = billing_row_count+1;
+ EXIT WHEN billing_offset = billing_row_count + 1;
END LOOP;
current_result money.materialized_payment_by_billing_type%ROWTYPE;
BEGIN
- -- first, we find transactions at specified locations involivng
+ -- first, we find transactions at specified locations involving
-- positve, unvoided payments within the specified range
FOR current_transaction IN
SELECT DISTINCT x.id