From d5830f0971fc5dc74f89cd260dfb2725a606ef19 Mon Sep 17 00:00:00 2001 From: Matthew Bafford Date: Sat, 17 Oct 2020 11:43:44 -0400 Subject: [PATCH] Amazon: Support for grocery orders (weighed, tip) Support for multiple pricing formats involving weighed items: * 1 of: 365 Everyday Value, Potato Yellow Bag Organic, 48 Ounce * 2 (1.04 lb) of: Broccoli Crowns Conventional, 1 Each * 2.07 lb of: Pork Sausage Link Italian Mild Step 1 And ensure the final price for the item is the amount Amazon charged and not the amount charged multiplied by the "quantity" weighed. This labels each weighed item entry as a single quantity. Also add support for parsing out tip left for delivery driver. --- beancount_import/amount_parsing.py | 6 +- beancount_import/source/amazon_invoice.py | 58 +- .../source/amazon/114-4993473-6978631.html | 570 ++++++++++++++++++ .../test_basic/import_results.beancount | 94 +++ .../import_results.beancount | 74 +++ .../import_results.beancount | 74 +++ .../test_prediction/import_results.beancount | 74 +++ 7 files changed, 934 insertions(+), 16 deletions(-) create mode 100644 testdata/source/amazon/114-4993473-6978631.html diff --git a/beancount_import/amount_parsing.py b/beancount_import/amount_parsing.py index db5e4213..79e25c2c 100644 --- a/beancount_import/amount_parsing.py +++ b/beancount_import/amount_parsing.py @@ -25,18 +25,20 @@ def parse_number(x): sign, number_str = parse_possible_negative(x) return sign * D(number_str) -def parse_amount(x): +def parse_amount(x, assumed_currency=None): """Parses a number and currency.""" if not x: return None sign, amount_str = parse_possible_negative(x) - m = re.fullmatch(r'([\$€£])?((?:[0-9](?:,?[0-9])*|(?=\.))(?:\.[0-9]+)?)(?:\s+([A-Z]{3}))?', amount_str) + m = re.fullmatch(r'(?:[(][^)]+[)])?\s*([\$€£])?((?:[0-9](?:,?[0-9])*|(?=\.))(?:\.[0-9]+)?)(?:\s+([A-Z]{3}))?', amount_str) if m is None: raise ValueError('Failed to parse amount from %r' % amount_str) if m.group(1): currency = {'$': 'USD', '€': 'EUR', '£': 'GBP'}[m.group(1)] elif m.group(3): currency = m.group(3) + elif assumed_currency is not None: + currency = assumed_currency else: raise ValueError('Failed to determine currency from %r' % amount_str) number = D(m.group(2)) diff --git a/beancount_import/source/amazon_invoice.py b/beancount_import/source/amazon_invoice.py index 97a7365e..b7fc2130 100644 --- a/beancount_import/source/amazon_invoice.py +++ b/beancount_import/source/amazon_invoice.py @@ -80,7 +80,7 @@ '(?:.*) Discount', 'Gift[ -]Wrap', ]) + ') *:') -posttax_adjustment_fields_pattern = r'Gift Card Amount:|Rewards Points:|Recycle Fee \$X' +posttax_adjustment_fields_pattern = r'Gift Card Amount:|Rewards Points:|Tip [(]optional[)]:|Recycle Fee \$X' def to_json(obj): @@ -127,12 +127,13 @@ def predicate(node): return results -def get_adjustments_in_table(table, pattern): +def get_adjustments_in_table(table, pattern, assumed_currency=None): adjustments = [] for label, amount_str in get_field_in_table( table, pattern, allow_multiple=True, return_label=True): adjustments.append( - Adjustment(amount=parse_amount(amount_str), description=label)) + Adjustment(amount=parse_amount(amount_str, assumed_currency), + description=label)) return adjustments @@ -198,15 +199,41 @@ def is_items_ordered_header(node): price_node = tds[1] price = price_node.text.strip() - pattern_without_condition = r'^\s*(?P[0-9]+)\s+of:(?P.*)\n\s*(?:Sold|Provided) by:? (?P[^\n]+)' + price = parse_amount(price) + if price is None: + price = Amount(D(0), 'USD') + + # 1 of: 365 Everyday Value, Potato Yellow Bag Organic, 48 Ounce + # 2 (1.04 lb) of: Broccoli Crowns Conventional, 1 Each + # 2.07 lb of: Pork Sausage Link Italian Mild Step 1 + + pattern_quantity = r'^\s*(?:(?P[0-9]+)|(?P[0-9.]+\s+(?:lb|kg))|(?:(?P[0-9.]+) [(](?P[^)]+)[)]))\s+of:' + m = re.match(pattern_quantity, description_node.text, re.UNICODE|re.DOTALL) + quantity = 1 + if m is not None: + # Amazon will say you got, e.g. 2 broccoli crowns at $1.69/lb - but then this code multiplies the 2 by the price listed + # on the invoice, which is the total price in this case (but the per-unit price in other cases) - so if there's a quantity + # and a weight, ignore the quantity and treat it as 1 + # alternately, capture the weight and the per-unit price and multiply out + quantity = m.group("quantity") # ignore quantity for weight items + + if quantity is None: + #print("Unable to extract quantity, using 1: %s" % description_node.text) + quantity = D(1) + else: + quantity = D(quantity) + + text = description_node.text.split("of:",1)[1] + + pattern_without_condition = r'(?P.*)\n\s*(?:Sold|Provided) by:? (?P[^\n]+)' pattern_with_condition = pattern_without_condition + r'\n.*\n\s*Condition: (?P[^\n]+)' - m = re.match(pattern_with_condition, description_node.text, - re.UNICODE | re.DOTALL) + m = re.match(pattern_with_condition, text, re.UNICODE | re.DOTALL) if m is None: - m = re.match(pattern_without_condition, description_node.text, - re.UNICODE | re.DOTALL) - assert m is not None + m = re.match(pattern_without_condition, text, re.UNICODE | re.DOTALL) + if m is None: + raise Exception("Could not extract item from row", text) + description = re.sub(r'\s+', ' ', m.group('description').strip()) sold_by = re.sub(r'\s+', ' ', m.group('sold_by').strip()) try: @@ -218,11 +245,11 @@ def is_items_ordered_header(node): sold_by = sold_by[:-len(suffix)] items.append( Item( - quantity=D(m.group('quantity')), + quantity=quantity, description=description, sold_by=sold_by, condition=condition, - price=parse_amount(price), + price=price, )) items_subtotal = parse_amount( @@ -374,11 +401,16 @@ def parse_regular_order_invoice(path: str) -> Order: payments_total_adjustments = [] shipments_total_adjustments = [] + # parse first to get an idea of the working currency + grand_total = parse_amount( + get_field_in_table(payment_table, 'Grand Total:')) + def resolve_posttax_adjustments(): payment_adjustments.update( reduce_adjustments( get_adjustments_in_table(payment_table, - posttax_adjustment_fields_pattern))) + posttax_adjustment_fields_pattern, + assumed_currency=grand_total.currency))) all_shipments_adjustments = collections.OrderedDict( reduce_adjustments( sum((x.posttax_adjustments for x in shipments), []))) @@ -419,8 +451,6 @@ def resolve_posttax_adjustments(): payments_total_adjustment = reduce_amounts(payments_total_adjustments) shipments_total_adjustment = reduce_amounts(shipments_total_adjustments) - grand_total = parse_amount( - get_field_in_table(payment_table, 'Grand Total:')) expected_total = add_amount(shipments_total_adjustment, reduce_amounts(x.total for x in shipments)) diff --git a/testdata/source/amazon/114-4993473-6978631.html b/testdata/source/amazon/114-4993473-6978631.html new file mode 100644 index 00000000..96ce1af3 --- /dev/null +++ b/testdata/source/amazon/114-4993473-6978631.html @@ -0,0 +1,570 @@ + + + Amazon.com - Order 114-4993473-6978631 + + + +
+ + +
+
+ Final Details for Order #114-4993473-6978631 +
+ +

+ + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + Order Placed: + + September 1, 2020 +
+ Amazon.com order number: + 114-4993473-6978631 +
+ Order Total: + $32.05 +
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + +
+
+ Shipped on September 1, 2020 +
+
+
+ + + + +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Items Ordered + + Price +
+ + 2 (1.04 lb) + + of: + + Broccoli Crowns Conventional, 1 Each
+ + + + Sold by: Whole Foods Market + + + + + + + + + + + + +
+ + + +
+ + Condition: New
+ + +
+ +
+ + ($1.69/lb) + $1.76
+ +
+ + 2.07 lb + + of: + + Pork Sausage Link Italian Mild Step 1
+ + + + Sold by: Whole Foods Market + + + + + + + + + + + + +
+ + + +
+ + Condition: New
+ + +
+ +
+ + ($6.99/lb) + $14.47
+ +
+ + 3 (2.32 lb) + + of: + + Yellow Squash
+ + + + Sold by: Whole Foods Market + + + + + + + + + + + + +
+ + + +
+ + Condition: New
+ + +
+ +
+ + ($1.99/lb) + $4.62
+ +
+ + 10 (3.85 lb) + + of: + + Banana Conventional, 1 Each
+ + + + Sold by: Whole Foods Market + + + + + + + + + + + + +
+ + + +
+ + Condition: New
+ + +
+ +
+ + ($0.49/lb) + $1.89
+ +
+ + 4 (1.52 lb) + + of: + + Peach Tree Ripe Organic, 1 Each
+ + + + Sold by: Whole Foods Market + + + + + + + + + + + + +
+ + + +
+ + Condition: New
+ + +
+ +
+ + ($1.99/lb) + $3.02
+ +
+
+
+
+ + + + + +
+ + + +Shipping Address: + + + + +
+ + + + + + + + + + + + + + + + + + + +
+Shipping Speed: + + + + +
+Scheduled delivery +
+ + + + + + + + + +
+ +
+ +
+
+
+ +
+ + + + + + + + +
+ + + + + + + + + + +
+ + + + +
+
Payment information
+
+
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Item(s) Subtotal: $25.76
Shipping & Handling:$0.00
 -----
