Annotation of RT/Invoicing/lib/RTI/State.pm, Revision 1.1
1.1 ! andrew 1: package RTI::State;
! 2: use strict;
! 3: use warnings;
! 4:
! 5: use Carp;
! 6:
! 7: use DateTime;
! 8:
! 9: use 5.010;
! 10:
! 11: use YAML::Any qw/ LoadFile DumpFile /;
! 12:
! 13: my $file = '';
! 14:
! 15: sub new {
! 16: my $class;
! 17: ( $class, $file ) = @_;
! 18:
! 19: my $self = { lastinvoice => 0, };
! 20: if ( -e $file ) {
! 21: $self = LoadFile($file) or die "Unable to load state: $!";
! 22:
! 23: $self->{lastinvoice} ||= 0;
! 24: while ( my ( $id, $invoice ) = each %{ $self->{invoice} } ) {
! 25: $self->{lastinvoice} = $id if $self->{lastinvoice} < $id;
! 26: $invoice->{id} = $id;
! 27: }
! 28: }
! 29:
! 30: bless $self, $class;
! 31:
! 32: die "Need to pass filename to new: $!" unless $file;
! 33:
! 34: return $self;
! 35: }
! 36:
! 37: sub next_invoice_id {
! 38: my ($self) = @_;
! 39: return $self->{lastinvoice} + 1;
! 40: }
! 41:
! 42: sub add_invoice {
! 43: my ( $self, $invoice ) = @_;
! 44:
! 45: my $id = $invoice->{id} || $self->next_invoice_id;
! 46:
! 47: croak "Can't add duplicate invoice $id\n"
! 48: if exists $self->{invoice}->{$id};
! 49:
! 50: $invoice->{id} ||= $id;
! 51: $invoice->{invdate} ||= DateTime->now( time_zone => 'local' )->ymd,
! 52:
! 53: $self->{lastinvoice} = $id if $self->{lastinvoice} < $id;
! 54:
! 55: my %li;
! 56: foreach my $k (
! 57: qw/
! 58: id custid
! 59: file transactions
! 60: invdate start end
! 61: total past_due total_due
! 62: /
! 63: )
! 64: {
! 65: my $v = $invoice->{$k};
! 66:
! 67: if ( defined $v && length $v ) {
! 68: if ( ref $v eq 'DateTime' ) {
! 69: $li{$k} = $v->ymd;
! 70: }
! 71: else {
! 72: $li{$k} = $v;
! 73: }
! 74: }
! 75: }
! 76:
! 77: $self->{invoice}->{ $self->{lastinvoice} } = \%li;
! 78: delete $self->{_tables};
! 79:
! 80: return $self->{lastinvoice};
! 81: }
! 82:
! 83: sub get_invoice{
! 84: my ( $self, $id ) = @_;
! 85: return $self->{invoice}->{$id};
! 86: }
! 87:
! 88: sub last_invoice {
! 89: my ( $self, $custid ) = @_;
! 90:
! 91: if ( !$self->{_table}->{last_invoice} ) {
! 92: my $invoices = $self->{invoice};
! 93: foreach my $id ( sort { $a <=> $b } keys %{$invoices} ) {
! 94: my $inv = $invoices->{$id};
! 95: next unless $inv->{custid};
! 96: $self->{_table}->{last_invoice}->{ $inv->{custid} } = $inv;
! 97: }
! 98: }
! 99:
! 100: return $self->{_table}->{last_invoice}->{$custid};
! 101: }
! 102:
! 103: sub txn_is_invoiced {
! 104: my ( $self, $txn ) = @_;
! 105:
! 106: if ( !$self->{_table}->{txn} ) {
! 107: my $invoices = $self->{invoice};
! 108: foreach my $id ( sort { $a <=> $b } keys %{$invoices} ) {
! 109: my $inv = $invoices->{$id};
! 110: foreach my $t ( @{ $inv->{transactions} } ) {
! 111: $self->{_table}->{txn}->{$t} = 1;
! 112: }
! 113: }
! 114: }
! 115: return $self->{_table}->{txn}->{$txn};
! 116: }
! 117:
! 118: sub unpaid_invoices {
! 119: my ($self, $custid) = @_;
! 120:
! 121: $self->_match_payments;
! 122: return $self->{_table}->{unpaid}->{$custid};
! 123: }
! 124:
! 125: sub save {
! 126: my ($self) = @_;
! 127:
! 128: delete $self->{_table};
! 129: delete $self->{lastinvoice};
! 130: foreach my $invoice ( values %{ $self->{invoice} } ) {
! 131: delete $invoice->{id};
! 132: }
! 133: DumpFile( $file, {%$self} ) or die "Unable to save state: $!";
! 134: }
! 135:
! 136: sub _match_payments {
! 137: my ($self) = @_;
! 138:
! 139: return if $self->{_table}{credit} && $self->{_table}{unpaid};
! 140:
! 141: my $invoices = $self->{invoice};
! 142: my %owes = map { $_ => $invoices->{$_}->{total} } keys %{ $invoices };
! 143:
! 144: my %credit;
! 145:
! 146: foreach my $custid ( keys %{ $self->{payment} } ) {
! 147: $credit{$custid} = 0;
! 148:
! 149: my $payments = $self->{payment}->{$custid};
! 150: foreach my $p ( @{$payments} ) {
! 151: my $paid = $p->{paid};
! 152: $p->{invoices} ||= [];
! 153:
! 154: foreach my $id ( @{ $p->{invoices} } ) {
! 155: $owes{$id} ||= 0;
! 156:
! 157: if ( $owes{$id} == $paid ) {
! 158: $owes{$id} = 0;
! 159: $paid = 0;
! 160: }
! 161: elsif ( $owes{$id} > $paid ) {
! 162: $owes{$id} -= $paid;
! 163: $paid = 0;
! 164: }
! 165: elsif ( $owes{$id} < $paid ) {
! 166: $paid -= $owes{$id};
! 167: $owes{$id} = 0;
! 168: }
! 169: }
! 170:
! 171: $credit{$custid} += $paid;
! 172: }
! 173:
! 174: delete $credit{$custid} unless $credit{$custid};
! 175: }
! 176:
! 177: foreach my $id ( sort { $b <=> $a } keys %owes ) {
! 178: my $i = $invoices->{$id};
! 179: my $custid = $i->{custid} or next;
! 180:
! 181: my $owes = sprintf "%0.2f", $owes{$id} || 0;
! 182: my $paid = sprintf "%0.2f", $credit{$custid} || 0;
! 183:
! 184: if ( $owes == $paid ) {
! 185: $owes = 0;
! 186: $paid = 0;
! 187: }
! 188: elsif ( $owes > $paid ) {
! 189: $owes -= $paid;
! 190: $paid = 0;
! 191: }
! 192: elsif ( $owes < $paid ) {
! 193: $paid -= $owes;
! 194: $owes = 0;
! 195: }
! 196:
! 197: $self->{_table}{unpaid}{$custid}{$id} = $owes if $owes;
! 198:
! 199: if ($paid) {
! 200: $credit{$custid} = $paid;
! 201: }
! 202: elsif (exists $credit{$custid}) {
! 203: delete $credit{$custid};
! 204: }
! 205: }
! 206:
! 207: $self->{_table}{credit} = \%credit;
! 208: }
! 209:
! 210: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>