@@ -45,7 +45,7 @@ def fetch_account_responses(url, **kw):
4545 "type" : "MANUAL" ,
4646 "dateAdded" : "2025-11-04 18:07:00.0" ,
4747 "title" : "Test CashCtrl add_transaction" ,
48- "notes" : "Added through API " ,
48+ "notes" : "" ,
4949 "amount" : 100 ,
5050 "currencyRate" : 1 ,
5151 "accountIds" : '["1237","1477"]' ,
@@ -189,6 +189,12 @@ def fetch_account_responses(url, **kw):
189189 status_code = 200 ,
190190 )
191191 return Exception ("Unknown account number in URL" )
192+ return Mock (
193+ json = lambda : {
194+ "success" : False ,
195+ },
196+ status_code = 200 ,
197+ )
192198
193199 @staticmethod
194200 def fetch_transaction_responses (url , ** kw ):
@@ -247,10 +253,15 @@ def test_add_transaction(self, mock_post, mock_get):
247253 ]
248254 )
249255 called_url = mock_post .call_args [0 ][0 ]
250- assert (
251- f"{ self .cohiva_test_endpoint } journal/create.json?amount=100.00&creditId=1237&debitId=1477&title=Test+CashCtrl+add_transaction&dateAdded=2026-01-01"
252- in called_url
256+ self .assertIn (f"{ self .cohiva_test_endpoint } journal/create.json" , called_url )
257+ form_data_constructed = mock_post .call_args [1 ]
258+ self .assertEqual ("100.00" , form_data_constructed ["data" ]["amount" ])
259+ self .assertEqual (1237 , form_data_constructed ["data" ]["creditId" ])
260+ self .assertEqual (1477 , form_data_constructed ["data" ]["debitId" ])
261+ self .assertEqual (
262+ "Test CashCtrl add_transaction" , form_data_constructed ["data" ]["title" ]
253263 )
264+ self .assertEqual ("2026-01-01" , form_data_constructed ["data" ]["dateAdded" ])
254265
255266 @patch ("finance.accounting.cashctrl.requests.get" )
256267 @patch ("finance.accounting.cashctrl.requests.post" )
@@ -273,7 +284,7 @@ def test_add_transaction_without_date(self, mock_post, mock_get):
273284 self .account1 ,
274285 self .account2 ,
275286 None ,
276- "Test CashCtrl add_transaction" ,
287+ "Test CashCtrl add_transaction without date " ,
277288 autosave = False ,
278289 )
279290 self .assertTrue (transaction_id .startswith ("cct_" ))
@@ -283,11 +294,52 @@ def test_add_transaction_without_date(self, mock_post, mock_get):
283294 # verify that the API was called
284295 today = datetime .date .today ().strftime ("%Y-%m-%d" )
285296 called_url = mock_post .call_args [0 ][0 ]
286- assert (
287- f"{ self .cohiva_test_endpoint } journal/create.json?amount=100.00&creditId=1237"
288- f"&debitId=1477&title=Test+CashCtrl+add_transaction&dateAdded={ today } "
289- in called_url
297+ self .assertIn (f"{ self .cohiva_test_endpoint } journal/create.json" , called_url )
298+ form_data_constructed = mock_post .call_args [1 ]
299+ self .assertEqual (
300+ "Test CashCtrl add_transaction without date" ,
301+ form_data_constructed ["data" ]["title" ],
290302 )
303+ self .assertEqual (today , form_data_constructed ["data" ]["dateAdded" ])
304+
305+ @patch ("finance.accounting.cashctrl.requests.get" )
306+ @patch ("finance.accounting.cashctrl.requests.post" )
307+ def test_add_transaction_with_long_description (self , mock_post , mock_get ):
308+ messages = []
309+ with AccountingManager (messages ) as book :
310+ # configure fake responses
311+ mock_get .return_value .raise_for_status .side_effect = None
312+ mock_get .side_effect = self .fetch_account_responses
313+
314+ mock_post .return_value .json .return_value = {
315+ "success" : True ,
316+ "message" : "Buchung gespeichert" ,
317+ "insertId" : 700 ,
318+ }
319+ mock_post .return_value .raise_for_status .side_effect = None
320+
321+ long_description = (
322+ "Test CashCtrl add_transaction with long description (254 chars) "
323+ + 19 * "123456789_"
324+ )
325+ transaction_id = book .add_transaction (
326+ 100.00 ,
327+ self .account1 ,
328+ self .account2 ,
329+ None ,
330+ long_description ,
331+ autosave = False ,
332+ )
333+ self .assertTrue (transaction_id .startswith ("cct_" ))
334+ self .assertEqual ("cct_0_700" , transaction_id )
335+ book .save ()
336+
337+ # verify that the API was called
338+ called_url = mock_post .call_args [0 ][0 ]
339+ self .assertIn (f"{ self .cohiva_test_endpoint } journal/create.json" , called_url )
340+ form_data_constructed = mock_post .call_args [1 ]
341+ self .assertEqual (long_description [:250 ], form_data_constructed ["data" ]["title" ])
342+ self .assertEqual (long_description , form_data_constructed ["data" ]["notes" ])
291343
292344 @patch ("finance.accounting.cashctrl.requests.get" )
293345 @patch ("finance.accounting.cashctrl.requests.post" )
@@ -430,3 +482,44 @@ def test_delete_transaction(self, mock_post, mock_get):
430482 mock_post .assert_called_once_with (
431483 f"{ self .cohiva_test_endpoint } journal/delete.json?ids=801" , data = None , auth = ANY
432484 )
485+
486+ @patch ("finance.accounting.cashctrl.requests.get" )
487+ @patch ("finance.accounting.cashctrl.requests.post" )
488+ def test_process_api_error (self , mock_post , mock_get ):
489+ messages = []
490+ with AccountingManager (messages ) as book :
491+ # configure fake responses
492+ mock_get .return_value .raise_for_status .side_effect = None
493+ mock_get .side_effect = self .fetch_account_responses
494+
495+ mock_post .return_value .json .return_value = {
496+ "success" : False ,
497+ "message" : None ,
498+ "errors" : [
499+ {
500+ "field" : "creditId" ,
501+ "message" : "This account does not exist." ,
502+ },
503+ {
504+ "field" : "field2" ,
505+ "message" : "Another error for field2" ,
506+ },
507+ ],
508+ }
509+ mock_post .return_value .raise_for_status .side_effect = None
510+
511+ with self .assertRaisesRegex (
512+ RuntimeError ,
513+ (
514+ "CashCtrl API error: creditId: This account does not exist.; "
515+ "field2: Another error for field2 - for request"
516+ ),
517+ ):
518+ book .add_transaction (
519+ 100.00 ,
520+ self .account1 ,
521+ self .account2 ,
522+ None ,
523+ "Test error processing" ,
524+ autosave = False ,
525+ )
0 commit comments