PHP (Codeigniter) - Цена отличается в будние и выходные дни - PullRequest
0 голосов
/ 28 марта 2020

Я работаю в системе бронирования отелей, используя CI (codeigniter).

Для каждого номера цены на будни и выходные различны.

Итак, предположим, что посетитель пытается забронировать определенную c комнату с диапазоном дат со 2 апреля (четверг) - 6 апреля (понедельник) 2020, который включает 2 ночи в выходные.

Тариф на будние дни составляет 150 долларов, а на выходных - 200 долларов.

The calculation should be: 
2nd Apr - $150
3rd Apr - +150
4th Apr (weekend) - +200
5th Apr (Weekend) - +200
6th Apr -  Check out
The price should be : $700

Вместо 150 х 4 ночи = только 600 долларов.

Я не мог понять, как работает logi c?

Пожалуйста, сообщите, если у вас есть простой пример кодирования, чтобы он работал.

У меня есть стол для комнаты

Мне удается отследить, попадают ли «дата от» и «дата до» в будний или выходные дни, но не удается определить цену между диапазоном дат.

Ответы [ 3 ]

0 голосов
/ 28 марта 2020

Ну, давайте go! Допустим, у вас есть дата регистрации, дата проверки, цена в будние дни и цена в выходные дни.

$checkInDate = '2020-03-15';
$checkOutDate = '2020-03-28';
$regularPrice = 150;
$weekendPrice = 200;

Fantasti c! Теперь я считаю, что мы могли бы рассчитать разницу в днях между этим периодом.

 $date1=date_create($checkInDate);
 $date2=date_create($checkOutDate);
 $diff=date_diff($date1,$date2);
 $numberOfTheDaysInThisPeriod = $diff->format("%a") + 1;  //We add +1 here to count the checkin date

У нас здесь всего 14 дней

Теперь давайте посчитаем, сколько рабочих дней у нас в этот период! для этого мы можем использовать эту функцию, которая является полностью функциональной.

https://gist.github.com/andygock/4be9570ee7f56d7a80f6ac01d59cebc4

Эта функция возвращала мне всего 10 дней в неделю в течение этого периода, поэтому мы иметь

$totalWeekdays = 10;

Отлично, теперь давайте посчитаем, сколько дней у нас в выходные. Просто вычислите разницу между общим количеством дней и общим количеством дней недели.

$totalWeekendDays =  $numberOfTheDaysInThisPeriod - $totalWeekdays

Мы получаем в общей сложности 4 дня в выходные дни: 15/03 - 21/03 - 22 / 03 - 28/03

Теперь до фини sh мы рассчитываем общую цену на основе дней и цен.

$totalPrice =   (($regularPrice * $totalWeekdays) + ($weekendPrice * $totalWeekendDays));

Ну, я не проверял код, но Я верю, что так я бы подошел к проблеме :) Надеюсь, это поможет.

0 голосов
/ 28 марта 2020

Вот класс, который я создал для вычисления суммы с использованием массива тарифов, массив тарифов будет содержать все тарифы каждого дня недели.

/**
 * Total price calculator
 */
class TotalPrice
{
    protected $date_start = null;
    protected $date_end = null;
    protected $rates;

    public function __construct()
    {
        $this->rates = array_fill_keys(range(1, 7), 0.00);
    }

    public function setDateStart(DateTime $date)
    {
        if ($this->date_end && ($this->date_end < $date)) {
            throw new Exception("The end date must be greater than start date");
        }

        $this->date_start = $date;
        return $this;
    }

    public function setDateEnd(DateTime $date)
    {
        if ($this->date_start && ($this->date_start > $date)) {
            throw new Exception("The end date must be greater than start date");
        }

        $this->date_end = $date;
        return $this;
    }

    /**
     * Set rates
     * @param array $rates Must contain all week days and their rate
     */
    public function setRates(array $rates)
    {
        // Validate rates
        foreach (range(1, 7) as $key) {
            if (! array_key_exists($key, $rates)) {
                throw new Exception("Invalid rates, must include rates of all days of week");
            }
        }

        $this->rates = $rates;
        return $this;
    }

