[BACK]Return to pta_import.pl CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / pta

Annotation of pta/pta_import.pl, Revision 1.11

1.1       schwarze    1: #!/usr/bin/perl
                      2:
                      3: # Copyright (c) 2020 Freda Bundchen
                      4:
                      5: # Permission to use, copy, modify, and distribute this software for any
                      6: # purpose with or without fee is hereby granted, provided that the above
                      7: # copyright notice and this permission notice appear in all copies.
                      8: #
                      9: # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10: # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11: # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12: # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13: # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14: # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15: # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:
                     17: use warnings;
                     18: use strict;
                     19:
1.9       schwarze   20: use Getopt::Std qw(getopts);
                     21:
                     22: our ($opt_I);
                     23:
1.1       schwarze   24: # === SUBROUTINES  =====================================================
                     25:
1.10      schwarze   26: sub import_account ($$$$$) {
                     27:        my ($account_name, $accounts_ref, $bookings_ref,
                     28:            $compiled_ref, $csv_account) = @_;
                     29:        my ($account, $amount, $booking, $credit, $date, $debit,
                     30:            $description);
1.5       schwarze   31:        chomp(my $header = <>);
1.2       schwarze   32:        while (<>) {
1.5       schwarze   33:                next if (/^$/);
1.1       schwarze   34:                chomp;
1.3       schwarze   35:                my $line = $_;
1.5       schwarze   36:                foreach my $regex (@$compiled_ref) {
1.3       schwarze   37:                        if ($line =~ /$regex/) {
1.5       schwarze   38:                                $account = %$accounts_ref{$regex};
                     39:                                $booking = %$bookings_ref{$regex};
1.4       schwarze   40:                                last;
1.3       schwarze   41:                        }
                     42:                }
1.10      schwarze   43:                if ($account_name eq "chase_credit") {
                     44:                        ($date, $amount, $debit, $credit,
                     45:                            $description) =
                     46:                            import_chase_credit($account,
                     47:                            $csv_account, $line);
                     48:                } elsif ($account_name eq "capital_one_credit") {
                     49:                        ($date, $amount, $debit, $credit,
                     50:                            $description) =
                     51:                            import_capital_one_credit($account,
                     52:                            $csv_account, $line);
                     53:                } elsif ($account_name eq "optum_hsa") {
                     54:                        ($date, $amount, $debit, $credit,
                     55:                            $description) =
                     56:                            import_optum_hsa($account,
                     57:                            $csv_account, $line);
1.11    ! schwarze   58:                } elsif ($account_name eq "sparkasse_camt") {
        !            59:                        ($date, $amount, $debit, $credit,
        !            60:                            $description) =
        !            61:                            import_sparkasse_camt($account,
        !            62:                            $csv_account, $line);
1.10      schwarze   63:                } else {
                     64:                        die "undefined format: $account_name";
                     65:                }
                     66:                unless ($date && $booking && $debit && $credit &&
                     67:                    $amount && $description) {
1.5       schwarze   68:                        die "import parse error: $line";
1.3       schwarze   69:                }
1.10      schwarze   70:                $description =~ s/#//g;
                     71:                print "$date $booking $debit $credit $amount " .
1.1       schwarze   72:                    "$description\n";
                     73:        }
                     74: }
                     75:
1.10      schwarze   76: sub import_chase_credit ($$$) {
                     77:        my ($account, $csv_account, $line) = @_;
                     78:        my ($trans_date, $post_date, $description, $category,
                     79:            $type, $amount) = split /,/, $line;
                     80:        my ($debit, $credit);
                     81:        $post_date =~ s#(\d+)/(\d+)/(\d+)#$3$1$2#;
                     82:        ($amount, $debit, $credit) =
                     83:            get_accounts_by_amount_sign($amount, $account,
                     84:            $csv_account);
                     85:        return ($post_date, $amount, $debit, $credit, $description);
                     86: }
                     87:
                     88: sub import_capital_one_credit ($$$) {
                     89:        my ($account, $csv_account, $line) = @_;
                     90:        my ($trans_date, $post_date, $card_num,
                     91:            $description, $category, $csv_debit,
                     92:            $csv_credit) = split /,/, $line;
                     93:        $post_date =~ s/(\d+)-(\d+)-(\d+)/$1$2$3/;
                     94:        my ($amount, $debit, $credit) =
                     95:            get_accounts_by_csv_col($account, $csv_account,
                     96:            $csv_debit, $csv_credit);
                     97:        return ($post_date, $amount, $debit, $credit, $description);
                     98: }
                     99:
                    100: sub import_optum_hsa ($$$) {
                    101:         my ($account, $csv_account, $line) = @_;
                    102:         my ($date, $description, $amount,
                    103:             $type) = split /,/, $line;
                    104:        my ($debit, $credit);
                    105:        $date =~ s/(\d+)-(\d+)-(\d+)/$1$2$3/;
                    106:        $amount =~ s/\$//;
                    107:        ($amount, $debit, $credit) =
                    108:            get_accounts_by_amount_sign($amount, $account,
                    109:            $csv_account);
                    110:        return ($date, $amount, $debit, $credit, $description);
                    111: }
                    112:
