View | Details | Raw Unified | Return to bug 8220
Collapse All | Expand All

(-)a/C4/Circulation.pm (-2 / +15 lines)
Lines 3136-3144 sub GetOfflineOperation { Link Here
3136
}
3136
}
3137
3137
3138
sub AddOfflineOperation {
3138
sub AddOfflineOperation {
3139
    my ( $userid, $branchcode, $timestamp, $action, $barcode, $cardnumber, $amount ) = @_;
3139
    my $dbh = C4::Context->dbh;
3140
    my $dbh = C4::Context->dbh;
3140
    my $sth = $dbh->prepare("INSERT INTO pending_offline_operations (userid, branchcode, timestamp, action, barcode, cardnumber) VALUES(?,?,?,?,?,?)");
3141
    my $sth = $dbh->prepare("INSERT INTO pending_offline_operations (userid, branchcode, timestamp, action, barcode, cardnumber, amount) VALUES(?,?,?,?,?,?,?)");
3141
    $sth->execute( @_ );
3142
    $sth->execute( $userid, $branchcode, $timestamp, $action, $barcode, $cardnumber, $amount );
3142
    return "Added.";
3143
    return "Added.";
3143
}
3144
}
3144
3145
Lines 3157-3162 sub ProcessOfflineOperation { Link Here
3157
        $report = ProcessOfflineReturn( $operation );
3158
        $report = ProcessOfflineReturn( $operation );
3158
    } elsif ( $operation->{action} eq 'issue' ) {
3159
    } elsif ( $operation->{action} eq 'issue' ) {
3159
        $report = ProcessOfflineIssue( $operation );
3160
        $report = ProcessOfflineIssue( $operation );
3161
    } elsif ( $operation->{action} eq 'payment' ) {
3162
        $report = ProcessOfflinePayment( $operation );
3160
    }
3163
    }
3161
3164
3162
    DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid};
3165
    DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid};
Lines 3226-3231 sub ProcessOfflineIssue { Link Here
3226
    }
3229
    }
