**Edit :**

Maturity date, what is it ?
---------------------------

I'm not native english speaker. Sorry about that. I think the best we can do, is to define Maturity Date. 

> 
> A maturity date is a date that indicates the deadline for the payment
>  of an invoice. In BtoB, the maturity date indicates when the customer
>  wants to pay us, defined during the contract it is usually a later date between 1 and 3 months
>  after the publishing of the bill. It's a calculated data, and
>  implemented in my application with the following code.
> 
> 
> 

I have this code in my Invoice module I extracted it for you can tests :

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

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

    public function getPaymentCondition()
    {
        return $this->paymentCondition;
    }

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

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

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

    public function setPaymentCondition($condition)
    {
        $this->paymentCondition = $days;
        return $this;
    }

}

class Test {
    /**
     * @param DateTime $dateInvoice
     * @param Config $config
     * @return DateTime
     */
    public function calcMaturityDate(\DateTime $dateInvoice, $config)
    {
        if ($config->getPaymentCondition() == 'delayed') {
            $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;
        } else {
            return $dateInvoice;
        }
    }
}

$config = new Config;
$config->setPaymentDay(15);
$config->setAmountDelayedDays(60);
$config->setPaymentCondition('delayed');

$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');

        // From 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('31-03-2015', $maturityDate->format('d-m-Y'));

        // New years and pass february
        $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'));
    }

```