[open-ils-commits] [GIT] Evergreen ILS branch master updated. c4d1f82da6bb1f3cf73974153fa60644bbfa5e18

Evergreen Git git at git.evergreen-ils.org
Tue Sep 4 13:49:52 EDT 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  c4d1f82da6bb1f3cf73974153fa60644bbfa5e18 (commit)
       via  ab88fed1ef564fa0398c3a883ac1f51b0d1d5796 (commit)
       via  12294ccda64e0792b43a0970217d1658e4e36824 (commit)
       via  0c19fd9d220a92702bf3a0ef51a1a6c78672f5de (commit)
       via  7a120c31eac808708fdf58d09f1917ab915b4658 (commit)
       via  a9c3660f2b7a61069b445b06a4805121d3cf2cda (commit)
      from  647710dbdbd153b7d06ecfcc36ddcf97a933851a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c4d1f82da6bb1f3cf73974153fa60644bbfa5e18
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Tue Sep 4 14:07:38 2018 -0400

    LP#1779920: stamp database update
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 2269cd7..c2ace32 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -92,7 +92,7 @@ CREATE TRIGGER no_overlapping_deps
     BEFORE INSERT OR UPDATE ON config.db_patch_dependencies
     FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
 
-INSERT INTO config.upgrade_log (version, applied_to) VALUES ('1122', :eg_version); -- berick/kmlussier/gmcharlt
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('1123', :eg_version); -- cesardv/berick/gmcharlt
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql b/Open-ILS/src/sql/Pg/upgrade/1123.schema.autorenewals.sql
similarity index 99%
rename from Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
rename to Open-ILS/src/sql/Pg/upgrade/1123.schema.autorenewals.sql
index 5704469..e8b5fcf 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/1123.schema.autorenewals.sql
@@ -1,5 +1,6 @@
 BEGIN;
-    -- SELECT evergreen.upgrade_deps_block_check('xxxx', :eg_version);
+
+SELECT evergreen.upgrade_deps_block_check('1123', :eg_version);
 
     ALTER TABLE config.rule_circ_duration
     ADD column max_auto_renewals INTEGER;

commit ab88fed1ef564fa0398c3a883ac1f51b0d1d5796
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Tue Sep 4 13:55:18 2018 -0400

    LP#1779920: adjust release notes
    
    Wrap text and change the order of the paragraphs to put the
    intent of the feature first.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc b/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc
index b620830..4ad2bad 100644
--- a/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc
+++ b/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc
@@ -1,9 +1,22 @@
-Autorenewal Feature
-^^^^^^^^^^^^^^^^^^^
-Two new action triggers have been added to Evergreen that permit the Auto-Renew feature. They can be found, configured, and enabled in Administration>Local Administration>Notifications/Action Triggers. They are named **Autorenew** and **AutorenewNotify**.
+Autorenewal of Loans
+^^^^^^^^^^^^^^^^^^^^
+Circulation policies in Evergreen can now be configured to automatically renew
+certain items checked out on patron accounts. Circulations will be renewed
+automatically up to a custom limit (the `max_auto_renewal` field) and patrons
+will not need to log in to their OPAC accounts or ask library staff to manually
+renew materials.
 
-The **Autorenew** A/T definition uses the `checkout.due` hook to automatically validate and renew (in the reactor) circulations on the day they are due, grouped by user. The output events of this definition is is the input used by the related **AutorenewNotify** A/T that simply uses a new hook called `autorenewal` to notify patrons via email of their currently due or auto-renewed items.
+Two new action triggers have been added to Evergreen that permit the Auto-Renew
+feature. They can be found, configured, and enabled in Administration>Local
+Administration>Notifications/Action Triggers. They are named **Autorenew** and
+**AutorenewNotify**.
 
-Circulation policies in Evergreen can now be configured to automatically renew certain items checked out on patron accounts. Circulations will be renewed automatically up to a custom limit (the `max_auto_renewal` field) and patrons will not need to log in to their OPAC accounts or ask library staff to manually renew materials.
+The **Autorenew** A/T definition uses the `checkout.due` hook to automatically
+validate and renew (in the reactor) circulations on the day they are due,
+grouped by user. The output events of this definition is is the input used by
+the related **AutorenewNotify** A/T that simply uses a new hook called
+`autorenewal` to notify patrons via email of their currently due or
+auto-renewed items.
 
-In the webstaff's Patron Items Out page, the new column `AutoRenewalsRemaining` indicates how many autorenewals are available for a particular circulation.
+In the webstaff's Patron Items Out page, the new column `AutoRenewalsRemaining`
+indicates how many autorenewals are available for a particular circulation.

commit 12294ccda64e0792b43a0970217d1658e4e36824
Author: Bill Erickson <berickxx at gmail.com>
Date:   Tue Sep 4 10:31:00 2018 -0400

    LP#1779920 Auto-renew modify related tables/views
    
    Add new columns to these tables/views:
    
    * action.all_circulation
    * action.all_circulation_slim
    * action.aged_circulation
    * action.all_circ_chain
    * action.summarize_all_circ_chain
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/sql/Pg/090.schema.action.sql b/Open-ILS/src/sql/Pg/090.schema.action.sql
index 4ce492d..c8b252b 100644
--- a/Open-ILS/src/sql/Pg/090.schema.action.sql
+++ b/Open-ILS/src/sql/Pg/090.schema.action.sql
@@ -153,9 +153,9 @@ CREATE TABLE action.circulation (
 ) INHERITS (money.billable_xact);
 ALTER TABLE action.circulation ADD PRIMARY KEY (id);
 ALTER TABLE action.circulation
