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

(-)a/C4/Circulation.pm (-2 / +15 lines)
Lines 3126-3134 sub GetOfflineOperation { Link Here
3126
}
3126
}
3127
3127
3128
sub AddOfflineOperation {
3128
sub AddOfflineOperation {
3129
    my ( $userid, $branchcode, $timestamp, $action, $barcode, $cardnumber, $amount ) = @_;
3129
    my $dbh = C4::Context->dbh;
3130
    my $dbh = C4::Context->dbh;
3130
    my $sth = $dbh->prepare("INSERT INTO pending_offline_operations (userid, branchcode, timestamp, action, barcode, cardnumber) VALUES(?,?,?,?,?,?)");
3131
    my $sth = $dbh->prepare("INSERT INTO pending_offline_operations (userid, branchcode, timestamp, action, barcode, cardnumber, amount) VALUES(?,?,?,?,?,?,?)");
3131
    $sth->execute( @_ );
3132
    $sth->execute( $userid, $branchcode, $timestamp, $action, $barcode, $cardnumber, $amount );
3132
    return "Added.";
3133
    return "Added.";
3133
}
3134
}
3134
3135
Lines 3147-3152 sub ProcessOfflineOperation { Link Here
3147
        $report = ProcessOfflineReturn( $operation );
3148
        $report = ProcessOfflineReturn( $operation );
3148
    } elsif ( $operation->{action} eq 'issue' ) {
3149
    } elsif ( $operation->{action} eq 'issue' ) {
3149
        $report = ProcessOfflineIssue( $operation );
3150
        $report = ProcessOfflineIssue( $operation );
3151
    } elsif ( $operation->{action} eq 'payment' ) {
3152
        $report = ProcessOfflinePayment( $operation );
3150
    }
3153
    }
3151
3154
3152
    DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid};
3155
    DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid};
Lines 3216-3221 sub ProcessOfflineIssue { Link Here
3216
    }
3219
    }
3217
}
3220
}
3218
3221
3222
sub ProcessOfflinePayment {
3223
    my $operation = shift;
3224
3225
    my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber
3226
    my $amount = $operation->{amount};
3227
    
3228
    recordpayment( $borrower->{borrowernumber}, $amount );
3229
3230
    return "Success."
3231
}
3219
3232
3220
3233
3221
=head2 TransferSlip
3234
=head2 TransferSlip
(-)a/installer/data/mysql/kohastructure.sql (-9 / +9 lines)
Lines 1546-1562 CREATE TABLE `patronimage` ( Link Here
1546
-- so MyISAM is better in this case
1546
-- so MyISAM is better in this case
1547
1547
1548
DROP TABLE IF EXISTS `pending_offline_operations`;
1548
DROP TABLE IF EXISTS `pending_offline_operations`;
1549
CREATE TABLE `pending_offline_operations` (
1549
CREATE TABLE pending_offline_operations (
1550
  `operationid` int(11) NOT NULL AUTO_INCREMENT,
1550
  operationid int(11) NOT NULL AUTO_INCREMENT,
1551
  `userid` varchar(30) NOT NULL,
1551
  userid varchar(30) NOT NULL,
1552
  `branchcode` varchar(10) NOT NULL,
1552
  branchcode varchar(10) NOT NULL,
1553
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
1553
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
1554
  `action` varchar(10) NOT NULL,
1554
  `action` varchar(10) NOT NULL,
1555
  `barcode` varchar(20) NOT NULL,
1555
  barcode varchar(20) DEFAULT NULL,
1556
  `cardnumber` varchar(16) DEFAULT NULL,
1556
  cardnumber varchar(16) DEFAULT NULL,
1557
  PRIMARY KEY (`operationid`)
1557
  amount decimal(28,6) DEFAULT NULL,
1558
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
1558
  PRIMARY KEY (operationid)
1559
1559
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
1560
1560
1561
1561
1562
--
1562
--
(-)a/installer/data/mysql/updatedatabase.pl (+8 lines)
Lines 5308-5313 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
5308
    SetVersion ($DBversion);
5308
    SetVersion ($DBversion);
5309
}
5309
}
5310
5310
5311
$DBversion = "3.09.00.XXX";
5312
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
5313
    $dbh->do("ALTER TABLE `pending_offline_operations` CHANGE `barcode` `barcode` VARCHAR( 20 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
5314
    $dbh->do("ALTER TABLE `pending_offline_operations` ADD `amount` DECIMAL( 28, 6 ) NULL DEFAULT NULL");
5315
    print "Upgrade to $DBversion done (redefine the field branchcode as PRIMARY KEY of branches)\n";
5316
    SetVersion ($DBversion);
5317
}
5318
5311
=head1 FUNCTIONS
5319
=head1 FUNCTIONS
5312
5320
5313
=head2 TableExists($table)
5321
=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