아파트단지 엑셀업로드추가
This commit is contained in:
@@ -61,6 +61,7 @@ $routes->group('article', ['namespace' => 'App\Controllers\Article'], function (
|
|||||||
$routes->post('apt/chgAptVideoTarget', 'Apt::chgAptVideoTarget');
|
$routes->post('apt/chgAptVideoTarget', 'Apt::chgAptVideoTarget');
|
||||||
$routes->post('apt/chkTakeAptPhotoCnt', 'Apt::chkTakeAptPhotoCnt');
|
$routes->post('apt/chkTakeAptPhotoCnt', 'Apt::chkTakeAptPhotoCnt');
|
||||||
$routes->get('apt/excel', 'Apt::excel');
|
$routes->get('apt/excel', 'Apt::excel');
|
||||||
|
$routes->post('apt/uploadExcel', 'Apt::uploadExcel');
|
||||||
|
|
||||||
/** API - 아파트단지 상세 */
|
/** API - 아파트단지 상세 */
|
||||||
$routes->post('apt/saveKeeper', 'Apt::saveKeeper');
|
$routes->post('apt/saveKeeper', 'Apt::saveKeeper');
|
||||||
|
|||||||
@@ -267,6 +267,63 @@ class Apt extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 엑셀 업로드
|
||||||
|
public function uploadExcel()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$payload = $this->request->getJSON(true);
|
||||||
|
$datas = $payload['datas'] ?? null;
|
||||||
|
|
||||||
|
if (count($datas) === 0) {
|
||||||
|
return $this->response->setJSON([
|
||||||
|
'code' => '9',
|
||||||
|
'msg' => "데이터 없음",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($datas as $data) {
|
||||||
|
$rdate = date("Y-m-d H:i:s");
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'row_no' => $data[0],
|
||||||
|
'hscp_no' => $data[1],
|
||||||
|
'uni_hscp_no' => $data[2],
|
||||||
|
'region_cd' => $data[3],
|
||||||
|
'addr' => $data[4],
|
||||||
|
'addr2' => $data[5],
|
||||||
|
'apt_cate_nm' => $data[6],
|
||||||
|
'rcpt_hscp_nm' => $data[7],
|
||||||
|
'move_ym' => $data[8],
|
||||||
|
'households_cnt' => $data[9],
|
||||||
|
'dong_cnt' => $data[10],
|
||||||
|
'pyeong_cnt' => $data[11],
|
||||||
|
'dongho' => $data[12],
|
||||||
|
'use_yn' => $data[13],
|
||||||
|
'rcpt_x' => $data[14],
|
||||||
|
'rcpt_y' => $data[15],
|
||||||
|
'pho_exept_yn' => $data[16],
|
||||||
|
'rdate' => $rdate,
|
||||||
|
];
|
||||||
|
|
||||||
|
// INSERT apt_receipt, apt_result
|
||||||
|
$this->aptModel->saveExcelUploadData($params);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response->setJSON([
|
||||||
|
'code' => '0',
|
||||||
|
'msg' => 'success'
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->response->setJSON([
|
||||||
|
'code' => '9',
|
||||||
|
'msg' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 엑셀 다운로드
|
// 엑셀 다운로드
|
||||||
public function excel()
|
public function excel()
|
||||||
|
|||||||
@@ -683,6 +683,77 @@ class AptModel extends Model
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 엑셀업로드 저장
|
||||||
|
public function saveExcelUploadData($params)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->db->transStart();
|
||||||
|
|
||||||
|
$builder = $this->db->table('apt_receipt');
|
||||||
|
$res = $builder->insert($params);
|
||||||
|
|
||||||
|
if ($res === false) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'msg' => "단지코드 : {$params['hscp_no']} 저장실패",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$rcpt_no = $this->db->insertID();
|
||||||
|
|
||||||
|
$params2 = [
|
||||||
|
'rcpt_no' => $rcpt_no,
|
||||||
|
'hscp_no' => $params['hscp_no'],
|
||||||
|
'region_cd' => $params['region_cd'],
|
||||||
|
'charger' => '',
|
||||||
|
'dept_sq' => '',
|
||||||
|
'addr' => $params['addr'],
|
||||||
|
'addr2' => $params['addr2'],
|
||||||
|
'rcpt_hscp_nm' => $params['rcpt_hscp_nm'],
|
||||||
|
'rcpt_x' => $params['rcpt_x'],
|
||||||
|
'rcpt_y' => $params['rcpt_y'],
|
||||||
|
'move_ym' => $params['move_ym'],
|
||||||
|
'households_cnt' => $params['households_cnt'],
|
||||||
|
'dong_cnt' => $params['dong_cnt'],
|
||||||
|
'apt_cate_nm' => $params['apt_cate_nm'],
|
||||||
|
'apt_step' => 'S01',
|
||||||
|
'check_yn' => 'N',
|
||||||
|
'resend_yn' => 'N',
|
||||||
|
'memo' => '',
|
||||||
|
'pho_up_yn' => 'N',
|
||||||
|
'vdo_up_ynx' => 'N',
|
||||||
|
'vdo_up_tm' => NULL,
|
||||||
|
'video_target' => 'N',
|
||||||
|
'not_vdo_reson' => '',
|
||||||
|
'note' => '',
|
||||||
|
'not_vdo_tm' => NULL,
|
||||||
|
'check_tm' => NULL,
|
||||||
|
'write_complete_yn' => 'N',
|
||||||
|
'write_complete_tm' => NULL,
|
||||||
|
'all_no_pho' => NULL,
|
||||||
|
'syncid' => '',
|
||||||
|
'sync_comp' => NULL,
|
||||||
|
'sync_wait_cnt' => '0'
|
||||||
|
];
|
||||||
|
|
||||||
|
$builder = $this->db->table('apt_result');
|
||||||
|
$res = $builder->insert($params2);
|
||||||
|
|
||||||
|
if ($res === false) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'msg' => "단지코드 : {$params['hscp_no']} 저장실패",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->transComplete();
|
||||||
|
|
||||||
|
// 성공
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// 엑셀 다운로드
|
// 엑셀 다운로드
|
||||||
public function getExcelList($data)
|
public function getExcelList($data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,15 @@
|
|||||||
background-color: #ff0000 !important;
|
background-color: #ff0000 !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#excelList.dataTable {
|
||||||
|
width: max-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.dataTable td,
|
||||||
|
table.dataTable th {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<h1>아파트단지 DB구축 현황</h1>
|
<h1>아파트단지 DB구축 현황</h1>
|
||||||
@@ -325,6 +334,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" id="excel-upload">
|
||||||
|
<i class="fa fa-fw" aria-hidden="true" title="file-excel-o"></i> 엑셀업로드
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm btn-outline-success" id="excel-download">
|
<button class="btn btn-sm btn-outline-success" id="excel-download">
|
||||||
<i class="fa fa-fw" aria-hidden="true" title="file-excel-o"></i> 엑셀다운로드
|
<i class="fa fa-fw" aria-hidden="true" title="file-excel-o"></i> 엑셀다운로드
|
||||||
</button>
|
</button>
|
||||||
@@ -375,6 +388,72 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="excelModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-xl">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">엑셀 업로드</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<!-- 업로드 영역 -->
|
||||||
|
<div class="d-flex align-items-center gap-3 mb-3">
|
||||||
|
<input type="file" id="excel" class="form-control" accept=".xlsx,.xls,.csv"
|
||||||
|
style="max-width: 320px;">
|
||||||
|
|
||||||
|
<a href="/plugin/sample/sample.xlsx" download="아파트단지_샘플양식" class="btn btn-outline-secondary btn-sm">
|
||||||
|
샘플양식 다운로드
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 안내 문구 -->
|
||||||
|
<div class="alert alert-light py-2 mb-3">
|
||||||
|
<ul class="mb-0 small">
|
||||||
|
<li>엑셀 첫 행은 헤더로 인식됩니다.</li>
|
||||||
|
<li>컬럼 순서 및 개수는 샘플양식과 동일해야 합니다.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 테이블 영역 -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table id="excelList"
|
||||||
|
class="table table-sm table-hover table-striped table-bordered align-middle text-center mb-0">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>줄번호</th>
|
||||||
|
<th>단지코드</th>
|
||||||
|
<th>통합단지코드</th>
|
||||||
|
<th>법정동코드</th>
|
||||||
|
<th>주소</th>
|
||||||
|
<th>상세주소</th>
|
||||||
|
<th>단지유형</th>
|
||||||
|
<th>단지명</th>
|
||||||
|
<th>입주년월</th>
|
||||||
|
<th>총세대수</th>
|
||||||
|
<th>총동수</th>
|
||||||
|
<th>평형수</th>
|
||||||
|
<th>동호수</th>
|
||||||
|
<th>사용여부</th>
|
||||||
|
<th>경도</th>
|
||||||
|
<th>위도</th>
|
||||||
|
<th>사진촬영제외</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="btnUpload">저장</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<?= $this->endSection() ?>
|
<?= $this->endSection() ?>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
|
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
|
||||||
@@ -389,7 +468,7 @@
|
|||||||
const teamArr = <?= json_encode($team, JSON_UNESCAPED_UNICODE); ?>;
|
const teamArr = <?= json_encode($team, JSON_UNESCAPED_UNICODE); ?>;
|
||||||
const userArr = <?= json_encode($user, JSON_UNESCAPED_UNICODE); ?>;
|
const userArr = <?= json_encode($user, JSON_UNESCAPED_UNICODE); ?>;
|
||||||
|
|
||||||
var table;
|
var table, excelTbl;
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
@@ -677,6 +756,136 @@
|
|||||||
table.ajax.reload()
|
table.ajax.reload()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 엑셀업로드 click
|
||||||
|
$("#excel-upload").on("click", function () {
|
||||||
|
$("#excel").val("");
|
||||||
|
$("#excelList").DataTable().clear().destroy();
|
||||||
|
|
||||||
|
$("#excelModal").modal("show");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 엑셀 업로드
|
||||||
|
$("#excel").on("change", async function () {
|
||||||
|
const file = this.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
const bodyRows = await readExcelBodyOnly(file);
|
||||||
|
renderExcelDataTable(bodyRows);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 엑셀 업로드 저장
|
||||||
|
$("#btnUpload").on("click", function () {
|
||||||
|
|
||||||
|
const dt = $("#excelList").DataTable();
|
||||||
|
|
||||||
|
// 전체 row 데이터 (모든 페이지)
|
||||||
|
const excelData = dt.rows().data().toArray();
|
||||||
|
|
||||||
|
if (excelData.length === 0) {
|
||||||
|
Swal.fire({
|
||||||
|
title: "업로드할 데이터가 없습니다.",
|
||||||
|
icon: "warning"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = [
|
||||||
|
"줄번호", "단지코드", "통합단지코드", "법정동코드", "주소"
|
||||||
|
, "상세주소", "단지유형", "단지명"
|
||||||
|
, "입주년월", "총세대수", "총동수", "평형수", "동호수"
|
||||||
|
, "사용여부", "경도", "위도", "사진촬영제외"
|
||||||
|
];
|
||||||
|
|
||||||
|
const errors = [];
|
||||||
|
let hasError = false;
|
||||||
|
for (let rowIdx = 0; rowIdx < excelData.length; rowIdx++) {
|
||||||
|
const row = excelData[rowIdx];
|
||||||
|
|
||||||
|
for (let colIdx = 0; colIdx < headers.length; colIdx++) {
|
||||||
|
const colName = headers[colIdx];
|
||||||
|
const val = row[colIdx];
|
||||||
|
|
||||||
|
|
||||||
|
if (val === undefined || val === null || String(val).trim() === "") {
|
||||||
|
Swal.fire({
|
||||||
|
title: `${rowIdx + 1}행 ${colName} 데이터 누락`,
|
||||||
|
icon: "warning"
|
||||||
|
});
|
||||||
|
|
||||||
|
hasError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasError) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasError) return;
|
||||||
|
|
||||||
|
swal.fire({
|
||||||
|
text: "저장 하시겠습니까?",
|
||||||
|
type: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: "예",
|
||||||
|
cancelButtonText: "아니오",
|
||||||
|
closeOnConfirm: false,
|
||||||
|
closeOnCancel: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
$.ajax({
|
||||||
|
url: '/article/apt/uploadExcel',
|
||||||
|
contentType: 'application/json;charset=UTF-8',
|
||||||
|
method: 'POST',
|
||||||
|
data: JSON.stringify({ datas: excelData }),
|
||||||
|
beforeSend: function () {
|
||||||
|
blockUI.blockPage({
|
||||||
|
message: tpl
|
||||||
|
})
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
blockUI.unblockPage()
|
||||||
|
},
|
||||||
|
error: function (xhr, error, thrown) {
|
||||||
|
blockUI.unblockPage()
|
||||||
|
var msg = "";
|
||||||
|
if (xhr.responseText != null) {
|
||||||
|
msg = xhr.responseText
|
||||||
|
} else {
|
||||||
|
msg = "잠시후 다시 시도해 주세요."
|
||||||
|
}
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: msg,
|
||||||
|
icon: "error"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
success: function (result) {
|
||||||
|
|
||||||
|
if (result.code == '0') {
|
||||||
|
$("#btnSearch").trigger('click')
|
||||||
|
$("#excelModal").modal("hide")
|
||||||
|
Swal.fire({
|
||||||
|
title: '정상 처리되었습니다.',
|
||||||
|
icon: "success"
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: result.msg,
|
||||||
|
icon: "error"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// 엑셀 다운로드 click
|
// 엑셀 다운로드 click
|
||||||
$("#excel-download").on("click", function () {
|
$("#excel-download").on("click", function () {
|
||||||
@@ -817,7 +1026,7 @@
|
|||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: msg,
|
title: msg,
|
||||||
icon: "error"
|
icon: "error"
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
success: function (result) {
|
success: function (result) {
|
||||||
|
|
||||||
@@ -940,6 +1149,48 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
async function readExcelBodyOnly(file) {
|
||||||
|
const data = await file.arrayBuffer();
|
||||||
|
const wb = XLSX.read(data, { type: "array" });
|
||||||
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||||
|
|
||||||
|
const rows2d = XLSX.utils.sheet_to_json(ws, {
|
||||||
|
header: 1,
|
||||||
|
defval: "",
|
||||||
|
raw: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 첫 줄(엑셀 헤더) 제거 + 빈 행 제거
|
||||||
|
return rows2d
|
||||||
|
.slice(1)
|
||||||
|
.filter(r => r.some(v => String(v).trim() !== ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderExcelDataTable(data2d) {
|
||||||
|
// 이미 DataTable이 있으면 파괴 후 재생성(컬럼 구조가 바뀔 수 있으니)
|
||||||
|
if ($.fn.DataTable.isDataTable("#excelList")) {
|
||||||
|
$("#excelList").DataTable().clear().destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
excelTbl = $("#excelList").DataTable({
|
||||||
|
language: lang_kor,
|
||||||
|
columnDefs: [
|
||||||
|
{ className: 'text-center dt-nowrap', targets: '_all' },
|
||||||
|
],
|
||||||
|
data: data2d,
|
||||||
|
searching: false,
|
||||||
|
ordering: false,
|
||||||
|
destroy: true,
|
||||||
|
deferRender: true,
|
||||||
|
pageLength: 10,
|
||||||
|
lengthMenu: [10, 25, 50, 100],
|
||||||
|
scrollX: true,
|
||||||
|
autoWidth: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function hscp_no_enter(event) {
|
function hscp_no_enter(event) {
|
||||||
if (event.keyCode == 13) {
|
if (event.keyCode == 13) {
|
||||||
table.ajax.reload()
|
table.ajax.reload()
|
||||||
@@ -1055,10 +1306,6 @@
|
|||||||
|
|
||||||
// 단지정보저장
|
// 단지정보저장
|
||||||
function fn_save_info(row, idx) {
|
function fn_save_info(row, idx) {
|
||||||
console.log('+++')
|
|
||||||
console.log(row)
|
|
||||||
console.log('idx ?? ' + idx)
|
|
||||||
console.log('+++')
|
|
||||||
|
|
||||||
const target = $("#video_target_" + idx).val();
|
const target = $("#video_target_" + idx).val();
|
||||||
console.log(target)
|
console.log(target)
|
||||||
|
|||||||
BIN
public/plugin/sample/sample.xlsx
Normal file
BIN
public/plugin/sample/sample.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user