]> Dogcows Code - chaz/homebank2ledger/commitdiff
add posting-specific dates
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sat, 15 Jan 2022 23:31:46 +0000 (16:31 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sat, 15 Jan 2022 23:31:46 +0000 (16:31 -0700)
lib/App/HomeBank2Ledger.pm
lib/App/HomeBank2Ledger/Formatter/Beancount.pm
lib/App/HomeBank2Ledger/Formatter/Ledger.pm
lib/App/HomeBank2Ledger/Ledger.pm

index c4bf5a6dcacd3d17dd44ec07caf5402aee8f2226..9ff8b00a23b4dd0ab01309fd24a9d07ce76e53fa 100644 (file)
@@ -294,10 +294,12 @@ sub convert_homebank_to_ledger {
         my $memo    = $transaction->{wording} || '';
         my $payee   = $homebank->find_payee_by_key($transaction->{payee});
         my $tags    = _split_tags($transaction->{tags});
         my $memo    = $transaction->{wording} || '';
         my $payee   = $homebank->find_payee_by_key($transaction->{payee});
         my $tags    = _split_tags($transaction->{tags});
+        my $date    = $transaction->{date};
 
         my @postings;
 
         push @postings, {
 
         my @postings;
 
         push @postings, {
+            date        => $date,
             account     => $account->{ledger_name},
             amount      => $amount,
             commodity   => $commodities{$account->{currency}},
             account     => $account->{ledger_name},
             amount      => $amount,
             commodity   => $commodities{$account->{currency}},
@@ -324,9 +326,11 @@ sub convert_homebank_to_ledger {
             $seen{$transaction->{transfer_key}}++        if $transaction->{transfer_key};
             $seen{$paired_transaction->{transfer_key}}++ if $paired_transaction->{transfer_key};
 
             $seen{$transaction->{transfer_key}}++        if $transaction->{transfer_key};
             $seen{$paired_transaction->{transfer_key}}++ if $paired_transaction->{transfer_key};
 
+            my $paired_date  = $paired_transaction && $paired_transaction->{date};
             my $paired_payee = $homebank->find_payee_by_key($paired_transaction->{payee});
 
             push @postings, {
             my $paired_payee = $homebank->find_payee_by_key($paired_transaction->{payee});
 
             push @postings, {
+                date        => $paired_date,
                 account     => $dst_account->{ledger_name},
                 amount      => $paired_transaction->{amount} || -$transaction->{amount},
                 commodity   => $commodities{$dst_account->{currency}},
                 account     => $dst_account->{ledger_name},
                 amount      => $paired_transaction->{amount} || -$transaction->{amount},
                 commodity   => $commodities{$dst_account->{currency}},
@@ -360,7 +364,7 @@ sub convert_homebank_to_ledger {
                 };
             }
         }
                 };
             }
         }
-        else {  # with or without category
+        else {  # normal transaction with or without category
             my $amount          = -$transaction->{amount};
             my $category        = $homebank->find_category_by_key($transaction->{category});
             my $other_account   = $category   ? $category->{ledger_name}
             my $amount          = -$transaction->{amount};
             my $category        = $homebank->find_category_by_key($transaction->{category});
             my $other_account   = $category   ? $category->{ledger_name}
@@ -386,7 +390,7 @@ sub convert_homebank_to_ledger {
         }
 
         $ledger->add_transactions({
         }
 
         $ledger->add_transactions({
-            date        => $transaction->{date},
+            date        => $date,
             payee       => $payee->{name},
             memo        => $memo,
             postings    => \@postings,
             payee       => $payee->{name},
             memo        => $memo,
             postings    => \@postings,
index dc9893499e9a8c3186e03410237dcef7e668282d..ca1510876a032a77fb766800d429d09aac0a3c75 100644 (file)
@@ -172,7 +172,7 @@ sub _format_transaction {
     my $date        = $transaction->{date};
     my $status      = $transaction->{status};
     my $payee       = $transaction->{payee} || '';
     my $date        = $transaction->{date};
     my $status      = $transaction->{status};
     my $payee       = $transaction->{payee} || '';
-    my $memo        = $transaction->{memo}  || '';
+    my $memo        = $transaction->{note} // $transaction->{memo} // '';
     my @postings    = @{$transaction->{postings}};
 
     my @out;
     my @postings    = @{$transaction->{postings}};
 
     my @out;
@@ -220,9 +220,10 @@ sub _format_transaction {
         push @line, '  ';
         if (defined $posting->{amount}) {
             push @line, $self->_format_amount($posting->{amount}, $posting->{commodity});
         push @line, '  ';
         if (defined $posting->{amount}) {
             push @line, $self->_format_amount($posting->{amount}, $posting->{commodity});
-            my $lot_price = $posting->{lot_price};
-            my $lot_date  = $posting->{lot_date};
-            my $lot_ref   = $posting->{lot_ref};
+            my $lot = $posting->{lot} || {};
+            my $lot_price = $lot->{price} // $posting->{lot_price};
+            my $lot_date  = $lot->{date}  // $posting->{lot_date};
+            my $lot_ref   = $lot->{ref}   // $posting->{lot_ref};
             if ($lot_price || $lot_date || $lot_ref) {
                 push @line, ' {',
                             join(', ',
             if ($lot_price || $lot_date || $lot_ref) {
                 push @line, ' {',
                             join(', ',
index 300a83281788f040c52f751551b77cf0bb4ea3a9..c6fa55668a6eb4ec02ab6a3b58117965c638124e 100644 (file)
@@ -208,16 +208,18 @@ sub _format_transaction {
 
     my $account_width = $self->account_width;
 
 
     my $account_width = $self->account_width;
 
-    my $date        = $transaction->{date};
-    my $status      = $transaction->{status};
-    my $payee       = $self->_format_string($transaction->{payee} || '');
-    my $memo        = $self->_format_string($transaction->{memo}  || '');
-    my @postings    = @{$transaction->{postings}};
+    my $date        = $transaction->{date} or _croak 'Transaction date is required';
+    my $aux_date    = $transaction->{aux_date} || $transaction->{effective_date} || '';
+    my $status      = $transaction->{status} // '';
+    my $code        = $transaction->{code};
+    my $payee       = $self->_format_string($transaction->{payee});
+    my $note        = $self->_format_string($transaction->{note} // $transaction->{memo});
+    my @postings    = @{$transaction->{postings} || _croak 'At least one transaction posting is required'};
 
     my @out;
 
     # figure out the Ledger transaction status
 
     my @out;
 
     # figure out the Ledger transaction status
-    my $status_symbol = $STATUS_SYMBOLS{$status || ''};
+    my $status_symbol = $STATUS_SYMBOLS{$status};
     if (!$status_symbol) {
         my %posting_statuses = map { ($_->{status} || '') => 1 } @postings;
         if (keys(%posting_statuses) == 1) {
     if (!$status_symbol) {
         my %posting_statuses = map { ($_->{status} || '') => 1 } @postings;
         if (keys(%posting_statuses) == 1) {
@@ -226,17 +228,28 @@ sub _format_transaction {
         }
     }
 
         }
     }
 
-    $payee =~ s/(?:  )|\t;/ ;/g;    # don't turn into a memo
+    $aux_date = '' if $date eq $aux_date;
+    $code =~ s/[\(\)]+// if defined $code;
+    $payee =~ s/(?:  )|\t;/ ;/g if defined $payee;    # don't turn into a note
 
 
-    push @out, sprintf('%s%s%s%s', $date,
-        $status_symbol && " ${status_symbol}",
-        $payee         && " $payee",
-        $memo          && "  ; $memo",
+    my $has_code = defined $code && $code ne '';
+    my $has_payee = defined $payee && $payee ne '';
+    my $has_note = defined $note && $note ne '';
+
+    push @out, join('', $date,
+        $aux_date               && "=${aux_date}",
+        $status_symbol          && " ${status_symbol}",
+        $has_code               && " (${code})",
+        $has_payee              && " ${payee}",
+        $has_note && $has_payee && "  ; ${note}",
     );
     );
+    if ($has_note && !$has_payee) {
+        push @out, "    ; ${note}";
+    }
 
     my $metadata = $transaction->{metadata} || {};
     for my $key (sort keys %$metadata) {
 
     my $metadata = $transaction->{metadata} || {};
     for my $key (sort keys %$metadata) {
-        my $value = $self->_format_string($metadata->{$key});
+        my $value = $self->_format_string($metadata->{$key}) ;
         push @out, "    ; ${key}: ${value}";
     }
 
         push @out, "    ; ${key}: ${value}";
     }
 
@@ -253,15 +266,21 @@ sub _format_transaction {
         push @line, '  ';
         if (defined $posting->{amount}) {
             push @line, $self->_format_amount($posting->{amount}, $posting->{commodity});
         push @line, '  ';
         if (defined $posting->{amount}) {
             push @line, $self->_format_amount($posting->{amount}, $posting->{commodity});
-            if (my $price = $posting->{lot_price}) {
-                my $is_fixed = $posting->{lot_fixed};
+            my $lot = $posting->{lot} || {};
+            if (my $lot_price = $lot->{price} // $posting->{lot_price}) {
+                my $is_fixed = $lot_price->{fixed} // $posting->{lot_fixed};
                 my $fixed_symbol = $is_fixed ? '=' : '';
                 push @line, " {${fixed_symbol}",
                 my $fixed_symbol = $is_fixed ? '=' : '';
                 push @line, " {${fixed_symbol}",
-                            $self->_format_amount($price->{amount}, $price->{commodity}),
+                            $self->_format_amount($lot_price->{amount}, $lot_price->{commodity}),
                             '}';
             }
                             '}';
             }
-            if (my $lot_date = $posting->{lot_date}) {
-                push @line, " [$posting->{lot_date}]";
+            if (my $lot_date = $lot->{date} // $posting->{lot_date}) {
+                push @line, " [${lot_date}]";
+            }
+            if (my $lot_note = $self->_format_string($lot->{note} // $posting->{lot_note} // '')) {
+                $lot_note =~ s/[\(\)]+//;   # cleanup
+                $lot_note =~ s/^\@+//;
+                push @line, " (${lot_note})" if $lot_note;
             }
             if (my $cost = $posting->{total_cost} // $posting->{cost}) {
                 my $is_total = defined $posting->{total_cost};
             }
             if (my $cost = $posting->{total_cost} // $posting->{cost}) {
                 my $is_total = defined $posting->{total_cost};
@@ -270,9 +289,22 @@ sub _format_transaction {
                             $self->_format_amount($cost->{amount}, $cost->{commodity});
             }
         }
                             $self->_format_amount($cost->{amount}, $cost->{commodity});
             }
         }
-        if (my $note = $posting->{note}) {
-            $note = $self->_format_string($note);
-            push @line, "  ; $note" if $note ne $memo;
+        my $posting_date        = $posting->{date} || '';
+        my $posting_aux_date    = $posting->{aux_date} || '';
+        my $posting_note        = $self->_format_string($posting->{note} // $posting->{memo} // '');
+        $posting_date       = '' if $posting_date eq $date;
+        $posting_aux_date   = '' if $posting_aux_date eq $aux_date;
+        $posting_note       = '' if $has_note && $posting_note eq $note;
+        my $has_posting_note = defined $posting_note && $posting_note ne '';
+        if ($posting_date || $posting_aux_date || $has_posting_note) {
+            if ($posting_date || $posting_aux_date) {
+                $posting_note = sprintf('[%s%s]%s',
+                    $posting_date,
+                    $posting_aux_date && "=${posting_aux_date}",
+                    $has_posting_note && " ${posting_note}",
+                );
+            }
+            push @line, "  ; ${posting_note}";
         }
 
         push @out, join('', @line);
         }
 
         push @out, join('', @line);
@@ -283,9 +315,8 @@ sub _format_transaction {
             push @out, "      ; ${key}: ${value}";
         }
 
             push @out, "      ; ${key}: ${value}";
         }
 
-        if (my $posting_payee = $posting->{payee}) {
-            $posting_payee = $self->_format_string($posting_payee);
-            push @out, "      ; Payee: $posting_payee" if $posting_payee ne $payee;
+        if (my $posting_payee = $self->_format_string($posting->{payee} // '')) {
+            push @out, "      ; Payee: $posting_payee" if !$has_payee || $posting_payee ne $payee;
         }
 
         if (my @tags = @{$posting->{tags} || []}) {
         }
 
         if (my @tags = @{$posting->{tags} || []}) {
@@ -300,7 +331,7 @@ sub _format_transaction {
 
 sub _format_string {
     my $self = shift;
 
 sub _format_string {
     my $self = shift;
-    my $str  = shift;
+    my $str  = shift // return;
     $str =~ s/\v//g;
     return $str;
 }
     $str =~ s/\v//g;
     return $str;
 }
index 72a0953fac64d30f561b50b189512cda1ddaca95..2c8f15eda65899cff859080f60809c5490e3aa47 100644 (file)
@@ -24,7 +24,7 @@ accounts. Examples:
 
 =for :list
 * "Assets:Bank:Chase1234"
 
 =for :list
 * "Assets:Bank:Chase1234"
-* "Liabilities:Credit Card:CapitalOne"
+* "Liabilities:Credit Card:Capital One"
 
 =head2 commodity
 
 
 =head2 commodity
 
@@ -51,9 +51,11 @@ This is a hashref like this:
 
     {
         date        => '2019-06-12',        # required
 
     {
         date        => '2019-06-12',        # required
-        payee       => 'Malcolm Reynolds',  # required
+        aux_date    => '2019-06-13',        # optional
         status      => 'cleared',           # optional; can be "cleared" or "pending"
         status      => 'cleared',           # optional; can be "cleared" or "pending"
-        memo        => 'Medical supplies',  # optional
+        code        => '1234',              # optional
+        payee       => 'Malcolm Reynolds',  # required
+        note        => 'Medical supplies',  # optional
         postings    => [                    # required
             {
                 account     => 'Some Account',  # required
         postings    => [                    # required
             {
                 account     => 'Some Account',  # required
@@ -69,9 +71,20 @@ This is a hashref like this:
                     frac    => 2,
                 },
                 payee       => 'Somebody',      # optional
                     frac    => 2,
                 },
                 payee       => 'Somebody',      # optional
-                memo        => 'Whatever',      # optional
+                note        => 'Whatever',      # optional
                 status      => 'pending',       # optional; can be "cleared" or "pending"
                 tags        => [qw(niska train-job)],
                 status      => 'pending',       # optional; can be "cleared" or "pending"
                 tags        => [qw(niska train-job)],
+                lot         => {                # optional
+                    date        => '2019-01-28',
+                    price       => {
+                        amount      => '15.00',
+                        commodity   => { ... },
+                    },
+                },
+                cost        => {                # optional
+                    amount      => '10.00',
+                    commodity   => { ... },
+                },
             },
             ...
         ],
             },
             ...
         ],
This page took 0.031414 seconds and 4 git commands to generate.