Query to get available slot from appointments table - mysql

I have employees, working_hours, & appointments table. with the following details:
Employees | working_hours | appointment
id, name | id, day, start_time, end_time, employeeable_id, employeeable_type | id, employee_id, start_date_time, end_date_time
Relation:
class Employee extends Model
{
public function workingHours()
{
return $this->morphMany(WorkingHour::class, 'employeeable');
}
}
class WorkingHour extends Model
{
public function employeeable()
{
return $this->morphTo();
}
}
class Appointment extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
Employee A has the following working hours:
[
{ day: 1, start_time: '08:00:00', end_time: '17:00:00' },
...
{ day: 5, start_time: '08:00:00', end_time: '17:00:00 }
]
Employee A has an appointment on May 23, 2022 09:00:00 till 09:30:00 (each appointment duration is 30 minutes)
Question:
If admin requests for available slots from May 22, 2022 to June 1, 2022 for Employee A, I expect response like this:
[
{ '2022-05-22': ['08:00', '08:30', '09:00', ..., '17:00'] },
{ '2022-05-23': ['08:00', '08:30', '09:30'] } // 09:00 notice excluded.
...
{ '2022-06-01, [] }
]
How to define the above query? All I can think of is to loop every working hours time from employee A and check if the time is available or not.

I suggest you don't handle time with queries.
this is my solution:
public function index()
{
$appointment = [
'id' => 1,
'name' => 'Appointment 1',
'start_date_time' => '2022-05-23 09:00:00',
'end_date_time' => '2022-05-23 09:30:00'
];
// Employee A working hours
$workingHours = collect([
['day' => 1, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 2, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 3, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 4, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 5, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 6, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 0, 'start_time' => '08:00:00', 'end_time' => '17:00:00'], // carbon for sunday default is 0
]);
$dateArray = [];
$startDate = Carbon::parse('2022-05-22');
$endDate = Carbon::parse('2022-06-01');
while ($startDate->lte($endDate)) {
// seach for working hours that match the day of the week
$workingHour = (array) $workingHours->firstWhere('day', $startDate->dayOfWeek);
// generate time for each day
$times = $this->generateTimes($workingHour);
// extract date from appoint start date time
$appointmentDate = Carbon::parse($appointment['start_date_time'])->format('Y-m-d');
if ($appointmentDate === $startDate->format('Y-m-d')) {
// remove time according to appointment time
$times = $this->removeTime($times, $appointment);
}
// add time to date array
$dateArray[$startDate->format('Y-m-d')] = $times;
// increment date
$startDate->addDay();
}
dd($dateArray);
}
private function generateTimes(array $workingHour)
{
// the working time of the workers must be reduced by at least 1 hour.
// because there is no way for you to have an appointment on your end working time.
$startTime = Carbon::parse($workingHour['start_time']);
$endTime = Carbon::parse($workingHour['end_time'])->subHour();
$times = [];
while ($startTime->lte($endTime)) {
$times[] = $startTime->format('H:i');
$startTime->addMinutes(30);
}
return $times;
}
private function removeTime($times, $appointment)
{
$startTime = Carbon::parse($appointment['start_date_time']);
$endTime = Carbon::parse($appointment['end_date_time']);
$startTime = $startTime->format('H:i');
$endTime = $endTime->format('H:i');
$times = array_diff($times, [$startTime, $endTime]);
return $times;
}

Related

Looping Array of Json to Database Laravel?

I have Json Data like this :
$data = '[
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 250 gr",
"SKU": "20091"
},
{
"OrderId": "1038806370",
"qtty": "2",
"Item": "Strawberry 130 gr",
"SKU": "20092"
},
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 130 gr",
"SKU": "20092"
}
]';
and I want to Save in my database MySql using PHP Laravel,...
I Want To save data from json to my table, there are table Order values [orderID,...] and OrderDetail values [orderID, SKU, Qty]
This is my code in controller
$order = json_decode($data, true);
foreach ($order as $ord) {
$check = Order::where('orderid', $ord['OrderId'])->get();
if (count($data) > 0) {
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
but i dont get what i want, I get QTY of SKU 20091 is 2 but actual json data is 3
I'm not sure why you're counting the $data instead of $check variable. You don't really need the $check variable either though. I'll rewrite your code below.
$order = json_decode($data, true);
foreach ($order as $ord) {
// use EXIST query to check if Order exists or not.
if (Order::where('orderid', $ord['OrderId'])->exists())
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
But your if/else could also be removed by using the firstOrCreate() method.
$orders = json_decode($data, true);
foreach ($orders as $order) {
// Get Order Model with orderid = $order['OrderId'] or create it if it doesn't exist
$model = Order::firstOrCreate([
'orderid'=> $order['OrderId']
]);
// Get OrderDetail with provided SKU, qtty and orderid or create it if it doesn't exist.
OrderDetail::firstOrCreate([
'order_id' => $model->orderid
'sku_id' => $order['SKU'],
'qty' => $order['qtty']
]);
}
You could also do it inline.
$orders = json_decode($data, true);
foreach ($orders as $order) {
OrderDetail::firstOrCreate([
'order_id' => Order::firstOrCreate(['orderid'=> $order['OrderId']])->orderid,
'sku_id' => $order['SKU'],
'qty' => $order['qtty'],
]);
}

Laravel determine the date from database if MONDAY-SUNDAY

Good day gorgeous friends on the internet!
I have a query to get data from database per week. Now I can get a result as you can see in the picture below.
Query:
return static::selectRaw('SUM(total) as total')
->selectRaw('COUNT(*) as total_orders')
->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()])
->whereNotIn('status', ['canceled', 'refunded'])
->selectRaw('EXTRACT(DAY FROM created_at) as day')
->groupBy(DB::raw('EXTRACT(DAY FROM created_at)'))
->orderby('day')
->get();
and in my controller
return response()->json([
'data' => Order::salesAnalytics(),
]);
RESULT
The problem is how can I show it to my chartjs like this see picture below.
You can use this array to determine the day name from day number
days_numbers = [
0 => 'saturday',
1 => 'sunday',
2 => 'monday',
3 => 'thuesday',
4 => 'wednesday',
5 => 'thursday',
6 => 'friday',
];
you can use this for getting day index:
$day_index = fmod($day_number, 7);

Yii2. How to build subexpression

How can i build query with subexpression, without using yii\db\Expression and raw sql. For example this:
SELECT * FROM user WHERE archived = 3 AND ((group = 2 AND status = 3) OR (group = 3 AND status = 2));
You can build such condition using array expressions:
$users = (new Query())
->from('user')
->where(['archived' => 3])
->andWhere([
'or',
[
'group' => 2,
'status' => 3,
],
[
'group' => 3,
'status' => 2,
],
])
->all();

Total of all days

I'm trying to get the total budgets of the last x days. I tried the following but the days without budgets are not being returned.
<?php
class Budget extends \Eloquent {
public static function getTotalBudgetsByDay($days = 31)
{
$budgetByDays = self::where('created_at', '>=', \Carbon\Carbon::now()->subDays($days))
->groupBy('date')
->orderBy('date', 'ASC')
->get([
\DB::raw('Date(created_at) as date'),
\DB::raw('COUNT(*) as total')
]);
return array_map(function ($row) {
return $row->getAttributes();
}, $budgetByDays->all());
}
}
$budgetsByDays = \Budget::getTotalBudgetsByDay();
Result:
Array (
[0] => Array
(
[date] => 2015-01-08
[total] => 2
)
[1] => Array
(
[date] => 2015-01-09
[total] => 1
)
[2] => Array
(
[date] => 2015-01-11
[total] => 7
)
)
in this case on 10 not appear in the array

WordPress get specific posts in arbitrary order

Right now, I'm doing:
$posts = get_posts(array('post_type' => 'page', 'post__in' => array(1, 3, 2, 9, 7)));
and am having two issues:
Post 3 is of 'post_type' => 'post', so it doesn't get selected, but I want it! If I leave out 'post_type' => 'page', then only post 3 is selected (because it must assume 'post_type' => 'post'.).
I want to be able to order the posts arbitrarily by their ids. If I knew how to use MySQL, I could do:
SELECT * FROM wp_posts WHERE ID IN (1, 3, 2, 9, 7)
ORDER BY FIND_IN_SET(ID, '1,3,2,9,7');
But, how should I do this with WordPress?
First fetch all posts arbitrarily by their ids and then loop through all the posts
You can do in this way:-
$posts=$wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE ID IN (1, 3, 2, 9, 7)
ORDER BY FIND_IN_SET(ID, '1,3,2,9,7')");
$count=count($posts);
for ($counter=0 ; $counter < $count; $counter++)
{
$post=get_post( $posts[$counter]->ID, $output );
//do your stuffs with posts
}
Hope this helps
Kawauso on the #wordpress IRC channel informed me that "post_type takes an array of values." From that, I found that the following also selects post 3:
So, I did the following:
$post_ids = array(1 => 0, 3 => 1, 2 => 2, 9 => 3, 7 => 4);
$posts = get_posts(array('post_type' => array('post', 'page'),
'post__in' => array_keys($post_ids)));
$ordered_posts = array(0,0,0,0,0); // size of five; keeps order
foreach ($posts as $p) {
setup_postdata($p);
$ordered_posts[$post_ids[$p->ID]] = array(
'permalink' => get_permalink($p->ID),
'title' => $p->post_title,
'excerpt' => get_the_excerpt(),
'date' => date('F j, Y', strtotime($p->post_date)));
}
According to this thread, you can use this code and then use the classic WordPress loop:
$args = array(
'post_type'=>'page',
'orderby'=>'menu_order',
'order'=>'ASC'
);
query_posts($args);