기간별 수량 조회 페이지 신설
This commit is contained in:
269
manager/bakery/bakery_stock_view.php
Normal file
269
manager/bakery/bakery_stock_view.php
Normal file
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
// 베이커리 재고관리
|
||||
include_once "_common.php";
|
||||
if (!isset($_SESSION['user_id'])) header( 'Location: FG_MANAGER_URL' ); // 로그인 되어있지 않으면 로그인 페이지로 보냄
|
||||
|
||||
include_once 'head.sub.php';
|
||||
include_once FG_MANAGER_PATH."/head.php";
|
||||
|
||||
// 검색 변수 초기화
|
||||
!isset($search) ?? "";
|
||||
!isset($where) ?? "";
|
||||
!isset($search_count) ?? "";
|
||||
|
||||
$is_debug = false; // 디버깅 시 true로 변경
|
||||
|
||||
// ord_by 로 넘어온 값이 있으면 반영
|
||||
$ord_by = isset($_REQUEST["ord_by"]) ? $_REQUEST["ord_by"] : "product_name ASC";
|
||||
|
||||
// 검색어 반영
|
||||
$searchWord = $_GET["searchWord"] ?? "";
|
||||
|
||||
// 날짜 가져오기
|
||||
$today = new DateTime();
|
||||
|
||||
$startDate = $_REQUEST["startDate"] ?? (clone $today)->modify('-7 days')->format('Y-m-d');
|
||||
$endDate = $_REQUEST["endDate"] ?? (clone $today)->modify('-1 day')->format('Y-m-d');
|
||||
|
||||
// 최종 수정시간
|
||||
$edit_datetime = date('Y-m-d H:i:s'); // 최종 수정 시간 업데이트
|
||||
|
||||
// 베이커리 계정인지 확인하고, 오늘 이후 날짜인 경우 생산-매출액란을 공란으로 출력하기 위한 변수
|
||||
$is_bakery = ( $_SESSION['user_id'] == "bakery" ) ? true : false;
|
||||
$is_bakery_input = ( strtotime($searchDate) >= strtotime(date("Y-m-d")) ) ? true : false;
|
||||
|
||||
// 합계 구하기
|
||||
$totalBakeryInvenData = getBakeryInvenSumPeriod($startDate, $endDate, $searchWord);
|
||||
// barcode별 그룹화된 상세 데이터를 구하기
|
||||
$bakeryInvenData = getBakeryInvenDataPeriod($startDate, $endDate, $searchWord);
|
||||
|
||||
?>
|
||||
|
||||
<style>
|
||||
/* 틀 고정
|
||||
.tableWrapper {
|
||||
overflow: auto;
|
||||
height: 700px;
|
||||
width: 100%;
|
||||
}
|
||||
#bakeryTable th {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
}
|
||||
*/
|
||||
|
||||
</style>
|
||||
|
||||
<div class="d-flex justify-content-between mb-3 ">
|
||||
<div class="row align-items-start">
|
||||
<h2>베이커리 기간별 현황</h2>
|
||||
</div>
|
||||
<div class="row align-items-end align-self-end only-print">
|
||||
<p>조회일자 : <?=$startDate?> ~ <?=$endDate?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-3 no-print">
|
||||
<div class="row align-items-start flex-nowrap">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">시작일</span>
|
||||
<input type="date" class="form-control" id="startDateInput" name="startDate" max="9999-12-31" value="<?= $startDate ?>">
|
||||
<span class="input-group-text">종료일</span>
|
||||
<input type="date" class="form-control" id="endDateInput" name="endDate" max="9999-12-31" value="<?= $endDate ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row align-items-end">
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="text" name="searchWord" id="searchWord" placeholder="상품명 검색" value="<?= htmlspecialchars($_GET['searchWord'] ?? '') ?>" />
|
||||
<button class="btn btn-success" id="searchBtn" type="button">검색</button>
|
||||
<button class="btn btn-primary" type="button" id="resetSearch">초기화</button>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
<div class="row align-items-end">
|
||||
<input type="file" id="inventoryFileInput" style="display:none;" accept=".xls,.xlsx" />
|
||||
<div class="btn-group" role="group" aria-label="bakery-button">
|
||||
<button type="button" class="btn btn-success" id="exportExcelButton">엑셀변환</button>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="table">
|
||||
<h3>개요</h3>
|
||||
<table class="table align-middle" id="bakeryTotalTable">
|
||||
<thead class="table-light">
|
||||
<tr class="align-middle">
|
||||
<th class="text-center">품목</th>
|
||||
<th class="text-center">생산</th>
|
||||
<th class="text-center">업장사용</th>
|
||||
<th class="text-center">재활용</th>
|
||||
<th class="text-center">폐기</th>
|
||||
<th class="text-center">판매</th>
|
||||
<th class="text-center">매출액</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="align-middle">
|
||||
<th class="text-center"><?=number_format(cntUsedBakeryItems())?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_production'])?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_inhouse_use'])?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_recycling'])?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_disposal'])?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_sales'])?></th>
|
||||
<th class="text-center"><?=number_format($totalBakeryInvenData['t_payment_amount'])?></th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tableWrapper">
|
||||
<h3>상세</h3>
|
||||
<table class="table align-middle table-hover <?php if( $bakeryInvenData) echo 'table-striped'?> bakery" id="bakeryTable">
|
||||
<colgroup>
|
||||
<col width="30px">
|
||||
<col width="150px">
|
||||
<col width="70px">
|
||||
<col width="70px">
|
||||
<col width="70px">
|
||||
<col width="70px">
|
||||
<col width="70px">
|
||||
<col width="70px">
|
||||
</colgroup>
|
||||
<!-- 테이블 제목 -->
|
||||
<thead class="table-light">
|
||||
<tr class="align-middle">
|
||||
<th class="text-center no-click">No.</th>
|
||||
<th class="text-center" data-column="product_name" data-order="asc">품목 <span class="sort-icon fa fa-sort-up" data-column="product_name"></span></th>
|
||||
<th class="text-center" data-column="production" data-order="asc">생산 <span class="sort-icon" data-column="production"></span></th>
|
||||
<th class="text-center" data-column="inhouse_use" data-order="asc">업장사용 <span class="sort-icon" data-column="inhouse_use"></span></th>
|
||||
<th class="text-center" data-column="recycling" data-order="asc">재활용 <span class="sort-icon" data-column="recycling"></span></th>
|
||||
<th class="text-center" data-column="disposal" data-order="asc">폐기 <span class="sort-icon" data-column="disposal"></span></th>
|
||||
<th class="text-center" data-column="sales" data-order="asc">판매 <span class="sort-icon" data-column="sales"></span></th>
|
||||
<th class="text-center" data-column="payment_amount" data-order="asc">매출액 <span class="sort-icon" data-column="payment_amount"></span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- 테이블 데이터 -->
|
||||
<tbody class="table-group-divider" id="bakeryTableBody">
|
||||
<?php
|
||||
if ( $bakeryInvenData ) {
|
||||
// 데이터 가져와서 뿌리기
|
||||
$i = 1; // number 표시를 위한 변수
|
||||
foreach ($bakeryInvenData as $row) {
|
||||
?>
|
||||
|
||||
<tr id="row-<?=$row['barcode']?>">
|
||||
<td class="text-center"><?=$i?></td>
|
||||
<td class="text-left"><?=htmlspecialchars($row['product_name'])?></td>
|
||||
<td class="text-end"><span class="value"><?=number_format($row['production'])?></span>
|
||||
<input class="form-control text-end d-none" type="text" value="<?=$row['production']?>" id="production-<?=$row['barcode']?>" product_name="<?=$row['product_name']?>" aria-label="production" readonly>
|
||||
</td>
|
||||
<td class="text-end"><span class="value"><?=number_format($row['inhouse_use'])?></span>
|
||||
<input class="form-control text-end d-none" type="text" value="<?=$row['inhouse_use']?>" id="inhouse_use-<?=$row['barcode']?>" product_name="<?=$row['product_name']?>" aria-label="inhouse_use" readonly>
|
||||
</td>
|
||||
<td class="text-end"><span class="value"><?=number_format($row['recycling'])?></span>
|
||||
<input class="form-control text-end d-none" type="text" value="<?=$row['recycling']?>" id="recycling-<?=$row['barcode']?>" product_name="<?=$row['product_name']?>" aria-label="recycling" readonly>
|
||||
</td>
|
||||
<td class="text-end"><span class="value"><?=number_format($row['disposal'])?></span>
|
||||
<input class="form-control text-end d-none" type="text" value="<?=$row['disposal']?>" id="disposal-<?=$row['barcode']?>" product_name="<?=$row['product_name']?>" aria-label="disposal" readonly>
|
||||
</td>
|
||||
<td class="text-end"><?=number_format($row['sales'])?></td>
|
||||
<td class="text-end"><?=number_format($row['payment_amount'])?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
$i++;
|
||||
} // endforeach
|
||||
?>
|
||||
</tbody>
|
||||
<!-- 합계 데이터 출력 -->
|
||||
<tfoot class="no-print">
|
||||
<tr>
|
||||
<td colspan="2" class="text-center">합계</th>
|
||||
<td class="text-end" id="total_production"><?=number_format($totalBakeryInvenData['t_production'])?></td>
|
||||
<td class="text-end" id="total_inhouse_use"><?=number_format($totalBakeryInvenData['t_inhouse_use'])?></td>
|
||||
<td class="text-end" id="total_recycling"><?=number_format($totalBakeryInvenData['t_recycling'])?></td>
|
||||
<td class="text-end" id="total_disposal"><?=number_format($totalBakeryInvenData['t_disposal'])?></td>
|
||||
<td class="text-end" id="total_sales"><?=number_format($totalBakeryInvenData['t_sales'])?></td>
|
||||
<td class="text-end" id="total_payment_amount"><?=number_format($totalBakeryInvenData['t_payment_amount'])?></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<?php
|
||||
} else {
|
||||
// 데이터가 없을 경우 출력
|
||||
echo "<tr class='align-middle'>";
|
||||
echo "<td class='text-center' colspan='9'> 자료가 존재하지 않습니다 </td>";
|
||||
echo "</tr></tbody>";
|
||||
} // endif
|
||||
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const startDateInput = document.getElementById('startDateInput');
|
||||
const endDateInput = document.getElementById('endDateInput');
|
||||
const searchInput = document.getElementById('searchWord');
|
||||
const searchBtn = document.getElementById('searchBtn');
|
||||
const resetBtn = document.getElementById('resetSearch');
|
||||
|
||||
// URL 쿼리 갱신 함수
|
||||
function getUrlWithParams(paramsToUpdate = {}, paramsToDelete = []) {
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
// 업데이트
|
||||
for (const key in paramsToUpdate) {
|
||||
url.searchParams.set(key, paramsToUpdate[key]);
|
||||
}
|
||||
|
||||
// 삭제
|
||||
for (const key of paramsToDelete) {
|
||||
url.searchParams.delete(key);
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
// 날짜 변경 시
|
||||
function onDateChange() {
|
||||
const url = getUrlWithParams({
|
||||
startDate: startDateInput.value,
|
||||
endDate: endDateInput.value,
|
||||
});
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
// 검색 버튼 클릭 시
|
||||
function onSearchClick() {
|
||||
const url = getUrlWithParams({
|
||||
startDate: startDateInput.value,
|
||||
endDate: endDateInput.value,
|
||||
searchWord: searchInput.value,
|
||||
});
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
// 검색어 입력창에서 엔터 입력 시 검색 실행
|
||||
searchInput.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault(); // 폼 제출 방지
|
||||
onSearchClick(); // 검색 함수 호출
|
||||
}
|
||||
});
|
||||
|
||||
// 초기화 버튼 클릭 시
|
||||
function onResetClick() {
|
||||
const url = getUrlWithParams({}, ['searchWord']);
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
// 이벤트 바인딩
|
||||
startDateInput.addEventListener('change', onDateChange);
|
||||
endDateInput.addEventListener('change', onDateChange);
|
||||
searchBtn.addEventListener('click', onSearchClick);
|
||||
resetBtn.addEventListener('click', onResetClick);
|
||||
</script>
|
||||
<?php
|
||||
include_once "tail.sub.php";
|
||||
include_once FG_MANAGER_PATH."/tail.php";
|
||||
@ -315,7 +315,77 @@ function get_total_count($db_name) {
|
||||
|
||||
return $R;
|
||||
}
|
||||
|
||||
|
||||
function getBakeryInvenDataPeriod($start_date, $end_date, $searchWord = "", $ord_by = "a.date ASC, b.product_name ASC") {
|
||||
global $fg;
|
||||
|
||||
// 검색 조건
|
||||
$search_sql = "";
|
||||
if ($searchWord !== "") {
|
||||
$searchWord = sql_real_escape_string($searchWord);
|
||||
$search_sql = "AND b.product_name LIKE '%{$searchWord}%'";
|
||||
}
|
||||
|
||||
$query = "SELECT
|
||||
b.product_name,
|
||||
SUM(a.production) AS production,
|
||||
SUM(a.inhouse_use) AS inhouse_use,
|
||||
SUM(a.recycling) AS recycling,
|
||||
SUM(a.disposal) AS disposal,
|
||||
SUM(a.sales) AS sales,
|
||||
SUM(a.payment_amount) AS payment_amount
|
||||
FROM {$fg['bakery_inventory_table']} AS a
|
||||
LEFT JOIN {$fg['bakery_product_table']} AS b
|
||||
ON a.barcode = b.barcode
|
||||
WHERE b.used = 1
|
||||
AND a.date BETWEEN '{$start_date}' AND '{$end_date}'
|
||||
{$search_sql}
|
||||
GROUP BY a.barcode
|
||||
ORDER BY {$ord_by}";
|
||||
|
||||
error_log($query);
|
||||
|
||||
$result = sql_query($query);
|
||||
$R = array();
|
||||
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$R[] = $row;
|
||||
}
|
||||
|
||||
return $R;
|
||||
}
|
||||
|
||||
// 기간별 합계 수량 구하기
|
||||
function getBakeryInvenSumPeriod($start_date, $end_date, $searchWord = "") {
|
||||
global $fg;
|
||||
|
||||
$search_sql = "";
|
||||
if ($searchWord !== "") {
|
||||
$searchWord = sql_real_escape_string($searchWord);
|
||||
$search_sql = "AND b.product_name LIKE '%{$searchWord}%'";
|
||||
}
|
||||
|
||||
$query = "SELECT
|
||||
SUM(a.production) AS t_production,
|
||||
SUM(a.inhouse_use) AS t_inhouse_use,
|
||||
SUM(a.recycling) AS t_recycling,
|
||||
SUM(a.disposal) AS t_disposal,
|
||||
SUM(a.sales) AS t_sales,
|
||||
SUM(a.payment_amount) AS t_payment_amount
|
||||
FROM {$fg['bakery_inventory_table']} AS a
|
||||
LEFT JOIN {$fg['bakery_product_table']} AS b
|
||||
ON a.barcode = b.barcode
|
||||
WHERE b.used = 1
|
||||
AND a.date BETWEEN '{$start_date}' AND '{$end_date}'
|
||||
{$search_sql}";
|
||||
|
||||
error_log($query);
|
||||
|
||||
return sql_fetch($query); // 결과 없으면 false 반환
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 전체 품명 불러오기
|
||||
function getBakeryProductList($ord_by = "ASC") {
|
||||
global $fg;
|
||||
@ -329,6 +399,21 @@ function get_total_count($db_name) {
|
||||
return $R;
|
||||
}
|
||||
|
||||
// 사용 중인(used=1) 품목 수 구하기
|
||||
function cntUsedBakeryItems() {
|
||||
global $fg;
|
||||
|
||||
$query = "SELECT COUNT(*) AS cnt FROM {$fg['bakery_product_table']} WHERE used = 1";
|
||||
|
||||
error_log($query);
|
||||
|
||||
$result = sql_fetch($query);
|
||||
$result = $result['cnt'];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// 어제자 최종재고 불러오기
|
||||
function getPrevStock($date, $barcode) {
|
||||
global $fg;
|
||||
|
||||
Reference in New Issue
Block a user