forked from cursorman/coffer
133 lines
5.5 KiB
Python
133 lines
5.5 KiB
Python
import unittest
|
|
|
|
from coffer.ledger import GrantedCreditNotForGoods
|
|
|
|
from coffer import CannotSupply, InsufficientCredit, UnknownGood, new_store
|
|
from coffer.ledger import Ledger
|
|
from coffer.store import Store
|
|
from coffer.units import ACCOUNT_COFFER, agent_account
|
|
|
|
|
|
class LedgerTests(unittest.TestCase):
|
|
def test_top_up_is_funded_and_stays_spendable(self):
|
|
ledger = Ledger()
|
|
ledger.top_up("cursorMan", 20)
|
|
self.assertEqual(
|
|
ledger.balance("cursorMan"),
|
|
{"promotional": 0.0, "funded": 20.0, "earned": 0.0, "spendable": 20.0, "goods_spendable": 20.0},
|
|
)
|
|
|
|
def test_grant_is_promotional(self):
|
|
ledger = Ledger()
|
|
ledger.grant("cursorMan", 20, "launch shirt")
|
|
self.assertEqual(ledger.balance("cursorMan")["promotional"], 20.0)
|
|
self.assertEqual(ledger.balance("cursorMan")["funded"], 0.0)
|
|
|
|
def test_spend_uses_promotional_credit_first(self):
|
|
ledger = Ledger()
|
|
ledger.grant("cursorMan", 12, "launch shirt")
|
|
ledger.top_up("cursorMan", 20)
|
|
draws = ledger.spend("cursorMan", 20)
|
|
self.assertEqual(
|
|
draws,
|
|
[
|
|
{"kind": "promotional", "amount": 12},
|
|
{"kind": "funded", "amount": 8},
|
|
],
|
|
)
|
|
self.assertEqual(ledger.balance("cursorMan")["spendable"], 12.0)
|
|
self.assertEqual(ledger.balance("cursorMan")["funded"], 12.0)
|
|
|
|
def test_spend_stops_at_zero(self):
|
|
ledger = Ledger()
|
|
ledger.top_up("cursorMan", 19)
|
|
with self.assertRaises(InsufficientCredit):
|
|
ledger.spend("cursorMan", 20)
|
|
self.assertEqual(ledger.balance("cursorMan")["spendable"], 19.0)
|
|
|
|
def test_rejects_fractions_and_zero(self):
|
|
ledger = Ledger()
|
|
with self.assertRaises(ValueError):
|
|
ledger.top_up("cursorMan", 0)
|
|
with self.assertRaises(ValueError):
|
|
ledger.grant("cursorMan", 1.5, "launch")
|
|
|
|
|
|
class StoreTests(unittest.TestCase):
|
|
def test_shirt_from_catalog_procures_and_invoices_in_dollars(self):
|
|
store = new_store()
|
|
buyer = agent_account("cursorMan")
|
|
store.ledger.grant(buyer, 20, "launch shirt")
|
|
with self.assertRaises(GrantedCreditNotForGoods):
|
|
store.place_order("cursorMan", "coffer-shirt") # granted credit: services only
|
|
store.ledger.top_up(buyer, 20)
|
|
order = store.place_order("cursorMan", "coffer-shirt")
|
|
self.assertEqual(order.credits_charged, 20)
|
|
self.assertEqual(order.status, "procuring")
|
|
self.assertEqual(order.procured, 1)
|
|
invoice = store.invoices[order.invoice_id]
|
|
self.assertEqual(invoice.supplier_id, "printer")
|
|
self.assertEqual(invoice.dollars, 8)
|
|
self.assertEqual(invoice.status, "payable")
|
|
self.assertEqual(store.ledger.balance(buyer)["spendable"], 20.0) # the grant is untouched
|
|
self.assertEqual(store.ledger.balance(buyer)["promotional"], 20.0)
|
|
self.assertEqual(store.ledger.balance(ACCOUNT_COFFER)["spendable"], 20.0)
|
|
self.assertNotIn("printer", store.ledger.accounts)
|
|
|
|
def test_stock_fulfills_without_an_invoice(self):
|
|
store = new_store()
|
|
store.receive_stock("coffer-shirt", 2)
|
|
self.assertEqual(len(store.invoices), 1)
|
|
store.ledger.top_up(agent_account("buyer"), 40)
|
|
order = store.place_order("buyer", "coffer-shirt", 2)
|
|
self.assertEqual(order.status, "fulfilled")
|
|
self.assertEqual(order.from_stock, 2)
|
|
self.assertIsNone(order.invoice_id)
|
|
self.assertEqual(store.goods["coffer-shirt"].stock, 0)
|
|
|
|
def test_mixed_stock_and_procurement(self):
|
|
store = new_store()
|
|
store.goods["coffer-shirt"].stock = 1
|
|
store.ledger.top_up(agent_account("buyer"), 60)
|
|
order = store.place_order("buyer", "coffer-shirt", 3)
|
|
self.assertEqual(order.from_stock, 1)
|
|
self.assertEqual(order.procured, 2)
|
|
self.assertEqual(store.invoices[order.invoice_id].dollars, 16)
|
|
self.assertEqual(order.status, "procuring")
|
|
|
|
def test_failed_spend_does_not_take_stock(self):
|
|
store = new_store()
|
|
store.goods["coffer-shirt"].stock = 1
|
|
with self.assertRaises(InsufficientCredit):
|
|
store.place_order("buyer", "coffer-shirt")
|
|
self.assertEqual(store.goods["coffer-shirt"].stock, 1)
|
|
self.assertEqual(store.orders, {})
|
|
|
|
def test_unknown_good_and_no_supplier(self):
|
|
store = Store()
|
|
store.add_good("own-note", "Note", 5)
|
|
store.ledger.top_up(agent_account("buyer"), 5)
|
|
with self.assertRaises(UnknownGood):
|
|
store.place_order("buyer", "missing")
|
|
with self.assertRaises(CannotSupply):
|
|
store.place_order("buyer", "own-note", 1)
|
|
self.assertEqual(store.ledger.balance(agent_account("buyer"))["spendable"], 5.0)
|
|
|
|
def test_idempotency_key_returns_the_same_order(self):
|
|
store = new_store()
|
|
store.ledger.top_up(agent_account("buyer"), 40)
|
|
first = store.place_order("buyer", "coffer-shirt", idempotency_key="k1")
|
|
second = store.place_order("buyer", "coffer-shirt", idempotency_key="k1")
|
|
self.assertEqual(first.order_id, second.order_id)
|
|
self.assertEqual(store.ledger.balance(agent_account("buyer"))["spendable"], 20.0)
|
|
|
|
def test_coffer_price_is_not_the_supplier_cost(self):
|
|
store = new_store()
|
|
good = store.goods["coffer-shirt"]
|
|
self.assertEqual(good.credit_price, 20)
|
|
self.assertEqual(good.supplier_unit_cost, 8)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|