3227
}
3230
}
3228
3231
3232
sub ProcessOfflinePayment {
3233
    my $operation = shift;
3234
3235
    my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber
3236
    my $amount = $operation->{amount};
3237
    
3238
    recordpayment( $borrower->{borrowernumber}, $amount );
3239
3240
    return "Success."
3241
}
3229
3242
3230
3243
3231
=head2 TransferSlip
3244
=head2 TransferSlip
(-)a/installer/data/mysql/kohastructure.sql (-9 / +9 lines)
Lines 1548-1564 CREATE TABLE `patronimage` ( Link Here
1548
-- so MyISAM is better in this case
1548
-- so MyISAM is better in this case
1549
1549
1550
DROP TABLE IF EXISTS `pending_offline_operations`;
1550
DROP TABLE IF EXISTS `pending_offline_operations`;
1551
CREATE TABLE `pending_offline_operations` (
1551
CREATE TABLE pending_offline_operations (
1552
  `operationid` int(11) NOT NULL AUTO_INCREMENT,
1552
  operationid int(11) NOT NULL AUTO_INCREMENT,
1553
  `userid` varchar(30) NOT NULL,
1553
  userid varchar(30) NOT NULL,
1554
  `branchcode` varchar(10) NOT NULL,
1554
  branchcode varchar(10) NOT NULL,
1555
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
1555
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
1556
  `action` varchar(10) NOT NULL,
1556
  `action` varchar(10) NOT NULL,
1557
  `barcode` varchar(20) NOT NULL,
1557
  barcode varchar(20) DEFAULT NULL,
1558
  `cardnumber` varchar(16) DEFAULT NULL,
1558
  cardnumber varchar(16) DEFAULT NULL,
1559
  PRIMARY KEY (`operationid`)
1559
  amount decimal(28,6) DEFAULT NULL,
1560
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
1560
  PRIMARY KEY (operationid)
1561
1561
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
1562
1562
1563
1563
1564
--
1564
--
(-)a/installer/data/mysql/updatedatabase.pl (+8 lines)
Lines 5452-5457 if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { Link Here
5452
    SetVersion($DBversion);
5452
    SetVersion($DBversion);
5453
}
5453
}
5454
5454
5455
$DBversion = "3.09.00.XXX";
5456
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
5457
    $dbh->do("ALTER TABLE `pending_offline_operations` CHANGE `barcode` `barcode` VARCHAR( 20 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
5458
    $dbh->do("ALTER TABLE `pending_offline_operations` ADD `amount` DECIMAL( 28, 6 ) NULL DEFAULT NULL");
5459
    print "Upgrade to $DBversion done (redefine the field branchcode as PRIMARY KEY of branches)\n";
5460
    SetVersion ($DBversion);
5461
}
5462
5455
=head1 FUNCTIONS
5463
=head1 FUNCTIONS
5456
5464
5457
=head2 TableExists($table)
5465
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt (-2 / +6 lines)
Lines 51-58 Link Here
51
	<div class="yui-u">
51
	<div class="yui-u">
52
        <h5>Offline circulation</h5>
52
        <h5>Offline circulation</h5>
53
		<ul>
53
		<ul>
54
            <li><a href="/cgi-bin/koha/offline_circ/process_koc.pl">Offline circulation file (.koc) uploader</a></li>
54
                    <li><a href="/cgi-bin/koha/offline_circ/process_koc.pl">Upload offline circulation file (.koc)</a></li>
55
            <li><a href="/cgi-bin/koha/offline_circ/list.pl">Offline circulation</a> (<a href="https://addons.mozilla.org/[% lang %]/firefox/addon/koct/">Firefox add-on</a>)</li>
55
                    <li><a href="/cgi-bin/koha/offline_circ/list.pl">Pending offline circulation actions</a> 
56
                    <ul>
57
                        <li><a href="http://kylehall.info/index.php/projects/koha/koha-offline-circulation/">Get desktop application</a></li>
58
                        <li><a href="https://addons.mozilla.org/[% lang %]/firefox/addon/koct/">Get Firefox add-on</a></li>
59
                    </ul>
56
		</ul>
60
		</ul>
57
	</div>
61
	</div>
58
</div>
62
</div>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/enqueue_koc.tt (+31 lines)
Line 0 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Circulation &rsaquo; Add offline circulations to queue</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
</head>
5
<body>
6
[% INCLUDE 'header.inc' %]
7
[% INCLUDE 'circ-search.inc' %]
8
9
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a> &rsaquo; <a href="/cgi-bin/koha/offline_circ/process_koc.pl">Add offline circulations to queue</a></div>
10
11
<div id="doc" class="yui-t7">
12
13
   <div id="bd">
14
15
  <h2>Koha offline circulation</h2>
16
  <p>Your file was processed.</p>
17
18
[% FOREACH message IN messages %]
19
  [% IF ( message.message ) %]	
20
      [% IF ( message.ERROR_file_version ) %]
21
          <div class="dialog alert"><p>Warning: This file is version [% message.upload_version %], but I only know how to import version [% message.current_version %]. I'll try my best.</p>
22
      [% END %]
23
  [% END %]
24
[% END %]
25
26
<p><a href="process_koc.pl">Upload another KOC file</a></p>
27
28
<p><a href="list.pl">View pending offline circulation actions</a></p>
29
30
</div>
31
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/list.tt (-2 / +4 lines)
Lines 78-84 Link Here
78
			            <th>Date</th>
78
			            <th>Date</th>
79
			            <th>Action</th>
79
			            <th>Action</th>
80
			            <th>Barcode</th>
80
			            <th>Barcode</th>
81
                        <th>Card number</th>
81
                                    <th>Card number</th>
82
                                    <th>Amount</th>
82
		            </tr>
83
		            </tr>
83
		        </thead>
84
		        </thead>
84
		        <tbody>
85
		        <tbody>
Lines 95-101 Link Here
95
			                    [% END %]
96
			                    [% END %]
96
			                </td>
97
			                </td>
97
			                <td>
98
			                <td>
98
			                [% IF ( operation.actionissue ) %]
99
			                [% IF ( operation.actionissue || operation.actionpayment) %]
99
		                        [% IF ( operation.borrowernumber ) %]
100
		                        [% IF ( operation.borrowernumber ) %]
100
		                            <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% operation.borrowernumber %]" title="[% operation.borrower %]">[% operation.cardnumber %]</a>
101
		                            <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% operation.borrowernumber %]" title="[% operation.borrower %]">[% operation.cardnumber %]</a>
101
		                        [% ELSE %]
