LP#1474051 Drop unneeded CC payment fields
authorBill Erickson <berickxx@gmail.com>
Mon, 13 Jul 2015 18:00:06 +0000 (14:00 -0400)
committerKathy Lussier <klussier@masslnc.org>
Fri, 19 Feb 2016 17:43:43 +0000 (12:43 -0500)
Avoid storing the following credit card fields:

expire month
expire year
first name
last name
credit card type

Print and email receipts for credit card data modified to avoid
referencing these fields.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/money.pm
Open-ILS/src/sql/Pg/080.schema.money.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.drop_cc_cols.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/YYYY.data.drop_cc_cols.sql [new file with mode: 0644]

index 85b485f..42b66f2 100644 (file)
@@ -2591,14 +2591,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field name="amount_collected" reporter:datatype="money" />
                        <field name="approval_code" reporter:datatype="text"/>
                        <field name="cash_drawer" reporter:datatype="link"/>
-                       <field name="cc_first_name" reporter:datatype="text"/>
-                       <field name="cc_last_name" reporter:datatype="text"/>
                        <field name="cc_number" reporter:datatype="text"/>
                        <field name="cc_order_number" reporter:datatype="text"/>
-                       <field name="cc_type" reporter:datatype="text"/>
                        <field name="cc_processor" reporter:datatype="text"/>
-                       <field name="expire_month" reporter:datatype="int" />
-                       <field name="expire_year" reporter:datatype="int" />
                        <field name="id" reporter:datatype="id" />
                        <field name="note" reporter:datatype="text"/>
                        <field name="payment_ts" reporter:datatype="timestamp"/>