-	ADD COLUMN parent_circ BIGINT
-	REFERENCES action.circulation( id )
-	DEFERRABLE INITIALLY DEFERRED;
+       ADD COLUMN parent_circ BIGINT
+       REFERENCES action.circulation( id )
+       DEFERRABLE INITIALLY DEFERRED;
 CREATE INDEX circ_open_xacts_idx ON action.circulation (usr) WHERE xact_finish IS NULL;
 CREATE INDEX circ_outstanding_idx ON action.circulation (usr) WHERE checkin_time IS NULL;
 CREATE INDEX circ_checkin_time ON "action".circulation (checkin_time) WHERE checkin_time IS NOT NULL;
@@ -254,6 +254,7 @@ CREATE OR REPLACE VIEW action.all_circulation AS
         stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine,
         max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule,
         max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ,
+        auto_renewal, auto_renewal_remaining,
         NULL AS usr
       FROM  action.aged_circulation
             UNION ALL
@@ -263,7 +264,7 @@ CREATE OR REPLACE VIEW action.all_circulation AS
         circ.checkin_lib, circ.renewal_remaining, circ.grace_period, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration,
         circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule,
         circ.recurring_fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_workstation, circ.checkin_scan_time,
-        circ.parent_circ, circ.usr
+        circ.parent_circ, circ.auto_renewal, circ.auto_renewal_remaining, circ.usr
       FROM  action.circulation circ
         JOIN asset.copy cp ON (circ.target_copy = cp.id)
         JOIN asset.call_number cn ON (cp.call_number = cn.id)
@@ -306,6 +307,8 @@ UNION ALL
         checkin_workstation,
         copy_location,
         checkin_scan_time,
+        auto_renewal,
+        auto_renewal_remaining,
         parent_circ
     FROM action.aged_circulation
 ;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
index 0bb4a7e..5704469 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
@@ -10,6 +10,12 @@ BEGIN;
     ALTER TABLE action.circulation
     ADD column auto_renewal_remaining INTEGER;
 
+    ALTER TABLE action.aged_circulation
+    ADD column auto_renewal BOOLEAN;
+
+    ALTER TABLE action.aged_circulation
+    ADD column auto_renewal_remaining INTEGER;
+
     INSERT INTO action_trigger.validator values('CircIsAutoRenewable', 'Checks whether the circulation is able to be autorenewed.');
     INSERT INTO action_trigger.reactor values('Circ::AutoRenew', 'Auto-Renews a circulation.');
     INSERT INTO action_trigger.hook(key, core_type, description) values('autorenewal', 'circ', 'Item was auto-renewed to patron.');
@@ -56,4 +62,199 @@ $$
     ( currval('action_trigger.event_definition_id_seq'), 'usr' ),
     ( currval('action_trigger.event_definition_id_seq'), 'circ_lib' );
 
