From: Paul Poulain <[email protected]> Note: this one will be rewritten very soon (graphically) --- acqui/basketgroup.pl | 303 ++++++++++++++++++++ .../prog/en/modules/acqui/basketgroup.tmpl | 261 +++++++++++++++++ 2 files changed, 564 insertions(+), 0 deletions(-) create mode 100755 acqui/basketgroup.pl create mode 100755 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroup.tmpl
diff --git a/acqui/basketgroup.pl b/acqui/basketgroup.pl new file mode 100755 index 0000000..c760936 --- /dev/null +++ b/acqui/basketgroup.pl @@ -0,0 +1,303 @@ +#!/usr/bin/perl + +#script to group (closed) baskets into basket groups for easier order management +#written by [email protected] 01/10/2008 + +# Copyright 2008 - 2009 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., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + + +=head1 NAME + +basketgroup.pl + +=head1 DESCRIPTION + + This script lets the user group (closed) baskets into basket groups for easier order management. Note that the grouped baskets have to be from the same bookseller and + have to be closed. + +=head1 CGI PARAMETERS + +=over 4 + +=item $booksellerid + +The bookseller who we want to display the baskets (and basketgroups) of. + +=back + +=cut + +use strict; +use warnings; + +use C4::Input; +use C4::Auth; +use C4::Output; +use CGI; + +use C4::Bookseller qw/GetBookSellerFromId/; +use C4::Acquisition qw/GetOrders GetBasketsByBasketgroup GetBasketsByBookseller ModBasketgroup NewBasketgroup DelBasketgroup GetBasketgroups ModBasket GetBasketgroup/; +use C4::Bookseller qw/GetBookSellerFromId/; + +my $input=new CGI; + +my ($template, $loggedinuser, $cookie) + = get_template_and_user({template_name => "acqui/basketgroup.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => {acquisition => 'group_manage'}, + debug => 1, + }); + +sub parseinputbaskets { + my $booksellerid = shift; + my $baskets = &GetBasketsByBookseller($booksellerid); + for(my $i=0; $i < scalar @$baskets; ++$i) { + if( @$baskets[$i] && ! @$baskets[$i]->{'closedate'} ) { + splice(@$baskets, $i, 1); + --$i; + } + } + foreach my $basket (@$baskets){ +#perl DBI uses value "undef" for the mysql "NULL" value, so i need to check everywhere where $basket->{'basketgroupid'} is used for undef ☹ + $basket->{'basketgroupid'} = $input->param($basket->{'basketno'}.'-group') || undef; + } + return $baskets; +} + + + +sub parseinputbasketgroups { + my $booksellerid = shift; + my $baskets = shift; + my $basketgroups = &GetBasketgroups($booksellerid); + my $newbasketgroups; + foreach my $basket (@$baskets){ + my $basketgroup; + my $i = 0; + my $exists; + if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){ + $exists = "true"; + } else { + foreach my $basketgroup (@$basketgroups){ + if($basket->{'basketgroupid'} == $basketgroup->{'id'}){ + $exists = "true"; + push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'}); + last; + } + } + } + if (! $exists){ +#if the basketgroup doesn't exist yet + $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef; + $basketgroup->{'booksellerid'} = $booksellerid; + } else { + while($i < scalar @$basketgroups && @$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){ + ++$i; + } + $basketgroup = @$basketgroups[$i]; + } + $basketgroup->{'id'}=$basket->{'basketgroupid'}; + $basketgroup->{'name'}=$input->param('basketgroup-'.$basketgroup->{'id'}.'-name') || ""; + $basketgroup->{'closed'}= $input->param('basketgroup-'.$basketgroup->{'id'}.'-closed'); + push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'}); + if (! $exists){ + $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup; + } else { + if($basketgroup->{'id'}){ + @$basketgroups[$i] = $basketgroup; + } + } + } + return($basketgroups, $newbasketgroups); +} + +sub BasketTotal { + my $basketno = shift; + my $bookseller = shift; + my $total = 0; + my @orders = GetOrders($basketno); + for my $order (@orders){ + $total = $total + ( $order->{ecost} * $order->{quantity} ); + if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} || C4::Context->preference("gist") )) { + my $gst = $bookseller->{gstrate} || C4::Context->preference("gist"); + $total = $total * ( $gst / 100 +1); + } + } + $total .= $bookseller->{invoiceprice}; + return $total; +} + +#displays all basketgroups and all closed baskets (in their respective groups) +sub displaybasketgroups { + my $basketgroups = shift; + my $bookseller = shift; + my $baskets = shift; + if (scalar @$basketgroups != 0) { + foreach my $basketgroup (@$basketgroups){ + my $i = 0; + while($i < scalar(@$baskets)){ + my $basket = @$baskets[$i]; + if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){ + $basket->{total} = BasketTotal($basket->{basketno}, $bookseller); + push(@{$basketgroup->{'baskets'}}, $basket); + splice(@$baskets, $i, 1); + --$i; + } + ++$i; + } + } + $template->param(basketgroups => $basketgroups); + } + for(my $i=0; $i < scalar @$baskets; ++$i) { + if( ! @$baskets[$i]->{'closedate'} ) { + splice(@$baskets, $i, 1); + --$i; + } + } + $template->param(baskets => $baskets); + $template->param( booksellername => $bookseller ->{'name'}); +} + + +my $op = $input->param('op'); +my $booksellerid = $input->param('booksellerid'); + +if (! $op ) { + if(! $booksellerid){ + $template->param( ungroupedlist => 1); + my @booksellers = GetBookSeller(''); + for (my $i=0; $i < scalar @booksellers; $i++) { + my $baskets = &GetBasketsByBookseller($booksellers[$i]->{id}); + for (my $j=0; $j < scalar @$baskets; $j++) { + if(! @$baskets[$i]->{closedate} || @$baskets[$i]->{basketgroupid}) { + splice(@$baskets, $j, 1); + $j--; + } + } + if (scalar @$baskets == 0){ + splice(@booksellers, $i, 1); + $i--; + } + } + } else { + $template->param( booksellerid => $booksellerid ); + } + my $basketgroups = &GetBasketgroups($booksellerid); + my $bookseller = &GetBookSellerFromId($booksellerid); + my $baskets = &GetBasketsByBookseller($booksellerid); + + displaybasketgroups($basketgroups, $bookseller, $baskets); +} elsif ($op eq 'mod_basket') { +#we want to modify an individual basket's group + my $basketno=$input->param('basketno'); + my $basketgroupid=$input->param('basketgroupid'); + ModBasket( { basketno => $basketno, + basketgroupid => $basketgroupid } ); + print $input->redirect("basket.pl?basketno=" . $basketno); +} elsif ($op eq 'validate') { + if(! $booksellerid){ + $template->param( booksellererror => 1); + } else { + $template->param( booksellerid => $booksellerid ); + } + my $baskets = parseinputbaskets($booksellerid); + my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets); + foreach my $nbgid (keys %$newbasketgroups){ +#javascript just picks an ID that's higher than anything else, the ID might not be correct..chenge it and change all the basket's basketgroupid as well + my $bgid = NewBasketgroup($newbasketgroups->{$nbgid}); + ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid; + ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid; + } + foreach my $basket (@$baskets){ +#if the basket was added to a new basketgroup, first change the groupid to the groupid of the basket in mysql, because it contains the id from javascript otherwise. + if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){ + $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'}; + } + ModBasket($basket); + } + foreach my $basketgroup (@$basketgroups){ + if(! $basketgroup->{'id'}){ + foreach my $basket (@{$basketgroup->{'baskets'}}){ + if($input->param('basket'.$basket->{'basketno'}.'changed')){ + ModBasket($basket); + } + } + } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){ + ModBasketgroup($basketgroup); + } + } + $basketgroups = &GetBasketgroups($booksellerid); + my $bookseller = &GetBookSellerFromId($booksellerid); + $baskets = &GetBasketsByBookseller($booksellerid); + + displaybasketgroups($basketgroups, $bookseller, $baskets); +} elsif ( $op eq 'printbgroup') { + my $pdfformat = C4::Context->preference("pdfformat"); + eval "use $pdfformat" ; + eval "use C4::Branch"; + my $basketgroupid = $input->param('bgroupid'); + my $basketgroup = GetBasketgroup($basketgroupid); + my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'}); + my $baskets = GetBasketsByBasketgroup($basketgroupid); + my %orders; + for my $basket (@$baskets) { + my @ba_orders; + my @ords = &GetOrders($basket->{basketno}); + for my $ord (@ords) { + # ba_order is filled with : + # 0 1 2 3 4 5 6 7 8 9 + #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate + my @ba_order; + if ( $ord->{biblionumber} && $ord->{quantity}> 0 ) { + eval "use C4::Biblio"; + eval "use C4::Koha"; + my $bib = GetBiblioData($ord->{biblionumber}); + my $itemtypes = GetItemTypes(); + if($ord->{isbn}){ + push(@ba_order, $ord->{isbn}); + } else { + push(@ba_order, undef); + } + if ($ord->{itemtype}){ + push(@ba_order, $itemtypes->{$bib->{itemtype}}->{description}); + } else { + push(@ba_order, undef); + } +# } else { +# push(@ba_order, undef, undef); + for my $key (qw/author title publishercode quantity listprice ecost/) { + push(@ba_order, $ord->{$key}); #Order lines + } + push(@ba_order, $bookseller->{discount}); + push(@ba_order, $bookseller->{gstrate}*100 || C4::Context->preference("gist")); + push(@ba_orders, \...@ba_order); + } + } + %orders->{$basket->{basketno}...@ba_orders; + } + print $input->header( -type => 'application/pdf', -attachment => 'basketgroup.pdf' ); + my $branch = GetBranchInfo(GetBranch($input, GetBranches())); + $branch = @$branch[0]; + my $pdf = printpdf($basketgroup, $bookseller, $baskets, $branch, \%orders, $bookseller->{gstrate} || C4::Context->preference("gist")) || die "pdf generation failed"; + print $pdf; + exit; +} +#prolly won't use all these, maybe just use print, the rest can be done inside validate +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroup.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroup.tmpl new file mode 100755 index 0000000..5e716cf --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroup.tmpl @@ -0,0 +1,261 @@ +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> +<title>Koha › Basket grouping for Vendor <!-- TMPL_VAR name="booksellername" --></title> +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> + +<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.6.0/build/fonts/fonts-min.css" /> +<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"></script> +<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/animation/animation-min.js"></script> +<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/dragdrop/dragdrop-min.js"></script> +<script type="text/javascript" src="<!-- TMPL_VAR NAME='themelang' -->/js/acq.js"></script> + +<script type="text/javascript"> +//<![CDATA[ +function Check(ff) { + ff.submit(); +} +var basketgroups = 1; +YAHOO.util.Event.onDOMReady(DDApp.init, DDApp, true); +//]]> +</script> +<style type="text/css"> +/*margin and padding on body element + can introduce errors in determining + element position and are not recommended; + we turn them off as a foundation for YUI + CSS treatments. */ +body { + margin:0; + padding:0; +} + +div.workarea { padding:10px; float:left; width: 45%;} +div.workarea_alt { padding: 5px; float:left; width: 95%;} +div.closed { background-color="pink"; padding:10px; float:left; width: 45%;} + +ul.closed { + position: relative; + background: grey; + padding-bottom:10; + border: 1px solid gray; + list-style: none; + margin:0; + padding: 5px; +} + +ul.draglist { + position: relative; + background: #f7f7f7; + padding-bottom:10; + border: 1px solid gray; + list-style: none; + margin:0; + padding: 5px; +} + +ul.draglist li { + margin: 1px; + cursor: move; + list-style: none; +} + +ul.draglist_alt { + position: relative; + border: 1px solid gray; + list-style: none; + margin: 0; + background: #f7f7f7; + padding: 5px; + cursor: move; +} + +ul.draglist_alt li { + margin: 1px; + list-style: none; +} + +li.grouped { + background-color: #D1E6EC; + border:1px solid #7EA6B2; + list-style: none; +} + +li.ungrouped { + background-color: #D8D4E2; + border:1px solid #6B4C86; +} + +fieldset.various li { + list-style: none; + clear: none; +} + +</style> +</head> +<body> +<!-- TMPL_INCLUDE NAME="header.inc" --> +<!-- TMPL_INCLUDE NAME="acquisitions-search.inc" --> + +<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/acqui/acqui-home.pl">Acquisitions</a> ›<a href="/cgi-bin/koha/acqui/supplier.pl?supplierid=<!-- TMPL_VAR NAME="booksellerid" -->"><!-- TMPL_VAR NAME="booksellername" --></a> › Basket grouping for vendor: <!-- TMPL_VAR NAME="booksellername" --></div> + +<div id="doc" class="yui-t7"> + <div id="bd"> + <div id="yui-main"> + + <div id="toolbar"> +<script type="text/javascript"> + //<![CDATA[ + + // prepare DOM for YUI Toolbar + + $(document).ready(function() { + $("#toolbar").empty(); + yuiToolbar(); + }); + + // YUI Toolbar Functions + + function yuiToolbar() { + new YAHOO.widget.Button("newrecord"); + var booksellermenu = [ + { text: _("Bookseller"), url: "/cgi-bin/koha/acqui/supplier.pl?booksellerid=<!-- TMPL_VAR name="booksellerid" -->" }, + { text: _("Edit bookseller"), url: "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=<!-- TMPL_VAR name="booksellerid" -->"}, + ] + var ordersbutton = [ + { text: _("Manage orders"), url: "/cgi-bin/koha/acqui/booksellers.pl?supplier=<!-- TMPL_VAR name="booksellerid" -->" }, + { text: _("Edit uncertain prices"), url: "/cgi-bin/koha/acqui/uncertainprice.pl?booksellerid=<!-- TMPL_VAR name="booksellerid" -->&owner=1" }, + ] + + new YAHOO.widget.Button({ + type: "menu", + label: _("Bookseller"), + name: "booksellerbutton", + menu: booksellermenu, + container: "toolbar" + }); + + new YAHOO.widget.Button({ + type: "menu", + label: _("Orders"), + name: "ordersbutton", + menu: ordersbutton, + container: "toolbar" + }); + } + //]]> + </script> + </div> + + </div> + <div class="yui-b"> + <h1>Basket grouping for Vendor <a href="/cgi-bin/koha/acqui/supplier.pl?supplierid=<!-- TMPL_VAR NAME="booksellerid" -->"><!-- TMPL_VAR name="booksellername" --></a></h1> + <div class="yui-gc"> + <div class="yui-u"> + <fieldset id="various" class='various' > + <ul > + <li> + <label for="newbasketgroupname">New Basketgroup:</label> + <input type="text" name="newbasketgroupname" id="newbasketgroupname" onkeypress="newGroup(event, document.getElementById('newbasketgroupname').value);" checked/> + <span class="yui-button yui-link-button"> + <span class=" first-child"><a href="javascript: newGroup('button', document.getElementById('newbasketgroupname').value);">Ok</a></span> + </span> + </li> + <li> + <label for="filter baskets (regexp)">Filter Basketgroups (regexps allowed):</label> + <input type="text" name="filter baskets (regexp)" id="filter baskets (regexp)" onkeypress="filterGroups(event, document.getElementById('filter baskets (regexp)').value);" /> + <span class="yui-button yui-link-button"> + <span class=" first-child"><a href="javascript: filterGroups('button', document.getElementById('filter baskets (regexp)').value);">Ok</a></span> + </span> + </li> + <li> + <label for="showclosed">Show closed basketgroups</label> + <input type="checkbox" name="showclosed" id="showclosed" value="1" onChange="showhideclosegroups(document.getElementById('showclosed').checked);" unchecked /> + </li> + <li> + <label for="Move all ungrouped baskets to:">Move all ungrouped baskets to</label> + <input type="text" name="Move all ungrouped baskets to:" id="Move all ungrouped baskets to:" onkeypress="moveallungroupedto(event, document.getElementById('Move all ungrouped baskets to:').value);" /> + <span class="yui-button yui-link-button"> + <span class=" first-child"><a href="javascript: moveallungroupedto('button', document.getElementById('Move all ungrouped baskets to:').value);">Ok</a></span> + </span> + </li> + </ul> + </fieldset> + </div> + <div class="yui-u first"> + <form action="<!-- TMPL_VAR name="scriptname" -->" method="post" name="basketgroups" id="basketgroups"> + <div id="groups"> + <div class="workarea_alt" > + <h3>Ungrouped Baskets</h3> + <ul id="ungrouped" class="draglist_alt"> + <!-- TMPL_IF NAME="baskets" --> + <!-- TMPL_LOOP NAME="baskets" --> + <li class="ungrouped" id="<!-- TMPL_VAR NAME="basketno" -->" > + <a href="basket.pl?basketno=<!-- TMPL_VAR NAME="basketno" -->"> + <!-- TMPL_IF NAME="basketname" --> + <!-- TMPL_VAR NAME="basketname" --> + <!-- TMPL_ELSE --> + No name, basketnumber: <!-- TMPL_VAR NAME="basketno" --> + <!-- /TMPL_IF --> + </a>, <br /> + Total: <!-- TMPL_VAR name="total" --> + <input type="hidden" id="<!-- TMPL_VAR NAME="basketno" -->-group" name="<!-- TMPL_VAR NAME="basketno" -->-group" value="0" /> + <input type="hidden" id="basket-<!-- TMPL_VAR NAME="basketno" -->-changed" name="basket-<!-- TMPL_VAR NAME="basketno" -->-changed" value="0" /> + </li> + <!-- /TMPL_LOOP --> + <!-- /TMPL_IF> + </ul> + </div> + + <!-- TMPL_IF NAME="basketgroups" --> + <!-- TMPL_LOOP NAME="basketgroups" --> + <!-- TMPL_IF NAME="closed" --> + <div class="closed" style="display: none"> + <h3 ><!-- TMPL_VAR NAME="name" --></h3> + <p > [ + <a href="javascript:parent.location='basketgroup.pl?op=printbgroup&bgroupid=<!-- TMPL_VAR NAME="id" -->';">print</a>/ + <a href="javascript:unclosegroup('<!-- TMPL_VAR name="id" -->');">Unclose group</a> + ]</p> + <ul id="bg-<!-- TMPL_VAR NAME="id" -->" class="closed"> + <!-- TMPL_ELSE --> + <div class="workarea"> + <h3 ><!-- TMPL_VAR NAME="name" --></h3> + <p > [ + <a href="javascript:renameinit(<!-- TMPL_VAR NAME="id" -->);">rename</a> / + <a href="javascript:closebasketgroup('<!-- TMPL_VAR NAME="id" -->');">close</a> + ]</p> + <ul id="bg-<!-- TMPL_VAR NAME="id" -->" class="draglist"> + + <!-- /TMPL_IF --> + <!-- TMPL_LOOP NAME="baskets" --> + <li class="grouped" id="<!-- TMPL_VAR NAME="basketno" -->"> + <a href="basket.pl?basketno=<!-- TMPL_VAR NAME="basketno" -->"> + <!-- TMPL_IF NAME="basketname" --> + <!-- TMPL_VAR NAME="basketname" --> + <!-- TMPL_ELSE --> + No name, basketnumber: <!-- TMPL_VAR NAME="basketno" --> + <!-- /TMPL_IF --> + </a>, <br /> + Total: <!-- TMPL_VAR name="total" --> + <input type="hidden" id="<!-- TMPL_VAR NAME="basketno" -->-group"name="<!-- TMPL_VAR NAME="basketno" -->-group" value="<!-- TMPL_VAR NAME="id" -->" /> + <input type="hidden" id="basket-<!-- TMPL_VAR NAME="basketno" -->-changed" name="basket-<!-- TMPL_VAR NAME="basketno" -->-changed" value="0" /> + </li> + <!-- /TMPL_LOOP --> + </ul> + <input type="hidden" name="basketgroup-<!-- TMPL_VAR NAME="id" -->-name" id="basketgroup-<!-- TMPL_VAR NAME="id" -->-name" value='<!-- TMPL_VAR NAME="name" -->' /> + <input type="hidden" id="basketgroup-<!-- TMPL_VAR NAME="id" -->-closed" name="basketgroup-<!-- TMPL_VAR NAME="id" -->-closed" value="<!-- TMPL_VAR NAME="closed" -->" /> + <input type="hidden" id="basketgroup-<!-- TMPL_VAR NAME="id" -->-changed" name="basketgroup-<!-- TMPL_VAR NAME="id" -->-changed" value="0" /> + </div> + <!-- /TMPL_LOOP --> + <!-- /TMPL_IF --> + </div> + <fieldset class="action"> + <input type="hidden" name="booksellerid" value="<!-- TMPL_VAR name="booksellerid" -->" /> + <input type="hidden" name="op" value="validate" /> + <input type="button" value="Save" onclick="Check(this.form);" /> + </fieldset> + </form> + </div> + </div> + </div> + </div> + </div> +</div> -- 1.6.0.4 _______________________________________________ Koha-patches mailing list [email protected] http://lists.koha.org/mailman/listinfo/koha-patches