index 2cd07f8..a558777 100644 (file)
@@ -269,7 +269,7 @@ sub make_payments {
 
 
     # unless/until determined by payment processor API
-    my ($approval_code, $cc_processor, $cc_type, $cc_order_number) = (undef,undef,undef, undef);
+    my ($approval_code, $cc_processor, $cc_order_number) = (undef,undef,undef, undef);
 
     my $patron = $e->retrieve_actor_user($user_id) or return $e->die_event;
 
@@ -382,16 +382,13 @@ sub make_payments {
 
         if ($payobj->has_field('accepting_usr')) { $payobj->accepting_usr($e->requestor->id); }
         if ($payobj->has_field('cash_drawer')) { $payobj->cash_drawer($drawer); }
-        if ($payobj->has_field('cc_type')) { $payobj->cc_type($cc_args->{type}); }
         if ($payobj->has_field('check_number')) { $payobj->check_number($check_number); }
 
         # Store the last 4 digits of the CC number
         if ($payobj->has_field('cc_number')) {
             $payobj->cc_number(substr($cc_args->{number}, -4));
         }
-        if ($payobj->has_field('expire_month')) { $payobj->expire_month($cc_args->{expire_month}); $logger->info("LFW XXX expire_month is $cc_args->{expire_month}"); }
-        if ($payobj->has_field('expire_year')) { $payobj->expire_year($cc_args->{expire_year}); }
-        
+
         # Note: It is important not to set approval_code
         # on the fieldmapper object yet.
 
@@ -434,7 +431,6 @@ sub make_payments {
 
                 {
                     no warnings 'uninitialized';
-                    $cc_type = $cc_payload->{card_type};
                     $approval_code = $cc_payload->{authorization} ||
                         $cc_payload->{id};
                     $cc_processor = $cc_payload->{processor} ||
@@ -523,17 +519,12 @@ sub make_payments {
 
         # Urgh, clean up this mega-function one day.
         if ($cc_processor eq 'Stripe' and $approval_code and $cc_payload) {
-            $payment->expire_month($cc_payload->{card}{exp_month});
-            $payment->expire_year($cc_payload->{card}{exp_year});
             $payment->cc_number($cc_payload->{card}{last4});
         }
 
         $payment->approval_code($approval_code) if $approval_code;
         $payment->cc_order_number($cc_order_number) if $cc_order_number;
-        $payment->cc_type($cc_type) if $cc_type;
         $payment->cc_processor($cc_processor) if $cc_processor;
-        $payment->cc_first_name($cc_args->{'billing_first'}) if $cc_args->{'billing_first'};
-        $payment->cc_last_name($cc_args->{'billing_last'}) if $cc_args->{'billing_last'};
         if (!$e->$create_money_method($payment)) {
             return _recording_failure(
                 $e, "$create_money_method failed", $payment, $cc_payload
index c3e65fc..c9d7247 100644 (file)
@@ -116,9 +116,8 @@ use base qw/money/;
 __PACKAGE__->table('money_credit_card_payment');
 __PACKAGE__->columns(Primary => 'id');
 __PACKAGE__->columns(Essential => qw/xact amount payment_ts cash_drawer
-                     accepting_usr amount_collected cc_type
-                     cc_number expire_month expire_year
-                     approval_code note/);
+                     accepting_usr amount_collected cc_processor
+                     approval_code note voided cc_number/);
 #-------------------------------------------------------------------------------
 
 package money::forgive_payment;
index 3bba2ed..e67c0a7 100644 (file)
@@ -640,14 +640,9 @@ CREATE TRIGGER mat_summary_del_tgr BEFORE DELETE ON money.check_payment FOR EACH
 
 
 CREATE TABLE money.credit_card_payment (
-       cc_type         TEXT,
-       cc_number       TEXT,
+    cc_number     TEXT,
     cc_processor TEXT,
-    cc_first_name TEXT,
-    cc_last_name TEXT,
     cc_order_number TEXT,
-       expire_month    INT,
-       expire_year     INT,
        approval_code   TEXT
 ) INHERITS (money.bnm_desk_payment);
 ALTER TABLE money.credit_card_payment ADD PRIMARY KEY (id);
index df34cce..2505f50 100644 (file)
@@ -9726,12 +9726,8 @@ Transaction ID: [% xact_id %]
                 Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
                     [% CASE "cash_payment" %]cash
                     [% CASE "check_payment" %]check
-                    [% CASE "credit_card_payment" %]credit card (
-                        [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
-                        [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
-                        [% cc_chunks.last -%]
-                        exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
-                    )
+                    [% CASE "credit_card_payment" %]credit card
+                    [%- IF mp.credit_card_payment.cc_number %] ([% mp.credit_card_payment.cc_number %])[% END %]
                     [% CASE "credit_payment" %]credit
                     [% CASE "forgive_payment" %]forgiveness
                     [% CASE "goods_payment" %]goods
@@ -9797,12 +9793,8 @@ $$
                         Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
                             [% CASE "cash_payment" %]cash
                             [% CASE "check_payment" %]check
-                            [% CASE "credit_card_payment" %]credit card (
-                                [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
-                                [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
-                                [% cc_chunks.last -%]
-                                exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
-                            )
+                            [% CASE "credit_card_payment" %]credit card
+                            [%- IF mp.credit_card_payment.cc_number %] ([% mp.credit_card_payment.cc_number %])[% END %]
                             [% CASE "credit_payment" %]credit
                             [% CASE "forgive_payment" %]forgiveness
                             [% CASE "goods_payment" %]goods
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.drop_cc_cols.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.drop_cc_cols.sql
new file mode 100644 (file)
index 0000000..c24ab04
--- /dev/null
@@ -0,0 +1,13 @@
+BEGIN;
+
+-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+ALTER TABLE money.credit_card_payment 
+    DROP COLUMN cc_type,
+    DROP COLUMN expire_month,
+    DROP COLUMN expire_year,
+    DROP COLUMN cc_first_name,
+    DROP COLUMN cc_last_name;
+
+COMMIT;
+
diff --git a/Open-ILS/src/sql/Pg/upgrade/YYYY.data.drop_cc_cols.sql b/Open-ILS/src/sql/Pg/upgrade/YYYY.data.drop_cc_cols.sql
new file mode 100644 (file)
index 0000000..763dcbd
--- /dev/null
@@ -0,0 +1,270 @@
+
+BEGIN;
+
+-- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+-- Remove references to dropped CC payment columns in the print/email 
+-- payment receipt templates, but only if the in-db template matches 
+-- the stock template.
+-- The actual diff here is only about 8 lines.
+
+UPDATE action_trigger.event_definition SET template = 
+$$
+[%- USE date -%]
+[%- SET user = target.0.xact.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Payment Receipt
+
+[% date.format -%]
+[%- SET xact_mp_hash = {} -%]
+[%- FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions -%]
+    [%- SET xact_id = mp.xact.id -%]
+    [%- IF ! xact_mp_hash.defined( xact_id ) -%][%- xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } -%][%- END -%]
+    [%- xact_mp_hash.$xact_id.payments.push(mp) -%]
+[%- END -%]
+[%- FOR xact_id IN xact_mp_hash.keys.sort -%]
+    [%- SET xact = xact_mp_hash.$xact_id.xact %]
+Transaction ID: [% xact_id %]
+    [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+    [% ELSE %]Miscellaneous
+    [% END %]
+    Line item billings:
+        [%- SET mb_type_hash = {} -%]
+        [%- FOR mb IN xact.billings %][%# Group billings by their btype -%]
+            [%- IF mb.voided == 'f' -%]
+                [%- SET mb_type = mb.btype.id -%]
+                [%- IF ! mb_type_hash.defined( mb_type ) -%][%- mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } -%][%- END -%]
+                [%- IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) -%][%- mb_type_hash.$mb_type.first_ts = mb.billing_ts -%][%- END -%]
+                [%- mb_type_hash.$mb_type.last_ts = mb.billing_ts -%]
+                [%- mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount -%]
+                [%- mb_type_hash.$mb_type.billings.push( mb ) -%]
+            [%- END -%]
+        [%- END -%]
+        [%- FOR mb_type IN mb_type_hash.keys.sort -%]
+            [%- IF mb_type == 1 %][%-# Consolidated view of overdue billings -%]
+                $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                    on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+            [%- ELSE -%][%# all other billings show individually %]
+                [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                    $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                [% END %]
+            [% END %]
+        [% END %]
+    Line item payments:
+        [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+            Payment ID: [% mp.id %]
+                Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                    [% CASE "cash_payment" %]cash
+                    [% CASE "check_payment" %]check
+                    [% CASE "credit_card_payment" %]credit card
+                    [%- IF mp.credit_card_payment.cc_number %] ([% mp.credit_card_payment.cc_number %])[% END %]
+                    [% CASE "credit_payment" %]credit
+                    [% CASE "forgive_payment" %]forgiveness
+                    [% CASE "goods_payment" %]goods
+                    [% CASE "work_payment" %]work
+                [%- END %] on [% mp.payment_ts %] [% mp.note %]
+        [% END %]
+[% END %]
+$$
+
+WHERE id = 29 AND template =
+
+$$
+[%- USE date -%]
+[%- SET user = target.0.xact.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Payment Receipt
+
+[% date.format -%]
+[%- SET xact_mp_hash = {} -%]
+[%- FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions -%]
+    [%- SET xact_id = mp.xact.id -%]
+    [%- IF ! xact_mp_hash.defined( xact_id ) -%][%- xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } -%][%- END -%]
+    [%- xact_mp_hash.$xact_id.payments.push(mp) -%]
+[%- END -%]
+[%- FOR xact_id IN xact_mp_hash.keys.sort -%]
+    [%- SET xact = xact_mp_hash.$xact_id.xact %]
+Transaction ID: [% xact_id %]
+    [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+    [% ELSE %]Miscellaneous
+    [% END %]
+    Line item billings:
+        [%- SET mb_type_hash = {} -%]
+        [%- FOR mb IN xact.billings %][%# Group billings by their btype -%]
+            [%- IF mb.voided == 'f' -%]
+                [%- SET mb_type = mb.btype.id -%]
+                [%- IF ! mb_type_hash.defined( mb_type ) -%][%- mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } -%][%- END -%]
+                [%- IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) -%][%- mb_type_hash.$mb_type.first_ts = mb.billing_ts -%][%- END -%]
+                [%- mb_type_hash.$mb_type.last_ts = mb.billing_ts -%]
+                [%- mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount -%]
+                [%- mb_type_hash.$mb_type.billings.push( mb ) -%]
+            [%- END -%]
+        [%- END -%]
+        [%- FOR mb_type IN mb_type_hash.keys.sort -%]
+            [%- IF mb_type == 1 %][%-# Consolidated view of overdue billings -%]
+                $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                    on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+            [%- ELSE -%][%# all other billings show individually %]
+                [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                    $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                [% END %]
+            [% END %]
+        [% END %]
+    Line item payments:
+        [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+            Payment ID: [% mp.id %]
+                Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                    [% CASE "cash_payment" %]cash
+                    [% CASE "check_payment" %]check
+                    [% CASE "credit_card_payment" %]credit card (
+                        [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
+                        [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
+                        [% cc_chunks.last -%]
+                        exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
+                    )
+                    [% CASE "credit_payment" %]credit
+                    [% CASE "forgive_payment" %]forgiveness
+                    [% CASE "goods_payment" %]goods
+                    [% CASE "work_payment" %]work
+                [%- END %] on [% mp.payment_ts %] [% mp.note %]
+        [% END %]
+[% END %]
+$$;
+
+
+UPDATE action_trigger.event_definition SET template = 
+$$
+[%- USE date -%][%- SET user = target.0.xact.usr -%]
+<div style="li { padding: 8px; margin 5px; }">
+    <div>[% date.format %]</div><br/>
+    <ol>
+    [% SET xact_mp_hash = {} %]
+    [% FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions %]
+        [% SET xact_id = mp.xact.id %]
+        [% IF ! xact_mp_hash.defined( xact_id ) %][% xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } %][% END %]
+        [% xact_mp_hash.$xact_id.payments.push(mp) %]
+    [% END %]
+    [% FOR xact_id IN xact_mp_hash.keys.sort %]
+        [% SET xact = xact_mp_hash.$xact_id.xact %]
+        <li>Transaction ID: [% xact_id %]
+            [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+            [% ELSE %]Miscellaneous
+            [% END %]
+            Line item billings:<ol>
+                [% SET mb_type_hash = {} %]
+                [% FOR mb IN xact.billings %][%# Group billings by their btype %]
+                    [% IF mb.voided == 'f' %]
+                        [% SET mb_type = mb.btype.id %]
+                        [% IF ! mb_type_hash.defined( mb_type ) %][% mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } %][% END %]
+                        [% IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) %][% mb_type_hash.$mb_type.first_ts = mb.billing_ts %][% END %]
+                        [% mb_type_hash.$mb_type.last_ts = mb.billing_ts %]
+                        [% mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount %]
+                        [% mb_type_hash.$mb_type.billings.push( mb ) %]
+                    [% END %]
+                [% END %]
+                [% FOR mb_type IN mb_type_hash.keys.sort %]
+                    <li>[% IF mb_type == 1 %][%# Consolidated view of overdue billings %]
+                        $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                            on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+                    [% ELSE %][%# all other billings show individually %]
+                        [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                            $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                        [% END %]
+                    [% END %]</li>
+                [% END %]
+            </ol>
+            Line item payments:<ol>
+                [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+                    <li>Payment ID: [% mp.id %]
+                        Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                            [% CASE "cash_payment" %]cash
+                            [% CASE "check_payment" %]check
+                            [% CASE "credit_card_payment" %]credit card
+                            [%- IF mp.credit_card_payment.cc_number %] ([% mp.credit_card_payment.cc_number %])[% END %]
+                            [% CASE "credit_payment" %]credit
+                            [% CASE "forgive_payment" %]forgiveness
+                            [% CASE "goods_payment" %]goods
+                            [% CASE "work_payment" %]work
+                        [%- END %] on [% mp.payment_ts %] [% mp.note %]
+                    </li>
+                [% END %]
+            </ol>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+
+WHERE id = 30 AND template =
+
+$$
+[%- USE date -%][%- SET user = target.0.xact.usr -%]
+<div style="li { padding: 8px; margin 5px; }">
+    <div>[% date.format %]</div><br/>
+    <ol>
+    [% SET xact_mp_hash = {} %]
+    [% FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions %]
+        [% SET xact_id = mp.xact.id %]
+        [% IF ! xact_mp_hash.defined( xact_id ) %][% xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } %][% END %]
+        [% xact_mp_hash.$xact_id.payments.push(mp) %]
+    [% END %]
+    [% FOR xact_id IN xact_mp_hash.keys.sort %]
+        [% SET xact = xact_mp_hash.$xact_id.xact %]
+        <li>Transaction ID: [% xact_id %]
+            [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+            [% ELSE %]Miscellaneous
+            [% END %]
+            Line item billings:<ol>
+                [% SET mb_type_hash = {} %]
+                [% FOR mb IN xact.billings %][%# Group billings by their btype %]
+                    [% IF mb.voided == 'f' %]
+                        [% SET mb_type = mb.btype.id %]
+                        [% IF ! mb_type_hash.defined( mb_type ) %][% mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } %][% END %]
+                        [% IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) %][% mb_type_hash.$mb_type.first_ts = mb.billing_ts %][% END %]
+                        [% mb_type_hash.$mb_type.last_ts = mb.billing_ts %]
+                        [% mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount %]
+                        [% mb_type_hash.$mb_type.billings.push( mb ) %]
+                    [% END %]
+                [% END %]
+                [% FOR mb_type IN mb_type_hash.keys.sort %]
+                    <li>[% IF mb_type == 1 %][%# Consolidated view of overdue billings %]
+                        $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                            on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+                    [% ELSE %][%# all other billings show individually %]
+                        [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                            $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                        [% END %]
+                    [% END %]</li>
+                [% END %]
+            </ol>
+            Line item payments:<ol>
+                [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+                    <li>Payment ID: [% mp.id %]
+                        Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                            [% CASE "cash_payment" %]cash
+                            [% CASE "check_payment" %]check
+                            [% CASE "credit_card_payment" %]credit card (
+                                [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
+                                [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
+                                [% cc_chunks.last -%]
+                                exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
+                            )
+                            [% CASE "credit_payment" %]credit
+                            [% CASE "forgive_payment" %]forgiveness
+                            [% CASE "goods_payment" %]goods
+                            [% CASE "work_payment" %]work
+                        [%- END %] on [% mp.payment_ts %] [% mp.note %]
+                    </li>
+                [% END %]
+            </ol>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$;
+
+
+--ROLLBACK;
+COMMIT;