centos_like: install_centos_rpms install_yaz install_cpan_marc install install_centos_perl create_ld_local install_cpan_safe install_cpan_force
fedora14: install_fedora_rpms install_cpan install_cpan_fedora install_cpan_marc install_js_sm install_cpan_force
+fedora15: fedora14
debian-squeeze: squeeze generic_debian
squeeze: install_pgsql_client_debs_90 install_extra_debs_squeeze
sub mark_item_missing_pieces {
my( $self, $conn, $auth, $copy_id, $args ) = @_;
### FIXME: We're starting a transaction here, but we're doing a lot of things outside of the transaction
- my $e = new_editor(authtoken=>$auth, xact =>1);
- return $e->die_event unless $e->checkauth;
+ ### FIXME: Even better, we're going to use two transactions, the first to affect pertinent holds before checkout can
+
+ my $e2 = new_editor(authtoken=>$auth, xact =>1);
+ return $e2->die_event unless $e2->checkauth;
$args ||= {};
- my $copy = $e->retrieve_asset_copy([
+ my $copy = $e2->retrieve_asset_copy([
$copy_id,
{flesh => 1, flesh_fields => {'acp' => ['call_number']}}])
- or return $e->die_event;
+ or return $e2->die_event;
my $owning_lib =
($copy->call_number->id == OILS_PRECAT_CALL_NUMBER) ?
$copy->circ_lib : $copy->call_number->owning_lib;
- return $e->die_event unless $e->allowed('MARK_ITEM_MISSING_PIECES', $owning_lib);
+ return $e2->die_event unless $e2->allowed('MARK_ITEM_MISSING_PIECES', $owning_lib);
#### grab the last circulation
- my $circ = $e->search_action_circulation([
+ my $circ = $e2->search_action_circulation([
{ target_copy => $copy->id},
{ limit => 1,
order_by => {circ => "xact_start DESC"}
}
])->[0];
- if ($circ) {
- if (! $circ->checkin_time) { # if circ active, attempt renew
- my ($res) = $self->method_lookup('open-ils.circ.renew')->run($e->authtoken,{'copy_id'=>$circ->target_copy});
- if (ref $res ne 'ARRAY') { $res = [ $res ]; }
- if ( $res->[0]->{textcode} eq 'SUCCESS' ) {
- $circ = $res->[0]->{payload}{'circ'};
- $circ->target_copy( $copy->id );
- $logger->info('open-ils.circ.mark_item_missing_pieces: successful renewal');
- } else {
- $logger->info('open-ils.circ.mark_item_missing_pieces: non-successful renewal');
- }
- } else {
+ if (!$circ) {
+ $logger->info('open-ils.circ.mark_item_missing_pieces: no previous checkout');
+ $e2->rollback;
+ return OpenILS::Event->new('ACTION_CIRCULATION_NOT_FOUND',{'copy'=>$copy});
+ }
- my $co_params = {
- 'copy_id'=>$circ->target_copy,
- 'patron_id'=>$circ->usr,
- 'skip_deposit_fee'=>1,
- 'skip_rental_fee'=>1
- };
+ my $holds = $e2->search_action_hold_request(
+ {
+ current_copy => $copy->id,
+ fulfillment_time => undef,
+ cancel_time => undef,
+ }
+ );
- if ($U->ou_ancestor_setting_value($e->requestor->ws_ou, 'circ.block_renews_for_holds')) {
+ $logger->debug("resetting holds that target the marked copy");
+ OpenILS::Application::Circ::Holds->_reset_hold($e2->requestor, $_) for @$holds;
- my ($hold, undef, $retarget) = $holdcode->find_nearest_permitted_hold(
- $e, $copy, $e->requestor, 1 );
+
+ if (! $e2->commit) {
+ return $e2->die_event;
+ }
- if ($hold) { # needed for hold? then due now
+ my $e = new_editor(authtoken=>$auth, xact =>1);
+ return $e->die_event unless $e->checkauth;
- $logger->info('open-ils.circ.mark_item_missing_pieces: item needed for hold, shortening due date');
- my $due_date = DateTime->now(time_zone => 'local');
- $co_params->{'due_date'} = cleanse_ISO8601( $due_date->strftime('%FT%T%z') );
- } else {
- $logger->info('open-ils.circ.mark_item_missing_pieces: item not needed for hold');
- }
- }
+ if (! $circ->checkin_time) { # if circ active, attempt renew
+ my ($res) = $self->method_lookup('open-ils.circ.renew')->run($e->authtoken,{'copy_id'=>$circ->target_copy});
+ if (ref $res ne 'ARRAY') { $res = [ $res ]; }
+ if ( $res->[0]->{textcode} eq 'SUCCESS' ) {
+ $circ = $res->[0]->{payload}{'circ'};
+ $circ->target_copy( $copy->id );
+ $logger->info('open-ils.circ.mark_item_missing_pieces: successful renewal');
+ } else {
+ $logger->info('open-ils.circ.mark_item_missing_pieces: non-successful renewal');
+ }
+ } else {
+
+ my $co_params = {
+ 'copy_id'=>$circ->target_copy,
+ 'patron_id'=>$circ->usr,
+ 'skip_deposit_fee'=>1,
+ 'skip_rental_fee'=>1
+ };
+
+ if ($U->ou_ancestor_setting_value($e->requestor->ws_ou, 'circ.block_renews_for_holds')) {
+
+ my ($hold, undef, $retarget) = $holdcode->find_nearest_permitted_hold(
+ $e, $copy, $e->requestor, 1 );
- my ($res) = $self->method_lookup('open-ils.circ.checkout.full.override')->run($e->authtoken,$co_params);
- if (ref $res ne 'ARRAY') { $res = [ $res ]; }
- if ( $res->[0]->{textcode} eq 'SUCCESS' ) {
- $logger->info('open-ils.circ.mark_item_missing_pieces: successful checkout');
- $circ = $res->[0]->{payload}{'circ'};
+ if ($hold) { # needed for hold? then due now
+
+ $logger->info('open-ils.circ.mark_item_missing_pieces: item needed for hold, shortening due date');
+ my $due_date = DateTime->now(time_zone => 'local');
+ $co_params->{'due_date'} = cleanse_ISO8601( $due_date->strftime('%FT%T%z') );
} else {
- $logger->info('open-ils.circ.mark_item_missing_pieces: non-successful checkout');
- $e->rollback;
- return $res;
+ $logger->info('open-ils.circ.mark_item_missing_pieces: item not needed for hold');
}
}
- } else {
- $logger->info('open-ils.circ.mark_item_missing_pieces: no previous checkout');
- $e->rollback;
- return OpenILS::Event->new('ACTION_CIRCULATION_NOT_FOUND',{'copy'=>$copy});
+
+ my ($res) = $self->method_lookup('open-ils.circ.checkout.full.override')->run($e->authtoken,$co_params);
+ if (ref $res ne 'ARRAY') { $res = [ $res ]; }
+ if ( $res->[0]->{textcode} eq 'SUCCESS' ) {
+ $logger->info('open-ils.circ.mark_item_missing_pieces: successful checkout');
+ $circ = $res->[0]->{payload}{'circ'};
+ } else {
+ $logger->info('open-ils.circ.mark_item_missing_pieces: non-successful checkout');
+ $e->rollback;
+ return $res;
+ }
}
### Update the item status
$e->update_asset_copy($copy) or return $e->die_event;
- my $holds = $e->search_action_hold_request(
- {
- current_copy => $copy->id,
- fulfillment_time => undef,
- cancel_time => undef,
- }
- );
-
- $logger->debug("resetting holds that target the marked copy");
- OpenILS::Application::Circ::Holds->_reset_hold($e->requestor, $_) for @$holds;
-
if ($e->commit) {
my $ses = OpenSRF::AppSession->create('open-ils.trigger');
$circulator->editor->rollback;
} else {
+
$circulator->editor->commit;
- }
- $circulator->script_runner->cleanup if $circulator->script_runner;
+ if ($circulator->generate_lost_overdue) {
+ # Generating additional overdue billings has to happen after the
+ # main commit and before the final respond() so the caller can
+ # receive the latest transaction summary.
+ my $evt = $circulator->generate_lost_overdue_fines;
+ $circulator->bail_on_events($evt) if $evt;
+ }
+ }
$conn->respond_complete(circ_events($circulator));
- unless($circulator->bail_out) {
- $circulator->do_hold_notify($circulator->notify_hold)
- if $circulator->notify_hold;
- $circulator->retarget_holds if $circulator->retarget;
- $circulator->append_reading_list;
- $circulator->make_trigger_events;
- }
+ $circulator->script_runner->cleanup if $circulator->script_runner;
+
+ return undef if $circulator->bail_out;
+
+ $circulator->do_hold_notify($circulator->notify_hold)
+ if $circulator->notify_hold;
+ $circulator->retarget_holds if $circulator->retarget;
+ $circulator->append_reading_list;
+ $circulator->make_trigger_events;
+
+ return undef;
}
sub circ_events {
skip_deposit_fee
skip_rental_fee
use_booking
+ generate_lost_overdue
/;
$circ_lib, OILS_SETTING_VOID_LOST_PROCESS_FEE_ON_CHECKIN, $self->editor) || 0;
my $restore_od = $U->ou_ancestor_setting_value(
$circ_lib, OILS_SETTING_RESTORE_OVERDUE_ON_LOST_RETURN, $self->editor) || 0;
+ $self->generate_lost_overdue(1) if $U->ou_ancestor_setting_value(
+ $circ_lib, OILS_SETTING_GENERATE_OVERDUE_ON_LOST_RETURN, $self->editor);
$self->checkin_handle_lost_now_found(3) if $void_lost;
$self->checkin_handle_lost_now_found(4) if $void_lost_fee;
- $self->checkin_handle_lost_now_found_restore_od() if $restore_od && ! $self->void_overdues;
+ $self->checkin_handle_lost_now_found_restore_od($circ_lib) if $restore_od && ! $self->void_overdues;
}
$self->copy->status($U->copy_status(OILS_COPY_STATUS_RESHELVING));
sub checkin_handle_lost_now_found_restore_od {
my $self = shift;
+ my $circ_lib = shift;
# ------------------------------------------------------------------
# restore those overdue charges voided when item was set to lost
}
}
+# ------------------------------------------------------------------
+# Lost-then-found item checked in. This sub generates new overdue
+# fines, beyond the point of any existing and possibly voided
+# overdue fines, up to the point of final checkin time (or max fine
+# amount).
+# ------------------------------------------------------------------
+sub generate_lost_overdue_fines {
+ my $self = shift;
+ my $circ = $self->circ;
+ my $e = $self->editor;
+
+ # Re-open the transaction so the fine generator can see it
+ if($circ->xact_finish or $circ->stop_fines) {
+ $e->xact_begin;
+ $circ->clear_xact_finish;
+ $circ->clear_stop_fines;
+ $circ->clear_stop_fines_time;
+ $e->update_action_circulation($circ) or return $e->die_event;
+ $e->xact_commit;
+ }
+
+ $e->xact_begin; # generate_fines expects an in-xact editor
+ $self->generate_fines;
+ $circ = $self->circ; # generate fines re-fetches the circ
+
+ my $update = 0;
+
+ # Re-close the transaction if no money is owed
+ my ($obt) = $U->fetch_mbts($circ->id, $e);
+ if ($obt and $obt->balance_owed == 0) {
+ $circ->xact_finish('now');
+ $update = 1;
+ }
+
+ # Set stop fines if the fine generator didn't have to
+ unless($circ->stop_fines) {
+ $circ->stop_fines(OILS_STOP_FINES_CHECKIN);
+ $circ->stop_fines_time('now');
+ $update = 1;
+ }
+
+ # update the event data sent to the caller within the transaction
+ $self->checkin_flesh_events;
+
+ if ($update) {
+ $e->update_action_circulation($circ) or return $e->die_event;
+ $e->commit;
+ } else {
+ $e->rollback;
+ }
+
+ return undef;
+}
+
1;
$e->commit;
+ _reset_hold($self, $e->requestor, $_) for @$holds;
+
return 1;
}
econst OILS_SETTING_RESTORE_OVERDUE_ON_LOST_RETURN => 'circ.restore_overdue_on_lost_return';
econst OILS_SETTING_LOST_IMMEDIATELY_AVAILABLE => 'circ.lost_immediately_available';
econst OILS_SETTING_BLOCK_HOLD_FOR_EXPIRED_PATRON => 'circ.holds.expired_patron_block';
+econst OILS_SETTING_GENERATE_OVERDUE_ON_LOST_RETURN => 'circ.lost.generate_overdue_on_checkin';
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 ('0566', :eg_version); -- miker/berick
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0567', :eg_version); -- miker/berick
CREATE TABLE config.bib_source (
id SERIAL PRIMARY KEY,
(38, 'bib_rec.bib_record.simple_record');
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+ 'circ.lost.generate_overdue_on_checkin',
+ oils_i18n_gettext(
+ 'circ.lost.generate_overdue_on_checkin',
+ 'Circ: Lost Checkin Generates New Overdues',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.lost.generate_overdue_on_checkin',
+ 'Enabling this setting causes retroactive creation of not-yet-existing overdue fines on lost item checkin, up to the point of checkin time (or max fines is reached). This is different than "restore overdue on lost", because it only creates new overdue fines. Use both settings together to get the full complement of overdue fines for a lost item',
+ 'coust',
+ 'label'
+ ),
+ 'bool'
+);
--- /dev/null
+-- Evergreen DB patch XXXX.data.ou_setting_generate_overdue_on_lost.sql.sql
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('0567', :eg_version);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+ 'circ.lost.generate_overdue_on_checkin',
+ oils_i18n_gettext(
+ 'circ.lost.generate_overdue_on_checkin',
+ 'Circ: Lost Checkin Generates New Overdues',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.lost.generate_overdue_on_checkin',
+ 'Enabling this setting causes retroactive creation of not-yet-existing overdue fines on lost item checkin, up to the point of checkin time (or max fines is reached). This is different than "restore overdue on lost", because it only creates new overdue fines. Use both settings together to get the full complement of overdue fines for a lost item',
+ 'coust',
+ 'label'
+ ),
+ 'bool'
+);
+
+COMMIT;
var col_id = prefix + hint + '_' + my_field.name;
var dataobj = hint;
var datafield = my_field.name;
+ var fleshed_display_field;
if (column_extras) {
if (column_extras['*']) {
if (column_extras['*']['dataobj']) {
if (column_extras[col_id]['datafield']) {
datafield = column_extras[col_id]['datafield'];
}
+ if (column_extras[col_id]['fleshed_display_field']) {
+ fleshed_display_field = column_extras[col_id]['fleshed_display_field'];
+ }
}
}
var def = {
// my_field.datatype => bool float id int interval link money number org_unit text timestamp
if (my_field.datatype == 'link') {
def.render = function(my) {
- return typeof my[dataobj][datafield]() == 'object' ? my[dataobj][datafield]()[my_field.key]() : my[dataobj][datafield]();
+ // is the object fleshed?
+ return my[dataobj][datafield]() && typeof my[dataobj][datafield]() == 'object'
+ // yes, show the display field
+ ? my[dataobj][datafield]()[fleshed_display_field||my_field.key]()
+ // no, do we have its class in data.hash?
+ : ( typeof data.hash[ my[dataobj].Structure.field_map[datafield].class ] != 'undefined'
+ // yes, do we have this particular object cached?
+ ? ( data.hash[ my[dataobj].Structure.field_map[datafield].class ][ my[dataobj][datafield]() ]
+ // yes, show the display field
+ ? data.hash[ my[dataobj].Structure.field_map[datafield].class ][ my[dataobj][datafield]() ][
+ fleshed_display_field||my_field.key
+ ]()
+ // no, just show the raw value
+ : my[dataobj][datafield]()
+ )
+ // no, just show the raw value
+ : my[dataobj][datafield]()
+ );
}
} else {
def.render = function(my) { return my[dataobj][datafield](); }
'au_family_name' : { 'hidden' : false },
'au_first_given_name' : { 'hidden' : false },
'au_second_given_name' : { 'hidden' : false },
- 'au_dob' : { 'hidden' : false }
+ 'au_dob' : { 'hidden' : false },
+ 'au_profile' : { 'fleshed_display_field' : 'name' },
+ 'au_ident_type' : { 'fleshed_display_field' : 'name' },
+ 'au_ident_type2' : { 'fleshed_display_field' : 'name' },
+ 'au_net_access_level' : { 'fleshed_display_field' : 'name' }
}).concat(
obj.list.fm_columns('ac',{
'*' : { 'remove_virtual' : true, 'expanded_label' : true, 'hidden' : true },
README for Evergreen master
-========================
+===========================
Installing prerequisites:
-------------------------
* On Fedora 14, follow the http://yum.pgrpms.org/howtoyum.php[instructions
in the Yum HOWTO] to enable the PostgreSQL RPM Building Project yum
repository.
+ * Fedora 15 comes with PostgreSQL 9, so no additional steps are required.
+
-3. On Debian and Ubuntu, the easiest way to install the rest of the
+3. On Debian and Ubuntu, run `aptitude update` to retrieve the new packages
+ from the backports repository.
+4. On Debian and Ubuntu, the easiest way to install the rest of the
prerequisites for Evergreen is to use the Makefile.install prerequisite
installer.
-4. Issue the following commands as the root user to install prerequisites
+5. Issue the following commands as the root user to install prerequisites
using the Makefile.install prerequisite installer, substituting
- `debian-squeeze`, `fedora-14`, `ubuntu-lucid`, `centos`, or `rhel` for
- <osname> below:
+ `debian-squeeze`, `fedora15`, `fedora14`, `ubuntu-lucid`, `centos`, or
+ `rhel` for <osname> below:
+
[source, bash]
------------------------------------------------------------------------------
The `STAFF_CLIENT_STAMP_ID` variable stamps the server-side and client-side files
for the staff client to ensure that they match.
-Install Dojo Toolkit:
----------------------
-
-Evergreen uses the Dojo Toolkit to support its Web and staff client interfaces.
-
-Download the Dojo Toolkit (Dojo + Dijit + DojoX) from
-http://dojotoolkit.org/downloads
-
-Issue the following commands as the root user to fetch, extract, and copy the
-files into the correct directory, adjusting the version number to match the
-version of the Dojo Toolkit that you downloaded:
-
-[source, bash]
-------------------------------------------------------------------------------
-wget http://download.dojotoolkit.org/release-1.3.3/dojo-release-1.3.3.tar.gz
-tar -C /openils/var/web/js -xzf dojo-release-1.3.3.tar.gz
-cp -r /openils/var/web/js/dojo-release-1.3.3/* /openils/var/web/js/dojo/.
-------------------------------------------------------------------------------
-
Create the oils_web.xml configuration file:
-------------------------------------------
Many administration interfaces, such as acquisitions, bookings, and various
Configure the Apache Web server:
--------------------------------
-Use the example configuration files in `Open-ILS/examples/apache/` to configure
+1. Use the example configuration files in `Open-ILS/examples/apache/` to configure
your Web server for the Evergreen catalog, staff client, Web services, and
administration interfaces.
++
+.Debian and Ubuntu
+[source,bash]
+------------------------------------------------------------------------------
+cp Open-ILS/examples/apache/eg.conf /etc/apache2/sites-available/
+cp Open-ILS/examples/apache/eg_vhost.conf /etc/apache2/
+cp Open-ILS/examples/apache/startup.pl /etc/apache2/
+# Now set up SSL
+mkdir /etc/apache2/ssl
+cd /etc/apache2/ssl
+------------------------------------------------------------------------------
++
+.Fedora
+[source,bash]
+------------------------------------------------------------------------------
+cp Open-ILS/examples/apache/eg.conf /etc/httpd/sites-available/
+cp Open-ILS/examples/apache/eg_vhost.conf /etc/httpd/
+cp Open-ILS/examples/apache/startup.pl /etc/httpd/
+# Now set up SSL
+mkdir /etc/httpd/ssl
+cd /etc/httpd/ssl
+------------------------------------------------------------------------------
++
+2. Create an SSL key for the Apache server:
++
+[source,bash]
+------------------------------------------------------------------------------
+openssl req -new -x509 -days 365 -nodes -out server.crt -keyout server.key
+------------------------------------------------------------------------------
++
+The `openssl` command cuts a new SSL key for your Apache server. For a
+production server, you should purchase a signed SSL certificate, but you can
+just use a self-signed certificate and accept the warnings in the staff client
+and browser during testing and development
++
+3. Edit the `eg.conf` file that you copied into place.
+ a. Replace `Allow from 10.0.0.0/8` with `Allow from all` (to enable
+ access to the offline upload / execute interface from any workstation on
+ any network - note that you must secure this for a production instance)
+ b. Comment the line `Listen 443` as it conflicts with the same declaration
+ elsewhere in the Apache configuration files.
+4. Change the user for the Apache server.
+ * (Debian and Ubuntu): As the root user, edit `/etc/apache2/envvars`.
+ Change `export APACHE_RUN_USER=www-data` to
+ `export APACHE_RUN_USER=opensrf`.
+ * (Fedora): As the root user, edit `/etc/httpd/conf/httpd.conf`. Change
+ `User apache` to `User opensrf`.
+5. Configure Apache with performance settings appropriate for Evergreen:
+ * (Debian and Ubuntu): As the root user, edit `/etc/apache2/apache2.conf`:
+ * (Fedora): As the root user, edit `/etc/httpd/conf/httpd.conf`:
+ a. Change `KeepAliveTimeout` to `1`. Higher values reduce the chance of
+ a request timing out unexpectedly, but increase the risk of using up
+ all available Apache child processes.
+ b. 'Optional': Change `MaxKeepAliveRequests` to `100`
+ c. Update the prefork configuration section to suit your environment. The
+ following settings apply to a busy system:
++
+[source,bash]
+------------------------------------------------------------------------------
+<IfModule mpm_prefork_module>
+ StartServers 20
+ MinSpareServers 5
+ MaxSpareServers 15
+ MaxClients 150
+ MaxRequestsPerChild 10000
+</IfModule>
+------------------------------------------------------------------------------
++
+6. (Debian and Ubuntu): As the root user, enable the Evergreen site:
++
+[source,bash]
+------------------------------------------------------------------------------
+a2dissite default # OPTIONAL: disable the default site (the "It Works" page)
+a2ensite eg.conf
+------------------------------------------------------------------------------
Configure OpenSRF for the Evergreen application:
------------------------------------------------
-
There are a number of example OpenSRF configuration files in `/openils/conf/`
that you can use as a template for your Evergreen installation.
[source, bash]
------------------------------------------------------------------------------
wget http://download.dojotoolkit.org/release-1.3.3/dojo-release-1.3.3.tar.gz
-tar xzf dojo-release-1.3.3.tar.gz
-cp -r dojo-release-1.3.3/* /openils/var/web/js/dojo/.
+tar -C /openils/var/web/js -xzf dojo-release-1.3.3.tar.gz
+cp -r /openils/var/web/js/dojo-release-1.3.3/* /openils/var/web/js/dojo/.
------------------------------------------------------------------------------
Getting help: