Bugzilla – Attachment 7892 Details for
Bug 7178
Improve order item creation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
[SIGNED-OFF] Bug 7178: Acquisition item creation improvement
SIGNED-OFF-Bug-7178-Acquisition-item-creation-impr.patch (text/plain), 45.85 KB, created by
Katrin Fischer
on 2012-02-26 16:39:45 UTC
(
hide
)
Description:
[SIGNED-OFF] Bug 7178: Acquisition item creation improvement
Filename:
MIME Type:
Creator:
Katrin Fischer
Created:
2012-02-26 16:39:45 UTC
Size:
45.85 KB
patch
obsolete
>From e025c8d6b60f231dcad2db7ac559fe1cf75ce177 Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Thu, 19 Jan 2012 16:59:58 +0100 >Subject: [PATCH] [SIGNED-OFF] Bug 7178: Acquisition item creation improvement > >- Display a unique item block at once > >On orderreceive.pl when AcqCreateItem is 'receiving', and on >neworderempty.pl when AcqCreateItem is 'ordering' it displays an >item block with item infos to fill, and a '+' button. >When user clicks on '+', the block is hidden and a list shows up with >the items that will be received. User can then edit or delete items in >the list and click 'Save' to receive items. > >- PrepareItemrecordDisplay is now used for cloning block > >Previous cloning function was duplicating ids, the side effect is that >plugins didn't work when several items were displayed. >PrepareItemrecordDisplay regenerate the form with new ids > >- New system preference UniqueItemFields > >Contains a space-separated list of sql column names (of items table). >This syspref is used in two ways: > - Values corresponding to fields in syspref are not duplicated when > adding a new item (button 'Add') > - When saving the form, a check is made on fields in syspref for > detecting duplicate (in DB and in the form) > >Signed-off-by: Katrin Fischer <Katrin.Fischer.83@web.de> >All tests done are noted on the bug report. >--- > acqui/check_uniqueness.pl | 68 ++++ > acqui/neworderempty.pl | 16 +- > acqui/orderreceive.pl | 15 +- > installer/data/mysql/updatedatabase.pl | 10 + > .../intranet-tmpl/prog/en/includes/additem.js.inc | 10 + > koha-tmpl/intranet-tmpl/prog/en/js/additem.js | 337 ++++++++++++++------ > .../prog/en/modules/acqui/neworderempty.tt | 157 +++++----- > .../prog/en/modules/acqui/orderreceive.tt | 133 +++++--- > .../en/modules/admin/preferences/acquisitions.pref | 3 + > .../prog/en/modules/services/itemrecorddisplay.tt | 24 ++ > services/itemrecorddisplay.pl | 57 ++++ > 11 files changed, 587 insertions(+), 243 deletions(-) > create mode 100755 acqui/check_uniqueness.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/services/itemrecorddisplay.tt > create mode 100755 services/itemrecorddisplay.pl > >diff --git a/acqui/check_uniqueness.pl b/acqui/check_uniqueness.pl >new file mode 100755 >index 0000000..95b1992 >--- /dev/null >+++ b/acqui/check_uniqueness.pl >@@ -0,0 +1,68 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 BibLibre SARL >+# >+# 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 2 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. >+ >+# This script search in items table if a value for a given field exists. >+# It is used in check_additem (additem.js) >+# Parameters are a list of 'field', which must be field names in items table >+# and a list of 'value', which are the corresponding value to check >+# Eg. @field = ('barcode', 'barcode', 'stocknumber') >+# @value = ('1234', '1235', 'ABC') >+# The script will check if there is already an item with barcode '1234', >+# then an item with barcode '1235', and finally check if there is an item >+# with stocknumber 'ABC' >+# It returns a JSON string which contains what have been found >+# Eg. { barcode: ['1234', '1235'], stocknumber: ['ABC'] } >+ >+use Modern::Perl; >+ >+use CGI; >+use JSON; >+use C4::Context; >+use C4::Output; >+use C4::Auth; >+ >+my $input = new CGI; >+my @field = $input->param('field'); >+my @value = $input->param('value'); >+ >+my $dbh = C4::Context->dbh; >+ >+my $query = "SHOW COLUMNS FROM items"; >+my $sth = $dbh->prepare($query); >+$sth->execute; >+my $results = $sth->fetchall_hashref('Field'); >+my @columns = keys %$results; >+ >+my $r = {}; >+my $index = 0; >+for my $f ( @field ) { >+ if(0 < grep /^$f$/, @columns) { >+ $query = "SELECT $f FROM items WHERE $f = ?"; >+ $sth = $dbh->prepare( $query ); >+ $sth->execute( $value[$index] ); >+ my @values = $sth->fetchrow_array; >+ >+ if ( @values ) { >+ push @{ $r->{$f} }, $values[0]; >+ } >+ } >+ $index++; >+} >+ >+output_with_http_headers $input, undef, to_json($r), 'json'; >diff --git a/acqui/neworderempty.pl b/acqui/neworderempty.pl >index f3d107d..4265692 100755 >--- a/acqui/neworderempty.pl >+++ b/acqui/neworderempty.pl >@@ -303,17 +303,15 @@ if ($CGIsort2) { > } > > if (C4::Context->preference('AcqCreateItem') eq 'ordering' && !$ordernumber) { >- # prepare empty item form >- my $cell = PrepareItemrecordDisplay('','','','ACQ'); >-# warn "==> ".Data::Dumper::Dumper($cell); >- unless ($cell) { >- $cell = PrepareItemrecordDisplay('','','',''); >+ # Check if ACQ framework exists >+ my $marc = GetMarcStructure(1, 'ACQ'); >+ unless($marc) { > $template->param('NoACQframework' => 1); > } >- my @itemloop; >- push @itemloop,$cell; >- >- $template->param(items => \@itemloop); >+ $template->param( >+ AcqCreateItemOrdering => 1, >+ UniqueItemFields => C4::Context->preference('UniqueItemFields'), >+ ); > } > # Get the item types list, but only if item_level_itype is YES. Otherwise, it will be in the item, no need to display it in the biblio > my @itemtypes; >diff --git a/acqui/orderreceive.pl b/acqui/orderreceive.pl >index 659c103..2b59698 100755 >--- a/acqui/orderreceive.pl >+++ b/acqui/orderreceive.pl >@@ -117,16 +117,15 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > # prepare the form for receiving > if ( $count == 1 ) { > if (C4::Context->preference('AcqCreateItem') eq 'receiving') { >- # prepare empty item form >- my $cell = PrepareItemrecordDisplay('','','','ACQ'); >- unless ($cell) { >- $cell = PrepareItemrecordDisplay('','','',''); >+ # Check if ACQ framework exists >+ my $marc = GetMarcStructure(1, 'ACQ'); >+ unless($marc) { > $template->param('NoACQframework' => 1); > } >- my @itemloop; >- push @itemloop,$cell; >- >- $template->param(items => \@itemloop); >+ $template->param( >+ AcqCreateItemReceiving => 1, >+ UniqueItemFields => C4::Context->preference('UniqueItemFields'), >+ ); > } > > if ( @$results[0]->{'quantityreceived'} == 0 ) { >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index d2d9d97..59550ce 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -4712,6 +4712,16 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { > SetVersion($DBversion); > } > >+$DBversion = "XXX"; >+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { >+ $dbh->do(qq{ >+ INSERT INTO systempreferences(variable,value,explanation,options,type) >+ VALUES('UniqueItemFields', 'barcode', 'Space-separated list of fields that should be unique (used in acquisition module for item creation). Fields must be valid SQL column names of items table', '', 'Free') >+ }); >+ print "Upgrade to $DBversion done (Added system preference 'UniqueItemFields')\n"; >+ SetVersion($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 DropAllForeignKeys($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc >new file mode 100644 >index 0000000..5ab37f4 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc >@@ -0,0 +1,10 @@ >+<script type="text/javascript"> >+//<![CDATA[ >+var MSG_ADDITEM_JS_EDIT = _("Edit"); >+var MSG_ADDITEM_JS_DELETE = _("Delete"); >+var MSG_ADDITEM_JS_CLEAR = _("Clear"); >+var MSG_ADDITEM_JS_CANT_RECEIVE_MORE_ITEMS = _("You can't receive any more items"); >+var MSG_ADDITEM_JS_IS_DUPLICATE = _("is duplicated"); >+var MSG_ADDITEM_JS_ALREADY_EXISTS_IN_DB = _("already exists in database"); >+//]]> >+</script> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/additem.js b/koha-tmpl/intranet-tmpl/prog/en/js/additem.js >index 2f6c3fe..859fe02 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/js/additem.js >+++ b/koha-tmpl/intranet-tmpl/prog/en/js/additem.js >@@ -1,110 +1,239 @@ >-function deleteItemBlock(index) { >- var aDiv = document.getElementById(index); >- aDiv.parentNode.removeChild(aDiv); >- var quantity = document.getElementById('quantity'); >- quantity.setAttribute('value',parseFloat(quantity.getAttribute('value'))-1); >+function addItem( node, unique_item_fields ) { >+ var index = $(node).parent().attr('id'); >+ var current_qty = parseInt($("#quantity").val()); >+ var max_qty; >+ if($("#quantity_to_receive").length != 0){ >+ max_qty = parseInt($("#quantity_to_receive").val()); >+ } else { >+ max_qty = 99999; >+ } >+ if ( $("#items_list table").find('tr[idblock="' + index + '"]').length == 0 ) { >+ if ( current_qty < max_qty ) { >+ if ( current_qty < max_qty - 1 ) >+ cloneItemBlock(index, unique_item_fields); >+ addItemInList(index, unique_item_fields); >+ $("#" + index).find("a[name='buttonPlus']").text("Update"); >+ $("#quantity").val(current_qty + 1); >+ } else if ( current_qty >= max_qty ) { >+ alert(window.MSG_ADDITEM_JS_CANT_RECEIVE_MORE_ITEMS >+ || "You can't receive any more items."); >+ } >+ } else { >+ if ( current_qty < max_qty ) >+ cloneItemBlock(index, unique_item_fields); >+ var tr = constructTrNode(index); >+ $("#items_list table").find('tr[idblock="' + index + '"]:first').replaceWith(tr); >+ } >+ $("#" + index).hide(); >+} >+ >+function showItem(index) { >+ $("#outeritemblock").children("div").each(function(){ >+ if ( $(this).attr('id') == index ) { >+ $(this).show(); >+ } else { >+ if ( $("#items_list table").find('tr[idblock="' + $(this).attr('id') + '"]').length == 0 ) { >+ $(this).remove(); >+ } else { >+ $(this).hide(); >+ } >+ } >+ }); >+} >+ >+function constructTrNode(index, unique_item_fields) { >+ var fields = ['barcode', 'homebranch', 'holdingbranch', 'notforloan', >+ 'restricted', 'location', 'itemcallnumber', 'copynumber', >+ 'stocknumber', 'ccode', 'itype', 'materials', 'itemnotes']; >+ >+ var result = "<tr idblock='" + index + "'>"; >+ var edit_link = "<a href='#itemfieldset' style='text-decoration:none' onclick='showItem(\"" + index + "\");'>" >+ + (window.MSG_ADDITEM_JS_EDIT || "Edit") + "</a>"; >+ var del_link = "<a style='cursor:pointer' " >+ + "onclick='deleteItemBlock(this, \"" + index + "\", \"" + unique_item_fields + "\");'>" >+ + (window.MSG_ADDITEM_JS_DELETE || "Delete") + "</a>"; >+ result += "<td>" + edit_link + "</td>"; >+ result += "<td>" + del_link + "</td>"; >+ for(i in fields) { >+ var field = fields[i]; >+ var field_elt = $("#" + index) >+ .find("[name='kohafield'][value='items."+field+"']") >+ .prevAll("[name='field_value']")[0]; >+ var field_value; >+ if($(field_elt).is('select')) { >+ field_value = $(field_elt).find("option:selected").text(); >+ } else { >+ field_value = $(field_elt).val(); >+ } >+ result += "<td>" + field_value + "</td>"; >+ } >+ result += "</tr>"; >+ >+ return result; >+} >+ >+function addItemInList(index, unique_item_fields) { >+ $("#items_list").show(); >+ var tr = constructTrNode(index, unique_item_fields); >+ $("#items_list table tbody").append(tr); >+} >+ >+function deleteItemBlock(node_a, index, unique_item_fields) { >+ $("#" + index).remove(); >+ var current_qty = parseInt($("#quantity").val()); >+ var max_qty; >+ if($("#quantity_to_receive").length != 0) { >+ max_qty = parseInt($("#quantity_to_receive").val()); >+ } else { >+ max_qty = 99999; >+ } >+ $("#quantity").val(current_qty - 1); >+ $(node_a).parents('tr').remove(); >+ if(current_qty - 1 == 0) >+ $("#items_list").hide(); >+ >+ if ( $("#quantity").val() <= max_qty - 1) { >+ if ( $("#outeritemblock").children("div :visible").length == 0 ) { >+ $("#outeritemblock").children("div:last").show(); >+ } >+ } >+ if ( $("#quantity").val() == 0 && $("#outeritemblock > div").length == 0) { >+ cloneItemBlock(0, unique_item_fields); >+ } > } >-function cloneItemBlock(index) { >- var original = document.getElementById(index); //original <div> >- var clone = clone_with_selected(original) >+ >+function cloneItemBlock(index, unique_item_fields) { >+ var original; >+ if(index) { >+ original = $("#" + index); //original <div> >+ } >+ var dont_copy_fields = new Array(); >+ if(unique_item_fields) { >+ var dont_copy_fields = unique_item_fields.split(' '); >+ for(i in dont_copy_fields) { >+ dont_copy_fields[i] = "items." + dont_copy_fields[i]; >+ } >+ } >+ > var random = Math.floor(Math.random()*100000); // get a random itemid. >- // set the attribute for the new 'div' subfields >- clone.setAttribute('id',index + random);//set another id. >- var NumTabIndex; >- NumTabIndex = parseInt(original.getAttribute('tabindex')); >- if(isNaN(NumTabIndex)) NumTabIndex = 0; >- clone.setAttribute('tabindex',NumTabIndex+1); >- var CloneButtonPlus; >- var CloneButtonMinus; >- // try{ >- var jclone = $(clone); >- CloneButtonPlus = $("a.addItem", jclone).get(0); >- CloneButtonPlus.setAttribute('onclick',"cloneItemBlock('" + index + random + "')"); >- CloneButtonMinus = $("a.delItem", jclone).get(0); >- CloneButtonMinus.setAttribute('onclick',"deleteItemBlock('" + index + random + "')"); >- CloneButtonMinus.setAttribute('style',"display:inline"); >- // change itemids of the clone >- var elems = clone.getElementsByTagName('input'); >- for( i = 0 ; elems[i] ; i++ ) >- { >- if(elems[i].name.match(/^itemid/)) { >- elems[i].value = random; >+ var clone = $("<div id='itemblock"+random+"'></div>") >+ $.ajax({ >+ url: "/cgi-bin/koha/services/itemrecorddisplay.pl", >+ dataType: 'html', >+ data: { >+ frameworkcode: 'ACQ' >+ }, >+ success: function(data, textStatus, jqXHR) { >+ /* Create the item block */ >+ $(clone).append(data); >+ /* Change all itemid fields value */ >+ $(clone).find("input[name='itemid']").each(function(){ >+ $(this).val(random); >+ }); >+ /* Add buttons + and Clear */ >+ var buttonPlus = '<a name="buttonPlus" style="cursor:pointer; margin:0 1em;" onclick="addItem(this,\'' + unique_item_fields + '\')">Add</a>'; >+ var buttonClear = '<a name="buttonClear" style="cursor:pointer;" onclick="clearItemBlock(this)">' + (window.MSG_ADDITEM_JS_CLEAR || 'Clear') + '</a>'; >+ $(clone).append(buttonPlus).append(buttonClear); >+ /* Copy values from the original block (input) */ >+ $(original).find("input[name='field_value']").each(function(){ >+ var kohafield = $(this).siblings("input[name='kohafield']").val(); >+ if($(this).val() && dont_copy_fields.indexOf(kohafield) == -1) { >+ $(this).parent("div").attr("id").match(/^(subfield.)/); >+ var id = RegExp.$1; >+ var value = $(this).val(); >+ $(clone).find("div[id^='"+id+"'] input[name='field_value']").val(value); >+ } >+ }); >+ /* Copy values from the original block (select) */ >+ $(original).find("select[name='field_value']").each(function(){ >+ var kohafield = $(this).siblings("input[name='kohafield']").val(); >+ if($(this).val() && dont_copy_fields.indexOf(kohafield) == -1) { >+ $(this).parent("div").attr("id").match(/^(subfield.)/); >+ var id = RegExp.$1; >+ var value = $(this).val(); >+ $(clone).find("div[id^='"+id+"'] select[name='field_value']").val(value); >+ } >+ }); >+ >+ $("#outeritemblock").append(clone); > } >- } >- // } >- //catch(e){ // do nothig if ButtonPlus & CloneButtonPlus don't exist. >- //} >- // insert this line on the page >- original.parentNode.insertBefore(clone,original.nextSibling); >- var quantity = document.getElementById('quantity'); >- quantity.setAttribute('value',parseFloat(quantity.getAttribute('value'))+1); >+ }); > } >-function check_additem() { >- var barcodes = document.getElementsByName('barcode'); >- var success = true; >- for(i=0;i<barcodes.length;i++){ >- for(j=0;j<barcodes.length;j++){ >- if( (i > j) && (barcodes[i].value == barcodes[j].value) && barcodes[i].value !='') { >- barcodes[i].className='error'; >- barcodes[j].className='error'; >- success = false; >- } >- } >- } >- // TODO : Add AJAX function to test against barcodes already in the database, not just >- // duplicates within the form. >- return success; >+ >+function clearItemBlock(node) { >+ var index = $(node).parent().attr('id'); >+ var block = $("#"+index); >+ $(block).find("input[type='text']").each(function(){ >+ $(this).val(""); >+ }); >+ $(block).find("select").each(function(){ >+ $(this).find("option:first").attr("selected", true); >+ }); >+} >+ >+function check_additem(unique_item_fields) { >+ var success = true; >+ var data = new Object(); >+ data['field'] = new Array(); >+ data['value'] = new Array(); >+ var array_fields = unique_item_fields.split(' '); >+ $(".error").empty(); // Clear error div >+ >+ // Check if a value is duplicated in form >+ for ( field in array_fields ) { >+ var fieldname = array_fields[field]; >+ var values = new Array(); >+ $("[name='kohafield'][value=items."+array_fields[field]+"]").each(function(){ >+ var input = $(this).prevAll("input[name='field_value']")[0]; >+ if($(input).val()) { >+ values.push($(input).val()); >+ data['field'].push(fieldname); >+ data['value'].push($(input).val()); >+ } >+ }); >+ >+ var sorted_arr = values.sort(); >+ for (var i = 0; i < sorted_arr.length - 1; i += 1) { >+ if (sorted_arr[i + 1] == sorted_arr[i]) { >+ $(".error").append( >+ fieldname + " '" + sorted_arr[i] + "' " >+ + (window.MSG_ADDITEM_JS_IS_DUPLICATE || "is duplicated") >+ + "<br/>"); >+ success = false; >+ } >+ } >+ } >+ >+ // If there is a duplication, we raise an error >+ if ( success == false ) { >+ $(".error").show(); >+ return false; >+ } >+ >+ $.ajax({ >+ url: '/cgi-bin/koha/acqui/check_uniqueness.pl', >+ async: false, >+ dataType: 'json', >+ data: data, >+ success: function(data) { >+ for (field in data) { >+ success = false; >+ for (var i=0; i < data[field].length; i++) { >+ var value = data[field][i]; >+ $(".error").append( >+ field + " '" + value + "' " >+ + (window.MSG_ADDITEM_JS_ALREADY_EXISTS_IN_DB >+ || "already exists in database") >+ + "<br />" >+ ); >+ } >+ } >+ } >+ }); >+ >+ if ( success == false ) { >+ $(".error").show(); >+ } >+ return success; > } > >-function clone_with_selected (node) { >- var origin = node.getElementsByTagName("select"); >- var tmp = node.cloneNode(true) >- var selectelem = tmp.getElementsByTagName("select"); >- for (var i=0; i<origin.length; i++) { >- selectelem[i].selectedIndex = origin[i].selectedIndex; >- } >- origin = null; >- selectelem = null; >- return tmp; >- } >- >-$(document).ready(function(){ >- $(".cloneItemBlock").click(function(){ >- var clonedRow = $(this).parent().parent().clone(true); >- clonedRow.insertAfter($(this).parent().parent()).find("a.deleteItemBlock").show(); >- // find ID of cloned row so we can increment it for the clone >- var count = $("input[id^=volinf]",clonedRow).attr("id"); >- var current = Number(count.replace("volinf","")); >- var increment = current + 1; >- // loop over inputs >- var inputs = ["volinf","barcode"]; >- jQuery.each(inputs,function() { >- // increment IDs of labels and inputs in the clone >- $("label[for="+this+current+"]",clonedRow).attr("for",this+increment); >- $("input[name="+this+"]",clonedRow).attr("id",this+increment); >- }); >- // loop over selects >- var selects = ["homebranch","location","itemtype","ccode"]; >- jQuery.each(selects,function() { >- // increment IDs of labels and selects in the clone >- $("label[for="+this+current+"]",clonedRow).attr("for",this+increment); >- $("input[name="+this+"]",clonedRow).attr("id",this+increment); >- $("select[name="+this+"]",clonedRow).attr("id",this+increment); >- // find the selected option and select it in the clone >- var selectedVal = $("select#"+this+current).find("option:selected").attr("value"); >- $("select[name="+this+"] option[value="+selectedVal+"]",clonedRow).attr("selected","selected"); >- }); >- >- var quantityrec = parseFloat($("#quantityrec").attr("value")); >- quantityrec++; >- $("#quantityrec").attr("value",quantityrec); >- return false; >- }); >- $(".deleteItemBlock").click(function(){ >- $(this).parent().parent().remove(); >- var quantityrec = parseFloat($("#quantityrec").attr("value")); >- quantityrec--; >- $("#quantityrec").attr("value",quantityrec); >- return false; >- }); >-}); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >index a27d151..3604de5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >@@ -3,12 +3,28 @@ > [% INCLUDE 'doc-head-close.inc' %] > > <script type="text/javascript" src="[% themelang %]/js/acq.js"></script> >+[% INCLUDE 'additem.js.inc' %] > <script type="text/javascript" src="[% themelang %]/js/additem.js"></script> > <script type="text/javascript"> > //<![CDATA[ > actTotal = ""; > > function Check(ff) { >+ [% IF (AcqCreateItemOrdering) %] >+ // Remove last itemblock if it is not in items_list >+ var lastitemblock = $("#outeritemblock > div:last"); >+ var tobedeleted = true; >+ var listitems = $("#items_list tr"); >+ $(listitems).each(function(){ >+ if($(this).attr('idblock') == $(lastitemblock).attr('id')){ >+ tobedeleted = false; >+ } >+ }); >+ if(tobedeleted){ >+ $(lastitemblock).remove(); >+ } >+ [% END %] >+ > var ok=0; > var _alertString= _("Form not submitted because of the following problem(s)")+"\n"; > >@@ -24,7 +40,7 @@ function Check(ff) { > _alertString += "\n- "+ _("You must select a budget"); > } > >- if (!(isNum(ff.quantity,0))){ >+ if (!(isNum(ff.quantity,0)) || ff.quantity.value == 0){ > ok=1; > _alertString += "\n- " + _("Quantity must be greater than '0'"); > } >@@ -46,16 +62,12 @@ function Check(ff) { > } > > if ( ff.field_value ) { >- var barcodes = []; > var empty_item_mandatory = 0; > for (i = 0; i < ff.field_value.length; i++) { > //alert("i = " + i + " => " + ff.kohafield[i] ); > if (ff.field_value[i].value.length == 0 && ff.mandatory[i].value == 1) { > empty_item_mandatory++; > } >- if(ff.subfield[i].value === '[% barcode_subfield %]' && ff.field_value[i].value.length != 0) { >- barcodes.push(ff.field_value[i].value); >- } > } > if (empty_item_mandatory > 0) { > ok = 1; >@@ -63,56 +75,34 @@ function Check(ff) { > "\n- " + empty_item_mandatory + _(" item mandatory fields empty"); > } > >- if(barcodes.length > 0) { >- // Check for duplicate barcodes in the form >- barcodes = barcodes.sort(); >- for(var i=0; i<barcodes.length-1; i++) { >- if(barcodes[i] == barcodes[i+1]) { >- ok = 1; >- _alertString += "\n- " + _("The barcode ") + barcodes[i] + _(" is used more than once in the form. Every barcode must be unique"); >- } >- } >- >- // Check for duplicate barcodes in the database via an ajax call >- $.ajax({ >- url: "/cgi-bin/koha/acqui/check_duplicate_barcode_ajax.pl", >- async:false, >- method: "post", >- data: {barcodes : barcodes}, >- dataType: 'json', >- >- error: function(xhr) { >- alert("Error: \n" + xhr.responseText); >- }, >- success: function(json) { >- switch(json.status) { >- case 'UNAUTHORIZED': >- ok = 1; >- _alertString += "\n- " + _("Error: Duplicate barcode verification failed. Insufficient user permissions."); >- break; >- case 'DUPLICATES': >- ok = 1; >- $.each(json.barcodes, function(index, barcode) { >- _alertString += "\n- " + _("The barcode ") + barcode + _(" already exists in the database"); >- }); >- break; >- } >- }, >- }); >- } > } > > if (ok) { > alert(_alertString); >+ [% IF (AcqCreateItemOrdering) %] >+ if(tobedeleted) { >+ $(lastitemblock).appendTo('#outeritemblock'); >+ } >+ [% END %] > return false; > } > >- ff.submit(); >- >+ [% IF (AcqCreateItemOrdering) %] >+ if(check_additem('[% UniqueItemFields %]') == false) { >+ alert(_('Duplicate values detected. Please correct the errors and resubmit.') ); >+ if(tobedeleted) { >+ $(lastitemblock).appendTo('#outeritemblock'); >+ } >+ return false; >+ } >+ [% END %] > } > > $(document).ready(function() > { >+ [% IF (AcqCreateItemOrdering) %] >+ cloneItemBlock(0, '[% UniqueItemFields %]'); >+ [% END %] > //We apply the fonction only for modify option > [% IF ( quantityrec ) %] > $('#quantity').blur(function() >@@ -168,6 +158,8 @@ $(document).ready(function() > [% END %] > </h2> > >+<div class="error" style="display:none"></div> >+ > [% IF ( basketno ) %] > <div id="acqui_basket_summary" class="yui-g"> > <fieldset class="rows"> >@@ -207,7 +199,7 @@ $(document).ready(function() > </div> > [% END %] > >-<form action="/cgi-bin/koha/acqui/addorder.pl" method="post" id="Aform"> >+<form action="/cgi-bin/koha/acqui/addorder.pl" method="post" id="Aform" onsubmit="return Check(this);"> > > <fieldset class="rows"> > <legend> >@@ -332,41 +324,47 @@ $(document).ready(function() > </fieldset> > [% END %] > >- [% IF ( items ) %] >- <fieldset class="rows"> >+ [% IF (AcqCreateItemOrdering) %] >+ >+ <div id="items_list" style="display:none"> >+ <p><b>Items list</b></p> >+ <div style="width:100%;overflow:auto;"> >+ <table> >+ <thead> >+ <tr> >+ <th> </th> >+ <th> </th> >+ <th>Barcode</th> >+ <th>Home branch</th> >+ <th>Holding branch</th> >+ <th>Not for loan</th> >+ <th>Restricted</th> >+ <th>Location</th> >+ <th>Call number</th> >+ <th>Copy number</th> >+ <th>Stock number</th> >+ <th>Collection code</th> >+ <th>Item type</th> >+ <th>Materials</th> >+ <th>Notes</th> >+ </tr> >+ </thead> >+ <tbody> >+ </tbody> >+ </table> >+ </div> >+ </div> >+ >+ <fieldset class="rows" id="itemfieldset"> > <legend>Item</legend> > [% IF ( NoACQframework ) %] > <div class="dialog message">No ACQ framework, using default. You should create a framework with code ACQ, the items framework would be used</div> > [% END %] > >- [% FOREACH item IN items %] >- <div id="outeritemblock"> >- <div id="itemblock"> >- <ol>[% FOREACH iteminformatio IN item.iteminformation %]<li style="[% iteminformatio.hidden %];"> >- <div class="subfield_line" id="subfield[% iteminformatio.serialid %][% iteminformatio.countitems %][% iteminformatio.subfield %][% iteminformatio.random %]"> >- >- <label>[% iteminformatio.subfield %] - [% IF ( iteminformatio.mandatory ) %]<b>[% END %][% iteminformatio.marc_lib %][% IF ( iteminformatio.mandatory ) %] *</b>[% END %]</label> >- [% iteminformatio.marc_value %] >- <input type="hidden" name="itemid" value="1" /> >- <input type="hidden" name="kohafield" value="[% iteminformatio.kohafield %]" /> >- <input type="hidden" name="tag" value="[% iteminformatio.tag %]" /> >- <input type="hidden" name="subfield" value="[% iteminformatio.subfield %]" /> >- <input type="hidden" name="mandatory" value="[% iteminformatio.mandatory %]" /> >- [% IF ( iteminformatio.ITEM_SUBFIELDS_ARE_NOT_REPEATABLE ) %] >- <span class="buttonPlus" onclick="CloneSubfield('subfield[% iteminformatio.serialid %][% iteminformatio.countitems %][% iteminformatio.subfield %][% iteminformatio.random %]')">+</span> >- [% END %] >- >- </div></li> >- [% END %] >- </ol> >- <a class="addItem" onclick="cloneItemBlock('itemblock[% item.itemBlockIndex %]')">Add</a> >- <a class="delItem" style="display:none;" onclick="deleteItemBlock('itemblock[% item.itemBlockIndex %]')">Delete</a> >- </div><!-- /iteminformation --> >- </div> >+ <div id="outeritemblock"></div> > >- [% END %] <!-- /items --> > </fieldset> >- [% END %] <!-- items --> >+ [% END %][%# IF (AcqCreateItemOrdering) %] > <fieldset class="rows"> > <legend>Accounting Details</legend> > <ol> >@@ -375,9 +373,9 @@ $(document).ready(function() > <span class="label required">Quantity: </span> > <input type="hidden" size="20" name="quantity" value="[% quantity %]" />[% quantity %] > [% ELSE %] >- <label class="required" for="quantity">Quantity: </label> >- [% IF ( items ) %] >- <input type="text" readonly="readonly" size="20" id="quantity" name="quantity" value="1" onchange="calcNeworderTotal();" /> >+ <label class="required" for="quantity">Quantity: </label> >+ [% IF (AcqCreateItemOrdering) %] >+ <input type="text" readonly="readonly" size="20" id="quantity" name="quantity" value="0" onchange="updateCosts();" /> > [% ELSE %] > <input type="text" size="20" id="quantity" name="quantity" value="[% quantityrec %]" onchange="calcNeworderTotal();" /> > [% END %] >@@ -529,7 +527,12 @@ $(document).ready(function() > </ol> > </fieldset> > <fieldset class="action"> >- <input type="button" value="Save" onclick="Check(this.form)" /> [% IF ( suggestionid ) %]<a class="cancel" href="/cgi-bin/koha/acqui/newordersuggestion.pl?booksellerid=[% booksellerid %]&basketno=[% basketno %]">Cancel</a>[% ELSE %]<a class="cancel" href="/cgi-bin/koha/acqui/basket.pl?basketno=[% basketno %]">Cancel</a>[% END %] >+ <input type="submit" value="Save" /> >+ [% IF (suggestionid) %] >+ <a class="cancel" href="/cgi-bin/koha/acqui/newordersuggestion.pl?booksellerid=[% booksellerid %]&basketno=[% basketno %]">Cancel</a> >+ [% ELSE %] >+ <a class="cancel" href="/cgi-bin/koha/acqui/basket.pl?basketno=[% basketno %]">Cancel</a> >+ [% END %] > </fieldset> > </form> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >index e238278..623db10 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >@@ -1,7 +1,44 @@ > [% INCLUDE 'doc-head-open.inc' %] > <title>Koha › Acquisitions › Receipt summary for : [% name %] [% IF ( invoice ) %]invoice, [% invoice %][% END %]</title> > [% INCLUDE 'doc-head-close.inc' %] >+[% INCLUDE 'additem.js.inc' %] > <script type="text/javascript" src="[% themelang %]/js/additem.js"> </script> >+<script type="text/javascript"> >+//<![CDATA[ >+ function Check(form) { >+ [% IF (AcqCreateItemReceiving) %] >+ // Remove last itemblock if it is not in items_list >+ var lastitemblock = $("#outeritemblock > div:last"); >+ var tobedeleted = true; >+ var listitems = $("#items_list tr"); >+ $(listitems).each(function(){ >+ if($(this).attr('idblock') == $(lastitemblock).attr('id')){ >+ tobedeleted = false; >+ } >+ }); >+ if(tobedeleted){ >+ $(lastitemblock).remove(); >+ } >+ >+ if(check_additem('[% UniqueItemFields %]') == false){ >+ alert(_('Duplicate values detected. Please correct the errors and resubmit.') ); >+ if(tobedeleted) { >+ $(lastitemblock).appendTo("#outeritemblock"); >+ } >+ return false; >+ }; >+ [% END %] >+ >+ return true; >+ } >+ >+ $(document).ready(function() { >+ [% IF (AcqCreateItemReceiving) %] >+ cloneItemBlock(0, '[% UniqueItemFields %]'); >+ [% END %] >+ }); >+//]]> >+</script> > </head> > <body> > [% INCLUDE 'header.inc' %] >@@ -18,10 +55,11 @@ > <h1>Receive items from : [% name %] [% IF ( invoice ) %][[% invoice %]] [% END %] (order #[% ordernumber %])</h1> > > [% IF ( count ) %] >- <form action="/cgi-bin/koha/acqui/finishreceive.pl" method="post"> >+ <form action="/cgi-bin/koha/acqui/finishreceive.pl" method="post" onsubmit="return Check(this);"> > <div class="yui-g"> > <div class="yui-u first"> >- >+ <div class="error" style="display:none"></div> >+ > <fieldset class="rows"> > <legend>Catalog Details</legend> > <ol><li><span class="label">Title: </span><span class="title">[% title |html %]</span></li> >@@ -48,48 +86,48 @@ > </fieldset> > [% END %] > >- [% IF ( items ) %] >- <fieldset class="rows"> >- <legend>Item</legend> >- [% IF ( NoACQframework ) %] >- <p class="required">No ACQ framework, using default. You should create a framework with code ACQ, the items framework would be used</p> >- [% END %] >+ [% IF (AcqCreateItemReceiving) %] >+ <div id="items_list" style="display:none"> >+ <p><b>Items list</b></p> >+ <div style="width:100%;overflow:auto;"> >+ <table> >+ <thead> >+ <tr> >+ <th> </th> >+ <th> </th> >+ <th>Barcode</th> >+ <th>Home branch</th> >+ <th>Holding branch</th> >+ <th>Not for loan</th> >+ <th>Restricted</th> >+ <th>Location</th> >+ <th>Call number</th> >+ <th>Copy number</th> >+ <th>Stock number</th> >+ <th>Collection code</th> >+ <th>Item type</th> >+ <th>Materials</th> >+ <th>Notes</th> >+ </tr> >+ </thead> >+ <tbody> >+ </tbody> >+ </table> >+ </div> >+ </div> > >- [% FOREACH item IN items %] >- <div id="outeritemblock"> >- <div id="itemblock"> >- <ol>[% FOREACH iteminformatio IN item.iteminformation %]<li style="[% iteminformatio.hidden %];"> >- <div class="subfield_line" id="subfield[% iteminformatio.serialid %][% iteminformatio.countitems %][% iteminformatio.subfield %][% iteminformatio.random %]"> >- >- <label>[% iteminformatio.subfield %] - [% IF ( iteminformatio.mandatory ) %]<b>[% END %][% iteminformatio.marc_lib %][% IF ( iteminformatio.mandatory ) %] *</b>[% END %]</label> >- [% iteminformatio.marc_value %] >- <input type="hidden" name="itemid" value="1" /> >- <input type="hidden" name="kohafield" value="[% iteminformatio.kohafield %]" /> >- <input type="hidden" name="tag" value="[% iteminformatio.tag %]" /> >- <input type="hidden" name="subfield" value="[% iteminformatio.subfield %]" /> >- <input type="hidden" name="mandatory" value="[% iteminformatio.mandatory %]" /> >- [% IF ( iteminformatio.ITEM_SUBFIELDS_ARE_NOT_REPEATABLE ) %] >- <span class="buttonPlus" onclick="CloneSubfield('subfield[% iteminformatio.serialid %][% iteminformatio.countitems %][% iteminformatio.subfield %][% iteminformatio.random %]')">+</span> >- [% END %] >- >- </div></li> >+ <fieldset class="rows" id="itemfieldset"> >+ <legend>Item</legend> >+ [% IF ( NoACQframework ) %] >+ <p class="required"> >+ No ACQ framework, using default. You should create a >+ framework with code ACQ, the items framework would be >+ used >+ </p> > [% END %] >- </ol> >- <a class="addItem" onclick="cloneItemBlock('itemblock[% item.itemBlockIndex %]')">Add</a> >- <a class="delItem" style="display:none;" onclick="deleteItemBlock('itemblock[% item.itemBlockIndex %]')">Delete</a> >- </div><!-- /iteminformation --> >- </div> >- >- <input type="hidden" name="moditem" value="" /> >- <input type="hidden" name="tag" value="[% item.itemtagfield %]" /> >- <input type="hidden" name="subfield" value="[% item.itemtagsubfield %]" /> >- <input type="hidden" name="serial" value="[% item.serialid %]" /> >- <input type="hidden" name="bibnum" value="[% item.biblionumber %]" /> >- <input type="hidden" name="itemid" value="1" /> >- <input type="hidden" name="field_value" value="[% item.itemnumber %]" /> >- [% END %] <!-- /items --> >- </fieldset> >- [% END %] <!-- items --> >+ <div id="outeritemblock"></div> >+ </fieldset> >+ [% END %][%# IF (AcqCreateItemReceiving) %] > <input type="hidden" name="biblionumber" value="[% biblionumber %]" /> > <input type="hidden" name="ordernumber" value="[% ordernumber %]" /> > <input type="hidden" name="biblioitemnumber" value="[% biblioitemnumber %]" /> >@@ -107,12 +145,15 @@ > <li><label for="creator">Created by: </label><span> [% IF ( memberfirstname and membersurname ) %][% IF ( memberfirstname ) %][% memberfirstname %][% END %] [% membersurname %][% ELSE %]No name[% END %]</span></li> > <li><label for="quantityto">Quantity to receive: </label><span class="label"> > [% IF ( edit ) %] >- <input type="text" name="quantity" value="[% quantity %]" /> >+ <input type="text" id="quantity_to_receive" name="quantity" value="[% quantity %]" /> > [% ELSE %] >- <input type="text" READONLY name="quantity" value="[% quantity %]" /> >+ <input type="text" readonly="readonly" id="quantity_to_receive" name="quantity" value="[% quantity %]" /> > [% END %] > </span></li> > <li><label for="quantity">Quantity received: </label> >+ [% IF (AcqCreateItemReceiving) %] >+ <input readonly="readonly" type="text" size="20" name="quantityrec" id="quantity" value="0" /> >+ [% ELSE %] > [% IF ( quantityreceived ) %] > [% IF ( edit ) %] > <input type="text" size="20" name="quantityrec" id="quantity" value="[% quantityreceived %]" /> >@@ -133,6 +174,7 @@ > [% END %] > <input id="origquantityrec" READONLY type="hidden" name="origquantityrec" value="0" /> > [% END %] >+ [% END %][%# IF (AcqCreateItemReceiving) %] > </li> > <li><label for="rrp">Replacement cost: </label><input type="text" size="20" name="rrp" id="rrp" value="[% rrp %]" /></li> > <li><label for="ecost">Budgeted cost: </label><input type="text" size="20" name="ecost" id="ecost" value="[% ecost %]" /></li> >@@ -148,7 +190,8 @@ > > </div> > </div><div class="yui-g"><fieldset class="action"> >- <input type="button" value="Save" onclick="javascript:if(check_additem()) { this.form.submit(); } else { alert( _('Duplicate barcodes detected. Please correct the errors and resubmit.') ); return false };" /> <a class="cancel" href="/cgi-bin/koha/acqui/parcel.pl?booksellerid=[% booksellerid %]&invoice=[% invoice %]&gst=[% gst %]&freight=[% freight %]">Cancel</a> >+ <input type="submit" value="Save" /> >+ <a class="cancel" href="/cgi-bin/koha/acqui/parcel.pl?booksellerid=[% supplierid %]&invoice=[% invoice %]&gst=[% gst %]&freight=[% freight %]">Cancel</a> > </fieldset></div> </form> > [% ELSE %] > <div id="acqui_acquire_orderlist"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/acquisitions.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/acquisitions.pref >index 70e660d..d67954e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/acquisitions.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/acquisitions.pref >@@ -9,6 +9,9 @@ Acquisitions: > receiving: receiving an order. > cataloguing: cataloging the record. > - >+ - pref: UniqueItemFields >+ - (space-separated list of fields that should be unique for items, must be valid SQL fields of items table) >+ - > - When closing or reopening a basket, > - pref: BasketConfirmations > default: 1 >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/services/itemrecorddisplay.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/services/itemrecorddisplay.tt >new file mode 100644 >index 0000000..6790b3d >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/services/itemrecorddisplay.tt >@@ -0,0 +1,24 @@ >+<ol> >+ [% FOREACH iteminfo IN iteminformation %] >+ <li> >+ <div class="subfield_line" style="[% iteminfo.hidden %];" id="subfield[% iteminfo.serialid %][% iteminfo.countitems %][% iteminfo.subfield %][% iteminfo.random %]"> >+ <label> >+ [% iteminfo.subfield %] - >+ [% IF ( iteminfo.mandatory ) %] >+ <b> >+ [% END %] >+ [% iteminfo.marc_lib %] >+ [% IF ( iteminfo.mandatory ) %] >+ *</b> >+ [% END %] >+ </label> >+ [% iteminfo.marc_value %] >+ <input type="hidden" name="itemid" value="1" /> >+ <input type="hidden" name="kohafield" value="[% iteminfo.kohafield %]" /> >+ <input type="hidden" name="tag" value="[% iteminfo.tag %]" /> >+ <input type="hidden" name="subfield" value="[% iteminfo.subfield %]" /> >+ <input type="hidden" name="mandatory" value="[% iteminfo.mandatory %]" /> >+ </div> >+ </li> >+ [% END %] >+</ol> >diff --git a/services/itemrecorddisplay.pl b/services/itemrecorddisplay.pl >new file mode 100755 >index 0000000..cd5fb32 >--- /dev/null >+++ b/services/itemrecorddisplay.pl >@@ -0,0 +1,57 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 BibLibre SARL >+# 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 2 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 NAME >+ >+itemrecorddisplay.pl >+ >+=head1 DESCRIPTION >+ >+Return a HTML form for Item record modification or creation. >+It uses PrepareItemrecordDisplay >+ >+=cut >+ >+use strict; >+use warnings; >+ >+use CGI; >+use C4::Auth; >+use C4::Output; >+use C4::Items; >+ >+my $input = new CGI; >+my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( { >+ template_name => 'services/itemrecorddisplay.tmpl', >+ query => $input, >+ type => 'intranet', >+ authnotrequired => 1, >+} ); >+ >+my $biblionumber = $input->param('biblionumber') || ''; >+my $itemnumber = $input->param('itemnumber') || ''; >+my $frameworkcode = $input->param('frameworkcode') || ''; >+ >+my $result = PrepareItemrecordDisplay($biblionumber, $itemnumber, undef, $frameworkcode); >+unless($result) { >+ $result = PrepareItemrecordDisplay($biblionumber, $itemnumber, undef, ''); >+} >+ >+$template->param(%$result); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >-- >1.7.5.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 7178
:
6233
|
7249
|
7279
|
7450
|
7806
|
7807
|
7892
|
7963
|
8558
|
8672
|
8715
|
8857
|
8886
|
9511
|
9518
|
9690