102
		                        [% ELSE %]
Lines 103-108 Link Here
103
		                        [% END %]
104
		                        [% END %]
104
			                [% END %]
105
			                [% END %]
105
			                </td>
106
			                </td>
107
                                        <td>[% operation.amount %]</td>
106
		                </tr>
108
		                </tr>
107
		            [% END %]
109
		            [% END %]
108
		        </tbody>
110
		        </tbody>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/offline_circ/process_koc.tt (-12 / +22 lines)
Lines 6-27 Link Here
6
<script type="text/javascript">
6
<script type="text/javascript">
7
//<![CDATA[
7
//<![CDATA[
8
$(document).ready(function(){
8
$(document).ready(function(){
9
	$("#processfile").hide();
9
    $("#enqueuefile").hide();
10
    $("#processfile").hide();
10
});
11
});
12
11
function CheckUpload(f){
13
function CheckUpload(f){
12
	if(f.fileToUpload.value == ""){
14
    if (f.fileToUpload.value == ""){
13
		alert(_("Please choose a file to upload"));
15
        alert(_("Please choose a file to upload"));
14
	} else {
16
    } else {
15
		return ajaxFileUpload()
17
        return ajaxFileUpload()
16
	}
18
    }
17
		return false;
19
    return false;
18
}
20
}
21
19
function CheckForm(f) {
22
function CheckForm(f) {
20
    if (f.uploadedfileid.value == '') {
23
    if (f.uploadedfileid.value == '') {
21
        alert(_('Please upload a file first.'));
24
        alert(_('Please upload a file first.'));
22
    } else {
25
    } else {
23
		$("#fileuploadstatus").hide();
26
        $("#fileuploadstatus").hide();
24
		$("#fileuploadform").slideUp();
27
        $("#fileuploadform").slideUp();
25
        return submitBackgroundJob(f);
28
        return submitBackgroundJob(f);
26
    }
29
    }
27
    return false;
30
    return false;
Lines 60-66 function CheckForm(f) { Link Here
60
	[% IF ( message.payment ) %]<p>Accepted payment ([% message.amount %]) from <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% message.borrowernumber %]">[% message.firstname %] [% message.surname %]</a> ([% message.cardnumber %]): [% message.datetime %]</p>[% END %]
63
	[% IF ( message.payment ) %]<p>Accepted payment ([% message.amount %]) from <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% message.borrowernumber %]">[% message.firstname %] [% message.surname %]</a> ([% message.cardnumber %]): [% message.datetime %]</p>[% END %]
61
  [% END %]
64
  [% END %]
62
[% ELSE %]
65
[% ELSE %]
63
  <h2>Upload offline circulation data</h2>
66
   <h2>Upload offline circulation data</h2>
67
64
   <div id="fileuploadform">
68
   <div id="fileuploadform">
65
     <form method="post" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
69
     <form method="post" action="[% SCRIPT_NAME %]" enctype="multipart/form-data">
66
		<fieldset class="brief">
70
		<fieldset class="brief">
Lines 72-82 function CheckForm(f) { Link Here
72
     <div id="fileuploadstatus" style="display:none">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
76
     <div id="fileuploadstatus" style="display:none">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div>
73
     <div id="fileuploadfailed" style="display:none"></div>
77
     <div id="fileuploadfailed" style="display:none"></div>
74
   </div>
78
   </div>
75
   <form action="process_koc.pl" id="processfile" method="post" enctype="multipart/form-data">
79
80
   <form action="enqueue_koc.pl" id="processfile" method="post" enctype="multipart/form-data">
81
     <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
82
     <input type="submit" value="Add to offline circulation queue" onclick="return CheckForm(this.form);" id="queueformsubmit" />
83
   </form>
84
85
   <form action="process_koc.pl" id="enqueuefile" method="post" enctype="multipart/form-data">
76
     <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
86
     <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
77
     <input type="hidden" name="runinbackground" id="runinbackground" value="" />
87
     <input type="hidden" name="runinbackground" id="runinbackground" value="" />
78
     <input type="hidden" name="completedJobID" id="completedJobID" value="" />
88
     <input type="hidden" name="completedJobID" id="completedJobID" value="" />
79
     <input type="submit" value="Process offline circulation file" onclick="return CheckForm(this.form);" id="mainformsubmit" />
89
     <input type="submit" value="Apply directly" onclick="return CheckForm(this.form);" id="mainformsubmit" />
80
     <div id="jobstatus" style="display:none">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div>
90
     <div id="jobstatus" style="display:none">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div>
81
     <div id="jobfailed" style="display:none"></div>
91
     <div id="jobfailed" style="display:none"></div>
82
   </form>
92
   </form>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt (+9 lines)
Lines 53-59 Link Here
53
<p>Sorry, the CAS login failed.</p>
53
<p>Sorry, the CAS login failed.</p>
54
[% END %]
54
[% END %]
55
55
56
<<<<<<< HEAD
56
<p>If you have a <acronym title="Central Authentication Service">CAS</acronym> account, 
57
<p>If you have a <acronym title="Central Authentication Service">CAS</acronym> account, 
58
=======
59
<p><acronym title="Central Authentication Service">If you have a CAS account</acronym>, 
60
>>>>>>> Bug 5983 minor fix in html to improve translatability
57
[% IF ( casServerUrl ) %]
61
[% IF ( casServerUrl ) %]
58
    please <a href="[% casServerUrl %]">click here to login</a>.<p>
62
    please <a href="[% casServerUrl %]">click here to login</a>.<p>
59
[% END %]
63
[% END %]
Lines 61-68 Link Here
61
[% IF ( casServersLoop ) %]
65
[% IF ( casServersLoop ) %]
62
please choose against which one you would like to authenticate: </p>
66
please choose against which one you would like to authenticate: </p>
63
<ul>
67
<ul>
68
<<<<<<< HEAD
64
    [% FOREACH casServer IN casServersLoop %]
69
    [% FOREACH casServer IN casServersLoop %]
65
	<li><a href="[% casServer.value %]">[% casServer.name %]</a></li>
70
	<li><a href="[% casServer.value %]">[% casServer.name %]</a></li>
71
=======
72
    [% FOREACH casServersLoo IN casServersLoop %]
73
	<li><a href="[% searchdomainloo.value %]">[% searchdomainloo.name %]</a></li>
74
>>>>>>> Bug 5983 minor fix in html to improve translatability
66
    [% END %]
75
    [% END %]
67
[% END %]
76
[% END %]
68
</ul>
77
</ul>
(-)a/offline_circ/enqueue_koc.pl (+197 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# 2008 Kyle Hall <kyle.m.hall@gmail.com>
4
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
#
20
21
use strict;
22
use warnings;
23
24
use CGI;
25
use C4::Output;
26
use C4::Auth;
27
use C4::Koha;
28
use C4::Context;
29
use C4::Biblio;
30
use C4::Accounts;
31
use C4::Circulation;
32
use C4::Items;
33
use C4::Members;
34
use C4::Stats;
35
use C4::UploadedFile;
36
37
use Date::Calc qw( Add_Delta_Days Date_to_Days );
38
39
use constant DEBUG => 0;
40
41
# this is the file version number that we're coded against.
42
my $FILE_VERSION = '1.0';
43
44
my $query = CGI->new;
45
my @output;
46
47
my ($template, $loggedinuser, $cookie) = get_template_and_user({
48
    template_name => "offline_circ/enqueue_koc.tmpl",
49
    query => $query,
50
    type => "intranet",
51
    authnotrequired => 0,
52
     flagsrequired   => { circulate => "circulate_remaining_permissions" },
53
});
54
55
56
my $fileID=$query->param('uploadedfileid');
57
my %cookies = parse CGI::Cookie($cookie);
58
my $sessionID = $cookies{'CGISESSID'}->value;
59
## 'Local' globals.
60
our $dbh = C4::Context->dbh();
61
62
if ($fileID) {
63
    my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID);
64
    my $fh = $uploaded_file->fh();
65
    my @input_lines = <$fh>;
66
67
    my $header_line = shift @input_lines;
68
    my $file_info   = parse_header_line($header_line);
69
    if ($file_info->{'Version'} ne $FILE_VERSION) {
70
        push @output, {
71
            message => 1,
72
            ERROR_file_version => 1,
73
            upload_version => $file_info->{'Version'},
74
            current_version => $FILE_VERSION
75
        };
76
    }
77
78
    my $userid = C4::Context->userenv->{id};
79
    my $branchcode = C4::Context->userenv->{branch};
80
    
81
    foreach  my $line (@input_lines)  {
82
        my $command_line = parse_command_line($line);
83
        my $timestamp = $command_line->{'date'} . ' ' . $command_line->{'time'};
84
        my $action = $command_line->{'command'};
85
        my $barcode = $command_line->{'barcode'};
86
        my $cardnumber = $command_line->{'cardnumber'};
87
        my $amount = $command_line->{'amount'};
88
        
89
        AddOfflineOperation( $userid, $branchcode, $timestamp, $action, $barcode, $cardnumber, $amount );
90
    }
91
92
}
93
94
$template->param( messages => \@output );
95
96
output_html_with_http_headers $query, $cookie, $template->output;
97
98
=head1 FUNCTIONS
99
100
=head2 parse_header_line
101
102
parses the header line from a .koc file. This is the line that
103
specifies things such as the file version, and the name and version of
104
the offline circulation tool that generated the file. See
105
L<http://wiki.koha-community.org/wiki/Koha_offline_circulation_file_format>
106
for more information.
107
108
pass in a string containing the header line (the first line from th
109
file).
110
111
returns a hashref containing the information from the header.
112
113
=cut
114
115
sub parse_header_line {
116
    my $header_line = shift;
117
    chomp($header_line);
118
    $header_line =~ s/\r//g;
119
120
    my @fields = split( /\t/, $header_line );
121
    my %header_info = map { split( /=/, $_ ) } @fields;
122
    return \%header_info;
123
}
124
125
=head2 parse_command_line
126
127
=cut
128
129
sub parse_command_line {
130
    my $command_line = shift;
131
    chomp($command_line);
132
    $command_line =~ s/\r//g;
133
134
    my ( $timestamp, $command, @args ) = split( /\t/, $command_line );
135
    my ( $date,      $time,    $id )   = split( /\s/, $timestamp );
136
137
    my %command = (
138
        date    => $date,
139
        time    => $time,
140
        id      => $id,
141
        command => $command,
142
    );
143
144
    # set the rest of the keys using a hash slice
145
    my $argument_names = arguments_for_command($command);
146
    @command{@$argument_names} = @args;
147
148
    return \%command;
149
150
}
151
152
=head2 arguments_for_command
153
154
fetches the names of the columns (and function arguments) found in the
155
.koc file for a particular command name. For instance, the C<issue>
156
command requires a C<cardnumber> and C<barcode>. In that case this
157
function returns a reference to the list C<qw( cardnumber barcode )>.
158
159
parameters: the command name
160
161
returns: listref of column names.
162
163
=cut
164
165
sub arguments_for_command {
166
    my $command = shift;
167
168
    # define the fields for this version of the file.
169
    my %format = (
170
        issue   => [qw( cardnumber barcode )],
171
        return  => [qw( barcode )],
172
        payment => [qw( cardnumber amount )],
173
    );
174
175
    return $format{$command};
176
}
177
178
=head2 _get_borrowernumber_from_barcode
179
180
pass in a barcode
181
get back the borrowernumber of the patron who has it checked out.
182
undef if that can't be found
183
184
=cut
185
186
sub _get_borrowernumber_from_barcode {
187
    my $barcode = shift;
188
189
    return unless $barcode;
190
191
    my $item = GetBiblioFromItemNumber( undef, $barcode );
192
    return unless $item->{'itemnumber'};
193
194
    my $issue = C4::Circulation::GetItemIssue( $item->{'itemnumber'} );
195
    return unless $issue->{'borrowernumber'};
196
    return $issue->{'borrowernumber'};
197
}
(-)a/offline_circ/list.pl (-1 / +1 lines)
Lines 54-59 for (@$operations) { Link Here
54
    }
54
    }
55
    $_->{'actionissue'}    = $_->{'action'} eq 'issue';
55
    $_->{'actionissue'}    = $_->{'action'} eq 'issue';
56
    $_->{'actionreturn'}   = $_->{'action'} eq 'return';
56
    $_->{'actionreturn'}   = $_->{'action'} eq 'return';
57
    $_->{'actionpayment'}  = $_->{'action'} eq 'payment';
57
}
58
}
58
$template->param(pending_operations => $operations);
59
$template->param(pending_operations => $operations);
59
60
60
- 

Return to bug 8220