Maturity date with PHP

I have this kind of code in my Invoice module :

/**
 * @param DateTime $dateInvoice
 * @param Config $config
 * @return DateTime
 */
public function calcMaturityDate(\DateTime $dateInvoice, Config $config)
{
        $dateMaturity = clone $dateInvoice;
        $startDay = $dateMaturity->format('j');

        $dateMaturity->modify("+{$config->getAmountDelayedDays()} days");
        $endDay = $dateMaturity->format('j');

        if ($startDay != $endDay && $endDay < 30) {
            $dateMaturity->modify('last day of last month');
        } else {
            $dateMaturity->modify('last day of this month');
        }
        if ($config->getPaymentDay() != 0) {
            $dateMaturity->modify('+' . $config->getPaymentDay() . 'days');
        }
        return $dateMaturity;
}

For the purpose of this problem explaination :

<?php
class Config
{
    protected $amountDelayedDays;
    protected $paymentDay;

    public function getAmountDelayedDays()
    {
        return $this->amountDelayedDays;
    }

    public function getPaymentDay()
    {
        return $this->paymentDay;
    }


    public function setAmountDelayedDays($days)
    {
        $this->amountDelayedDays = $days;
        return $this;
    }

    public function setPaymentDay($days)
    {
        $this->paymentDay = $days;
        return $this;
    }

}

class Test {
    /**
     * @param DateTime $dateInvoice
     * @param Config $config
     * @return DateTime
     */
    public function calcMaturityDate(\DateTime $dateInvoice, $config)
    {
            $dateMaturity = clone $dateInvoice;
            $startDay = $dateMaturity->format('j');

            $dateMaturity->modify("+{$config->getAmountDelayedDays()} days");
            $endDay = $dateMaturity->format('j');

            if ($startDay != $endDay && $endDay < 30) {
                $dateMaturity->modify('last day of last month');
            } else {
                $dateMaturity->modify('last day of this month');
            }
            if ($config->getPaymentDay() != 0) {
                $dateMaturity->modify('+' . $config->getPaymentDay() . 'days');
            }
            return $dateMaturity;
    }
}
$config = new Config;
$config->setPaymentDay(15);
$config->setAmountDelayedDays(60);

$test = new Test;
$date = $test->calcMaturityDate(new DateTime('2015-01-31'), $config);

var_dump($date);

?>

I have to calculate a maturity date from the date of invoice.

If my invoice is dated at 2014-11-30 and my client is configured to be charged 2 month later & on the 15′(=60days + 15 ), I have to produce a maturity date like this :

‘2015-02-15’

For doing this I have to variables in my Config class :

$config->getAmountDelayedDays() and $config->getPaymentDay()

My code is not perfect to handle all problems. February changing years, custom value of days… Jumped month…

I think the problem is in

if ($startDay != $endDay && $endDay < 30) {
                $dateMaturity->modify('last day of last month');
            } else {
                $dateMaturity->modify('last day of this month');
            }

It’s too simple to handle all cases, maybe it’s wrong. I can’t make my mind clear about this…

Tests case

I have units test testing this function I’m not passing

/**
     * Tests MaturityDate
     * 
     */
    public function testCanGiveCorrectMaturityDate()
    {
        $config = $this->parser->setConfig();
        $config->setAmountDelayedDays(60);
        $config->setPaymentDay(15);
        $config->setPaymentCondition('delayed');

        // in February Ok ?
        $dateInvoice = new \Datetime('2015-02-28');
        $maturityDate = $this->mock->calcMaturityDate($dateInvoice , $config);
        $this->assertEquals('15-05-2015', $maturityDate->format('d-m-Y'));

        // From February ok ?
        $dateInvoice = new \Datetime('2015-02-28');
        $config->setAmountDelayedDays(30);
        $config->setPaymentDay(0);
        $maturityDate = $this->mock->calcMaturityDate($dateInvoice , $config);
        $this->assertEquals('30-04-2015', $maturityDate->format('d-m-Y'));

        // New years
        $config->setAmountDelayedDays(90);
        $config->setPaymentDay(15);
        $dateInvoice = new \Datetime('2014-11-30');
        $maturityDate = $this->mock->calcMaturityDate($dateInvoice , $config);
        $this->assertEquals('15-03-2015', $maturityDate->format('d-m-Y'));

        // No delayed
        $config->setPaymentCondition('standard');
        $dateInvoice = new \Datetime('2014-11-30');
        $maturityDate = $this->mock->calcMaturityDate($dateInvoice , $config);
        $this->assertEquals('30-11-2014', $maturityDate->format('d-m-Y'));
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s