在 Laravel 中预订时间段,带有设备库存查询

Posted

技术标签:

【中文标题】在 Laravel 中预订时间段,带有设备库存查询【英文标题】:Booking Time slot, with Equipment Stock query, in Laravel 【发布时间】:2020-08-09 18:39:30 【问题描述】:

这是一个对大家来说很有趣的。 我发现自己陷入了实施难题。

我正在 Laravel 中开发一个预订应用程序,它允许人们在特定时间为空间预订房间和设备。 可用设备的数量是有限的,因此库存数量必须与预订相关的时间段一起查询。

我认为我已经解决了这个问题,方法是遍历同时发生的“其他预订”并计算当前正在使用的项目 -> 然后检查是否有库存。

对于我 90% 的测试来说,这一切正常,但只是设法找到了一个不允许我这样做的错误。

    $guitarheadcount = 0;
    $guitarcabcount = 0;
    $guitarcombocount = 0;
    $bassheadcount = 0;
    $basscabcount = 0;
    $basscombocount = 0;
    $drumkitcount = 0;
    $cymbalscount = 0;

    $otherbookings = Booking::where('Room_id', '!=', $bookinginfo->Room_id)
        ->where(function ($query) use ($begin, $end) 
            $query->where(function ($q) use ($begin, $end) 
                $q->where('Booking_start', '>=', $begin)
                ->where('Booking_start', '<', $end);
            )->orWhere(function ($q) use ($begin, $end) 
                $q->where('Booking_start', '<=', $begin)
                ->where('Booking_end', '>', $end);
            )->orWhere(function ($q) use ($begin, $end) 
                $q->where('Booking_end', '>', $begin)
                ->where('Booking_end', '<=', $end);
            )->orWhere(function ($q) use ($begin, $end) 
                $q->where('Booking_start', '>=', $begin)
                ->where('Booking_end', '<=', $end);
            );
    )->get();

   //'amounts' are attributes for Booking objects. 

    foreach($otherbookings as $other)
        $guitarheadcount = $other->Equip->guitarheadamount + $guitarheadcount;
        $guitarcabcount = $other->Equip->guitarcabamount + $guitarcabcount;
        $guitarcombocount = $other->Equip->guitarcomboamount + $guitarcombocount;
        $bassheadcount = $other->Equip->bassheadamount + $bassheadcount;
        $basscabcount = $other->Equip->basscabamount + $basscabcount;
        $basscombocount = $other->Equip->basscomboamount + $basscombocount;
        $drumkitcount = $other->Equip->drumkitamount + $drumkitcount;
        $cymbalscount = $other->Equip->cymbalsamount + $cymbalscount;
    

然后我使用单独的 if 语句来重定向如果计数最终大于库存中的数量。

一个实际的错误示例是:

库存有 2 套鼓组。 在下午 1 点到 2 点预订一个……然后在下午 2 点到 3 点在同一个房间预订另一个。两者都需要架子鼓。

如果我随后尝试在下午 1 点到 3 点在不同的空间进行预订,那么计数已经是 2,即使一组鼓再次免费(如果这有意义的话)。

我真的很难过。我无法想象是否需要:

继续“计数”,但生成的结果为与另一个在同一个房间中的每个项目减去 1 (?)。 我是否应该完全取消计数并为每个设备项目编写单独的查询...以及我将如何做到这一点!

任何帮助都将不胜感激。

【问题讨论】:

不确定,但请考虑一下。如果 1-2 需要一个架子鼓,2-3 需要另一个架子鼓。从计算机的角度来看,2h00m00s000000ms 具有精确值。换句话说。一微秒内,需要 2 个架子鼓。这将导致您的查询计数 2。使用 Illuminate\Support\Carbon$end 中减去 1 秒,然后再次检查。 感谢 Dimitri 回到我身边。我会试一试,看看它是否有帮助。我已经解决了,我可以将之前的 $order info 保存为在 for each 循环之前定义的数组。这样我就可以引用之前的 $order,而当前的订单正在被迭代。我也意识到... Room1 有 1:2pm + 1 个鼓。房间 2 有 2-3pm + 1 鼓。下午 1 点至 3 点预订 -> 房间 3 + 1 鼓。应该没问题。 【参考方案1】:

我将对此进行进一步测试,但我想我可能已经提出了解决方案。

我已经拥有的:

一种在选定时间范围内获取所有冲突预订的机制。 它可以提供集合中包含的所有项目的计数。 它不“知道”的是在预订过程中,库存是否会用完。

解决方案(到目前为止,早期测试正在发挥作用)。

我使用 orderBy 将原始查询结果按开始时间排序。

我使用了一个 foreach 来遍历它们。

我在循环之外定义了几个数组,我可以使用它们将先前循环的属性传递回下一个循环。如果没有发现计数错误,则在最后覆盖。

然后我创建了一些 if 语句来检查下一个预订与前一个预订。