1.11    ! schwarze  113: sub import_sparkasse_camt ($$$) {
        !           114:         my ($account, $csv_account, $line) = @_;
        !           115:        my @fields;
        !           116:        $_ = $line;
        !           117:        push @fields, $1 while s/"([^"]*)";?//;
        !           118:        $_ eq "" or die "CAMT parse error before $_ in $line";
        !           119:        @fields == 17 or die "not 17 but @fields fields: $line";
        !           120:        $fields[1] =~ s/^(\d\d)\.(\d\d)\.(\d\d)$/20$3$2$1/
        !           121:            or die "date parse error: $line";
        !           122:        $fields[14] =~ s/,/./;
        !           123:        return $fields[1],
        !           124:            get_accounts_by_amount_sign($fields[14], $account, $csv_account),
        !           125:            (join ' ', $fields[11], $fields[4]);
        !           126: }
        !           127:
1.10      schwarze  128: sub get_accounts_by_amount_sign ($$$) {
                    129:        my ($amount, $account, $csv_account) = @_;
                    130:        my ($debit, $credit);
                    131:        if ($amount <= 0) {
                    132:                $amount = substr $amount, 1;
                    133:                $credit = $csv_account;
                    134:                $debit = $account;
                    135:        } else {
                    136:                $debit = $csv_account;
                    137:                $credit = $account;
1.5       schwarze  138:        }
1.10      schwarze  139:        return ($amount, $debit, $credit);
1.5       schwarze  140: }
1.9       schwarze  141:
1.10      schwarze  142: sub get_accounts_by_csv_col ($$$$) {
                    143:        my ($account, $csv_account, $csv_debit, $csv_credit) = @_;
                    144:        my ($amount, $debit, $credit);
                    145:        if ($csv_debit eq "") {
                    146:                $amount = $csv_credit;
                    147:                $credit = $account;
                    148:                $debit = $csv_account;
                    149:        } else {
                    150:                $amount = $csv_debit;
                    151:                $credit = $csv_account;
                    152:                $debit = $account;
                    153:        }
                    154:        return ($amount, $debit, $credit);
1.9       schwarze  155: }
                    156:
                    157: sub usage () {
1.10      schwarze  158:        printf STDERR "usage: %s -I accountname csvfilename\n", $0;
1.9       schwarze  159:        exit 1;
                    160: }
                    161:
1.1       schwarze  162: # === MAIN PROGRAM =====================================================
                    163:
1.10      schwarze  164: my ($csv_account, $fn, $in, $account_name, %accounts, %bookings, @compiled);
1.9       schwarze  165: getopts 'I:' or usage;
                    166: if ($opt_I) {
1.10      schwarze  167:        $account_name = $opt_I;
                    168:        $fn = "import_" . $account_name . ".txt";
1.9       schwarze  169:        open $in, $fn or die "$fn: $!";
1.1       schwarze  170: } else {
1.9       schwarze  171:        usage;
                    172: }
                    173: while (<$in>) {
                    174:        chomp;
                    175:        next if /^(?:#|$)/;
                    176:        my $line = $_;
                    177:        if (/^ACCOUNT\s+(\d+)$/) {
                    178:                $csv_account and die "duplicate ACCOUNT line: $1";
                    179:                $csv_account = $1;
                    180:                next;
                    181:        }
1.11    ! schwarze  182:        /^(.*)[,;]\s+(\d+)\s+(\S+)$/ or
1.9       schwarze  183:            die "$fn import parse error: $line";
                    184:        my ($reg, $account, $booking) = ($1, $2, $3);
1.11    ! schwarze  185:        if ($account_name eq 'sparkasse_camt') {
        !           186:                $reg =~ s/(?:^|(?<=;))(?:$|(?=;))/"[^"]*"/g;
        !           187:        } else {
        !           188:                $reg =~ s/(?:^|(?<=,))(?:$|(?=,))/[^,]*/g;
        !           189:        }
1.9       schwarze  190:        $reg = qr/$reg/;
                    191:        push @compiled, $reg;
                    192:        $bookings{$reg} = $booking;
                    193:        $accounts{$reg} = $account;
1.1       schwarze  194: }
1.9       schwarze  195: close $in;
                    196: $csv_account or die "no ACCOUNT line in $fn";
1.10      schwarze  197: import_account($account_name, \%accounts, \%bookings,
                    198:     \@compiled, $csv_account);

CVSweb