- [INSTALL WAIT LIST] Preferred Date 표시 추가.
- [INSTALL WAIT LIST] Assigned List 도 검색 가능하도록 수정.
- [EXPORT] 드라이버 가져올 때 버그 수정.
- [CUSTOMER] 각 섹션마다 SAVE 버튼 추가. Install Date, Exchange Date, Removal Date 추가.
This commit is contained in:
Hyojin Ahn 2026-04-29 13:30:04 -04:00
parent e01e72c0ca
commit a0ebce1a14
7 changed files with 161 additions and 51 deletions

View File

@ -436,6 +436,7 @@ trait InstallAPI {
$scheduled = intval($_POST['scheduled'] ?? 0); $scheduled = intval($_POST['scheduled'] ?? 0);
$cycle = intval($_POST['scheduled_cycle'] ?? 0); $cycle = intval($_POST['scheduled_cycle'] ?? 0);
$lock_date = intval($_POST['lock_date'] ?? 0);
// Two-person OFF = NULL // Two-person OFF = NULL
if (!$person_cnt) { if (!$person_cnt) {
@ -453,6 +454,7 @@ trait InstallAPI {
SET SET
iw_request_at = ".($request_at ? "'{$request_at}'" : "NOW()").", iw_request_at = ".($request_at ? "'{$request_at}'" : "NOW()").",
iw_requested_due_date = ".($due_date ? "'{$due_date}'" : "NULL").", iw_requested_due_date = ".($due_date ? "'{$due_date}'" : "NULL").",
iw_lock_date = '{$lock_date}',
iw_request_by = ".($request_by ? "'{$request_by}'" : "NULL").", iw_request_by = ".($request_by ? "'{$request_by}'" : "NULL").",
iw_request_note = ".($request_note ? "'".addslashes($request_note)."'" : "NULL").", iw_request_note = ".($request_note ? "'".addslashes($request_note)."'" : "NULL").",
iw_cs_note = ".($cs_note ? "'".addslashes($cs_note)."'" : "NULL").", iw_cs_note = ".($cs_note ? "'".addslashes($cs_note)."'" : "NULL").",
@ -529,6 +531,7 @@ trait InstallAPI {
ifnull(mem.m_initial,'') as di_customer_driver_initial, ifnull(mem.m_initial,'') as di_customer_driver_initial,
di.di_install_date, di.di_install_date,
di.di_install_time, di.di_install_time,
di.di_lock_date,
di.di_wait_uid, di.di_wait_uid,
di.di_customer_uid, di.di_customer_uid,
di.di_accountno, di.di_accountno,
@ -603,6 +606,7 @@ trait InstallAPI {
di_order_seq, di_order_seq,
di_driver_uid, di_driver_uid,
di_install_date, di_install_date,
di_lock_date,
di_wait_uid, di_wait_uid,
di_customer_uid, di_customer_uid,
di_customer_name, di_customer_name,
@ -618,12 +622,14 @@ trait InstallAPI {
di_oil_pickup, di_oil_pickup,
di_request_note, di_request_note,
di_work_note, di_work_note,
di_cs_note,
di_created_by di_created_by
) )
SELECT SELECT
'{$di_order_seq}', '{$di_order_seq}',
'{$di_driver_uid}', '{$di_driver_uid}',
'{$di_install_date}', '{$di_install_date}',
iw.iw_lock_date,
iw.iw_uid, iw.iw_uid,
iw.iw_customer_uid, iw.iw_customer_uid,
iw.iw_customer_name, iw.iw_customer_name,
@ -639,6 +645,7 @@ trait InstallAPI {
iw.iw_need_oil_pickup, iw.iw_need_oil_pickup,
iw.iw_request_note, iw.iw_request_note,
iw.iw_work_note, iw.iw_work_note,
iw.iw_cs_note,
'{$created_by}' '{$created_by}'
FROM tbl_install_waitlist iw FROM tbl_install_waitlist iw
LEFT JOIN tbl_customer c LEFT JOIN tbl_customer c

View File

@ -1833,6 +1833,10 @@ table.table-search-report .tb-list th {
border-color: #ffc107; border-color: #ffc107;
box-shadow: 0 0 0 2px rgba(255,193,7,.25); box-shadow: 0 0 0 2px rgba(255,193,7,.25);
} }
.wait-card.assigned {
opacity: 0.5;
pointer-events: none;
}
.container-chips { .container-chips {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@ -2308,6 +2312,7 @@ tr.status-X {
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
width: 100%;
} }
/* label = button */ /* label = button */
@ -2322,13 +2327,16 @@ tr.status-X {
} }
.radio-segment span { .radio-segment span {
display: block; display: flex;
width: 100%; width: 100%;
text-align: center; text-align: center;
align-items: center;
justify-content: center;
padding: 8px 0; padding: 8px 0;
background: #e7e7e7; background: #e7e7e7;
color: #333; color: #333;
font-weight: 500; font-weight: 500;
height: 100%;
} }
.radio-segment input[type="radio"]:checked + span { .radio-segment input[type="radio"]:checked + span {
@ -2345,6 +2353,17 @@ tr.status-X {
border-radius: 0 5px 5px 0; border-radius: 0 5px 5px 0;
} }
/* check box */
.radio-segment input[type="checkbox"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.radio-segment input[type="checkbox"]:checked + span {
background: #ffca1a;
color: #333;
}
/* mobile */ /* mobile */
@media (max-width: 768px) { @media (max-width: 768px) {
.radio-segment { .radio-segment {

View File

@ -407,7 +407,7 @@ addLog ("add", "CUSTOMER DETAIL", "VIEW", $lguserid, $query, $c_uid);
$(document).ready(function(){ $(document).ready(function(){
$(function () { $(function () {
$('#c_contractdate, #c_form_eu, #c_form_corsia, #c_fpickup, #c_removaldate, #d_visitdate, #c_inactivedate, #c_switchformdate').datepicker({ $('#c_contractdate, #c_form_eu, #c_form_corsia, #c_fpickup, #c_removaldate, #c_installdate, #c_exchangedate, #d_visitdate, #c_inactivedate, #c_switchformdate').datepicker({
dateFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd',
buttonImage: "/images/cal_red.png", buttonImage: "/images/cal_red.png",
buttonImageOnly: true, buttonImageOnly: true,
@ -697,8 +697,6 @@ $(document).ready(function() {
$('#fpna').val($(this).is(':checked')); $('#fpna').val($(this).is(':checked'));
}); });
//set initial state.
$('#sfna').val($(this).is(':checked')); $('#sfna').val($(this).is(':checked'));
$('#sfna').change(function() { $('#sfna').change(function() {
@ -712,6 +710,48 @@ $(document).ready(function() {
$('#sfna').val($(this).is(':checked')); $('#sfna').val($(this).is(':checked'));
}); });
$('#inna').val($(this).is(':checked'));
$('#inna').change(function() {
if($(this).is(":checked")) {
$(this).attr("checked", 1);
document.getElementById('c_installdate').value = "";
}
else {
document.getElementById('c_installdate').value = "";
}
$('#inna').val($(this).is(':checked'));
});
$('#rena').val($(this).is(':checked'));
$('#rena').change(function() {
if($(this).is(":checked")) {
$(this).attr("checked", 1);
document.getElementById('c_removaldate').value = "";
}
else {
document.getElementById('c_removaldate').value = "";
}
$('#rena').val($(this).is(':checked'));
});
$('#exna').val($(this).is(':checked'));
$('#exna').change(function() {
if($(this).is(":checked")) {
$(this).attr("checked", 1);
document.getElementById('c_exchangedate').value = "";
}
else {
document.getElementById('c_exchangedate').value = "";
}
$('#exna').val($(this).is(':checked'));
});
}); });
</SCRIPT> </SCRIPT>
@ -1461,6 +1501,11 @@ $(document).ready(function()
</table> </table>
</div><!--wrap-border--> </div><!--wrap-border-->
<div class="btn-box">
<button type="submit" id="customer-button-id1" class="btn-save text-center" href="#">SAVE</button>
</div><!--btn-box Ends-->
</div><!--Container Ends--> </div><!--Container Ends-->
<!--Restaurant Information Ends--> <!--Restaurant Information Ends-->
@ -1492,24 +1537,26 @@ $(document).ready(function()
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="td-title-info">First Install Date</td> <td class="td-title-info">First Install Date<div style="display: inline; float:right; padding-right: 30px;">Init <input type="checkbox" id="inna" name="inna" value="1"></div></td>
<td class="td-text-info"> <td class="td-text-info">
<input type="text" id="c_installdate" name="c_installdate" value="<?=$c_installdateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly> <input type="text" id="c_installdate" name="c_installdate" value="<?=$c_installdateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly>
</td> </td>
<td class="td-title-info">Removal Date</td> <td class="td-title-info">Removal Date<div style="display: inline; float:right; padding-right: 30px;">Init <input type="checkbox" id="rena" name="rena" value="1"></div></td>
<td class="td-text-info"> <td class="td-text-info">
<input type="text" id="c_removaldate" name="c_removaldate" value="<?=$c_removaldateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly> <input type="text" id="c_removaldate" name="c_removaldate" value="<?=$c_removaldateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly>
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="td-title-info">Last Container Work Date</td> <td class="td-title-info">Last Container Work Date<div style="display: inline; float:right; padding-right: 30px;">Init <input type="checkbox" id="exna" name="exna" value="1"></div></td>
<td class="td-text-info"> <td class="td-text-info">
<input type="text" id="c_exchangedate" name="c_exchangedate" value="<?=$c_exchangedateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly> <input type="text" id="c_exchangedate" name="c_exchangedate" value="<?=$c_exchangedateSTR?>" placeholder="<?=date('Y-m-d')?>" readonly>
</td> </td>
<td class="td-title-info"></td> <td class="td-text-info" colspan="2">
<td class="td-text-info"> <div class="btn-box">
<button type="submit" id="customer-button-id2" class="btn-save text-center" href="#">SAVE</button>
</div><!--btn-box Ends-->
</td> </td>
</tr> </tr>
<tr> <tr>
@ -1853,7 +1900,7 @@ $(document).ready(function()
</div><!--wrap-border--> </div><!--wrap-border-->
<div class="btn-box"> <div class="btn-box">
<button type="submit" id="customer-button-id" class="btn-save text-center" href="#">SAVE</button> <button type="submit" id="customer-button-id3" class="btn-save text-center" href="#">SAVE</button>
</div><!--btn-box Ends--> </div><!--btn-box Ends-->
</div> </div>

View File

@ -364,6 +364,8 @@ if ($actionStr == "CUSTOMER") {
FROM tbl_daily d FROM tbl_daily d
JOIN tbl_customer c JOIN tbl_customer c
ON d.d_customeruid = c.c_uid ON d.d_customeruid = c.c_uid
JOIN tbl_member m
ON d.d_driveruid = m.m_uid
WHERE d.d_status = 'F' WHERE d.d_status = 'F'
AND d.d_orderdate BETWEEN '$oil_period_fromTMP' AND '$oil_period_toTMP' AND d.d_orderdate BETWEEN '$oil_period_fromTMP' AND '$oil_period_toTMP'
ORDER BY d.d_orderdate, c.c_accountno ORDER BY d.d_orderdate, c.c_accountno

View File

@ -7,7 +7,18 @@ $where = [];
if (!empty($kw_customer)) $where[] = "(iw_customer_name LIKE '%{$kw_customer}%' OR iw_address LIKE '%{$kw_customer}%' OR iw_accountno LIKE '%{$kw_customer}%' OR iw_city LIKE '%{$kw_customer}%')"; if (!empty($kw_customer)) $where[] = "(iw_customer_name LIKE '%{$kw_customer}%' OR iw_address LIKE '%{$kw_customer}%' OR iw_accountno LIKE '%{$kw_customer}%' OR iw_city LIKE '%{$kw_customer}%')";
if (!empty($kw_work)) $where[] = "(iw_work_type = '{$kw_work}')"; if (!empty($kw_work)) $where[] = "(iw_work_type = '{$kw_work}')";
if (!empty($_GET['kw_two_person'])) $where[] = "(iw_required_person_cnt IS NOT NULL AND iw_required_person_cnt > 0)"; if (!empty($_GET['kw_two_person'])) $where[] = "(iw_required_person_cnt IS NOT NULL AND iw_required_person_cnt > 0)";
if (!empty($_GET['kw_draft'])) $where[] = "(iw_status = 'DRAFT')";
$statusList = [];
if (!empty($_GET['kw_waiting'])) $statusList[] = "'WAITING'";
if (!empty($_GET['kw_draft'])) $statusList[] = "'DRAFT'";
if (!empty($_GET['kw_assigned'])) $statusList[] = "'ASSIGNED'";
// 기본
if (!$statusList) {
$statusList = ["'WAITING'", "'DRAFT'"];
}
$statusWhere = "iw_status IN (" . implode(',', $statusList) . ")";
if (!empty($where)) { if (!empty($where)) {
$add_where = ' AND ' . implode(' AND ', $where); $add_where = ' AND ' . implode(' AND ', $where);
} }
@ -21,7 +32,7 @@ function db_escape($jdb, $str) {
$sql_cnt = " $sql_cnt = "
SELECT COUNT(*) SELECT COUNT(*)
FROM tbl_install_waitlist FROM tbl_install_waitlist
WHERE iw_status in ('WAITING','DRAFT') WHERE {$statusWhere}
$add_where $add_where
"; ";
$total_count = $jdb->rQuery($sql_cnt, "Install wait list count error"); $total_count = $jdb->rQuery($sql_cnt, "Install wait list count error");
@ -30,11 +41,19 @@ $total_count = $jdb->rQuery($sql_cnt, "Install wait list count error");
// 1) Load waitlist // 1) Load waitlist
// ============================ // ============================
$sql = " $sql = "
SELECT iw.*, CONCAT(m.m_firstname, ' ', m.m_lastname) as iw_created_member SELECT iw.*, CONCAT(m.m_firstname, ' ', m.m_lastname) as iw_created_member, di.di_install_date
FROM tbl_install_waitlist iw FROM tbl_install_waitlist iw
LEFT OUTER JOIN tbl_member m LEFT OUTER JOIN tbl_member m
ON iw.iw_created_by = m.m_uid ON iw.iw_created_by = m.m_uid
WHERE iw_status in ('WAITING','DRAFT') LEFT JOIN (
SELECT
di_wait_uid,
MAX(di_install_date) as di_install_date
FROM tbl_daily_install
WHERE di_status != 'X'
GROUP BY di_wait_uid
) di ON di.di_wait_uid = iw.iw_uid
WHERE {$statusWhere}
$add_where $add_where
ORDER BY iw_requested_due_date ASC, iw_request_at ASC ORDER BY iw_requested_due_date ASC, iw_request_at ASC
"; ";
@ -391,6 +410,7 @@ function formatPhone($phone) {
// Step3 의 기본 필드 채우기 // Step3 의 기본 필드 채우기
iwRequestDate.value = data.iw_request_at?.substring(0,10) || ''; iwRequestDate.value = data.iw_request_at?.substring(0,10) || '';
iwScheduleDate.value = data.iw_requested_due_date || ''; iwScheduleDate.value = data.iw_requested_due_date || '';
document.getElementById('iwLockDate').checked = (data.iw_lock_date == 1);
//iwRequestBy.value = data.iw_request_by || ''; //iwRequestBy.value = data.iw_request_by || '';
iwRequestNote.value = data.iw_request_note || ''; iwRequestNote.value = data.iw_request_note || '';
iwCsNote.value = data.iw_cs_note || ''; iwCsNote.value = data.iw_cs_note || '';
@ -412,8 +432,7 @@ function formatPhone($phone) {
} }
// job label 갱신 // job label 갱신
document.getElementById('iwStep3Title').innerText = document.getElementById('iwStep3Title').innerText = `Step 3 of 3 - ${data.iw_work_type} Detail`;
`Step 3 of 3 - ${data.iw_work_type} Detail`;
// action box 다시 그림 // action box 다시 그림
setStep3Title(); setStep3Title();
@ -514,15 +533,27 @@ function formatPhone($phone) {
<input type="hidden" name="kw_two_person" id="kw_two_person"> <input type="hidden" name="kw_two_person" id="kw_two_person">
</div> </div>
<div class="col-md-1 d-flex"> <div class="col-md-3 d-flex align-items-stretch">
<button type="button" id="filterDraft" class="btn btn-outline-dark w-100 h-100" data-active="0" title="Draft Filter"> <div class="radio-segment w-100">
<i class="bi bi-clipboard-check"></i> <label>
</button> <input type="checkbox" name="kw_draft" id="kw_draft" checked>
<input type="hidden" name="kw_draft" id="kw_draft"> <span title="Draft"><i class="bi bi-clipboard-check"></i> </span>
</label>
<label>
<input type="checkbox" name="kw_waiting" id="kw_waiting" checked>
<span title="Waiting"><i class="bi bi-hourglass-split"></i> </span>
</label>
<label>
<input type="checkbox" name="kw_assigned" id="kw_assigned">
<span title="Assigned"><i class="bi bi-link-45deg"></i> </span>
</label>
</div>
</div> </div>
<!-- Search --> <!-- Search -->
<div class="col-md-5"> <div class="col-md-3">
<div class="input-group h-100 search-container"> <div class="input-group h-100 search-container">
<input type="text" name="kw_customer" id="kwCustomer" class="form-control" placeholder="City / Customer / Account" value="<?=htmlspecialchars($kw_customer)?>"> <input type="text" name="kw_customer" id="kwCustomer" class="form-control" placeholder="City / Customer / Account" value="<?=htmlspecialchars($kw_customer)?>">
<button type="submit" class="btn btn-outline-secondary"> <button type="submit" class="btn btn-outline-secondary">
@ -595,8 +626,10 @@ function formatPhone($phone) {
} }
} }
?> ?>
<?php
<div class="wait-card" $isAssigned = ($row['iw_status'] === 'ASSIGNED');
?>
<div class="wait-card <?= $isAssigned ? 'assigned' : '' ?>"
data-iw="<?= (int)$row['iw_uid'] ?>" data-iw="<?= (int)$row['iw_uid'] ?>"
data-status="<?= htmlspecialchars($row['iw_status']) ?>" data-status="<?= htmlspecialchars($row['iw_status']) ?>"
data-accountno="<?= htmlspecialchars($row['iw_accountno']) ?>" data-accountno="<?= htmlspecialchars($row['iw_accountno']) ?>"
@ -657,7 +690,13 @@ function formatPhone($phone) {
<!-- RIGHT --> <!-- RIGHT -->
<div class="ms-auto d-flex align-items-center gap-2"> <div class="ms-auto d-flex align-items-center gap-2">
<small class="text-muted me-2"> <small class="text-muted me-2">
Due: <?=$row['iw_requested_due_date'] ?: '-';?> <?php if (!empty($row['di_install_date'])): ?>
<i class="bi bi-link-45deg text-secondary" title="Assigned"></i>
Assigned: <?=$row['di_install_date']?>
<?php else: ?>
<?=$row['iw_lock_date'] == 1 ? '<i class="bi bi-lock text-secondary" title="Preferred Date"></i>' : '';?>
Due: <?=$row['iw_requested_due_date'] ?: '-'?>
<?php endif; ?>
</small> </small>
<a href="#" class="btn btn-sm btn-outline-secondary btn-edit-install-wait" data-iw-uid="<?=$row['iw_uid']?>" title="Edit"> <a href="#" class="btn btn-sm btn-outline-secondary btn-edit-install-wait" data-iw-uid="<?=$row['iw_uid']?>" title="Edit">
@ -862,7 +901,7 @@ function formatPhone($phone) {
</button> </button>
<strong> <strong>
<input type="text" id="iwMapDate" class="form-control form-control-sm date-picker-form" style="max-height:20px;" autocomplete="off" placeholder="<?=date('Y-m-d')?>" readonly> <input type="text" id="iwMapDate" class="form-control form-control-sm date-picker-form" style="max-height:20px; max-width:120px;" autocomplete="off" placeholder="<?=date('Y-m-d')?>" readonly>
</strong> </strong>
<button type="button" class="btn btn-sm btn-outline-secondary btn-date-next"> <button type="button" class="btn btn-sm btn-outline-secondary btn-date-next">
@ -1103,25 +1142,7 @@ function formatPhone($phone) {
searchWaitlist(); searchWaitlist();
}); });
$('#filterDraft').on('click', function () { $('#kw_draft, #kw_waiting, #kw_assigned').on('change', function () {
const active = $(this).attr('data-active') === '1';
if (active) {
$(this)
.removeClass('btn-dark text-white')
.addClass('btn-outline-dark')
.attr('data-active', '0');
$('#kw_draft').val('');
} else {
$(this)
.removeClass('btn-outline-dark')
.addClass('btn-dark text-white')
.attr('data-active', '1');
$('#kw_draft').val('1');
}
searchWaitlist(); searchWaitlist();
}); });
@ -1227,7 +1248,15 @@ function formatPhone($phone) {
tr.dataset.orderSeq = r.di_order_seq; tr.dataset.orderSeq = r.di_order_seq;
} }
tr.innerHTML = ` tr.innerHTML = `
<td>${r.is_trial ? '': `<label class="iw-checkbox-wrap"><input type="checkbox" class="iw-checkbox" value="${r.di_uid}"><span class="iw-checkbox-box"></span></label>`}</td> <td>
${r.is_trial ? '' : `
<label class="iw-checkbox-wrap">
<input type="checkbox" class="iw-checkbox" value="${r.di_uid}">
<span class="iw-checkbox-box"></span>
</label>
${r.di_lock_date == 1 ? '<i class="bi bi-lock text-secondary" title="Preferred Date"></i>' : ''}
`}
</td>
<td>${r.di_order_seq}</td> <td>${r.di_order_seq}</td>
<td class="iw-drag-handle" style="cursor:grab; max-width: 220px;"> <td class="iw-drag-handle" style="cursor:grab; max-width: 220px;">
<span class="text-muted me-2" title="Drag to reorder"> <span class="text-muted me-2" title="Drag to reorder">

View File

@ -282,6 +282,7 @@ function initInstallWaitStep3() {
iw_uid: InstallWait.iw_uid, iw_uid: InstallWait.iw_uid,
request_at: document.getElementById('iwRequestDate').value || null, request_at: document.getElementById('iwRequestDate').value || null,
due_date: document.getElementById('iwScheduleDate').value || null, due_date: document.getElementById('iwScheduleDate').value || null,
lock_date: document.getElementById('iwLockDate').checked ? 1 : 0,
request_by: document.getElementById('iwRequestBy').value || null, request_by: document.getElementById('iwRequestBy').value || null,
request_note: document.getElementById('iwRequestNote').value || null, request_note: document.getElementById('iwRequestNote').value || null,
cs_note: document.getElementById('iwCsNote').value || null, cs_note: document.getElementById('iwCsNote').value || null,

View File

@ -134,7 +134,12 @@
<input type="text" id="iwRequestDate" class="form-control form-control-sm date-picker-form" autocomplete="off" placeholder="<?=date('Y-m-d')?>" readonly> <input type="text" id="iwRequestDate" class="form-control form-control-sm date-picker-form" autocomplete="off" placeholder="<?=date('Y-m-d')?>" readonly>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="d-flex justify-content-between align-items-center">
<label class="form-label small">Due date</label> <label class="form-label small">Due date</label>
<div>
<input class="form-check-input me-2" type="checkbox" id="iwLockDate"><label class="form-check-label small" for="iwLockDate">Preferred Date</label>
</div>
</div>
<input type="text" id="iwScheduleDate" class="form-control form-control-sm date-picker-form" autocomplete="off" placeholder="yyyy-mm-dd" readonly> <input type="text" id="iwScheduleDate" class="form-control form-control-sm date-picker-form" autocomplete="off" placeholder="yyyy-mm-dd" readonly>
</div> </div>
</div> </div>