Repository: beancount/beancount

Issue:
Pad gets incorrect difference with forecast plugin
I am using the forecast plugin to set down some income, and when I try adding pad/balance at the end of the year, it's not generating the correct amount to match the given balance.

versions: 
beancount 2.3.5
python 3.10.4

Here is the sample beancount file for testing:

```
plugin "beancount.plugins.forecast"

2022-01-01 open Assets:Income
2022-01-01 open Income:Fulltime
2022-01-01 open Equity:Opening-Balances

2022-01-01 # "Income [MONTHLY UNTIL 2022-03-01]"
    Income:Fulltime               -1000 AUD
    Assets:Income                  1000 AUD

2022-12-24 pad Assets:Income Equity:Opening-Balances
2022-12-25 balance Assets:Income   3000 AUD

```

results for `bean-check`

```
Balance failed for 'Assets:Income': expected 3000 AUD != accumulated 5000 AUD (2000 too much)

   2022-12-25 balance Assets:Income                                   3000 AUD
```

the generated pad transaction:

```
** Balances before transaction --------------------------------

  Assets:Income                                                     3000 AUD

  Equity:Opening-Balances                                                   


** Unbooked Transaction --------------------------------

2022-12-24 P "(Padding inserted for Balance of 3000 AUD for difference 2000 AUD)"
  Assets:Income             2000 AUD
  Equity:Opening-Balances  -2000 AUD


** Transaction --------------------------------

2022-12-24 P "(Padding inserted for Balance of 3000 AUD for difference 2000 AUD)"
  Assets:Income             2000 AUD
  Equity:Opening-Balances  -2000 AUD


** Residual and Tolerances --------------------------------



** Balances after transaction --------------------------------

* Assets:Income                                                     5000 AUD

* Equity:Opening-Balances                                          -2000 AUD
```

I expect a unused pad entry in above case, which it should report:
```
Unused Pad entry
  2022-12-24 pad Assets:Income Equity:Opening-Balances
```


Discussion:
I read the source code and found a workaround by moving the `forecast` before `pad`:
```
option "plugin_processing_mode" "raw"

plugin "beancount.ops.documents"
plugin "beancount.plugins.forecast" ; <--
plugin "beancount.ops.pad"
plugin "beancount.ops.balance"
```



Patch:
diff --git a/beancount/loader.py b/beancount/loader.py
index a4b1ec35f..01ccbba61 100644
--- a/beancount/loader.py
+++ b/beancount/loader.py
@@ -42,7 +42,6 @@
 
 # List of default plugins to run.
 PLUGINS_PRE = [
-    ("beancount.ops.pad", None),
     ("beancount.ops.documents", None),
     ]
 
@@ -54,6 +53,7 @@
 PLUGINS_AUTO = []
 
 PLUGINS_POST = [
+    ("beancount.ops.pad", None),
     ("beancount.ops.balance", None),
     ]
 


Test patch:
diff --git a/beancount/ops/pad_test.py b/beancount/ops/pad_test.py
index b1da7528f..ada070c74 100644
--- a/beancount/ops/pad_test.py
+++ b/beancount/ops/pad_test.py
@@ -3,6 +3,9 @@
 
 import datetime
 import unittest
+import tempfile
+from os import path
+import textwrap
 
 from beancount.core.amount import A
 from beancount.core import inventory
@@ -13,7 +16,6 @@
 from beancount.parser import cmptest
 from beancount import loader
 
-
 class TestPadding(cmptest.TestCase):
 
     @loader.load_doc()
@@ -570,6 +572,68 @@ def test_pad_issue362(self, entries, errors, __):
         # self.assertRegex(errors[0].message, "Balance failed")
         # self.assertEqual(datetime.date(2015, 9, 15), errors[0].entry.date)
 
+    def test_pad_plugin_modify(self):
+        with tempfile.TemporaryDirectory() as tmpdir:
+            ledger_fn = path.join(tmpdir, 'my.beancount')
+            with open(ledger_fn, 'w') as ledger_file:
+                ledger_file.write(textwrap.dedent("""
+                    option "insert_pythonpath" "True"
+                    plugin "plugin_temp"
+
+                    2020-01-01 open Equity:Opening-Balances
+                    2020-01-01 open Assets:Checking
+                    2020-01-01 open Assets:Cash
+
+                    2023-02-01 * "Add 20$"
+                      Assets:Checking            20.0 USD
+                      Assets:Cash               -20.0 USD
+
+                    2023-03-01 pad Assets:Checking Equity:Opening-Balances
+                    2023-03-02 balance Assets:Checking 100.0 USD
+                    """))
+
+            plugin_fn = path.join(tmpdir, 'plugin_temp.py')
+            with open(plugin_fn, 'w') as plugin_file:
+                plugin_file.write(textwrap.dedent("""
+                    from beancount.core import data
+
+                    __plugins__ = ('plugin_temp',)
+
+                    def plugin_temp(entries, unused_options_map):
+                        new_entries = list(
+                                e._replace(narration=e.narration + " - Duplicate")
+                                for e in data.filter_txns(entries)
+                                if e.flag == '*'
+                                )
+                        return new_entries + entries, []
+                    """))
+            entries, errors, options_map = loader.load_file(ledger_fn)
+
+        self.assertFalse(errors)
+        self.assertEqualEntries("""
+            option "insert_pythonpath" "True"
+            plugin "plugin_temp"
+
+            2020-01-01 open Equity:Opening-Balances
+            2020-01-01 open Assets:Checking
+            2020-01-01 open Assets:Cash
+
+            2023-02-01 * "Add 20$ - Duplicate"
+              Assets:Checking            20.0 USD
+              Assets:Cash               -20.0 USD
+
+            2023-02-01 * "Add 20$"
+              Assets:Checking            20.0 USD
+              Assets:Cash               -20.0 USD
+
+            2023-03-01 pad Assets:Checking Equity:Opening-Balances
+
+            2023-03-01 P "(Padding inserted for Balance of 100.0 USD for difference 60.0 USD)"
+              Assets:Checking                                                        60.0 USD
+              Equity:Opening-Balances                                                -60.0 USD
+
+            2023-03-02 balance Assets:Checking 100.0 USD
+            """, entries)
 
 if __name__ == '__main__':
     unittest.main()