File size: 5,541 Bytes
de77711
 
eee30e1
3eff181
 
 
 
 
 
 
 
 
802b31f
de77711
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eee30e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802b31f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3eff181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from pathlib import Path

from voiceledger.ledger.customers import get_customer_balances
from voiceledger.ledger.database import (
    add_transaction,
    delete_transaction,
    export_transactions_csv,
    get_transaction,
    get_transactions,
    initialize_database,
    update_transaction,
)
from voiceledger.ledger.inventory import get_inventory
from voiceledger.parser.rules import parse_transaction


def test_initialize_database_creates_file(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"

    created_path = initialize_database(db_path)

    assert created_path == db_path
    assert db_path.exists()


def test_add_and_get_transactions(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    transaction = parse_transaction("Sold 12 mangoes, 20 each")

    transaction_id = add_transaction(transaction, db_path)
    ledger = get_transactions(db_path)

    assert transaction_id == 1
    assert len(ledger) == 1
    assert ledger.iloc[0]["transaction_type"] == "sale"
    assert ledger.iloc[0]["item"] == "mangoes"
    assert ledger.iloc[0]["amount"] == 240


def test_customer_credit_transaction_updates_balance(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"

    add_transaction(parse_transaction("Amit owes 100"), db_path)
    balances = get_customer_balances(db_path)

    assert len(balances) == 1
    assert balances.iloc[0]["customer"] == "Amit"
    assert balances.iloc[0]["outstanding_balance"] == 100


def test_customer_payment_transaction_decreases_balance(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"

    add_transaction(parse_transaction("Amit owes 100"), db_path)
    add_transaction(parse_transaction("Amit paid 50"), db_path)
    balances = get_customer_balances(db_path)

    assert len(balances) == 1
    assert balances.iloc[0]["customer"] == "Amit"
    assert balances.iloc[0]["outstanding_balance"] == 50


def test_inventory_purchase_transaction_increases_stock(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"

    add_transaction(parse_transaction("Bought 50 mangoes"), db_path)
    inventory = get_inventory(db_path)

    assert len(inventory) == 1
    assert inventory.iloc[0]["item"] == "mangoes"
    assert inventory.iloc[0]["current_stock"] == 50


def test_sale_transaction_decreases_stock(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"

    add_transaction(parse_transaction("Bought 50 mangoes"), db_path)
    add_transaction(parse_transaction("Sold 12 mangoes"), db_path)
    inventory = get_inventory(db_path)

    assert len(inventory) == 1
    assert inventory.iloc[0]["item"] == "mangoes"
    assert inventory.iloc[0]["current_stock"] == 38


def test_get_transaction_returns_saved_transaction(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    transaction_id = add_transaction(parse_transaction("Paid 500 for supplies"), db_path)

    transaction = get_transaction(transaction_id, db_path)

    assert transaction is not None
    assert transaction.transaction_type == "expense"
    assert transaction.amount == 500


def test_update_sale_rebuilds_inventory(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    add_transaction(parse_transaction("Bought 50 mangoes"), db_path)
    sale_id = add_transaction(parse_transaction("Sold 12 mangoes"), db_path)

    updated = update_transaction(sale_id, parse_transaction("Sold 20 mangoes"), db_path)
    inventory = get_inventory(db_path)

    assert updated is True
    assert inventory.iloc[0]["current_stock"] == 30


def test_delete_sale_rebuilds_inventory(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    add_transaction(parse_transaction("Bought 50 mangoes"), db_path)
    sale_id = add_transaction(parse_transaction("Sold 12 mangoes"), db_path)

    deleted = delete_transaction(sale_id, db_path)
    inventory = get_inventory(db_path)

    assert deleted is True
    assert inventory.iloc[0]["current_stock"] == 50


def test_update_customer_credit_rebuilds_balance(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    credit_id = add_transaction(parse_transaction("Amit owes 100"), db_path)
    add_transaction(parse_transaction("Amit paid 50"), db_path)

    updated = update_transaction(credit_id, parse_transaction("Amit owes 200"), db_path)
    balances = get_customer_balances(db_path)

    assert updated is True
    assert balances.iloc[0]["outstanding_balance"] == 150


def test_delete_customer_payment_rebuilds_balance(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    add_transaction(parse_transaction("Amit owes 100"), db_path)
    payment_id = add_transaction(parse_transaction("Amit paid 50"), db_path)

    deleted = delete_transaction(payment_id, db_path)
    balances = get_customer_balances(db_path)

    assert deleted is True
    assert balances.iloc[0]["outstanding_balance"] == 100


def test_export_transactions_csv_includes_ledger_columns(tmp_path: Path) -> None:
    db_path = tmp_path / "voiceledger.sqlite3"
    export_path = tmp_path / "transactions.csv"
    add_transaction(parse_transaction("Sold 12 mangoes, 20 each"), db_path)

    result_path = export_transactions_csv(db_path, export_path)
    csv_text = result_path.read_text()

    assert result_path == export_path
    assert "id,transaction_type,item,quantity,unit_price,amount,customer,payment_status,notes,confidence,created_at" in csv_text
    assert "sale,mangoes" in csv_text