如果下一次开始是在上一次结束之前,我创建了另一个数组来传递当前值,然后在 if 中为每个数组开始另一个数组,然后重新计算该时间范围内的所有预订。然后,如果计数再次超出该时间内的可用库存,它将爆发并重定向。

当该循环结束时,我们继续前一个循环。

为意大利面条代码道歉。

$first = $otherbookings->first();

    if ($first == null)


    else
       $previous = [];
    $previous ['id'] = $first->id;
    $previous ['Booking_end'] = $first->Booking_end;
    

    $tempdrumkitcount = 0;

    foreach($otherbookings as $other)

        if($previous ['id'] == $other->id)

            $drumkitcount = (int)$first->Equip->drumkitamount;
            //check
            if(($currenthireprices->drumkitstock - ($other->drumkitamount + $drumkitcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Check 1 error");
            
        
        else
            if($previous ['Booking_end'] > $other->Booking_start)

                $current ['id'] = $other->id;
                $current ['Booking_start'] = $other->Booking_start;
                $current ['Booking_end'] = $other->Booking_end;

                foreach($otherbookings as $newother)

                    if($newother->id != $current ['id'])

                        if(($newother->Booking_start < $current ['Booking_start']) && ($newother->Booking_end > $current ['Booking_start'] ))
                            $tempdrumkitcount = $tempdrumkitcount + $newother->Equip->drumkitamount;
                        
                        if(($newother->Booking_start > $current ['Booking_start']) && ($newother->Booking_end < $current ['Booking_end'] ))
                            $tempdrumkitcount = $tempdrumkitcount + $newother->Equip->drumkitamount;
                        
                        if(($currenthireprices->drumkitstock - ($drumkitamount + $tempdrumkitcount)) < 0)
                            return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $drumkitamount 'Drum kits' available between $timestart and $timeend to complete your booking. (Error- 100 [Cummalative Check]).");
                        
                    

                
                $drumkitcount = $other->Equip->drumkitamount + $drumkitcount;

                if(($currenthireprices->drumkitstock - ($drumkitamount + $drumkitcount)) < 0)
                    return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $drumkitamount 'Drum kits' available between $timestart and $timeend to complete your booking. (Error- 150 [Non-Cummalative Check]).");
                
                $drumkitcount =  $drumkitcount - $previous ['drumkitamount'];
            
            if($previous ['Booking_end'] <= $other->Booking_start)
                $drumkitcount =  $drumkitcount - $previous ['drumkitamount'];
                $drumkitcount = $drumkitcount + $other->Equip->drumkitamount;

                if(($currenthireprices->drumkitstock - ($drumkitamount + $drumkitcount)) < 0)
                    return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $drumkitamount 'Drum kits' available between $timestart and $timeend to complete your booking. (Error- 200 [Non-overlap main check]).");
                
            
        

        $previous ['id'] = $other->id;
        $previous ['Booking_end'] = $other->Booking_end;
        $previous ['drumkitamount'] = $other->Equip->drumkitamount;
    

【讨论】:

【参考方案2】:

虽然我之前回答中的方法看起来很有希望……但随着库存量和相邻预订量的增加,它开始出现无法修复的计数错误。

我重新考虑并设计了一个更好的解决方案。无论如何,用户只能预订至少 30 分钟的时段。

因此,使用 do/while 循环,对于用户选择的时间段每增加 30 分钟,它就会进行一次库存检查。

我确定锤击服务器不是很好,但至少在预订期间会有固定的时间对其进行查询。

///STOCK CHECK

    $stockcheckbegin = $begin;
    $stockcheckend = date("Y-m-d H:i", strtotime('+30 minutes',strtotime($begin)));

    $tempguitarheadcount = 0;
    $tempguitarcabcount = 0;
    $tempguitarcombocount = 0;
    $tempbassheadcount = 0;
    $tempbasscabcount = 0;
    $tempbasscombocount = 0;
    $tempdrumkitcount = 0;
    $tempcymbalscount = 0;

    do 
        $otherbookings = Booking::orderby('Booking_start', 'ASC')
        ->where(function ($query) use ($stockcheckbegin, $stockcheckend) 
            $query->where(function ($q) use ($stockcheckbegin, $stockcheckend) 
                $q->where('Booking_start', '>=', $stockcheckbegin)
                ->where('Booking_start', '<', $stockcheckend);
            )->orWhere(function ($q) use ($stockcheckbegin, $stockcheckend) 
                $q->where('Booking_start', '<=', $stockcheckbegin)
                ->where('Booking_end', '>', $stockcheckend);
            )->orWhere(function ($q) use ($stockcheckbegin, $stockcheckend) 
                $q->where('Booking_end', '>', $stockcheckbegin)
                ->where('Booking_end', '<=', $stockcheckend);
            )->orWhere(function ($q) use ($stockcheckbegin, $stockcheckend) 
                $q->where('Booking_start', '>=', $stockcheckbegin)
                ->where('Booking_end', '<=', $stockcheckend);
            );
        )->get();

        foreach($otherbookings as $other)

            $tempguitarheadcount = $tempguitarheadcount + $other->Equip->guitarheadamount;
            $tempguitarcabcount = $tempguitarcabcount + $other->Equip->guitarcabamount;
            $tempguitarcombocount = $tempguitarcombocount + $other->Equip->guitarcomboamount;
            $tempbassheadcount = $tempbassheadcount + $other->Equip->bassheadamount;
            $tempbasscabcount = $tempbasscabcount + $other->Equip->basscabamount;
            $tempbasscombocount = $tempbasscombocount + $other->Equip->basscomboamount;
            $tempdrumkitcount = $tempdrumkitcount + $other->Equip->drumkitamount;
            $tempcymbalscount = $tempcymbalscount + $other->Equip->cymbalsamount;

            if(($currenthireprices->guitarheadstock - ($guitarheadamount + $tempguitarheadcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Guitar Head' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->guitarcabstock - ($guitarcabamount + $tempguitarcabcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Guitar Cab' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->guitarcombostock - ($guitarcomboamount + $tempguitarcombocount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Guitar Combo' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->bassheadstock - ($bassheadamount + $tempbassheadcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Bass Head' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->basscabstock - ($basscabamount + $tempbasscabcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Bass Cab' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->basscombostock - ($basscomboamount + $tempbasscombocount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Bass Combo' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->drumkitstock - ($drumkitamount + $tempdrumkitcount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our 'Drum kit' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
            if(($currenthireprices->cymbalsstock - ($cymbalsamount + $tempcymbalscount)) < 0)
                return redirect()->back()->withInput()->with('Booking_query_error', "Sorry! Our sets of 'Cymbals' stock will run out during the course of this booking. (Between $stockcheckbegin and $stockcheckend)");
            
        

            $tempguitarheadcount = 0;
            $tempguitarcabcount = 0;
            $tempguitarcombocount = 0;
            $tempbassheadcount = 0;
            $tempbasscabcount = 0;
            $tempbasscombocount = 0;
            $tempdrumkitcount = 0;
            $tempcymbalscount = 0;

            $stockcheckbegin = date("Y-m-d H:i", strtotime('+30 minutes',strtotime($stockcheckbegin)));
            $stockcheckend = date("Y-m-d H:i", strtotime('+30 minutes',strtotime($stockcheckend)));

     while ($stockcheckbegin != $end);

    if(($currenthireprices->guitarheadstock - ($guitarheadamount + $guitarheadcount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $guitarheadamount guitar heads available between $timestart and $timeend. There's $currenthireprices->guitarheadstock in stock and $guitarheadcount in use.");
    
    if(($currenthireprices->guitarcabstock - ($guitarcabamount + $guitarcabcount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $guitarcabamount 'Guitar cabs' available between $timestart and $timeend. There's $currenthireprices->guitarcabstock in stock and $guitarcabcount in use.");
    
    if(($currenthireprices->guitarcombostock - ($guitarcomboamount + $guitarcombocount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $guitarcomboamount 'Guitar combos' available between $timestart and $timeend. There's $currenthireprices->guitarcombostock in stock and $guitarcombocount in use.");
    
    if(($currenthireprices->bassheadstock - ($bassheadamount + $bassheadcount)) < 0) 
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $bassheadamount 'Bass heads' available between $timestart and $timeend. There's $currenthireprices->bassheadstock in stock and $bassheadcount in use.");
    
    if(($currenthireprices->basscabstock - ($basscabamount + $basscabcount)) < 0) 
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $basscabamount 'Bass cabs' available between $timestart and $timeend. There's $currenthireprices->basscabstock in stock and $basscabcount in use.");
    
    if(($currenthireprices->basscombostock - ($basscomboamount + $basscombocount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $basscomboamount 'Bass combos' available between $timestart and $timeend. There's $currenthireprices->basscombostock in stock and $basscombocount in use.");
    
    if(($currenthireprices->drumkitstock - ($drumkitamount + $drumkitcount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $drumkitamount 'Drum kits' available between $timestart and $timeend. There's $currenthireprices->drumkitstock in stock and $drumkitcount in use.");
    
    if(($currenthireprices->cymbalsstock - ($cymbalsamount + $cymbalscount)) < 0)
        return redirect()->back()->withInput()->with('Booking_query_error', "Unfortunatly there aren't $cymbalsamount 'sets of cymbals' available between $timestart and $timeend. There's $currenthireprices->cymbalsstock in stock and $cymbalscount in use.");
    

    //----- END OF STOCK CHECK

【讨论】:

以上是关于在 Laravel 中预订时间段,带有设备库存查询的主要内容,如果未能解决你的问题,请参考以下文章

在 laravel 中获得总预订量为零的天数

如何使用 WHERE LIKE (或等效)搜索 Laravel 集合

orWhere 不使用 Laravel 雄辩的关系查询

如何使用 php 在 mysql 中进行购票预订系统?

在 Laravel Eloquent 中求和并返回页面

如何将带参数的 Laravel 模型函数调用到 Vuejs 模板中?