Project: Codii

[Codii] is a desktop address book application specially designed for debt collectors to manage debtors in a simple manner. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface).

Debt collectors can store information such as the amount owed, debt borrow date and debt cleared date in addition to debtor’s personal information.

Unique features such as an interest calculator help debt collectors manage debts more efficiently.

Codii is evolved from [AddressBook - Level 4] which is a desktop address book application used for teaching Software Engineering principles.

Code contributed: [Functional code] [Test code]

Enhancement Added: Date Storing Mechanism

Implementation


Start of Extract [from: Developer Guide]

Date storing mechanism

The date storing mechanism only begins to work when an instance of the Person class is implemented. An instance of the Date class is created and used to store the current date that the Person instance was created. An example of such an implementation of this is the dateBorrow field of Person.

public class Person implements ReadOnlyPerson {

    private ObjectProperty<Name> name;
    private ObjectProperty<Phone> phone;
    private ObjectProperty<Email> email;
    private ObjectProperty<Address> address;
    private ObjectProperty<PostalCode> postalCode;
    private ObjectProperty<Cluster> cluster;
    private ObjectProperty<Debt> debt;
    private ObjectProperty<Interest> interest;
    private ObjectProperty<DateBorrow> dateBorrow;

Such an implementation doesn’t allow for errors when creating the field as there is no room for mistakes on the user’s side. When the Person instance is created, the following line is called:

    this.dateBorrow = new SimpleObjectProperty<>(new DateBorrow());

Suppose the above line is called, the DateBorrow class creates a new Date with the following line:

    public DateBorrow() {
        Date date = new Date();
        value = formatDate(date);
    }

This way of implementation is rather intuitive when adding a new Person as a new Date can simply be created. However, whenever a Person constructor is called, such as the following:

    public Person(ReadOnlyPerson source) {
        this(source.getName(), source.getPhone(), source.getEmail(), source.getAddress(), source.getPostalCode(),
                source.getDebt(), source.getInterest(), source.getDeadline(), source.getTags());

This would result in inconsistencies in the code. For example, an Edit command is implemented in such a way that it creates an editedPerson. This is because the above mentioned constructor was meant to make a copy of the Person with a given source. Hence the following line was added to ensure consistency.

        this.dateBorrow = new SimpleObjectProperty<>(source.getDateBorrow());

Design Considerations

Aspect: Implementation of DateBorrow
Alternative 1(current choice): Create a DateBorrow class as such but modify the constructor to maintain consistency
Pros: Blends well with existing coding style and how the commands work.
Cons: As of now there is no problems with the implementation.
Alternative 2: Have the user manually key in the date
Pros: Implementation is very simple as the developer could just follow current coding style to create a new field.
Cons: Such an implementation would not be as user-friendly as the first alternative. Currently the amount of fields for the user to key in is rather high. Implementing alternative 2 would be more tedious on the user’s side.

End of Extract


Enhancement Added: Overdue List Command

External Behavior


Start of Extract [from: User Guide]

Listing all persons with overdue debt: overduelist

It should be noted that each time the user logs into Codii, it checks through the address book for debtors whose deadlines have been passed and automatically adds them into the overdue list.
If any debtor in the overdue list has cleard his/her debt, they are removed from the overdue list.

Shows a list of all persons with overdue debt in the address book.
Format: overduelist

End of Extract


Justification

It would be more convenient for debt collectors to view all the debtors with overdue debts with a simple command.

Enhancement Added: Interest calculator

External Behavior


Start of Extract [from: User Guide]

Interest Calculator

This is only applicable to debtors with a set interest rate. For the current version, only positive whole numbers are accepted.
Codii only checks through its list of debtors when the user logs into the application.

At the start of each month, Codii will check through the list of debtors and accrue their debt if applicable. Even if the user has not logged into Codii for many months, the application will compound the debt accordingly.

This is convenient for debts or loans with a monthly interest rate.

End of Extract


Justification

It would be convenient for debt collectors to have their debtors' debts updated automatically. However, it should be noted that it is still a basic feature as it only accrues a debtor’s debt at the start of each month. An updated version will be included in V2.0.

Implementation


Start of Extract [from: Developer Guide]

Interest Calculator Mechanism

As a debt collector, it can be troublesome to manage so many debts. The task is made more tedious when the debt collector has to consider all the debtor’s loan’s interest rates as well. Codii is able to automatically calculate a Person 's new debt based on his / her’s interest rate. Whenever the user logs into Codii, the Model component, which handles the event LoginAppRequestEvent and checks every Person in the AddressBook.

@Subscribe
    public void handleLoginUpdateDebt(LoginAppRequestEvent event) {
        // login is successful
        if (event.getLoginStatus() == true) {
            for (ReadOnlyPerson person : allPersons) {
                if (!person.getInterest().value.equals("No interest set.")
                        && (person.checkLastAccruedDate(new Date()) != 0)) {
                    updateDebtFromInterest(person, person.checkLastAccruedDate(new Date()));
                }
            }
        }
    }

As seen from the above if a Person has his / her interest field defined,the event handler checks a Person 's debts last accrued date via the method:

    /**
     * Compares date of last accrued against current date.
     * @return number of months the current date is ahead of last accrued date. Returns 0 if
     * there is no need to increment debt.
     */
    @Override
    public int checkLastAccruedDate(Date currentDate) {
        if (lastAccruedDate.before(currentDate)) {
            return DateUtil.getNumberOfMonthBetweenDates(currentDate, lastAccruedDate);
        } else {
            return 0;
        }
    }

The above method returns the difference in the number of months between the last accrued date and the current date to the event handler. The event handler than calls another method to update the Person 's debt by passing in the number of months as a parameter:

    @Override
    public void updateDebtFromInterest(ReadOnlyPerson person, int differenceInMonths) {
        String accruedAmount = person.calcAccruedAmount(differenceInMonths);
        try {
            Debt amount = new Debt(accruedAmount);
            addDebtToPerson(person, amount);
        } catch (PersonNotFoundException pnfe) {
            assert false : "Should not occur as person obtained from allPersons";
        } catch (IllegalValueException ive) {
            assert false : Debt.MESSAGE_DEBT_CONSTRAINTS;
        }
    }

From the above code, the Person 's debts accrued amount would be calculated by the line:

String accruedAmount = person.calcAccruedAmount(differenceInMonths);

Their respective debts would then be updated accordingly with the following line:

addDebtToPerson(person, amount);

Design Considerations

Aspect: When to update / check a Person’s debt
Alternative 1 (Current choice): Check through the AddressBook in the Model component every time the user logs in
Pros: Convenient and intuitive to implement for developer.
Cons: If user never logs out, the debt would not be accrued.
Alternative 2: Create a Refresh command that does the checking instead of relying on the LoginAppRequestEvent
Pros: User can have the most up-to-date debt as long as he / she remembers to always enter the Refresh command.
Cons: Not convenient for user at all. It is also unlikely that the user would remain logged in for such a long duration.

End of Extract


other contributions

Added various fields to the Person Class

  • Debt field

  • Interest field

  • Date Borrow field

  • Deadline field