Total before tax:$25.76
Estimated tax to be collected:$1.29
 -----
Tip (optional):5.00
 -----
Grand Total:$32.05
+ +
+ + + + + + +Payment Method: + + +
+ + + Amazon.com Visa Signature + | Last digits: 1234 +
+ +
+
+ + + + + +
+
Credit Card transactions 
+
+ + + + + + + + + + + + + + + +
+ Visa ending in 1234: September 3, 2020: + + $5.00 +
+ Visa ending in 1234: September 1, 2020: + + $27.05 +
+ +
+
+
+ + + +
+ + + + + diff --git a/testdata/source/amazon/test_basic/import_results.beancount b/testdata/source/amazon/test_basic/import_results.beancount index f89f4035..25aa6a1a 100644 --- a/testdata/source/amazon/test_basic/import_results.beancount +++ b/testdata/source/amazon/test_basic/import_results.beancount @@ -447,3 +447,97 @@ Expenses:FIXME 0.00 USD amazon_credit_card_description: "Amazon.com Visa Signature ending in 1234" transaction_date: 2019-09-18 + +;; date: 2020-09-01 +;; info: {"filename": "/114-4993473-6978631.html", "type": "text/html"} + +; features: [ +; { +; "amount": "1.29 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_item_description": [ +; "Broccoli Crowns Conventional, 1 Each", +; "Pork Sausage Link Italian Mild Step 1", +; "Yellow Squash", +; "Banana Conventional, 1 Each", +; "Peach Tree Ripe Organic, 1 Each" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "5.00 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_posttax_adjustment": [ +; "Tip (optional)" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "-5.00 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_credit_card_description": [ +; "Visa ending in 1234" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "-27.05 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_credit_card_description": [ +; "Visa ending in 1234" +; ] +; }, +; "source_account": "" +; } +; ] +2020-09-01 * "Amazon.com" "Order" + amazon_account: "name@domain.com" + amazon_order_id: "114-4993473-6978631" + associated_data0: "{\"description\": \"Amazon order invoice\", \"meta\": [\"amazon_order_id\", \"114-4993473-6978631\"], \"path\": \"/114-4993473-6978631.html\", \"type\": \"text/html\"}" + Expenses:FIXME:A 1.76 USD + amazon_item_condition: "New" + amazon_item_description: "Broccoli Crowns Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 14.47 USD + amazon_item_condition: "New" + amazon_item_description: "Pork Sausage Link Italian Mild Step 1" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 4.62 USD + amazon_item_condition: "New" + amazon_item_description: "Yellow Squash" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.89 USD + amazon_item_condition: "New" + amazon_item_description: "Banana Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 3.02 USD + amazon_item_condition: "New" + amazon_item_description: "Peach Tree Ripe Organic, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.29 USD + amazon_invoice_description: "Sales Tax" + Expenses:FIXME 5.00 USD + amazon_posttax_adjustment: "Tip (optional)" + Expenses:FIXME -5.00 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-03 + Expenses:FIXME -27.05 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-01 diff --git a/testdata/source/amazon/test_cleared_and_invalid/import_results.beancount b/testdata/source/amazon/test_cleared_and_invalid/import_results.beancount index d332f23e..11a2a4a2 100644 --- a/testdata/source/amazon/test_cleared_and_invalid/import_results.beancount +++ b/testdata/source/amazon/test_cleared_and_invalid/import_results.beancount @@ -148,3 +148,77 @@ Liabilities:Credit-Card 0.00 USD amazon_credit_card_description: "Amazon.com Visa Signature ending in 1234" transaction_date: 2019-09-18 + +;; date: 2020-09-01 +;; info: {"filename": "/114-4993473-6978631.html", "type": "text/html"} + +; features: [ +; { +; "amount": "1.29 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_item_description": [ +; "Broccoli Crowns Conventional, 1 Each", +; "Pork Sausage Link Italian Mild Step 1", +; "Yellow Squash", +; "Banana Conventional, 1 Each", +; "Peach Tree Ripe Organic, 1 Each" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "5.00 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_posttax_adjustment": [ +; "Tip (optional)" +; ] +; }, +; "source_account": "" +; } +; ] +2020-09-01 * "Amazon.com" "Order" + amazon_account: "name@domain.com" + amazon_order_id: "114-4993473-6978631" + associated_data0: "{\"description\": \"Amazon order invoice\", \"meta\": [\"amazon_order_id\", \"114-4993473-6978631\"], \"path\": \"/114-4993473-6978631.html\", \"type\": \"text/html\"}" + Expenses:FIXME:A 1.76 USD + amazon_item_condition: "New" + amazon_item_description: "Broccoli Crowns Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 14.47 USD + amazon_item_condition: "New" + amazon_item_description: "Pork Sausage Link Italian Mild Step 1" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 4.62 USD + amazon_item_condition: "New" + amazon_item_description: "Yellow Squash" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.89 USD + amazon_item_condition: "New" + amazon_item_description: "Banana Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 3.02 USD + amazon_item_condition: "New" + amazon_item_description: "Peach Tree Ripe Organic, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.29 USD + amazon_invoice_description: "Sales Tax" + Expenses:FIXME 5.00 USD + amazon_posttax_adjustment: "Tip (optional)" + Liabilities:Credit-Card -5.00 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-03 + Liabilities:Credit-Card -27.05 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-01 diff --git a/testdata/source/amazon/test_credit_card_transactions/import_results.beancount b/testdata/source/amazon/test_credit_card_transactions/import_results.beancount index ef9959be..8a538dba 100644 --- a/testdata/source/amazon/test_credit_card_transactions/import_results.beancount +++ b/testdata/source/amazon/test_credit_card_transactions/import_results.beancount @@ -337,3 +337,77 @@ Liabilities:Credit-Card 0.00 USD amazon_credit_card_description: "Amazon.com Visa Signature ending in 1234" transaction_date: 2019-09-18 + +;; date: 2020-09-01 +;; info: {"filename": "/114-4993473-6978631.html", "type": "text/html"} + +; features: [ +; { +; "amount": "1.29 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_item_description": [ +; "Broccoli Crowns Conventional, 1 Each", +; "Pork Sausage Link Italian Mild Step 1", +; "Yellow Squash", +; "Banana Conventional, 1 Each", +; "Peach Tree Ripe Organic, 1 Each" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "5.00 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_posttax_adjustment": [ +; "Tip (optional)" +; ] +; }, +; "source_account": "" +; } +; ] +2020-09-01 * "Amazon.com" "Order" + amazon_account: "name@domain.com" + amazon_order_id: "114-4993473-6978631" + associated_data0: "{\"description\": \"Amazon order invoice\", \"meta\": [\"amazon_order_id\", \"114-4993473-6978631\"], \"path\": \"/114-4993473-6978631.html\", \"type\": \"text/html\"}" + Expenses:FIXME:A 1.76 USD + amazon_item_condition: "New" + amazon_item_description: "Broccoli Crowns Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 14.47 USD + amazon_item_condition: "New" + amazon_item_description: "Pork Sausage Link Italian Mild Step 1" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 4.62 USD + amazon_item_condition: "New" + amazon_item_description: "Yellow Squash" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.89 USD + amazon_item_condition: "New" + amazon_item_description: "Banana Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 3.02 USD + amazon_item_condition: "New" + amazon_item_description: "Peach Tree Ripe Organic, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.29 USD + amazon_invoice_description: "Sales Tax" + Expenses:FIXME 5.00 USD + amazon_posttax_adjustment: "Tip (optional)" + Liabilities:Credit-Card -5.00 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-03 + Liabilities:Credit-Card -27.05 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-01 diff --git a/testdata/source/amazon/test_prediction/import_results.beancount b/testdata/source/amazon/test_prediction/import_results.beancount index 0f31c751..9ed2f2c8 100644 --- a/testdata/source/amazon/test_prediction/import_results.beancount +++ b/testdata/source/amazon/test_prediction/import_results.beancount @@ -178,3 +178,77 @@ Liabilities:Credit-Card 0.00 USD amazon_credit_card_description: "Amazon.com Visa Signature ending in 1234" transaction_date: 2019-09-18 + +;; date: 2020-09-01 +;; info: {"filename": "/114-4993473-6978631.html", "type": "text/html"} + +; features: [ +; { +; "amount": "1.29 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_item_description": [ +; "Broccoli Crowns Conventional, 1 Each", +; "Pork Sausage Link Italian Mild Step 1", +; "Yellow Squash", +; "Banana Conventional, 1 Each", +; "Peach Tree Ripe Organic, 1 Each" +; ] +; }, +; "source_account": "" +; }, +; { +; "amount": "5.00 USD", +; "date": "2020-09-01", +; "key_value_pairs": { +; "amazon_posttax_adjustment": [ +; "Tip (optional)" +; ] +; }, +; "source_account": "" +; } +; ] +2020-09-01 * "Amazon.com" "Order" + amazon_account: "name@domain.com" + amazon_order_id: "114-4993473-6978631" + associated_data0: "{\"description\": \"Amazon order invoice\", \"meta\": [\"amazon_order_id\", \"114-4993473-6978631\"], \"path\": \"/114-4993473-6978631.html\", \"type\": \"text/html\"}" + Expenses:FIXME:A 1.76 USD + amazon_item_condition: "New" + amazon_item_description: "Broccoli Crowns Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 14.47 USD + amazon_item_condition: "New" + amazon_item_description: "Pork Sausage Link Italian Mild Step 1" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 4.62 USD + amazon_item_condition: "New" + amazon_item_description: "Yellow Squash" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.89 USD + amazon_item_condition: "New" + amazon_item_description: "Banana Conventional, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 3.02 USD + amazon_item_condition: "New" + amazon_item_description: "Peach Tree Ripe Organic, 1 Each" + amazon_item_quantity: 1 + amazon_seller: "Whole Foods Market" + shipped_date: 2020-09-01 + Expenses:FIXME:A 1.29 USD + amazon_invoice_description: "Sales Tax" + Expenses:FIXME 5.00 USD + amazon_posttax_adjustment: "Tip (optional)" + Liabilities:Credit-Card -5.00 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-03 + Liabilities:Credit-Card -27.05 USD + amazon_credit_card_description: "Visa ending in 1234" + transaction_date: 2020-09-01