def test_create_basictransaction(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") e = book_basic.accounts(name="exp") tr = Transaction(currency=EUR, description=u"wire from Hélène", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 1), enter_date=datetime(2014, 1, 1), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=e, value=-10, memo=u"mémo exp"), ]) # check issue with balance with pytest.raises(GncImbalanceError): book_basic.flush() book_basic.validate() # adjust balance Split(account=e, value=-90, memo="missing exp", transaction=tr) book_basic.flush() # check no issue with str assert str(tr) assert str(tr.splits) assert repr(tr) assert repr(tr.splits)
def test_update_currency_prices(self, book_basic): if not is_inmemory_sqlite(book_basic): print("skipping test for {}".format(book_basic)) return EUR = book_basic.default_currency with pytest.raises(GncPriceError): EUR.update_prices() USD = book_basic.currencies(mnemonic="USD") USD.update_prices() assert len(list(USD.prices)) < 7 assert (USD.prices.first() is None) or (USD.prices.first().commodity is USD) CAD = book_basic.currencies(mnemonic="CAD") CAD.update_prices() assert len(list(CAD.prices)) < 7 assert (CAD.prices.first() is None) or (CAD.prices.first().commodity is CAD) # redo update prices which should not bring new prices l = len(list(USD.prices)) USD.update_prices() assert len(list(USD.prices)) == l book_basic.validate() assert len(book_basic.prices) < 14
def test_create_basictransaction(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") e = book_basic.accounts(name="exp") tr = Transaction(currency=EUR, description=u"wire from Hélène", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 1), enter_date=datetime(2014, 1, 1), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=e, value=-10, memo=u"mémo exp"), ]) # check issue with balance with pytest.raises(GncImbalanceError): book_basic.flush() book_basic.validate() # adjust balance Split(account=e, value=-90, memo="missing exp", transaction=tr) book_basic.flush() # check no issue with str assert str(tr) assert str(tr.splits) assert repr(tr) assert repr(tr.splits) assert tr.notes == u"on St-Eugène day"
def test_create_duplicateprice(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") USD = book_basic.currencies(mnemonic="USD") p = Price(commodity=USD, currency=EUR, date=date(2014, 2, 22), value=Decimal('0.54321')) p1 = Price(commodity=USD, currency=EUR, date=date(2014, 2, 22), value=Decimal('0.12345')) book_basic.flush() assert USD.prices.filter_by(value=Decimal('0')).all() == [] assert USD.prices.filter_by(value=Decimal('0.12345')).one() == p1 with pytest.raises(ValueError): book_basic.validate()
def test_create_basictransaction_validation_date(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") e = book_basic.accounts(name="exp") splits = [ Split(account=a, value=100, memo="mémo asset"), Split(account=e, value=-10, memo="mémo exp"), ] with pytest.raises(GncValidationError): tr = Transaction( currency=EUR, description="wire from Hélène", notes="on St-Eugène day", post_date=datetime(2014, 1, 1), enter_date=datetime(2014, 1, 1), splits=splits, ) with pytest.raises(GncValidationError): tr = Transaction( currency=EUR, description="wire from Hélène", notes="on St-Eugène day", post_date=datetime(2014, 1, 1), enter_date=time(10, 59, 00), splits=splits, ) with pytest.raises(GncValidationError): tr = Transaction( currency=EUR, description="wire from Hélène", notes="on St-Eugène day", post_date=date(2014, 1, 1), enter_date=date(2014, 1, 1), splits=splits, ) tr = Transaction( currency=EUR, description="wire from Hélène", notes="on St-Eugène day", post_date=None, enter_date=None, splits=splits, ) with pytest.raises(GncImbalanceError): book_basic.flush() book_basic.validate()
def test_create_duplicateprice_different_source(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") USD = book_basic.currencies(mnemonic="USD") p = Price(commodity=USD, currency=EUR, date=date(2014, 2, 22), value=Decimal('0.54321'), source="user:price") p1 = Price(commodity=USD, currency=EUR, date=date(2014, 2, 22), value=Decimal('0.12345'), source="other:price") book_basic.flush() assert USD.prices.filter_by(value=Decimal('0')).all() == [] assert USD.prices.filter_by(value=Decimal('0.12345')).one() == p1 # validation should work as different sources book_basic.validate()
def test_single_transaction_rollback(self, book_basic): today = tzlocal.get_localzone().localize(datetime.today()) factories.single_transaction(today, today, "my test", Decimal(100), from_account=book_basic.accounts(name="inc"), to_account=book_basic.accounts(name="asset")) book_basic.validate() assert len(book_basic.transactions) == 1 book_basic.cancel() assert len(book_basic.transactions) == 0
def test_create_cdtytransaction_tradingaccount(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") book_basic.use_trading_accounts = True tr = Transaction(currency=EUR, description="buy stock", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=s, value=-100, quantity=-15, memo=u"mémo brok"), ]) book_basic.validate() assert "{}".format( tr) == "Transaction<[EUR] 'buy stock' on 2014-01-02>" assert "{}".format(s) == "Account<asset:broker[ïoà]>" assert "{}".format( tr.splits(account=s) ) == "Split<Account<asset:broker[ïoà]> -100 EUR [-15 ïoà]>" assert "{}".format( tr.splits(account=a)) == "Split<Account<asset[EUR]> 100 EUR>" # check sum of quantities are all balanced per commodity as values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v == Decimal(0) for k, v in d.items() if k != "cur"]) # change existing quantity sp = tr.splits(memo=u"mémo brok") sp.quantity += 1 book_basic.validate() # check sum of quantities are all balanced per commodity as values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v == Decimal(0) for k, v in d.items() if k != "cur"])
def test_create_customer_job(self, book_basic, Person): EUR = book_basic.commodities(namespace="CURRENCY") # create detached person c = Person(name="John Föo", currency=EUR) book_basic.add(c) if Person != Employee: j = Job(name="my job", owner=c) book_basic.validate() book_basic.flush() if Person != Employee: print(c.jobs)
def test_create_cdtytransaction_cdtycurrency(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") tr = Transaction(currency=s.commodity, description="buy stock", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, quantity=10, memo=u"mémo asset"), Split(account=s, value=-100, quantity=-10, memo=u"mémo brok"), ]) # raise error as Transaction has a non CURRENCY commodity with pytest.raises(GncValidationError): book_basic.validate()
def test_create_cdtytransaction_cdtycurrency(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") tr = Transaction(currency=s.commodity, description="buy stock", notes=u"on St-Eugène day", post_date=date(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, quantity=10, memo=u"mémo asset"), Split(account=s, value=-100, quantity=-10, memo=u"mémo brok"), ]) # raise error as Transaction has a non CURRENCY commodity with pytest.raises(GncValidationError): book_basic.validate()
def test_create_simplelot_inconsistentaccounts(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") l = Lot(title=u"test mé", account=a, notes=u"ïlya") # raise valueerror as split account not the same as lot account tr = Transaction(currency=EUR, description="trade stock", notes=u"àçö", post_date=date(2014, 1, 1), enter_date=datetime(2014, 1, 1), splits=[ Split(account=a, value=10, memo=u"mémo asset"), Split(account=s, value=- 10, quantity=-2, memo=u"mémo brok", lot=l), ]) with pytest.raises(ValueError): book_basic.validate()
def test_create_simplelot_inconsistentaccounts(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") l = Lot(title=u"test mé", account=a, notes=u"ïlya") # raise valueerror as split account not the same as lot account tr = Transaction(currency=EUR, description="trade stock", notes=u"àçö", post_date=datetime(2014, 1, 1), enter_date=datetime(2014, 1, 1), splits=[ Split(account=a, value=10, memo=u"mémo asset"), Split(account=s, value=- 10, quantity=-2, memo=u"mémo brok", lot=l), ]) with pytest.raises(ValueError): book_basic.validate()
def test_create_cdtytransaction(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") tr = Transaction( currency=EUR, description="buy stock", notes="on St-Eugène day", post_date=date(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, memo="mémo asset"), Split(account=s, value=-90, memo="mémo brok"), ], ) # check issue with quantity for broker split not defined with pytest.raises(GncValidationError): book_basic.validate() sb = tr.splits(account=s) sb.quantity = 15 # check issue with quantity not same sign as value with pytest.raises(GncValidationError): book_basic.validate() sb.quantity = -15 # verify imbalance issue with pytest.raises(GncImbalanceError): book_basic.validate() # adjust balance Split(account=a, value=-10, memo="missing asset corr", transaction=tr) book_basic.save() assert str(sb) assert str(sb) # changing currency of an existing transaction is not allowed tr.currency = book_basic.currencies(mnemonic="USD") with pytest.raises(GncValidationError): book_basic.validate() book_basic.cancel() # check sum of quantities are not balanced per commodity but values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v != 0 for k, v in d.items() if k != "cur"])
def test_create_person_noid_nobook(self, book_basic, Person): EUR = book_basic.commodities(namespace="CURRENCY") # create detached person c = Person(name="John Föo", currency=EUR) # id should not be set assert c.id is None # flushing should not set the id as person not added to book book_basic.flush() assert c.id is None # adding the person to the book does not per se set the id book_basic.add(c) assert c.id is None # but validation sets the id if still to None book_basic.validate() assert c.id == "000001"
def test_create_cdtytransaction_tradingaccount(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") book_basic.use_trading_accounts = True tr = Transaction(currency=EUR, description="buy stock", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=s, value=-100, quantity=-15, memo=u"mémo brok"), ]) book_basic.validate() assert "{}".format(tr) == "Transaction<[EUR] 'buy stock' on 2014-01-02>" assert "{}".format(s) == "Account<asset:broker[ïoà]>" assert "{}".format(tr.splits(account=s)) == "Split<Account<asset:broker[ïoà]> -100 EUR [-15 ïoà]>" assert "{}".format(tr.splits(account=a)) == "Split<Account<asset[EUR]> 100 EUR>" # check sum of quantities are all balanced per commodity as values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v == Decimal(0) for k, v in d.items() if k != "cur"]) # change existing quantity sp = tr.splits(memo=u"mémo brok") sp.quantity += 1 book_basic.validate() # check sum of quantities are all balanced per commodity as values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v == Decimal(0) for k, v in d.items() if k != "cur"])
def test_create_basictransaction_neutraltime(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") e = book_basic.accounts(name="exp") tr = Transaction(currency=EUR, description=u"wire from Hélène", notes=u"on St-Eugène day", post_date=date(2014, 1, 1), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=e, value=-100, memo=u"mémo exp"), ]) assert isinstance(tr.post_date, date) book_basic.flush() book_basic.validate() assert isinstance(tr.post_date, date)
def test_update_stock_prices(self, book_basic): if not is_inmemory_sqlite(book_basic): print("skipping test for {}".format(book_basic)) return cdty = Commodity(mnemonic="AAPL", namespace="NASDAQ", fullname="Apple", book=book_basic) # cdty["quoted_currency"] = "USD" # assert cdty.get("quoted_currency") == "USD" cdty.update_prices() book_basic.flush() L = len(list(cdty.prices)) assert L < 7 cdty.update_prices() book_basic.flush() assert len(list(cdty.prices)) == L book_basic.validate()
def test_create_cdtytransaction(self, book_basic): EUR = book_basic.commodities(namespace="CURRENCY") racc = book_basic.root_account a = book_basic.accounts(name="asset") s = book_basic.accounts(name="broker") tr = Transaction(currency=EUR, description="buy stock", notes=u"on St-Eugène day", post_date=datetime(2014, 1, 2), enter_date=datetime(2014, 1, 3), splits=[ Split(account=a, value=100, memo=u"mémo asset"), Split(account=s, value=-90, memo=u"mémo brok"), ]) # check issue with quantity for broker split not defined with pytest.raises(GncValidationError): book_basic.validate() sb = tr.splits(account=s) sb.quantity = 15 # check issue with quantity not same sign as value with pytest.raises(GncValidationError): book_basic.validate() sb.quantity = -15 # verify imbalance issue with pytest.raises(GncImbalanceError): book_basic.validate() # adjust balance Split(account=a, value=-10, memo="missing asset corr", transaction=tr) book_basic.save() assert str(sb) assert str(sb) # changing currency of an existing transaction is not allowed tr.currency = book_basic.currencies(mnemonic="USD") with pytest.raises(GncValidationError): book_basic.validate() book_basic.cancel() # check sum of quantities are not balanced per commodity but values are d = defaultdict(lambda: Decimal(0)) for sp in tr.splits: assert sp.quantity == sp.value or sp.account != a d[sp.account.commodity] += sp.quantity d["cur"] += sp.value assert d["cur"] == 0 assert all([v != 0 for k, v in d.items() if k != "cur"])