+
+DROP VIEW action.all_circulation;
+CREATE OR REPLACE VIEW action.all_circulation AS
+    SELECT  id,usr_post_code, usr_home_ou, usr_profile, usr_birth_year, copy_call_number, copy_location,
+        copy_owning_lib, copy_circ_lib, copy_bib_record, xact_start, xact_finish, target_copy,
+        circ_lib, circ_staff, checkin_staff, checkin_lib, renewal_remaining, grace_period, due_date,
+        stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine,
+        max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule,
+        max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ,
+        auto_renewal, auto_renewal_remaining, NULL AS usr
+      FROM  action.aged_circulation
+            UNION ALL
+    SELECT  DISTINCT circ.id,COALESCE(a.post_code,b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, EXTRACT(YEAR FROM p.dob)::INT AS usr_birth_year,
+        cp.call_number AS copy_call_number, circ.copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib,
+        cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff,
+        circ.checkin_lib, circ.renewal_remaining, circ.grace_period, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration,
+        circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule,
+        circ.recurring_fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_workstation, circ.checkin_scan_time,
+        circ.parent_circ, circ.auto_renewal, circ.auto_renewal_remaining, circ.usr
+      FROM  action.circulation circ
+        JOIN asset.copy cp ON (circ.target_copy = cp.id)
+        JOIN asset.call_number cn ON (cp.call_number = cn.id)
+        JOIN actor.usr p ON (circ.usr = p.id)
+        LEFT JOIN actor.usr_address a ON (p.mailing_address = a.id)
+        LEFT JOIN actor.usr_address b ON (p.billing_address = b.id);
+
+
+DROP FUNCTION action.summarize_all_circ_chain (INTEGER);
+DROP FUNCTION action.all_circ_chain (INTEGER);
+
+-- rebuild slim circ view
+DROP VIEW action.all_circulation_slim;
+CREATE OR REPLACE VIEW action.all_circulation_slim AS
+    SELECT
+        id,
+        usr,
+        xact_start,
+        xact_finish,
+        unrecovered,
+        target_copy,
+        circ_lib,
+        circ_staff,
+        checkin_staff,
+        checkin_lib,
+        renewal_remaining,
+        grace_period,
+        due_date,
+        stop_fines_time,
+        checkin_time,
+        create_time,
+        duration,
+        fine_interval,
+        recurring_fine,
+        max_fine,
+        phone_renewal,
+        desk_renewal,
+        opac_renewal,
+        duration_rule,
+        recurring_fine_rule,
+        max_fine_rule,
+        stop_fines,
+        workstation,
+        checkin_workstation,
+        copy_location,
+        checkin_scan_time,
+        auto_renewal,
+        auto_renewal_remaining,
+        parent_circ
+    FROM action.circulation
+UNION ALL
+    SELECT
+        id,
+        NULL AS usr,
+        xact_start,
+        xact_finish,
+        unrecovered,
+        target_copy,
+        circ_lib,
+        circ_staff,
+        checkin_staff,
+        checkin_lib,
+        renewal_remaining,
+        grace_period,
+        due_date,
+        stop_fines_time,
+        checkin_time,
+        create_time,
+        duration,
+        fine_interval,
+        recurring_fine,
+        max_fine,
+        phone_renewal,
+        desk_renewal,
+        opac_renewal,
+        duration_rule,
+        recurring_fine_rule,
+        max_fine_rule,
+        stop_fines,
+        workstation,
+        checkin_workstation,
+        copy_location,
+        checkin_scan_time,
+        auto_renewal,
+        auto_renewal_remaining,
+        parent_circ
+    FROM action.aged_circulation
+;
+
+CREATE OR REPLACE FUNCTION action.all_circ_chain (ctx_circ_id INTEGER) 
+    RETURNS SETOF action.all_circulation_slim AS $$
+DECLARE
+    tmp_circ action.all_circulation_slim%ROWTYPE;
+    circ_0 action.all_circulation_slim%ROWTYPE;
+BEGIN
+
+    SELECT INTO tmp_circ * FROM action.all_circulation_slim WHERE id = ctx_circ_id;
+
+    IF tmp_circ IS NULL THEN
+        RETURN NEXT tmp_circ;
+    END IF;
+    circ_0 := tmp_circ;
+
+    -- find the front of the chain
+    WHILE TRUE LOOP
+        SELECT INTO tmp_circ * FROM action.all_circulation_slim 
+            WHERE id = tmp_circ.parent_circ;
+        IF tmp_circ IS NULL THEN
+            EXIT;
+        END IF;
+        circ_0 := tmp_circ;
+    END LOOP;
+
+    -- now send the circs to the caller, oldest to newest
+    tmp_circ := circ_0;
+    WHILE TRUE LOOP
+        IF tmp_circ IS NULL THEN
+            EXIT;
+        END IF;
+        RETURN NEXT tmp_circ;
+        SELECT INTO tmp_circ * FROM action.all_circulation_slim 
+            WHERE parent_circ = tmp_circ.id;
+    END LOOP;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- same as action.summarize_circ_chain, but returns data collected
+-- from action.all_circulation, which may include aged circulations.
+CREATE OR REPLACE FUNCTION action.summarize_all_circ_chain 
+    (ctx_circ_id INTEGER) RETURNS action.circ_chain_summary AS $$
+
+DECLARE
+
+    -- first circ in the chain
+    circ_0 action.all_circulation_slim%ROWTYPE;
+
+    -- last circ in the chain
+    circ_n action.all_circulation_slim%ROWTYPE;
+
+    -- circ chain under construction
+    chain action.circ_chain_summary;
+    tmp_circ action.all_circulation_slim%ROWTYPE;
+
+BEGIN
+    
+    chain.num_circs := 0;
+    FOR tmp_circ IN SELECT * FROM action.all_circ_chain(ctx_circ_id) LOOP
+
+        IF chain.num_circs = 0 THEN
+            circ_0 := tmp_circ;
+        END IF;
+
+        chain.num_circs := chain.num_circs + 1;
+        circ_n := tmp_circ;
+    END LOOP;
+
+    chain.start_time := circ_0.xact_start;
+    chain.last_stop_fines := circ_n.stop_fines;
+    chain.last_stop_fines_time := circ_n.stop_fines_time;
+    chain.last_checkin_time := circ_n.checkin_time;
+    chain.last_checkin_scan_time := circ_n.checkin_scan_time;
+    SELECT INTO chain.checkout_workstation name FROM actor.workstation WHERE id = circ_0.workstation;
+    SELECT INTO chain.last_checkin_workstation name FROM actor.workstation WHERE id = circ_n.checkin_workstation;
+
+    IF chain.num_circs > 1 THEN
+        chain.last_renewal_time := circ_n.xact_start;
+        SELECT INTO chain.last_renewal_workstation name FROM actor.workstation WHERE id = circ_n.workstation;
+    END IF;
+
+    RETURN chain;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+
 COMMIT;

commit 0c19fd9d220a92702bf3a0ef51a1a6c78672f5de
Author: Cesar Velez <cesar.velez at equinoxinitiative.org>
Date:   Tue Aug 21 18:23:14 2018 -0400

    LP#1779920 - Autorenewal Feature-Release Docs
    
    Summary release notes for Autorenewal
    
    Signed-off by: Cesar Velez <cesar.velez at equinoxinitiative.org>
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc b/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc
new file mode 100644
index 0000000..b620830
--- /dev/null
+++ b/docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc
@@ -0,0 +1,9 @@
+Autorenewal Feature
+^^^^^^^^^^^^^^^^^^^
+Two new action triggers have been added to Evergreen that permit the Auto-Renew feature. They can be found, configured, and enabled in Administration>Local Administration>Notifications/Action Triggers. They are named **Autorenew** and **AutorenewNotify**.
+
+The **Autorenew** A/T definition uses the `checkout.due` hook to automatically validate and renew (in the reactor) circulations on the day they are due, grouped by user. The output events of this definition is is the input used by the related **AutorenewNotify** A/T that simply uses a new hook called `autorenewal` to notify patrons via email of their currently due or auto-renewed items.
+
+Circulation policies in Evergreen can now be configured to automatically renew certain items checked out on patron accounts. Circulations will be renewed automatically up to a custom limit (the `max_auto_renewal` field) and patrons will not need to log in to their OPAC accounts or ask library staff to manually renew materials.
+
+In the webstaff's Patron Items Out page, the new column `AutoRenewalsRemaining` indicates how many autorenewals are available for a particular circulation.

commit 7a120c31eac808708fdf58d09f1917ab915b4658
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Aug 29 17:19:07 2018 -0400

    LP#1779920 Circ auto-renewal repairs
    
    * Remove hard-coded granularity for auto-renewal notification event
      generation
    * Moved schema update changes from 950 seed file into schema files.
    * Added CircIsOpen validator to auto-renewal reactor on the off chance
      a circ is renewed by the patron in the middle of event processing.
    * Notification template formatting and language updates, and removed
      debugging content.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Cesar Velez <cesar.velez at equinoxinitiative.org>
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
index 71eeb65..f06adc8 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
@@ -75,7 +75,10 @@ sub handler {
             old_due_date => !$is_renewed ? $_->due_date() : '',
         );
 
-        $ses->request('open-ils.trigger.event.autocreate', 'autorenewal', $_, $_->circ_lib(), 'system_autorenewal', \%user_data);
+        # Create the event from the source circ instead of the
+        # new circ, since the renewal may have failed.
+        $ses->request('open-ils.trigger.event.autocreate', 
+            'autorenewal', $_, $_->circ_lib(), undef, \%user_data);
     }
 
     $ses->disconnect;
diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 43c1903..2269cd7 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -333,7 +333,8 @@ CREATE TABLE config.rule_circ_duration (
 	extended	INTERVAL	NOT NULL,
 	normal		INTERVAL	NOT NULL,
 	shrt		INTERVAL	NOT NULL,
-	max_renewals	INT		NOT NULL
+	max_renewals	INT		NOT NULL,
+    max_auto_renewals INTEGER
 );
 COMMENT ON TABLE config.rule_circ_duration IS $$
 Circulation Duration rules
diff --git a/Open-ILS/src/sql/Pg/090.schema.action.sql b/Open-ILS/src/sql/Pg/090.schema.action.sql
index 2fb3659..4ce492d 100644
--- a/Open-ILS/src/sql/Pg/090.schema.action.sql
+++ b/Open-ILS/src/sql/Pg/090.schema.action.sql
@@ -147,7 +147,9 @@ CREATE TABLE action.circulation (
 	                               ON DELETE SET NULL
 								   DEFERRABLE INITIALLY DEFERRED,
 	copy_location	INT				NOT NULL DEFAULT 1 REFERENCES asset.copy_location (id) DEFERRABLE INITIALLY DEFERRED,
-	checkin_scan_time   TIMESTAMP WITH TIME ZONE
+	checkin_scan_time   TIMESTAMP WITH TIME ZONE,
+    auto_renewal            BOOLEAN,
+    auto_renewal_remaining  INTEGER
 ) INHERITS (money.billable_xact);
 ALTER TABLE action.circulation ADD PRIMARY KEY (id);
 ALTER TABLE action.circulation
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index 8412225..cf51b60 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -10293,49 +10293,46 @@ INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
 
 -- AUTORENEWAL Action Trigger definitions and email notification template
 
-ALTER TABLE config.rule_circ_duration
-ADD column max_auto_renewals INTEGER;
-
-ALTER TABLE action.circulation
-ADD column auto_renewal BOOLEAN;
-
-ALTER TABLE action.circulation
-ADD column auto_renewal_remaining INTEGER;
-
 INSERT INTO action_trigger.validator values('CircIsAutoRenewable', 'Checks whether the circulation is able to be autorenewed.');
 INSERT INTO action_trigger.reactor values('Circ::AutoRenew', 'Auto-Renews a circulation.');
 INSERT INTO action_trigger.hook(key, core_type, description) values('autorenewal', 'circ', 'Item was auto-renewed to patron.');
 
 -- AutoRenewer A/T Def: 
 INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, delay, max_delay, delay_field, group_field)
