<?php
//kakunin コメント確認する
/*
ファイル名:kintoneCalendarService.php
処理概要:kintone予定アプリから情報を渡す
作成年月日:2023/08/18
作成者:a.tojo
修正年月日:2024/04/24 k.saito
修正内容:kintoneでキャンセルになった(非表示チェックがON)データは、抽出対象から外す
修正年月日:2024/07/23 k.saito
修正内容:エアコン2階下ろし工事のカレンダ表示ができない現象の調査で、ログ埋込
*/
declare(strict_types=1); //ECCUBEでエラー出たら外す
namespace Customize\Service;
require_once(dirname(__FILE__, 4) . '/php/kintone/kntn_class_schedule.php');
require_once(dirname(__FILE__, 4) . '/php/kintone/kntn_class_staff.php');
require_once(dirname(__FILE__, 4) . '/php/common/error_notification.php'); // エラー通知クラス
//PHPUnit用
//namespace kintone\sinwasama;
//require_once(dirname(__FILE__) . '/php/kintone/kntn_class_schedule.php');
//require_once(dirname(__FILE__) . '/php/kintone/kntn_class_staff.php');
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use php\kintone\KntnSchedule;
use php\kintone\KntnStaff;
//use php\common\ErrNotifi;
//use php\common\LogOut;
use \Datetime;
use Eccube\Request\Context;
use Customize\Service\getAreaForCalendarService; //各エリアの変数が格納されている
class kintoneCalendarService
{
/**
* @var KntnSchedule
*/
private $kntn;
/**
* @var sendErrorNotifiService
*/
protected $sendErrorNotifi;
public function __construct(
sendErrorNotifiService $sendErrorNotifi,
getAreaForCalendarService $getAreaForCalendarService
) {
$this->sendErrorNotifi = $sendErrorNotifi;
$this->getAreaForCalendarService = $getAreaForCalendarService;
}
/**
* カレンダーに設定する予約可能日の詳細を作成する
*
* @param Carbon $targetDate ターゲット日 本日
* @param array $reservationDetail 予約可能日の詳細。カレンダーで使用。商品カテゴリ対応のスタッフを各地域ごとに表示
* @param array $subStaffReservationDetail サブ担当者の予約可能日の詳細。カレンダーで使用。商品カテゴリ関係なく各地域対応スタッフを表示
* @param array $areaStaffFromCalender 各エリアの担当スタッフ
* @param Carbon $startMonth 本日の前月の中旬 ※作業開始日と作業終了日が前月〜今月を跨ぐ可能性があるため
* @param Carbon $endMonth 本日の来月末
* @param boolean $subStaffFlg エコキュート判断用。trueの場合は対象カテゴリがエコキュート
* @param array $subStaff エコキュート用、担当エリアのサブスタッフ
*
* @return array $reservationDetail,$subStaffReservationDetail
*/
public function
makeReservationDetail(Carbon $targetDate, $area, $categoryName, &$reservationDetail, &$subStaffReservationDetail, $subStaffFlg)
{
log_debug('makereservationDetail start');
//dump($targetDate);
//初期化 start
$startMonth = $targetDate->copy()->startOfMonth(); //>subMonth()->endOfMonth()->subDays(15);
$endMonth = $targetDate->copy()->addMonth()->endOfMonth();
$startMonthString = $startMonth->toDateString();
$endMonthString = $endMonth->toDateString();
$subStaff = [];
$subStaffKey = 'サブスタッフ';
$reservationDetail = [];
$staffFlg = 'default';
//deleteTargetの値で削除対象の時間帯が変わる為
$am1 = 'AM1';
$am2 = 'AM2';
$pm1 = 'PM1';
$pm2 = 'PM2';
$timePeriodDelete = array(
'AM1' => array($am1),
'AM2' => array($am2),
'AM' => array($am1, $am2),
'PM1' => array($pm1),
'PM2' => array($pm2),
'PM' => array($pm1, $pm2),
'AM1~PM1' => array($am1, $am2, $pm1),
'AM2~PM2' => array($am2, $pm1, $pm2),
'AM2~PM1' => array($am2, $pm1),
'終日' => array($am1, $am2, $pm1, $pm2)
);
$normalTimezone = $timePeriodDelete['終日'];
$ecocuteTimezone = $timePeriodDelete['AM'];
//kintoneから商品カテゴリ対応のメインスタッフを取得(エコキュート含む)
$categoryStaff = $this->getStaffScheduleRecord($categoryName, $startMonthString, $endMonthString);
dump($categoryStaff);
log_debug($categoryName . 'に対応しているスタッフ');
log_debug(print_r($categoryStaff, true));
//各エリア対応のスタッフを取得する
$areaStaff = $this->getAreaStaffRecord($categoryStaff, $area);
dump($areaStaff);
//デバッグ
$areastaff_txt = print_r($areaStaff, true);
log_debug('areastaff:'.$areastaff_txt);
//エコキュートの場合はサブ担当者の情報も取得するため
if ($subStaffFlg) {
log_info('エコキュートなのでサブ担当者を選択');
$createdStaff = $categoryStaff;
//検索しやすくする為、キー値をスタッフコードにする
foreach ($createdStaff as $staffKey => $staffValue) {
$staffCode = $staffValue['ユーザー選択'][0]['code'];
$createdStaff[$staffCode] = $staffValue;
unset($createdStaff[$staffKey]);
}
foreach ($area as $targetArea) {
$variable = $targetArea['variable'];
$areaName = $targetArea['name'];
$subStaff[$variable] = $this->getStaffScheduleRecord($areaName, $startMonthString, $endMonthString, $subStaffFlg, $createdStaff); //サブスタッフのレコードを取得
}
}
//カレンダー用の各エリアスタッフ $areaStaffFromCalender を作成する
$key = '';
$value = '';
$areaStaffFromCalender = [];
foreach ($areaStaff as $targetAreaKey => $targetArea) {
//商品カテゴリ担当&エリア担当のスタッフがいない可能性がある為
if ($areaStaff[$targetAreaKey]['対応スタッフ']) {
foreach ($areaStaff[$targetAreaKey]['対応スタッフ'] as $targetAreaStaff) {
$key = $targetAreaStaff['id']; //レコードid
$value = $targetAreaStaff['name']; //名前
$areaStaffFromCalender[$targetAreaKey]['対応スタッフ'][$key] = $value;
}
} else {
$areaStaffFromCalender[$targetAreaKey]['対応スタッフ'] = [];
}
};
dump($areaStaffFromCalender);
//デバッグ
$areaStaffFromCalender_txt = print_r($areaStaffFromCalender, true);
log_debug('areaStaffFromCalender:'.$areaStaffFromCalender_txt);
//各日付の予約状況を作成する
//初期化 各日付・時間帯を作成する
$period = $startMonth->copy()->toPeriod($endMonth);
foreach ($period as $day) {
//dump($day);
$day = $day->format('Y-m-d');
$reservationDetail[$day] = [];
foreach ($area as $targetarea) {
$variable = $targetarea['variable']; //anjou
$reservationDetail[$day][$variable]['AM1'] = [];
$reservationDetail[$day][$variable]['AM2'] = [];
$reservationDetail[$day][$variable]['PM1'] = [];
$reservationDetail[$day][$variable]['PM2'] = [];
}
}
//dump($areaStaffFromCalender);
foreach ($reservationDetail as $dayKey => $dayValue) {
foreach ($dayValue as $areaKey => $areaValue) {
// reservationDetailに値を設定
foreach ($normalTimezone as $timeZoneKey) {
$reservationDetail[$dayKey][$areaKey][$timeZoneKey] = $areaStaffFromCalender[$areaKey]['対応スタッフ'];
}
if ($subStaffFlg) {
//dump('エコキュートの場合');
foreach ($ecocuteTimezone as $timeZoneKey) {
$subStaffReservationDetail[$dayKey][$areaKey][$timeZoneKey] = $subStaff[$areaKey]['list'];
}
}
}
}
//デバッグ
$reservationDetail_txt = print_r($reservationDetail, true);
log_debug('削除前reservationDetail:'.$reservationDetail_txt);
//dump('削除前');
//dump($reservationDetail);
//dump($subStaffReservationDetail);
//dump($categoryStaff);
//dump($subStaff);
//予定がある担当スタッフを配列から削除
if ($subStaffFlg) {
$staffFlg = 'main';
}
//dump($categoryStaff);
//予定がある担当スタッフを配列から削除
foreach ($categoryStaff as $staff) {
//dump($staff);
$targetStaffId = $staff['レコードid'];
$targetStaff = $staff['名前']; //削除対象スタッフ
$deleteArea = $staff['担当エリアテーブル']; //削除対象エリア
//dump($staff);
//来月の予定がない場合がある為
if (is_array($staff['予定'])) {
foreach ($staff['予定'] as $schedule) { //スタッフの予定を取得
//dump($schedule);
$deleteTarget = $schedule['スケジュール選択']; //削除する時間帯。AM1、AM1~PM2など
$deleteDayStart = $schedule['作業開始日'];
$deleteDayEnd = $schedule['作業完了日'];
if ($deleteDayStart === $deleteDayEnd) {
log_debug('予定アプリレコード番号' . $schedule['レコード番号'] . ':作業開始日と作業完了日が同じ');
log_info('$reservationDetailから' . $deleteDayStart . '~' . $deleteDayEnd . 'までの' . $targetStaff . 'さんを削除開始。 削除スケジュール:' . $deleteTarget);
$deleteDay = $deleteDayStart;
//作業開始日が先月末の予定もあるため
if (array_key_exists($deleteDay, $reservationDetail)) {
$reservationDetail[$deleteDayStart] = $this->deleteStaffFromScheduleArray($reservationDetail[$deleteDay], $timePeriodDelete, $deleteDay, $targetStaffId, $targetStaff, $deleteArea, $deleteTarget, $staffFlg);
}
} else {
log_debug('予定アプリレコード番号' . $schedule['レコード番号'] . ':作業開始日と作業完了日が違う');
//削除する作業開始日から作業完了日までの日付の範囲を作成する
log_debug('作業開始日' . $deleteDayStart . 'と作業終了日' . $deleteDayEnd . 'をcarbonに変換');
$deleteDayStart = Carbon::parse($deleteDayStart);
$deleteDayEnd = Carbon::parse($deleteDayEnd);
//dump($deleteDayStart);
//dump($deleteDayEnd);
$deleteDayPeriod = $deleteDayStart->copy()->toPeriod($deleteDayEnd);
foreach ($deleteDayPeriod as $deleteDayCarbon) {
$deleteDay = $deleteDayCarbon->toDateString();
//dump($deleteDay);
//作業開始日が先月末の予定もあるため
if (array_key_exists($deleteDay, $reservationDetail)) {
$reservationDetail[$deleteDay] = $this->deleteStaffFromScheduleArray($reservationDetail[$deleteDay], $timePeriodDelete, $deleteDay, $targetStaffId, $targetStaff, $deleteArea, $deleteTarget, $staffFlg);
}
}
}
}
}
}
if ($subStaffFlg) {
//エコキュートの場合
//サブスタッフ
$staffFlg = 'sub';
foreach ($subStaff as $areaKey => $areaValue) {
foreach ($areaValue as $staffKey => $staff) {
if ($staffKey === 'list') { //listキーは見ない
continue;
}
$targetStaffId = $staff['レコードid'];
$targetStaff = $staff['名前']; //削除対象スタッフ
$deleteArea = $staff['担当エリアテーブル']; //削除対象エリア
//来月の予定がない場合がある為
if (is_array($staff['予定'])) {
foreach ($staff['予定'] as $schedule) { //スタッフの予定を取得
//dump($schedule);
$deleteDayStart = $schedule['作業開始日'];
$deleteDayEnd = $schedule['作業完了日'];
if ($deleteDayStart === $deleteDayEnd) {
log_debug('予定アプリレコード番号' . $schedule['レコード番号'] . ':作業開始日と作業完了日が同じ' . $staffFlg);
log_debug('$reservationDetailから' . $deleteDayStart . '~' . $deleteDayEnd . 'までの' . $targetStaff . 'さんを削除開始。 削除スケジュール:' . $deleteTarget);
$deleteDay = $deleteDayStart;
//作業開始日が先月末の予定もあるため
if (array_key_exists($deleteDay, $subStaffReservationDetail)) {
$subStaffReservationDetail[$deleteDayStart] = $this->deleteStaffFromScheduleArray($subStaffReservationDetail[$deleteDay], $timePeriodDelete, $deleteDay, $targetStaffId, $targetStaff, $deleteArea, $deleteTarget, $staffFlg);
}
} else {
log_debug('予定アプリレコード番号' . $schedule['レコード番号'] . ':作業開始日と作業完了日が違う');
//削除する作業開始日から作業完了日までの日付の範囲を作成する
log_debug('作業開始日' . $deleteDayStart . 'と作業終了日' . $deleteDayEnd . 'をcarbonに変換');
$deleteDayStart = Carbon::parse($deleteDayStart);
$deleteDayEnd = Carbon::parse($deleteDayEnd);
//dump($deleteDayStart);
//dump($deleteDayEnd);
$deleteDayPeriod = $deleteDayStart->copy()->toPeriod($deleteDayEnd);
foreach ($deleteDayPeriod as $deleteDayCarbon) {
$deleteDay = $deleteDayCarbon->toDateString();
//dump($deleteDay);
//作業開始日が先月末の予定もあるため
if (array_key_exists($deleteDay, $subStaffReservationDetail)) {
log_debug('サブ担当者削除開始日と終了日が違う');
log_debug($deleteDayStart);
log_debug($targetStaff);
$subStaffReservationDetail[$deleteDay] = $this->deleteStaffFromScheduleArray($subStaffReservationDetail[$deleteDay], $timePeriodDelete, $deleteDay, $targetStaffId, $targetStaff, $deleteArea, $deleteTarget, $staffFlg);
}
}
}
}
}
}
}
}
//デバッグ
$reservationDetail_txt = print_r($reservationDetail, true);
log_debug('削除後reservationDetail:'.$reservationDetail_txt);
//dump('削除後');
//dump($reservationDetail);
//dump($subStaffReservationDetail);
//debug 問題なければ消す
dump($categoryName . 'に対応しているスタッフは(作業レベル');
dump($categoryStaff);
dump('エリアごとのスタッフ');
dump($areaStaff);
if ($subStaff) {
dump('エコキュートの場合');
dump($subStaff);
}
//debug
//問題なければ消す
//debug
log_debug('makereservationDetail end');
}
/**
*kintone 予約アプリの情報を返す
*担当スタッフの空き状況を確認する為
*/
public function getScheduleRecord($staffCode, $startMonthString, $endMonthString)
{
log_debug('getScheduleRecord start');
log_info($staffCode . 'の' . $startMonthString . 'から' . $endMonthString . 'までの予定をkintoneから取得する');
$staff_record = '予定アプリにデータなし';
//レコード取得
$result = array(); // 戻り値格納変数
// 抽出条件。カテゴリー & レコード番号で抽出
$query = '(内容 not in ("削除") and 非表示チェック not in ("非表示") and 対応スタッフ in (' . '"' . $staffCode . '")' . ' and (作業開始日時 >= "' . $startMonthString . '" and 作業開始日時 <= ' . '"' . $endMonthString . '" )) or (内容 not in ("削除") and 非表示チェック not in ("非表示") and 対応スタッフ in (' . '"' . $staffCode . '")' . 'and (作業完了日時 >= "' . $startMonthString . '" and 作業完了日時 <= ' . '"' . $endMonthString . '" ))';
//dump($staffCode);
//dump($query);
// クエリ以外を指定
$non_query = "order by 作業開始日時 asc";
// 取得するフィールドコードを指定。nullは全フィールドコード。
$fields = array('fields' => array('レコード番号', '対応スタッフ', '作業開始日時', '作業完了日時', 'スケジュール選択', '内容'));
//$fields = null;
$kntn = new KntnSchedule();
// $count > 0 の間、ループ。クエリー対象の全レコードのECコード取得
while (($count = $kntn->getRecords($result, $fields, $query, $non_query)) > 0) {
// 1000件単位で読み出し。各処理は、以下のようにレコード単位で取り出して処理したり、色々。
$staff_record = [];
foreach ($result['records'] as $record) {
$startOfWork = Carbon::parse($record['作業開始日時']['value'])->setTimezone('Asia/Tokyo');
$endOfWork = Carbon::parse($record['作業完了日時']['value'])->setTimezone('Asia/Tokyo');
$data = array(
'レコード番号' => $record['レコード番号']['value'],
'対応スタッフ' => $record['対応スタッフ']['value'],
'作業開始日時' => $startOfWork->format('Y-m-d H:i:s'),
'作業完了日時' => $endOfWork->format('Y-m-d H:i:s'),
'作業開始日' => $startOfWork->format('Y-m-d'),
'作業完了日' => $endOfWork->format('Y-m-d'),
'スケジュール選択' => $record['スケジュール選択']['value']
);
$staff_record[] = $data;
}
}
//dump($staff_record);
if (!$kntn->getSuccessFlg()) {
// 失敗
// エラーログ出力
dump('kntn error');
log_error('kntn getCalendarRecord fail');
log_error('kntn result' . print_r($result, true));
return false;
}
log_debug('getScheduleRecord end');
//dump($staff_record);
return $staff_record;
}
//各地域の対応スタッフ名を返す
public function getAreaStaffRecord($CategoryStaff, $area): array
{
log_debug('getAreaStaffRecord start');
$staff = '';
$areaData = [];
//dump($area);
foreach ($area as $targetArea) {
$areaName = $targetArea['name'];
$variable = $targetArea['variable'];
$areaData[$variable] = [];
$areaCharge = [];
foreach ($CategoryStaff as $staff) {
//dump($staff);
if (in_array($areaName, $staff['担当エリアテーブル'], true)) {
$staffCode = $staff['ユーザー選択'][0]['code'];
$staffData = array('id' => $staff['レコードid'], 'name' => $staff['名前'], 'ユーザー選択コード' => $staffCode);
$areaCharge[] = $staffData;
}
}
$areaData[$variable] = array('variable' => $variable, '対応エリア' => $areaName, '対応スタッフ' => $areaCharge);
}
//log_debug(print_r($areaData, true));
log_debug('getAreaStaffRecord end');
return $areaData;
}
/**
*kintone スタッフアプリの情報を返す
*担当エリア、設置出来る商品を取得するため
*/
public function getStaffRecord($targetName, $subStaffFlg)
{
log_debug('getStaffRecord start:');
log_info($targetName . '対応のスタッフをkintoneから検索');
//レコード取得
$staffRecord = [];
$data = [];
$result = []; // 戻り値格納変数
//エリアに応じた変数を検索出来る配列を作成
//$getAreaForCalendarService = new getAreaForCalendarService(); //各エリアの変数が格納されたクラス
//$getAreaForCalendarService = $getAreaForCalendarService->getArea();
$getAreaForCalendarService = $this->getAreaForCalendarService->getArea();
$searchAreaVariables = [];
foreach ($getAreaForCalendarService as $variable) {
$key = $variable['name'];
$value = $variable['variable'];
$searchAreaVariables[$key] = $value;
}
dump($searchAreaVariables);
$query = '中分類 in ("' . $targetName . '")';
//エコキュートの場合はサブ担当者も決めないといけないため条件を変える
if ($subStaffFlg) {
//dump('サブ担当者を検索する');
$query = '担当エリア in ("' . $targetName . '")';
}
$non_query = "order by レコード番号 desc";
// 取得するフィールドコードを指定。nullは全フィールドコード。
$fields = array('fields' => array('$id', '名前', 'ユーザー選択', 'スキル入力テーブル', '担当エリアテーブル'));
$kntn = new KntnStaff();
// $count > 0 の間、ループ。クエリー対象の全レコードのECコード取得
while (($count = $kntn->getRecords($result, $fields, $query, $non_query)) > 0) {
//dump($result['records']);
// 1000件単位で読み出し。各処理は、以下のようにレコード単位で取り出して処理したり、色々。
foreach ($result['records'] as $record) {
//テーブルフィールド用
$table = [];
$area = [];
$skill = [];
$user = [];
foreach ($record['ユーザー選択']['value'] as $table) {
$tabledata = array('code' => $table['code'], 'name' => $table['name']);
$user[] = $tabledata;
}
foreach ($record['スキル入力テーブル']['value'] as $table) {
$skill[] = $table['value']['中分類']['value'];
}
foreach ($record['担当エリアテーブル']['value'] as $table) {
$value = $table['value']['担当エリア']['value'];
//kintoneスタッフアプリで対応エリア外の地域を設定する可能性がある為、設定した場合はスルーする
if (array_key_exists($value, $searchAreaVariables)) {
$key = $searchAreaVariables[$value]; //該当エリアの変数をキーにする。安城市の場合はanjouをキーにする
} else {
log_info($record['名前']['value'] . 'さんはスタッフアプリの担当エリアテーブルにECCUBEエリア外のエリア[' . $value . ']を設定しております。');
}
$area[$key] = $value;
}
$data = array(
'レコードid' => $record['$id']['value'],
'名前' => $record['名前']['value'],
'ユーザー選択' => $user,
'スキル入力テーブル' => $skill,
'担当エリアテーブル' => $area
);
$staffRecord[] = $data;
//dump($staffRecord);
}
}
if (!$kntn->getSuccessFlg()) {
// 失敗
// エラーログ出力
dump('kntn error');
log_error('kntn getCalendarRecord fail');
log_error('kntn result' . print_r($result, true));
//LogOut::error(basename(__FILE__), __LINE__, "kntn getCalendarRecord", 'fail', dirname(__FILE__));
//LogOut::error(basename(__FILE__), __LINE__, "kntn result", print_r($result, true), dirname(__FILE__));
return false;
}
log_debug('getStaffRecord end');
return $staffRecord;
}
//商品カテゴリ対応スタッフの配列に予定アプリのスケジュールを追加して返す
public function getStaffScheduleRecord($targetName, $startMonthString, $endMonthString, $subStaffFlg = false, &$createdStaff = null): array
{
log_debug('getStaffScheduleRecord start');
$CategoryScheduleStaff = [];
$CategoryStaff = $this->getStaffRecord($targetName, $subStaffFlg);
dump($CategoryStaff);
if ($subStaffFlg === false) {
log_debug('通常スタッフ');
foreach ($CategoryStaff as $staff) {
$staffCode = $staff['ユーザー選択'][0]['code'];
$scheduleData = $this->getScheduleRecord($staffCode, $startMonthString, $endMonthString);
$staff['予定'] = $scheduleData;
$CategoryScheduleStaff[] = $staff;
}
} else {
log_debug('サブスタッフ');
$CategoryScheduleStaff['list'] = [];
//スタッフのレコードが既に存在する場合は使い回す
foreach ($CategoryStaff as $staff) {
//dump($staff);
$staffCode = $staff['ユーザー選択'][0]['code'];
$recordId = $staff['レコードid'];
if (array_key_exists($staffCode, $createdStaff)) {
//dump('$createdStaffに' . $staffCode . 'あり');
$staff['予定'] = $createdStaff[$staffCode]['予定'];
} else {
log_debug('$createdStaffに' . $staffCode . 'なし');
$scheduleData = $this->getScheduleRecord($staffCode, $startMonthString, $endMonthString);
$staff['予定'] = $scheduleData;
$createdStaff[$staffCode] = $staff;
}
$CategoryScheduleStaff[] = $staff;
$CategoryScheduleStaff['list'][$recordId] = $staff['名前'];
}
}
//dump($CategoryScheduleStaff);
log_debug('getStaffScheduleRecord end');
return $CategoryScheduleStaff;
}
/**
* カレンダー生成用の配列からスタッフを削除する
*
* @param string $deleteDay 削除日
* @param array $reservationDetailDeleteDay カレンダー生成用の各スタッフの予定が格納された配列(削除日のみ)。
* @param string $targetStaff 削除対象のスタッフ
* @param string $deleteTarget 削除対象の時間帯(AM1など)
* @param array $deleteArea スタッフの対応エリア(削除するエリア)
*/
//public function deleteStaffFromScheduleArray($reservationDetail, $targetStaffId, $targetStaff, $deleteArea, $deleteDayStart, $deleteDayEnd, $deleteTarget): array
public function deleteStaffFromScheduleArray($reservationDetailDeleteDay, $timePeriodDelete, $deleteDay, $targetStaffId, $targetStaff, $deleteArea, $deleteTarget, $staffFlg): array
{
log_debug('deleteStaffFromScheduleArray start');
switch ($staffFlg) {
case 'main':
log_debug('エコキュートメインスタッフなのでAM1〜PM2まで削除');
$deleteTarget = $timePeriodDelete['終日'];
break;
case 'sub':
log_debug('エコキュートサブスタッフなのでAM1〜AM2まで削除');
$deleteTarget = $timePeriodDelete['AM'];
break;
default:
log_debug('エコキュート以外のスタッフなので通常通り削除');
$deleteTarget = $timePeriodDelete[$deleteTarget];
}
log_debug($targetStaff . 'さんの対応エリア' . print_r($deleteArea, true));
log_debug($targetStaff . 'さんの削除スケジュール' . print_r($deleteTarget, true));
//dump('削除前のカレンダー(' . $deleteDay . ')' . print_r($reservationDetailDeleteDay, true));
//スタッフの対応エリアのスケジュール(AM1など)を削除
foreach ($deleteArea as $targetAreaKey => $targetArea) {
foreach ($deleteTarget as $deleteTimeKey => $deleteTime) {
log_debug($deleteDay . ':' . $targetArea . 'の' . $targetStaff . 'さんを削除。' . $deleteTime . 'の' . '対象配列キー(スタッフアプリレコードid):' . $targetStaffId);
if (in_array($targetStaff, $reservationDetailDeleteDay[$targetAreaKey][$deleteTime], true)) {
unset($reservationDetailDeleteDay[$targetAreaKey][$deleteTime][$targetStaffId]);
} else {
log_info('削除出来ませんでした。' . $targetStaff . 'さんが存在しません(予定アプリで別レコードで同じ日付・時間帯を選択した場合も表示される)');
}
}
}
log_debug('deleteStaffFromScheduleArray end');
return $reservationDetailDeleteDay;
}
/**
* 各時間帯のスタッフの空き状況数を計算・表示する
*
* @param string $availabilityDisplay 空き状況(カレンダーディスプレイ用)
* @param int $availabilityCount AMかPMのスタッフ数
* @param array $schedule1 時間帯のスタッフ数、AM1/PM1用
* @param array $schedule2 時間帯のスタッフ数、AM2/PM2用
* @param string $reservable カレンダーディスプレイ用 予約可能
* @param string $reservationNot カレンダーディスプレイ用 予約不可
* @param string $few カレンダーディスプレイ用 残りわずか
*/
public function
calculateAvailability(&$availabilityDisplay, &$availabilityCount, $schedule1, $schedule2, $reservable, $reservationNot, $few)
{
log_debug('calculateAvailability start');
//dump($schedule1);
//dump($schedule2);
$availabilityCount = count($schedule1) + count($schedule2);
$availabilityCount = intval($availabilityCount);
if ($availabilityCount >= 4) {
$availabilityDisplay = $reservable;
} elseif ($availabilityCount <= 3 && $availabilityCount >= 1) {
$availabilityDisplay = $few;
} elseif ($availabilityCount <= 0) {
$availabilityDisplay = $reservationNot;
}
log_debug('calculateAvailability end');
}
/**
* ECCUBEカレンダーの営業日の予約不可能日を設定する
*
* @param Carbon $few ターゲット日
* @var array $japanHoliday date型のGoogleカレンダ-の祝日
* @param array $targetMonthCalendar 対象月のカレンダー
* @param array $reservationDetail 各日付のAM1~PM2のまでの対応スタッフ詳細。$targetMonthCalendar生成時に使用
* @param array $subStaffReservationDetail エコキュートの場合、各日付のAM1~PM2のまでのサブスタッフ詳細。$targetMonthCalendar生成時に使用
* @var array $areaStaffFromCalender 各エリアの担当スタッフ
* @var date $targetYmdDateTime カレンダーの対象日
* @var string $availabilityCount 各時間帯の合計スタッフ数(AMの場合はAM1とAM2の合計)
*
* @var string $searchDay 検索対象の日付。$reservationDetailの検索に使用。
*/
public function
setReservationDay($targetMonthCalendar, $reservationDetail, $subStaffReservationDetail, Carbon $targetDate, $area, $category, $reservable, $reservationNot, $few, $subStaffFlg): array
{
log_debug('setReservationDay start');
//dump($reservationDetail);
//dump($subStaffReservationDetail);
//初期化 start
$targetYearString = (string) $targetDate->copy()->year; //reservationDetailから予約日を検索するため
$targetMonthString = $targetDate->copy()->format('m'); //reservationDetailから予約日を検索するため
$availabilityDisplay = '';
$availabilityCount = '';
if ($subStaffFlg) {
//エコキュートの場合
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
continue;
}
$searchDay = $targetYearString . '-' . $targetMonthString . '-' . sprintf('%02d', $targetMonthCalendar[$i]['day']);
foreach ($reservationDetail[$searchDay] as $areaKey => $areaValue) {
//空き状況の計算と表示
//AM
$schedule2 = []; //予定がある対象日は時間帯関わらず削除されている為、AM2は計算しなくて良い
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM1'] = $schedule1 = $reservationDetail[$searchDay][$areaKey]['AM1'];
$this->calculateAvailability($availabilityDisplay, $availabilityCount, $schedule1, $schedule2, $reservable, $reservationNot, $few);
$mainStaffCount = $availabilityCount;
$mainStaffDispllay = $availabilityDisplay;
if ($mainStaffCount === 1) {
//dump('エコキュートのメインスタッフ数が残り1の場合');
//残り1名のメインスタッフはサブスタッフにならない為、削除
$delete_key = array_key_first($reservationDetail[$searchDay][$areaKey]['AM1']);
unset($subStaffReservationDetail[$searchDay][$areaKey]['AM1'][$delete_key]);
//dump($subStaffReservationDetail[$searchDay][$areaKey]['AM1']);
}
//サブスタッフ
//AM1、AM2のいずれかに予定がある対象日は削除されているため、AM2は計算しなくて良い
$targetMonthCalendar[$i]['reservation'][$areaKey]['subStaff']['AM1'] = $schedule1 = $subStaffReservationDetail[$searchDay][$areaKey]['AM1'];
$this->calculateAvailability($availabilityDisplay, $availabilityCount, $schedule1, $schedule2, $reservable, $reservationNot, $few);
//メインスタッフとサブスタッフの人数を比較して、少ない方を表示する.
if ($mainStaffCount <= $availabilityCount) {
$targetMonthCalendar[$i]['reservation'][$areaKey]['AMCount'] = $mainStaffCount;
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM'] = $mainStaffDispllay;
} else {
$targetMonthCalendar[$i]['reservation'][$areaKey]['AMCount'] = $availabilityCount;
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM'] = $availabilityDisplay;
}
//PM エコキュートの場合は強制的に予約不可にする
$targetMonthCalendar[$i]['reservation'][$areaKey]['PM'] = $reservationNot;
}
}
} else {
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
continue;
}
$searchDay = $targetYearString . '-' . $targetMonthString . '-' . sprintf('%02d', $targetMonthCalendar[$i]['day']);
//dump($reservationDetail[$searchDay]);
foreach ($reservationDetail[$searchDay] as $areaKey => $areaValue) {
//空き状況の計算と表示
//AM
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM1'] = $schedule1 = $reservationDetail[$searchDay][$areaKey]['AM1'];
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM2'] = $schedule2 = $reservationDetail[$searchDay][$areaKey]['AM2'];
$this->calculateAvailability($availabilityDisplay, $availabilityCount, $schedule1, $schedule2, $reservable, $reservationNot, $few);
$targetMonthCalendar[$i]['reservation'][$areaKey]['AMCount'] = $availabilityCount;
$targetMonthCalendar[$i]['reservation'][$areaKey]['AM'] = $availabilityDisplay;
//PM
$targetMonthCalendar[$i]['reservation'][$areaKey]['PM1'] = $schedule1 = $reservationDetail[$searchDay][$areaKey]['PM1'];
$targetMonthCalendar[$i]['reservation'][$areaKey]['PM2'] = $schedule2 = $reservationDetail[$searchDay][$areaKey]['PM2'];
$this->calculateAvailability($availabilityDisplay, $availabilityCount, $schedule1, $schedule2, $reservable, $reservationNot, $few);
$targetMonthCalendar[$i]['reservation'][$areaKey]['PMCount'] = $availabilityCount;
$targetMonthCalendar[$i]['reservation'][$areaKey]['PM'] = $availabilityDisplay;
}
}
}
log_debug('setReservationDay end');
return $targetMonthCalendar;
}
/**
* ECCUBEカレンダーの定休日と祝日を予約不可にする
*
* @param Carbon $few ターゲット日
* @param array $japanHoliday date型のGoogleカレンダ-の祝日
* @param array $targetMonthCalendar 対象月のカレンダー
*/
public function
setReservationHoliDay($targetMonthCalendar, $holidayListOfTwoMonths, $holiday, Carbon $targetDate, $area, $reservationNot): array
{
log_debug('setReservationHoliDay start');
//ECCUBEカレンダーがDATE型の為、型変換を行う
$japanHoliday = array();
foreach ($holiday as $day) {
$japanHoliday[] = Carbon::parse($day)->toDateTime()->setTime(0, 0, 0);
}
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
$targetMonthCalendar[$i]['holiday'] = false;
$targetMonthCalendar[$i]['today'] = false;
continue;
}
$targetYmdDateTime = new \DateTime($targetDate->copy()->format('Y-n') . '-' . $targetMonthCalendar[$i]['day']); //対象日
//dump($targetYmdDateTime);
// カレンダーの日付が定休日リストに存在するかを確認
$result = array_search($targetYmdDateTime, $holidayListOfTwoMonths);
//dump($holidayListOfTwoMonths);
// 定休日フラグを設定
if ($result !== false) {
$targetMonthCalendar[$i]['holiday'] = true;
//定休日は予約不可
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
} else {
$targetMonthCalendar[$i]['holiday'] = false;
}
// 今日フラグを設定
if ($targetYmdDateTime == new \DateTime($targetDate->copy()->format('Y-n-j'))) {
$targetMonthCalendar[$i]['today'] = true;
} else {
$targetMonthCalendar[$i]['today'] = false;
}
//対象日が日曜日なら予約不可
if ($targetMonthCalendar[$i]['dayOfWeek'] === 'Sun') {
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
}
//対象日が祝日なら予約不可
//dump($targetYmdDateTime);
//dump($japanHoliday);
$japanHolidayjudgement = array_search($targetYmdDateTime, $japanHoliday);
if ($japanHolidayjudgement !== false) {
$targetMonthCalendar[$i]['holiday'] = true;
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
}
}
log_debug('setReservationHoliDay end');
//dump($targetMonthCalendar);
return $targetMonthCalendar;
}
/**
* ECCUBEカレンダーの月初から本日までを予約不可にする
* 在庫がある商品は本日から予約可能にする。
* 在庫がない商品は本日から4日までを予約不可にする。
* 在庫がない場合は在庫の取り寄せ状況を考慮して祝日がある場合は予約不可日数を増やす
* 在庫あり・なしは$bakusokuflgで判断する。
*
* @param array $targetMonthCalendar 対象月のカレンダー
* @param string $bakusokuflg 在庫がある場合はtrue、ない場合はfalse
* @param Carbon $targetDate 本日の日付と時刻
* @param string $targetDateCopy 本日。比較対象のため0時にセットする
* @param string $noReservationDayStart 予約不可日開始日(月初)
* @param string $noReservationDayEnd 予約不可日終了日、爆速商品で値が変わる為、初期値は前日
* @param array $japanHoliday 祝日と定休日をまとめた配列。本日〜4日以内に祝日があるか判断する為
* @param Carbon $amTenFlg 本日のAM10時。現在時刻が10時か比較する為
* @param string $today 本日。現在時刻が10時か比較する為
* @param Carbon $noReservationDayEnd 爆速商品以外の場合に不可にする日付の最終日、来月用に仕様する。
*/
public function
setNotReservationToday(&$targetMonthCalendar, $bakusokuflg, $area, $holidayListOfTwoMonths, $holiday, Carbon $targetDate, $reservationNot, &$notReservationDay, &$noReservationDayEnd)
{
log_debug("setNotReservationToday start");
//dump($targetDate);
$targetDateCopy = $targetDate->copy()->startOfDay(); //本日。比較対象のため0時にセットする
$noReservationDayStart = $targetDateCopy->copy()->startOfMonth(); //予約不可日開始日(月初)
$noReservationDayEnd = $targetDateCopy->copy()->subDay(); //予約不可日終了日、爆速商品で値が変わる為、初期値は前日
$today = $targetDate->format("Y-m-d"); //本日。比較対象のため0時にセットする
$amTenFlg = $targetDate->copy()->hour(10); // 10時のCarbonオブジェクトを作成
//dump($noReservationDayStart);
//dump($noReservationDayEnd);
//dump($holidayListOfTwoMonths);
//dump($holiday);
//ECCUBEカレンダーがDATE型の為、祝日は型変換を行う
$japanHoliday = array();
foreach ($holiday as $day) {
$japanHoliday[] = Carbon::parse($day)->toDateTime()->setTime(0, 0, 0);
}
//dump($japanHoliday);
//判定の為、定休日と祝日をまとめる
$japanHoliday = array_merge($japanHoliday, $holidayListOfTwoMonths);
//爆速商品(在庫ありかなしか)に合わせて予約不可日を設定する為
//dump($bakusokuflg);
if ($bakusokuflg === true) {
log_info('爆速商品ではない');
$addDaysCounter = 0; //予約可能日を当日+平日4日分の日にちにするため
while ($addDaysCounter < 4) {
dump($addDaysCounter);
$noReservationDayEnd->addDays(1);
$dateJudge = $noReservationDayEnd->toDate(); //祝日判定用
//dump($noReservationDayEnd);
//dump($dateJudge);
//dump($japanHoliday);
//土日の場合
if ($noReservationDayEnd->dayOfWeek === Carbon::SATURDAY || $noReservationDayEnd->dayOfWeek === Carbon::SUNDAY) {
log_debug($noReservationDayEnd . 'は土日なのでカウントしない');
}
//祝日、定休日の場合、指定日が土日で祝日の場合はカウントしない
elseif (array_search($dateJudge, $japanHoliday) !== false) {
log_debug($noReservationDayEnd . 'は祝日,定休日なのでカウントしない');
} else {
log_debug($noReservationDayEnd . 'は平日なのでカウントする');
$addDaysCounter++;
}
}
} elseif ($bakusokuflg === false) {
log_info('爆速商品');
} else {
$errormsg = __LINE__ . ':爆速商品の判断が出来ません';
log_error($errormsg);
$this->sendErrorNotifi->errorNotifi($errormsg);
}
$dayEnd = $noReservationDayEnd->copy()->addDays()->toDateString();
//予約不可日を作成する
$period = CarbonPeriod::create($noReservationDayStart, $noReservationDayEnd);
log_notice($noReservationDayStart->toString() . 'から' . $noReservationDayEnd->toString() . 'までは予約不可にする');
foreach ($period as $periodDate) {
$notReservationDay[] = $periodDate->toDate();
}
dump($noReservationDayEnd);
//カレンダー作成
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
$targetMonthCalendar[$i]['holiday'] = false;
$targetMonthCalendar[$i]['today'] = false;
continue;
}
$targetYmdDateTime = new \DateTime($targetDate->copy()->format('Y-n') . '-' . $targetMonthCalendar[$i]['day']); //対象日
//dump($targetYmdDateTime);
// カレンダーの日付がお休みか確認
$result = array_search($targetYmdDateTime, $notReservationDay);
//dump($targetMonthCalendar[$i]);
if ($result !== false) {
//予約不可設定
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
}
//現在時刻が10時前後で本日の予約状況を変える為
$targetYmdDateTime = $targetYmdDateTime->format("Y-m-d"); //比較のため
if ($targetYmdDateTime === $today) {
//dump('本日判断');
if ($targetDate->lessThan($amTenFlg)) {
//dump("AM10時前");
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
}
} else {
log_debug("AM10時以降");
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
}
}
//4日目以降の処理はしなくて良いため
if ($targetMonthCalendar[$i]['yearMonthDay'] === $dayEnd) {
log_debug("setNotReservationToday end");
return;
}
}
log_debug("setNotReservationToday end");
return;
}
/**
* 来月用ECCUBEカレンダーの月初から予約不可日までを予約不可にする
*
* @param array $targetMonthCalendar 来月のカレンダー
* @param Carbon $targetDate 本日の日付と時刻
* @param array $notReservationDay 予約不可日
*/
public function
setNotReservationNextCalendar($targetMonthCalendar, $area, Carbon $targetDate, $reservationNot, $notReservationDay, $noReservationDayEnd)
{
log_debug("setNotReservationNextCalendar start");
//$targetDate = $targetDate->copy()->addMonth();
$targetDate = $targetDate->copy()->startOfMonth()->addMonth(); //うるう年回避のため、月初にしてから1月加算する
$lastKey = array_key_last($notReservationDay);
$dayEnd = $notReservationDay[$lastKey];
$noReservationDayStart = $targetDate->copy()->startOfMonth(); //予約不可日開始日(月初)
//予約不可日を作成する
$period = CarbonPeriod::create($noReservationDayStart, $noReservationDayEnd);
log_notice($noReservationDayStart->toString() . 'から' . $noReservationDayEnd->toString() . 'までは予約不可にする');
foreach ($period as $periodDate) {
$notReservationDay[] = $periodDate->toDate();
}
//カレンダー作成
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
$targetMonthCalendar[$i]['holiday'] = false;
$targetMonthCalendar[$i]['today'] = false;
continue;
}
$targetYmdDateTime = new \DateTime($targetDate->copy()->format('Y-n') . '-' . $targetMonthCalendar[$i]['day']); //対象日
// カレンダーの日付がお休みか確認
dump($targetYmdDateTime);
$result = array_search($targetYmdDateTime, $notReservationDay);
//dump($targetMonthCalendar[$i]);
if ($result !== false) {
//予約不可設定
foreach ($area as $targetarea) {
$variable = $targetarea['variable'];
$targetMonthCalendar[$i]['reservation'][$variable]['AM'] = $reservationNot;
$targetMonthCalendar[$i]['reservation'][$variable]['PM'] = $reservationNot;
}
}
//4日目以降の処理はしなくて良いため
if ($targetMonthCalendar[$i]['yearMonthDay'] === $dayEnd) {
log_debug("setNotReservationToday end");
return $targetMonthCalendar;
}
}
log_debug("setNotReservationNextCalendar end");
return $targetMonthCalendar;
}
}