updating money handling; adding readonly fieldmapper classes (views); allow fields...
[Evergreen.git] / Open-ILS / src / support-scripts / generate-fines.pl
1 #!/usr/bin/perl -w
2 use strict;
3 use OpenSRF::EX qw/:try/;
4 use OpenSRF::System;
5 use OpenSRF::Application;
6 use OpenSRF::Utils::SettingsClient;
7 use OpenILS::Utils::Fieldmapper;
8 use OpenSRF::Utils;
9 use DateTime;
10 use DateTime::Format::ISO8601;
11 use Data::Dumper;
12
13 die "USAGE:\n\t$0 config_file [grace?]\n" unless @ARGV;
14
15 my $parser = DateTime::Format::ISO8601->new;
16
17 # hard coded for now, option later
18
19 OpenSRF::System->bootstrap_client( config_file => $ARGV[0] );
20 my $session = OpenSRF::AppSession->create('open-ils.storage');
21
22 my $grace = $ARGV[1];
23
24 try {
25         my $req = $session->request( 'open-ils.storage.action.circulation.overdue',$grace );
26         while (!$req->failed && (my $res = $req->recv)) {
27                 my $c = $res->content;
28
29                 print   "ARG! Overdue circulation ".$c->id.
30                         " for item ".$c->target_copy.
31                         " (user ".$c->usr.")".
32                         " : it was due at ".$c->due_date."\n";
33
34                 my $fine = $session->request(
35                         'open-ils.storage.direct.money.billing.search.xact',
36                         $c->id, { order_by => 'billing_ts DESC', limit => '1' }
37                 )->gather(1);
38
39                 my $now = time;
40                 my $fine_interval = OpenSRF::Utils->interval_to_seconds( $c->fine_interval );
41
42                 my $last_fine;
43                 if ($fine) {
44                         $last_fine = $parser->parse_datetime( OpenSRF::Utils->clense_ISO8601( $fine->billing_ts ) )->epoch;
45                 } else {
46                         # Use Date::Manip here
47                         $last_fine = $parser->parse_datetime( OpenSRF::Utils->clense_ISO8601( $c->due_date ) )->epoch;
48                         $last_fine += $fine_interval if ($grace);
49                 }
50
51                 my $pending_fine_count = int( ($now - $last_fine) / $fine_interval ); 
52                 next unless($pending_fine_count);
53
54                 print "\t$pending_fine_count pending fine(s)\n";
55
56                 for my $bill (1 .. $pending_fine_count) {
57
58                         my $total = $session->request(
59                                 'open-ils.storage.direct.money.billable_transaction_summary.retrieve',
60                                 $c->id
61                         )->gather(1);
62
63                         if ($total && $total->balance_owed > $c->max_fine) {
64                                 $c->stop_fines('MAXFINES');
65                                 
66                                 $session->request(
67                                         'open-ils.storage.direct.action.circulation.update',
68                                         $c
69                                 )->gather(1);
70
71                                 last;
72                         }
73
74                         my $billing = new Fieldmapper::money::billing;
75                         $billing->xact( $c->id );
76                         $billing->note( "Overdue Fine" );
77                         $billing->amount( $c->recuring_fine );
78                         $billing->billing_ts(
79                                 DateTime->from_epoch(
80                                         epoch => $last_fine + $fine_interval * $bill
81                                 )->strftime('%FT%T%z')
82                         );
83
84                         $session->request(
85                                 'open-ils.storage.direct.money.billing.create',
86                                 $billing
87                         )->gather(1);
88
89                 }
90         }
91
92 } catch Error with {
93         my $e = shift;
94         die "Error processing overdue circulations:\n\n$e\n";
95 };
96
97