Bugzilla – Attachment 16629 Details for
Bug 7736
Edifact QUOTE and ORDER functionality
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 7736 - Edifact QUOTE and ORDER functionality
0001-Bug-7736-EDI-Edifact-quote-and-order-functionality.patch (text/plain), 84.26 KB, created by
Fridolin Somers
on 2013-03-21 13:49:03 UTC
(
hide
)
Description:
Bug 7736 - Edifact QUOTE and ORDER functionality
Filename:
MIME Type:
Creator:
Fridolin Somers
Created:
2013-03-21 13:49:03 UTC
Size:
84.26 KB
patch
obsolete
>From ace4d92807503b5c1dd99975098191c79e5e5d58 Mon Sep 17 00:00:00 2001 >From: Zeno Tajoli <tajoli@cilea.it> >Date: Wed, 20 Mar 2013 15:43:54 +0100 >Subject: [PATCH] Bug 7736: EDI Edifact quote and order functionality > >This is a patch brining together the original >work by Mark Gavillet and the subsequent patches >by Mark, Martin Renvoize and myself > >It contains the code as currently runnng in >production > >In addition I've added updatedatebase entries to >installer and replaced the hardcoded currency with >a currency extraction. As the db currently does not >force the standard codes we check if that is 3 uppercase >ascii characters before using it. > >Elliott Davis: >Added unit test for EDI > >Zeno Tajoli: >Rebased on last master git tree. >I have change only the file installer/data/mysql/sysprefs.sql >--- > C4/EDI.pm | 1086 ++++++++++++++++++++ > acqui/basket.pl | 12 + > admin/edi-accounts.pl | 72 ++ > admin/edi-edit.pl | 75 ++ > installer/data/mysql/atomicupdate/edifact.sql | 27 + > .../data/mysql/de-DE/mandatory/userpermissions.sql | 1 + > .../data/mysql/en/mandatory/userpermissions.sql | 1 + > .../data/mysql/es-ES/mandatory/userpermissions.sql | 1 + > .../mysql/fr-FR/1-Obligatoire/userpermissions.sql | 1 + > .../data/mysql/it-IT/necessari/userpermissions.sql | 1 + > installer/data/mysql/kohastructure.sql | 29 + > .../mysql/nb-NO/1-Obligatorisk/userpermissions.sql | 1 + > .../data/mysql/pl-PL/mandatory/userpermissions.sql | 1 + > .../ru-RU/mandatory/permissions_and_user_flags.sql | 1 + > installer/data/mysql/sysprefs.sql | 1 + > .../uk-UA/mandatory/permissions_and_user_flags.sql | 1 + > installer/data/mysql/updatedatabase.pl | 45 + > .../intranet-tmpl/prog/en/includes/admin-menu.inc | 1 + > .../intranet-tmpl/prog/en/includes/tools-menu.inc | 5 +- > .../intranet-tmpl/prog/en/modules/acqui/basket.tt | 11 +- > .../prog/en/modules/admin/admin-home.tt | 2 + > .../prog/en/modules/admin/edi-accounts.tt | 46 + > .../prog/en/modules/admin/edi-edit.tt | 102 ++ > .../intranet-tmpl/prog/en/modules/tools/edi.tt | 63 ++ > .../prog/en/modules/tools/tools-home.tt | 4 + > misc/cronjobs/clean_edifiles.pl | 43 + > misc/cronjobs/edifact_order_ftp_transfer.pl | 127 +++ > misc/cronjobs/send_queued_edi_orders.pl | 26 + > misc/edi_files/README.txt | 3 + > t/Calendar.t | 1 - > t/EDI.t | 85 ++ > tools/edi.pl | 43 + > 32 files changed, 1915 insertions(+), 3 deletions(-) > create mode 100644 C4/EDI.pm > create mode 100755 admin/edi-accounts.pl > create mode 100755 admin/edi-edit.pl > create mode 100644 installer/data/mysql/atomicupdate/edifact.sql > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-accounts.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-edit.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/edi.tt > create mode 100755 misc/cronjobs/clean_edifiles.pl > create mode 100755 misc/cronjobs/edifact_order_ftp_transfer.pl > create mode 100755 misc/cronjobs/send_queued_edi_orders.pl > create mode 100644 misc/edi_files/README.txt > create mode 100644 t/EDI.t > create mode 100755 tools/edi.pl > >diff --git a/C4/EDI.pm b/C4/EDI.pm >new file mode 100644 >index 0000000..0223243 >--- /dev/null >+++ b/C4/EDI.pm >@@ -0,0 +1,1086 @@ >+package C4::EDI; >+ >+# Copyright 2011 Mark Gavillet >+# >+# 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. >+ >+use strict; >+use warnings; >+use C4::Context; >+use C4::Acquisition; >+use C4::Budgets qw( GetCurrency ); >+use Net::FTP; >+use Business::Edifact::Interchange; >+use C4::Biblio; >+use C4::Items; >+use Business::ISBN; >+use Carp; >+use parent qw(Exporter); >+ >+our $VERSION = 3.09.00.53; >+our @EXPORT_OK = qw( >+ GetEDIAccounts >+ GetEDIAccountDetails >+ CreateEDIDetails >+ UpdateEDIDetails >+ LogEDIFactOrder >+ LogEDIFactQuote >+ DeleteEDIDetails >+ GetVendorList >+ GetEDIfactMessageList >+ GetEDIFTPAccounts >+ LogEDITransaction >+ GetVendorSAN >+ CreateEDIOrder >+ SendEDIOrder >+ SendQueuedEDIOrders >+ ParseEDIQuote >+ GetDiscountedPrice >+ GetBudgetID >+ CheckOrderItemExists >+ GetBranchCode >+ string35escape >+ GetOrderItemInfo >+ CheckVendorFTPAccountExists >+); >+ >+=head1 NAME >+ >+C4::EDI - Perl Module containing functions for Vendor EDI accounts and EDIfact messages >+ >+=head1 VERSION >+ >+Version 0.01 >+ >+=head1 SYNOPSIS >+ >+use C4::EDI; >+ >+=head1 DESCRIPTION >+ >+This module contains routines for adding, modifying and deleting EDI account details for vendors, interacting with vendor FTP sites to send/retrieve quote and order messages, formatting EDIfact orders, and parsing EDIfact quotes to baskets >+ >+=head2 GetVendorList >+ >+Returns a list of vendors from aqbooksellers to populate drop down select menu >+ >+=cut >+ >+sub GetVendorList { >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ $sth = >+ $dbh->prepare('select id, name from aqbooksellers order by name asc'); >+ $sth->execute(); >+ my $vendorlist = $sth->fetchall_arrayref( {} ); >+ return $vendorlist; >+} >+ >+=head2 CreateEDIDetails >+ >+Inserts a new EDI vendor FTP account >+ >+=cut >+ >+sub CreateEDIDetails { >+ my ( $provider, $description, $host, $user, $pass, $in_dir, $san ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ if ($provider) { >+ $sth = $dbh->prepare( >+'insert into vendor_edi_accounts (description, host, username, password, provider, in_dir, san) values (?,?,?,?,?,?,?)' >+ ); >+ $sth->execute( $description, $host, $user, >+ $pass, $provider, $in_dir, $san ); >+ } >+ return; >+} >+ >+=head2 GetEDIAccounts >+ >+Returns all vendor FTP accounts >+ >+=cut >+ >+sub GetEDIAccounts { >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ $sth = $dbh->prepare( >+'select vendor_edi_accounts.id, aqbooksellers.id as providerid, aqbooksellers.name as vendor, vendor_edi_accounts.description, vendor_edi_accounts.last_activity from vendor_edi_accounts inner join aqbooksellers on vendor_edi_accounts.provider = aqbooksellers.id order by aqbooksellers.name asc' >+ ); >+ $sth->execute(); >+ my $ediaccounts = $sth->fetchall_arrayref( {} ); >+ return $ediaccounts; >+} >+ >+=head2 DeleteEDIDetails >+ >+Remove a vendor's FTP account >+ >+=cut >+ >+sub DeleteEDIDetails { >+ my ($id) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ if ($id) { >+ $sth = $dbh->prepare('delete from vendor_edi_accounts where id=?'); >+ $sth->execute($id); >+ } >+ return; >+} >+ >+=head2 UpdateEDIDetails >+ >+Update a vendor's FTP account >+ >+=cut >+ >+sub UpdateEDIDetails { >+ my ( $editid, $description, $host, $user, $pass, $provider, $in_dir, $san ) >+ = @_; >+ my $dbh = C4::Context->dbh; >+ if ($editid) { >+ my $sth = $dbh->prepare( >+'update vendor_edi_accounts set description=?, host=?, username=?, password=?, provider=?, in_dir=?, san=? where id=?' >+ ); >+ $sth->execute( $description, $host, $user, $pass, $provider, $in_dir, >+ $san, $editid ); >+ } >+ return; >+} >+ >+=head2 LogEDIFactOrder >+ >+Updates or inserts to the edifact_messages table when processing an order and assigns a status and basket number >+ >+=cut >+ >+sub LogEDIFactOrder { >+ my ( $provider, $status, $basketno ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $key; >+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); >+ my $date_sent = sprintf '%4d-%02d-%0d', $year + 1900, $mon + 1, $mday; >+ my $sth = $dbh->prepare( >+'select edifact_messages.id from edifact_messages where basketno=? and provider=?' >+ ); >+ $sth->execute( $basketno, $provider ); >+ >+ while ( my @row = $sth->fetchrow_array() ) { >+ $key = $row[0]; >+ } >+ if ($key) { >+ $sth = $dbh->prepare( >+'update edifact_messages set date_sent=?, status=? where edifact_messages.id=?' >+ ); >+ $sth->execute( $date_sent, $status, $key ); >+ } >+ else { >+ $sth = $dbh->prepare( >+'insert into edifact_messages (message_type,date_sent,provider,status,basketno) values (?,?,?,?,?)' >+ ); >+ $sth->execute( 'ORDER', $date_sent, $provider, $status, $basketno ); >+ } >+ return; >+} >+ >+=head2 LogEDIFactOrder >+ >+Updates or inserts to the edifact_messages table when processing a quote and assigns a status and basket number >+ >+=cut >+ >+sub LogEDIFactQuote { >+ my ( $provider, $status, $basketno, $key ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); >+ my $date_sent = sprintf '%4d-%02d-%0d', $year + 1900, $mon + 1, $mday; >+ if ( $key != 0 ) { >+ $sth = $dbh->prepare( >+'update edifact_messages set date_sent=?, status=?, basketno=? where edifact_messages.id=?' >+ ); >+ $sth->execute( $date_sent, $status, $basketno, $key ); >+ } >+ else { >+ $sth = $dbh->prepare( >+'insert into edifact_messages (message_type,date_sent,provider,status,basketno) values (?,?,?,?,?)' >+ ); >+ $sth->execute( 'QUOTE', $date_sent, $provider, $status, $basketno ); >+ $key = >+ $dbh->last_insert_id( undef, undef, qw(edifact_messages id), undef ); >+ } >+ return $key; >+} >+ >+=head2 GetEDIAccountDetails >+ >+Returns FTP account details for a given vendor >+ >+=cut >+ >+sub GetEDIAccountDetails { >+ my ($id) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ if ($id) { >+ $sth = $dbh->prepare('select * from vendor_edi_accounts where id=?'); >+ $sth->execute($id); >+ return $sth->fetchrow_hashref; >+ } >+ return; >+} >+ >+=head2 GetEDIfactMessageList >+ >+Returns a list of edifact_messages that have been processed, including the type (quote/order) and status >+ >+=cut >+ >+sub GetEDIfactMessageList { >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ $sth = $dbh->prepare( >+q|select edifact_messages.id, edifact_messages.message_type, DATE_FORMAT(edifact_messages.date_sent,'%d/%m/%Y') as date_sent, aqbooksellers.id as providerid, aqbooksellers.name as providername, edifact_messages.status, edifact_messages.basketno from edifact_messages inner join aqbooksellers on edifact_messages.provider = aqbooksellers.id order by edifact_messages.date_sent desc, edifact_messages.id desc| >+ ); >+ $sth->execute(); >+ return $sth->fetchall_arrayref( {} ); >+} >+ >+=head2 GetEDIFTPAccounts >+ >+Returns all vendor FTP accounts. Used when retrieving quotes messages overnight >+ >+=cut >+ >+sub GetEDIFTPAccounts { >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare( >+'select id, host, username, password, provider, in_dir from vendor_edi_accounts order by id asc' >+ ); >+ $sth->execute(); >+ return $sth->fetchall_arrayref( {} ); >+} >+ >+=head2 LogEDITransaction >+ >+Updates the timestamp for a given vendor FTP account whenever there is activity >+ >+=cut >+ >+sub LogEDITransaction { >+ my $id = shift; >+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); >+ my $datestamp = sprintf '%4d/%02d/%0d', $year + 1900, $mon + 1, $mday; >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare( >+ 'update vendor_edi_accounts set last_activity=? where id=?'); >+ $sth->execute( $datestamp, $id ); >+ return; >+} >+ >+=head2 GetVendorSAN >+ >+Returns the stored SAN number for a given vendor >+ >+=cut >+ >+sub GetVendorSAN { >+ my $booksellerid = shift; >+ my $dbh = C4::Context->dbh; >+ my $san; >+ my $sth = >+ $dbh->prepare('select san from vendor_edi_accounts where provider=?'); >+ $sth->execute($booksellerid); >+ while ( my @result = $sth->fetchrow_array() ) { >+ $san = $result[0]; >+ } >+ return $san; >+} >+ >+=head2 CreateEDIOrder >+ >+Formats an EDIfact order message from a given basket and stores as a file on the server >+ >+=cut >+ >+sub CreateEDIOrder { >+ my ( $basketno, $booksellerid ) = @_; >+ my @datetime = localtime(time); >+ my $longyear = $datetime[5] + 1900; >+ my $shortyear = sprintf '%02d', $datetime[5] - 100; >+ my $date = sprintf '%02d%02d', $datetime[4] + 1, $datetime[3]; >+ my $hourmin = sprintf '%02d%02d', $datetime[2], $datetime[1]; >+ my $year = $datetime[5] - 100; >+ my $month = sprintf '%02d', $datetime[4] + 1; >+ my $linecount = 0; >+ my $filename = "ediorder_$basketno.CEP"; >+ my $exchange = int( rand(99999999999999) ); >+ my $ref = int( rand(99999999999999) ); >+ my $san = GetVendorSAN($booksellerid); >+ my $message_type = GetMessageType($basketno); >+ my $output_file = C4::Context->config('intranetdir'); >+ >+ # Currencies must be the 3 upper case alpha codes >+ # Koha soes not currently enforce this >+ my $default_currency = GetCurrency(); >+ if ( $default_currency->{currency} =~ m/^[[:upper:]]{3}$/ ) { >+ $default_currency = $default_currency->{currency}; >+ } >+ else { >+ $default_currency = 'GBP'; >+ } >+ >+ $output_file .= "/misc/edi_files/$filename"; >+ >+ open my $fh, '>', $output_file >+ or croak "Unable to create $output_file : $!"; >+ >+ print $fh q{UNA:+.? '}; # print opening header >+ print $fh q{UNB+UNOC:2+} >+ . C4::Context->preference("EDIfactEAN") >+ . ":14+$san:31B+$shortyear$date:$hourmin+" >+ . $exchange >+ . "++ORDERS+++EANCOM'" >+ ; # print identifying EANs/SANs, date/time, exchange reference number >+ print $fh 'UNH+' . $ref >+ . q{+ORDERS:D:96A:UN:EAN008'}; # print message reference number >+ >+ if ( $message_type eq 'QUOTE' ) { >+ print $fh 'BGM+22V+' >+ . $basketno >+ . q{+9'}; # print order number and quote confirmation ref >+ } >+ else { >+ print $fh 'BGM+220+', $basketno, "+9'"; # print order number >+ } >+ print $fh "DTM+137:$longyear$date:102'"; # print date of message >+ print $fh "NAD+BY+" >+ . C4::Context->preference("EDIfactEAN") >+ . "::9'"; # print buyer EAN >+ print $fh 'NAD+SU+', $san, "::31B'"; # print vendor SAN >+ print $fh 'NAD+SU+', $booksellerid, "::92'"; # print internal ID >+ >+ # get items from basket >+ my @results = GetOrders($basketno); >+ foreach my $item (@results) { >+ $linecount++; >+ my $price; >+ my $title = string35escape( escape( $item->{title} ) ); >+ my $author = string35escape( escape( $item->{author} ) ); >+ my $publisher = string35escape( escape( $item->{publishercode} ) ); >+ $price = sprintf '%.2f', $item->{listprice}; >+ my $isbn; >+ if ( length( $item->{isbn} ) == 10 >+ || substr( $item->{isbn}, 0, 3 ) eq '978' >+ || index( $item->{isbn}, '|' ) != -1 ) >+ { >+ $isbn = cleanisbn( $item->{isbn} ); >+ $isbn = Business::ISBN->new($isbn); >+ if ($isbn) { >+ if ( $isbn->is_valid ) { >+ $isbn = ( $isbn->as_isbn13 )->isbn; >+ } >+ else { >+ $isbn = '0'; >+ } >+ } >+ else { >+ $isbn = 0; >+ } >+ } >+ else { >+ $isbn = $item->{isbn}; >+ } >+ my $copyrightdate = escape( $item->{publicationyear} ); >+ my $quantity = escape( $item->{quantity} ); >+ my $ordernumber = escape( $item->{ordernumber} ); >+ my $notes; >+ if ( $item->{notes} ) { >+ $notes = $item->{notes}; >+ $notes =~ s/[\r\n]+//g; >+ $notes = string35escape( escape($notes) ); >+ } >+ >+ my ( $branchcode, $callnumber, $itype, $lsqccode, $fund ) = >+ GetOrderItemInfo( $item->{'ordernumber'} ); >+ $callnumber = escape($callnumber); >+ >+ print $fh "LIN+$linecount++" . $isbn . ":EN'"; # line number, isbn >+ print $fh "PIA+5+" . $isbn >+ . ":IB'"; # isbn as main product identification >+ print $fh "IMD+L+050+:::$title'"; # title >+ print $fh "IMD+L+009+:::$author'"; # full name of author >+ print $fh "IMD+L+109+:::$publisher'"; # publisher >+ print $fh "IMD+L+170+:::$copyrightdate'"; # date of publication >+ print $fh "IMD+L+220+:::O'"; # binding (e.g. PB) (O if not specified) >+ if ( $callnumber ne '' ) { >+ print $fh "IMD+L+230+:::$callnumber'"; # shelfmark >+ } >+ print $fh "QTY+21:$quantity'"; # quantity >+ if ( $message_type ne 'QUOTE' && $quantity > 1 ) { >+ print $fh "GIR+001+$quantity:LQT+$branchcode:LLO+$fund:LFN+" >+ ; # branchcode, fund code >+ } >+ else { >+ print $fh >+ "GIR+001+$branchcode:LLO+$fund:LFN+"; # branchcode, fund code >+ } >+ if ( $callnumber ne '' ) { >+ print $fh "$callnumber:LCL+"; # shelfmark >+ } >+ print $fh $itype . ":LST+$lsqccode:LSQ'"; # stock category, sequence >+ if ($notes) { >+ print $fh "FTX+LIN+++:::$notes'"; >+ } >+ ###REQUEST ORDERS TO REVISIT >+#if ($message_type ne 'QUOTE') >+#{ >+# print $fh "FTX+LIN++$linecount:10B:28'"; # freetext ** used for request orders to denote priority (to revisit) >+#} >+ print $fh "PRI+AAB:$price'"; # price per item >+ my $currency = >+ $item->{currency} =~ m/^[[:upper:]]{3}$/ >+ ? $item->{currency} >+ : $default_currency; >+ print $fh "CUX+2:$currency:9'"; # currency (e.g. GBP, EUR, USD) >+ print $fh "RFF+LI:$ordernumber'"; # Local order number >+ if ( $message_type eq 'QUOTE' ) { >+ print $fh "RFF+QLI:" >+ . $item->{booksellerinvoicenumber} >+ . q{'}; # If QUOTE confirmation, include booksellerinvoicenumber >+ } >+ } >+ print $fh "UNS+S'"; # print summary section header >+ print $fh "CNT+2:$linecount'"; # print number of line items in the message >+ my $segments = ( ( $linecount * 13 ) + 9 ); >+ print $fh "UNT+$segments+" >+ . $ref . "'" >+ ; # No. of segments in message (UNH+UNT elements included, UNA, UNB, UNZ excluded) >+ # Message ref number >+ print $fh "UNZ+1+" . $exchange . "'\n"; # Exchange ref number >+ >+ close $fh; >+ >+ LogEDIFactOrder( $booksellerid, 'Queued', $basketno ); >+ >+ return $filename; >+ >+} >+ >+sub GetMessageType { >+ my $basketno = shift; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ my $message_type; >+ my @row; >+ $sth = $dbh->prepare( >+ 'select message_type from edifact_messages where basketno=?'); >+ $sth->execute($basketno); >+ while ( @row = $sth->fetchrow_array() ) { >+ $message_type = $row[0]; >+ } >+ return $message_type; >+} >+ >+sub cleanisbn { >+ my $isbn = shift; >+ if ($isbn) { >+ my $i = index( $isbn, '(' ); >+ if ( $i > 1 ) { >+ $isbn = substr( $isbn, 0, ( $i - 1 ) ); >+ } >+ if ( $isbn =~ /\|/ ) { >+ my @isbns = split( /\|/, $isbn ); >+ $isbn = $isbns[0]; >+ } >+ $isbn = escape($isbn); >+ $isbn =~ s/^\s+//; >+ $isbn =~ s/\s+$//; >+ return $isbn; >+ } >+ return; >+} >+ >+sub escape { >+ my $string = shift; >+ if ($string) { >+ $string =~ s/\?/\?\?/g; >+ $string =~ s/\'/\?\'/g; >+ $string =~ s/\:/\?\:/g; >+ $string =~ s/\+/\?\+/g; >+ return $string; >+ } >+ return; >+} >+ >+=head2 GetBranchCode >+ >+Return branchcode for an order when formatting an EDIfact order message >+ >+=cut >+ >+sub GetBranchCode { >+ my $biblioitemnumber = shift; >+ my $dbh = C4::Context->dbh; >+ my $branchcode; >+ my @row; >+ my $sth = >+ $dbh->prepare("select homebranch from items where biblioitemnumber=?"); >+ $sth->execute($biblioitemnumber); >+ while ( @row = $sth->fetchrow_array() ) { >+ $branchcode = $row[0]; >+ } >+ return $branchcode; >+} >+ >+=head2 SendEDIOrder >+ >+Transfers an EDIfact order message to the relevant vendor's FTP site >+ >+=cut >+ >+sub SendEDIOrder { >+ my ( $basketno, $booksellerid ) = @_; >+ my $newerr; >+ my $result; >+ >+ # check edi order file exists >+ my $edi_files = C4::Context->config('intranetdir'); >+ $edi_files .= '/misc/edi_files/'; >+ if ( -e "${edi_files}ediorder_$basketno.CEP" ) { >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ $sth = $dbh->prepare( >+"select id, host, username, password, provider, in_dir from vendor_edi_accounts where provider=?" >+ ); >+ $sth->execute($booksellerid); >+ my $ftpaccount = $sth->fetchrow_hashref; >+ >+ #check vendor edi account exists >+ if ($ftpaccount) { >+ >+ # connect to ftp account >+ my $ftp = Net::FTP->new( $ftpaccount->{host}, Timeout => 10 ) >+ or $newerr = 1; >+ if ( !$newerr ) { >+ $newerr = 0; >+ >+ # login >+ $ftp->login( $ftpaccount->{username}, $ftpaccount->{password} ) >+ or $newerr = 1; >+ $ftp->quit if $newerr; >+ if ( !$newerr ) { >+ >+ # cd to directory >+ $ftp->cwd( $ftpaccount->{in_dir} ) or $newerr = 1; >+ $ftp->quit if $newerr; >+ >+ # put file >+ if ( !$newerr ) { >+ $newerr = 0; >+ $ftp->put("${edi_files}ediorder_$basketno.CEP") >+ or $newerr = 1; >+ $ftp->quit if $newerr; >+ if ( !$newerr ) { >+ $result = >+"File: ediorder_$basketno.CEP transferred successfully"; >+ $ftp->quit; >+ unlink "${edi_files}ediorder_$basketno.CEP"; >+ LogEDITransaction( $ftpaccount->{id} ); >+ LogEDIFactOrder( $booksellerid, 'Sent', $basketno ); >+ return $result; >+ } >+ else { >+ $result = >+"Could not transfer the file ${edi_files}ediorder_$basketno.CEP to $ftpaccount->{host}: $_"; >+ FTPError($result); >+ LogEDIFactOrder( $booksellerid, 'Failed', >+ $basketno ); >+ return $result; >+ } >+ } >+ else { >+ $result = >+"Cannot get remote directory ($ftpaccount->{in_dir}) on $ftpaccount->{host}"; >+ FTPError($result); >+ LogEDIFactOrder( $booksellerid, 'Failed', $basketno ); >+ return $result; >+ } >+ } >+ else { >+ $result = "Cannot log in to $ftpaccount->{host}: $!"; >+ FTPError($result); >+ LogEDIFactOrder( $booksellerid, 'Failed', $basketno ); >+ return $result; >+ } >+ } >+ else { >+ $result = >+ "Cannot make an FTP connection to $ftpaccount->{host}: $!"; >+ FTPError($result); >+ LogEDIFactOrder( $booksellerid, 'Failed', $basketno ); >+ return $result; >+ } >+ } >+ else { >+ $result = >+"Vendor ID: $booksellerid does not have a current EDIfact FTP account"; >+ FTPError($result); >+ LogEDIFactOrder( $booksellerid, 'Failed', $basketno ); >+ return $result; >+ } >+ } >+ else { >+ $result = 'There is no EDIfact order for this basket'; >+ return $result; >+ } >+} >+ >+sub FTPError { >+ my $error = shift; >+ my $log_file = C4::Context->config('intranetdir'); >+ $log_file .= '/misc/edi_files/edi_ftp_error.log'; >+ open my $log_fh, '>>', $log_file >+ or croak "Could not open $log_file: $!"; >+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); >+ printf $log_fh "%4d-%02d-%02d %02d:%02d:%02d\n-----\n", >+ $year + 1900, $mon + 1, $mday, $hour, $min, $sec; >+ print $log_fh "$error\n\n"; >+ close $log_fh; >+ return; >+} >+ >+=head2 SendQueuedEDIOrders >+ >+Sends all EDIfact orders that are held in the Queued >+ >+=cut >+ >+sub SendQueuedEDIOrders { >+ my $dbh = C4::Context->dbh; >+ my @orders; >+ my $sth = $dbh->prepare( >+ q|select basketno, provider from edifact_messages where status='Queued'| >+ ); >+ $sth->execute(); >+ while ( @orders = $sth->fetchrow_array() ) { >+ SendEDIOrder( $orders[0], $orders[1] ); >+ } >+ return; >+} >+ >+=head2 ParseEDIQuote >+ >+Uses Business::Edifact::Interchange to parse a stored EDIfact quote message, creates basket, biblios, biblioitems, and items >+ >+=cut >+ >+sub ParseEDIQuote { >+ my ( $filename, $booksellerid ) = @_; >+ my $basketno; >+ my $ParseEDIQuoteItem; >+ >+ my $edi = Business::Edifact::Interchange->new; >+ my $path = C4::Context->config('intranetdir'); >+ $path .= '/misc/edi_files/'; >+ $edi->parse_file("$path$filename"); >+ my $messages = $edi->messages(); >+ my $msg_cnt = @{$messages}; >+ >+ # create default edifact_messages entry >+ my $messagekey = LogEDIFactQuote( $booksellerid, 'Failed', 0, 0 ); >+ >+ #create basket >+ if ( $msg_cnt > 0 && $booksellerid ) { >+ $basketno = NewBasket( $booksellerid, 0, $filename, q{}, q{}, q{} ); >+ } >+ >+ $ParseEDIQuoteItem = sub { >+ my ( $item, $gir, $bookseller_id ) = @_; >+ my $relnos = $item->{related_numbers}; >+ my $author = $item->author_surname . ", " . $item->author_firstname; >+ >+ my $ecost = >+ GetDiscountedPrice( $bookseller_id, $item->{price}->{price} ); >+ >+ my $ftxlin; >+ my $ftxlno; >+ if ( $item->{free_text}->{qualifier} eq 'LIN' ) { >+ $ftxlin = $item->{free_text}->{text}; >+ } >+ if ( $item->{free_text}->{qualifier} eq 'LNO' ) { >+ $ftxlno = $item->{free_text}->{text}; >+ } >+ >+ my ( $llo, $lfn, $lsq, $lst, $lfs, $lcl, $id ); >+ my $relcount = 0; >+ foreach my $rel ( @{$relnos} ) { >+ if ( $rel->{id} == ( $gir + 1 ) ) { >+ if ( $item->{related_numbers}->[$relcount]->{LLO}->[0] ) { >+ $llo = $item->{related_numbers}->[$relcount]->{LLO}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{LFN}->[0] ) { >+ $lfn = $item->{related_numbers}->[$relcount]->{LFN}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{LSQ}->[0] ) { >+ $lsq = $item->{related_numbers}->[$relcount]->{LSQ}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{LST}->[0] ) { >+ $lst = $item->{related_numbers}->[$relcount]->{LST}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{LFS}->[0] ) { >+ $lfs = $item->{related_numbers}->[$relcount]->{LFS}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{LCL}->[0] ) { >+ $lcl = $item->{related_numbers}->[$relcount]->{LCL}->[0]; >+ } >+ if ( $item->{related_numbers}->[$relcount]->{id} ) { >+ $id = $item->{related_numbers}->[$relcount]->{id}; >+ } >+ } >+ $relcount++; >+ } >+ >+ my $lclnote; >+ if ( !$lst ) { >+ $lst = uc( $item->item_format ); >+ } >+ if ( !$lcl ) { >+ $lcl = $item->shelfmark; >+ } >+ else { >+ ( $lcl, $lclnote ) = DawsonsLCL($lcl); >+ } >+ if ($lfs) { >+ $lcl .= " $lfs"; >+ } >+ >+ my $budget_id = GetBudgetID($lfn); >+ >+ #Uncomment section below to define a default budget_id if there is no match >+ #if (!defined $budget_id) >+ #{ >+ # $budget_id=0; >+ #} >+ >+ # create biblio record >+ my $bib_record = TransformKohaToMarc( >+ { >+ 'biblio.title' => $item->title, >+ 'biblio.author' => $author ? $author : q{}, >+ 'biblio.seriestitle' => q{}, >+ 'biblioitems.isbn' => $item->{item_number} >+ ? $item->{item_number} >+ : q{}, >+ 'biblioitems.publishercode' => $item->publisher >+ ? $item->publisher >+ : q{}, >+ 'biblioitems.publicationyear' => $item->date_of_publication >+ ? $item->date_of_publication >+ : q{}, >+ 'biblio.copyrightdate' => $item->date_of_publication >+ ? $item->date_of_publication >+ : q{}, >+ 'biblioitems.itemtype' => uc( $item->item_format ), >+ 'biblioitems.cn_source' => 'ddc', >+ 'items.cn_source' => 'ddc', >+ 'items.notforloan' => -1, >+ >+ #"items.ccode" => $lsq, >+ 'items.location' => $lsq, >+ 'items.homebranch' => $llo, >+ 'items.holdingbranch' => $llo, >+ 'items.booksellerid' => $bookseller_id, >+ 'items.price' => $item->{price}->{price}, >+ 'items.replacementprice' => $item->{price}->{price}, >+ 'items.itemcallnumber' => $lcl, >+ 'items.itype' => $lst, >+ 'items.cn_sort' => q{}, >+ } >+ ); >+ >+ #check if item already exists in catalogue >+ my $biblionumber; >+ my $bibitemnumber; >+ ( $biblionumber, $bibitemnumber ) = >+ CheckOrderItemExists( $item->{item_number} ); >+ >+ if ( !defined $biblionumber ) { >+ >+ # create the record in catalogue, with framework '' >+ ( $biblionumber, $bibitemnumber ) = AddBiblio( $bib_record, q{} ); >+ } >+ >+ my $ordernote; >+ if ($lclnote) { >+ $ordernote = $lclnote; >+ } >+ if ($ftxlno) { >+ $ordernote = $ftxlno; >+ } >+ if ($ftxlin) { >+ $ordernote = $ftxlin; >+ } >+ >+ my %orderinfo = ( >+ basketno => $basketno, >+ ordernumber => q{}, >+ subscription => 'no', >+ uncertainprice => 0, >+ biblionumber => $biblionumber, >+ title => $item->title, >+ quantity => 1, >+ biblioitemnumber => $bibitemnumber, >+ rrp => $item->{price}->{price}, >+ ecost => $ecost, >+ sort1 => q{}, >+ sort2 => q{}, >+ booksellerinvoicenumber => $item->{item_reference}[0][1], >+ listprice => $item->{price}->{price}, >+ branchcode => $llo, >+ budget_id => $budget_id, >+ notes => $ordernote, >+ ); >+ >+ my $orderinfo = \%orderinfo; >+ >+ my ( $retbasketno, $ordernumber ) = NewOrder($orderinfo); >+ >+ # now, add items if applicable >+ if ( C4::Context->preference('AcqCreateItem') eq 'ordering' ) { >+ my $itemnumber; >+ ( $biblionumber, $bibitemnumber, $itemnumber ) = >+ AddItemFromMarc( $bib_record, $biblionumber ); >+ NewOrderItem( $itemnumber, $ordernumber ); >+ } >+ }; >+ >+ for ( my $count = 0 ; $count < $msg_cnt ; $count++ ) { >+ my $items = $messages->[$count]->items(); >+ my $ref_num = $messages->[$count]->{ref_num}; >+ >+ foreach my $item ( @{$items} ) { >+ for ( my $i = 0 ; $i < $item->{quantity} ; $i++ ) { >+ &$ParseEDIQuoteItem( $item, $i, $booksellerid, $basketno ); >+ } >+ } >+ } >+ >+ # update edifact_messages entry >+ LogEDIFactQuote( $booksellerid, 'Received', $basketno, $messagekey ); >+ return 1; >+ >+} >+ >+=head2 GetDiscountedPrice >+ >+Returns the discounted price for an order based on the discount rate for a given vendor >+ >+=cut >+ >+sub GetDiscountedPrice { >+ my ( $booksellerid, $price ) = @_; >+ my $dbh = C4::Context->dbh; >+ my $sth; >+ my @discount; >+ my $ecost; >+ my $percentage; >+ $sth = $dbh->prepare(q|select discount from aqbooksellers where id=?|); >+ $sth->execute($booksellerid); >+ >+ while ( @discount = $sth->fetchrow_array() ) { >+ $percentage = $discount[0]; >+ } >+ $ecost = ( $price - ( ( $percentage * $price ) / 100 ) ); >+ return $ecost; >+} >+ >+=head2 DawsonsLCL >+ >+Checks for a call number encased by asterisks. If found, returns call number as $lcl and string with >+asterisks as $lclnote to go into FTX field enabling spine label creation by Dawsons bookseller >+ >+=cut >+ >+sub DawsonsLCL { >+ my $lcl = shift; >+ my $lclnote; >+ my $f = index( $lcl, '*' ); >+ my $l = rindex( $lcl, '*' ); >+ if ( $f == 0 && $l == ( length($lcl) - 1 ) ) { >+ $lclnote = $lcl; >+ $lcl =~ s/\*//g; >+ } >+ return ( $lcl, $lclnote ); >+} >+ >+=head2 GetBudgetID >+ >+Returns the budget_id for a given budget_code >+ >+=cut >+ >+sub GetBudgetID { >+ my $fundcode = shift; >+ my $dbh = C4::Context->dbh; >+ my @funds; >+ my $ecost; >+ my $budget_id; >+ my $sth = >+ $dbh->prepare('select budget_id from aqbudgets where budget_code=?'); >+ $sth->execute($fundcode); >+ >+ while ( @funds = $sth->fetchrow_array() ) { >+ $budget_id = $funds[0]; >+ } >+ return $budget_id; >+} >+ >+=head2 CheckOrderItemExists >+ >+Checks to see if a biblio record already exists in the catalogue when parsing a quotes message >+Converts 10-13 digit ISBNs and vice-versa if an initial match is not found >+ >+=cut >+ >+sub CheckOrderItemExists { >+ my $isbn = shift; >+ my $dbh = C4::Context->dbh; >+ my @matches; >+ my $biblionumber; >+ my $bibitemnumber; >+ my $sth = $dbh->prepare( >+ 'select biblionumber, biblioitemnumber from biblioitems where isbn=?'); >+ $sth->execute($isbn); >+ >+ while ( @matches = $sth->fetchrow_array() ) { >+ $biblionumber = $matches[0]; >+ $bibitemnumber = $matches[1]; >+ } >+ if ($biblionumber) { >+ return $biblionumber, $bibitemnumber; >+ } >+ else { >+ $isbn = cleanisbn($isbn); >+ if ( length($isbn) == 10 ) { >+ $isbn = Business::ISBN->new($isbn); >+ if ($isbn) { >+ if ( $isbn->is_valid ) { >+ $isbn = ( $isbn->as_isbn13 )->isbn; >+ $sth->execute($isbn); >+ while ( @matches = $sth->fetchrow_array() ) { >+ $biblionumber = $matches[0]; >+ $bibitemnumber = $matches[1]; >+ } >+ } >+ } >+ } >+ elsif ( length($isbn) == 13 ) { >+ $isbn = Business::ISBN->new($isbn); >+ if ($isbn) { >+ if ( $isbn->is_valid ) { >+ $isbn = ( $isbn->as_isbn10 )->isbn; >+ $sth->execute($isbn); >+ while ( @matches = $sth->fetchrow_array() ) { >+ $biblionumber = $matches[0]; >+ $bibitemnumber = $matches[1]; >+ } >+ } >+ } >+ } >+ return $biblionumber, $bibitemnumber; >+ } >+} >+ >+sub string35escape { >+ my $string = shift; >+ my $colon_string; >+ my @sections; >+ if ( length($string) > 35 ) { >+ my ( $chunk, $stringlength ) = ( 35, length($string) ); >+ for ( my $counter = 0 ; $counter < $stringlength ; $counter += $chunk ) >+ { >+ push @sections, substr( $string, $counter, $chunk ); >+ } >+ foreach my $section (@sections) { >+ $colon_string .= "$section:"; >+ } >+ chop $colon_string; >+ } >+ else { >+ $colon_string = $string; >+ } >+ return $colon_string; >+} >+ >+sub GetOrderItemInfo { >+ my $ordernumber = shift; >+ my $dbh = C4::Context->dbh; >+ my @rows; >+ my $homebranch; >+ my $callnumber; >+ my $itype; >+ my $ccode; >+ my $fund; >+ my $sth = $dbh->prepare( >+q|select items.homebranch, items.itemcallnumber, items.itype, items.location from items >+ inner join aqorders_items on aqorders_items.itemnumber=items.itemnumber >+ where aqorders_items.ordernumber=?| >+ ); >+ $sth->execute($ordernumber); >+ >+ while ( @rows = $sth->fetchrow_array() ) { >+ $homebranch = $rows[0]; >+ $callnumber = $rows[1]; >+ $itype = $rows[2]; >+ $ccode = $rows[3]; >+ } >+ $sth = $dbh->prepare( >+ q|select aqbudgets.budget_code from aqbudgets inner join aqorders on >+ aqorders.budget_id=aqbudgets.budget_id where aqorders.ordernumber=?| >+ ); >+ $sth->execute($ordernumber); >+ while ( @rows = $sth->fetchrow_array() ) { >+ $fund = $rows[0]; >+ } >+ return $homebranch, $callnumber, $itype, $ccode, $fund; >+} >+ >+sub CheckVendorFTPAccountExists { >+ my $booksellerid = shift; >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare( >+ q|select count(id) from vendor_edi_accounts where provider=?|); >+ $sth->execute($booksellerid); >+ while ( my @rows = $sth->fetchrow_array() ) { >+ if ( $rows[0] > 0 ) { >+ return 1; >+ } >+ } >+ return; >+} >+ >+1; >+ >+__END__ >+ >+=head1 AUTHOR >+ >+Mark Gavillet >+ >+=cut >diff --git a/acqui/basket.pl b/acqui/basket.pl >index f203af2..87df9d7 100755 >--- a/acqui/basket.pl >+++ b/acqui/basket.pl >@@ -28,6 +28,7 @@ use C4::Output; > use CGI; > use C4::Acquisition; > use C4::Budgets; >+use C4::EDI qw( CreateEDIOrder SendEDIOrder ); > use C4::Bookseller qw( GetBookSellerFromId); > use C4::Debug; > use C4::Biblio; >@@ -86,6 +87,8 @@ my $basket = GetBasket($basketno); > # if no booksellerid in parameter, get it from basket > # warn "=>".$basket->{booksellerid}; > $booksellerid = $basket->{booksellerid} unless $booksellerid; >+my $ediaccount = CheckVendorFTPAccountExists($booksellerid); >+$template->param(ediaccount=>$ediaccount); > my ($bookseller) = GetBookSellerFromId($booksellerid); > my $op = $query->param('op'); > if (!defined $op) { >@@ -95,6 +98,15 @@ if (!defined $op) { > my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1'; > $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2'; > >+if ( $op eq 'ediorder') { >+ my $edifile=CreateEDIOrder($basketno,$booksellerid); >+ $template->param(edifile => $edifile); >+} >+if ( $op eq 'edisend') { >+ my $edisend=SendEDIOrder($basketno,$booksellerid); >+ $template->param(edisend => $edisend); >+} >+ > if ( $op eq 'delete_confirm' ) { > my $basketno = $query->param('basketno'); > DelBasket($basketno); >diff --git a/admin/edi-accounts.pl b/admin/edi-accounts.pl >new file mode 100755 >index 0000000..3b25a7e >--- /dev/null >+++ b/admin/edi-accounts.pl >@@ -0,0 +1,72 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011,2012 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use CGI; >+use C4::Auth; >+use C4::Output; >+use C4::EDI >+ qw( CreateEDIDetails UpdateEDIDetails GetEDIAccounts DeleteEDIDetails); >+ >+my $input = CGI->new(); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => 'admin/edi-accounts.tmpl', >+ query => $input, >+ type => 'intranet', >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1 }, >+ } >+); >+ >+my $op = $input->param('op'); >+$template->param( op => $op ); >+ >+if ( $op eq 'delsubmit' ) { >+ my $del = DeleteEDIDetails( $input->param('id') ); >+ $template->param( opdelsubmit => 1 ); >+} >+ >+if ( $op eq 'addsubmit' ) { >+ CreateEDIDetails( >+ $input->param('provider'), $input->param('description'), >+ $input->param('host'), $input->param('user'), >+ $input->param('pass'), $input->param('path'), >+ $input->param('in_dir'), $input->param('san') >+ ); >+ $template->param( opaddsubmit => 1 ); >+} >+ >+if ( $op eq 'editsubmit' ) { >+ UpdateEDIDetails( >+ $input->param('editid'), $input->param('description'), >+ $input->param('host'), $input->param('user'), >+ $input->param('pass'), $input->param('provider'), >+ $input->param('path'), $input->param('in_dir'), >+ $input->param('san') >+ ); >+ $template->param( opeditsubmit => 1 ); >+} >+ >+my $ediaccounts = GetEDIAccounts(); >+$template->param( ediaccounts => $ediaccounts ); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/admin/edi-edit.pl b/admin/edi-edit.pl >new file mode 100755 >index 0000000..05148e4 >--- /dev/null >+++ b/admin/edi-edit.pl >@@ -0,0 +1,75 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use CGI; >+use C4::Auth; >+use C4::Output; >+use C4::EDI qw( GetVendorList GetEDIAccountDetails); >+ >+my $input = CGI->new(); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => 'admin/edi-edit.tmpl', >+ query => $input, >+ type => 'intranet', >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1 }, >+ } >+); >+my $vendorlist = GetVendorList(); >+ >+my $op = $input->param('op'); >+$template->param( op => $op ); >+ >+if ( $op eq 'add' ) { >+ $template->param( opaddsubmit => 'addsubmit' ); >+} >+if ( $op eq 'edit' ) { >+ $template->param( opeditsubmit => 'editsubmit' ); >+ my $edi_details = GetEDIAccountDetails( $input->param('id') ); >+ my $selectedprovider = $edi_details->{provider}; >+ foreach my $prov (@$vendorlist) { >+ $prov->{selected} = 'selected' >+ if $prov->{id} == $selectedprovider; >+ } >+ $template->param( >+ editid => $edi_details->{id}, >+ description => $edi_details->{description}, >+ host => $edi_details->{host}, >+ user => $edi_details->{username}, >+ pass => $edi_details->{password}, >+ provider => $edi_details->{provider}, >+ in_dir => $edi_details->{in_dir}, >+ san => $edi_details->{san} >+ ); >+} >+if ( $op eq 'del' ) { >+ $template->param( >+ opdelsubmit => 'delsubmit', >+ opdel => 1, >+ id => $input->param('id') >+ ); >+} >+ >+$template->param( vendorlist => $vendorlist ); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/installer/data/mysql/atomicupdate/edifact.sql b/installer/data/mysql/atomicupdate/edifact.sql >new file mode 100644 >index 0000000..6fc7a16 >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/edifact.sql >@@ -0,0 +1,27 @@ >+CREATE TABLE IF NOT EXISTS vendor_edi_accounts ( >+ id int(11) NOT NULL auto_increment, >+ description text NOT NULL, >+ host text, >+ username text, >+ password text, >+ last_activity date default NULL, >+ provider int(11) default NULL, >+ in_dir text, >+ san varchar(10) default NULL, >+ PRIMARY KEY (id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+CREATE TABLE IF NOT EXISTS edifact_messages ( >+ id int(11) NOT NULL auto_increment, >+ message_type text NOT NULL, >+ date_sent date default NULL, >+ provider int(11) default NULL, >+ status text, >+ basketno int(11) NOT NULL default '0', >+ PRIMARY KEY (id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+insert into permissions (module_bit, code, description) values (13, 'edi_manage', 'Manage EDIFACT transmissions'); >+ >+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES >+('EDIfactEAN', '56781234', '', 'EAN identifier for the library used in EDIfact messages', 'Textarea'); >diff --git a/installer/data/mysql/de-DE/mandatory/userpermissions.sql b/installer/data/mysql/de-DE/mandatory/userpermissions.sql >index dc281a9..a17d6dc 100644 >--- a/installer/data/mysql/de-DE/mandatory/userpermissions.sql >+++ b/installer/data/mysql/de-DE/mandatory/userpermissions.sql >@@ -43,6 +43,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Von Benutzern vergebene Tags moderieren'), > (13, 'rotating_collections', 'Wandernde Sammlungen verwalten'), > (13, 'upload_local_cover_images', 'Eigene Coverbilder hochladen'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Ablauf eines Abonnements prüfen'), > (15, 'claim_serials', 'Fehlende Hefte reklamieren'), > (15, 'create_subscription', 'Neues Abonnement anlegen'), >diff --git a/installer/data/mysql/en/mandatory/userpermissions.sql b/installer/data/mysql/en/mandatory/userpermissions.sql >index 124e030..7bb99dc 100644 >--- a/installer/data/mysql/en/mandatory/userpermissions.sql >+++ b/installer/data/mysql/en/mandatory/userpermissions.sql >@@ -43,6 +43,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Moderate patron tags'), > (13, 'rotating_collections', 'Manage rotating collections'), > (13, 'upload_local_cover_images', 'Upload local cover images'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Check the expiration of a serial'), > (15, 'claim_serials', 'Claim missing serials'), > (15, 'create_subscription', 'Create a new subscription'), >diff --git a/installer/data/mysql/es-ES/mandatory/userpermissions.sql b/installer/data/mysql/es-ES/mandatory/userpermissions.sql >index f731eab..ba780f0 100644 >--- a/installer/data/mysql/es-ES/mandatory/userpermissions.sql >+++ b/installer/data/mysql/es-ES/mandatory/userpermissions.sql >@@ -43,6 +43,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Moderate patron tags'), > (13, 'rotating_collections', 'Manage rotating collections'), > (13, 'upload_local_cover_images', 'Upload local cover images'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Check the expiration of a serial'), > (15, 'claim_serials', 'Claim missing serials'), > (15, 'create_subscription', 'Create a new subscription'), >diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/userpermissions.sql b/installer/data/mysql/fr-FR/1-Obligatoire/userpermissions.sql >index 8edc356..d543521 100644 >--- a/installer/data/mysql/fr-FR/1-Obligatoire/userpermissions.sql >+++ b/installer/data/mysql/fr-FR/1-Obligatoire/userpermissions.sql >@@ -43,6 +43,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'items_batchmod', 'Modifier les exemplaires par lot'), > (13, 'items_batchdel', 'Supprimer les exemplaires par lot'), > (13, 'upload_local_cover_images', 'Téléchargement des images de couverture'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Contrôler l''expiration d''un périodique'), > (15, 'claim_serials', 'Réclamer les périodiques manquants'), > (15, 'create_subscription', 'Créer de nouveaux abonnements'), >diff --git a/installer/data/mysql/it-IT/necessari/userpermissions.sql b/installer/data/mysql/it-IT/necessari/userpermissions.sql >index 96746cc..e8bc6c0 100644 >--- a/installer/data/mysql/it-IT/necessari/userpermissions.sql >+++ b/installer/data/mysql/it-IT/necessari/userpermissions.sql >@@ -45,6 +45,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Modera i tag inseriti dagli utenti'), > (13, 'rotating_collections', 'Gestisci le collezioni circolanti (rotating collections)'), > (13, 'upload_local_cover_images', 'Carica copertine in locale'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Controlla la scadenza di una risora in continuazione'), > (15, 'claim_serials', 'Richiedi i fascicoli non arrivati'), > (15, 'create_subscription', 'Crea un nuovo abbonamento'), >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index c74c39b..671fad7 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -3041,6 +3041,35 @@ CREATE TABLE IF NOT EXISTS `borrower_modifications` ( > PRIMARY KEY (`verification_token`,`borrowernumber`), > KEY `verification_token` (`verification_token`), > KEY `borrowernumber` (`borrowernumber`) >+ >+-- >+-- Table structure for table `vendor_edi_accounts` >+-- >+ >+CREATE TABLE IF NOT EXISTS vendor_edi_accounts ( >+ id int(11) NOT NULL auto_increment, >+ description text NOT NULL, >+ host text, >+ username text, >+ password text, >+ last_activity date default NULL, >+ provider int(11) default NULL, >+ in_dir text, >+ san varchar(10) default NULL, >+ PRIMARY KEY (id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+-- >+-- Table structure for table `edifact_messages` >+-- >+CREATE TABLE IF NOT EXISTS edifact_messages ( >+ id int(11) NOT NULL auto_increment, >+ message_type text NOT NULL, >+ date_sent date default NULL, >+ provider int(11) default NULL, >+ status text, >+ basketno int(11) NOT NULL default '0', >+ PRIMARY KEY (id) > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > > -- >diff --git a/installer/data/mysql/nb-NO/1-Obligatorisk/userpermissions.sql b/installer/data/mysql/nb-NO/1-Obligatorisk/userpermissions.sql >index ba56e3a..083a757 100644 >--- a/installer/data/mysql/nb-NO/1-Obligatorisk/userpermissions.sql >+++ b/installer/data/mysql/nb-NO/1-Obligatorisk/userpermissions.sql >@@ -63,6 +63,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Behandle tagger fra lÃ¥nere'), > (13, 'rotating_collections', 'Administrere roterende samlinger'), > (13, 'upload_local_cover_images', 'Laste opp lokale omslagsbilder'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Sjekke utløpsdato for et periodikum'), > (15, 'claim_serials', 'Purre manglende tidsskrifthefter'), > (15, 'create_subscription', 'Opprette abonnementer'), >diff --git a/installer/data/mysql/pl-PL/mandatory/userpermissions.sql b/installer/data/mysql/pl-PL/mandatory/userpermissions.sql >index 5659aba..718c8eb 100644 >--- a/installer/data/mysql/pl-PL/mandatory/userpermissions.sql >+++ b/installer/data/mysql/pl-PL/mandatory/userpermissions.sql >@@ -44,6 +44,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (16, 'execute_reports', 'Execute SQL reports'), > (13, 'rotating_collections', 'Manage rotating collections'), > (13, 'upload_local_cover_images', 'Upload local cover images'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Check the expiration of a serial'), > (15, 'claim_serials', 'Claim missing serials'), > (15, 'create_subscription', 'Create a new subscription'), >diff --git a/installer/data/mysql/ru-RU/mandatory/permissions_and_user_flags.sql b/installer/data/mysql/ru-RU/mandatory/permissions_and_user_flags.sql >index a7123ba..b6edd71 100644 >--- a/installer/data/mysql/ru-RU/mandatory/permissions_and_user_flags.sql >+++ b/installer/data/mysql/ru-RU/mandatory/permissions_and_user_flags.sql >@@ -68,6 +68,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Moderate patron tags'), > (13, 'rotating_collections', 'Manage rotating collections'), > (13, 'upload_local_cover_images', 'Upload local cover images'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Check the expiration of a serial'), > (15, 'claim_serials', 'Claim missing serials'), > (15, 'create_subscription', 'Create a new subscription'), >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index df821c0..e4a4715 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -419,3 +419,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('FinesIncludeGracePeriod','1','If enabled, fines calculations will include the grace period.',NULL,'YesNo'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('UNIMARCAuthorsFacetsSeparator',', ', 'UNIMARC authors facets separator', NULL, 'short'); > INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UseKohaPlugins','1','Enable or disable the ability to use Koha Plugins.','','YesNo'); >+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES('EDIfactEAN', '56781234', '', 'EAN identifier for the library used in EDIfact messages', 'Textarea'); >diff --git a/installer/data/mysql/uk-UA/mandatory/permissions_and_user_flags.sql b/installer/data/mysql/uk-UA/mandatory/permissions_and_user_flags.sql >index 366764c..af9d79a 100644 >--- a/installer/data/mysql/uk-UA/mandatory/permissions_and_user_flags.sql >+++ b/installer/data/mysql/uk-UA/mandatory/permissions_and_user_flags.sql >@@ -68,6 +68,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES > (13, 'moderate_tags', 'Moderate patron tags'), > (13, 'rotating_collections', 'Manage rotating collections'), > (13, 'upload_local_cover_images', 'Upload local cover images'), >+ (13, 'edi_manage', 'Manage EDIFACT transmissions'), > (15, 'check_expiration', 'Check the expiration of a serial'), > (15, 'claim_serials', 'Claim missing serials'), > (15, 'create_subscription', 'Create a new subscription'), >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 222428d..7647fde 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -6652,6 +6652,51 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { > "); > > print "Upgrade to $DBversion done (Bug 7804: Added plugin system.)\n"; >+ >+$DBversion = "3.11.00.XXX"; >+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { >+ print "Upgrade to $DBversion done (Add tables for EDI EDIfact ordering)\n"; >+my $sql1 = <<"END_EDI1"; >+CREATE TABLE IF NOT EXISTS vendor_edi_accounts ( >+ id int(11) NOT NULL auto_increment, >+ description text NOT NULL, >+ host text, >+ username text, >+ password text, >+ last_activity date default NULL, >+ provider int(11) default NULL, >+ in_dir text, >+ san varchar(10) default NULL, >+ PRIMARY KEY (id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+END_EDI1 >+ >+my $sql2 = <<"END_EDI2"; >+CREATE TABLE IF NOT EXISTS edifact_messages ( >+ id int(11) NOT NULL auto_increment, >+ message_type text NOT NULL, >+ date_sent date default NULL, >+ provider int(11) default NULL, >+ status text, >+ basketno int(11) NOT NULL default '0', >+ PRIMARY KEY (id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+END_EDI2 >+ >+my $sql3 = <<"END_EDI3"; >+insert into permissions (module_bit, code, description) values (13, 'edi_manage', 'Manage EDIFACT transmissions'); >+END_EDI3 >+ >+my $sql4 = <<"END_EDI4"; >+INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES >+('EDIfactEAN', '56781234', '', 'EAN identifier for the library used in EDIfact messages', 'Textarea'); >+END_EDI4 >+ >+ $dbh->do($sql1); >+ $dbh->do($sql2); >+ $dbh->do($sql3); >+ $dbh->do($sql4); >+ > SetVersion($DBversion); > } > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >index 91878bf..ddb2d6d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >@@ -63,6 +63,7 @@ > <!-- <li><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></li> --> > <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50 client targets</a></li> > <li><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></li> >+ <li><a href="/cgi-bin/koha/admin/edi-accounts.pl">EDI Accounts</a></li> > </ul> > </div> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >index e4fd8c7..3f42075 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >@@ -23,7 +23,7 @@ > [% IF ( CAN_user_tools_import_patrons ) %] > <li><a href="/cgi-bin/koha/tools/import_borrowers.pl">Import patrons</a></li> > [% END %] >- [% IF ( CAN_user_tools_edit_notices ) %] >+ [% IF CAN_user_tools_edit_notices %] > <li><a href="/cgi-bin/koha/tools/letter.pl">Notices & slips</a></li> > [% END %] > [% IF ( CAN_user_tools_edit_notice_status_triggers ) %] >@@ -98,4 +98,7 @@ > [% IF ( CAN_user_tools_edit_quotes ) %] > <li><a href="/cgi-bin/koha/tools/quotes.pl">Quote editor</a></li> > [% END %] >+ [% IF ( CAN_user_tools_edi_manage ) %] >+ <li><a href="/cgi-bin/koha/tools/edi.pl">EDIfact messages</a></li> >+ [% END %] > </ul></div></div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt >index 386d699..59a64fb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt >@@ -146,6 +146,7 @@ > new YAHOO.widget.Button("basketheadbutton"); > new YAHOO.widget.Button("exportbutton"); > new YAHOO.widget.Button("delbasketbutton"); >+ new YAHOO.widget.Button("ediorderbutton"); > } > //]]> > </script> >@@ -160,6 +161,9 @@ > <li><a href="[% script_name %]?op=close&basketno=[% basketno %]&booksellerid=[% booksellerid %]" class="button" id="closebutton">Close this basket</a></li> > [% END %] > <li><a href="[% script_name %]?op=export&basketno=[% basketno %]&booksellerid=[% booksellerid %]" class="button" id="exportbutton">Export this basket as CSV</a></li> >+ [% IF ediaccount %] >+ <li><a href="[% script_name %]?op=ediorder&basketno=[% basketno %]&booksellerid=[% booksellerid %]" class="button" id="ediorderbutton">EDIfact order</a></li> >+ [% END %] > </ul> > > </div> >@@ -187,7 +191,12 @@ > [% END %] > [% END %] > [% END %] >- >+ [% IF ( edifile ) %] >+ <div id="edifile" class="dialog alert">EDIfact order created and will be sent overnight. Filename: <strong>[% edifile %]</strong> - <a href="/cgi-bin/koha/acqui/basket.pl?op=edisend&basketno=[% basketno %]&booksellerid=[% booksellerid %]">Send this order now?</a></div> >+ [% END %] >+ [% IF ( edisend ) %] >+ <div id="edisend" class="dialog alert"><strong>[% edisend %]</strong></div> >+ [% END %] > [% IF ( NO_BOOKSELLER ) %] > <h2>Vendor not found</h2> > [% ELSE %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index a5dbe44..6b522d5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -107,6 +107,8 @@ > <dd>Define which servers to query for MARC data in the integrated Z39.50 client.</dd> > <dt><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></dt> > <dd>Choose which plugins to use to suggest searches to patrons and staff.</dd> >+ <dt><a href="/cgi-bin/koha/admin/edi-accounts.pl">EDI Accounts</a></dt> >+ <dd>Manage vendor EDI accounts for import/export</dd> > </dl> > </div> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-accounts.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-accounts.tt >new file mode 100644 >index 0000000..fae2c8c >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-accounts.tt >@@ -0,0 +1,46 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Administration - EDI Accounts</title> >+[% INCLUDE 'doc-head-close.inc' %] >+ >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › <a href="/cgi-bin/koha/admin/edi-accounts.pl">EDI Accounts</a></div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b" >+ <h1>Vendor EDI Accounts</h1> >+ [% IF ( ediaccounts ) %] >+ <div id="ediaccounts" class="rows"> >+ [% IF ( opdelsubmit ) %] >+ <div class="dialog alert">The account was successfully deleted</div> >+ [% END %] >+ [% IF ( opaddsubmit ) %] >+ <div class="dialog alert">The account was successfully added</div> >+ [% END %] >+ [% IF ( opeditsubmit ) %] >+ <div class="dialog alert">The account was successfully updated</div> >+ [% END %] >+ <div><ul class="toolbar"><li><span class="yui-button yui-link-button"><span class="first-child"><a href="/cgi-bin/koha/admin/edi-edit.pl?op=add">Add a new account</a></span></span></li></ul></div> >+ <table border="0" width="100%" cellpadding="3" cellspacing="0"> >+ <th><strong>ID</strong></th><th><strong>Vendor</strong></th><th><strong>Description</strong></th><th><strong>Last activity</strong></th><th><strong>Actions</strong></th></tr> >+ [% FOREACH account IN ediaccounts %] >+ <tr><td>[% account.id %]</td><td><a href="/cgi-bin/koha/acqui/supplier.pl?supplierid=[% account.providerid %]">[% account.vendor %]</a></td><td>[% account.description %]</td><td>[% account.last_activity %]</td><td align="center"><a href="/cgi-bin/koha/admin/edi-edit.pl?op=edit&id=[% account.id %]&providerid=[% account.providerid %]">Edit</a> | <a href="/cgi-bin/koha/admin/edi-edit.pl?op=del&id=[% account.id %]">Delete</a></td></tr> >+ [% END %] >+ </table> >+ </div> >+ [% ELSE %] >+ <p>You currently do not have any Vendor EDI Accounts. To add a new account <a href="/cgi-bin/koha/admin/edi-edit.pl?op=add">click here</a>.</p> >+ [% END %] >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'admin-menu.inc' %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-edit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-edit.tt >new file mode 100644 >index 0000000..dedbaf9 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/edi-edit.tt >@@ -0,0 +1,102 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Administration - EDI Accounts</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript" language="javascript"> >+$(document).ready(function() { >+ $('#failcheck').hide(); >+}); >+function check_form_edi() >+{ >+ if ($('#provider').val()!="" && $('#description').val()!="" && $('#host').val()!="") >+ { >+ $('#edi_form').submit(); >+ } >+ else >+ { >+ $('#failcheck').show('fast'); >+ } >+ >+} >+function deleteInstance() >+{ >+ window.location="/cgi-bin/koha/members/houseboundinstances.pl?op=delsubmit&borrowernumber=[% borrowernumber %]&instanceid=[% delinstanceid %]&hbnumber=[% hbnumber %]"; >+} >+function cancelInstance() >+{ >+ window.location="/cgi-bin/koha/members/housebound.pl?borrowernumber=[% borrowernumber %]"; >+} >+</script> >+[% INCLUDE 'calendar.inc' %] >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › <a href="/cgi-bin/koha/admin/edi-accounts.pl">EDI Accounts</a></div> >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <h1>Vendor EDI Accounts</h1> >+ <div id="failcheck" class="dialog alert">You must complete all required fields</div> >+ <form name="form" id="edi_form" method="post" action="/cgi-bin/koha/admin/edi-accounts.pl"> >+ <input type="hidden" name="op" value="[% opeditsubmit %][% opaddsubmit %][% opdelsubmit %]" /> >+ >+ <input type="hidden" name="editid" value="[% editid %]" /> >+ [% IF opdel %] >+ <p>Are you sure you want to delete this account?</p> >+ <p><a href="/cgi-bin/koha/admin/edi-accounts.pl?id=[% id %]&op=delsubmit">YES</a> | <a href="/cgi-bin/koha/admin/edi-accounts.pl">NO</a></p> >+ [% ELSE %] >+ <fieldset class="rows" id="edi_details"> >+ <legend>EDI Account details</legend> >+ <ol> >+ <li> >+ <label for="provider" class="required">Vendor:*</label> >+ <select id="provider" name="provider"> >+ <option value="">Select a vendor</option> >+ [% FOREACH vendor IN vendorlist %] >+ <option value="[% vendor.id %]" [% vendor.selected %]>[% vendor.name %]</option> >+ [% END %] >+ </select> >+ </li> >+ <li> >+ <label for="description" class="required">Description:* </label> >+ <input type="text" id="description" name="description" size="40" value="[% description %]" /> >+ </li> >+ <li> >+ <label for="host" class="required">Server hostname:*</label> >+ <input type="text" id="host" name="host" size="40" value="[% host %]" /> >+ </li> >+ <li> >+ <label for="user">Server username:</label> >+ <input type="text" id="user" name="user" size="40" value="[% user %]" /> >+ </li> >+ <li> >+ <label for="pass">Server password:</label> >+ <input type="text" id="pass" name="pass" size="40" value="[% pass %]" /> >+ </li> >+ <li> >+ <label for="in_dir">Server remote directory:</label> >+ <input type="text" id="in_dir" name="in_dir" size="40" value="[% in_dir %]" /> >+ </li> >+ <li> >+ <label for="san">Vendor SAN:</label> >+ <input type="text" id="san" name="san" size="40" value="[% san %]" /> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" value="Save" onclick="check_form_edi(); return false; " name="save"> >+ <a class="cancel" href="/cgi-bin/koha/admin/edi-accounts.pl">Cancel</a> >+ </fieldset> >+ [% END %] >+ </form> >+ >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'admin-menu.inc' %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/edi.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/edi.tt >new file mode 100644 >index 0000000..0fbdbcf >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/edi.tt >@@ -0,0 +1,63 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Tools › EDIfact messages</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/javascript" language="javascript"> >+function check_sent(status,key,basketno,providerid) >+{ >+ if (status == 'Failed' && basketno !=0) >+ { >+ document.write(' - (<a href="/cgi-bin/koha/acqui/basket.pl?op=edisend&basketno='+basketno+'&booksellerid='+providerid+'">Re-send</a>)'); >+ } >+} >+</script> >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › EDIfact messages</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b" >+ <h1>EDIfact messages</h1> >+ [% IF messagelist %] >+ <div id="messagelist" class="rows"> >+ [% IF opdelsubmit %] >+ <div class="dialog alert">The account was successfully deleted</div> >+ [% END %] >+ [% IF opaddsubmit %] >+ <div class="dialog alert">The account was successfully added</div> >+ [% END %] >+ [% IF opeditsubmit %] >+ <div class="dialog alert">The account was successfully updated</div> >+ [% END %] >+ <table border="0" width="100%" cellpadding="3" cellspacing="0"> >+ <th><strong>Date</strong></th><th><strong>Message type</strong></th><th><strong>Provider</strong></th><th><strong>Status</strong></th><th>Basket</th> >+ [% FOREACH message IN messagelist %] >+ <tr> >+ <td>[% message.date_sent %]</td> >+ <td>[% message.message_type %]</td> >+ <td><a href="/cgi-bin/koha/acqui/supplier.pl?supplierid=[% message.providerid %]">[% message.providername %]</a></td> >+ <td>[% message.status %]<script type="text/javascript" language="javascript">check_sent('[% message.status %]',[% message.id %],[% message.basketno %],[% message.providerid %]);</script></td> >+ <td> >+ [% IF message.basketno %] >+ <a href="/cgi-bin/koha/acqui/basket.pl?basketno=[% message.basketno %]">View basket</a> >+ [% END %] >+ </td></tr> >+ [% END %] >+ </table> >+ </div> >+ >+ [% ELSE %] >+ <p>There are currently no EDIfact messages to display.</p> >+ [% END %] >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'tools-menu.inc' %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >index 4fff721..77dbe26 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >@@ -100,6 +100,10 @@ > [% IF ( UseKohaPlugins && CAN_user_plugins_tool ) %] > <dt><a href="/cgi-bin/koha/plugins/plugins-home.pl?method=tool">Tool Plugins</a></dt> > <dd>Use tool plugins</dd> >+ >+ [% IF ( CAN_user_tools_edi_manage ) %] >+ <dt><a href="/cgi-bin/koha/tools/edi.pl">EDIfact messages</a></dt> >+ <dd>Manage EDIfact transmissions</dd> > [% END %] > > </dl> >diff --git a/misc/cronjobs/clean_edifiles.pl b/misc/cronjobs/clean_edifiles.pl >new file mode 100755 >index 0000000..ac33516 >--- /dev/null >+++ b/misc/cronjobs/clean_edifiles.pl >@@ -0,0 +1,43 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use C4::Context; >+my $edidir = C4::Context->config('intranetdir'); >+ >+$edidir .= '/misc/edi_files'; >+opendir( my $dh, $edidir ); >+my @files = readdir($dh); >+close $dh; >+ >+foreach my $file (@files) { >+ my $now = time; >+ my @stat = stat("$edidir/$file"); >+ if ( >+ $stat[9] < ( $now - 2592000 ) >+ && ( ( index lc($file), '.ceq' ) > -1 >+ || ( index lc($file), '.cep' ) > -1 ) >+ ) >+ { >+ print "Deleting file $edidir/$file..."; >+ unlink("$edidir/$file"); >+ print "Done.\n"; >+ } >+} >diff --git a/misc/cronjobs/edifact_order_ftp_transfer.pl b/misc/cronjobs/edifact_order_ftp_transfer.pl >new file mode 100755 >index 0000000..47aaaf3 >--- /dev/null >+++ b/misc/cronjobs/edifact_order_ftp_transfer.pl >@@ -0,0 +1,127 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011,2012 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use C4::Context; >+use C4::EDI qw ( GetEDIFTPAccounts ParseEDIQuote LogEDITransaction); >+use Net::FTP; >+ >+my $ftpaccounts = GetEDIFTPAccounts; >+ >+my @errors; >+my @putdirlist; >+my $newerr; >+my @files; >+my $putdir = C4::Context->config('intranetdir'); >+$putdir .= '/misc/edi_files/'; >+my $ediparse; >+opendir( my $dh, $putdir ); >+@putdirlist = readdir $dh; >+closedir $dh; >+ >+foreach my $accounts (@$ftpaccounts) { >+ my $ftp = Net::FTP->new( $accounts->{host}, Timeout => 10, Passive => 1 ) >+ or $newerr = 1; >+ $ftp->binary(); >+ push @errors, "Can't ftp to $accounts->{host}: $!\n" if $newerr; >+ myerr() if $newerr; >+ if ( !$newerr ) { >+ $newerr = 0; >+ print "Connected to $accounts->{host}\n"; >+ >+ $ftp->login( "$accounts->{username}", "$accounts->{password}" ) >+ or $newerr = 1; >+ print "Getting file list\n"; >+ push @errors, "Can't login to $accounts->{host}: $!\n" if $newerr; >+ $ftp->quit if $newerr; >+ myerr() if $newerr; >+ if ( !$newerr ) { >+ print "Logged in\n"; >+ $ftp->cwd( $accounts->{in_dir} ) or $newerr = 1; >+ push @errors, "Can't cd in server $accounts->{host} $!\n" >+ if $newerr; >+ myerr() if $newerr; >+ $ftp->quit if $newerr; >+ >+ @files = $ftp->ls or $newerr = 1; >+ push @errors, >+ "Can't get file list from server $accounts->{host} $!\n" >+ if $newerr; >+ myerr() if $newerr; >+ if ( !$newerr ) { >+ print "Got file list\n"; >+ foreach my $file (@files) { >+ if ( $file =~ m/\.ceq/i ) { >+ my $match; >+ foreach my $f (@putdirlist) { >+ if ( $f eq $file ) { >+ $match = 1; >+ last; >+ } >+ } >+ if ( $match != 1 ) { >+ chdir $putdir; >+ $ftp->get($file) or $newerr = 1; >+ push @errors, >+"Can't transfer file ($file) from $accounts->{host} $!\n" >+ if $newerr; >+ $ftp->quit if $newerr; >+ myerr() if $newerr; >+ if ( !$newerr ) { >+ $ediparse = >+ ParseEDIQuote( $file, $accounts->{provider} ); >+ } >+ if ( $ediparse == 1 ) { >+ my $qext = '.ceq'; >+ my $rext = '.eeq'; >+ my $renamed = lc $file; >+ $renamed =~ s/$qext/$rext/g; >+ $ftp->rename( $file, $renamed ); >+ } >+ } >+ } >+ } >+ } >+ } >+ if ( !$newerr ) { >+ LogEDITransaction( $accounts->{id} ); >+ } >+ $ftp->quit; >+ } >+ $newerr = 0; >+} >+ >+print "\n@errors\n"; >+ >+if (@errors) { >+ my $logfile = C4::Context->config('intranetdir'); >+ $logfile .= '/misc/edi_files/edi_ftp_error.log'; >+ open my $fh, '>>', $logfile; >+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time); >+ printf $fh "%4d-%02d-%02d %02d:%02d:%02d\n-----\n", $year + 1900, >+ $mon + 1, $mday, $hour, $min, $sec; >+ print $fh "@errors\n"; >+ close $fh; >+} >+ >+sub myerr { >+ print 'Error: ', @errors; >+ return; >+} >diff --git a/misc/cronjobs/send_queued_edi_orders.pl b/misc/cronjobs/send_queued_edi_orders.pl >new file mode 100755 >index 0000000..9b13bb2 >--- /dev/null >+++ b/misc/cronjobs/send_queued_edi_orders.pl >@@ -0,0 +1,26 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use C4::Context; >+use C4::EDI qw( SendQueuedEDIOrders ); >+ >+ >+SendQueuedEDIOrders(); >diff --git a/misc/edi_files/README.txt b/misc/edi_files/README.txt >new file mode 100644 >index 0000000..059de82 >--- /dev/null >+++ b/misc/edi_files/README.txt >@@ -0,0 +1,3 @@ >+This is a readme file but is secretly just a placeholder for the edi_files directory. >+ >+--Elliott Davis >diff --git a/t/Calendar.t b/t/Calendar.t >index 8648968..dcaddbc 100755 >--- a/t/Calendar.t >+++ b/t/Calendar.t >@@ -36,7 +36,6 @@ $module_context->mock( > return 'Calendar'; > } > ); >- > SKIP: { > > skip "DBD::Mock is too old", 33 >diff --git a/t/EDI.t b/t/EDI.t >new file mode 100644 >index 0000000..abfcfee >--- /dev/null >+++ b/t/EDI.t >@@ -0,0 +1,85 @@ >+#!/usr/bin/env perl >+ >+use strict; >+use warnings; >+use Test::More qw/no_plan/; >+use Test::MockModule; >+use DBD::Mock; >+ >+my $module_context = new Test::MockModule('C4::Context'); >+my $module_budgets = new Test::MockModule("C4::Budgets"); >+ >+$module_context->mock( >+ '_new_dbh', >+ sub { >+ my $dbh = DBI->connect( 'DBI:Mock:', '', '' ) >+ || die "Cannot create handle: $DBI::errstr\n"; >+ return $dbh; >+ } >+ ); >+ >+my $dbh = C4::Context->dbh(); >+ >+$module_context->mock("EDIfactEAN",sub{ return 1; }); >+$module_budgets->mock('GetCurrency',sub{ return {currency => "USD"}; }); >+ >+use_ok('C4::EDI'); >+ SKIP: { >+ skip "DBD::Mock is too old", 33 >+ unless $DBD::Mock::VERSION >= 1.45; >+ >+ $dbh->{mock_session} = DBD::Mock::Session->new('EDI_session' => ( >+ { #GetVendorList >+ statement => "select id, name from aqbooksellers order by name asc", >+ results => [ >+ ["id","name"], >+ [1,"Amazon"], >+ ] >+ }, >+ { #GetEDIAccounts >+ statement => "select vendor_edi_accounts.id, aqbooksellers.id as providerid, aqbooksellers.name as vendor, vendor_edi_accounts.description, vendor_edi_accounts.last_activity from vendor_edi_accounts inner join aqbooksellers on vendor_edi_accounts.provider = aqbooksellers.id order by aqbooksellers.name asc", >+ results => [ >+ ["vendor_edi_accounts.id", "providerid", "vendor", "vendor_edi_accounts.description", "vendor_edi_accounts.last_activity"], >+ [1,1,"Amazon", "Online Bookseller","2013-01-01 00:00:00"], >+ ] >+ }, >+ { #GetEDIAccounts >+ statement => "select san from vendor_edi_accounts where provider=?", >+ results => [ >+ ["san"], >+ [1], >+ ] >+ }, >+ { >+ statement => "select message_type from edifact_messages where basketno=?", >+ results => [ >+ ["message_type"], >+ ["QUOTE"], >+ ] >+ } >+ ) >+ ); >+ cmp_ok(C4::EDI->GetVendorList()->[0]->{name}, 'eq', 'Amazon'); >+ cmp_ok(C4::EDI->GetEDIAccounts->[0]->{vendor}, 'eq', 'Amazon'); >+ >+my $module_acquisition = new Test::MockModule("C4::Acquisition"); >+$module_acquisition->mock('GetOrderItemInfo',sub{ return ("MPL","npl.lgf","BOOK","1234","Emergency"); }); >+$module_acquisition->mock('GetOrders',sub{ >+ return ({title => "test", >+ author => "test", >+ publishercode => '1', >+ isbn => '1234567890', >+ publicationyear => "1996", >+ quantity => '1', >+ ordernumber => '35', >+ notes => "test_notes", >+ }); >+ >+}); >+ >+my ($basketno, $booksellerid) = 1; >+(-e C4::EDI->CreateEDIOrder($basketno,$booksellerid)) ? >+ pass("Create EDI File!") : >+ fail("Create EDI file!"); >+ >+} # End Skip Block >diff --git a/tools/edi.pl b/tools/edi.pl >new file mode 100755 >index 0000000..8bbb608 >--- /dev/null >+++ b/tools/edi.pl >@@ -0,0 +1,43 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 Mark Gavillet & PTFS Europe Ltd >+# >+# 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. >+ >+use strict; >+use warnings; >+use CGI; >+use C4::Auth; >+use C4::Output; >+use C4::EDI qw( GetEDIfactMessageList); >+ >+my $input = CGI->new(); >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => 'tools/edi.tmpl', >+ query => $input, >+ type => 'intranet', >+ authnotrequired => 0, >+ flagsrequired => { borrowers => 1 }, >+ } >+); >+ >+my $messagelist = GetEDIfactMessageList(); >+ >+$template->param( messagelist => $messagelist ); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >-- >1.7.10.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 7736
:
8275
|
8276
|
8446
|
8635
|
10226
|
12398
|
12438
|
12467
|
13071
|
15304
|
15729
|
16538
|
16629
|
16649
|
16652
|
16667
|
16732
|
16761
|
16779
|
16792
|
16864
|
16865
|
16866
|
16867
|
16868
|
16869
|
16870
|
16871
|
16872
|
16873
|
16874
|
16882
|
16883
|
16884
|
16885
|
16886
|
17120
|
17121
|
20983
|
20984
|
21475
|
33953
|
33957
|
34332
|
34833
|
35030
|
35106
|
35716
|
35717
|
35718
|
36738
|
44079
|
44080
|
44081
|
44082
|
44083
|
44084
|
46996
|
47004
|
48623
|
48624
|
48625
|
48626
|
48971
|
48972
|
48973
|
48974
|
48975
|
48976
|
49037
|
49038
|
49039
|
49040
|
49041
|
49042
|
49307
|
49850
|
50002
|
50008