Bug 405

Summary: CompanyTransaction & CompanyAccount: Negative balance when tried to debit credit_account type with insufficient fund
Product: Group 3 Reporter: Hsu To-Liang <tlhsu2-c>
Component: Corporation Accounting SystemAssignee: Hsu To-Liang <tlhsu2-c>
Status: RESOLVED FIXED    
Severity: critical    
Priority: ---    
Version: unspecified   
Hardware: PC   
OS: Windows   
Attachments: CompanyAccount: when testing printTLedger

Description Hsu To-Liang 2020-11-14 21:23:53 HKT
Created attachment 43 [details]
CompanyAccount: when testing printTLedger

Note that Cash account is of DEBIT_ACCOUNT type (debitting to Cash means increasing balance, creditting to Cash means decreasing)

Consider the following test case:

1. Cash account has a beginning balance of 0
2. Debit cash account with 1,000 -> now cash account has balance 1,000
3. Credit cash account with 2,000 -> will lead to balance -1,000 -> this transaction is not valid, should not be recorded at all

Code for test case: (may refer to attachement)
//
Company lukecompany=new Company();
CompanyAccount cashAccount=lukecompany.getAccountList().get("Cash");
Date tday=new Date();
CompanyTransaction trans1=new CompanyTransaction("id12334", tday, "Cash", "Accounts Payable",1000.0, "Borrow from bank");
CompanyTransaction trans2=new CompanyTransaction("id12335", tday, "Land", "Cash", 2000.0,"Buy land with cash");
lukecompany.recordTransaction(trans1);
lukecompany.recordTransaction(trans2);
		
cashAccount.printTLedger();
//

Output result:
                          Cash
--------------------------------------------------------------
Debit                          | Credit                        
--------------------------------------------------------------
TransID        |Amount         |TransID        |Amount         
--------------------------------------------------------------
id12334        |1000.0         |id12335        |2000.0         
--------------------------------------------------------------
Total          |-1000.0        |               |               
--------------------------------------------------------------
Comment 1 Hsu To-Liang 2020-12-04 21:12:42 HKT
Solved, add validation process before recording each transaction. 
I have put into consideration all 4 possible combinations:

  [Action]   [Account Type]
1.[Credit] a [Credit Account]
2.[Debit]  a [Debit Account]
3.[Credit] a [Debit Account]
4.[Debit]  a [Credit Account]

note that for 1 and 2, the balance will only increase, so no need for checking sufficient fund. On the other hand, for 3 and 4, the balance will decrease, therefore should test if the deducted amount is higher than current balance.

public boolean isValidTransaction(CompanyTransaction trans) {
		
		CompanyAccount accountToDebit = accountList.get(trans.getDebittedAccount());
		CompanyAccount accountToCredit = accountList.get(trans.getCredittedAccount());
		
		if (accountToCredit == null) {
			System.out.println("Error: " + trans.getCredittedAccount() + " is not a valid account.");
			return false;
		} else if (accountToDebit == null) {
			System.out.println("Error: " + trans.getDebittedAccount() + " is not a valid account.");
			return false;
		}
		
		//for credit account type, if debit means decrease -> may have credit balance < 0
		if(accountToDebit.getAccountType() == CompanyAccountType.CREDIT_ACCOUNT) {
			if(accountToDebit.getBalance() - trans.getAmount()<0) {
				System.out.println("Error: Cannot debit account "+trans.getDebittedAccount());
				return false;
			}
		}
		
		//for debit account type, if credit means decrease -> may have insufficient fund
		if(accountToCredit.getAccountType() == CompanyAccountType.DEBIT_ACCOUNT) {
			if(accountToCredit.getBalance() - trans.getAmount()<0) {
				System.out.println("Error: Cannot credit account "+trans.getCredittedAccount());
				return false;
			}
		}
		
		return true;
	}