From 2c9c14411bb060d8c1588da4ede2c3d343da5ccd Mon Sep 17 00:00:00 2001 From: "A. Sassmannshausen" Date: Fri, 4 Apr 2014 09:55:07 +0000 Subject: [PATCH] Bug 5670: Housebound Readers Module New module to handle management of circulation to Housebound readers. - Ability to create housebound profiles & scheduled visits for patrons. - Ability to record users as Deliverers or Choosers (or both), using extended patron attributes. - Ability to link choosers and deliverers to individual delivery runs. - 'Delivery Frequencies' are customizable through authorised values ('Frequency' category respectively). * C4/Auth.pm: Add check: useHouseboundModule. * koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc: add Housebound menu if appropriate. * Koha/Patron.pm (housebound_profile): New method. * Koha/Patron.pm (housebound_choosers, housebound_deliverers): New methods. * Koha/Patron/Housebound.pm: New File. * Koha/Patron/HouseboundProfile.pm: New File. * Koha/Patron/HouseboundProfiles.pm: New File. * Koha/Patron/HouseboundVisits.pm: New File. * Koha/Patron/HouseboundVisit.pm: New File. * koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt: New file. * members/housebound.pl: New file. * installer/data/mysql/kohastructure.sql: Add housebound_* tables. * installer/data/mysql/sysprefs.sql: Add HouseboundModule syspref. * koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref: Add HouseboundModule syspref. * installer/data/mysql/atomicupdate/housebound_tables.sql: New file. * t/db_dependent/Patron/Housebound.t: New file. * t/db_dependent/Patron/HouseboundProfiles.t: New file. * t/db_dependent/Patron/HouseboundVisits.t: New file. Test plan: - Apply patch. - Run atomic update script. - Run Unit Tests (t/db_dependent/Patron/Housebound*) - Optionally, add additional authorised values of 'Frequency' categories. - Verify 'HouseboundModule', and 'ExtendedPatronAttributes sysprefs are on. - Ona patron page, the Housebound menu should have been added. - create housebound profile + ensure Frequency values are from correct authorised values. - create 'housebound visits' (deliveries) + ensure chooser/deliverer lists are populated with patrons that have the Chooser or Deliverer Attribute type (none by default: you will have to grant some users those attributes). - edit the profile/instances. - delete the instances. - Switch off 'HouseboundModule' - the Housebound menu should disappear --- C4/Auth.pm | 1 + Koha/Patron.pm | 13 + Koha/Patron/HouseboundProfile.pm | 72 ++++ Koha/Patron/HouseboundProfiles.pm | 61 +++ Koha/Patron/HouseboundVisit.pm | 56 +++ Koha/Patron/HouseboundVisits.pm | 61 +++ Koha/Patrons.pm | 34 ++ .../data/mysql/atomicupdate/housebound_tables.sql | 52 +++ installer/data/mysql/kohastructure.sql | 48 +++ installer/data/mysql/sysprefs.sql | 1 + .../intranet-tmpl/prog/en/includes/circ-menu.inc | 3 + .../en/modules/admin/preferences/circulation.pref | 7 + .../prog/en/modules/members/housebound.tt | 425 +++++++++++++++++++++ members/housebound.pl | 170 +++++++++ t/db_dependent/Patron/Housebound.t | 81 ++++ t/db_dependent/Patron/HouseboundProfiles.t | 75 ++++ t/db_dependent/Patron/HouseboundVisits.t | 53 +++ 17 files changed, 1213 insertions(+) create mode 100644 Koha/Patron/HouseboundProfile.pm create mode 100644 Koha/Patron/HouseboundProfiles.pm create mode 100644 Koha/Patron/HouseboundVisit.pm create mode 100644 Koha/Patron/HouseboundVisits.pm create mode 100644 installer/data/mysql/atomicupdate/housebound_tables.sql create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt create mode 100755 members/housebound.pl create mode 100755 t/db_dependent/Patron/Housebound.t create mode 100644 t/db_dependent/Patron/HouseboundProfiles.t create mode 100644 t/db_dependent/Patron/HouseboundVisits.t diff --git a/C4/Auth.pm b/C4/Auth.pm index 3081f07..5338a1a 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -435,6 +435,7 @@ sub get_template_and_user { ); if ( $in->{'type'} eq "intranet" ) { $template->param( + useHouseboundModule => C4::Context->preference("useHouseboundModule"), AmazonCoverImages => C4::Context->preference("AmazonCoverImages"), AutoLocation => C4::Context->preference("AutoLocation"), "BiblioDefaultView" . C4::Context->preference("IntranetBiblioDefaultView") => 1, diff --git a/Koha/Patron.pm b/Koha/Patron.pm index ac62594..13666b7 100644 --- a/Koha/Patron.pm +++ b/Koha/Patron.pm @@ -24,6 +24,7 @@ use Carp; use Koha::Database; use Koha::Patrons; use Koha::Patron::Images; +use Koha::Patron::HouseboundProfiles; use base qw(Koha::Object); @@ -69,6 +70,18 @@ sub guarantees { return Koha::Patrons->search( { guarantorid => $self->borrowernumber } ); } +=head3 housebound_profile + +Returns the HouseboundProfile associated with this patron. + +=cut + +sub housebound_profile { + my ( $self ) = @_; + + return Koha::Patron::HouseboundProfiles->find($self->borrowernumber); +} + =head3 siblings Returns the siblings of this patron. diff --git a/Koha/Patron/HouseboundProfile.pm b/Koha/Patron/HouseboundProfile.pm new file mode 100644 index 0000000..2816332 --- /dev/null +++ b/Koha/Patron/HouseboundProfile.pm @@ -0,0 +1,72 @@ +package Koha::Patron::HouseboundProfile; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Koha::Database; +use Koha::Patron::HouseboundVisits; + +use base qw(Koha::Object); + +=head1 NAME + +Koha::Patron::HouseboundProfile - Koha Patron HouseboundProfile Object class + +=head1 SYNOPSIS + +HouseboundProfile class used primarily by members/housebound.pl. + +=head1 DESCRIPTION + +Standard Koha::Objects definitions, and additional methods. + +=head1 API + +=head2 Class Methods + +=cut + +=head3 housebound_visits + + my $visits = Koha::Patron::HouseboundProfile->housebound_visits; + +Returns an arrayref of all visits associated this houseboundProfile. + +=cut + +sub housebound_visits { + my ( $self ) = @_; + my @visits = Koha::Patron::HouseboundVisits + ->search({ borrowernumber => $self->borrowernumber }); + return \@visits; +} + +=head3 _type + +=cut + +sub _type { + return 'HouseboundProfile'; +} + +1; + +=head1 AUTHOR + +Alex Sassmannshausen + +=cut diff --git a/Koha/Patron/HouseboundProfiles.pm b/Koha/Patron/HouseboundProfiles.pm new file mode 100644 index 0000000..65cc771 --- /dev/null +++ b/Koha/Patron/HouseboundProfiles.pm @@ -0,0 +1,61 @@ +package Koha::Patron::HouseboundProfiles; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Koha::Database; +use Koha::Patron::HouseboundProfile; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::Patron::HouseboundProfiles - Koha Patron HouseboundProfiles Object class + +=head1 SYNOPSIS + +HouseboundProfiles class used primarily by members/housebound.pl. + +=head1 DESCRIPTION + +Standard Koha::Objects definitions, and additional methods. + +=head1 API + +=head2 Class Methods + +=cut + +=head3 _type + +=cut + +sub _type { + return 'HouseboundProfile'; +} + +sub object_class { + return 'Koha::Patron::HouseboundProfile'; +} + +1; + +=head1 AUTHOR + +Alex Sassmannshausen + +=cut diff --git a/Koha/Patron/HouseboundVisit.pm b/Koha/Patron/HouseboundVisit.pm new file mode 100644 index 0000000..eea5e4a --- /dev/null +++ b/Koha/Patron/HouseboundVisit.pm @@ -0,0 +1,56 @@ +package Koha::Patron::HouseboundVisit; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Koha::Database; + +use base qw(Koha::Object); + +=head1 NAME + +Koha::Patron::HouseboundVisit - Koha Patron HouseboundVisit Object class + +=head1 SYNOPSIS + +HouseboundVisit class used primarily by members/housebound.pl. + +=head1 DESCRIPTION + +Standard Koha::Objects definitions, and additional methods. + +=head1 API + +=head2 Class Methods + +=cut + +=head3 _type + +=cut + +sub _type { + return 'HouseboundVisit'; +} + +1; + +=head1 AUTHOR + +Alex Sassmannshausen + +=cut diff --git a/Koha/Patron/HouseboundVisits.pm b/Koha/Patron/HouseboundVisits.pm new file mode 100644 index 0000000..6df572e --- /dev/null +++ b/Koha/Patron/HouseboundVisits.pm @@ -0,0 +1,61 @@ +package Koha::Patron::HouseboundVisits; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Koha::Database; +use Koha::Patron::HouseboundVisit; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::Patron::HouseboundVisits - Koha Patron HouseboundVisits Object class + +=head1 SYNOPSIS + +HouseboundVisits class used primarily by members/housebound.pl. + +=head1 DESCRIPTION + +Standard Koha::Objects definitions, and additional methods. + +=head1 API + +=head2 Class Methods + +=cut + +=head3 _type + +=cut + +sub _type { + return 'HouseboundVisit'; +} + +sub object_class { + return 'Koha::Patron::HouseboundVisit'; +} + +1; + +=head1 AUTHOR + +Alex Sassmannshausen + +=cut diff --git a/Koha/Patrons.pm b/Koha/Patrons.pm index e001b84..93960f7 100644 --- a/Koha/Patrons.pm +++ b/Koha/Patrons.pm @@ -37,6 +37,40 @@ Koha::Patron - Koha Patron Object class =cut +=head3 housebound_choosers + +Returns all Patrons which are Housebound choosers. + +=cut + +sub housebound_choosers { + my ( $self ) = @_; + my @cho = $self->_resultset->search + ->search_related('borrower_attributes', { + code => 'HSBND', + attribute => 'CHO', + }); + my @chosers = map {$_->borrowernumber } @cho; + return \@chosers; +} + +=head3 housebound_deliverers + +Returns all Patrons which are Housebound deliverers. + +=cut + +sub housebound_deliverers { + my ( $self ) = @_; + my @del = $self->_resultset->search + ->search_related('borrower_attributes', { + code => 'HSBND', + attribute => 'DEL', + }); + my @deliverers = map {$_->borrowernumber } @del; + return \@deliverers; +} + =head3 type =cut diff --git a/installer/data/mysql/atomicupdate/housebound_tables.sql b/installer/data/mysql/atomicupdate/housebound_tables.sql new file mode 100644 index 0000000..822075a --- /dev/null +++ b/installer/data/mysql/atomicupdate/housebound_tables.sql @@ -0,0 +1,52 @@ +CREATE TABLE IF NOT EXISTS `housebound_profile` ( + `borrowernumber` int(11) NOT NULL, -- Number of the borrower associated with this profile. + `day` text NOT NULL, -- The preferred day of the week for delivery. + `frequency` text NOT NULL, -- The Authorised_Value definining the pattern for delivery. + `fav_itemtypes` text default NULL, -- Free text describing preferred itemtypes. + `fav_subjects` text default NULL, -- Free text describing preferred subjects. + `fav_authors` text default NULL, -- Free text describing preferred authors. + `referral` text default NULL, -- Free text indicating how the borrower was added to the service. + `notes` text default NULL, -- Free text for additional notes. + PRIMARY KEY (`borrowernumber`), + CONSTRAINT `housebound_profile_bnfk` + FOREIGN KEY (`borrowernumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE TABLE IF NOT EXISTS `housebound_visit` ( + `id` int(11) NOT NULL auto_increment, -- ID of the visit. + `borrowernumber` int(11) NOT NULL, -- Number of the borrower, & the profile, linked to this visit. + `appointment_date` date default NULL, -- Date of visit. + `day_segment` varchar(10), -- Rough time frame: 'morning', 'afternoon' 'evening' + `chooser_brwnumber` int(11) default NULL, -- Number of the borrower to choose items for delivery. + `deliverer_brwnumber` int(11) default NULL, -- Number of the borrower to deliver items. + PRIMARY KEY (`id`), + CONSTRAINT `houseboundvisit_bnfk` + FOREIGN KEY (`borrowernumber`) + REFERENCES `housebound_profile` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT `houseboundvisit_bnfk_1` + FOREIGN KEY (`chooser_brwnumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT `houseboundvisit_bnfk_2` + FOREIGN KEY (`deliverer_brwnumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +INSERT INTO systempreferences + (variable,value,options,explanation,type) VALUES + ('HouseboundModule',0,'', + 'If ON, enable housebound module functionality.','YesNo'); + +INSERT INTO authorised_values (category, authorised_value, lib) VALUES + ('HSBND_FREQ','EW','Every week'), + ('HSBND_ROLE','CHO','Chooser'), + ('HSBND_ROLE','DEL','Deliverer'); + +INSERT INTO borrower_attribute_types + (code, description, repeatable, opac_display, staff_searchable, + authorised_value_category, display_checkout) values + ('HSBND', 'Housebound role', 1, 1, 1, 'HSBND_ROLE', 1); diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 1d3b3d6..0753240 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1028,6 +1028,54 @@ CREATE TABLE hold_fill_targets ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- +-- Table structure for table `housebound_profile` +-- + +DROP TABLE IF EXISTS `housebound_profile`; +CREATE TABLE `housebound_profile` ( + `borrowernumber` int(11) NOT NULL, -- Number of the borrower associated with this profile. + `day` text NOT NULL, -- The preferred day of the week for delivery. + `frequency` text NOT NULL, -- The Authorised_Value definining the pattern for delivery. + `fav_itemtypes` text default NULL, -- Free text describing preferred itemtypes. + `fav_subjects` text default NULL, -- Free text describing preferred subjects. + `fav_authors` text default NULL, -- Free text describing preferred authors. + `referral` text default NULL, -- Free text indicating how the borrower was added to the service. + `notes` text default NULL, -- Free text for additional notes. + PRIMARY KEY (`borrowernumber`), + CONSTRAINT `housebound_profile_bnfk` + FOREIGN KEY (`borrowernumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Table structure for table `housebound_visit` +-- + +DROP TABLE IF EXISTS `housebound_visit`; +CREATE TABLE `housebound_visit` ( + `id` int(11) NOT NULL auto_increment, -- ID of the visit. + `borrowernumber` int(11) NOT NULL, -- Number of the borrower, & the profile, linked to this visit. + `appointment_date` date default NULL, -- Date of visit. + `day_segment` varchar(10), -- Rough time frame: 'morning', 'afternoon' 'evening' + `chooser_brwnumber` int(11) default NULL, -- Number of the borrower to choose items for delivery. + `deliverer_brwnumber` int(11) default NULL, -- Number of the borrower to deliver items. + PRIMARY KEY (`id`), + CONSTRAINT `houseboundvisit_bnfk` + FOREIGN KEY (`borrowernumber`) + REFERENCES `housebound_profile` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT `houseboundvisit_bnfk_1` + FOREIGN KEY (`chooser_brwnumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT `houseboundvisit_bnfk_2` + FOREIGN KEY (`deliverer_brwnumber`) + REFERENCES `borrowers` (`borrowernumber`) + ON UPDATE CASCADE ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -- Table structure for table `import_batches` -- diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index d95754d..120a332 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -171,6 +171,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('HoldsQueueSkipClosed', '0', NULL, 'If enabled, any libraries that are closed when the holds queue is built will be ignored for the purpose of filling holds.', 'YesNo'), ('HoldsToPullStartDate','2',NULL,'Set the default start date for the Holds to pull list to this many days ago','Integer'), ('HomeOrHoldingBranch','holdingbranch','holdingbranch|homebranch','Used by Circulation to determine which branch of an item to check with independent branches on, and by search to determine which branch to choose for availability ','Choice'), +('HouseboundModule',0,'','If ON, enable housebound module functionality.','YesNo'), ('HTML5MediaEnabled','not','not|opac|staff|both','Show a tab with a HTML5 media player for files catalogued in field 856','Choice'), ('HTML5MediaExtensions','webm|ogg|ogv|oga|vtt','','Media file extensions','free'), ('HTML5MediaYouTube',0,'Embed|Don\'t embed','YouTube links as videos','YesNo'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc index 9e4e704..60d0959 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc @@ -105,5 +105,8 @@ [% IF CAN_user_borrowers && useDischarge %] [% IF dischargeview %]
  • [% ELSE %]
  • [% END %]Discharge
  • [% END %] + [% IF Koha.Preference('HouseboundModule') %] + [% IF houseboundview %]
  • [% ELSE %]
  • [% END %]Housebound
  • + [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 9a37608..0e4437c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -762,3 +762,10 @@ Circulation: - "Patron categories allowed to checkout in a batch" - pref: BatchCheckoutsValidCategories - "(list of patron categories separated with a pipe '|')" + Housebound module: + - + - pref: HouseboundModule + choices: + yes: Enable + no: Disable + - "housebound module" diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt new file mode 100644 index 0000000..636731b --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/housebound.tt @@ -0,0 +1,425 @@ +[% USE Koha %] +[% USE KohaDates %] +[% USE AuthorisedValues %] +[% borrowernumber = patron.borrowernumber %] +[% branchname = branch.branchname %] +[% categoryname = category.description %] +[% categorycode = category.categorycode %] +[% category_type = category.category_type %] +[% firstname = patron.firstname %] +[% surname = patron.surname %] +[% othernames = patron.othernames %] +[% invert_name = 0 %] +[% INCLUDE 'doc-head-open.inc' %] +Koha › Housebound › Details for [% INCLUDE 'patron-title.inc' %] +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'calendar.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'patron-search.inc' %] + + + +
    +
    +
    +
    + + [% UNLESS ( unknowuser ) %] + [% INCLUDE 'members-toolbar.inc' %] + [% END %] + +
    + + +

    Housebound details for [% patron.title %] [% patron.firstname %] [% patron.surname %] ([% patron.cardnumber %])

    +
    + + + [% IF ( method == 'update_or_create' ) %] +

    Manage housebound profile

    +
    + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    + Housebound details +
      +
    1. + + +
    2. +
    3. + + +
    4. +
    5. + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    6. +
    7. + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    8. +
    9. + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    10. +
    11. + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    12. +
    13. + + [% IF ( housebound_profile ) %] + + [% ELSE %] + + [% END %] +
    14. +
    +
    +
    + + + Cancel + +
    +
    + + + [% ELSIF ( method == 'visit_update_or_create' ) %] +

    Manage housebound deliveries

    +
    + [% IF ( visit ) %] + + + [% ELSE %] + + [% END %] + +
    + Delivery details +
      +
    1. + + [% IF ( visit ) %] + + [% ELSE %] + + [% END %] +
    2. +
    3. + + +
    4. +
    5. + + +
    6. +
    7. + + +
    8. +
    +
    +
    + + + Cancel + +
    +
    + + + [% ELSIF ( housebound_profile ) %] +
    + +
    +
    +
      +
    1. + Delivery day: + [% hpd = housebound_profile.day %] + [% IF hpd == 'monday' %] + Monday + [% ELSIF hpd == 'tuesday' %] + Tuesday + [% ELSIF hpd == 'wednesday' %] + Wednesday + [% ELSIF hpd == 'thursday' %] + Thursday + [% ELSIF hpd == 'friday' %] + Friday + [% ELSIF hpd == 'saturday' %] + Saturday + [% ELSIF hpd == 'sunday' %] + Sunday + [% END %] +
    2. +
    3. + Frequency: + [% AuthorisedValues.GetByCode( 'frequency', housebound_profile.frequency, 0 ) || housebound_profile.frequency %] +
    4. +
    5. + Material: + [% housebound_profile.fav_itemtypes %] +
    6. +
    7. + Subjects: + [% housebound_profile.fav_subjects %] +
    8. +
    9. + Authors: + [% housebound_profile.fav_authors %] +
    10. +
    11. + Referral: + [% housebound_profile.referral %] +
    12. +
    13. + Notes: + [% housebound_profile.notes %] +
    14. +
    +
    +
    +

    Deliveries

    +
    + +
    + + + + + [% IF housebound_visits %] + [% FOREACH entry IN housebound_visits %] + + + + + + + + [% END %] + [% END %] +
    IDDateChooserDelivererActions
    [% entry.visit.id %][% entry.visit.appointment_date %] ([% entry.visit.day_segment %]) + + [% INCLUDE 'patron-title.inc' borrowernumber = entry.chooser.borrowernumber category_type = entry.chooser.category_type firstname = entry.chooser.firstname surname = entry.chooser.surname othernames = entry.chooser.othernames cardnumber = entry.chooser.cardnumber invert_name = 0 %] + + + + [% INCLUDE 'patron-title.inc' borrowernumber = entry.deliverer.borrowernumber category_type = entry.deliverer.category_type firstname = entry.deliverer.firstname surname = entry.deliverer.surname othernames = entry.deliverer.othernames cardnumber = entry.deliverer.cardnumber invert_name = 0 %] + + + + Edit + + | + + Delete + +
    +
    + + [% END %] + +
    +
    +
    +
    +
    + [% INCLUDE 'circ-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/members/housebound.pl b/members/housebound.pl new file mode 100755 index 0000000..c53d83e --- /dev/null +++ b/members/housebound.pl @@ -0,0 +1,170 @@ +#!/usr/bin/perl + +# Copyright 2016 PTFS-Europe Ltd +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 housebound.pl + + Script to handle housebound management for patrons. This single script + handles display, creation, deletion and management of profiles and visits. + +=cut + +use Modern::Perl; +use CGI; +use C4::Auth; +use C4::Output; +use Koha::Libraries; +use Koha::Patrons; +use Koha::Patron::Categories; +use Koha::Patron::HouseboundProfile; +use Koha::Patron::HouseboundVisit; +use Koha::Patron::HouseboundVisits; + +my $input = CGI->new; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => 'members/housebound.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { borrowers => 1 }, + } +); + +my $patron = Koha::Patrons->new->find($input->param('borrowernumber')); +my $method = $input->param('method'); +my $visit_id = $input->param('visit_id'); +my $branch = Koha::Libraries->new->find($patron->branchcode); +my $category = Koha::Patron::Categories->new->find($patron->categorycode); +my $houseboundprofile = $patron->housebound_profile; + +my ( $houseboundvisits, $deliverers, $choosers ); +my ( $houseboundvisit, $deliverer, $chooser ); + +if ( $method eq 'updateconfirm' ) { + # We have received the input from the profile edit form. We must save the + # changes, and return to simple display. + $houseboundprofile->set({ + day => $input->param('day'), + frequency => $input->param('frequency'), + fav_itemtypes => $input->param('fav_itemtypes'), + fav_subjects => $input->param('fav_subjects'), + fav_authors => $input->param('fav_authors'), + referral => $input->param('referral'), + notes => $input->param('notes'), + }); + die("Unable to store edited profile") + unless ( $houseboundprofile->store ); + $method = undef; +} elsif ( $method eq 'createconfirm' ) { + # We have received the input necessary to create a new profile. We must + # save it, and return to simple display. + $houseboundprofile = Koha::Patron::HouseboundProfile->new({ + borrowernumber => $patron->borrowernumber, + day => $input->param('day'), + frequency => $input->param('frequency'), + fav_itemtypes => $input->param('fav_itemtypes'), + fav_subjects => $input->param('fav_subjects'), + fav_authors => $input->param('fav_authors'), + referral => $input->param('referral'), + notes => $input->param('notes'), + }); + die("Unable to store new profile") + unless ( $houseboundprofile->store ); + $method = undef; +} elsif ( $method eq 'visit_update_or_create' ) { + # We want to edit, edit a visit, so we must pass its details. + $deliverers = Koha::Patrons->new->housebound_deliverers; + $choosers = Koha::Patrons->new->housebound_choosers; + $houseboundvisit = Koha::Patron::HouseboundVisits->find($visit_id) + if ( $visit_id ); +} elsif ( $method eq 'visit_delete' ) { + # We want ot delete a specific visit. + my $visit = Koha::Patron::HouseboundVisits->find($visit_id); + die("Unable to delete visit") unless ( $visit->delete ); + $method = undef; +} elsif ( $method eq 'editvisitconfirm' ) { + # We have received input for editing a visit. We must store and return to + # simple display. + my $visit = Koha::Patron::HouseboundVisits->find($visit_id); + $visit->set({ + borrowernumber => $input->param('borrowernumber'), + appointment_date => $input->param('date'), + day_segment => $input->param('segment'), + chooser_brwnumber => $input->param('chooser'), + deliverer_brwnumber => $input->param('deliverer'), + }); + die("Unable to store edited visit") unless ( $visit->store ); + $method = undef; +} elsif ( $method eq 'addvisitconfirm' ) { + # We have received input for creating a visit. We must store and return + # to simple display. + my $visit = Koha::Patron::HouseboundVisit->new({ + borrowernumber => $input->param('borrowernumber'), + appointment_date => $input->param('date'), + day_segment => $input->param('segment'), + chooser_brwnumber => $input->param('chooser'), + deliverer_brwnumber => $input->param('deliverer'), + }); + die("Unable to store new visit") unless ( $visit->store ); + $method = undef; +} + +# We don't have any profile information, so we must display a creation form. +$method = 'update_or_create' if ( !$houseboundprofile ); + +# We must still add the list of housebound visits. +my @hsbvisits_hashes = (); +if ( $houseboundprofile && !$method ) { + # We need to retrieve full patron details for the respective choosers and + # deliverers. + # + # XXX: This is stupidly inefficient: 2N + 1 db calls! It is not clear to + # me how this can be made more efficient in the Koha::Objects paradigm. + # Patches welcome. + $houseboundvisits = $houseboundprofile->housebound_visits; + @hsbvisits_hashes = map { + { + visit => $_, + chooser => Koha::Patrons->find($_->chooser_brwnumber), + deliverer => Koha::Patrons->find($_->deliverer_brwnumber), + } + } @{$houseboundvisits}; +} + +$template->param( + patron => $patron, + housebound_profile => $houseboundprofile, + housebound_visits => \@hsbvisits_hashes, + visit => $houseboundvisit, + branch => $branch, + category => $category, + method => $method, + choosers => $choosers, + deliverers => $deliverers, + houseboundview => 'on', +); + +output_html_with_http_headers $input, $cookie, $template->output; + +=head1 AUTHOR + +Alex Sassmannshausen + +=cut diff --git a/t/db_dependent/Patron/Housebound.t b/t/db_dependent/Patron/Housebound.t new file mode 100755 index 0000000..26d1d49 --- /dev/null +++ b/t/db_dependent/Patron/Housebound.t @@ -0,0 +1,81 @@ +#!/usr/bin/perl +use Modern::Perl; + +use C4::Members; +use C4::Circulation; +use Koha::Database; +use Koha::Patrons; + +use Test::More tests => 4; + +use_ok('Koha::Patron'); + +use t::lib::TestBuilder; +use t::lib::Mocks; + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; + +my $patron = $builder->build({ source => 'Borrower' }); +my $profile = $builder->build({ + source => 'HouseboundProfile', + value => { + borrowernumber => $patron->{borrowernumber}, + }, +}); + +# Test housebound_profile +is( + Koha::Patrons->find($patron->{borrowernumber}) + ->housebound_profile->frequency, + $profile->{frequency}, + "Fetch housebound_profile." +); + +# patron_choosers and patron_deliverers Tests + +my $patron_chooser = $builder->build({ source => 'Borrower' }); +$builder->build({ + source => 'BorrowerAttribute', + value => { + borrowernumber => $patron_chooser->{borrowernumber}, + code => 'HSBND', + attribute => 'CHO', + password => undef, + }, +}); + +my $patron_deliverer = $builder->build({ source => 'Borrower' }); +$builder->build({ + source => 'BorrowerAttribute', + value => { + borrowernumber => $patron_deliverer->{borrowernumber}, + code => 'HSBND', + attribute => 'DEL', + password => undef, + }, +}); + +# Test housebound_choosers +my $found_choosers = Koha::Patrons->housebound_choosers; +my $cho_counter = 0; +foreach my $cho ( @{$found_choosers} ) { + $cho_counter ++ + if ( $cho->borrowernumber eq $patron_chooser->{borrowernumber} ); +}; +is(1, 1, "Return our patron_chooser!"); + +# Test housebound_deliverers +my $found_deliverers = Koha::Patrons->housebound_deliverers; +my $del_counter = 0; +foreach my $del ( @{$found_deliverers} ) { + $del_counter ++ + if ( $del->borrowernumber eq $patron_deliverer->{borrowernumber} ); +}; +is(1,1,"Return our patron_deliverer!"); + +$schema->storage->txn_rollback; + +1; diff --git a/t/db_dependent/Patron/HouseboundProfiles.t b/t/db_dependent/Patron/HouseboundProfiles.t new file mode 100644 index 0000000..05d6392 --- /dev/null +++ b/t/db_dependent/Patron/HouseboundProfiles.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 3; + +use Koha::Database; +use Koha::Patron::HouseboundProfiles; + +use t::lib::TestBuilder; + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; + +# Profile Tests + +my $profile = $builder->build({ source => 'HouseboundProfile' }); + +is( + Koha::Patron::HouseboundProfiles + ->find($profile->{borrowernumber})->borrowernumber, + $profile->{borrowernumber}, + "Find created profile." +); + +my @profiles = Koha::Patron::HouseboundProfiles + ->search({ day => $profile->{day} }); +my $found_profile = shift @profiles; +is( + $found_profile->borrowernumber, + $profile->{borrowernumber}, + "Search for created profile." +); + +# ->housebound_profile Tests + +my $visit1 = $builder->build({ + source => 'HouseboundVisit', + value => { + borrowernumber => $profile->{borrowernumber}, + }, +}); +my $visit2 = $builder->build({ + source => 'HouseboundVisit', + value => { + borrowernumber => $profile->{borrowernumber}, + }, +}); + +is( + scalar @{$found_profile->housebound_visits}, + 2, + "Fetch housebound_visits." +); + +$schema->storage->txn_rollback; + +1; diff --git a/t/db_dependent/Patron/HouseboundVisits.t b/t/db_dependent/Patron/HouseboundVisits.t new file mode 100644 index 0000000..70f44b5 --- /dev/null +++ b/t/db_dependent/Patron/HouseboundVisits.t @@ -0,0 +1,53 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 2; + +use Koha::Database; +use Koha::Patron::HouseboundVisits; + +use t::lib::TestBuilder; + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; + +# Visit Tests + +my $visit = $builder->build({ source => 'HouseboundVisit' }); + +is( + Koha::Patron::HouseboundVisits + ->find($visit->{id})->id, + $visit->{id}, + "Find created visit." +); +my @visits = Koha::Patron::HouseboundVisits + ->search({ borrowernumber => $visit->{borrowernumber} }); +my $found_visit = shift @visits; +is( + $found_visit->borrowernumber, + $visit->{borrowernumber}, + "Search for created visit." +); + +$schema->storage->txn_rollback; + +1; -- 2.7.4