v1.3.14
- [INSTALL WAIT LIST] Wait List 작업중인 날짜/드라이버 유지. 전체 선택 체크박스 추가. - [INSTALL] Install 작업 완료 후 Request note를 Customer note 에 추가. - [IMAGE] multi images 업로드 할 때, 파일명 순 보장. - [CUSTOMER] Contract Date, Inactive Date 표시.
This commit is contained in:
parent
2c7c8565e2
commit
daa4093a33
|
|
@ -1413,7 +1413,10 @@ trait InstallAPI {
|
||||||
// 2) 상태 업데이트
|
// 2) 상태 업데이트
|
||||||
$this->updateDailyInstallStatus($di_uid, $newStatus, $install_note, $oil_qty, $sludge);
|
$this->updateDailyInstallStatus($di_uid, $newStatus, $install_note, $oil_qty, $sludge);
|
||||||
|
|
||||||
// 2-1) additional note 저장
|
// 2-1) request note 저장 (di_request_note → tbl_note) : additional 보다 먼저
|
||||||
|
$this->upsertRequestNote($di);
|
||||||
|
|
||||||
|
// 2-2) additional note 저장
|
||||||
$this->upsertAdditionalNote($di, $additional_note);
|
$this->upsertAdditionalNote($di, $additional_note);
|
||||||
|
|
||||||
// 3) 컨테이너 반영
|
// 3) 컨테이너 반영
|
||||||
|
|
@ -1484,6 +1487,142 @@ trait InstallAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* di_request_note 를 tbl_note 에 upsert
|
||||||
|
*
|
||||||
|
* waitlist 에서 넘어온 데이터이고 request 시점에 남긴 노트라
|
||||||
|
* di_wait_uid 와 더 강하게 결합. n_dailyuid 를 'w_{di_wait_uid}' 로 저장.
|
||||||
|
* 예: di_wait_uid = 55 이면 n_dailyuid = 'w_55'
|
||||||
|
*
|
||||||
|
* 본문 뒤에 iw_request_at / iw_request_by 를 덧붙인다.
|
||||||
|
* iw_request_by 가 'Customer' 면 'Customer', 아니면 tbl_driver.dr_initial.
|
||||||
|
*/
|
||||||
|
private function upsertRequestNote(array $di): void
|
||||||
|
{
|
||||||
|
$connect = $GLOBALS['conn'];
|
||||||
|
|
||||||
|
$di_wait_uid = intval($di['di_wait_uid'] ?? 0);
|
||||||
|
if ($di_wait_uid <= 0) {
|
||||||
|
return; // waitlist 에서 온 게 아니면 스킵
|
||||||
|
}
|
||||||
|
|
||||||
|
// request 전용 note key (di_wait_uid 기준)
|
||||||
|
$noteDailyUid = 'w_' . $di_wait_uid;
|
||||||
|
$n_dailyuid = mysqli_real_escape_string($connect, $noteDailyUid);
|
||||||
|
|
||||||
|
$noteText = trim($di['di_request_note'] ?? '');
|
||||||
|
|
||||||
|
// 노트 없으면 기존 note 삭제 후 종료
|
||||||
|
if (strlen($noteText) <= 1) {
|
||||||
|
mysqli_query($connect, "
|
||||||
|
DELETE FROM tbl_note
|
||||||
|
WHERE n_dailyuid = '{$n_dailyuid}'
|
||||||
|
");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitlist 에서 request 정보 조회 (request_by → Customer or driver initial)
|
||||||
|
$qrWait = mysqli_query($connect, "
|
||||||
|
SELECT
|
||||||
|
iw.iw_request_at,
|
||||||
|
CASE
|
||||||
|
WHEN iw.iw_request_by = 'Customer' THEN 'Customer'
|
||||||
|
ELSE IFNULL(dr.dr_initial, '')
|
||||||
|
END AS request_by_name
|
||||||
|
FROM tbl_install_waitlist iw
|
||||||
|
LEFT JOIN tbl_driver dr
|
||||||
|
ON iw.iw_request_by = dr.dr_uid
|
||||||
|
WHERE iw.iw_uid = '{$di_wait_uid}'
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
|
$requestBy = '';
|
||||||
|
$requestAt = '';
|
||||||
|
if ($qrWait && ($w = mysqli_fetch_assoc($qrWait))) {
|
||||||
|
$requestBy = trim($w['request_by_name'] ?? '');
|
||||||
|
$requestAt = trim($w['iw_request_at'] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 본문 뒤에 request 정보 덧붙이기
|
||||||
|
$suffixParts = [];
|
||||||
|
if ($requestBy !== '') $suffixParts[] = $requestBy;
|
||||||
|
if ($requestAt !== '') $suffixParts[] = date('Y-m-d', strtotime($requestAt));
|
||||||
|
|
||||||
|
$finalNote = $noteText;
|
||||||
|
if (count($suffixParts)) {
|
||||||
|
$finalNote .= " (Install requested by " . implode(' at ', $suffixParts) . ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
$customeruid = mysqli_real_escape_string($connect, $di['di_customer_uid'] ?? '');
|
||||||
|
$memberuid = mysqli_real_escape_string($connect, $_SESSION['ss_UID'] ?? '');
|
||||||
|
$noteEsc = mysqli_real_escape_string($connect, $finalNote);
|
||||||
|
$now14 = date('YmdHis');
|
||||||
|
$level = intval($_SESSION['ss_LEVEL'] ?? 9);
|
||||||
|
|
||||||
|
// 기존 note 존재 여부 확인
|
||||||
|
$qr = mysqli_query($connect, "
|
||||||
|
SELECT n_uid
|
||||||
|
FROM tbl_note
|
||||||
|
WHERE n_dailyuid = '{$n_dailyuid}'
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
|
if (!$qr) {
|
||||||
|
throw new Exception('request note select failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing = mysqli_fetch_assoc($qr);
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
// UPDATE
|
||||||
|
$ok = mysqli_query($connect, "
|
||||||
|
UPDATE tbl_note
|
||||||
|
SET
|
||||||
|
n_memberuid = '{$memberuid}',
|
||||||
|
n_customeruid = '{$customeruid}',
|
||||||
|
n_type = 'D',
|
||||||
|
n_level = {$level},
|
||||||
|
n_view = 1,
|
||||||
|
n_note = '{$noteEsc}',
|
||||||
|
n_createddate = '{$now14}'
|
||||||
|
WHERE n_dailyuid = '{$n_dailyuid}'
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
|
if (!$ok) {
|
||||||
|
throw new Exception('request note update failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// INSERT
|
||||||
|
$ok = mysqli_query($connect, "
|
||||||
|
INSERT INTO tbl_note (
|
||||||
|
n_memberuid,
|
||||||
|
n_customeruid,
|
||||||
|
n_dailyuid,
|
||||||
|
n_type,
|
||||||
|
n_level,
|
||||||
|
n_view,
|
||||||
|
n_note,
|
||||||
|
n_createddate
|
||||||
|
) VALUES (
|
||||||
|
'{$memberuid}',
|
||||||
|
'{$customeruid}',
|
||||||
|
'{$n_dailyuid}',
|
||||||
|
'D',
|
||||||
|
{$level},
|
||||||
|
1,
|
||||||
|
'{$noteEsc}',
|
||||||
|
'{$now14}'
|
||||||
|
)
|
||||||
|
");
|
||||||
|
|
||||||
|
if (!$ok) {
|
||||||
|
throw new Exception('request note insert failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* install 추가 메모를 tbl_note에 upsert
|
* install 추가 메모를 tbl_note에 upsert
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1292,6 +1292,11 @@ $(document).ready(function()
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
padding:-1em;
|
padding:-1em;
|
||||||
}
|
}
|
||||||
|
.cm-opt:hover:not(.active):not(:disabled){
|
||||||
|
color: #6c757d;
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: #6c757d;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,9 @@ foreach ($rows as $list) {
|
||||||
$c_statusSTR = $arrStatus[$c_status];
|
$c_statusSTR = $arrStatus[$c_status];
|
||||||
$c_istopSTR = ($c_is_top === 'A') ? 'A Rank' : (($c_is_top === 'G') ? 'Ghost' : '');
|
$c_istopSTR = ($c_is_top === 'A') ? 'A Rank' : (($c_is_top === 'G') ? 'Ghost' : '');
|
||||||
|
|
||||||
|
$c_contractdateSTR = substr ($c_contractdate, 0, 4)."-".substr ($c_contractdate, 4, 2)."-".substr ($c_contractdate, 6, 2);
|
||||||
|
$c_inactivedateSTR = !empty($c_inactivedate) ? substr($c_inactivedate, 0, 4).'-'.substr($c_inactivedate, 4, 2).'-'.substr($c_inactivedate, 6, 2) : '';
|
||||||
|
|
||||||
$todayQty = number_format(round(floatval($c_fullquantity - $c_fullquantitydaily)));
|
$todayQty = number_format(round(floatval($c_fullquantity - $c_fullquantitydaily)));
|
||||||
//$qry_driver = "SELECT m_firstname, m_lastname FROM tbl_member WHERE m_uid = '$c_driveruid' ";
|
//$qry_driver = "SELECT m_firstname, m_lastname FROM tbl_member WHERE m_uid = '$c_driveruid' ";
|
||||||
//$rt_driver = $jdb->fQuery($qry_driver, "fetch query error");
|
//$rt_driver = $jdb->fQuery($qry_driver, "fetch query error");
|
||||||
|
|
@ -183,7 +186,7 @@ foreach ($rows as $list) {
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>$list_number</td>
|
<td>$list_number</td>
|
||||||
<td><a onclick=\"location.href='/index_intranet.php?view=customer_detail&mode=update&c_uid=$c_uid&page=$page&key_word=$key_wordStr&column=$column&switched=$getSWHStr&sorting_type=$sorting_type&switch=$switch&cstatus=$cstatus'\" style='cursor:pointer;cursor:hand;'><i class=\"bi bi-pencil-square icon-edit\"></i></a>
|
<!--td><a onclick=\"location.href='/index_intranet.php?view=customer_detail&mode=update&c_uid=$c_uid&page=$page&key_word=$key_wordStr&column=$column&switched=$getSWHStr&sorting_type=$sorting_type&switch=$switch&cstatus=$cstatus'\" style='cursor:pointer;cursor:hand;'><i class=\"bi bi-pencil-square icon-edit\"></i></a-->
|
||||||
<!--$OPTIONstr-->
|
<!--$OPTIONstr-->
|
||||||
</td>
|
</td>
|
||||||
<td style=\"text-align:right; padding-right:20px;\">".$todayQty." </td>
|
<td style=\"text-align:right; padding-right:20px;\">".$todayQty." </td>
|
||||||
|
|
@ -191,14 +194,16 @@ foreach ($rows as $list) {
|
||||||
<td onclick=\"location.href='/index_intranet.php?view=customer_detail&mode=update&c_uid=$c_uid&page=$page&key_word=$key_wordStr&column=$column&switched=$getSWHStr&sorting_type=$sorting_type&switch=$switch&cstatus=$cstatus'\" style='cursor:pointer;cursor:hand;'>$c_accountno</td>
|
<td onclick=\"location.href='/index_intranet.php?view=customer_detail&mode=update&c_uid=$c_uid&page=$page&key_word=$key_wordStr&column=$column&switched=$getSWHStr&sorting_type=$sorting_type&switch=$switch&cstatus=$cstatus'\" style='cursor:pointer;cursor:hand;'>$c_accountno</td>
|
||||||
<td>$c_addressSTR </td>
|
<td>$c_addressSTR </td>
|
||||||
<td>$c_city </td>
|
<td>$c_city </td>
|
||||||
<td>$c_postal</td>
|
<!--td>$c_postal</td-->
|
||||||
<td>$c_paymenttype </td>
|
<td>$c_paymenttype </td>
|
||||||
<td>$c_rate </td>
|
<td>$c_rate </td>
|
||||||
<td>$containerChipsHtml </td>
|
<td>$containerChipsHtml </td>
|
||||||
<td>$m_initial </td>
|
<td>$m_initial </td>
|
||||||
<td>$c_phoneSTR </td>
|
<td>$c_phoneSTR </td>
|
||||||
<td>$c_statusSTR </td>
|
<td>$c_statusSTR </td>
|
||||||
<td style=\"min-width:70px;\">$c_istopSTR </td>
|
<!--td style=\"min-width:70px;\">$c_istopSTR </td-->
|
||||||
|
<td>$c_contractdateSTR </td>
|
||||||
|
<td>$c_inactivedateSTR </td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
";
|
";
|
||||||
|
|
@ -430,206 +435,26 @@ $(document).ready(function(){
|
||||||
<table class="tb-list">
|
<table class="tb-list">
|
||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th class="col-rate">Option</th>
|
<!-- <th class="col-rate">Option</th> -->
|
||||||
<th class="col-liter">Liter</th>
|
<th class="col-liter">Liter</th>
|
||||||
<th class="td-restaurant"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_name">Restaurant Name</a></th>
|
<th class="td-restaurant"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_name">Restaurant Name</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_accountno">Account</a></th>
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_accountno">Account</a></th>
|
||||||
<th class="col-address"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_address">Address</a></th>
|
<th class="col-address"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_address">Address</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_word?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_city">City</a></th>
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_word?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_city">City</a></th>
|
||||||
<th class="col-postal-code"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_postal">Postal Code</a></th>
|
<!-- <th class="col-postal-code"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_postal">Postal Code</a></th> -->
|
||||||
<th class="col-payment"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_paymenttype">Payment</a></th>
|
<th class="col-payment"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_paymenttype">Payment</a></th>
|
||||||
<th class="col-rate"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_rate">Rate</a></th>
|
<th class="col-rate"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_rate">Rate</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_maincontainer">Container</a></th>
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_maincontainer">Container</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=m_initial">Driver</a></th>
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=m_initial">Driver</a></th>
|
||||||
<th class="th-width-phone"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_phone">Phone</a></th>
|
<th class="th-width-phone"><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_phone">Phone</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_status">Status</a></th>
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_status">Status</a></th>
|
||||||
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_is_top">Rank</a></th>
|
<!-- <th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_is_top">Rank</a></th> -->
|
||||||
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_contractdate">Contract</a></th>
|
||||||
|
<th><a href="/index_intranet.php?view=customer_list&switched=<?=$getSWHStr?>&page=<?=$page?>&key_word=<?=$key_wordStr?>&sorting_type=<?=$sorting_type?>&cstatus=<?=$cstatus?>&cistop=<?=$cistop?>&switch=c_inactivedate">Inactive</a></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<?=$strList?>
|
<?=$strList?>
|
||||||
|
|
||||||
<!--
|
|
||||||
<tr class="bg-request">
|
|
||||||
<td>1</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="bg-request">
|
|
||||||
<td>2</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="bg-period">
|
|
||||||
<td>3</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="bg-period">
|
|
||||||
<td>4</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="bg-will-call">
|
|
||||||
<td>5</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="bg-will-call">
|
|
||||||
<td>6</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>7</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>8</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>9</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>10</td>
|
|
||||||
<td>Restaurant Name</td>
|
|
||||||
<td>GD221150</td>
|
|
||||||
<td>145 Kingston Rd. Nork Yorth, ON M1K 7Y8</td>
|
|
||||||
<td>Toronto</td>
|
|
||||||
<td>CHQ </td>
|
|
||||||
<td>0.150 </td>
|
|
||||||
<td>400B </td>
|
|
||||||
<td>Every summer I try to find the biggest tree around to climb. My mom always complains that my socks stink after I get home from camp.</td>
|
|
||||||
|
|
||||||
<td>D.S </td>
|
|
||||||
<td>647-123-1234</td>
|
|
||||||
<td>Active </td>
|
|
||||||
<td><i class="bi bi-pencil-square icon-edit"></i></td>
|
|
||||||
<td><i class="bi bi-x-circle icon-delete"></i></td>
|
|
||||||
</tr>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1075,7 +1075,12 @@ $categoryLabels = [
|
||||||
<table class="table table-sm table-hover align-middle mb-0 small">
|
<table class="table table-sm table-hover align-middle mb-0 small">
|
||||||
<thead class="iw-header">
|
<thead class="iw-header">
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th>
|
||||||
|
<label class="iw-checkbox-wrap" title="Select all">
|
||||||
|
<input type="checkbox" class="iw-checkbox-all" id="iwCheckAll">
|
||||||
|
<span class="iw-checkbox-box"></span>
|
||||||
|
</label>
|
||||||
|
</th>
|
||||||
<th style="width:20px;">#</th>
|
<th style="width:20px;">#</th>
|
||||||
<th>Customer</th>
|
<th>Customer</th>
|
||||||
<th>UCO</th>
|
<th>UCO</th>
|
||||||
|
|
@ -1145,6 +1150,68 @@ $categoryLabels = [
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 작업 상태(날짜/드라이버/뷰) 유지
|
||||||
|
const IW_MAP_DATE_KEY = 'iwMapDate';
|
||||||
|
const IW_MAP_DRIVER_KEY = 'iwMapDriverUid';
|
||||||
|
const IW_MAP_VIEW_KEY = 'iwViewMode';
|
||||||
|
|
||||||
|
function getSelectedViewMode() {
|
||||||
|
return document.querySelector('input[name="view_mode"]:checked')?.value || 'list';
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveMapControls() {
|
||||||
|
try {
|
||||||
|
const date = document.getElementById('iwMapDate')?.value || '';
|
||||||
|
if (date) sessionStorage.setItem(IW_MAP_DATE_KEY, date);
|
||||||
|
else sessionStorage.removeItem(IW_MAP_DATE_KEY);
|
||||||
|
|
||||||
|
const driverUid = getSelectedDriverUid();
|
||||||
|
if (driverUid) sessionStorage.setItem(IW_MAP_DRIVER_KEY, String(driverUid));
|
||||||
|
else sessionStorage.removeItem(IW_MAP_DRIVER_KEY);
|
||||||
|
|
||||||
|
sessionStorage.setItem(IW_MAP_VIEW_KEY, getSelectedViewMode());
|
||||||
|
} catch (e) { /* sessionStorage 사용 불가 시 무시 */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
// change 이벤트를 발생시키지 않고 값만 복원한다(중복 로드 방지).
|
||||||
|
function restoreMapControls() {
|
||||||
|
try {
|
||||||
|
const savedDate = sessionStorage.getItem(IW_MAP_DATE_KEY);
|
||||||
|
if (savedDate) {
|
||||||
|
const input = document.getElementById('iwMapDate');
|
||||||
|
if (input) input.value = savedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedDriver = sessionStorage.getItem(IW_MAP_DRIVER_KEY);
|
||||||
|
if (savedDriver) {
|
||||||
|
// 저장된 드라이버가 현재 목록에 남아 있을 때만 선택을 복원한다.
|
||||||
|
const radio = document.querySelector(
|
||||||
|
'input[name="driver"][value="' + savedDriver + '"]'
|
||||||
|
);
|
||||||
|
if (radio) radio.checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 뷰(map/list) 복원: change 이벤트 없이 직접 토글한다.
|
||||||
|
// initInstallMap() 안에서 iwMap 생성 직후 호출되므로 이 시점에 iwMap 존재.
|
||||||
|
const savedView = sessionStorage.getItem(IW_MAP_VIEW_KEY);
|
||||||
|
if (savedView) {
|
||||||
|
const viewRadio = document.querySelector(
|
||||||
|
'input[name="view_mode"][value="' + savedView + '"]'
|
||||||
|
);
|
||||||
|
if (viewRadio) viewRadio.checked = true;
|
||||||
|
|
||||||
|
const isMap = savedView === 'map';
|
||||||
|
document.getElementById('view-map')?.classList.toggle('d-none', !isMap);
|
||||||
|
document.getElementById('view-list')?.classList.toggle('d-none', isMap);
|
||||||
|
|
||||||
|
// 숨겨진 div에서 init된 구글맵의 사이즈 어긋남 방지
|
||||||
|
if (isMap && typeof iwMap !== 'undefined' && iwMap) {
|
||||||
|
setTimeout(() => google.maps.event.trigger(iwMap, 'resize'), 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) { /* sessionStorage 사용 불가 시 무시 */ }
|
||||||
|
}
|
||||||
|
|
||||||
function clearMarkers(){
|
function clearMarkers(){
|
||||||
if (iwInfo) iwInfo.close();
|
if (iwInfo) iwInfo.close();
|
||||||
iwMarkers.forEach(m => { if ('map' in m) m.map = null; });
|
iwMarkers.forEach(m => { if ('map' in m) m.map = null; });
|
||||||
|
|
@ -1169,6 +1236,8 @@ $categoryLabels = [
|
||||||
disableDefaultUI: true
|
disableDefaultUI: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 새로고침 전에 작업하던 날짜/드라이버 복원 (loadDailyInstallPoints 호출 전)
|
||||||
|
restoreMapControls();
|
||||||
loadDailyInstallPoints();
|
loadDailyInstallPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1198,11 +1267,13 @@ $categoryLabels = [
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#iwMapDate').on('change', function(){
|
$('#iwMapDate').on('change', function(){
|
||||||
|
saveMapControls();
|
||||||
resetTrialSelectionUI()
|
resetTrialSelectionUI()
|
||||||
loadDailyInstallPoints();
|
loadDailyInstallPoints();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on('change', 'input[name="driver"]', function () {
|
$(document).on('change', 'input[name="driver"]', function () {
|
||||||
|
saveMapControls();
|
||||||
resetTrialSelectionUI()
|
resetTrialSelectionUI()
|
||||||
loadDailyInstallPoints();
|
loadDailyInstallPoints();
|
||||||
});
|
});
|
||||||
|
|
@ -1780,6 +1851,35 @@ $categoryLabels = [
|
||||||
updateModifyButtonState();
|
updateModifyButtonState();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 헤더 일괄 체크박스 (onchange 라 재바인딩 시 중복 안 됨)
|
||||||
|
const checkAll = document.getElementById('iwCheckAll');
|
||||||
|
if (checkAll) {
|
||||||
|
checkAll.onchange = function () {
|
||||||
|
const on = this.checked;
|
||||||
|
document.querySelectorAll('.iw-checkbox').forEach(cb => {
|
||||||
|
cb.checked = on;
|
||||||
|
});
|
||||||
|
updateModifyButtonState();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncCheckAllState() {
|
||||||
|
const checkAll = document.getElementById('iwCheckAll');
|
||||||
|
if (!checkAll) return;
|
||||||
|
|
||||||
|
const boxes = document.querySelectorAll('.iw-checkbox');
|
||||||
|
const checked = document.querySelectorAll('.iw-checkbox:checked');
|
||||||
|
|
||||||
|
if (!boxes.length) {
|
||||||
|
checkAll.checked = false;
|
||||||
|
checkAll.indeterminate = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAll.checked = checked.length === boxes.length;
|
||||||
|
checkAll.indeterminate = checked.length > 0 && checked.length < boxes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateModifyButtonState() {
|
function updateModifyButtonState() {
|
||||||
|
|
@ -1836,6 +1936,7 @@ $categoryLabels = [
|
||||||
if (this.value === 'map' && iwMap) {
|
if (this.value === 'map' && iwMap) {
|
||||||
setTimeout(() => google.maps.event.trigger(iwMap, 'resize'), 50);
|
setTimeout(() => google.maps.event.trigger(iwMap, 'resize'), 50);
|
||||||
}
|
}
|
||||||
|
saveMapControls();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2672,8 +2672,9 @@ function popup(){
|
||||||
fd.append('i_createdby', <?=$_SESSION['ss_UID']?>);
|
fd.append('i_createdby', <?=$_SESSION['ss_UID']?>);
|
||||||
fd.append('i_note', $installNote);
|
fd.append('i_note', $installNote);
|
||||||
fd.append('i_sourceuid', iw_uid);
|
fd.append('i_sourceuid', iw_uid);
|
||||||
|
// 파일명 순서대로
|
||||||
[...files].forEach(file => {
|
[...files].sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }))
|
||||||
|
.forEach(file => {
|
||||||
fd.append('upload_file[]', file);
|
fd.append('upload_file[]', file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,9 @@ function initInstallWaitStep3() {
|
||||||
fd.append('i_createdby', memberUid);
|
fd.append('i_createdby', memberUid);
|
||||||
fd.append('i_note', 'Before Install');
|
fd.append('i_note', 'Before Install');
|
||||||
fd.append('i_sourceuid', InstallWait.iw_uid);
|
fd.append('i_sourceuid', InstallWait.iw_uid);
|
||||||
[...files].forEach(file => {
|
// 파일명 순서대로
|
||||||
|
[...files].sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }))
|
||||||
|
.forEach(file => {
|
||||||
fd.append('upload_file[]', file);
|
fd.append('upload_file[]', file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@
|
||||||
<!-- Row 3 : Request Note + CS Note -->
|
<!-- Row 3 : Request Note + CS Note -->
|
||||||
<div class="row g-2 mb-3">
|
<div class="row g-2 mb-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label small">Note from Request</label>
|
<label class="form-label small">Note from Request (will be placed on Customer Note)</label>
|
||||||
<textarea id="iwRequestNote" class="form-control form-control-sm" rows="2"></textarea>
|
<textarea id="iwRequestNote" class="form-control form-control-sm" rows="2"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
|
||||||
|
|
@ -119,9 +119,23 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
|
||||||
if (input) {
|
if (input) {
|
||||||
input.addEventListener("change", function () {
|
input.addEventListener("change", function () {
|
||||||
|
// 파일명순 보장: 선택된 파일을 파일명 기준 자연정렬(numeric)하고
|
||||||
|
// input.files 자체를 재구성한다. native form submit 은 이 input.files 를
|
||||||
|
// 그대로 전송하므로, 서버에도 이 순서대로 올라간다. 미리보기도 같은 순서.
|
||||||
|
const sorted = Array.from(this.files)
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const dt = new DataTransfer();
|
||||||
|
sorted.forEach(f => dt.items.add(f));
|
||||||
|
this.files = dt.files; // 재할당해도 change 가 다시 발생하지는 않음
|
||||||
|
} catch (e) {
|
||||||
|
// 구형 브라우저에서 DataTransfer 미지원 시: 미리보기만 정렬됨
|
||||||
|
}
|
||||||
|
|
||||||
previewList.innerHTML = "";
|
previewList.innerHTML = "";
|
||||||
|
|
||||||
Array.from(this.files).forEach(file => {
|
sorted.forEach(file => { // ← this.files 대신 sorted 로 미리보기
|
||||||
if (!file.type.startsWith("image/")) return;
|
if (!file.type.startsWith("image/")) return;
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue