app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/views/HorizontalBar.java
public class HorizontalBar extends View {

    //Consts
    private static final int DEFAULT_TEXT_SIZE_PX = 26;
    private static final int DEFAULT_BACKGROUND_COLOR = R.color.horizontal_bar_default_background;
    private static final int DEFAULT_TEXT_COLOR = R.color.horizontal_bar_default_text;
    private static final int DEFAULT_TEXT_COLOR_IN = R.color.horizontal_bar_default_text_in;
    private static final int DEFAULT_TEXT_COLOR_OUT = R.color.horizontal_bar_default_text_out;
    private static final int DEFAULT_BAR_COLOR = R.color.horizontal_bar_default_bar;
    private static final int DEFAULT_BAR_HEIGHT = 40;           //Bar height in px
    private static final int DEFAULT_CANVAS_HEIGHT = 80;        //Canvas height in px when no height is given
    private static final int BAR_PADDING_X = 90;                //Bar padding on sides
    private static final int TEXT_PADDING_TOP = 90;             //Text from top of canvas
    private static final int BAR_TEXT_MARGIN = 30;              //Extra horizontal margin for mTextBar
    private static final int BAR_PADDING_TOP = 10;              //Bar from top of canvas
    private static final int BACKGROUND_EXTRA = 14;              //Background paint stroke = mBarHeightPx + BACKGROUND_EXTRA

    //Vars
    private int mCanvasHeight;
    private int mCanvasWidth;
    private int mBarLeftX;
    private int mBarProgressX;
    private int mBarRightX;
    private int mBarCenterY;

    //Attrs
    private String mTextLo;
    private String mTextHi;
    private String mTextBar;
    private float mTextSizePx;
    private int mTextColor;
    private int mBarTextColorIn;
    private int mBarTextColorOut;
    private int mBarHeightPx;
    private int mBarColor;
    private int mBarGradientColorStart;
    private int mBarGradientColorEnd;
    private int mProgressPercentage;
    private int mBackgroundColor;

    //Paints
    private Paint mTextPaint;
    private Paint mBarTextPaint;
    private Paint mBackgroundPaint;
    private Paint mBarPaint;

    public HorizontalBar(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context, attrs);
    }
    private void init(Context context, AttributeSet attrs) {

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.HorizontalBar, 0, 0);
        try {
            mTextLo = a.getString(R.styleable.HorizontalBar_textLo);
            mTextHi = a.getString(R.styleable.HorizontalBar_textHi);
            mTextBar = a.getString(R.styleable.HorizontalBar_textBar);
            mTextSizePx = a.getInt(R.styleable.HorizontalBar_textSizePx, DEFAULT_TEXT_SIZE_PX);
            mTextColor = a.getColor(R.styleable.HorizontalBar_textColor, ContextCompat.getColor(context, DEFAULT_TEXT_COLOR));
            mBarTextColorIn = a.getColor(R.styleable.HorizontalBar_barTextColorIn, ContextCompat.getColor(context, DEFAULT_TEXT_COLOR_IN));
            mBarTextColorOut = a.getColor(R.styleable.HorizontalBar_barTextColorOut, ContextCompat.getColor(context, DEFAULT_TEXT_COLOR_OUT));
            mBarHeightPx = a.getInt(R.styleable.HorizontalBar_barHeightPx, DEFAULT_BAR_HEIGHT);
            mBarColor = a.getColor(R.styleable.HorizontalBar_barColor, ContextCompat.getColor(context, DEFAULT_BAR_COLOR));
            mBarGradientColorStart = a.getColor(R.styleable.HorizontalBar_barGradientColorStart, -1);
            mBarGradientColorEnd = a.getColor(R.styleable.HorizontalBar_barGradientColorEnd, -1);
            mProgressPercentage = a.getInt(R.styleable.HorizontalBar_progressPercentage, 0);
            mBackgroundColor = a.getColor(R.styleable.HorizontalBar_backgroundColor, ContextCompat.getColor(context, DEFAULT_BACKGROUND_COLOR));

        } finally {
            a.recycle();
        }

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setTextSize(mTextSizePx);

        mBarTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBarTextPaint.setTextSize(mTextSizePx);

        mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundPaint.setStyle(Paint.Style.FILL);
        mBackgroundPaint.setStrokeWidth(mBarHeightPx + BACKGROUND_EXTRA);
        mBackgroundPaint.setColor(mBackgroundColor);
        mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);

        mBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBarPaint.setStrokeWidth(mBarHeightPx);
        mBarPaint.setStrokeCap(Paint.Cap.ROUND);

        if(mBarGradientColorStart == -1 || mBarGradientColorEnd == -1) {    //If gradient was not setup
            mBarPaint.setColor(mBarColor);
        }

    }



    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // Account for padding
        int xpad = getPaddingLeft() + getPaddingRight();
        int ypad = getPaddingTop() + getPaddingBottom();

        //Calculate usable canvas size
        mCanvasHeight = (h != 0 ? (h - ypad) : DEFAULT_CANVAS_HEIGHT);
        mCanvasWidth = w - xpad;

        mBarLeftX = getPaddingLeft() + BAR_PADDING_X;
        mBarRightX = getPaddingLeft() + mCanvasWidth - BAR_PADDING_X;
        mBarProgressX = mBarLeftX + (int)((mBarRightX - mBarLeftX)*((float)mProgressPercentage/100));
        if(mBarProgressX > mBarRightX)
            mBarProgressX = mBarRightX;
        mBarCenterY = getPaddingTop() + BAR_PADDING_TOP + (int)(mBarHeightPx*0.5);

        if(mBarGradientColorStart != -1 && mBarGradientColorEnd != -1) {    //If gradient was setup
            Shader shader = new LinearGradient(0, 0, mBarRightX, 0, mBarGradientColorStart, mBarGradientColorEnd, Shader.TileMode.MIRROR);
            mBarPaint.setShader(shader);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //Draw background
        canvas.drawLine(mBarLeftX, mBarCenterY, mBarRightX, mBarCenterY, mBackgroundPaint);

        //Draw bar
        canvas.drawLine(mBarLeftX, mBarCenterY, mBarProgressX, mBarCenterY, mBarPaint);

        if(mTextLo != null)
            canvas.drawText(mTextLo, mBarLeftX, getPaddingTop() + TEXT_PADDING_TOP, mTextPaint);
        if(mTextHi != null)
            canvas.drawText(mTextHi, mBarRightX, getPaddingTop() + TEXT_PADDING_TOP, mTextPaint);
        if(mTextBar != null) {
            if(mBarTextPaint.measureText(mTextBar, 0, mTextBar.length()) > (mBarProgressX - mBarLeftX)) {    //Text is too big to fit inside bar
                mBarTextPaint.setTextAlign(Paint.Align.LEFT);
                mBarTextPaint.setColor(mBarTextColorOut);
                canvas.drawText(mTextBar, mBarProgressX+BAR_TEXT_MARGIN, mBarCenterY+((float)DEFAULT_BAR_HEIGHT/4), mBarTextPaint);
            }
            else {
                mBarTextPaint.setTextAlign(Paint.Align.RIGHT);
                mBarTextPaint.setColor(mBarTextColorIn);
                canvas.drawText(mTextBar, mBarProgressX, mBarCenterY+((float)DEFAULT_BAR_HEIGHT/4), mBarTextPaint);

            }
        }

    }

    public String getTextLo() {
        return mTextLo;
    }

    public String getTextHi() {
        return mTextHi;
    }

    public String getTextBar() {
        return mTextBar;
    }

    public int getProgressPercentage() {
        return mProgressPercentage;
    }

    public int getLineColor() {
        return mBackgroundColor;
    }

    public int getBarColor() {
        return mBarColor;
    }

    public int getBarGradientColorStart() {
        return mBarGradientColorStart;
    }

    public int getBarGradientColorEnd() {
        return mBarGradientColorEnd;
    }

    public void setTextLo(String mTextLo) {
        this.mTextLo = mTextLo;
        invalidate();
        requestLayout();
    }

    public void setTextHi(String mTextHi) {
        this.mTextHi = mTextHi;
        invalidate();
        requestLayout();
    }

    public void setTextBar(String mTextBar) {
        this.mTextBar = mTextBar;
        invalidate();
        requestLayout();
    }

    public void setProgressPercentage(int mProgressPercentage) {
        this.mProgressPercentage = mProgressPercentage;
        invalidate();
        requestLayout();
    }

    public void setLineColor(int mLineColor) {
        this.mBackgroundColor = mLineColor;
        invalidate();
        requestLayout();
    }

    public void setBarColor(int mBarColor) {
        this.mBarColor = mBarColor;
        invalidate();
        requestLayout();
    }

    public void setBarGradientColorStart(int mBarGradientColorStart) {
        this.mBarGradientColorStart = mBarGradientColorStart;
        invalidate();
        requestLayout();
    }

    public void setBarGradientColorEnd(int mBarGradientColorEnd) {
        this.mBarGradientColorEnd = mBarGradientColorEnd;
        invalidate();
        requestLayout();
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/utils/Constants.java
public class Constants {
    public static final String PREFS_NAME = "CCManagerPreferences";
    public static final String ACTIVE_CC_ID = "ActiveCCId";

    public static final int EXPENSE_DETAIL_ACTIVITY_REQUEST_CODE = 283;
    public static final int RESULT_REFRESH_DATA = 5;
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/exceptions/CreditCardNotFoundException.java
public class CreditCardNotFoundException extends Exception {

    public static final String DEFAULT_MESSAGE = "Credit Card does not exist";

    public CreditCardNotFoundException(String message) {
        super(message);
    }

    public CreditCardNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/utils/DateUtils.java
public class DateUtils {
    public static String getRelativeTimeSpanString(Calendar date) {
        return android.text.format.DateUtils.getRelativeTimeSpanString(date.getTimeInMillis(), System.currentTimeMillis(), android.text.format.DateUtils.SECOND_IN_MILLIS).toString();
    }
    public static String getShortDateString(Calendar date) {
        return String.format(Locale.getDefault(), "%d/%02d/%02d @ %02d:%02d%s",
                date.get(Calendar.YEAR),
                (date.get(Calendar.MONTH)+1),
                date.get(Calendar.DAY_OF_MONTH),
                date.get(Calendar.HOUR),
                date.get(Calendar.MINUTE),
                (date.get(Calendar.AM_PM) == Calendar.AM ? "am" : "pm"));
    }

    public static String getDayShortMonthString(Calendar cal) {
        return new SimpleDateFormat("d MMM", Locale.getDefault()).format(cal.getTime());
    }


    /**
     * Returns the days in this period, startDate - endDate
     */
    public static int getDaysBetween(Calendar startDate, Calendar endDate) {

        // Create copies so we don't update the original calendars.
        Calendar start = Calendar.getInstance();
        start.setTimeZone(startDate.getTimeZone());
        start.setTimeInMillis(startDate.getTimeInMillis());

        Calendar end = Calendar.getInstance();
        end.setTimeZone(endDate.getTimeZone());
        end.setTimeInMillis(endDate.getTimeInMillis());

        // Add one millisecond so that the subtraction below works.
        // If end = Aug 5 23:59:59 we add one millisecond
        // so end = Aug 6 00:00:00 so that Aug 5 counts
        end.add(Calendar.MILLISECOND, 1);


        // At this point, each calendar is set to midnight on
        // their respective days. Now use TimeUnit.MILLISECONDS to
        // compute the number of full days between the two of them.
        int days = (int) TimeUnit.MILLISECONDS.toDays(Math.abs(end.getTimeInMillis() - start.getTimeInMillis()));
        return days;
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/utils/SharedPreferencesUtils.java
public class SharedPreferencesUtils {

    private static SharedPreferences getSharedPreferences(Context context) {
        return context.getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE);
    }

    private static void checkIfPreferenceExists(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        if(!getSharedPreferences(context).contains(preferenceName))
            throw new SharedPreferenceNotFoundException(preferenceName + " does not exist");
    }

    public static void setString(Context context, String preferenceName, String value) {
        getSharedPreferences(context).edit().putString(preferenceName, value).commit();
    }
    public static void setInt(Context context, String preferenceName, int value) {
        getSharedPreferences(context).edit().putInt(preferenceName, value).commit();
    }
    public static void setBoolean(Context context, String preferenceName, boolean value) {
        getSharedPreferences(context).edit().putBoolean(preferenceName, value).commit();
    }
    public static void setLong(Context context, String preferenceName, long value) {
        getSharedPreferences(context).edit().putLong(preferenceName, value).commit();
    }
    public static void setFloat(Context context, String preferenceName, float value) {
        getSharedPreferences(context).edit().putFloat(preferenceName, value).commit();
    }

    public static String getString(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        checkIfPreferenceExists(context, preferenceName);
        return getSharedPreferences(context).getString(preferenceName, "");
    }
    public static int getInt(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        checkIfPreferenceExists(context, preferenceName);
        return getSharedPreferences(context).getInt(preferenceName, 0);
    }
    public static boolean getBoolean(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        checkIfPreferenceExists(context, preferenceName);
        return getSharedPreferences(context).getBoolean(preferenceName, false);
    }
    public static long getLong(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        checkIfPreferenceExists(context, preferenceName);
        return getSharedPreferences(context).getLong(preferenceName, 0);
    }
    public static float getFloat(Context context, String preferenceName) throws SharedPreferenceNotFoundException {
        checkIfPreferenceExists(context, preferenceName);
        return getSharedPreferences(context).getFloat(preferenceName, 0);
    }

}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/dialogs/CheckCreditPeriodLimitDialogFragment.java
public class CheckCreditPeriodLimitDialogFragment extends AppCompatDialogFragment implements View.OnClickListener  {

    //CONSTS
    private static String TAG_ARGS_CREDIT_CARD = "TAG_ARGS_CREDIT_CARD";
    private static String TAG_ARGS_PREVIOUS_CREDIT_LIMIT = "TAG_ARGS_PREVIOUS_CREDIT_LIMIT";

    //DB
    private ExpenseManagerDAO mDao;

    //UI
    private DialogInterface.OnDismissListener mOnDismissListener;
    private TextView mCreditPeriodLimitTitle;
    private EditText mCreditPeriodLimitAmount;
    private Button mCreateButton;

    //DATA
    private CreditCard mCreditCard;
    private BigDecimal mPreviousCreditPeriodLimit;


    public CheckCreditPeriodLimitDialogFragment() {
        // Empty constructor is required for DialogFragment
    }

    public static CheckCreditPeriodLimitDialogFragment newInstance(ExpenseManagerDAO dao, CreditCard creditCard, BigDecimal previousCreditPeriodLimit) {
        CheckCreditPeriodLimitDialogFragment frag = new CheckCreditPeriodLimitDialogFragment();
        Bundle args = new Bundle();
        args.putSerializable(TAG_ARGS_CREDIT_CARD, creditCard);
        args.putSerializable(TAG_ARGS_PREVIOUS_CREDIT_LIMIT, previousCreditPeriodLimit);
        frag.setArguments(args);
        frag.setDao(dao);
        return frag;
    }

    public void setDao(ExpenseManagerDAO dao) {
        mDao = dao;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.dialog_new_credit_period, container);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getDialog().setTitle(R.string.dialog_new_credit_period_title);
        getDialog().setCancelable(false);

        // Fetch arguments from bundle and set title
        mCreditCard = (CreditCard) getArguments().getSerializable(TAG_ARGS_CREDIT_CARD);
        mPreviousCreditPeriodLimit = (BigDecimal) getArguments().getSerializable(TAG_ARGS_PREVIOUS_CREDIT_LIMIT);

        if(mPreviousCreditPeriodLimit == null || mCreditCard == null) {
            Toast.makeText(getActivity(), "Error, wrong arguments passed. Dismissing dialog.", Toast.LENGTH_SHORT).show();
            dismiss();
        }

        // Get fields from view
        mCreditPeriodLimitTitle = (TextView) view.findViewById(R.id.dialog_new_credit_period_limit_title);
        mCreditPeriodLimitAmount = (EditText) view.findViewById(R.id.dialog_new_credit_period_limit_amount);
        mCreateButton = (Button) view.findViewById(R.id.dialog_new_credit_period_button_create);

        // Set onClick listener
        mCreateButton.setOnClickListener(this);

        mCreditPeriodLimitAmount.setText(mPreviousCreditPeriodLimit.toPlainString());
        mCreditPeriodLimitTitle.setText(String.format(
                Locale.getDefault(),
                getResources().getText(R.string.dialog_new_credit_period_limit_title).toString(),
                mCreditCard.getCurrency().getCode()));

    }


    @Override
    public void onClick(View view) {
        int id = view.getId();
        switch(id) {
            case R.id.dialog_new_credit_period_button_create:

                //Verify the credit limit value
                String amount = mCreditPeriodLimitAmount.getText().toString();
                if(amount.equals("") || new BigDecimal(amount).compareTo(new BigDecimal(0)) == 0) {
                    Toast.makeText(getContext(), getResources().getString(R.string.dialog_new_credit_period_error_bad_amount), Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    mDao.insertCurrentCreditPeriod(mCreditCard.getId(), mCreditCard.getClosingDay(), new BigDecimal(amount));
                    Toast.makeText(getActivity(), "Credit Period successfully created", Toast.LENGTH_SHORT).show();
                }catch (CouldNotInsertDataException e) {
                    Toast.makeText(getActivity(), "Could not create Credit Period", Toast.LENGTH_SHORT).show();
                }

                dismiss();
                break;
        }
    }


    public void setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
        mOnDismissListener = onDismissListener;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (mOnDismissListener != null) {
            mOnDismissListener.onDismiss(dialog);
        }
    }

}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/holders/SelectableCreditCardViewHolder.java
public class SelectableCreditCardViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private Context mContext;
    SelectableCreditCardSelectedListener mListener = null;

    //DATA
    private CreditCard mCurrent;
    private int mPosition;

    //UI
    private RelativeLayout container;
    private TextView bankName;
    private TextView alias;
    private TextView currency;
    private TextView cardNumber;
    private TextView creditCardLabel;
    private TextView cardExpirationLabel;
    private TextView cardExpiration;
    private ImageView cardType;
    private ImageView cardChip;


    public SelectableCreditCardViewHolder(View itemView) {
        super(itemView);

        container = (RelativeLayout) itemView.findViewById(R.id.list_item_credit_card_container);
        bankName = (TextView) itemView.findViewById(R.id.list_item_credit_card_bank_name);
        alias = (TextView) itemView.findViewById(R.id.list_item_credit_card_alias);
        currency = (TextView) itemView.findViewById(R.id.list_item_credit_card_currency);
        cardNumber = (TextView) itemView.findViewById(R.id.list_item_credit_card_number);
        creditCardLabel = (TextView) itemView.findViewById(R.id.list_item_credit_card_label);
        cardExpirationLabel = (TextView) itemView.findViewById(R.id.list_item_credit_card_expiration_label);
        cardExpiration = (TextView) itemView.findViewById(R.id.list_item_credit_card_expiration);
        cardType = (ImageView) itemView.findViewById(R.id.list_item_credit_card_type);
        cardChip = (ImageView) itemView.findViewById(R.id.list_item_credit_card_chip);

        //LAYOUT_DETAILED views


    }


    public void setData(Context context, CreditCard current, int position) {
        mContext = context;
        mCurrent = current;
        mPosition = position;

        bankName.setText(current.getBankName());
        alias.setText(current.getCardAlias());
        cardNumber.setText(current.getCardNumber());
        currency.setText(current.getCurrency().getCode());
        cardExpiration.setText(current.getShortCardExpirationString());

        container.setBackground(current.getCreditCardBackground().getBackgroundDrawable(context));
        bankName.setTextColor(current.getCreditCardBackground().getTextColor(context));
        alias.setTextColor(current.getCreditCardBackground().getTextColor(context));
        currency.setTextColor(current.getCreditCardBackground().getTextColor(context));
        cardNumber.setTextColor(current.getCreditCardBackground().getTextColor(context));
        cardExpiration.setTextColor(current.getCreditCardBackground().getTextColor(context));
        creditCardLabel.setTextColor(current.getCreditCardBackground().getTextColor(context));
        cardExpirationLabel.setTextColor(current.getCreditCardBackground().getTextColor(context));

        switch(current.getCardType()) {
            case AMEX:
                cardType.setImageResource(R.drawable.logo_amex);
                break;
            case DISCOVER:
                cardType.setImageResource(R.drawable.logo_discover);
                break;
            case MASTERCARD:
                cardType.setImageResource(R.drawable.logo_mastercard);
                break;
            case VISA:
                cardType.setImageResource(R.drawable.logo_visa);
                break;
        }


    }

    public void setListeners() {
        container.setOnClickListener(this);
    }

    public void setOnCreditCardSelectedListener(SelectableCreditCardSelectedListener listener) {
        mListener = listener;
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();

        switch(id) {
            case R.id.list_item_credit_card_container:
                if(mListener != null)
                    mListener.OnCreditCardSelected(mCurrent);
                break;
        }
    }


    public interface SelectableCreditCardSelectedListener {
        void OnCreditCardSelected(CreditCard creditCard);
    }

}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/exceptions/SharedPreferenceNotFoundException.java
public class SharedPreferenceNotFoundException extends Exception {

    public static final String DEFAULT_MESSAGE = "Preference not found";

    public SharedPreferenceNotFoundException(String message) {
        super(message);
    }

    public SharedPreferenceNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/app/utils/TextUtils.java
public class TextUtils {

    @SuppressWarnings("deprecation")
    public static Spanned fromHtml(String html){
        Spanned result;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            result = Html.fromHtml(html,Html.FROM_HTML_MODE_LEGACY);
        } else {
            result = Html.fromHtml(html);
        }
        return result;
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/model/CreditCard.java
public class CreditCard implements Serializable {

    private int id;
    private String cardAlias;
    private String bankName;
    private String cardNumber;
    private Currency currency;
    private CreditCardType cardType;
    private Calendar cardExpiration;
    private int closingDay;         // Fecha de corte: Fecha de cierre de operaciones del mes, para efectos de registros y cobros.
    private int dueDay;             // Fecha Limite de Pago: Fecha máxima para el próximo pago sin generar incumplimiento e intereses de mora.
    private CreditCardBackground creditCardBackground;


    private Map<Integer, CreditPeriod> creditPeriods;

    public CreditCard(String cardAlias, String bankName, String cardNumber, @NonNull Currency currency, @NonNull CreditCardType cardType, @NonNull Calendar cardExpiration, int closingDay, int dueDay, @NonNull CreditCardBackground creditCardBackground) {
        this.cardAlias = cardAlias;
        this.bankName = bankName;
        this.cardNumber = cardNumber;
        this.currency = currency;
        this.cardType = cardType;

        this.cardExpiration = Calendar.getInstance();
        this.cardExpiration.setTimeZone(cardExpiration.getTimeZone());
        this.cardExpiration.setTimeInMillis(cardExpiration.getTimeInMillis());

        this.dueDay = dueDay;
        this.closingDay = closingDay;
        this.creditCardBackground = creditCardBackground;
    }

    public CreditCard(int id, String cardAlias, String bankName, String cardNumber, @NonNull Currency currency, @NonNull CreditCardType cardType, @NonNull Calendar cardExpiration, int closingDay, int dueDay, @NonNull CreditCardBackground creditCardBackground) {
        this(cardAlias, bankName, cardNumber, currency, cardType, cardExpiration, closingDay, dueDay, creditCardBackground);
        this.id = id;
    }

    public CreditCard(int id, String cardAlias, String bankName, String cardNumber, @NonNull Currency currency, @NonNull CreditCardType cardType, @NonNull Calendar cardExpiration, int closingDay, int dueDay, @NonNull CreditCardBackground creditCardBackground, @NonNull Map<Integer, CreditPeriod> creditPeriods) {
        this(id, cardAlias, bankName, cardNumber, currency, cardType, cardExpiration, closingDay, dueDay, creditCardBackground);
        this.creditPeriods = creditPeriods;
    }



    public int getId() {
        return id;
    }


    public String getCardAlias() {
        return cardAlias;
    }

    public void setCardAlias(String cardAlias) {
        this.cardAlias = cardAlias;
    }

    public String getBankName() {
        return bankName;
    }

    public void setBankName(String bankName) {
        this.bankName = bankName;
    }

    public String getCardNumber() {
        return cardNumber;
    }

    public void setCardNumber(String cardNumber) {
        this.cardNumber = cardNumber;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }

    public CreditCardType getCardType() {
        return cardType;
    }

    public void setCardType(CreditCardType cardType) {
        this.cardType = cardType;
    }

    public Calendar getCardExpiration() {
        return cardExpiration;
    }

    public void setCardExpiration(Calendar cardExpiration) {
        this.cardExpiration = Calendar.getInstance();
        this.cardExpiration.setTimeZone(cardExpiration.getTimeZone());
        this.cardExpiration.setTimeInMillis(cardExpiration.getTimeInMillis());
    }

    public String getShortCardExpirationString() {
        if(cardExpiration == null)
            return "-/-";

        SimpleDateFormat formatter = new SimpleDateFormat("MM/yy", Locale.getDefault());
        return formatter.format(cardExpiration.getTime());
    }

    public String getLongCardExpirationString() {
        if(cardExpiration == null)
            return "-";

        SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault());
        return formatter.format(cardExpiration.getTime());
    }

    public int getClosingDay() {
        return closingDay;
    }

    public void setClosingDay(int closingDay) {
        this.closingDay = closingDay;
    }

    public int getDueDay() {
        return dueDay;
    }

    public void setDueDay(int dueDay) {
        this.dueDay = dueDay;
    }

    public CreditCardBackground getCreditCardBackground() {
        return creditCardBackground;
    }

    public Map<Integer, CreditPeriod> getCreditPeriods() {
        return creditPeriods;
    }

    public void setCreditPeriods(Map<Integer, CreditPeriod> creditPeriods) {
        this.creditPeriods = creditPeriods;
    }

    /**
     * Returns a List of Credit Cards based on the number of existing CreditCardBackgrounds, instantiated with default values
     * @return List<CreditCard>
     */
    public static List<CreditCard> getCreditCardBackgroundTypesList(Context context) {
        List<CreditCard> creditCards = new ArrayList<>();

        String defaultAlias = context.getResources().getString(R.string.activity_add_new_cc_alias);
        String defaultBankName = context.getResources().getString(R.string.activity_add_new_cc_bank);
        String defaultCardNumber = context.getResources().getString(R.string.activity_add_new_cc_number);
        Calendar defaultExpiration = Calendar.getInstance();
        defaultExpiration.add(Calendar.YEAR, 5);

        for (CreditCardBackground c : CreditCardBackground.values()) {
            creditCards.add(new CreditCard(defaultAlias, defaultBankName, defaultCardNumber, Currency.USD, CreditCardType.AMEX, defaultExpiration, 0, 0, c));
        }

        return creditCards;
    }

    @Override
    public String toString() {
        return  "ID=" + id + "\r\n" +
                " cardAlias=" + cardAlias + "\r\n" +
                " cardNumber=" + cardNumber + "\r\n" +
                " currency=" + currency + "\r\n" +
                " cardType=" + cardType + "\r\n" +
                " cardExpiration=" + cardExpiration + "\r\n" +
                " closingDay=" + closingDay + "\r\n" +
                " dueDay=" + dueDay + "\r\n" +
                " creditPeriods=" + creditPeriods;
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/exceptions/CreditPeriodNotFoundException.java
public class CreditPeriodNotFoundException extends Exception {

    public static final String DEFAULT_MESSAGE = "Credit Period does not exist";

    public CreditPeriodNotFoundException(String message) {
        super(message);
    }

    public CreditPeriodNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/enums/ExpenseCategory.java
public enum ExpenseCategory {

    FOOD(0, "Food", R.color.expense_category_1),
    LEISURE(1, "Leisure", R.color.expense_category_2),
    ENTERTAINMENT(2, "Entertainment", R.color.expense_category_3),
    CLOTHING(3, "Clothing", R.color.expense_category_4),
    EDUCATION(4, "Education", R.color.expense_category_5);



    private int mIndex;
    private String mFriendlyName;
    private int mColor;

    ExpenseCategory(int index, String friendlyName, int color) {

        mIndex = index;
        mFriendlyName = friendlyName;
        mColor = color;
    }


    public String getCode(){
        return this.name();
    }

    public int getColor() {
        return mColor;
    }

    public String getFriendlyName() {
        return mFriendlyName;
    }

    @Override
    public String toString() {
        return mFriendlyName;
    }

    public int getIndex() {
       return mIndex;
    }

    public static ExpenseCategory getByExpenseCategoryId(int expenseCategoryId) {

        for(ExpenseCategory expenseCategory : ExpenseCategory.values()) {
            if(expenseCategory.getIndex() == expenseCategoryId)
                return expenseCategory;
        }
        throw new IllegalArgumentException(String.valueOf(expenseCategoryId));
    }

}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/database/ExpenseManagerDAO.java
public class ExpenseManagerDAO {

    private ExpenseManagerDbHelper mDatabaseHelper;

    public ExpenseManagerDAO(Context context) {
        mDatabaseHelper = new ExpenseManagerDbHelper(context);

    }

    /**
     * Returns a List of stored Credit Cards.
     * Note: The Credit Cards will not contain CreditPeriods, Expenses or Payments.
     */
    public List<CreditCard> getCreditCardList() {

        List<CreditCard> creditCards = new ArrayList<>();
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();

        Cursor cursor = db.query(ExpenseManagerContract.CreditCardTable.TABLE_NAME, null, null, null, null, null, null);

        try {
            while (cursor.moveToNext()) {
                creditCards.add(getCreditCardFromCursor(cursor));
            }
        } finally {
            cursor.close();
        }

        return creditCards;
    }

    /**
     * Returns a List of CreditPeriods associated with ccardId.
     * Note: The periods will not contain Expenses or Payments.
     * @param cardId The ID of the Credit Card
     */
    public List<CreditPeriod> getCreditPeriodListFromCard(int cardId) {
        List<CreditPeriod> creditPeriods = new ArrayList<>();
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();

        Cursor cursor =  db.query(ExpenseManagerContract.CreditPeriodTable.TABLE_NAME, null,
                ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_CARD.getName() + " == " + cardId, null, null, null,
                ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_START_DATE.getName() + " DESC");

        try {
            while (cursor.moveToNext()) {
                creditPeriods.add(getCreditPeriodFromCursor(cursor));
            }
        } finally {
            cursor.close();
        }

        return creditPeriods;
    }



    /**
     * Finds a CreditCard with the supplied cardId, will not return creditPeriods associated with
     * the card
     * @param cardId The ID of the Credit Card
     */
    public CreditCard getCreditCard(int cardId) throws CreditCardNotFoundException {
        String[] selectionArgs = new String[]{String.valueOf(cardId)};
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();

        Cursor cursor =  db.query(ExpenseManagerContract.CreditCardTable.TABLE_NAME, null,
                ExpenseManagerContract.CreditCardTable._ID + " =? ", selectionArgs, null, null, null);

        if(cursor.getCount() == 0)
            throw new CreditCardNotFoundException("Specified Credit Card not found in the database. Passed value=" + cardId);
        if(cursor.getCount() > 1)
            throw new CreditCardNotFoundException("Database UNIQUE constraint failure, more than one record found. Passed value=" + cardId);

        cursor.moveToNext();
        return getCreditCardFromCursor(cursor);
    }

    /**
     * Returns a Credit Card with the supplied cardId and the specified periodIndex.
     * Note: PeriodIndex must be either zero (returns credit period contaning current date) or a
     * negative value (-1 returns previous credit period, and so on)
     * @param cardId The ID of the Credit Card
     * @param periodIndex An integer <= 0
     */
    public CreditCard getCreditCardWithCreditPeriod(int cardId, int periodIndex) throws CreditCardNotFoundException, CreditPeriodNotFoundException, InvalidParameterException{
        if(periodIndex > 0)
            throw new InvalidParameterException("PeriodIndex must be >=0. Passed value=" + periodIndex);

        CreditCard creditCard = getCreditCard(cardId);

        //Get ordered (DESC) list of credit periods
        List<CreditPeriod> creditPeriods = getCreditPeriodListFromCard(cardId);

        //Find the creditPeriod according to periodIndex
        CreditPeriod cp = getCreditPeriodFromPeriodIndex(creditPeriods, periodIndex, creditCard.getClosingDay());

        //Create Map and set it on the Credit Card
        Map<Integer, CreditPeriod> creditPeriodMap = new HashMap<>();
        creditPeriodMap.put(periodIndex, cp);
        creditCard.setCreditPeriods(creditPeriodMap);

        return creditCard;
    }


    /**
     * Returns a Credit Card with the supplied cardId and as many credit periods as numPeriods
     * indicates. Counting backwards starting on periodIndex.
     * Note: PeriodIndex must be either zero (current creditPriod) or a
     * negative value (-1 refers to the previous credit period, and so on)
     * Note2: Passing periodIndex=-1, numPeriods=3 will return three periods (Period -1, -2 and -3)
     * @param cardId The ID of the Credit Card
     * @param periodIndex An integer <= 0
     * @param numPeriods An integer >= 1
     */
    public CreditCard getCreditCardWithCreditPeriodRange(int cardId, int periodIndex, int numPeriods) throws CreditCardNotFoundException, CreditPeriodNotFoundException, InvalidParameterException {
        if (periodIndex > 0)
            throw new InvalidParameterException("PeriodIndex must be less or equal than 0. Passed value=" + periodIndex);
        if (numPeriods <= 0)
            throw new InvalidParameterException("NumPeriods must be more or equal than 1. Passed value=" + periodIndex);

        CreditCard creditCard = getCreditCard(cardId);

        //Get ordered (DESC) list of credit periods
        List<CreditPeriod> creditPeriods = getCreditPeriodListFromCard(cardId);

        Map<Integer, CreditPeriod> creditPeriodMap = new HashMap<>();

        //Find the creditPeriod according to periodIndex
        for (int i = periodIndex; i > (periodIndex-numPeriods); --i) {
            CreditPeriod cp = getCreditPeriodFromPeriodIndex(creditPeriods, i, creditCard.getClosingDay());
            creditPeriodMap.put(i, cp);
        }

        //Set creditPeriods in creditCard and return
        creditCard.setCreditPeriods(creditPeriodMap);
        return creditCard;
    }


    /**
     * Returns a Credit Period from a List of creditPeriods which complies with the supplied
     * periodIndex and closingDay.
     * Note: PeriodIndex must be either zero (returns credit period contaning current date) or a
     * negative value (-1 returns previous credit period, and so on)
     * Note2: closingDay must be between 1 and 28.
     * @param creditPeriods List of Credit Periods to search into
     * @param periodIndex An integer <= 0
     * @param closingDay An integer between 1 and 28
     */
    private CreditPeriod getCreditPeriodFromPeriodIndex(List<CreditPeriod> creditPeriods, int periodIndex, int closingDay) throws CreditPeriodNotFoundException, InvalidParameterException {
        if(closingDay < 1 || closingDay > 28)
            throw new InvalidParameterException("ClosingDay must be between 1 and 28. Passed value=" + closingDay);
        if(periodIndex > 0)
            throw new InvalidParameterException("PeriodIndex must be >=0. Passed value=" + periodIndex);
        if(creditPeriods == null || creditPeriods.size() == 0)
            throw new InvalidParameterException("creditPeriods is null or empty");

        //Get a day which will be between the starting and ending dates of the wanted creditPeriod
        Calendar day = Calendar.getInstance();
        if(periodIndex != 0)
            day.add(Calendar.MONTH, periodIndex);

        for (CreditPeriod cp : creditPeriods) {
            if(cp.getStartDate().compareTo(day) <=0 && cp.getEndDate().compareTo(day) >=0) {
                cp.setExpenses(getExpensesFromCreditPeriod(cp.getId()));
                cp.setPayments(getPaymentsFromCreditPeriod(cp.getId()));
                return cp;

            }
        }

        throw new CreditPeriodNotFoundException("Credit period (index " + periodIndex + ") not found in passed creditPeriods List");
    }

    /**
     * Returns a Credit Period with the supplied periodId, containing its Expenses and Payments
     * @param periodId The ID of the Credit Period
     */
    public CreditPeriod getCreditPeriodFromPeriodId(int periodId) throws CreditPeriodNotFoundException {
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
        CreditPeriod creditPeriod;

        Cursor cursor =  db.query(ExpenseManagerContract.CreditPeriodTable.TABLE_NAME, null, ExpenseManagerContract.CreditPeriodTable._ID + " == " + periodId, null, null, null, null);

        if(cursor.getCount() == 0)
            throw new CreditPeriodNotFoundException("Specified Credit Period not found in the database. Passed value=" + periodId);
        if(cursor.getCount() > 1)
            throw new CreditPeriodNotFoundException("Database UNIQUE constraint failure, more than one record found. Passed Value=" + periodId);

        try{
            cursor.moveToNext();
            creditPeriod = getCreditPeriodFromCursor(cursor);
            creditPeriod.setExpenses(getExpensesFromCreditPeriod(periodId));
            creditPeriod.setPayments(getPaymentsFromCreditPeriod(periodId));
        } finally {
            cursor.close();
        }

        return creditPeriod;
    }


    /**
     * Returns a List of Expenses, given a creditPeriodId
     * @param periodId the Id of the Credit period
     */
    public List<Expense> getExpensesFromCreditPeriod(int periodId) {
        List<Expense> expenses = new ArrayList<>();
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();

        Cursor cursor =  db.query(ExpenseManagerContract.ExpenseTable.TABLE_NAME, null,
                ExpenseManagerContract.ExpenseTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName() + " == " + periodId,
                null, null, null, ExpenseManagerContract.ExpenseTable.COLUMN_NAME_DATE.getName() + " DESC");


        try {
            while (cursor.moveToNext()) {
                expenses.add(getExpenseFromCursor(cursor));
            }
        } finally {
            cursor.close();
        }

        return expenses;
    }

    /**
     * Returns a List of Payments, given a creditPeriodId
     * @param periodId the Id of the Credit period
     */
    public List<Payment> getPaymentsFromCreditPeriod(int periodId) {
        List<Payment> payments = new ArrayList<>();
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();

        Cursor cursor =  db.query(ExpenseManagerContract.PaymentTable.TABLE_NAME, null,
                ExpenseManagerContract.PaymentTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName() + " == " + periodId,
                null, null, null, ExpenseManagerContract.PaymentTable.COLUMN_NAME_DATE.getName() + " DESC");

        try {
            while (cursor.moveToNext()) {
                payments.add(getPaymentFromCursor(cursor));
            }
        } finally {
            cursor.close();
        }

        return payments;
    }


    /**
     * Returns an Expenses, given an Expense ID
     * @param expenseId the Id of the Expense
     */
    public Expense getExpense(int expenseId) throws CouldNotGetDataException {
        SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
        String[] selectionArgs = new String[]{String.valueOf(expenseId)};


        Cursor cursor =  db.query(ExpenseManagerContract.ExpenseTable.TABLE_NAME, null,
                ExpenseManagerContract.ExpenseTable._ID + " =? ",
                selectionArgs, null, null, null);


        if(cursor.getCount() == 0)
            throw new CouldNotGetDataException("Expense not found for ID = " + expenseId);


        cursor.moveToNext();
        return getExpenseFromCursor(cursor);
    }



    /* Delete data from database */

    /**
     * Deletes a credit card, with its associated credit periods, expenses and payments
     */
    public boolean deleteCreditCard(int creditCardId) throws CouldNotDeleteDataException {

        //Fetch all credit periods and delete associated expenses and payments
        for( CreditPeriod cp : getCreditPeriodListFromCard(creditCardId)) {
            deleteExpensesFromCreditPeriod(cp.getId());
            deletePaymentsFromCreditPeriod(cp.getId());
            deleteCreditPeriod(cp.getId());
        }

        //Finally, delete the credit card
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(creditCardId)};

        return db.delete(ExpenseManagerContract.CreditCardTable.TABLE_NAME,
                ExpenseManagerContract.CreditCardTable._ID + " =?",
                whereArgs) > 0;
    }

    public boolean deleteCreditPeriod(int creditPeriodId) throws CouldNotDeleteDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(creditPeriodId)};

        return db.delete(ExpenseManagerContract.CreditPeriodTable.TABLE_NAME,
                ExpenseManagerContract.CreditPeriodTable._ID + " =?",
                whereArgs) > 0;
    }


    public boolean deleteExpensesFromCreditPeriod(int creditPeriodId) throws CouldNotDeleteDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(creditPeriodId)};

        return db.delete(ExpenseManagerContract.ExpenseTable.TABLE_NAME,
                ExpenseManagerContract.ExpenseTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName() + " =?",
                whereArgs) > 0;
    }

    public boolean deleteExpense(int expenseId) throws CouldNotDeleteDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(expenseId)};

        return db.delete(ExpenseManagerContract.ExpenseTable.TABLE_NAME,
                ExpenseManagerContract.ExpenseTable._ID + " =?",
                whereArgs) > 0;
    }



    public boolean deletePaymentsFromCreditPeriod(int creditPeriodId) throws CouldNotDeleteDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(creditPeriodId)};

        return db.delete(ExpenseManagerContract.PaymentTable.TABLE_NAME,
                ExpenseManagerContract.PaymentTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName() + " =?",
                whereArgs) > 0;
    }

    public boolean deletePayment(int paymentId) throws CouldNotDeleteDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
        String[] whereArgs = new String[]{String.valueOf(paymentId)};

        return db.delete(ExpenseManagerContract.PaymentTable.TABLE_NAME,
                ExpenseManagerContract.PaymentTable._ID + " =?",
                whereArgs) > 0;
    }




    /* Update data on database */
    public long updateCreditCard(CreditCard creditCard) throws CouldNotUpdateDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        //Set values
        ContentValues values = getValuesFromCreditCard(creditCard);

        //Which row to update
        String selection = ExpenseManagerContract.CreditCardTable._ID + " =? ";
        String[] selectionArgs = { String.valueOf(creditCard.getId()) };

        int count = db.update(
                ExpenseManagerContract.CreditCardTable.TABLE_NAME,
                values,
                selection,
                selectionArgs);

        return count;
    }

    public long updateExpense(Expense expense) throws CouldNotUpdateDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        //Set values
        ContentValues values = getValuesFromExpense(expense);

        //Which row to update
        String selection = ExpenseManagerContract.ExpenseTable._ID + " =? ";
        String[] selectionArgs = { String.valueOf(expense.getId()) };

        int count = db.update(
                ExpenseManagerContract.ExpenseTable.TABLE_NAME,
                values,
                selection,
                selectionArgs);

        return count;
    }

    public long updateCreditPeriod(int creditCardId, CreditPeriod creditPeriod) throws CouldNotUpdateDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        //Set values
        ContentValues values = getValuesFromCreditPeriod(creditCardId, creditPeriod);

        //Which row to update
        String selection = ExpenseManagerContract.CreditPeriodTable._ID + " =? ";
        String[] selectionArgs = { String.valueOf(creditPeriod.getId()) };

        int count = db.update(
                ExpenseManagerContract.CreditPeriodTable.TABLE_NAME,
                values,
                selection,
                selectionArgs);

        return count;
    }



    /* Insert data into database */

    public long insertCreditCard(CreditCard creditcard, BigDecimal firstCreditPeriodLimit) throws CouldNotInsertDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_ALIAS.getName(), creditcard.getCardAlias());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BANK_NAME.getName(), creditcard.getBankName());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_NUMBER.getName(), creditcard.getCardNumber());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CURRENCY.getName(), creditcard.getCurrency().getCode());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_TYPE.getName(), creditcard.getCardType().getCode());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CLOSING_DAY.getName(), creditcard.getClosingDay());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_DUE_DAY.getName(), creditcard.getDueDay());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BACKGROUND.getName(), creditcard.getCreditCardBackground().getCode());

        if(creditcard.getCardExpiration() != null)
            values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_EXPIRATION.getName(), creditcard.getCardExpiration().getTimeInMillis());
        else
            values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_EXPIRATION.getName(), "");

        long newRowId;
        newRowId = db.insert(ExpenseManagerContract.CreditCardTable.TABLE_NAME, null, values);

        if(newRowId == -1)
            throw new CouldNotInsertDataException("There was a problem inserting the Credit Card: " + creditcard.toString());
        else {
            //Insert first creditPeriod
            insertCurrentCreditPeriod(newRowId, creditcard.getClosingDay(), firstCreditPeriodLimit);
        }

        return newRowId;

    }

    /**
     * Inserts a creditPeriod associated to a creditCard, which engulfs the current date (today), given a closing date
     * @param creditCardId the Id of the CreditCard to associate the CreditPeriod
     * @param  closingDay the credit card's closing day
     * @param creditPeriodLimit BigDecimal value of the currency limit of the period
     */
    public long insertCurrentCreditPeriod(long creditCardId, int closingDay, BigDecimal creditPeriodLimit) throws CouldNotInsertDataException {
        //Insert first creditPeriod

        // Set dates to be at midnight (start of day) today.
        Calendar startDate = Calendar.getInstance();
        startDate.set(Calendar.HOUR_OF_DAY, 0);
        startDate.set(Calendar.MINUTE, 0);
        startDate.set(Calendar.SECOND, 0);
        startDate.set(Calendar.MILLISECOND, 0);
        startDate.set(Calendar.DAY_OF_MONTH, closingDay);

        Calendar endDate = Calendar.getInstance();
        endDate.setTimeInMillis(startDate.getTimeInMillis());

        //Check if closingDay if before or after today
        if(closingDay <= Calendar.getInstance().get(Calendar.DAY_OF_MONTH))
            endDate.add(Calendar.MONTH, 1);
        else
            startDate.add(Calendar.MONTH, -1);

        endDate.add(Calendar.MILLISECOND, -1);

        CreditPeriod creditPeriod = new CreditPeriod(CreditPeriod.PERIOD_NAME_COMPLETE, startDate, endDate, creditPeriodLimit);
        return insertCreditPeriod(creditCardId, creditPeriod);
    }

    public long insertCreditPeriod(long creditCardId, CreditPeriod creditPeriod) throws CouldNotInsertDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_CARD.getName(), creditCardId);
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_PERIOD_NAME_STYLE.getName(), creditPeriod.getPeriodNameStyle());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_START_DATE.getName(), creditPeriod.getStartDate().getTimeInMillis());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_END_DATE.getName(), creditPeriod.getEndDate().getTimeInMillis());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_CREDIT_LIMIT.getName(), creditPeriod.getCreditLimit().toPlainString());


        long newRowId = -1;
        newRowId = db.insert(ExpenseManagerContract.CreditPeriodTable.TABLE_NAME, null, values);

        if(newRowId == -1)
            throw new CouldNotInsertDataException("There was a problem inserting the Credit Period: " + creditPeriod.toString());

        return newRowId;

    }

    public long insertExpense(int creditPeriodId, Expense expense) throws CouldNotInsertDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        ContentValues values = getValuesFromExpense(expense);
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName(), creditPeriodId);

        long newRowId;
        newRowId = db.insert(ExpenseManagerContract.ExpenseTable.TABLE_NAME, null, values);

        if(newRowId == -1)
            throw new CouldNotInsertDataException("There was a problem inserting the Expense: " + expense.toString());

        return newRowId;
    }


    public long insertPayment(int creditPeriodId, Payment payment) throws CouldNotInsertDataException {
        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.PaymentTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_PERIOD.getName(), creditPeriodId);
        values.put(ExpenseManagerContract.PaymentTable.COLUMN_NAME_DESCRIPTION.getName(), payment.getDescription());
        values.put(ExpenseManagerContract.PaymentTable.COLUMN_NAME_AMOUNT.getName(), payment.getAmount().toPlainString());
        values.put(ExpenseManagerContract.PaymentTable.COLUMN_NAME_CURRENCY.getName(), payment.getCurrency().getCode());
        values.put(ExpenseManagerContract.PaymentTable.COLUMN_NAME_DATE.getName(), payment.getDate().getTimeInMillis());


        long newRowId;
        newRowId = db.insert(ExpenseManagerContract.ExpenseTable.TABLE_NAME, null, values);

        if(newRowId == -1)
            throw new CouldNotInsertDataException("There was a problem inserting the Payment: " + payment.toString());

        return newRowId;
    }



    /* Model to ContentValues */
    private ContentValues getValuesFromExpense(Expense expense) {
        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_DESCRIPTION.getName(), expense.getDescription());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_THUMBNAIL.getName(), expense.getThumbnail());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_FULL_IMAGE_PATH.getName(), expense.getFullImagePath());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_AMOUNT.getName(), expense.getAmount().toPlainString());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_CURRENCY.getName(), expense.getCurrency().getCode());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_DATE.getName(), expense.getDate().getTimeInMillis());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_EXPENSE_CATEGORY.getName(), expense.getExpenseCategory().getCode());
        values.put(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_EXPENSE_TYPE.getName(), expense.getExpenseType().getCode());
        return values;
    }

    private ContentValues getValuesFromCreditCard(CreditCard creditCard) {
        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_ALIAS.getName(), creditCard.getCardAlias());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BANK_NAME.getName(), creditCard.getBankName());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_NUMBER.getName(), creditCard.getCardNumber());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CURRENCY.getName(), creditCard.getCurrency().getCode());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_TYPE.getName(), creditCard.getCardType().getCode());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_EXPIRATION.getName(), creditCard.getCardExpiration().getTimeInMillis());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CLOSING_DAY.getName(), creditCard.getClosingDay());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_DUE_DAY.getName(), creditCard.getDueDay());
        values.put(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BACKGROUND.getName(), creditCard.getCreditCardBackground().getCode());
        return values;
    }

    private ContentValues getValuesFromCreditPeriod(int creditCardId, CreditPeriod creditPeriod) {
        ContentValues values = new ContentValues();
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_FOREIGN_KEY_CREDIT_CARD.getName(), creditCardId);
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_PERIOD_NAME_STYLE.getName(), creditPeriod.getPeriodNameStyle());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_START_DATE.getName(), creditPeriod.getStartDate().getTimeInMillis());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_END_DATE.getName(), creditPeriod.getEndDate().getTimeInMillis());
        values.put(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_CREDIT_LIMIT.getName(), creditPeriod.getCreditLimit().toPlainString());
        return values;
    }


    /* Cursor to Model */

    private CreditCard getCreditCardFromCursor(Cursor cursor) {
        int id = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable._ID));
        String cardAlias = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_ALIAS.getName()));
        String bankName = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BANK_NAME.getName()));
        String cardNumber = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_NUMBER.getName()));
        Currency currency = Currency.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CURRENCY.getName())));
        CreditCardType cardType = CreditCardType.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_TYPE.getName())));
        int closingDay = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CLOSING_DAY.getName()));
        int dueDay = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_DUE_DAY.getName()));
        CreditCardBackground creditCardBackground = CreditCardBackground.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_BACKGROUND.getName())));


        Calendar cardExpiration = null;
        if(!cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_EXPIRATION.getName())).isEmpty()) {
            cardExpiration = Calendar.getInstance();
            cardExpiration.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(ExpenseManagerContract.CreditCardTable.COLUMN_NAME_CARD_EXPIRATION.getName())));
        }

        return new CreditCard(id, cardAlias, bankName, cardNumber, currency, cardType, cardExpiration, closingDay, dueDay, creditCardBackground);
    }


    private CreditPeriod getCreditPeriodFromCursor(Cursor cursor) {
        int id = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.CreditPeriodTable._ID));
        int periodNameStyle = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_PERIOD_NAME_STYLE.getName()));
        Calendar startDate = Calendar.getInstance();
        startDate.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_START_DATE.getName())));
        Calendar endDate = Calendar.getInstance();
        endDate.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_END_DATE.getName())));
        BigDecimal creditLimit =  new BigDecimal(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.CreditPeriodTable.COLUMN_NAME_CREDIT_LIMIT.getName())));

        return new CreditPeriod(id, periodNameStyle, startDate, endDate, creditLimit);
    }


    private Expense getExpenseFromCursor(Cursor cursor) {

        int id = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable._ID));
        String description = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_DESCRIPTION.getName()));
        byte[] image = cursor.getBlob(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_THUMBNAIL.getName()));
        String fullImagePath = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_FULL_IMAGE_PATH.getName()));
        BigDecimal amount = new BigDecimal(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_AMOUNT.getName())));
        Currency currency = Currency.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_CURRENCY.getName())));
        Calendar date = Calendar.getInstance();
        date.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_DATE.getName())));
        ExpenseCategory expenseCategory = ExpenseCategory.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_EXPENSE_CATEGORY.getName())));
        ExpenseType expenseType = ExpenseType.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.ExpenseTable.COLUMN_NAME_EXPENSE_TYPE.getName())));

        return new Expense(id, description, image, fullImagePath, amount, currency, date, expenseCategory, expenseType);
    }


    private Payment getPaymentFromCursor(Cursor cursor) {

        int id = cursor.getInt(cursor.getColumnIndex(ExpenseManagerContract.PaymentTable._ID));
        String description = cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.PaymentTable.COLUMN_NAME_DESCRIPTION.getName()));
        BigDecimal amount = new BigDecimal(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.PaymentTable.COLUMN_NAME_AMOUNT.getName())));
        Currency currency = Currency.valueOf(cursor.getString(cursor.getColumnIndex(ExpenseManagerContract.PaymentTable.COLUMN_NAME_CURRENCY.getName())));
        Calendar date = Calendar.getInstance();
        date.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(ExpenseManagerContract.PaymentTable.COLUMN_NAME_DATE.getName())));

        return new Payment(id, description, amount, currency, date);
    }
}
app/src/main/java/ve/com/abicelis/creditcardexpensemanager/model/DailyExpense.java
public class DailyExpense {

    Calendar date;
    BigDecimal amount;

    public DailyExpense (Calendar date, BigDecimal amount) {
        this.amount = amount;

        this.date = Calendar.getInstance();
        this.date.setTimeZone(date.getTimeZone());
        this.date.setTimeInMillis(date.getTimeInMillis());
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void addToAmount(BigDecimal amountToAdd) {
        amount = amount.add(amountToAdd);
    }

    public Calendar getDate() {
        return date;
    }

    public String getFormattedDate() {
        String formattedDate = String.format(Locale.getDefault(), "%1s %2$02d", date.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault()), date.get(Calendar.DAY_OF_MONTH));

        return formattedDate;
    }

}


Question: package ve.com.abicelis.creditcardexpensemanager.app.fragments;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import ve.com.abicelis.creditcardexpensemanager.R;
import ve.com.abicelis.creditcardexpensemanager.app.dialogs.CheckCreditPeriodLimitDialogFragment;
import ve.com.abicelis.creditcardexpensemanager.app.holders.SelectableCreditCardViewHolder;
import ve.com.abicelis.creditcardexpensemanager.app.utils.Constants;
import ve.com.abicelis.creditcardexpensemanager.app.utils.DateUtils;
import ve.com.abicelis.creditcardexpensemanager.app.utils.SharedPreferencesUtils;
import ve.com.abicelis.creditcardexpensemanager.app.utils.TextUtils;
import ve.com.abicelis.creditcardexpensemanager.app.views.HorizontalBar;
import ve.com.abicelis.creditcardexpensemanager.database.ExpenseManagerDAO;
import ve.com.abicelis.creditcardexpensemanager.enums.ExpenseCategory;
import ve.com.abicelis.creditcardexpensemanager.exceptions.CreditCardNotFoundException;
import ve.com.abicelis.creditcardexpensemanager.exceptions.CreditPeriodNotFoundException;
import ve.com.abicelis.creditcardexpensemanager.exceptions.SharedPreferenceNotFoundException;
import ve.com.abicelis.creditcardexpensemanager.model.CreditCard;
import ve.com.abicelis.creditcardexpensemanager.model.DailyExpense;




/**
 * Created by abice on 4/10/2016.
 */

public class OverviewFragment extends Fragment {

    //CONST
    private static final String TAG = OverviewFragment.class.getSimpleName();

    //DATA
    int activeCreditCardId = -1;
    CreditCard activeCreditCard = null;
Answer:     ExpenseManagerDAO dao;