Bug 12222: members-update.tt has a giant hash variable
[koha.git] / acqui / basketgroup.pl
blobc226ea359ee06dd97e4293c614cbc034c3a82cb7
1 #!/usr/bin/perl
3 #script to group (closed) baskets into basket groups for easier order management
4 #written by john.soros@biblibre.com 01/10/2008
6 # Copyright 2008 - 2009 BibLibre SARL
7 # Parts Copyright Catalyst 2010
9 # This file is part of Koha.
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 =head1 NAME
27 basketgroup.pl
29 =head1 DESCRIPTION
31 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
32 have to be closed to be printed or exported.
34 =head1 CGI PARAMETERS
36 =over 4
38 =item $booksellerid
40 The bookseller who we want to display the baskets (and basketgroups) of.
42 =back
44 =cut
46 use strict;
47 use warnings;
48 use Carp;
50 use C4::Input;
51 use C4::Auth;
52 use C4::Output;
53 use CGI;
55 use C4::Bookseller qw/GetBookSellerFromId/;
56 use C4::Budgets qw/ConvertCurrency/;
57 use C4::Acquisition qw/CloseBasketgroup ReOpenBasketgroup GetOrders GetBasketsByBasketgroup GetBasketsByBookseller ModBasketgroup NewBasketgroup DelBasketgroup GetBasketgroups ModBasket GetBasketgroup GetBasket GetBasketGroupAsCSV/;
58 use C4::Bookseller qw/GetBookSellerFromId/;
59 use C4::Branch qw/GetBranches/;
60 use C4::Members qw/GetMember/;
62 our $input=new CGI;
64 our ($template, $loggedinuser, $cookie)
65 = get_template_and_user({template_name => "acqui/basketgroup.tt",
66 query => $input,
67 type => "intranet",
68 authnotrequired => 0,
69 flagsrequired => {acquisition => 'group_manage'},
70 debug => 1,
71 });
73 sub BasketTotal {
74 my $basketno = shift;
75 my $bookseller = shift;
76 my $total = 0;
77 my @orders = GetOrders($basketno);
78 for my $order (@orders){
79 $total = $total + ( $order->{ecost} * $order->{quantity} );
80 if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} // C4::Context->preference("gist") )) {
81 my $gst = $bookseller->{gstrate} // C4::Context->preference("gist");
82 $total = $total * ( $gst / 100 +1);
85 $total .= " " . ($bookseller->{invoiceprice} // 0);
86 return $total;
89 #displays all basketgroups and all closed baskets (in their respective groups)
90 sub displaybasketgroups {
91 my $basketgroups = shift;
92 my $bookseller = shift;
93 my $baskets = shift;
94 if (scalar @$basketgroups != 0) {
95 foreach my $basketgroup (@$basketgroups){
96 my $i = 0;
97 my $basketsqty = 0;
98 while($i < scalar(@$baskets)){
99 my $basket = @$baskets[$i];
100 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
101 $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
102 push(@{$basketgroup->{'baskets'}}, $basket);
103 splice(@$baskets, $i, 1);
104 ++$basketsqty;
105 --$i;
107 ++$i;
109 $basketgroup -> {'basketsqty'} = $basketsqty;
111 $template->param(basketgroups => $basketgroups);
113 for(my $i=0; $i < scalar @$baskets; ++$i) {
114 if( ! @$baskets[$i]->{'closedate'} ) {
115 splice(@$baskets, $i, 1);
116 --$i;
117 }else{
118 @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
121 $template->param(baskets => $baskets);
122 $template->param( booksellername => $bookseller ->{'name'});
125 sub printbasketgrouppdf{
126 my ($basketgroupid) = @_;
128 my $pdfformat = C4::Context->preference("OrderPdfFormat");
129 if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages' || $pdfformat eq 'pdfformat::layout3pagesfr'
130 || $pdfformat eq 'pdfformat::layout2pagesde'){
131 eval {
132 eval "require $pdfformat";
133 import $pdfformat;
135 if ($@){
138 else {
139 print $input->header;
140 print $input->start_html; # FIXME Should do a nicer page
141 print "<h1>Invalid PDF Format set</h1>";
142 print "Please go to the systempreferences and set a valid pdfformat";
143 exit;
146 my $basketgroup = GetBasketgroup($basketgroupid);
147 my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
148 my $baskets = GetBasketsByBasketgroup($basketgroupid);
150 my %orders;
151 for my $basket (@$baskets) {
152 my @ba_orders;
153 my @ords = &GetOrders($basket->{basketno});
154 for my $ord (@ords) {
156 next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
157 eval {
158 require C4::Biblio;
159 import C4::Biblio;
161 if ($@){
162 croak $@;
164 eval {
165 require C4::Koha;
166 import C4::Koha;
168 if ($@){
169 croak $@;
172 $ord->{rrp} = ConvertCurrency( $ord->{'currency'}, $ord->{rrp} );
173 if ( $bookseller->{'listincgst'} ) {
174 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} );
175 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
176 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
177 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstgsti} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
178 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} );
179 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
180 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
181 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
182 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
183 } else {
184 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} * ( 1 + ( $ord->{gstrate} ) ) );
185 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} );
186 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
187 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstrate} * 100 );
188 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} * ( 1 + ( $ord->{gstrate} ) ) );
189 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} );
190 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
191 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
192 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
194 my $bib = GetBiblioData($ord->{biblionumber});
195 my $itemtypes = GetItemTypes();
197 #FIXME DELETE ME
198 # 0 1 2 3 4 5 6 7 8 9
199 #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
201 # Editor Number
202 my $en;
203 my $edition;
204 my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
205 if ($marcrecord){
206 if ( C4::Context->preference("marcflavour") eq 'UNIMARC' ) {
207 $en = $marcrecord->subfield( '345', "b" );
208 $edition = $marcrecord->subfield( '205', 'a' );
209 } elsif ( C4::Context->preference("marcflavour") eq 'MARC21' ) {
210 $en = $marcrecord->subfield( '037', "a" );
211 $edition = $marcrecord->subfield( '250', 'a' );
215 my $ba_order = {
216 isbn => ($ord->{isbn} ? $ord->{isbn} : undef),
217 itemtype => ( $ord->{itemtype} and $bib->{itemtype} ? $itemtypes->{$bib->{itemtype}}->{description} : undef ),
218 en => ( $en ? $en : undef ),
219 edition => ( $edition ? $edition : undef ),
221 for my $key ( qw/ gstrate author title itemtype publishercode copyrightdate publicationyear discount quantity rrpgsti rrpgste gstgsti gstgste ecostgsti ecostgste gstvalue totalgste totalgsti order_vendornote / ) {
222 $ba_order->{$key} = $ord->{$key};
225 push(@ba_orders, $ba_order);
227 $orders{$basket->{basketno}} = \@ba_orders;
229 print $input->header(
230 -type => 'application/pdf',
231 -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
233 my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} // C4::Context->preference("gist")) || die "pdf generation failed";
234 print $pdf;
238 my $op = $input->param('op') || 'display';
239 # possible values of $op :
240 # - add : adds a new basketgroup, or edit an open basketgroup, or display a closed basketgroup
241 # - mod_basket : modify an individual basket of the basketgroup
242 # - closeandprint : close and print an closed basketgroup in pdf. called by clicking on "Close and print" button in closed basketgroups list
243 # - print : print a closed basketgroup. called by clicking on "Print" button in closed basketgroups list
244 # - export : export in CSV a closed basketgroup. called by clicking on "Export" button in closed basketgroups list
245 # - delete : delete an open basketgroup. called by clicking on "Delete" button in open basketgroups list
246 # - reopen : reopen a closed basketgroup. called by clicking on "Reopen" button in closed basketgroup list
247 # - attachbasket : save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
248 # - display : display the list of all basketgroups for a vendor
249 my $booksellerid = $input->param('booksellerid');
250 $template->param(booksellerid => $booksellerid);
252 if ( $op eq "add" ) {
254 # if no param('basketgroupid') is not defined, adds a new basketgroup
255 # else, edit (if it is open) or display (if it is close) the basketgroup basketgroupid
256 # the template will know if basketgroup must be displayed or edited, depending on the value of closed key
258 my $bookseller = &GetBookSellerFromId($booksellerid);
259 my $basketgroupid = $input->param('basketgroupid');
260 my $billingplace;
261 my $deliveryplace;
262 my $freedeliveryplace;
263 if ( $basketgroupid ) {
264 # Get the selected baskets in the basketgroup to display them
265 my $selecteds = GetBasketsByBasketgroup($basketgroupid);
266 foreach my $basket(@{$selecteds}){
267 $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
269 $template->param(basketgroupid => $basketgroupid,
270 selectedbaskets => $selecteds);
272 # Get general informations about the basket group to prefill the form
273 my $basketgroup = GetBasketgroup($basketgroupid);
274 $template->param(
275 name => $basketgroup->{name},
276 deliverycomment => $basketgroup->{deliverycomment},
277 freedeliveryplace => $basketgroup->{freedeliveryplace},
279 $billingplace = $basketgroup->{billingplace};
280 $deliveryplace = $basketgroup->{deliveryplace};
281 $freedeliveryplace = $basketgroup->{freedeliveryplace};
282 $template->param( closedbg => ($basketgroup ->{'closed'}) ? 1 : 0);
283 } else {
284 $template->param( closedbg => 0);
286 # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
287 my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
288 $billingplace = $billingplace || $borrower->{'branchcode'};
289 $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
291 my $branches = C4::Branch::GetBranchesLoop( $billingplace );
292 $template->param( billingplaceloop => $branches );
293 $branches = C4::Branch::GetBranchesLoop( $deliveryplace );
294 $template->param( deliveryplaceloop => $branches );
295 $template->param( booksellerid => $booksellerid );
297 # the template will display a unique basketgroup
298 $template->param(grouping => 1);
299 my $basketgroups = &GetBasketgroups($booksellerid);
300 my $baskets = &GetBasketsByBookseller($booksellerid);
301 displaybasketgroups($basketgroups, $bookseller, $baskets);
302 } elsif ($op eq 'mod_basket') {
304 # edit an individual basket contained in this basketgroup
306 my $basketno=$input->param('basketno');
307 my $basketgroupid=$input->param('basketgroupid');
308 ModBasket( { basketno => $basketno,
309 basketgroupid => $basketgroupid } );
310 print $input->redirect("basket.pl?basketno=" . $basketno);
311 } elsif ( $op eq 'closeandprint') {
313 # close an open basketgroup and generates a pdf
315 my $basketgroupid = $input->param('basketgroupid');
316 CloseBasketgroup($basketgroupid);
317 printbasketgrouppdf($basketgroupid);
318 exit;
319 }elsif ($op eq 'print'){
321 # print a closed basketgroup
323 my $basketgroupid = $input->param('basketgroupid');
324 printbasketgrouppdf($basketgroupid);
325 exit;
326 }elsif ( $op eq "export" ) {
328 # export a closed basketgroup in csv
330 my $basketgroupid = $input->param('basketgroupid');
331 print $input->header(
332 -type => 'text/csv',
333 -attachment => 'basketgroup' . $basketgroupid . '.csv',
335 print GetBasketGroupAsCSV( $basketgroupid, $input );
336 exit;
337 }elsif( $op eq "delete"){
339 # delete an closed basketgroup
341 my $basketgroupid = $input->param('basketgroupid');
342 DelBasketgroup($basketgroupid);
343 print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid.'&amp;listclosed=1');
344 }elsif ( $op eq 'reopen'){
346 # reopen a closed basketgroup
348 my $basketgroupid = $input->param('basketgroupid');
349 my $booksellerid = $input->param('booksellerid');
350 ReOpenBasketgroup($basketgroupid);
351 my $redirectpath = ((defined $input->param('mode'))&& ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&amp;basketgroupid='.$basketgroupid.'&amp;booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' .$booksellerid.'&amp;listclosed=1';
352 print $input->redirect($redirectpath);
353 } elsif ( $op eq 'attachbasket') {
355 # save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
357 # Getting parameters
358 my $basketgroup = {};
359 my @baskets = $input->param('basket');
360 my $basketgroupid = $input->param('basketgroupid');
361 my $basketgroupname = $input->param('basketgroupname');
362 my $booksellerid = $input->param('booksellerid');
363 my $billingplace = $input->param('billingplace');
364 my $deliveryplace = $input->param('deliveryplace');
365 my $freedeliveryplace = $input->param('freedeliveryplace');
366 my $deliverycomment = $input->param('deliverycomment');
367 my $closedbg = $input->param('closedbg') ? 1 : 0;
368 if ($basketgroupid) {
369 # If we have a basketgroupid we edit the basketgroup
370 $basketgroup = {
371 name => $basketgroupname,
372 id => $basketgroupid,
373 basketlist => \@baskets,
374 billingplace => $billingplace,
375 deliveryplace => $deliveryplace,
376 freedeliveryplace => $freedeliveryplace,
377 deliverycomment => $deliverycomment,
378 closed => $closedbg,
380 ModBasketgroup($basketgroup);
381 if($closedbg){
382 # FIXME
384 }else{
385 # we create a new basketgroup (whith a closed basket)
386 $basketgroup = {
387 name => $basketgroupname,
388 booksellerid => $booksellerid,
389 basketlist => \@baskets,
390 billingplace => $billingplace,
391 deliveryplace => $deliveryplace,
392 freedeliveryplace => $freedeliveryplace,
393 deliverycomment => $deliverycomment,
394 closed => $closedbg,
396 $basketgroupid = NewBasketgroup($basketgroup);
398 my $redirectpath = ((defined $input->param('mode')) && ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&amp;basketgroupid='.$basketgroupid.'&amp;booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
399 $redirectpath .= "&amp;listclosed=1" if $closedbg ;
400 print $input->redirect($redirectpath );
402 }else{
403 # no param : display the list of all basketgroups for a given vendor
404 my $basketgroups = &GetBasketgroups($booksellerid);
405 my $bookseller = &GetBookSellerFromId($booksellerid);
406 my $baskets = &GetBasketsByBookseller($booksellerid);
408 displaybasketgroups($basketgroups, $bookseller, $baskets);
410 $template->param(listclosed => ((defined $input->param('listclosed')) && ($input->param('listclosed') eq '1'))? 1:0 );
411 #prolly won't use all these, maybe just use print, the rest can be done inside validate
412 output_html_with_http_headers $input, $cookie, $template->output;