sub naive_ts_string { strftime("%F %T", localtime(shift)); }
+sub naive_start_of_day { strftime("%F", localtime(shift)) . " 00:00:00"; }
# Return a list of bresv or an ilsevent on failure.
sub get_uncaptured_bresv_for_brsrc {
);
+sub get_captured_reservations {
+ my ($self, $client, $auth, $barcode, $which) = @_;
+
+ my $e = new_editor(xact => 1, authtoken => $auth);
+ return $e->die_event unless $e->checkauth;
+ return $e->die_event unless $e->allowed("VIEW_USER");
+ return $e->die_event unless $e->allowed("ADMIN_BOOKING_RESERVATION");
+
+ # fetch the patron for our uses in any case...
+ my $patron = $U->fetch_user_by_barcode($barcode);
+ return $patron if ref($patron) eq "HASH" and exists $patron->{"ilsevent"};
+
+ my $bresv_flesh = {
+ "flesh" => 1,
+ "flesh_fields" => {"bresv" => [
+ qw/target_resource_type current_resource/
+ ]}
+ };
+
+ my $dispatch = {
+ "patron" => sub {
+ return $patron;
+ },
+ "ready" => sub {
+ return $e->search_booking_reservation([
+ {
+ "usr" => $patron->id,
+ "capture_time" => {"!=" => undef},
+ "pickup_time" => undef,
+ "cancel_time" => undef
+ },
+ $bresv_flesh
+ ]) or $e->die_event;
+ },
+ "out" => sub {
+ return $e->search_booking_reservation([
+ {
+ "usr" => $patron->id,
+ "pickup_time" => {"!=" => undef},
+ "return_time" => undef,
+ "cancel_time" => undef
+ },
+ $bresv_flesh
+ ]) or $e->die_event;
+ },
+ "in" => sub {
+ return $e->search_booking_reservation([
+ {
+ "usr" => $patron->id,
+ "return_time" => {">=" => naive_start_of_day()},
+ "cancel_time" => undef
+ },
+ $bresv_flesh
+ ]) or $e->die_event;
+ }
+ };
+
+ my $result = {};
+ foreach (@$which) {
+ my $f = $dispatch->{$_};
+ if ($f) {
+ my $r = &{$f}();
+ return $r if (ref($r) eq "HASH" and exists $r->{"ilsevent"});
+ $result->{$_} = $r;
+ }
+ }
+
+ return $result;
+}
+__PACKAGE__->register_method(
+ method => "get_captured_reservations",
+ api_name => "open-ils.booking.reservations.get_captured",
+ argc => 3,
+ signature=> {
+ params => [
+ {type => "string", desc => "Authentication token"},
+ {type => "string", desc => "Patron barcode"},
+ {type => "array", desc => "Parts wanted (patron, ready, out, in?)"}
+ ],
+ return => { desc => "A hash of parts." } # XXX describe more fully
+ }
+);
+
+
+sub get_bresv_by_returnable_resource_barcode {
+ my ($self, $client, $auth, $barcode) = @_;
+
+ my $e = new_editor(xact => 1, authtoken => $auth);
+ return $e->die_event unless $e->checkauth;
+ return $e->die_event unless $e->allowed("VIEW_USER");
+ return $e->die_event unless $e->allowed("ADMIN_BOOKING_RESERVATION");
+
+ my $rows = $e->json_query({
+ "select" => {"bresv" => ["id"]},
+ "from" => {
+ "bresv" => {
+ "brsrc" => {"field" => "id", "fkey" => "current_resource"}
+ }
+ },
+ "where" => {
+ "+brsrc" => {"barcode" => $barcode},
+ "-and" => {
+ "pickup_time" => {"!=" => undef},
+ "cancel_time" => undef,
+ "return_time" => undef
+ }
+ }
+ }) or return $e->die_event;
+
+ if (@$rows < 1) {
+ return $rows;
+ } else {
+ # More than one result might be possible, but we don't want to return
+ # more than one at this time.
+ my $id = $rows->[0]->{"id"};
+ return $e->retrieve_booking_reservation([
+ $id, {
+ "flesh" => 2,
+ "flesh_fields" => {
+ "bresv" => [qw/usr target_resource_type current_resource/],
+ "au" => ["card"]
+ }
+ }
+ ]) or $e->die_event;
+ }
+}
+
+__PACKAGE__->register_method(
+ method => "get_bresv_by_returnable_resource_barcode",
+ api_name => "open-ils.booking.reservations.by_returnable_resource_barcode",
+ argc => 2,
+ signature=> {
+ params => [
+ {type => "string", desc => "Authentication token"},
+ {type => "string", desc => "Resource barcode"},
+ ],
+ return => { desc => "A fleshed bresv or an ilsevent on error" }
+ }
+);
+
+
1;
$circulator->do_checkout();
} elsif( $circulator->is_res_checkin ) {
- my ($reservation, $evt) = $U->fetch_booking_reservation($self->reservation);
- if ($evt) {
- $self->bail_on_events($evt);
- } else {
- $self->reservation( $reservation );
- $self->generate_fines(1);
- $circulator->do_reservation_return();
- $circulator->do_checkin();
- }
+ $circulator->do_reservation_return();
+ $circulator->do_checkin() if ($circulator->copy());
} elsif( $api =~ /checkin/ ) {
$circulator->do_checkin();
my $target_r = $reservation->target_resource;
my $current_r = $reservation->current_resource;
- $reservation->usr($usr->id) if $usr;
- $reservation->target_resource_type($target_rt->id) if $target_rt;
- $reservation->target_resource($target_r->id) if $target_r;
- $reservation->current_resource($current_r->id) if $current_r;
+ $reservation->usr($usr->id) if ref $usr;
+ $reservation->target_resource_type($target_rt->id) if ref $target_rt;
+ $reservation->target_resource($target_r->id) if ref $target_r;
+ $reservation->current_resource($current_r->id) if ref $current_r;
return $self->bail_on_events($self->editor->event)
unless $self->editor->update_booking_reservation($self->reservation);
return $self->bail_on_events($evt) if $evt;
$self->reservation( $reservation );
+ $self->generate_fines(1);
$self->reservation->return_time('now');
$self->update_reservation();
font-style: italic;
padding-right: 12px;
}
-h1.booking, h2.booking {
+h1.booking, h2.booking, h3.booking {
margin: 0;
padding-top: 0;
padding-bottom: 8px;
}
+h1.booking { font-size: 16pt; font-weight: bold; }
select#brsrc_list {
width: 90%;
}
margin-bottom: 4px; margin-top: 4px;
}
span#result_display { margin-left: 12px; }
+div#contains_misc_controls { text-align:right; }
+div#patron_info { font-size: 12pt; font-weight: bold; }
+div#no_ready_bresv, div#no_out_bresv, div#no_in_bresv {
+ font-style: italic;
+}
--- /dev/null
+{
+ 'NO_PATRON_BARCODE': "Please enter a patron barcode.",
+ 'RESERVATIONS_NO_RESPONSE':
+ "No response from server when asking for reservations.",
+ 'RESERVATIONS_ERROR':
+ "Error communicating with server (asking for reservations):",
+ 'PICKUP_NO_RESPONSE': "No response from server when attempting pickup.",
+ 'PICKUP_ERROR': "Error communicating with server (attempting pickup):",
+ 'RETURN_NO_RESPONSE': "No response from server when attempting return.",
+ 'RETURN_ERROR': "Error communicating with server (attempting return):",
+ 'RETURN_SUCCESS': "Return successful.",
+ 'SELECT_SOMETHING': "You have not selected any reservations.",
+ 'NO_SUCH_RETURNABLE_RESOURCE': "No such returnable resource.",
+ 'RETURNABLE_RESOURCE_ERROR': "Error looking up returnable resource:",
+ 'NOTICE_CHANGE_OF_PATRON':
+ "Note that the resource scanned was out on reservation to different\n" +
+ "patron than the last resource you scanned. If this is not\n" +
+ "expected, stop to examine outstanding reservations for your patron\n" +
+ "or on the resource.",
+
+ 'AUTO_h1': "Reservations Pickup",
+ 'AUTO_return_h1': "Reservations Return",
+ 'AUTO_patron_barcode': "Enter patron barcode:",
+ 'AUTO_barcode_type': "Return by barcode of",
+ 'AUTO_in_bresv': "Patron has returned these resources today:",
+ 'AUTO_ready_bresv': "Patron has these reservations ready for pickup:",
+ 'AUTO_out_bresv': "Patron currently has these reservations out:",
+ 'AUTO_no_ready_bresv':
+ "Patron has no reservations ready for pickup at this time.",
+ 'AUTO_no_out_bresv': "Patron has no more reservations out at this time.",
+ 'AUTO_no_in_bresv': "Patron has not returned any resources today.",
+ 'AUTO_patron': "Patron",
+ 'AUTO_resource': "Resource",
+ 'AUTO_ATTR_VALUE_go': "Go",
+ 'AUTO_ATTR_VALUE_reset': "Clear / New Patron",
+ 'AUTO_ATTR_VALUE_pickup': "Pick up",
+ 'AUTO_ATTR_VALUE_return': "Return"
+}
}
return s;
}
+function set_datagrid_empty_store(grid, flattener) {
+ grid.setStore(
+ new dojo.data.ItemFileReadStore(
+ {"data": flattener([])}
+ )
+ );
+}
--- /dev/null
+dojo.requireLocalization("openils.booking", "pickup_and_return");
+var localeStrings = dojo.i18n.getLocalization(
+ "openils.booking", "pickup_and_return"
+);
+var p;
+
+function my_init() {
+ p = new Populator({
+ "ready": ready_bresv,
+ "out": out_bresv,
+ "patron": document.getElementById("patron_info")
+ }, document.getElementById("patron_barcode"));
+ init_auto_l10n(document.getElementById("auto_l10n_start_here"));
+
+ /* The following would be for pass-in from the patron interface, but
+ * doesn't yet work/is cheap and needs improved anyway. */
+// try {
+// document.getElementById("patron_barcode").value =
+// xulG.bresv_interface_opts.patron_barcode;
+// document.getElementById("lookup").submit();
+// } catch (E) {
+// ;
+// }
+}
--- /dev/null
+/* This module depends on common.js being loaded, as well as the
+ * localization (Dojo/nls) for pickup and return . */
+
+dojo.require("dojo.data.ItemFileReadStore");
+
+function Populator(widgets, primary_input) {
+ this.widgets = widgets;
+
+ this.all = [];
+ for (var k in widgets) this.all.push(k);
+
+ if (primary_input) this.primary_input = primary_input;
+
+ this.prepare_cache();
+ this.prepare_empty_stores();
+ this.reset();
+}
+Populator.prototype.prepare_cache = function(data) {
+ this.cache = {};
+ for (var k in this.all) this.cache[this.all[k]] = {};
+};
+Populator.prototype.prepare_empty_stores = function(data) {
+ this.empty_stores = {};
+
+ for (var i in this.all) {
+ var name = this.all[i];
+
+ if (this.widgets[name] && this["flatten_" + name]) {
+ this.empty_stores[name] =
+ new dojo.data.ItemFileReadStore({
+ "data": this["flatten_" + name]([])
+ });
+ this.widgets[name].setStore(this.empty_stores[name]);
+ }
+ }
+};
+Populator.prototype.flatten_ready = function(data) {
+ return {
+ "label": "id",
+ "identifier": "id",
+ "items": data.map(function(o) {
+ return {
+ "id": o.id(),
+ "type": o.target_resource_type().name(),
+ "resource": o.current_resource().barcode(),
+ "start_time": humanize_timestamp_string(o.start_time()),
+ "end_time": humanize_timestamp_string(o.end_time())
+ };
+ })
+ };
+};
+Populator.prototype.flatten_out = function(data) {
+ return {
+ "label": "id",
+ "identifier": "id",
+ "items": data.map(function(o) {
+ return {
+ "id": o.id(),
+ "type": o.target_resource_type().name(),
+ "resource": o.current_resource().barcode(),
+ "pickup_time": humanize_timestamp_string(o.pickup_time()),
+ "end_time": humanize_timestamp_string(o.end_time())
+ };
+ })
+ };
+};
+Populator.prototype.flatten_in = function(data) {
+ return {
+ "label": "id",
+ "identifier": "id",
+ "items": data.map(function(o) {
+ return {
+ "id": o.id(),
+ "type": o.target_resource_type().name(),
+ "resource": o.current_resource().barcode(),
+ "due_time": humanize_timestamp_string(o.end_time()),
+ "return_time": humanize_timestamp_string(o.return_time())
+ };
+ })
+ };
+};
+Populator.prototype.reveal_container = function(widget) {
+ var el = document.getElementById("contains_" + widget.id);
+ if (el) reveal_dom_element(el);
+};
+Populator.prototype.hide_container = function(widget) {
+ var el = document.getElementById("contains_" + widget.id);
+ if (el) hide_dom_element(el);
+};
+Populator.prototype.populate_ready = function(data) {
+ return this._populate_any_resv_grid(data, "ready");
+};
+Populator.prototype.populate_out = function(data) {
+ return this._populate_any_resv_grid(data, "out");
+};
+Populator.prototype.populate_in = function(data) {
+ return this._populate_any_resv_grid(data, "in");
+};
+Populator.prototype._populate_any_resv_grid = function(data, which) {
+ var flattener = this["flatten_" + which];
+ var widget = this.widgets[which];
+ var cache = this.cache[which];
+ var empty_store = this.empty_stores[which];
+
+ this.reveal_container(widget);
+
+ if (!data || !data.length) {
+ widget.setStore(empty_store);
+ this.toggle_anyness(false, which);
+ } else {
+ for (var i in data) cache[data[i].id()] = data[i];
+
+ widget.setStore(
+ new dojo.data.ItemFileReadStore({"data": flattener(data)})
+ );
+
+ this.toggle_anyness(true, which);
+
+ /* Arrrgh! Horrid but necessary: */
+ setTimeout(function() { widget.sort(); }, 100);
+ }
+};
+Populator.prototype.populate_patron = function(data) {
+ var h2 = document.createElement("h2");
+ h2.setAttribute("class", "booking");
+ h2.appendChild(document.createTextNode(formal_name(data)));
+
+ this.widgets.patron.innerHTML = "";
+ this.widgets.patron.appendChild(h2);
+
+ this.reveal_container(this.widgets.patron);
+ /* Maybe add patron's home OU or something here later... */
+};
+Populator.prototype.return_by_resource = function(barcode) {
+ /* XXX instead of talking to the server every time we do this, we could
+ * also check the "out" cache, iff we have one. */
+ var r = fieldmapper.standardRequest(
+ ["open-ils.booking",
+ "open-ils.booking.reservations.by_returnable_resource_barcode"],
+ [xulG.auth.session.key, barcode]
+ );
+ if (!r) {
+ alert(localeStrings.NO_SUCH_RETURNABLE_RESOURCE);
+ } else if (is_ils_error(r)) {
+ alert(my_ils_error(localeStrings.RETURNABLE_RESOURCE_ERROR, r));
+ } else {
+ var new_barcode = r.usr().card().barcode();
+ if (this.patron_barcode && this.patron_barcode != new_barcode) {
+ /* XXX make this more subtle, i.e. flash something in background */
+ alert(localeStrings.NOTICE_CHANGE_OF_PATRON);
+ }
+ this.patron_barcode = new_barcode;
+ var ret = this.return(r);
+ if (!ret) {
+ alert(localeStrings.RETURN_NO_RESPONSE);
+ } else if (is_ils_error(ret)) {
+ alert(my_ils_error(localeStrings.RETURN_ERROR, ret));
+ } else {
+ /* XXX speedbump should go, but something has to happen else
+ * there's no indication to staff that anything happened when
+ * starting from a fresh (blank) return interface.
+ */
+ alert(localeStrings.RETURN_SUCCESS);
+ }
+ this.populate(); /* Won't recurse with no args. All is well. */
+ }
+};
+Populator.prototype.populate = function(barcode, which) {
+ if (barcode) {
+ if (barcode.patron) {
+ this.patron_barcode = barcode.patron;
+ }
+ else if (barcode.resource) { /* resource OR patron, not both */
+ if (!this.return_by_resource(barcode.resource))
+ return;
+ }
+ }
+ if (!this.patron_barcode) {
+ alert(localeStrings.NO_PATRON_BARCODE);
+ return;
+ }
+
+ if (!which) which = this.all;
+
+ var result = fieldmapper.standardRequest(
+ ["open-ils.booking", "open-ils.booking.reservations.get_captured"],
+ [xulG.auth.session.key, this.patron_barcode, which]
+ );
+
+ if (!result) {
+ this.patron_barcode = undefined;
+ alert(localeStrings.RESERVATIONS_NO_RESPONSE);
+ } else if (is_ils_error(result)) {
+ this.patron_barcode = undefined;
+ alert(my_ils_error(localeStrings.RESERVATIONS_ERROR, result));
+ } else {
+ for (var k in result)
+ this["populate_" + k](result[k]);
+ }
+};
+Populator.prototype.toggle_anyness = function(any, which) {
+ var widget = this.widgets[which].domNode;
+ var empty_alternate = document.getElementById("no_" + widget.id);
+ var controls = document.getElementById("controls_" + widget.id);
+ if (any) {
+ reveal_dom_element(widget);
+ if (empty_alternate) hide_dom_element(empty_alternate);
+ if (controls) reveal_dom_element(controls);
+ } else {
+ hide_dom_element(widget);
+ if (empty_alternate) reveal_dom_element(empty_alternate);
+ if (controls) hide_dom_element(controls);
+ }
+};
+Populator.prototype.pickup = function(reservation) {
+ return fieldmapper.standardRequest(
+ ["open-ils.circ", "open-ils.circ.reservation.pickup"],
+ [xulG.auth.session.key, {
+ "patron_barcode": this.patron_barcode,
+ "reservation": reservation
+ }]
+ );
+};
+Populator.prototype.return = function(reservation) {
+ return fieldmapper.standardRequest(
+ ["open-ils.circ", "open-ils.circ.reservation.return"],
+ [xulG.auth.session.key, {
+ "patron_barcode": this.patron_barcode,
+ "reservation": reservation.id()
+ /* yeah just id here ------^; lack of parallelism */
+ }]
+ );
+};
+Populator.prototype.act_on_selected = function(how, which) {
+ var widget = this.widgets[which];
+ var cache = this.cache[which];
+ var no_response_msg = localeStrings[how.toUpperCase() + "_NO_RESPONSE"];
+ var error_msg = localeStrings[how.toUpperCase() + "_ERROR"];
+
+ var selected_id_list =
+ widget.selection.getSelected().map(function(o) { return o.id[0]; });
+
+ if (!selected_id_list || !selected_id_list.length) {
+ alert(localeStrings.SELECT_SOMETHING);
+ return;
+ }
+
+ var reservations = selected_id_list.map(function(o) { return cache[o]; });
+
+ /* Do we have to process these one at a time? I think so... */
+ for (var i in reservations) {
+ var result = this[how](reservations[i]);
+ if (!result) {
+ alert(no_response_msg);
+ } else if (is_ils_error(result)) {
+ alert(my_ils_error(error_msg, result));
+ } else {
+ continue;
+ }
+ break;
+ }
+
+ this.populate();
+};
+Populator.prototype.reset = function() {
+ for (var k in this.widgets) {
+ this.hide_container(this.widgets[k]);
+ }
+ this.patron_barcode = undefined;
+ if (this.primary_input) {
+ this.primary_input.value = "";
+ this.primary_input.focus();
+ }
+};
};
/*
- * Misc helper functions
- */
-function set_datagrid_empty_store(grid) {
- grid.setStore(
- new dojo.data.ItemFileReadStore(
- {"data": flatten_to_dojo_data([])}
- )
- );
-}
-
-/*
* These functions communicate with the middle layer.
*/
function get_all_noncat_brt() {
}, /* whole_obj */ true]
);
if (result == null) {
- set_datagrid_empty_store(bresvGrid);
+ set_datagrid_empty_store(bresvGrid, flatten_to_dojo_data);
alert(localeStrings.GET_BRESV_LIST_NO_RESULT);
} else if (is_ils_error(result)) {
- set_datagrid_empty_store(bresvGrid);
+ set_datagrid_empty_store(bresvGrid, flatten_to_dojo_data);
if (is_ils_actor_card_error(result)) {
alert(localeStrings.ACTOR_CARD_NOT_FOUND);
} else {
--- /dev/null
+dojo.requireLocalization("openils.booking", "pickup_and_return");
+var localeStrings = dojo.i18n.getLocalization(
+ "openils.booking", "pickup_and_return"
+);
+var p;
+
+function my_init() {
+ p = new Populator({
+ "out": out_bresv,
+ "in": in_bresv,
+ "patron": document.getElementById("patron_info")
+ }, document.getElementById("barcode"));
+ init_auto_l10n(document.getElementById("auto_l10n_start_here"));
+
+ /* The following would handle pass-in from the patron interface, but
+ * doesn't work (dirty solution, will come back to it, make it work,
+ * clean it up). */
+// try {
+// document.getElementById("barcode").value =
+// xulG.bresv_interface_opts.patron_barcode;
+// document.getElementById("barcode_type").selectedIndex = 1;
+// document.getElementById("lookup").submit();
+// } catch (E) {
+// alert(E);
+// }
+}
--- /dev/null
+[% WRAPPER "default/base.tt2" %]
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/pickup.js"></script>
+<link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
+<script type="text/javascript">
+ dojo.require("dojox.grid.DataGrid");
+ openils.Util.addOnLoad(my_init);
+
+ function act(f) {
+ p.populate({"patron": f.patron_barcode.value});
+ return false; /* Always. */
+ }
+</script>
+<div id="auto_l10n_start_here">
+ <h1 class="booking AUTO_h1"></h1>
+ <div class="nice_vertical_padding" id="contains_barcode_control">
+ <form id="lookup" onsubmit="return act(this);">
+ <label for="patron_barcode" class="AUTO_patron_barcode"></label>
+ <input id="patron_barcode" name="patron_barcode" />
+ <input type="submit" class="AUTO_ATTR_VALUE_go" />
+ </form>
+ </div>
+ <div class="nice_vertical_padding" id="contains_patron_info">
+ <div id="patron_info"></div>
+ </div>
+ <div class="nice_vertical_padding" id="contains_ready_bresv">
+ <h3 class="booking AUTO_ready_bresv"></h3>
+ <div class="AUTO_no_ready_bresv" id="no_ready_bresv"></div>
+ <table id="ready_bresv" jsId="ready_bresv"
+ dojoType="dojox.grid.DataGrid" query="{id: '*'}"
+ rowSelector="20px" autoHeight="true" width="auto">
+ <thead>
+ <tr><!-- FIXME: i18n problem: init_auto_l10n() runs
+ too late to take care of the below elements. -->
+ <th width="35%" field="type">Title</th>
+ <th width="25%" field="resource">Barcode</th>
+ <th width="20%" field="start_time">Start time</th>
+ <th width="20%" field="end_time">End time</th>
+ </tr>
+ </thead>
+ </table>
+ <div class="nice_vertical_padding" id="controls_ready_bresv">
+ <form>
+ <input type="button" id="pickup_button"
+ class="AUTO_ATTR_VALUE_pickup"
+ onclick="p.act_on_selected('pickup', 'ready');" />
+ </form>
+ </div>
+ </div>
+ <div class="nice_vertical_padding" id="contains_out_bresv">
+ <hr />
+ <h3 class="booking AUTO_out_bresv"></h3>
+ <div class="AUTO_no_out_bresv" id="no_out_bresv"></div>
+ <table id="out_bresv" jsId="out_bresv"
+ dojoType="dojox.grid.DataGrid" query="{id: '*'}"
+ rowSelector="20px" autoHeight="true" width="auto">
+ <thead>
+ <tr><!-- FIXME: i18n problem: init_auto_l10n() runs
+ too late to take care of the below elements. -->
+ <th width="35%" field="type">Title</th>
+ <th width="25%" field="resource">Barcode</th>
+ <th width="20%" field="pickup_time">Pickup time</th>
+ <th width="20%" field="end_time">Due time</th>
+ </tr>
+ </thead>
+ </table>
+ </div>
+ <div class="nice_vertical_padding" id="contains_misc_controls">
+ <hr />
+ <form>
+ <input type="button" class="AUTO_ATTR_VALUE_reset"
+ onclick="p.reset();" />
+ </form>
+ </div>
+</div>
+[% END %]
--- /dev/null
+[% WRAPPER "default/base.tt2" %]
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
+<script src="[% ctx.media_prefix %]/js/ui/default/booking/return.js"></script>
+<link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
+<script type="text/javascript">
+ dojo.require("dojox.grid.DataGrid");
+ openils.Util.addOnLoad(my_init);
+
+ function act(f) {
+ var key = f.barcode_type.options[f.barcode_type.selectedIndex].value;
+ var obj = {};
+ obj[key] = f.barcode.value;
+ p.populate(obj);
+ return false; /* Always. */
+ }
+</script>
+<div id="auto_l10n_start_here">
+ <h1 class="booking AUTO_return_h1"></h1>
+ <div class="nice_vertical_padding" id="contains_barcode_control">
+ <form id="lookup" onsubmit="return act(this);">
+ <label for="barcode_type" class="AUTO_barcode_type"></label>
+ <select name="barcode_type" id="barcode_type"
+ onchange="var b = this.form.barcode; b.focus(); b.select();">
+ <option id="option_resource" value="resource"
+ selected="selected" class="AUTO_resource"></option>
+ <option id="option_patron" value="patron"
+ class="AUTO_patron"></option>
+ </select>
+ <input id="barcode" name="barcode" />
+ <input type="submit" class="AUTO_ATTR_VALUE_go" />
+ </form>
+ </div>
+ <div class="nice_vertical_padding" id="contains_patron_info">
+ <div id="patron_info"></div>
+ </div>
+ <div class="nice_vertical_padding" id="contains_out_bresv">
+ <h3 class="booking AUTO_out_bresv"></h3>
+ <div class="AUTO_no_out_bresv" id="no_out_bresv"></div>
+ <table id="out_bresv" jsId="out_bresv"
+ dojoType="dojox.grid.DataGrid" query="{id: '*'}"
+ rowSelector="20px" autoHeight="true" width="auto">
+ <thead>
+ <tr><!-- FIXME: i18n problem: init_auto_l10n() runs
+ too late to take care of the below elements. -->
+ <th width="35%" field="type">Title</th>
+ <th width="25%" field="resource">Barcode</th>
+ <th width="20%" field="pickup_time">Pickup time</th>
+ <th width="20%" field="end_time">Due time</th>
+ </tr>
+ </thead>
+ </table>
+ <div class="nice_vertical_padding" id="controls_out_bresv">
+ <form>
+ <input type="button" id="return_button"
+ class="AUTO_ATTR_VALUE_return"
+ onclick="p.act_on_selected('return', 'out');" />
+ </form>
+ </div>
+ </div>
+ <div class="nice_vertical_padding" id="contains_in_bresv">
+ <hr />
+ <h3 class="booking AUTO_in_bresv"></h3>
+ <div class="AUTO_no_in_bresv" id="no_in_bresv"></div>
+ <table id="in_bresv" jsId="in_bresv"
+ dojoType="dojox.grid.DataGrid" query="{id: '*'}"
+ rowSelector="20px" autoHeight="true" width="auto">
+ <thead>
+ <tr><!-- FIXME: i18n problem: init_auto_l10n() runs
+ too late to take care of the below elements. -->
+ <th width="35%" field="type">Title</th>
+ <th width="25%" field="resource">Barcode</th>
+ <th width="20%" field="due_time">Due time</th>
+ <th width="20%" field="return_time">Return time</th>
+ </tr>
+ </thead>
+ </table>
+ </div>
+ <div class="nice_vertical_padding" id="contains_misc_controls">
+ <hr />
+ <form>
+ <input type="button" class="AUTO_ATTR_VALUE_reset"
+ onclick="p.reset();" />
+ </form>
+ </div>
+</div>
+[% END %]
['oncommand'],
function() {
obj.set_tab(
- "/eg/booking/reservation_pickup",
+ "/eg/booking/pickup",
{
"tab_name": offlineStrings.getString(
"menu.cmd_booking_reservation_pickup.tab"
['oncommand'],
function() {
obj.set_tab(
- "/eg/booking/reservation_return",
+ "/eg/booking/return",
{
"tab_name": offlineStrings.getString(
"menu.cmd_booking_reservation_return.tab"
<menuitem label="&staff.main.menu.booking.reservation.label;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_booking_reservation"/>
<menuitem label="&staff.main.menu.booking.pull_list.label;" accesskey="&staff.main.menu.booking.pull_list.accesskey;" command="cmd_booking_pull_list"/>
<menuitem label="&staff.main.menu.booking.capture.label;" accesskey="&staff.main.menu.booking.capture.accesskey;" command="cmd_booking_capture"/>
- <!-- <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_booking_reservation_pickup"/>
- <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_booking_reservation_return"/> -->
+ <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_booking_reservation_pickup"/>
+ <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_booking_reservation_return"/>
</menupopup>
</menu>
);
}
],
+ 'cmd_patron_reservation_pickup' : [
+ ['command'],
+ function(ev) {
+ if (xulG.auth == undefined) {
+ xulG.auth = {"session": {"key": ses()}};
+ }
+ xulG.bresv_interface_opts = {
+ "patron_barcode": obj.patron.card().barcode()
+ };
+ xulG.new_tab(
+ "/eg/booking/pickup",
+ {
+ "tab_name": offlineStrings.getString(
+ "menu.cmd_booking_reservation_pickup.tab"
+ ),
+ "browser": false
+ },
+ xulG
+ );
+ }
+ ],
+ 'cmd_patron_reservation_return' : [
+ ['command'],
+ function(ev) {
+ if (xulG.auth == undefined) {
+ xulG.auth = {"session": {"key": ses()}};
+ }
+ xulG.bresv_interface_opts = {
+ "patron_barcode": obj.patron.card().barcode()
+ };
+ xulG.new_tab(
+ "/eg/booking/return",
+ {
+ "tab_name": offlineStrings.getString(
+ "menu.cmd_booking_reservation_return.tab"
+ ),
+ "browser": false
+ },
+ xulG
+ );
+ }
+ ],
'cmd_patron_exit' : [
['command'],
function(ev) {
<command id="cmd_patron_other" />
<command id="cmd_patron_alert" />
<command id="cmd_patron_reservation" />
+ <command id="cmd_patron_reservation_pickup" />
+ <command id="cmd_patron_reservation_return" />
<command id="cmd_patron_exit" />
<command id="cmd_patron_retrieve" />
<command id="cmd_patron_merge" />
<command id="cmd_patron_other" />
<command id="cmd_patron_alert" />
<command id="cmd_patron_reservation" />
+ <command id="cmd_patron_reservation_pickup" />
+ <command id="cmd_patron_reservation_return" />
<command id="cmd_patron_exit" />
<command id="cmd_patron_retrieve" />
<command id="cmd_patron_merge" />
<menuitem label="&staff.patron.info.triggered_events.label;" accesskey="&staff.patron.info.triggered_events.accesskey;" command="cmd_patron_info_triggered_events"/>
<menuitem label="&staff.patron.info.stat_cats.label;" accesskey="&staff.patron.info.stat_cats.accesskey;" command="cmd_patron_info_stats"/>
<menuitem label="&staff.main.menu.booking.reservation.label;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
+ <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_patron_reservation_pickup" />
+ <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_patron_reservation_return" />
<menuitem label="&staff.patron.info.surveys.label;" accesskey="&staff.patron.info.surveys.accesskey;" command="cmd_patron_info_surveys"/>
<menuitem label="&staff.patron.info.group.label;" accesskey="&staff.patron.info.group.accesskey;" command="cmd_patron_info_groups"/>
<menuitem label="&staff.patron_display.verify_password.label;" accesskey="&staff.patron_display.verify_password.accesskey;" command="cmd_verify_credentials"/>
<menuitem label="&staff.patron.info.triggered_events.label;" accesskey="&staff.patron.info.triggered_events.accesskey;" command="cmd_patron_info_triggered_events"/>
<menuitem label="&staff.patron.info.stat_cats.label;" accesskey="&staff.patron.info.stat_cats.accesskey;" command="cmd_patron_info_stats"/>
<menuitem label="&staff.main.menu.booking.reservation.label;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
+ <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_patron_reservation_pickup" />
+ <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_patron_reservation_return" />
<menuitem label="&staff.patron.info.surveys.label;" accesskey="&staff.patron.info.surveys.accesskey;" command="cmd_patron_info_surveys"/>
<menuitem label="&staff.patron.info.group.label;" accesskey="&staff.patron.info.group.accesskey;" command="cmd_patron_info_groups"/>
<menuitem label="&staff.patron_display.verify_password.label;" accesskey="&staff.patron_display.verify_password.accesskey;" command="cmd_verify_credentials"/>