    /**
     * Set week-day rate
     * @param float $rate
     */
    public function setWeekDayRate(float $rate)
    {
        $this->rates[1] = $rate;
        $this->rates[2] = $rate;
        $this->rates[3] = $rate;
        $this->rates[4] = $rate;
        $this->rates[5] = $rate;

        return $this;
    }

    /**
     * Set week-end rate
     * @param float $rate
     */
    public function setWeekEndRate(float $rate)
    {
        $this->rates[6] = $rate;
        $this->rates[7] = $rate;

        return $this;
    }

    /**
     * Get the total price
     * @return float
     */
    public function getTotal(): float
    {
        $total = 0.00;
        $oneDayInterval = new DateInterval('P1D');
        $date = $this->date_start;

        do {
            $total += $this->rates[(int) $date->format('N')];
            $date->add($oneDayInterval);
        } while ($date <= $this->date_end);

        return $total;
    }
}

Тест 1:


// Test - 20 weekdays + 9 weekend days
$startDate = new DateTime('2020-02-01');
$endDate = new DateTime('2020-02-29');
$rates = [
    1 => 150, // Mon
    2 => 150, // Tue
    3 => 150, // Wed
    4 => 150, // Thu
    5 => 150, // Fri
    6 => 200, // Sat
    7 => 200, // Sun
];

$totalPriceCalculator = new TotalPrice();
$totalPriceCalculator->setDateStart($startDate)
    ->setDateEnd($endDate)
    ->setRates($rates);

$total = $totalPriceCalculator->getTotal();
$expectedTotal = 20 * 150 + 9 * 200;

echo "Expected total: {$expectedTotal}\n"; // Expected total: 4800
echo "Total: {$total}\n"; // Total: 4800

Тест 2:

// Test 2 - 20 weekdays + 9 weekend days
$startDate = new DateTime('2020-02-01');
$endDate = new DateTime('2020-02-29');
$weekDayRate = 150.00;
$weekEndRate = 200.00;

$totalPriceCalculator = new TotalPrice();
$totalPriceCalculator->setDateStart($startDate)
    ->setDateEnd($endDate)
    ->setWeekDayRate($weekDayRate)
    ->setWeekEndRate($weekEndRate);

$total = $totalPriceCalculator->getTotal();
$expectedTotal = 20 * 150 + 9 * 200;

echo "Expected total: {$expectedTotal}\n"; // Expected total: 4800
echo "Total: {$total}\n"; // Total: 4800

Вы можете использовать этот класс в качестве библиотеки.

0 голосов
/ 28 марта 2020

Упростить проблему (" разделяй и властвуй ")

Любой период времени можно разделить на "префикс недели" (все дни до первого воскресенья, исключая), a число «целых недель» (с воскресенья по субботу) и «суффикс недели» (неполная неделя, начинающаяся с воскресенья).

Может отсутствовать любой из этих трех периодов, но должен быть хотя бы один. Например, со вторника по следующий понедельник будет префикс TWTFS плюс суффикс SM без целых недель между ними.

Таким образом, у вас будет номер дня недели первого дня (от 0 до 6, 0 означает воскресенье); и день недели последнего дня. У вас также будет количество дней пребывания.

// Prefix: wait until Sunday
while (($beginDayNumber % 7) and ($stay > 0)) {
    // Here actually beginDayNumber can never be 0.
    if ($beginDayNumber == 0 || $beginDayNumber == 6) {
        $price += $weekendPrice;
    } else {
        $price += $normalPrice;
    }
    // Check next day
    $beginDayNumber++;
    // Day calculated, so decrement the stay.
    $stay--;
}

$beginDayNumber = 0;
// $fullWeekPrice should be 5*$normalPrice + 2*$weekendPrice,
// but who knows, there could even be a special offer.
$price += floor($stay / 7) * $fullWeekPrice;
// Now we have calculated the middle period.

// Get how many days remain.
$stay %= 7;
// Same code as above, slightly different loop condition
while ($stay > 0) {
    // Here, again, beginDayNumber can never be 6.
    if (($beginDayNumber == 0) || ($beginDayNumber == 6)) {
        $price += $weekendPrice;
    } else {
        $price += $normalPrice;
    }
    // Check next day
    $beginDayNumber ++;
    // Day calculated, so decrement the stay.
    $stay--;        
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...