From 3dc98d865e11b6b355e8bd33150724ea836a0017 Mon Sep 17 00:00:00 2001 From: Maxime Pelletier Date: Fri, 7 Mar 2014 12:31:30 -0500 Subject: [PATCH] Add RMA support for Acquisitions. --- C4/Letters.pm | 82 +++++++++ acqui/returnorder.pl | 182 ++++++++++++++++++++ .../data/mysql/en/mandatory/sample_notices.sql | 13 ++ .../mysql/fr-FR/1-Obligatoire/sample_notices.sql | 11 ++ installer/data/mysql/updatedatabase.pl | 19 ++ .../intranet-tmpl/prog/en/css/staff-global.css | 12 ++ .../prog/en/includes/acquisitions-menu.inc | 1 + .../prog/en/modules/acqui/returnorder.tt | 108 ++++++++++++ .../intranet-tmpl/prog/en/modules/tools/letter.tt | 5 + tools/letter.pl | 2 +- 10 files changed, 434 insertions(+), 1 deletions(-) create mode 100755 acqui/returnorder.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/returnorder.tt diff --git a/C4/Letters.pm b/C4/Letters.pm index 5025c10..6f10fa5 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -416,6 +416,88 @@ sub SendAlerts { ); sendmail(%mail) or carp $Mail::Sendmail::error; } + elsif ( $type eq 'rma' ) { + my $userenv = C4::Context->userenv; + my $branchcode = $userenv->{branch}; + + # prepare the letter... + # search the biblionumber + my $strsth = + "select aqorders.*,aqbasket.*,biblio.*,biblioitems.* from aqorders + LEFT JOIN aqbasket on aqbasket.basketno=aqorders.basketno + LEFT JOIN biblio on aqorders.biblionumber=biblio.biblionumber + LEFT JOIN biblioitems on aqorders.biblioitemnumber=biblioitems.biblioitemnumber + where aqorders.ordernumber IN (" + . join( ",", @$externalid ) . ")"; + my $sthorders = $dbh->prepare($strsth); + $sthorders->execute; + my $dataorders = $sthorders->fetchall_arrayref( {} ); + my $sthbookseller = + $dbh->prepare("select * from aqbooksellers where id=?"); + $sthbookseller->execute( $dataorders->[0]->{booksellerid} ); + my $databookseller = $sthbookseller->fetchrow_hashref; + + my $letter = GetPreparedLetter ( + module => 'rma', + letter_code => $letter_code, + branchcode => $branchcode, + tables => { + 'aqbooksellers' => $dataorders->[0]->{booksellerid}, + 'branches' => $branchcode, + }, + ); + + # parsing librarian name + $letter->{content} =~ s/<>/$userenv->{firstname}/g; + $letter->{content} =~ s/<>/$userenv->{surname}/g; + $letter->{content} =~ + s/<>/$userenv->{emailaddress}/g; + + #Parses the content of item tags + foreach my $data (@$dataorders) { + my $line = $1 if ($letter->{content} =~ m/(.*<\/item>)/); + foreach my $field ( keys %$data ) { + $line =~ s/(<<[^\.]+.$field>>)/$data->{$field}/; + } + $line =~ s/<\/{0,1}?item>//g; # strip all item tags... + $letter->{content} =~ s/(.*<\/item>)/$line\n$1/; + } + #Remove the final item tags from the initial content + $letter->{content} =~ s/(.*<\/item>)//; + + my $innerletter = $letter; + + # ... then send mail + if ( $databookseller->{bookselleremail} + || $databookseller->{contemail} ) + { + utf8::encode($innerletter->{title}); + utf8::encode($innerletter->{content}); + my %mail = ( + To => $databookseller->{bookselleremail} + . ( + $databookseller->{contemail} + ? "," . $databookseller->{contemail} + : "" + ), + From => $userenv->{emailaddress}, + Subject => "" . $innerletter->{title}, + Message => "" . $innerletter->{content}, + 'Content-Type' => 'text/plain; charset="utf8"', + ); + sendmail(%mail) or carp $Mail::Sendmail::error; + } + if ( C4::Context->preference("LetterLog") ) { + logaction( + "ACQUISITION", + "Send RMA letter", + "", + "order list : " + . join( ",", @$externalid ) + . "\n$innerletter->{title}\n$innerletter->{content}" + ); + } + } } =head2 GetPreparedLetter( %params ) diff --git a/acqui/returnorder.pl b/acqui/returnorder.pl new file mode 100755 index 0000000..ba1d0c6 --- /dev/null +++ b/acqui/returnorder.pl @@ -0,0 +1,182 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use CGI; +use C4::Bookseller; +use C4::Auth; +use C4::Koha; +use C4::Output; +use C4::Context; +use C4::Acquisition; +use C4::Letters; +use C4::Branch; # GetBranches +use C4::Members qw/GetMember/; +use C4::Dates qw/format_date/; +use C4::Reports; + +my $input = new CGI; +my ($template, $loggedinuser, $cookie) = get_template_and_user({ + template_name => "acqui/returnorder.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => {acquisition => 'order_receive'}, + debug => 1, +}); + +my $supplierid = $input->param('supplierid') || undef; # we don't want "" or 0 +my $delay = $input->param('delay'); +my $branch = $input->param('branch'); +my $op = $input->param('op'); + +my @errors = (); +$delay = 30 unless defined $delay; +unless ($delay =~ /^\d{1,3}$/) { + push @errors, {delay_digits => 1, bad_delay => $delay}; + $delay = 30; #default value for delay +} + +if ($op and $op eq "findsupplier") +{ + my $supplier = $input->param('supplier'); + my @suppliers = C4::Bookseller::GetBookSeller($supplier); + my $count = scalar @suppliers; + my @loop_suppliers; + for ( my $i = 0 ; $i < $count ; $i++ ) { + my $orders = GetBasketsByBookseller( $suppliers[$i]->{'id'}, {groupby => "aqbasket.basketno", orderby => "aqbasket.basketname"} ); + my $ordcount = scalar @$orders; + my %line; + + $line{supplierid} = $suppliers[$i]->{'id'}; + $line{name} = $suppliers[$i]->{'name'}; + $line{active} = $suppliers[$i]->{'active'}; + my @loop_basket; + my $uid = GetMember(borrowernumber => $loggedinuser)->{userid} if $loggedinuser; + my $i3 = 0; + for ( my $i2 = 0 ; $i2 < $ordcount ; $i2++ ) { + if ( $orders->[$i2]{'authorisedby'} == $loggedinuser || haspermission($uid, { flagsrequired => { 'acquisition' => '*' } } ) ) { + my %inner_line; + my @orders_items = GetOrders($orders->[$i2]{'basketno'}); + $inner_line{basketno} = $orders->[$i2]{'basketno'}; + $inner_line{basketname} = $orders->[$i2]{'basketname'}; + $inner_line{total} = scalar @orders_items; + $inner_line{authorisedby} = $orders->[$i2]{'authorisedby'}; + my $authby = GetMember(borrowernumber => $orders->[$i2]{'authorisedby'}); + $inner_line{surname} = $authby->{'firstname'}; + $inner_line{firstname} = $authby->{'surname'}; + $inner_line{creationdate} = format_date( $orders->[$i2]{'creationdate'} ); + $inner_line{closedate} = format_date( $orders->[$i2]{'closedate'} ); + $inner_line{uncertainprice} = $orders->[$i2]{'uncertainprice'}; + $inner_line{orders_items} = \@orders_items; + $inner_line{odd} = $i3 % 2; + if ($inner_line{total} > 0) { + push @loop_basket, \%inner_line; + $i3++; + } + } + } + $line{loop_basket} = \@loop_basket; + push @loop_suppliers, \%line; + } + + #use Data::Dumper; + #die Dumper \@loop_suppliers; + + my @letters; + my $letters=GetLetters("rma"); + foreach (keys %$letters){ + push @letters, {code=>$_,name=>$letters->{$_}}; + } + $template->param(letters=>\@letters) if (@letters); + $template->param(suppliers => \@loop_suppliers); + $template->param(suppliername => $input->param('supplier')); +} + +if ($op and $op eq "send_alert"){ + my @ordernums = $input->param("generate_for"); + my $output = $input->param("output"); + if ($output eq "email"){ + SendAlerts('rma',\@ordernums,$input->param("letter_code")); + } + else { + + my $dbh = C4::Context->dbh; + my $basename = $input->param("basename"); + my $sep = $input->param("sep"); + print $input->header( + -type => 'application/vnd.sun.xml.calc', + -encoding => 'utf-8', + -attachment => "$basename.csv", + -name => "$basename.csv" + ); + + my $strsth = "SELECT aqorders.*,aqbasket.*,biblio.*,biblioitems.*, bs.* + FROM aqorders + LEFT JOIN aqbasket on aqbasket.basketno=aqorders.basketno + LEFT JOIN biblio on aqorders.biblionumber=biblio.biblionumber + LEFT JOIN biblioitems on aqorders.biblionumber=biblioitems.biblionumber + JOIN aqbooksellers bs on bs.id = booksellerid + where aqorders.ordernumber IN (". join( ",", @ordernums ) . ")"; + my $sthorders = $dbh->prepare($strsth); + $sthorders->execute; + my $dataorders = $sthorders->fetchall_arrayref( {} ); + + print "aqbooksellers.name" . $sep; + print "aqbooksellers.address1" . $sep; + print "aqbooksellers.address2" . $sep; + print "aqbooksellers.address3" . $sep; + print "aqbooksellers.address4" . $sep; + print "aqbooksellers.phone" . $sep; + print "aqorders.ordernumber" . $sep; + print "biblioitems.isbn" . $sep; + print "biblio.title" . $sep; + print "biblio.author" . $sep; + print "aqorders.quantity" . $sep; + print "aqorders.listprice" . $sep; + print "\n"; + + foreach my $data (@$dataorders) { + print _surround($data->{name}) . $sep; + print _surround($data->{address1}) . $sep; + print _surround($data->{address2}) . $sep; + print _surround($data->{address3}) . $sep; + print _surround($data->{address4}) . $sep; + print _surround($data->{phone}) . $sep; + print _surround($data->{ordernumber}) . $sep; + print _surround($data->{isbn}) . $sep; + print _surround($data->{title}) . $sep; + print _surround($data->{author}) . $sep; + print _surround($data->{quantity}) . $sep; + print _surround($data->{listprice}) . $sep; + print "\n"; + } + + exit(1); + } +} + +sub _surround { + my $string = shift || ""; + $string =~ s/"/""/g; + return "\"$string\""; +} + +my $CGIextChoice = CGI::scrolling_list( + -name => 'MIME', + -id => 'MIME', + -values => ['CSV'], # FIXME translation + -size => 1, + -multiple => 0 +); + +my $CGIsepChoice = C4::Reports::GetDelimiterChoices; + +$template->param(ERROR_LOOP => \@errors) if (@errors); +$template->param( + CGIextChoice => $CGIextChoice, + CGIsepChoice => $CGIsepChoice, + delay => $delay, + intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"), +); +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/installer/data/mysql/en/mandatory/sample_notices.sql b/installer/data/mysql/en/mandatory/sample_notices.sql index 2d09971..242ddd2 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ b/installer/data/mysql/en/mandatory/sample_notices.sql @@ -117,3 +117,16 @@ http://<>/cgi-bin/koha/opac-registration-verify.pl?token=<> +<> +<> +<> +<> +<> + +Some items in this order will be returned : +Order number +<> (<>) (<> ordered) ($<> each)' +); diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql index 4b786b6..7c96ed7 100644 --- a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql @@ -19,3 +19,14 @@ VALUES ('suggestions','ORDERED','Suggestion commandée', 'Suggestion commandée','Cher(e) <> <>,\n\nVous avez effectué une demande de suggestion d\'achat sur le docuement <> de <>.\n\nNous sommes heureux de vous informer que le document que vous avez demandé est maintenant en commande. Le document devrait arriver rapidement dans nos collections.\n\nVous serez averti quand le docuement sera disponible.\n\nSi vous avez des questions, merci de nous contacter à l\'adresse <>\n\nMerci,\n\n<>'), ('suggestions','REJECTED','Suggestion rejetée', 'Suggestion d\'achat rejeté','Cher(e) <> <>,\n\nVous avez fait la demande du document <> de <>.\n\nla Bibliothèque a examiné votre demande ce jour, et a décidé de ne pas retenir la suggestion pour l\'instant.\n\nLa raison est la suivante: <>\n\nSi vous avez des questions, merci de nous contacter à l\'adresse <>.\n\nMerci,\n\n<>'); INSERT INTO `letter` (module, code, name, title, content) VALUES ('circulation','RENEWAL','Item Renewal','Renewals','Les documents suivants ont été renouvelés\r\n----\r\n<>\r\n----\r\nMerci, <>.'); +INSERT INTO `letter` VALUES ('rma', 'RMA', 'Bon de retour', 'Bon de retour', '<> +<> +<> +<> +<> +<> + +Certains items de la commande seront retournés : +Numéro de commande +<> (<>) (<> commandé(s)) ($<> chacun)' +); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 9039766..ea82cc6 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -8074,6 +8074,25 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do(q{ +INSERT INTO `letter` VALUES ('rma', 'RMA', 'Return merchandise authorization', 'Return merchandise authorization', '<> +<> +<> +<> +<> +<> + +Some items in this order will be returned : +Order number +<> (<>) (<> ordered) ($<> each)' +); + }); + print "Upgrade to $DBversion done (Add the RMA letter)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css index 685ebef..32488e9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -1984,6 +1984,18 @@ fieldset.rows+h3 {clear:both;padding-top:.5em;} color : #cc0000; } +td.expanded { + background : transparent url("../../img/collapse.gif") 0 6px no-repeat; + cursor : pointer; + padding-left : 12px; +} + +td.collapsed { + background : transparent url("../../img/expand.gif") 0 6px no-repeat; + cursor : pointer; + padding-left : 12px; +} + div.pager { background-color : #E8E8E8; border : 1px solid #BCBCBC; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc index 439118d..79e8ec5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc @@ -1,5 +1,6 @@
  • Late orders
  • +
  • Return order
  • [% IF ( suggestion ) %]
  • Suggestions
  • [% ELSE %][% END %]
  • Invoices
  • [% IF ( CAN_user_acquisition_budget_manage ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/returnorder.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/returnorder.tt new file mode 100644 index 0000000..2ee4919 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/returnorder.tt @@ -0,0 +1,108 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › Return merchandise authorization +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + + +
    + +
    +
    +
    + +

    Return merchandise authorization

    +
    + +
    + +

    + + +

    +
    + +[% IF ( suppliers ) %] +
    + + + + + + + + + [% FOREACH supplier IN suppliers %] + [% FOREACH loop_baske IN supplier.loop_basket %] + + + + + + + [% FOREACH orders_item IN loop_baske.orders_items %] + + + + + [% END %] + [% END %] + [% END %] +
    Basket (#)ItemsCreated byDate
    [% loop_baske.total %] + [% loop_baske.firstname %] + [% loop_baske.surname %] + [% loop_baske.creationdate %]
    +
    + Output +
      + [% IF ( letters ) %] +
    1. + + + + +
    2. + [% END %] +
    3. + + + + + + [% CGIextChoice %] + [% CGIsepChoice %] +
    4. +
    +
    +
    + + + +
    +
    +[% ELSE %]

    No baskets for this vendor.

    +[% END %] +
    +
    +
    +
    +[% INCLUDE 'acquisitions-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt index c414787..0858b5d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt @@ -279,6 +279,11 @@ $(document).ready(function() { [% ELSE %] [% END %] + [% IF ( rma ) %] + + [% ELSE %] + + [% END %] [% IF ( serial ) %] [% ELSE %] diff --git a/tools/letter.pl b/tools/letter.pl index 7582e66..e62d465 100755 --- a/tools/letter.pl +++ b/tools/letter.pl @@ -176,7 +176,7 @@ sub add_form { if ($module eq 'reserves') { push @{$field_selection}, add_fields('borrowers', 'reserves', 'biblio', 'items'); } - elsif ($module eq 'claimacquisition') { + elsif ($module eq 'claimacquisition' || $module eq 'rma') { push @{$field_selection}, add_fields('aqbooksellers', 'aqorders', 'biblio', 'biblioitems'); } elsif ($module eq 'claimissues') { -- 1.7.2.5