-    values (false, 1, 'Autorenew', 'checkout.due', 'NOOP_True', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
+    values (false, 1, 'Autorenew', 'checkout.due', 'CircIsOpen', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
 
 -- AutoRenewal outcome Email notifier A/T Def:
 INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, group_field, template)
     values (false, 1, 'AutorenewNotify', 'autorenewal', 'NOOP_True', 'SendEmail', 'usr', 
-    $$
-    [%- USE date -%]
-    [%- user = target.0.usr -%]
-    To: [%- params.recipient_email || user.email %]
-    From: [%- params.sender_email || default_sender %]
-    Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
-    Subject: Items Out Auto-Renewal Notification Auto-Submitted: auto-generated
-    
-    Dear [% user.family_name %], [% user.first_given_name %]
-    Your library would like to let you know about your currently borrowed item(s):
-    
-    [% FOR circ IN target %]
-        [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
-        Item# [%+ loop.count -%]
-        [%- SET cid = circ.target_copy || udata.copy -%]
-        [%- SET copy_details = helpers.get_copy_bib_basics(cid) +%]
-        Title: [% copy_details.title %]
-        Author: [% copy_details.author %]
-        Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
-        Status:   [%- IF udata.is_renewed %] Loan Renewed. Now Due: [%- date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
-        [% ELSE %] Not Renewed. Reason: [% udata.reason %] [% END %]
+$$
+[%- USE date -%]
+[%- user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
+Subject: Items Out Auto-Renewal Notification 
+Auto-Submitted: auto-generated
+
+Dear [% user.family_name %], [% user.first_given_name %]
+An automatic renewal attempt was made for the following items:
+
+[% FOR circ IN target %]
+    [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
+    [%- SET cid = circ.target_copy || udata.copy -%]
+    [%- SET copy_details = helpers.get_copy_bib_basics(cid) -%]
+    Item# [% loop.count %]
+    Title: [% copy_details.title %]
+    Author: [% copy_details.author %]
+    [%- IF udata.is_renewed %]
+    Status: Loan Renewed
+    New Due Date: [% date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
+    [%- ELSE %]
+    Status: Not Renewed
+    Reason: [% udata.reason %]
+    Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
     [% END %]
-    $$
+[% END %]
+$$
 );
 
 INSERT INTO action_trigger.environment (event_def, path ) VALUES
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
index 9fb38e3..0bb4a7e 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
@@ -16,34 +16,40 @@ BEGIN;
 
     -- AutoRenewer A/T Def: 
     INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, delay, max_delay, delay_field, group_field)
-        values (true, 1, 'Autorenew', 'checkout.due', 'NOOP_True', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
+        values (false, 1, 'Autorenew', 'checkout.due', 'CircIsOpen', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
 
     -- AutoRenewal outcome Email notifier A/T Def:
     INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, group_field, template)
-        values (true, 1, 'AutorenewNotify', 'autorenewal', 'NOOP_True', 'SendEmail', 'usr', 
-        $$
-        [%- USE date -%]
-        [%- user = target.0.usr -%]
-        To: [%- params.recipient_email || user.email %]
-        From: [%- params.sender_email || default_sender %]
-        Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
-        Subject: Items Out Auto-Renewal Notification Auto-Submitted: auto-generated
-        
-        Dear [% user.family_name %], [% user.first_given_name %] (UserID: [%- user.id +%])
-        Your library would like to let you know about your currently borrowed item(s):
-        
-        [% FOR circ IN target %]
-            [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
-            Item# [%+ loop.count -%] (circ_id: [%- circ.id -%])
-            [%- SET cid = circ.target_copy || udata.copy -%]
-            [%- SET copy_details = helpers.get_copy_bib_basics(cid) +%]
-            Title: [% copy_details.title %]
-            Author: [% copy_details.author %]
-            Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
-            Status:   [%- IF udata.is_renewed %] Loan Renewed. Now Due: [%- date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
-            [% ELSE %] Not Renewed. Reason: [% udata.reason %] [% END %]
-        [% END %]
-        $$
+        values (false, 1, 'AutorenewNotify', 'autorenewal', 'NOOP_True', 'SendEmail', 'usr', 
+$$
+[%- USE date -%]
+[%- user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
+Subject: Items Out Auto-Renewal Notification 
+Auto-Submitted: auto-generated
+
+Dear [% user.family_name %], [% user.first_given_name %]
+An automatic renewal attempt was made for the following items:
+
+[% FOR circ IN target %]
+    [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
+    [%- SET cid = circ.target_copy || udata.copy -%]
+    [%- SET copy_details = helpers.get_copy_bib_basics(cid) -%]
+    Item# [% loop.count %]
+    Title: [% copy_details.title %]
+    Author: [% copy_details.author %]
+    [%- IF udata.is_renewed %]
+    Status: Loan Renewed
+    New Due Date: [% date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
+    [%- ELSE %]
+    Status: Not Renewed
+    Reason: [% udata.reason %]
+    Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+    [% END %]
+[% END %]
+$$
     );
 
     INSERT INTO action_trigger.environment (event_def, path ) VALUES

commit a9c3660f2b7a61069b445b06a4805121d3cf2cda
Author: Cesar Velez <cesar.velez at equinoxinitiative.org>
Date:   Tue Aug 28 16:13:51 2018 -0400

    LP#1779920 - Autorenew Feature
    
    This branch adds the necessary changes to allow Evergreen via the
    Action/Trigger system to generate daily automatic renewals of
    outstanding loans. Implemented as pair of A/T definitions: Autorenew and
    AutorenewNotify.
    
    Signed-off by: Cesar Velez <cesar.velez at equinoxinitiative.org>
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 9436ceb..c9a60dd 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -3446,6 +3446,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field name="name" reporter:datatype="text"/>
 			<field name="normal" reporter:datatype="interval"/>
 			<field name="shrt" reporter:datatype="interval"/>
+			<field name="max_auto_renewals" reporter:datatype="int" />
 		</fields>
 		<links>
 		</links>
@@ -4562,6 +4563,8 @@ SELECT  usr,
 			<field reporter:label="Shelving Location" name="copy_location" reporter:datatype="link"/>
 			<field reporter:label="Archived Patron Stat-Cat Entries" name="aaactsc_entries" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field reporter:label="Archived Copy Stat-Cat Entries" name="aaasc_entries" oils_persist:virtual="true" reporter:datatype="link"/>
+			<field reporter:label="Auto Renewal" name="auto_renewal" reporter:datatype="bool"/>
+			<field reporter:label="Remaining Auto Renewals" name="auto_renewal_remaining" reporter:datatype="int" />
 		</fields>
 		<links>
 			<link field="billable_transaction" reltype="might_have" key="id" map="" class="mbt"/>
diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml
index 473b2d6..9f92944 100644
--- a/Open-ILS/src/extras/ils_events.xml
+++ b/Open-ILS/src/extras/ils_events.xml
@@ -930,6 +930,9 @@
 	<event code='7028' textcode='PATRON_CIRC_MISMATCH'>
 	        <desc xml:lang="en-US">Potentially notified patron does not own the circulation.</desc>
 	</event>
+	<event code='7029' textcode='MAX_AUTO_RENEWALS_REACHED'>
+		<desc xml:lang="en-US">Circulation has no more auto-renewals remaining</desc>
+	</event>
 
 
 	<!-- ================================================================ -->
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
index c2d5518..ab9d178 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
@@ -124,6 +124,11 @@ __PACKAGE__->register_method(
     signature => q/@see open-ils.circ.renew/,
 );
 
+__PACKAGE__->register_method(
+    method    => "run_method",
+    api_name  => "open-ils.circ.renew.auto",
+    signature => q/@see open-ils.circ.renew/,
+);
 
 __PACKAGE__->register_method(
     method  => "run_method",
@@ -239,6 +244,7 @@ sub run_method {
     }
 
     $circulator->is_renewal(1) if $api =~ /renew/;
+    $circulator->is_autorenewal(1) if $api =~ /renew.auto/;
     $circulator->is_checkin(1) if $api =~ /checkin/;
     $circulator->is_checkout(1) if $api =~ /checkout/;
     $circulator->override(1) if $api =~ /override/o;
@@ -282,7 +288,7 @@ sub run_method {
         $circulator->do_checkin();
 
     } elsif( $api =~ /renew/ ) {
-        $circulator->do_renew();
+        $circulator->do_renew($api);
     }
 
     if( $circulator->bail_out ) {
@@ -427,6 +433,7 @@ my @AUTOLOAD_FIELDS = qw/
     volume
     title
     is_renewal
+    is_autorenewal
     is_checkout
     is_res_checkout
     is_precat
@@ -464,6 +471,7 @@ my @AUTOLOAD_FIELDS = qw/
     recurring_fines_rule
     max_fine_rule
     renewal_remaining
+    auto_renewal_remaining
     hard_due_date
     due_date
     fulfilled_holds
@@ -1395,6 +1403,7 @@ sub get_circ_policy {
         max_fine => $self->get_max_fine_amount($max_fine_rule),
         fine_interval => $recurring_fine_rule->recurrence_interval,
         renewal_remaining => $duration_rule->max_renewals,
+        auto_renewal_remaining => $duration_rule->max_auto_renewals,
         grace_period => $recurring_fine_rule->grace_period
     };
 
@@ -2118,6 +2127,7 @@ sub build_checkout_circ_object {
         $circ->max_fine($policy->{max_fine});
         $circ->fine_interval($recurring->recurrence_interval);
         $circ->renewal_remaining($duration->max_renewals);
+        $circ->auto_renewal_remaining($duration->max_auto_renewals);
         $circ->grace_period($policy->{grace_period});
 
     } else {
@@ -2147,6 +2157,10 @@ sub build_checkout_circ_object {
       $circ->circ_staff($self->editor->requestor->id);
    }
 
+   if ( $self->is_autorenewal ){
+      $circ->auto_renewal_remaining($self->auto_renewal_remaining);
+      $circ->auto_renewal('t');
+   }
 
     # if the user provided an overiding checkout time,
     # (e.g. the checkout really happened several hours ago), then
@@ -3970,6 +3984,7 @@ sub log_me {
 
 sub do_renew {
     my $self = shift;
+    my $api = shift;
     $self->log_me("do_renew()");
 
     # Make sure there is an open circ to renew
@@ -3992,14 +4007,17 @@ sub do_renew {
     $self->push_events(OpenILS::Event->new('MAX_RENEWALS_REACHED'))
         if $circ->renewal_remaining < 1;
 
+    $self->push_events(OpenILS::Event->new('MAX_AUTO_RENEWALS_REACHED'))
+        if $api =~ /renew.auto/ and $circ->auto_renewal_remaining < 1;
     # -----------------------------------------------------------------
 
     $self->parent_circ($circ->id);
     $self->renewal_remaining( $circ->renewal_remaining - 1 );
+    $self->auto_renewal_remaining( $circ->auto_renewal_remaining - 1 ) if (defined($circ->auto_renewal_remaining));
     $self->circ($circ);
 
     # Opac renewal - re-use circ library from original circ (unless told not to)
-    if($self->opac_renewal) {
+    if($self->opac_renewal or $api =~ /renew.auto/) {
         unless(defined($opac_renewal_use_circ_lib)) {
             my $use_circ_lib = $self->editor->retrieve_config_global_flag('circ.opac_renewal.use_original_circ_lib');
             if($use_circ_lib and $U->is_true($use_circ_lib->enabled)) {
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/config.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/config.pm
index e91ff20..c1c2f9c 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/config.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/config.pm
@@ -52,7 +52,7 @@ package config::rules::circ_duration;
 use base qw/config/;
 __PACKAGE__->table('config_rule_circ_duration');
 __PACKAGE__->columns(Primary => 'id');
-__PACKAGE__->columns(Essential => qw/name extended normal shrt max_renewals/);
+__PACKAGE__->columns(Essential => qw/name extended normal shrt max_renewals max_auto_renewals/);
 #-------------------------------------------------------------------------------
 
 package config::rules::max_fine;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
new file mode 100644
index 0000000..71eeb65
--- /dev/null
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
@@ -0,0 +1,86 @@
+package OpenILS::Application::Trigger::Reactor::Circ::AutoRenew;
+use strict; use warnings;
+use Error qw/:try/;
+use Data::Dumper;
+use OpenSRF::Utils::SettingsClient;
+use OpenILS::Application::Trigger::Reactor;
+use OpenSRF::Utils::Logger qw/:logger/;
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Application::AppUtils;
+my $AppUtils = 'OpenILS::Application::AppUtils';
+
+use Encode;
+$Data::Dumper::Indent = 0;
+
+use base 'OpenILS::Application::Trigger::Reactor';
+
+my $log = 'OpenSRF::Utils::Logger';
+
+sub ABOUT {
+    return <<ABOUT;
+This Autorenew reactor will auto renew a circulation on the day it is due.
+ABOUT
+}
+
+sub handler {
+    my $self = shift;
+    my $env = shift;
+
+    # 1. get a session token for circ user
+
+    my $circs = $env->{target};
+    my $svc = "open-ils.auth_internal";
+    my $api = $svc . '.session.create';
+
+    my $auth_internal_svc = OpenSRF::AppSession->create($svc);
+
+    my $userid = $circs->[0]->usr();
+    # fetch user
+    my $userObj = new_editor()->retrieve_actor_user($userid);
+    my %args = 
+        ( 
+            user_id => $userid,
+            org_unit => $userObj->home_ou(), # all autorenewals occur from patron's Home OU.
+            login_type => "opac"
+        );
+
+    my $token = $auth_internal_svc->request($api, \%args)->gather(1)->{payload}->{authtoken};
+    
+    # 2. carry out renewal:
+    my $ses = OpenSRF::AppSession->connect('open-ils.trigger');
+    for (@$circs){
+
+        $logger->info( "AUTORENEW: circ.target_copy: " . Dumper($_->target_copy()) );
+        my $evt = $AppUtils->simplereq(
+            'open-ils.circ',
+            'open-ils.circ.renew.auto',
+            $token,
+            {
+                patron_id => $_->usr(),
+                copy_id => $_->target_copy(),
+                opac_renewal => 0
+            }
+        );
+
+        $evt = $evt->[0] if ref($evt) eq "ARRAY";  # we got two resp events, likely renewal errors, grab the first.
+        my $is_renewed = $evt->{textcode} eq 'SUCCESS' ? 1 : 0;
+
+        my $new_circ_due = $is_renewed ? $evt->{payload}->{circ}->due_date : '';
+
+        my %user_data = (
+            copy => $_->target_copy(),
+            is_renewed => $is_renewed,
+            reason => !$is_renewed ? sprintf("%s : %s", $evt->{textcode}, substr($evt->{desc}, 0, 140)) : '',
+            new_due_date => $is_renewed ? $evt->{payload}->{circ}->due_date : '',
+            old_due_date => !$is_renewed ? $_->due_date() : '',
+        );
+
+        $ses->request('open-ils.trigger.event.autocreate', 'autorenewal', $_, $_->circ_lib(), 'system_autorenewal', \%user_data);
+    }
+
+    $ses->disconnect;
+
+    return 1;
+}
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
index 1a53dfb..c45d1ea 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
@@ -7,6 +7,8 @@ use OpenSRF::Utils::Logger qw/:logger/;
 use OpenILS::Const qw/:const/;
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use Data::Dumper;
+
 sub fourty_two { return 42 }
 sub NOOP_True { return 1 }
 sub NOOP_False { return 0 }
@@ -25,6 +27,7 @@ sub CircIsOpen {
         return 0 if (!$self->MinPassiveTargetAge($env));
     }
 
+    $logger->info("AUTORENEW: CircIsOpen is TRUE!");
     return 1;
 }
 
@@ -188,5 +191,34 @@ sub PatronNotInCollections {
     return @$existing ? 0 : 1;
 }
 
+# core type circ in $env->{target}
+sub CircIsAutoRenewable {
+    my $self = shift;
+    my $env = shift;
+
+    my $circ = $env->{target};
+    my $userId = $env->{target}->usr;
+    # 1. check if circ is open
+    if (!$self->CircIsOpen($env)){
+        return 0;
+    }
+
+    # 2. Check if patron is barred
+
+    my ($user, $res) = $U->fetch_user($userId);
+    if ( $U->is_true($user->barred()) ){
+
+        my %user_data = (
+            is_renewed => 0,
+            reason => 'Please contact your library about your account.',
+        );
+
+        $U->create_events_for_hook('autorenewal', $circ, $user->home_ou(), 'system_autorenewal', \%user_data);
+
+        return 0;
+    }
+
+    return 1;
+}
 
 1;
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index d4ffab6..8412225 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -10291,6 +10291,58 @@ INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
     'A hold is cancelled by the patron'
 );
 
+-- AUTORENEWAL Action Trigger definitions and email notification template
+
+ALTER TABLE config.rule_circ_duration
+ADD column max_auto_renewals INTEGER;
+
+ALTER TABLE action.circulation
+ADD column auto_renewal BOOLEAN;
+
+ALTER TABLE action.circulation
+ADD column auto_renewal_remaining INTEGER;
+
+INSERT INTO action_trigger.validator values('CircIsAutoRenewable', 'Checks whether the circulation is able to be autorenewed.');
+INSERT INTO action_trigger.reactor values('Circ::AutoRenew', 'Auto-Renews a circulation.');
+INSERT INTO action_trigger.hook(key, core_type, description) values('autorenewal', 'circ', 'Item was auto-renewed to patron.');
+
+-- AutoRenewer A/T Def: 
+INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, delay, max_delay, delay_field, group_field)
+    values (false, 1, 'Autorenew', 'checkout.due', 'NOOP_True', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
+
+-- AutoRenewal outcome Email notifier A/T Def:
+INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, group_field, template)
+    values (false, 1, 'AutorenewNotify', 'autorenewal', 'NOOP_True', 'SendEmail', 'usr', 
+    $$
+    [%- USE date -%]
+    [%- user = target.0.usr -%]
+    To: [%- params.recipient_email || user.email %]
+    From: [%- params.sender_email || default_sender %]
+    Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
+    Subject: Items Out Auto-Renewal Notification Auto-Submitted: auto-generated
+    
+    Dear [% user.family_name %], [% user.first_given_name %]
+    Your library would like to let you know about your currently borrowed item(s):
+    
+    [% FOR circ IN target %]
+        [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
+        Item# [%+ loop.count -%]
+        [%- SET cid = circ.target_copy || udata.copy -%]
+        [%- SET copy_details = helpers.get_copy_bib_basics(cid) +%]
+        Title: [% copy_details.title %]
+        Author: [% copy_details.author %]
+        Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+        Status:   [%- IF udata.is_renewed %] Loan Renewed. Now Due: [%- date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
+        [% ELSE %] Not Renewed. Reason: [% udata.reason %] [% END %]
+    [% END %]
+    $$
+);
+
+INSERT INTO action_trigger.environment (event_def, path ) VALUES
+( currval('action_trigger.event_definition_id_seq'), 'usr' ),
+( currval('action_trigger.event_definition_id_seq'), 'circ_lib' );
+
+-- END of autorenwal trigger def stuff
 
 -- in-db indexing normalizers
 INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
new file mode 100644
index 0000000..9fb38e3
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.autorenewals_acp_and_circ_duration.sql
@@ -0,0 +1,53 @@
+BEGIN;
+    -- SELECT evergreen.upgrade_deps_block_check('xxxx', :eg_version);
+
+    ALTER TABLE config.rule_circ_duration
+    ADD column max_auto_renewals INTEGER;
+
+    ALTER TABLE action.circulation
+    ADD column auto_renewal BOOLEAN;
+
+    ALTER TABLE action.circulation
+    ADD column auto_renewal_remaining INTEGER;
+
+    INSERT INTO action_trigger.validator values('CircIsAutoRenewable', 'Checks whether the circulation is able to be autorenewed.');
+    INSERT INTO action_trigger.reactor values('Circ::AutoRenew', 'Auto-Renews a circulation.');
+    INSERT INTO action_trigger.hook(key, core_type, description) values('autorenewal', 'circ', 'Item was auto-renewed to patron.');
+
+    -- AutoRenewer A/T Def: 
+    INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, delay, max_delay, delay_field, group_field)
+        values (true, 1, 'Autorenew', 'checkout.due', 'NOOP_True', 'Circ::AutoRenew', '-23 hours'::interval,'-1 minute'::interval, 'due_date', 'usr');
+
+    -- AutoRenewal outcome Email notifier A/T Def:
+    INSERT INTO action_trigger.event_definition(active, owner, name, hook, validator, reactor, group_field, template)
+        values (true, 1, 'AutorenewNotify', 'autorenewal', 'NOOP_True', 'SendEmail', 'usr', 
+        $$
+        [%- USE date -%]
+        [%- user = target.0.usr -%]
+        To: [%- params.recipient_email || user.email %]
+        From: [%- params.sender_email || default_sender %]
+        Date: [%- date.format(date.now, '%a, %d %b %Y %T -0000', gmt => 1) %]
+        Subject: Items Out Auto-Renewal Notification Auto-Submitted: auto-generated
+        
+        Dear [% user.family_name %], [% user.first_given_name %] (UserID: [%- user.id +%])
+        Your library would like to let you know about your currently borrowed item(s):
+        
+        [% FOR circ IN target %]
+            [%- SET idx = loop.count - 1; SET udata =  user_data.$idx -%]
+            Item# [%+ loop.count -%] (circ_id: [%- circ.id -%])
+            [%- SET cid = circ.target_copy || udata.copy -%]
+            [%- SET copy_details = helpers.get_copy_bib_basics(cid) +%]
+            Title: [% copy_details.title %]
+            Author: [% copy_details.author %]
+            Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+            Status:   [%- IF udata.is_renewed %] Loan Renewed. Now Due: [%- date.format(helpers.format_date(udata.new_due_date), '%Y-%m-%d') %]
+            [% ELSE %] Not Renewed. Reason: [% udata.reason %] [% END %]
+        [% END %]
+        $$
+    );
+
+    INSERT INTO action_trigger.environment (event_def, path ) VALUES
+    ( currval('action_trigger.event_definition_id_seq'), 'usr' ),
+    ( currval('action_trigger.event_definition_id_seq'), 'circ_lib' );
+
+COMMIT;
diff --git a/Open-ILS/src/templates/conify/global/config/rule_circ_duration.tt2 b/Open-ILS/src/templates/conify/global/config/rule_circ_duration.tt2
index 1cdd497..aeff5eb 100644
--- a/Open-ILS/src/templates/conify/global/config/rule_circ_duration.tt2
+++ b/Open-ILS/src/templates/conify/global/config/rule_circ_duration.tt2
@@ -10,7 +10,7 @@
     </div>
     <table  jsId="ruleCircDurationGrid"
             dojoType="openils.widget.AutoGrid"
-            fieldOrder="['name', 'max_renewals', 'shrt', 'normal', 'extended']"
+            fieldOrder="['name', 'max_renewals', 'max_auto_renewals', 'shrt', 'normal', 'extended']"
             suppressFields="['id']"
             query="{id: '*'}"
             fmClass='crcd'

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/examples/fm_IDL.xml                       |    3 +
 Open-ILS/src/extras/ils_events.xml                 |    3 +
 .../lib/OpenILS/Application/Circ/Circulate.pm      |   22 ++-
 .../lib/OpenILS/Application/Storage/CDBI/config.pm |    2 +-
 .../Application/Trigger/Reactor/Circ/AutoRenew.pm  |   89 +++++++
 .../lib/OpenILS/Application/Trigger/Validator.pm   |   32 +++
 Open-ILS/src/sql/Pg/002.schema.config.sql          |    5 +-
 Open-ILS/src/sql/Pg/090.schema.action.sql          |   15 +-
 Open-ILS/src/sql/Pg/950.data.seed-values.sql       |   49 ++++
 .../sql/Pg/upgrade/1123.schema.autorenewals.sql    |  261 ++++++++++++++++++++
 .../conify/global/config/rule_circ_duration.tt2    |    2 +-
 .../Circulation/Autorenewal_Feature.adoc           |   22 ++
 12 files changed, 494 insertions(+), 11 deletions(-)
 create mode 100644 Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/Circ/AutoRenew.pm
 create mode 100644 Open-ILS/src/sql/Pg/upgrade/1123.schema.autorenewals.sql
 create mode 100644 docs/RELEASE_NOTES_NEXT/Circulation/Autorenewal_Feature.adoc


hooks/post-receive
-- 
Evergreen ILS




More information about the open-ils-commits mailing list