Files
sam-kd/0_dev_comment.php
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

2898 lines
126 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(경동기업, 주일기업)
한국사람이고, 한국어를 제일 잘한다. 위의 두개의 회사의 업무를 처리하는 프로그램을 개발하고 있다.
이제부터 코드를 만들거나 수정하는 일을 것이다.
웹사이트를 개발하고 관리하고 있다.
mysql, php, javascript로 대부분을 만들었다.
오류에 대한 언급을 하면, 해당오류에 대한 코드만 보여주면 좋겠다.
이제부터 코드에 관련된 내용을 물어볼 것이니, 최선을 다해 답변해줘.
모든 script에 대한 선언은 이미 되어 있는 상태다.
예를 들어 부트스트랩, 제이쿼리 전체 코드에 필요한 CDN 선언은 load_header.php 파일에 선언되어있다.
발주부터 출하, 재고관리, 인사관리 등등 전산시스템을 구축하고 있다.
회계부분도 매출, 출고통계, 로트번호관리 여러가지 종합적인 프로그램을 진행중에 있다.
지난 6개월간의 GPT와 협업해서 많은 코드를 만들었다. 하지만, 추가적인 요구사항들이 있어서 계속 수정할 것이다.
이제부터 개발과 관련된 코드에 대해 물어볼 것이다.
GPT의 모든 정보를 신뢰한다. 고마워. GPT 선생님! 추가적인 질문을 시작한다.
오류에 대한 언급을 하면, 해당오류에 대한 코드만 보여주면 좋겠다.
이제부터 코드에 관련된 내용을 물어볼 것이니, 최선을 다해 답변해줘.
이제부터 내가 질문하는 것에는 전체코드 생성이라는 말이 없으면 부분적으로 내가 요청한 부분만 대답해줘. 알겠지?
08/01 질문내용
위의 파일은 statistics.php이다. 코드에는 스크린, 스라트의 제조통계를 화면에 보여주는 것인데,
내가 만들고 싶은 것은 두개의 합산된 것도 유지하면서,
col-sm-4 활용해서 첫번째 col-sm-6에는 스크린의 차트가 보이고
옆의 col-sm-4에는 스라트
그리고 마지막 col-sm-4에는 두개의 합친 지금의 코드를 보여주는 코드로 수정하고자 한다.
가독성을 높이고, 경영자에게 좋은 정보를 제공하기 위해서이다.
아래의 코드로 충분히 이렇게 수정가능한 같다. 코드를 만들고 오류가 없지는 체크까지 부탁한다.
chandj의 DB 내용중 output 테이블은 아래의 형태를 갖고 있다.
num: 고유 번호
con_num: 공사 번호
is_deleted: 삭제 여부
outdate: 출고일
indate: 접수일
outworkplace: 출고 작업장
orderman: 발주자
outputplace: 수신처 주소
receiver: 수신자
phone: 연락처
comment: 비고
file_name_0 ~ file_name_4: 파일명
file_copied_0 ~ file_copied_4: 파일 경로
root: 회사 구분
steel: 절곡 발주 여부
motor: 모터 발주 여부
delivery: 배송 방식
regist_state: 등록 상태
bend_state: 절곡 상태
motor_state: 모터 상태
searchtag: 검색 태그
update_log: 업데이트 로그
screen: 스크린 정보
screen_state: 스크린 상태
screen_su: 스크린 수량
screen_m2: 스크린 면적 ()
screenlist: 스크린 목록
slatlist: 슬랫 목록
slat: 슬랫 정보
slat_state: 슬랫 상태
slat_su: 슬랫 수량
slat_m2: 슬랫 면적 ()
updatecomment: 수정 사항 기록
테이블의 구조를 이해할 있겠니? 컬럼의 역할도 마찬가지로 기억해줘.
모든 내용을 output 테이블이라고 칭하고 싶다.
fetch_deadlineDate.php 내용은 아래와 같다.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
$month = $_POST['month'];
$year = $_POST['year'];
$data_order = array();
// 출고일 outputdate 기준
try {
$stmh = $pdo->query("SELECT pjname, deadlineDate, secondord, deliverymethod, num, outputDate, status, hallDoorList, carDoorList, carWallList, etcList
FROM " . $DB . ".order
WHERE is_deleted IS NULL
AND MONTH(deadlineDate) = $month
AND YEAR(deadlineDate) = $year");
while($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
array_push($data_order, $row);
}
$data_order = array(
"data_order" => $data_order,
);
echo(json_encode($data_order, JSON_UNESCAPED_UNICODE));
} catch (PDOException $Exception) {
print "오류: ".$Exception->getMessage();
}
?>
fetch_outputDate.php 내용은 아래와 같다.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
$month = $_POST['month'];
$year = $_POST['year'];
$data_order = array();
// 출고일 deadlineDate 기준
try {
$stmh = $pdo->query("SELECT pjname, deadlineDate, secondord, deliverymethod, num, outputDate, status, hallDoorList, carDoorList, carWallList, etcList
FROM " . $DB . ".order
WHERE is_deleted IS NULL
AND MONTH(deadlineDate) = $month
AND YEAR(deadlineDate) = $year");
while($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
array_push($data_order, $row);
}
$data_order = array(
"data_order" => $data_order,
);
echo(json_encode($data_order, JSON_UNESCAPED_UNICODE));
} catch (PDOException $Exception) {
print "오류: ".$Exception->getMessage();
}
?>
위의 코드에는 공통사항이 많다. 내가 언급한 output 테이블의 요소들로 바꾸고 두개의 파일을 하나의 파일로 만들고 전달하는 인자에 따라 처리하면 될 것 같다.
fetch_date.php 파일로 통합하고 output테이블의 컬럼요소에 맞게 수정해줘.
아래의 파일은 month_schedule.php 파일인데, 한산엘테크 웹사이트에서 가져온 코드이다.
output 테이블에 맞게 모든 것을 수정해야 하는데,
방금 만든 fetch_date는 여기서 두개의 파일호출에 적용하면 된다.
스크린의 면적을 누적하고, 스라트의 면적을 누적하는 코드가 있어야 한다. 이미 정의는 되어있다.
################################## 주일기업
(주일기업)
난 한국사람이고, 한국어를 제일 잘한다. 위의 두개의 회사의 업무를 처리하는 프로그램을 개발하고 있다.
이제부터 코드를 만들거나 수정하는 일을 할 것이다.
웹사이트를 개발하고 관리하고 있다.
mysql, php, javascript로 대부분을 만들었다.
오류에 대한 언급을 하면, 그 해당오류에 대한 코드만 보여주면 좋겠다.
이제부터 코드에 관련된 내용을 물어볼 것이니, 최선을 다해 답변해줘.
모든 script에 대한 선언은 이미 되어 있는 상태다.
예를 들어 부트스트랩, 제이쿼리 등 전체 코드에 필요한 CDN 선언은 load_header.php 파일에 선언되어있다.
발주부터 출하, 재고관리, 인사관리 등등 전산시스템을 구축하고 있다.
회계부분도 매출, 출고통계, 로트번호관리 등 여러가지 종합적인 프로그램을 진행중에 있다.
지난 6개월간의 GPT와 협업해서 많은 코드를 만들었다. 하지만, 추가적인 요구사항들이 있어서 계속 수정할 것이다.
이제부터 이 개발과 관련된 코드에 대해 물어볼 것이다.
난 GPT의 모든 정보를 신뢰한다. 고마워. GPT 선생님! 추가적인 질문을 시작한다.
오류에 대한 언급을 하면, 그 해당오류에 대한 코드만 보여주면 좋겠다.
이제부터 코드에 관련된 내용을 물어볼 것이니, 최선을 다해 답변해줘.
이제부터 내가 질문하는 것에는 전체코드 생성이라는 말이 없으면 부분적으로 내가 요청한 부분만 대답해줘. 알겠지?
공사수주 리스트의 자료를 수정하려고 한다.
work 테이블의 컬럼은 아래와 같이 구성되어있다.
기본 정보:
num: 기본 키로, 자동 증가하는 정수값입니다.
is_deleted: 삭제 여부를 나타내는 플래그입니다.
work_state: 작업의 상태를 나타내는 문자열입니다.
프로젝트 및 고객 정보:
id, name, nick: 고객 또는 담당자에 대한 식별자 및 이름 정보입니다.
subject: 프로젝트나 작업의 제목입니다.
content, condate1, condate2: 프로젝트나 작업의 상세 내용 및 날짜 정보입니다.
regist_day: 등록 날짜를 기록합니다.
파일 및 문서 관련 정보:
file_name_0 ~ file_name_4: 관련된 파일의 이름을 저장합니다.
file_copied_0 ~ file_copied_4: 파일 복사본의 이름을 저장합니다.
금전 및 청구 관련 정보:
estimate1 ~ estimate4: 견적 관련 정보입니다.
bill1 ~ bill6: 청구서 관련 정보입니다.
deposit1 ~ deposit6: 입금 관련 정보입니다.
receivable: 미수금 관련 정보입니다.
claimamount1 ~ claimamount7, claimbalance1 ~ claimbalance7: 청구금액 및 잔액 정보입니다.
작업 진행 관련 정보:
worklist: 작업 리스트를 저장합니다.
workday, endworkday: 작업 시작일과 종료일을 나타냅니다.
worker, cablestaff, asman: 작업자, 케이블 스태프, A/S 담당자 정보를 포함합니다.
A/S 관련 정보:
asday, asendday, asproday: A/S 관련 날짜 정보입니다.
aslist, asresult, ashistory: A/S 관련 작업 리스트, 결과, 이력 정보를 저장합니다.
청구 및 클레임 정보:
claimperson, claimtel: 클레임을 제기한 사람과 그 연락처입니다.
claimdate1 ~ claimdate6: 클레임 발생일을 기록합니다.
claimfix1 ~ claimfix7: 클레임 수정 관련 정보입니다.
기타 정보:
comment, searchtag, update_log: 코멘트, 검색 태그, 업데이트 로그와 같은 부가 정보를 기록합니다.
## 공급가액,세액 자동만들기 프롬프트
위의 코드에서 4개의 estimate 관련 내용을 한행에 td요소를 8개로 나눠서 날짜부터 금액을 표현하는 것까지 표현하고,
파일첨부는 colspan="1", colspan="7"로 구분해서 사용하자.
그리고 위의 요소는 페이지를 오픈할때, 콤마를 제거하고, 숫자 3자리마다 콤마를 찍어주는 로직을 넣어준다.
그리고, input이 발생할때 위의 요소는 세액은 readonly로 놓고, 공급가액을 넣으면 세액과 금액을 자동으로 계산하고, 반대로 금액을 넣으면 역으로 공급가액과 세액을 계산하는 동적 페이지로 구조를 자바스크립트로 만든다.
$bill6_vat = isset($row['bill6_vat']) ? $row['bill6_vat'] : '';
위의 형식으로 만들어줘.
$bill6_vat = isset($_REQUEST['bill6_vat']) ? $_REQUEST['bill6_vat'] : '';
위의 형식으로 만들어줘.
1. 위의 코드를 $bill_issueDate1, $bill_issueDate2 ... 이런식으로 표현
2. 위의 코드를 bill_issueDate1, bill_issueDate2 ... 이런식으로 표현
3. 위의 코드를 bill_issueDate1=?, bill_issueDate2=? ... 이런식으로 표현
위의 3개를 만족하는 모양 형성해줘.
#컬럼제작
만든 컬럼을 적용해서 하는데, 혹시 등록일자는 기본으로 있어야 할 것 같아. 등록일자(registedate) , is_deleted, updatelog, searchtag는 항상 기본으로 들어가야 한다. 모든 table에 있어야 한다.
이에 따라 테이블에 4개의 컬럼을 추가하는 slq문장도 필요한다.
위의 코드에서 tbody의 tr요소를 4개 만들건데,
name은 위의 tr요소 행 숫자만큼 col1부터 col13까지 [] 형식으로 만들어줘.
아니다. 현재 php와 mysql의 버전이 json 타입으로 저장할수 없기에 text로 저장하는 대신 json으로 encode, decode해서 사용한다.
위의 코드는 수정되어야 한다. 일단 col18개까지 늘어야 한다.
엑셀은 D열부터 col1에 해당된다. 엑셀수식을 d5는 col1과 같은 것이다. 이렇게 해줘.
1) col7은 col3 * col4 으로 계산한다.
2) col8은 col5*col6*col7 로 계산한다.
3) col10 = col9* 1.2
4) col11 = col8 * col10
5) col12 는 엑셀수식 =ROUND(N5,-3) 이것을 이용한다. N5는 col11이다.
6) col14 는 엑셀수식 =ROUND(J5*P5,-3)
7) col15 , 엑셀수식 =O5+Q5
8) col16 = 엑셀수식 =R5/J5
9) col17 = 엑셀수식 =ROUND(S5,-3)
10) col18 = 엑셀수식 =R5/K5
이렇게 수식을 적용해줘.
위의 코드는 수정되어야 한다. 일단 col20개까지 늘어야 한다.
엑셀은 D열부터 col1에 해당된다. 엑셀수식을 d5는 col1과 같은 것이다. 이렇게 해줘.
1) col6은 =(col7*col8*col9*col9)/1000
2) col9은 col5/2
3) col12 = col6 * col11
4) col11 = col8 * col10
5) col13는 col2 * col3 * col12
6) col15는 col13 * col14
7) col15은 엑셀수식 =O5+Q5
8) col18은 =(col15/col2/col3)+col7
9) col19= 엑셀수식 math.round(col18*1.2*1000)/1000
10) col20= 엑셀수식 math.round(col18/3*1000)/1000
이렇게 수식을 적용해줘.
<tr>
<th class="align-middle">+ - Copy</th>
<th class="align-middle">품목</th>
<th class="align-middle">두께(T)</th>
<th class="align-middle">폭</th>
<th class="align-middle">길이(M)</th>
<th class="align-middle">가공비</th>
<th class="align-middle">입고가</th>
<th class="align-middle">원가합계</th>
<th class="align-middle bg-danger text-white">판매가 15%</th>
</tr>
위의 price_screenplate의 테이블을 아래의 th요소에 맞게 만들어야 한다.
function addRow(tableBody, rowData) {
var newRow = $('<tr>');
// + / - 버튼 추가
newRow.append('<td class="text-center" style="width:80px;">' +
'<div class="d-flex justify-content-center mt-1">' +
'<button type="button" class="btn btn-primary btn-sm viewNoBtn add-row me-1" data-table="' + tableBody.closest('table').attr('id') + '">+</button>' +
'<button type="button" class="btn btn-danger btn-sm viewNoBtn remove-row ms-2 me-2">-</button>' +
'<button type="button" class="btn btn-success btn-sm viewNoBtn copy-row"><i class="bi bi-copy"></i></button>' +
'</div></td>');
// col1부터 col8까지 채우기
for (let i = 1; i <= 8; i++) {
let colValue = rowData['col' + i] || ''; // 값이 없으면 빈 문자열 사용
// 첫 번째 열 제외, 모든 열에 텍스트 박스를 추가
newRow.append('<td><input type="text" name="col' + i + '[]" value="' + colValue + '" class="form-control text-center number-format col' + i + '" autocomplete="off"></td>');
}
// 새 행을 테이블에 추가
tableBody.append(newRow);
// 숫자 필드에 3자리마다 콤마 추가 (소수점 입력 가능)
newRow.find('.number-format').on('input change', function() {
let value = $(this).val().replace(/,/g, ''); // 기존의 콤마를 제거
// 소수점 포함 숫자 검사
if (!isNaN(value) && value !== '') {
// 정수와 소수 부분 분리
let parts = value.split('.');
parts[0] = Number(parts[0]).toLocaleString('en'); // 3자리마다 콤마 추가
// 소수점이 있는 경우
let formattedValue = parts.join('.');
$(this).val(formattedValue);
}
// 행 계산 함수 호출
calculateRow(newRow);
});
// 처음 로드될 때도 자동 계산 적용
calculateRow(newRow);
}
function calculateRow(row) {
// 소수점 자릿수와 콤마를 포함한 숫자 형식 변환 함수
function formatNumber(value, decimalPlaces) {
// value를 소수점 자릿수에 맞게 고정
let fixedValue = parseFloat(value).toFixed(decimalPlaces);
// 정수 부분과 소수 부분으로 분리
let [integerPart, decimalPart] = fixedValue.split('.');
// 정수 부분에만 콤마 추가
integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 소수점 이하가 존재하고 0보다 큰 경우, 정수 부분과 결합하여 반환
if (decimalPart && parseInt(decimalPart) > 0) {
return `${integerPart}.${decimalPart}`;
} else {
return integerPart; // 소수점 이하가 없거나 0인 경우 정수만 반환
}
}
// col1부터 col8까지의 값을 가져오기
const col6 = parseFloat(row.find('.col6').val().replace(/,/g, '')) || 0;
const col7 = parseFloat(row.find('.col7').val().replace(/,/g, '')) || 0;
const col8 = parseFloat(row.find('.col8').val().replace(/,/g, '')) || 0;
// 판매가 15% (col9) 계산: col8에 1.15를 곱한 값
const col9 = col8 * 1.15;
if (!isNaN(col9)) {
row.find('.col9').val(formatNumber(col9, 0));
}
// 콤마 및 소수점 표시 설정
if (!isNaN(col6)) {
row.find('.col6').val(formatNumber(col6, 2));
}
if (!isNaN(col7)) {
row.find('.col7').val(formatNumber(col7, 2));
}
if (!isNaN(col8)) {
row.find('.col8').val(formatNumber(col8, 0));
}
}
위의 코드를 col1부터 col8까지 만들어야하는데,
숫자 3자리마다 콤마 형태로 나오게 해줘.
자동계산은 원가합계에 해당되는 col7과, col8이 해당되고 이 col7,col8은 수식이 적용되어야 한다.
col7은 = col5 + col6
col8은 =ROUND(col7*1.2,-3)
#연기차단재 관련 생성 프롬프트
<tr>
<th class="align-middle">+ - Copy</th>
<th class="align-middle">품목</th>
<th class="align-middle">용도</th>
<th class="align-middle">단위(롤)</th>
<th class="align-middle">길이(mm)</th>
<th class="align-middle">폭(mm)</th>
<th class="align-middle">용차</th>
<th class="align-middle">가공비</th>
<th class="align-middle">입고가</th>
<th class="align-middle">원가합계</th>
<th class="align-middle bg-danger text-white">판매가 15%</th>
<th class="align-middle">1롤/50M</th>
</tr>
위의 price_smokeban의 테이블을 아래의 th요소에 맞게 만들어야 한다.
(위의 코드는 참고용이다. 11개의 컬럼을 만들어야 하니까.)
위의 코드를 col1부터 col11까지 만들어야하는데,
숫자 3자리마다 콤마 형태로 나오게 해줘.
자동계산은 원가합계에 해당되는 col9과, col10, col11이 해당되고 이는 수식이 적용되어야 한다.
col9은 = col6/(10*50) + col7+ col8
col10은 =ROUND(col9 * 1.15,-3)
col11은 ==ROUND((col10*50)/(1200/50),-4)
function addRow(tableBody, rowData) {
var newRow = $('<tr>');
// + / - 버튼 추가
newRow.append('<td class="text-center" style="width:80px;">' +
'<div class="d-flex justify-content-center mt-1">' +
'<button type="button" class="btn btn-primary btn-sm viewNoBtn add-row me-1" data-table="' + tableBody.closest('table').attr('id') + '">+</button>' +
'<button type="button" class="btn btn-danger btn-sm viewNoBtn remove-row ms-2 me-2">-</button>' +
'<button type="button" class="btn btn-success btn-sm viewNoBtn copy-row"><i class="bi bi-copy"></i></button>' +
'</div></td>');
// col1부터 col8까지 채우기
for (let i = 1; i <= 8; i++) {
let colValue = rowData['col' + i] || ''; // 값이 없으면 빈 문자열 사용
// 첫 번째 열 제외, 모든 열에 텍스트 박스를 추가
newRow.append('<td><input type="text" name="col' + i + '[]" value="' + colValue + '" class="form-control text-center number-format col' + i + '" autocomplete="off"></td>');
}
// 새 행을 테이블에 추가
tableBody.append(newRow);
// 숫자 필드에 3자리마다 콤마 추가 (소수점 입력 가능)
newRow.find('.number-format').on('input change', function() {
let value = $(this).val().replace(/,/g, ''); // 기존의 콤마를 제거
// 소수점 포함 숫자 검사
if (!isNaN(value) && value !== '') {
// 정수와 소수 부분 분리
let parts = value.split('.');
parts[0] = Number(parts[0]).toLocaleString('en'); // 3자리마다 콤마 추가
// 소수점이 있는 경우
let formattedValue = parts.join('.');
$(this).val(formattedValue);
}
// 행 계산 함수 호출
calculateRow(newRow);
});
// 처음 로드될 때도 자동 계산 적용
calculateRow(newRow);
}
function calculateRow(row) {
// 소수점 자릿수와 콤마를 포함한 숫자 형식 변환 함수
function formatNumber(value, decimalPlaces) {
// value를 소수점 자릿수에 맞게 고정
let fixedValue = parseFloat(value).toFixed(decimalPlaces);
// 정수 부분과 소수 부분으로 분리
let [integerPart, decimalPart] = fixedValue.split('.');
// 정수 부분에만 콤마 추가
integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 소수점 이하가 존재하고 0보다 큰 경우, 정수 부분과 결합하여 반환
if (decimalPart && parseInt(decimalPart) > 0) {
return `${integerPart}.${decimalPart}`;
} else {
return integerPart; // 소수점 이하가 없거나 0인 경우 정수만 반환
}
}
// col1부터 col8까지의 값을 가져오기
const col6 = parseFloat(row.find('.col6').val().replace(/,/g, '')) || 0;
const col7 = parseFloat(row.find('.col7').val().replace(/,/g, '')) || 0;
const col8 = parseFloat(row.find('.col8').val().replace(/,/g, '')) || 0;
// 판매가 15% (col9) 계산: col8에 1.15를 곱한 값
const col9 = col8 * 1.15;
if (!isNaN(col9)) {
row.find('.col9').val(formatNumber(col9, 0));
}
// 콤마 및 소수점 표시 설정
if (!isNaN(col6)) {
row.find('.col6').val(formatNumber(col6, 2));
}
if (!isNaN(col7)) {
row.find('.col7').val(formatNumber(col7, 2));
}
if (!isNaN(col8)) {
row.find('.col8').val(formatNumber(col8, 0));
}
}
######## #개발자 컬럼보기 ########
위의 코드에서 $user_id=='pro'인 경우는 th행을 하나 더 만들건데,
일련번호를 부여해서 개발할때 보려고 한다.
th 2번째 열부터 1로 시작해서 66열까지 1,2,.... 66번까지 col과 비교하면서 개발을 하려고 개발자 아이디인 'pro'만 보이도록 코드를 수정해줘.
######단가 가져오기 fetch_price ##### 제작 프롬프트
단가를 가져오는 코드들을 fetch_price.php를 호출해서 가져오는 방식이면 좋겠다.
이를 호출할때 테이블명과 값을 전달하면 결과를 리턴하는 방식이면 좋겠다.
그러면 위의 9가지 단가들에 대해서 하나의 모듈을 사용하면 효과적일 것 같다.
물론 조건은 파라미터는 하나에서 여러개가 될 수 있다.
## json 저장 안됨 ##
$sql = "SELECT itemList FROM {$DB}.$tablename WHERE JSON_UNQUOTE(JSON_EXTRACT(itemList, '$.code')) IN ($placeholders) AND (is_deleted IS NULL OR is_deleted = 0)";
위의 코드는 잘못되었다.
php버전과 mysql에서 json을 지원하지 않는 버전을 사용한다.
text로 저장하고, encode, decode로 작업한다.
// 모터 부분
if(True) {
$data = [];
$counter = 0;
foreach ($decodedEstimateList as $item) {
if (isset($item['col5']) && !empty($item['col5'])) {
$counter++;
// 각 col 값을 배열에 추가합니다.
$row = [];
$row['col1'] = '2.2 <br> 모터';
$row['col2'] = $item['col3'] ?? ''; // 부호
$row['col3'] = $item['col5'] ?? ''; // 실리카
$row['col4'] = $item['col7'] ?? ''; // SUS
$row['col5'] = $item['col6'] ; // 벽마감표시
$row['col6'] = $item['col8']; // 오픈 가로
$row['col7'] = $item['col9']; // 오픈 세로
$row['col8'] = $item['col10']; // 제작 가로
$row['col9'] = $item['col11']; // 제작 세로
$row['col10'] = $item['col31']; // 케이스 500*380
// $data 배열에 행을 추가합니다.
$data[] = $row;
}
}
모터부분의 내용의 누계를 내려고 한다.
## 모터 150 부터 1000까지 개수 파악하는 프롬프트 ##
전체 col1~col12까지 배열은 필요없고 sum의 개념만 있으면 된다.
$item['col13']은 중량을 나타내는데
이 값에 따라 col1~col7까지 누적해야 한다.
col1의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
엑셀공식
=IF(AND(E8="스크린",BK8=4,M8<=150),1,IF(AND(E8="스크린",BK8=5,M8<=123),1,IF(AND(E8="스크린",BK8=6,M8<=104),1,0)))
col2의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(E8="스크린",BK8=4,M8>150,M8<=300),1,IF(AND(E8="스크린",BK8=5,M8>123,M8<=246),1,IF(AND(E8="스크린",BK8=6,M8>104,M8<=208),1,IF(AND(E8="철재",BK8=4,M8<=300),1,IF(AND(E8="철재",BK8=5,M8<=246),1,IF(AND(E8="철재",BK8=6,M8<=208),1,0))))))
col3의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(E8="스크린",BK8=4,M8>300,M8<=400),1,IF(AND(E8="스크린",BK8=5,M8>246,M8<=327),1,IF(AND(E8="스크린",BK8=6,M8>208,M8<=300),1,IF(AND(E8="철재",BK8=4,M8>300,M8<=400),1,IF(AND(E8="철재",BK8=5,M8>246,M8<=327),1,IF(AND(E8="철재",BK8=6,M8>208,M8<=277),1,0))))))
col4의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(E8="스크린",BK8=5,M8>327,M8<=500),1,IF(AND(E8="스크린",BK8=6,M8>300,M8<=424),1,IF(AND(E8="철재",BK8=5,M8>400,M8<=500),1,IF(AND(E8="철재",BK8=5,M8>327,M8<=500),1,IF(AND(E8="철재",BK8=6,M8>277,M8<=424),1,IF(AND(E8="철재",BK8=8,M8<=324),1,0))))))
col5의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(BK8=5,M8>500,M8<=600),1,IF(AND(BK8=6,M8>424,M8<=508),1,IF(AND(BK8=8,M8>324,M8<=388),1,0)))
col6의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(E8="철재",BK8=6,M8>600,M8<=800),1,IF(AND(E8="철재",BK8=6,M8>508,M8<=800),1,IF(AND(E8="철재",BK8=8,M8>388,M8<=611),1,0)))
col7의 값은 아래의 엑셀공식이다.
E8은 $item['col4']의 문자열앞에 두문자'KS'이면 '스크린'으로 인식
m8은 중량을 의미하는 $item['col13'];
bk8은 $item['col53'];
엑셀공식
=IF(AND(E8="철재",BK8=6,M8>800,M8<=1000),1,IF(AND(E8="철재",BK8=8,M8>611,M8<=1000),1,0))
col8의 값은 아래이다.
$item['col15']의 합
col9의 값은 값은 아래이다.
$item['col16']의 합
col10의 값은 값은 아래이다.
$item['col17']의 합
col11의 값은 값은 아래이다.
$item['col14']의 합
col12의 값은 값은 아래이다.
col11 * 4
## 스크린 발주서 절곡 부분 ##
// 절곡 부분
if(True) {
$data = [];
foreach ($decodedEstimateList as $item) {
}
echo '<div class="d-flex align-items-center justify-content-center m-1">';
echo '<table class="table" style="border-collapse: collapse;">';
echo '<thead>';
echo '<tr>';
echo '<th rowspan="9" class="text-center"> 2.3 <br> 절곡 </th>';
echo '<th colspan="2" class="text-center"> (1) 가이드레일 <br> (EGI 1.6T/ SUS 1.2T) </th>';
echo '<th colspan="2" class="text-center"> (2) 케이스 <br> (EGI 1.6T) </th>';
echo '<th colspan="3" class="text-center"> (3) 하단마감재 <br> (SUS 1.2T) </th>';
echo '<th colspan="2" class="text-center"> (4) 연기차단재 </th>';
echo '</tr>';
echo '<tr>';
echo '<th class="text-center">사이즈</th>';
echo '<th class="text-center">수량</th>';
echo '<th class="text-center">사이즈</th>';
echo '<th class="text-center">수량</th>';
echo '<th class="text-center">분류</th>';
echo '<th class="text-center">3000</th>';
echo '<th class="text-center">4000</th>';
echo '<th class="text-center">종류</th>';
echo '<th class="text-center">수량</th>';
echo '</tr>';
echo '<tr>';
echo '<th class="text-center">' . $col1_sum . '</th>';
echo '<th class="text-center">' . $col2_sum . '</th>';
echo '<th class="text-center">' . $col3_sum . '</th>';
echo '<th class="text-center">' . $col4_sum . '</th>';
echo '<th class="text-center">' . $col5_sum . '</th>';
echo '<th class="text-center">' . $col6_sum . '</th>';
echo '<th class="text-center">' . $col7_sum . '</th>';
echo '<th class="text-center">' . $col8_sum . '</th>';
echo '<th class="text-center">' . $col9_sum . '</th>';
echo '</tr>';
echo '</thead>';
echo '</table>';
echo '</div>';
}
아래의 5개는 배열은 필요없고 sum의 개념만 있으면 된다.
AC8은 $item['col23']은 셔터의 유효 길이를 의미한다.
이 값에 따라 row3_1 ~ row3_5는 행의 누계를 3_1은 3열, 1행을 의미한다. 총 5개를 만들어야 한다.
row3_1의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AC8<=2438,2,IF(AND(AC8>4300,AC8<=5438),2,0))
row3_2의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AC8>2438, AC8<=3000),2,IF(AND(AC8>4300,AC8<=5438),2,IF(AND(AC8>5438,AC8<=6000),4,IF(AND(AC8>6000,AC8<=7300),2,0))))
row3_3의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AC8>3000, AC8<=3500),2,IF(AND(AC8>6000,AC8<=6500),2,0))
row3_4의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AC8>3500, AC8<=4000),2,IF(AND(AC8>6500,AC8<=7000),2,0))
row3_5의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AC8>4000, AC8<=4300),2,IF(AND(AC8>7000,AC8<=7300),2,0))
아래의 8개는 배열은 필요없고 sum의 개념만 있으면 된다.
AQ8은 $item['col32']은 셔터의 유효 길이를 의미한다.
이 값에 따라 row5_1 ~ row5_6는 행의 누계를 5_1은 5열, 1행을 의미한다.
row5_1의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AQ8<=1219,1,IF(AND(AQ8>4150,AQ8<=4219),1,IF(AND(AQ8>4219,AQ8<=4719),1,IF(AND(AQ8>4876,AQ8<=5219),1,IF(AND(AQ8>5219,AQ8<=5369),1,IF(AND(AQ8>9026,AQ8<=9219),1,0))))))
row5_2의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AQ8>1219,AQ8<=2438),1,IF(AND(AQ8>4719,AQ8<=4876),2,IF(AND(AQ8>5369,AQ8<=5938),1,IF(AND(AQ8>6000,AQ8<=6438),1,IF(AND(AQ8>6500,AQ8<=6588),1,IF(AND(AQ8>8300,AQ8<=8376),2,IF(AND(AQ8>8376,AQ8<=8438),1,IF(AND(AQ8>8438,AQ8<=8876),2,IF(AND(AQ8>9000,AQ8<=9026),2,IF(AND(AQ8>9219,AQ8<=9438),1,IF(AND(AQ8>10150,AQ8<=10738),1,0)))))))))))
row5_3의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AQ8>2438,AQ8<=3000),1,IF(AND(AQ8>4150,AQ8<=4219),1,IF(AND(AQ8>5369,AQ8<=5438),1,IF(AND(AQ8>5938,AQ8<=6000),2,IF(AND(AQ8>6438,AQ8<=6500),1,IF(AND(AQ8>7000,AQ8<=7150),1,IF(AND(AQ8>8376,AQ8<=8438),2,IF(AND(AQ8>8876,AQ8<=9000),3,IF(AND(AQ8>9438,AQ8<=10150),2,IF(AND(AQ8>10738,AQ8<=11000),1,0))))))))))
row5_4의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AQ8>3000,AQ8<=3500),1,IF(AND(AQ8>4219,AQ8<=4719),1,IF(AND(AQ8>5438,AQ8<=5938),1,IF(AND(AQ8>6438,AQ8<=6500),1,IF(AND(AQ8>6588,AQ8<=7000),2,IF(AND(AQ8>7150,AQ8<=7650),1,IF(AND(AQ8>8300,AQ8<=8376),1,IF(AND(AQ8>9219,AQ8<=9438),2,IF(AND(AQ8>9438,AQ8<=9500),1,0)))))))))
row5_5의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AQ8>3500,AQ8<=4000),1,IF(AND(AQ8>4876,AQ8<=5219),1,IF(AND(AQ8>6000,AQ8<=6438),1,IF(AND(AQ8>7150,AQ8<=7500),1,IF(AND(AQ8>7650,AQ8<=8000),2,IF(AND(AQ8>8000,AQ8<=8150),1,IF(AND(AQ8>8438,AQ8<=8876),1,IF(AND(AQ8>9026,AQ8<=9219),2,IF(AND(AQ8>9500,AQ8<=10000),1,IF(AND(AQ8>10150,AQ8<=10438),2,IF(AND(AQ8>10738,AQ8<=11000),2,0)))))))))))
row5_6의 값은 아래의 엑셀공식이다.
엑셀공식
=IF(AND(AQ8>4000,AQ8<=4150),1,IF(AND(AQ8>5219,AQ8<=5369),1,IF(AND(AQ8>6500,AQ8<=6588),1,IF(AND(AQ8>7000,AQ8<=7150),1,IF(AND(AQ8>7500,AQ8<=7650),1,IF(AND(AQ8>8000,AQ8<=8150),1,IF(AND(AQ8>8150,AQ8<=8300),2,IF(AND(AQ8>9000,AQ8<=9026),1,IF(AND(AQ8>10000,AQ8<=10150),1,IF(AND(AQ8>10438,AQ8<=10738),2,0))))))))))
row5_7의 값은 $item['col39'] 의 합
row5_8의 값은 $item['col41'] 의 합
work 테이블의 아래의 컬럼이 있다.
<td class="text-center">1차</td>
<td><input type="date" id="bill_issueDate1" name="bill_issueDate1" value="<?=$bill_issueDate1?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill1_supply" name="bill1_supply" value="<?=$bill1_supply?>" class="form-control text-end" placeholder="1차 공급가액" onkeyup="calculateVAT('bill', 1); inputNumberFormat(this);" /></td>
<td><input type="text" id="bill1_vat" name="bill1_vat" value="<?=$bill1_vat?>" class="form-control text-end" placeholder="1차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill1" name="bill1" value="<?=$bill1?>" class="form-control text-end" placeholder="1차 발행금액" onkeyup="calculateSupply('bill', 1); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate1" name="depositdate1" value="<?=$depositdate1?>" class="form-control" placeholder="1차 입금일자" /></td>
<td><input type="text" id="deposit1" name="deposit1" value="<?=$deposit1?>" class="form-control text-end" placeholder="1차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
<tr>
<td class="text-center">2차</td>
<td><input type="date" id="bill_issueDate2" name="bill_issueDate2" value="<?=$bill_issueDate2?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill2_supply" name="bill2_supply" value="<?=$bill2_supply?>" class="form-control text-end" placeholder="2차 공급가액" onkeyup="calculateVAT('bill', 2); inputNumberFormat(this);"/></td>
<td><input type="text" id="bill2_vat" name="bill2_vat" value="<?=$bill2_vat?>" class="form-control text-end" placeholder="2차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill2" name="bill2" value="<?=$bill2?>" class="form-control text-end" placeholder="2차 발행금액" onkeyup="calculateSupply('bill', 2); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate2" name="depositdate2" value="<?=$depositdate2?>" class="form-control" placeholder="2차 입금일자" /></td>
<td><input type="text" id="deposit2" name="deposit2" value="<?=$deposit2?>" class="form-control text-end" placeholder="2차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
<tr>
<td class="text-center">3차</td>
<td><input type="date" id="bill_issueDate3" name="bill_issueDate3" value="<?=$bill_issueDate3?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill3_supply" name="bill3_supply" value="<?=$bill3_supply?>" class="form-control text-end" placeholder="3차 공급가액" onkeyup="calculateVAT('bill', 3); inputNumberFormat(this);"/></td>
<td><input type="text" id="bill3_vat" name="bill3_vat" value="<?=$bill3_vat?>" class="form-control text-end" placeholder="3차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill3" name="bill3" value="<?=$bill3?>" class="form-control text-end" placeholder="3차 발행금액" onkeyup="calculateSupply('bill', 3); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate3" name="depositdate3" value="<?=$depositdate3?>" class="form-control" placeholder="3차 입금일자" /></td>
<td><input type="text" id="deposit3" name="deposit3" value="<?=$deposit3?>" class="form-control text-end" placeholder="3차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
<tr>
<td class="text-center">4차</td>
<td><input type="date" id="bill_issueDate4" name="bill_issueDate4" value="<?=$bill_issueDate4?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill4_supply" name="bill4_supply" value="<?=$bill4_supply?>" class="form-control text-end" placeholder="4차 공급가액" onkeyup="calculateVAT('bill', 4); inputNumberFormat(this);"/></td>
<td><input type="text" id="bill4_vat" name="bill4_vat" value="<?=$bill4_vat?>" class="form-control text-end" placeholder="4차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill4" name="bill4" value="<?=$bill4?>" class="form-control text-end" placeholder="4차 발행금액" onkeyup="calculateSupply('bill', 4); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate4" name="depositdate4" value="<?=$depositdate4?>" class="form-control" placeholder="4차 입금일자" /></td>
<td><input type="text" id="deposit4" name="deposit4" value="<?=$deposit4?>" class="form-control text-end" placeholder="4차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
<tr>
<td class="text-center">5차</td>
<td><input type="date" id="bill_issueDate5" name="bill_issueDate5" value="<?=$bill_issueDate5?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill5_supply" name="bill5_supply" value="<?=$bill5_supply?>" class="form-control text-end" placeholder="5차 공급가액" onkeyup="calculateVAT('bill', 5); inputNumberFormat(this);"/></td>
<td><input type="text" id="bill5_vat" name="bill5_vat" value="<?=$bill5_vat?>" class="form-control text-end" placeholder="5차 부가세" /></td>
<td><input type="text" id="bill5" name="bill5" value="<?=$bill5?>" class="form-control text-end" placeholder="5차 발행금액" onkeyup="calculateSupply('bill', 5); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate5" name="depositdate5" value="<?=$depositdate5?>" class="form-control" placeholder="5차 입금일자" /></td>
<td><input type="text" id="deposit5" name="deposit5" value="<?=$deposit5?>" class="form-control text-end" placeholder="5차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
<tr>
<td class="text-center">6차</td>
<td><input type="date" id="bill_issueDate6" name="bill_issueDate6" value="<?=$bill_issueDate6?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill6_supply" name="bill6_supply" value="<?=$bill6_supply?>" class="form-control text-end" placeholder="6차 공급가액" onkeyup="calculateVAT('bill', 6); inputNumberFormat(this);"/></td>
<td><input type="text" id="bill6_vat" name="bill6_vat" value="<?=$bill6_vat?>" class="form-control text-end" placeholder="6차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill6" name="bill6" value="<?=$bill6?>" class="form-control text-end" placeholder="6차 발행금액" onkeyup="calculateSupply('bill', 6); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate6" name="depositdate6" value="<?=$depositdate6?>" class="form-control" placeholder="6차 입금일자" /></td>
<td><input type="text" id="deposit6" name="deposit6" value="<?=$deposit6?>" class="form-control text-end" placeholder="6차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
6행의 컬럼이름들이 많다. 이 컬럼을 accountList 컬럼으로 넣으려고 하는데,
json형태로 만든 후 encode, decode를 통해 테이블에는 text형태로 저장할 것이다.
php와 mysql이 json 저장을 지원하지 않는 버전이라서 그렇다.
그러면 아래의 코드에서 json의 encode, decode 코드형태를 엿볼 수 있다.
위의 컬럼의 값들을 읽어서 1행부터 col1,col2,col3,col4,col5,col6까지 생성되는 것이다.
예를 들면,
<td class="text-center">1차</td>
<td><input type="date" id="bill_issueDate1" name="bill_issueDate1" value="<?=$bill_issueDate1?>" class="form-control"/></td> <!-- 추가된 열의 input 요소 -->
<td><input type="text" id="bill1_supply" name="bill1_supply" value="<?=$bill1_supply?>" class="form-control text-end" placeholder="1차 공급가액" onkeyup="calculateVAT('bill', 1); inputNumberFormat(this);" /></td>
<td><input type="text" id="bill1_vat" name="bill1_vat" value="<?=$bill1_vat?>" class="form-control text-end" placeholder="1차 부가세" onkeyup=" inputNumberFormat(this);" /></td>
<td><input type="text" id="bill1" name="bill1" value="<?=$bill1?>" class="form-control text-end" placeholder="1차 발행금액" onkeyup="calculateSupply('bill', 1); inputNumberFormat(this);"/></td>
<td><input type="date" id="depositdate1" name="depositdate1" value="<?=$depositdate1?>" class="form-control" placeholder="1차 입금일자" /></td>
<td><input type="text" id="deposit1" name="deposit1" value="<?=$deposit1?>" class="form-control text-end" placeholder="1차 입금액" onkeyup="calculateTotals(); inputNumberFormat(this);"/></td>
</tr>
위의 코드는 col1은 bill_issueDate1이 되는 것이다.
위의 데이터는 6행을 반복하면 col1의 데이터는
[{"col1":"2024-09-01"}.......{"col1":""}]
이렇게 되는 것이겠지?
아래의 코드를 참조하자.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
$mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : '';
$num = isset($_REQUEST['num']) ? $_REQUEST['num'] : '';
print 'accountList를 json형태의 파일 내용을 강제로 생성하기 위한 화면 ';
include '_request.php';
$tablename = 'work';
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
// PDO에서 버퍼링된 쿼리를 사용하도록 설정
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
// 이 스크립트의 메모리 제한 증가
ini_set('memory_limit', '256M');
$sql = "SELECT * FROM " . $DB . "." . $tablename . " ";
try {
$stmh = $pdo->prepare($sql);
$stmh->execute();
$rows = $stmh->fetchAll(PDO::FETCH_ASSOC);
$dataByNum = [];
// 데이터를 num별로 그룹화
foreach ($rows as $row) {
$num = $row['num'];
if (!isset($dataByNum[$num])) {
$dataByNum[$num] = [
'accountList' => []
];
}
$dataByNum[$num]['accountList'] = json_decode($row['accountList'], true);
}
$updateData = [];
// num별로 데이터 처리
foreach ($dataByNum as $num => $lists) {
$newOrderlist = [];
foreach ($lists['accountList'] as $item) {
$newItem = $item;
$tempCol14 = isset($item['col14']) ? $item['col14'] : '';
$tempCol15 = isset($item['col15']) ? $item['col15'] : '';
$newItem['col15'] = $tempCol14;
$newItem['col16'] = $tempCol15;
$newOrderlist[] = $newItem;
}
$updateData[$num] = [
'accountList' => json_encode($newOrderlist, JSON_UNESCAPED_UNICODE)
];
}
// 데이터베이스 업데이트
$pdo->beginTransaction();
$sql = "UPDATE " . $DB . ".{$tablename} SET accountList = ? WHERE num = ?";
$stmh = $pdo->prepare($sql);
foreach ($updateData as $num => $data) {
$stmh->execute([$data['accountList'], $num]);
}
$pdo->commit();
} catch (PDOException $Exception) {
$pdo->rollBack();
print "오류: " . $Exception->getMessage();
}
?>
work 테이블의 위의 컬럼들을 accountList에 저장하는 코드로 만들어줘. 컬럼을 정리하려고 한다.
## json으로 올바르게 나오지 않는경우#####
## 아래의 코드로 하면 된다.
// JSON이 배열인지 아닌지 여부를 확인하는 방법
if (typeof accountList === 'string') {
try {
accountList = JSON.parse(accountList);
} catch (e) {
console.error('JSON 파싱 오류:', e);
accountList = [];
}
}
if (Array.isArray(accountList)) {
console.log('accountList is an array:', accountList);
} else {
console.log('accountList is not an array, resetting to empty array');
accountList = [];
}
accountList.forEach(function(rowData, index) {
addBillRow($('#accountListBody'), rowData);
});
##공급가액 아이콘으로 계산하기 ###
function addRow_Bill(tableBody, rowData = {}) {
var newRow = $('<tr>');
// 첫 번째 열: 일련번호 (자동 생성)
newRow.append('<td class="text-center" style="width:80px;">' +
'<div class="d-flex justify-content-center align-items-center "> <span class="serial-number me-2"></span>' +
'<button type="button" class="btn btn-outline-primary btn-sm viewNoBtn add-row me-1" data-table="' + tableBody.closest('table').attr('id') + '">+</button>' +
'<button type="button" class="btn btn-outline-danger btn-sm viewNoBtn remove-row">-</button>' +
'</div></td>');
// col1 (발행일자) - "0000-00-00"을 빈 문자열로 처리
var col1Value = (rowData.col1 === "0000-00-00") ? '' : rowData.col1;
newRow.append('<td class="text-center"><input type="date" name="col1[]" class="form-control text-center" value="' + col1Value + '"></td>');
// col2 (공급가액)
newRow.append('<td class="text-center"><input type="text" name="col2[]" class="form-control text-end number-format" placeholder="공급가액" onkeyup="inputNumberFormat(this);" value="' + (rowData.col2 || '') + '"></td>');
// col3 (부가세)
newRow.append('<td class="text-center"><input type="text" name="col3[]" class="form-control text-end number-format" placeholder="부가세" onkeyup="inputNumberFormat(this);" value="' + (rowData.col3 || '') + '"></td>');
// col4 (발행금액)
newRow.append('<td class="text-center"><input type="text" name="col4[]" class="form-control text-end number-format" placeholder="발행금액" onkeyup="inputNumberFormat(this);" value="' + (rowData.col4 || '') + '"></td>');
// col5 (입금일자) - "0000-00-00"을 빈 문자열로 처리
var col5Value = (rowData.col5 === "0000-00-00") ? '' : rowData.col5;
newRow.append('<td class="text-center"><input type="date" name="col5[]" class="form-control text-center " value="' + col5Value + '"></td>');
// col6 (입금액)
newRow.append('<td class="text-center"><input type="text" name="col6[]" class="form-control text-end number-format" placeholder="입금액" onkeyup="inputNumberFormat(this);" value="' + (rowData.col6 || '') + '"></td>');
tableBody.append(newRow);
// 일련번호를 업데이트
updateSerialNumbers(tableBody);
// 숫자 필드에 3자리마다 콤마 추가 (소수점 입력 가능)
newRow.find('.number-format').on('input change', function() {
let value = $(this).val().replace(/,/g, ''); // 기존의 콤마를 제거
// 소수점 포함 숫자 검사
if (!isNaN(value) && value !== '') {
// 정수와 소수 부분 분리
let parts = value.split('.');
parts[0] = Number(parts[0]).toLocaleString('en'); // 3자리마다 콤마 추가
// 소수점이 있는 경우
let formattedValue = parts.join('.');
$(this).val(formattedValue);
}
//계산 함수 호출
calculateTotals();
});
// 처음 로드될 때도 자동 계산 적용
calculateTotals();
}
위의 코드에 3번째 요소와 5번째 td요소인 발행합계의 열에 input요소 옆에 계산 아이콘은 배치해서 누르면 공급가액/부가세/발행합계를 그 행에 대해서 자동계산을 하려고 한다.
공급가액 옆의 아이콘을 누르면 공급가액을 기준으로 부가세와 발행금액이 계산되고, 발행금액을 누르면 역으로 공급가액과 부가세를 계산하는 원리다.
<i class="bi bi-calculator-fill"></i> 이 아이콘을 사용할거야.
1행은 col1은 condate, col2는 estimate1_supply, col3는 estimate1_vat, col4는 estimate1,
col5는 file_name_0, , col6은 file_copied_0
다소 매치가 안될것 같지만, 내가 제공한 코드를 보면 규칙이있으니 참고바랍니다.
2행은 col1은 condate1, col2는 estimate2_supply, col3는 estimate2_vat, col4는 estimate2,
col5는 file_name_1, col6은 file_copied_1
2행은 col1은 condate2, col2는 estimate3_supply, col3는 estimate3_vat, col4는 estimate3,
col5는 file_name_2, col6은 file_copied_2
이렇게 나와야 한다.
#2. 파일 업로드 시 식별자 전송
saveData 함수에서 파일을 전송할 때, 해당 파일의 row_id도 함께 전송하여 파일이 어느 행에 속하는지 알 수 있도록 합니다.
실제 위와 같이 행을 동적으로 추가하고 그 마지막에 첨부파일을 넣는 방식인데, 여러가지 동적으로 행을 만들고 지우고 추가하고 하는 과정에서 내 마음대로 되지 않는구나.
화면의 동적추가 및 기타 동작은 되지만, 서버에서 처리하는 insert.php 에서 제대로 되지 않는다. 이유는 알것 같지만, 막상 코드로 잘 안된다.
문제는 이것이다.
estimateList에서 col5, col6을 json형태로 가져와서 웹에서 front end에서는 잘 되는데 이것이 file을 서버로 전달하면, insert.php에서 파일의 첨부가 있을때, 이것이 1행에서 추가된 것이면 기존의 col5, col6의 1행에 해당되는 값만 수정이 되어야 하는데,
지금은 만약 4행이 있다면 4행 전부가 그 파일이름으로 수정이 되고, 1행은 서버저장 파일이름도 잘못되서 나온다.
결국은 estimateList의 각 행과 upfile로 전달된 file의 첨부가 몇행에서 이뤄졌는지 정보가 전달되어야 정확할 것 같은데 방법이 있을까?
ChatGPT의 말:
ChatGPT
네, 상황을 이해했습니다. estimateList의 각 행과 파일 업로드가 정확히 매칭되지 않아서 문제가 발생하고 있습니다. 이를 해결하기 위해서는 다음과 같은 전략을 사용해야 합니다:
해결책:
행의 고유 식별자 추가: 각 행이 고유한 식별자를 가지도록 하여 파일 업로드와 정확히 매칭할 수 있도록 합니다. 이 식별자는 행이 생성될 때마다 할당되며, insert.php에서 파일 업로드 처리 시 이 식별자를 사용해 해당 행과 파일을 매칭합니다.
파일 업로드 시 식별자 전송: 파일 업로드가 일어날 때 해당 파일이 어느 행에 속하는지 식별자를 함께 전송합니다. 이를 통해 insert.php에서 해당 행만 파일 정보를 업데이트할 수 있습니다.
1. 행의 고유 식별자 추가
각 행에 고유한 data-id 속성을 추가합니다. 이 속성은 자바스크립트에서 행을 생성할 때 무작위 또는 순차적으로 생성됩니다.
#컬럼등 추가했을때 만들어주는 코드
cableworkStatus, certifiedInspector, certifiedLabelAttachedDate
위의 3개의 컬럼을 추가했다.
_row.php 파일은 아래의 형태이다. 추가해줘.
<?php
$num = isset($row['num']) ? $row['num'] : '';
위는 예시이다. 실제 요청한 컬럼만 생성하면 된다.
_request.php 파일은 아래의 형태이다. 추가해줘.
<?php
$num = isset($_REQUEST['num']) ? $_REQUEST['num'] : '';
위는 예시이다. 실제 요청한 컬럼만 생성하면 된다.
insert.php 파일에 서버에 신규생성 및 수정에 대한 선언부분이다.
아래와 같은 형태로 만들어줘.
1) issued_amount = ?, decided_estimate = ?, .....
2) $subject, $content, ....
3) receivable, chargedperson, .....
위는 예시이다. 실제 요청한 컬럼만 생성하면 된다.
foreach ($decodedEstimateList as $item) {
$col54 = floatval($item['col54']);
$col55 = floatval($item['col55']);
$col56 = floatval($item['col56']);
$col57 = floatval($item['col57']);
$col58 = floatval($item['col58']);
$col59 = floatval($item['col59']);
$col60 = floatval($item['col60']);
엑셀수식 :
E8 = $item['col4'] 의 앞 두자리가 'KS' 이면 '스크린'으로 인식한다.
H8은 $item['col8'] , BK8은 $item['col53']
$col61은 =IF(AND(E8="스크린",BK8=6,H8>8250,H8<=10200),1,0)
$col61은 =IF(AND(E8="스크린",BK8=6,H8>8250,H8<=10200),1,0)
var fileDiv = $('<div>').attr('id', 'file' + i).css({
display: 'inline-block',
width: 'calc(20% - 10px)', // 5개를 한 줄에 맞추기 위해 20%의 너비 할당 (5개의 이미지가 한 줄에 배치됨)
margin: '5px',
textAlign: 'center' // 이미지와 버튼을 중앙 정렬
});
위의 코드는 5개 있을때는 좋은데, 1개, 2개 이미지가 있을때는 서로 겹처보인다. 1개, 2개~ 5개까지 여백이 확보되게 수정해줘.
## 같은 이름의 첨부파일 등록하지 않기
코드 수정:
다음은 파일을 FormData에 추가하기 전에 중복 여부를 검사하는 코드입니다.
javascript
코드 복사
function uploadFiles(files) {
console.log('업로드 파일 리스트:', files);
isUploading = true; // 업로드 중 상태 설정
var formData = new FormData($('#board_form')[0]);
// 현재 폼 데이터에 추가된 파일 이름 목록 추적
var existingFiles = new Set();
for (var pair of formData.entries()) {
if (pair[0] === 'upfile[]') {
existingFiles.add(pair[1].name);
}
}
// 중복되지 않은 파일만 추가
for (var i = 0; i < files.length; i++) {
if (!existingFiles.has(files[i].name)) {
formData.append('upfile[]', files[i]);
existingFiles.add(files[i].name); // 추가된 파일 이름을 목록에 저장
console.log('파일 추가:', files[i].name); // 디버그
} else {
console.log('중복 파일 무시:', files[i].name); // 디버그
}
}
#토글버튼 추가로직 #
위의 코드에서 table을 보이게 안보이게 하는 토글 버튼을 만들건데, 아래의 코드를 참조해서 html 코드와 자바스크립트를 추가해줘.
쿠키에도 저장하고 다시 불러오는 과정도 포함된다.
<style>
#bendTableToggle {
cursor: pointer;
}
</style>
<div class="container">
<div class="row justify-content-center">
<div class="card w-50">
<div class="card-body">
<div class="d-flex justify-content-center align-items-center" >
<h5 class="card-title text-center">절곡판</h5>
<span id="bendTableToggle" class="badge bg-secondary ms-3 me-2">
<i class="bi bi-chevron-down"></i>
</span>
</div>
<table id="item_bendTable" class="table table-bordered table-hover">
<thead class="table-primary text-center">
<tr>
<th class="align-middle">품목</th>
<th class="align-middle">규격</th>
<th class="align-middle">두께(T)</th>
<th class="align-middle">비중</th>
<th class="align-middle">㎡ / 단가</th>
</tr>
</thead>
<tbody>
<!-- Additional Rows Go Here -->
</tbody>
</table>
</div>
</div>
</div> <!--row-->
$(document).ready(function() {
initializePage();
// Toggle button for bendTable
$("#bendTableToggle").on("click", function() {
var showBendTable = getCookie("showBendTable");
var bendTable = $("#item_bendTable");
if (showBendTable === "show") {
bendTable.css("display", "none");
setCookie("showBendTable", "hide", 10);
} else {
bendTable.css("display", "block");
setCookie("showBendTable", "show", 10);
}
});
// Check the cookie value on page load and set the table visibility
var showBendTable = getCookie("showBendTable");
var bendTable = $("#item_bendTable");
if (showBendTable === "show") {
bendTable.css("display", "block");
} else {
bendTable.css("display", "none");
}
});
##발주서 테이블 생성원리 설명자료 ##
이제부터 생성원리에 대한 설명을 시작한다.
tr 1행은 아래와 같이 구성된다. 12개로 나뉜다.
구성품 길이 (mm) 수량 구성품 길이 수량 구성품 길이 수량 구성품 길이 수량
td 1열은 '하단마감재 <br>
(60*40)'
td 2열은 길이 3000 또는 4000으로 구성된 자료를 읽어와서 해당수량을 다음열인 3열에 나타내는 것이다.
길이 3000에 대한 수량 col44
길이 4000에 대한 수량 col45
td 4열은 '하단 <br> 보강엘바 <br>
(60*17)'
td 5열은 길이 3000 또는 4000으로 구성된 자료를 읽어와서 해당수량을 다음열인 6열에 나타내는 것이다.
길이 3000에 대한 수량 col47
길이 4000에 대한 수량 col48
td 7열은 '하단 <br>
보강평철'
td 8열은 길이 3000 또는 4000으로 구성된 자료를 읽어와서 해당수량을 다음열인 9열에 나타내는 것이다.
길이 3000에 대한 수량 col50
길이 4000에 대한 수량 col51
td 10열은 '하단 <br> 무게평철 <br>
[50*12T]'
td 11열은 길이 2000으로 구성된 자료를 읽어와서 해당수량을 다음열인 12열에 나타내는 것이다.
길이 2000에 대한 수량 col52
위의 내용을 코드로 만들어줘.
<!-- 하단 마감재 및 테이블 출력 -->
<?PHP
// 마감 EGI, SUS 분리하기
foreach ($eList as $item) {
$prodcode = $item['col4'];
$GuiderailType = $item['col6'];
$items1 = ['KSS01'];
$items2 = ['KWE01','KSE01'];
// $prodcode가 $items1 배열에 있는 경우
if (in_array($prodcode, $items1)) {
$GuidrailFinish = 'SUS 1.2T';
$GuidrailExtraFinish = 'SUS 1.2T';
}
// $prodcode가 $items2 배열에 있는 경우
elseif (in_array($prodcode, $items2)) {
$GuidrailFinish = 'EGI 1.15T';
$GuidrailExtraFinish = 'SUS 1.2T';
} else {
$GuidrailFinish = 'EGI 1.15T';
$GuidrailExtraFinish = 'SUS 1.2T';
}
}
?>
<div class="row m-1 mt-3">
<?php
// 가이드 레일 계산 및 테이블 출력
if (True) {
$row3_data = [
['length' => 2438, 'sum' => 0],
['length' => 3000, 'sum' => 0],
['length' => 3500, 'sum' => 0],
['length' => 4000, 'sum' => 0],
['length' => 4300, 'sum' => 0]
];
foreach ($eList as $item) {
$AC8 = floatval($item['col23']); // 셔터의 유효 길이
$railType = trim($item['col6']); // 벽부형, 측면형, 혼합형 여부 판단
// 혼합형일 경우 1개씩 계산, 나머지는 2개씩 계산
for ($i = 0; $i < count($row3_data); $i++) {
$length = $row3_data[$i]['length'];
if ($AC8 <= $length) {
$row3_data[$i]['sum'] += ($railType == '혼합형') ? 1 : 2;
break;
}
}
}
// 벽면형과 측면형을 혼합형일 때는 두 개씩, 나머지는 하나씩 출력
$wall_rows = [];
$side_rows = [];
foreach ($row3_data as $row) {
if ($row['sum'] > 0) {
if ($railType == '혼합형') {
$wall_rows[] = [
'length' => $row['length'],
'sum' => $row['sum']
];
$side_rows[] = [
'length' => $row['length'],
'sum' => $row['sum']
];
} elseif ($railType == '벽면형(120*70)') {
$wall_rows[] = [
'length' => $row['length'],
'sum' => $row['sum']
];
} elseif ($railType == '측면형(120*120)') {
$side_rows[] = [
'length' => $row['length'],
'sum' => $row['sum']
];
}
}
}
// 벽면형 테이블 출력 (혼합형일 경우에만)
if ($railType == '혼합형' || $railType == '벽면형(120*70)') {
echo '<div class="col-sm-9 d-flex align-items-top justify-content-start">';
echo '<div class="d-flex align-items-center justify-content-start">';
echo '<table class="table " style="border-collapse: collapse;">';
echo '<tbody>';
echo '<tr>';
echo '<td rowspan="1" colspan="3" class="text-center align-middle lightgray">1.1 벽면형[120*70]</td>';
echo '<td rowspan="2" class="text-center yellowblackBold " style="width:250px;">입고 LOT NO.</td>';
echo '</tr>';
echo '<tr>';
echo '<td rowspan="7"><img src="../img/guiderail/guiderail_' . $prodCode . '_wall_120x70.jpg" alt="벽면형" width="220"></td>';
echo '<td class="text-center lightgray">세부품명</td>';
echo '<td class="text-center lightgray">재질</td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-danger ">①마감재</td>';
echo '<td class="text-center text-danger ">' . $GuidrailFinish . '</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">②가이드레일</td>';
echo '<td rowspan="3" class="text-center text-dark ">' . $GuidrailFinish . '</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">③C형</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">④D형</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-danger ">⑤별도마감재</td>';
echo '<td class="text-center text-danger ">' . $GuidrailExtraFinish . '</td>';
echo '<td class="text-center text-primary fw-bold"> 없음 </td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">하부BASE</td>';
echo '<td class="text-center text-dark ">EGI 1.55T</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '</tbody>';
echo '</table>';
echo '</div>';
echo '</div>';
// 작업량 테이블 추가 (벽면형)
echo '<div class="col-sm-3 d-flex justify-content-start">';
echo '<div class="d-flex justify-content-start m-1">';
echo '<table class="table" style="border-collapse: collapse;">';
echo '<tbody>';
echo '<tr>';
echo '<td colspan="2" class="text-center blueBlackBold"> 작업량 </td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center blueBlackBold w100px">길이/규격</td>';
echo '<td class="text-center blueBlackBold w100px">수량</td>';
echo '</tr>';
$wall_sum = 0;
foreach ($wall_rows as $row) {
echo '<tr>';
echo '<td class="text-center">' . $row['length'] . '</td>';
echo '<td class="text-center">' . $row['sum'] . '</td>';
echo '</tr>';
$wall_sum += $row['sum'];
}
echo '<tr>';
echo '<td class="text-center fw-bold ">하부BASE <br> (130*80)</td>';
echo '<td class="text-center fw-bold ">' . $wall_sum . '</td>';
echo '</tr>';
echo '</tbody>';
echo '</table>';
echo '</div>';
echo '</div>';
}
// 측면형 테이블 출력 (혼합형일 경우에만)
if ($railType == '혼합형' || $railType == '측면형(120*120)') {
echo '<div class="col-sm-9 d-flex align-items-top justify-content-start">';
echo '<div class="d-flex align-items-center justify-content-start">';
echo '<table class="table " style="border-collapse: collapse;">';
echo '<tbody>';
echo '<tr>';
echo '<td rowspan="1" colspan="3" class="text-center align-middle lightgray">1.2 측면형[120*120]</td>';
echo '<td rowspan="2" class="text-center yellowblackBold " style="width:250px;">입고 LOT NO.</td>';
echo '</tr>';
echo '<tr>';
echo '<td rowspan="8"><img src="../img/guiderail/guiderail_' . $prodCode . '_side_120x120.jpg" alt="측면형" width="220"></td>';
echo '<td class="text-center lightgray">세부품명</td>';
echo '<td class="text-center lightgray">재질</td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-danger ">①②마감재</td>';
echo '<td class="text-center text-danger ">' . $GuidrailFinish . '</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">③가이드레일</td>';
echo '<td rowspan="4" class="text-center text-dark ">' . $GuidrailFinish . '</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">④가이드레일</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">⑤C형</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">⑥D형</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-danger ">⑦⑧별도마감재</td>';
echo '<td class="text-center text-danger ">' . $GuidrailExtraFinish . '</td>';
echo '<td class="text-center text-primary fw-bold"> 없음 </td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center text-dark ">하부BASE</td>';
echo '<td class="text-center text-dark ">EGI 1.55T</td>';
echo '<td class="text-center "></td>';
echo '</tr>';
echo '</tbody>';
echo '</table>';
echo '</div>';
echo '</div>';
// 작업량 테이블 추가 (측면형)
echo '<div class="col-sm-3 d-flex justify-content-start">';
echo '<div class="d-flex justify-content-start m-1">';
echo '<table class="table" style="border-collapse: collapse;">';
echo '<tbody>';
echo '<tr>';
echo '<td colspan="2" class="text-center blueBlackBold"> 작업량 </td>';
echo '</tr>';
echo '<tr>';
echo '<td class="text-center blueBlackBold w100px">길이/규격</td>';
echo '<td class="text-center blueBlackBold w100px">수량</td>';
echo '</tr>';
$side_sum = 0;
foreach ($side_rows as $row) {
echo '<tr>';
echo '<td class="text-center">' . $row['length'] . '</td>';
echo '<td class="text-center">' . $row['sum'] . '</td>';
echo '</tr>';
$side_sum += $row['sum'];
}
echo '<tr>';
echo '<td class="text-center fw-bold ">하부BASE <br> (130*130)</td>';
echo '<td class="text-center fw-bold ">' . $side_sum . '</td>';
echo '</tr>';
echo '</tbody>';
echo '</table>';
echo '</div>';
echo '</div>';
}
}
?>
</div>
위의 코드를 하단마감재의 내용으로 전부 수정해줘.
하단마감재 계산방법은 아래와 같다. 즉, 혼합형,벽면형, 측면형 표시는 필요가 없다.
이미지는 ../img/bottombar/bottombar_KSS01.jpg
../img/bottombar/bottombar_KSE01.jpg
이런식으로 이름과 관련이미지가 저장되어있다.
KWE01는 KSE01과 같은 형태다.
하단마감재 산출공식은 아래를 참조한다.
<div class="row justify-content-start m-1 mt-2 ">
3-2. 하단마감재 <br>
<?php
if (trim($prodCode) == "KSS01") {
$result = "하단마감재(SUS 1.55T) + 하단보강엘바(EGI 1.55T) + 하단 보강평철(EGI 1.15T) + 하단 무게평철(50*12T)";
} else {
$result = "하단마감재(EGI 1.55T) + 하단보강엘바(EGI 1.55T) + 하단 보강평철(EGI 1.15T) + 하단 무게평철(50*12T)";
}
echo $result . '</div>' ;
?>
<!-- 하단마감재 -->
<?php
// 하단 마감재 및 구성품 테이블 출력
if (True) {
// 하단 마감재, 하단 보강엘바, 하단 보강평철, 하단 무게평철의 데이터를 저장할 배열
$item_data = [
'하단마감재' => [
'size' => '(60*40)',
'length_3000' => 0,
'length_4000' => 0
],
'하단 보강엘바' => [
'size' => '(60*17)',
'length_3000' => 0,
'length_4000' => 0
],
'하단 보강평철' => [
'size' => '',
'length_3000' => 0,
'length_4000' => 0
],
'하단 무게평철' => [
'size' => '[50*12T]',
'length_2000' => 0
]
];
// 데이터를 누적하여 합산
foreach ($eList as $item) {
$item_data['하단마감재']['length_3000'] += intval($item['col44']);
$item_data['하단마감재']['length_4000'] += intval($item['col45']);
$item_data['하단 보강엘바']['length_3000'] += intval($item['col47']);
$item_data['하단 보강엘바']['length_4000'] += intval($item['col48']);
$item_data['하단 보강평철']['length_3000'] += intval($item['col50']);
$item_data['하단 보강평철']['length_4000'] += intval($item['col51']);
$item_data['하단 무게평철']['length_2000'] += intval($item['col52']);
}
// 테이블 출력 시작
echo '<div class="d-flex align-items-center justify-content-center m-1">';
echo '<table class="table" style="border-collapse: collapse;">';
// 첫 번째 행: 자재 구성품명, 길이, 수량 표시
echo '<tr>';
echo '<td class="text-center lightgray fw-bold">구성품</td>';
echo '<td class="text-center lightgray fw-bold">길이 (mm)</td>';
echo '<td class="text-center lightgray fw-bold">수량</td>';
echo '<td class="text-center lightgray fw-bold">구성품</td>';
echo '<td class="text-center lightgray fw-bold">길이 (mm)</td>';
echo '<td class="text-center lightgray fw-bold">수량</td>';
echo '<td class="text-center lightgray fw-bold">구성품</td>';
echo '<td class="text-center lightgray fw-bold">길이 (mm)</td>';
echo '<td class="text-center lightgray fw-bold">수량</td>';
echo '<td class="text-center lightgray fw-bold">구성품</td>';
echo '<td class="text-center lightgray fw-bold">길이 (mm)</td>';
echo '<td class="text-center lightgray fw-bold">수량</td>';
echo '</tr>';
// 두 번째 행: 3000mm 길이에 대한 수량 표시
echo '<tr>';
// 하단 마감재
echo '<td class="text-center fw-bold" rowspan="2">하단마감재<br>' . $item_data['하단마감재']['size'] . '</td>';
echo '<td class="text-center">L : 3,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단마감재']['length_3000'] ?: '-') . '</td>';
// 하단 보강엘바
echo '<td class="text-center fw-bold" rowspan="2">하단<br>보강엘바<br>' . $item_data['하단 보강엘바']['size'] . '</td>';
echo '<td class="text-center">L : 3,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단 보강엘바']['length_3000'] ?: '-') . '</td>';
// 하단 보강평철
echo '<td class="text-center fw-bold" rowspan="2">하단<br>보강평철</td>';
echo '<td class="text-center">L : 3,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단 보강평철']['length_3000'] ?: '-') . '</td>';
// 하단 무게평철
echo '<td class="text-center fw-bold" rowspan="2">하단<br>무게평철<br>' . $item_data['하단 무게평철']['size'] . '</td>';
echo '<td class="text-center">L : 2,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단 무게평철']['length_2000'] ?: '-') . '</td>';
echo '</tr>';
// 세 번째 행: 4000mm 길이에 대한 수량 표시
echo '<tr>';
// 하단 마감재 (길이 4000)
echo '<td class="text-center">L : 4,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단마감재']['length_4000'] ?: '-') . '</td>';
// 하단 보강엘바 (길이 4000)
echo '<td class="text-center">L : 4,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단 보강엘바']['length_4000'] ?: '-') . '</td>';
// 하단 보강평철 (길이 4000)
echo '<td class="text-center">L : 4,000</td>';
echo '<td class="text-center text-danger">' . ($item_data['하단 보강평철']['length_4000'] ?: '-') . '</td>';
// 하단 무게평철은 2000mm만 존재하므로 공백 처리
echo '</tr>';
echo '</tbody>';
echo '</table>';
echo '</div>';
}
?>
이미지 정보를 하나 갖고 있는 컬럼(imgdata과 절곡의 전개치수를 저장하는 변수 plateList,
연신율을 저장하는 변수 bendingrateList, 음영정보를 기록하는 colorList, A각 정보를 담고 있는 AList
위의 컬럼은 전부 'text' 형태이고, 아래의 추가적인 정보를 포함해서 bending 테이블을 생성하는 sql 코드 만들어줘.
<?
$num = isset($_REQUEST['num']) ? $_REQUEST['num'] : '';
$memo = isset($_REQUEST['note']) ? $_REQUEST['note'] : '';
$is_deleted = isset($_REQUEST['is_deleted']) ? $_REQUEST['is_deleted'] : null;
$searchtag = isset($_REQUEST['searchtag']) ? $_REQUEST['searchtag'] : '';
$update_log = isset($_REQUEST['update_log']) ? $_REQUEST['update_log'] : '';
$parentnum = isset($_REQUEST['parentnum']) ? $_REQUEST['parentnum'] : '';
$registdate = isset($_REQUEST['registdate']) ? $_REQUEST['registdate'] : '';
?>
php 7.3이전의 버전이라서 json 형태의 mysql 저장이 안되서 text로 저장하고 JSON형태의 파일을 encode, decode해서 사용할 예정입니다.
위의 코드는 write.php 전체의 코드인데,
mysql 버전이 낮아서 json형태로 저장하는 것이 직접되지 않아서,
text형태로 json 디코드, 인코드하는 과정을 거쳐서 서버에 저장한다.
bending 테이블의 컬럼은 text로 선언된 상태이다.
사진관련 동작이 잘되니 좋다.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
if (!isset($_SESSION["level"]) || $_SESSION["level"] > 5) {
sleep(1);
header("Location:" . $WebSite . "login/login_form.php");
exit;
}
include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php';
// 첫 화면 표시 문구
$title_message = '절곡바라시 기초자료';
?>
<title> <?=$title_message?> </title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php
$option = isset($_REQUEST['option']) ? $_REQUEST['option'] : '';
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
$mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : '';
$header = isset($_REQUEST['header']) ? $_REQUEST['header'] : '';
$tablename = 'bending';
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
$num = isset($_REQUEST["num"]) ? $_REQUEST["num"] : 0;
// 수정일 경우
if ($num > 0) {
try {
$sql = "SELECT * FROM " . $DB . "." . $tablename . " WHERE num=?";
$stmh = $pdo->prepare($sql);
$stmh->bindValue(1, $num, PDO::PARAM_STR);
$stmh->execute();
$row = $stmh->fetch(PDO::FETCH_ASSOC);
include '_row.php';
} catch (PDOException $Exception) {
print "오류: " . $Exception->getMessage();
}
$mode = 'update';
$memo = '';
$imgdata = '';
$itemName = '';
$inputList = '{}'; // JSON 초기값
$plateList = '{}'; // JSON 초기값
$bendingrateList = '{}'; // JSON 초기값
$colorList = '{}'; // JSON 초기값
$AList = '{}'; // JSON 초기값
$sumList = '{}'; // JSON 초기값
$title_message = '절곡바라시 기초자료 수정';
} else {
include '_request.php';
$mode = 'insert';
$memo = '';
$imgdata = '';
$itemName = '';
$inputList = '{}'; // JSON 초기값
$plateList = '{}'; // JSON 초기값
$bendingrateList = '{}'; // JSON 초기값
$colorList = '{}'; // JSON 초기값
$AList = '{}'; // JSON 초기값
$sumList = '{}'; // JSON 초기값
$registdate = date('Y-m-d'); // 현재일자 기록
}
?>
<form id="board_form" name="board_form" method="post" enctype="multipart/form-data">
<input type="hidden" id="mode" name="mode" value="<?=$mode?>">
<input type="hidden" id="num" name="num" value=<?=$num?>>
<input type="hidden" id="tablename" name="tablename" value=<?=$tablename?>>
<input type="hidden" id="update_log" name="update_log" value=<?=$update_log?>>
<input type="hidden" id="header" name="header" value="<?=$header?>">
<input type="hidden" id="registdate" name="registdate" value="<?=$registdate?>">
<!-- Hidden Fields to store JSON Data -->
<input type="hidden" id="inputList" name="inputList">
<input type="hidden" id="bendingrateList" name="bendingrateList">
<input type="hidden" id="sumList" name="sumList">
<input type="hidden" id="colorList" name="colorList">
<input type="hidden" id="AList" name="AList">
<div class="container-fluid">
<div class="card">
<div class="card-header text-center">
<span class="text-center fs-5"><?=$title_message?></span>
</div>
<div class="card-body">
<div class="container-fluid">
<div class="card">
<div class="card-body">
<div class="row mt-3">
<!-- 기존 이미지 표시 영역 -->
<div class="col-sm-3 mt-3">
<div class="card mb-3">
<div class="card-body">
<div id="previewContainer" class="text-center mb-3">
<img src="../img/bending/Lbar.png" alt="L bar" id="currentImage" class="img-fluid">
</div>
</div>
</div>
<!-- 파일 선택 -->
<input type="file" id="upfile" name="upfile[]" multiple style="display:none;">
<button class="btn btn-dark btn-sm me-4" type="button" onclick="document.getElementById('upfile').click();">
<i class="bi bi-image"></i>
</button>
<div class="d-flex justify-content-center">
<!-- 드롭 영역 -->
<div id="dropArea" style="border: 1px dashed #ccc; padding: 5px; width:100%; height:80px; text-align: center;">
여기로 사진을 drop 하세요!
</div>
</div>
<!-- 파일 목록 표시 -->
<div class="d-flex mt-2 justify-content-center">
<div id="displayfile"></div>
</div>
</div>
<!-- JavaScript for handling drag and drop -->
<script>
document.getElementById('dropArea').addEventListener('dragover', function(event) {
event.preventDefault();
event.stopPropagation();
this.style.borderColor = '#000'; // 드래그 시 테두리 색상 변경
});
document.getElementById('dropArea').addEventListener('dragleave', function(event) {
event.preventDefault();
event.stopPropagation();
this.style.borderColor = '#ccc'; // 드래그 영역 벗어날 때 테두리 색상 복원
});
document.getElementById('dropArea').addEventListener('drop', function(event) {
event.preventDefault();
event.stopPropagation();
const files = event.dataTransfer.files;
if (files.length > 0) {
handleFiles(files);
}
});
document.getElementById('upfile').addEventListener('change', function(event) {
const files = event.target.files;
if (files.length > 0) {
handleFiles(files);
}
});
function handleFiles(files) {
const file = files[0]; // 첫 번째 파일만 처리
const reader = new FileReader();
reader.onload = function(event) {
const img = document.createElement('img');
img.src = event.target.result;
img.className = 'img-fluid';
const previewContainer = document.getElementById('previewContainer');
previewContainer.innerHTML = ''; // 기존 이미지 제거
previewContainer.appendChild(img);
// 이미지 데이터를 form 요소에 추가
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'imageData';
hiddenInput.value = event.target.result;
previewContainer.appendChild(hiddenInput);
};
reader.readAsDataURL(file);
}
</script>
<div class="col-sm-9">
<div class="card">
<div class="card-header text-center">
<div class="d-flex align-items-center justify-content-start">
<span class="text-start fs-6 me-1">등록일 </span>
<input type="date" id="registdate" class="form-control me-3" name="registdate" value="<?=$registdate?>" style="width: 120px;">
<span class="text-center fs-6 me-1">품명 </span>
<input type="text" id="itemName" class="form-control text-start me-3" name="itemName" value="<?=$itemName?>" style="width: 250px;">
<span class="text-center fs-6 me-1">재질 </span>
<select id="material" class="form-control text-center" name="material" style="width: 100px;">
<?php
$options = ['선택','EGI 1.15T', 'EGI 1.55T', 'SUS 1.2T', 'SUS 1.5T']; // 배열에 새로운 옵션 추가
foreach ($options as $option) {
$selected = ($material === $option) ? 'selected' : '';
echo "<option value=\"$option\" $selected>$option</option>";
}
?>
</select>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="table-container">
<table class="table table-bordered" id="dynamicTable">
<thead>
<tr>
<th class="lightgray" style="width: 150px;">항목</th>
<th class="text-start" style="width: 940px;"> &nbsp; 값</th>
</tr>
</thead>
<tbody>
<tr id="numberRow">
<td class="lightgray">번호</td>
<td>
<div class="input-container">
<span class="form-control text-center" style="width: 40px;">1</span>
</div>
</td>
</tr>
<tr>
<td class="lightgray">입력</td>
<td>
<div class="input-container">
<input type="text" class="form-control yellowBold text-start" name="inputList[]" style="width: 40px;" oninput="calculateSum()" onchange="calculateSum()">
</div>
</td>
</tr>
<tr>
<td class="lightgray">연신율 (-)</td>
<td>
<div class="input-container">
<input type="text" class="form-control text-start" name="bendingrateList[]" style="width: 40px;" oninput="calculateSum()" onchange="calculateSum()">
</div>
</td>
</tr>
<tr>
<td class="lightgray">합</td>
<td>
<div class="input-container">
<input type="text" class="form-control orangeBlackBold text-start" name="sumList[]" style="width: 40px;">
</div>
</td>
</tr>
<tr>
<td class="lightgray">음영 </td>
<td>
<div class="input-container">
<input type="checkbox" class="form-check-input" name="colorList[]" style="width: 20px; height: 20px; margin-left: 10px; margin-right: 20px;">
</div>
</td>
</tr>
<tr>
<td class="lightgray">A각 표시</td>
<td>
<div class="input-container">
<input type="checkbox" class="form-check-input" name="AList[]" style="width: 20px; height: 20px; margin-left: 10px; margin-right: 20px;">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<button type="button" class="btn btn-dark btn-sm" id="saveBtn">저장 </button>
<button type="button" class="btn btn-success btn-sm" id="addColumnBtn">열 추가</button>
<button type="button" class="btn btn-danger btn-sm" id="removeColumnBtn">열 제거</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.table-container {
width: 100%;
}
#dynamicTable {
table-layout: fixed;
width: 800px;
}
#dynamicTable th:first-child,
#dynamicTable td:first-child {
width: 150px;
min-width: 150px;
max-width: 150px;
}
#dynamicTable th:nth-child(2),
#dynamicTable td:nth-child(2) {
width: 900px;
min-width: 800px;
max-width: 800px;
}
.input-container {
width: 100%;
white-space: nowrap;
display: flex;
align-items: center;
}
.input-container input,
.input-container span {
display: inline-block;
margin-right: 10px;
}
.input-container input[type="text"] {
width: 40px;
}
.input-container input[type="checkbox"] {
width: 20px;
height: 20px;
margin-right: 20px;
}
.form-check {
display: flex;
align-items: center;
}
</style>
<script>
function calculateSum() {
const table = document.getElementById('dynamicTable');
const inputContainers = table.querySelectorAll('tr:nth-child(2) .input-container');
const bendingrateContainers = table.querySelectorAll('tr:nth-child(3) .input-container');
const sumContainers = table.querySelectorAll('tr:nth-child(4) .input-container');
let accumulatedSum = 0;
const inputs = inputContainers[0].querySelectorAll('input[type="text"]');
const bendingrates = bendingrateContainers[0].querySelectorAll('input[type="text"]');
const sums = sumContainers[0].querySelectorAll('input[type="text"]');
for (let i = 0; i < inputs.length; i++) {
const inputVal = parseFloat(inputs[i].value) || 0;
const bendingrateVal = parseFloat(bendingrates[i].value) || 0;
const result = inputVal - bendingrateVal;
accumulatedSum += result;
if (sums[i]) {
sums[i].value = accumulatedSum;
}
}
}
function addColumn() {
const table = document.getElementById('dynamicTable');
const numberRow = document.getElementById('numberRow').querySelector('.input-container');
const currentNumber = numberRow.querySelectorAll('span').length + 1;
// 번호 행에 새로운 숫자 추가
const newNumber = document.createElement('span');
newNumber.className = 'form-control text-center';
newNumber.style.width = '40px';
newNumber.innerText = currentNumber; // 새 열 번호
numberRow.appendChild(newNumber);
// 나머지 행에 새로운 열 추가
const rows = table.getElementsByTagName('tr');
for (let i = 2; i < rows.length; i++) {
const inputContainer = rows[i].querySelector('.input-container');
if (inputContainer) {
const inputName = inputContainer.querySelector('input') ? inputContainer.querySelector('input').name : '';
let additionalClass = i === 2 ? 'form-control yellowBold' : i === 4 ? 'form-control orangeBlackBold' : 'form-control';
const newInput = document.createElement('input');
newInput.type = (i === 5 || i === 6) ? 'checkbox' : 'text';
newInput.className = additionalClass;
newInput.name = inputName;
if (newInput.type === 'text') {
newInput.style.width = '40px';
newInput.oninput = calculateSum;
newInput.onchange = calculateSum;
} else {
newInput.className = 'form-check-input';
newInput.style.width = '20px';
newInput.style.height = '20px';
newInput.style.marginRight = '20px';
// 체크박스 라벨 추가
const label = document.createElement('label');
label.style.marginRight = '10px';
inputContainer.appendChild(label);
}
inputContainer.appendChild(newInput);
}
}
}
function removeColumn() {
const table = document.getElementById('dynamicTable');
const numberRow = document.getElementById('numberRow');
// 번호 제거
const numbers = numberRow.querySelectorAll('span');
if (numbers.length > 1) {
numberRow.querySelector('.input-container').removeChild(numbers[numbers.length - 1]);
}
// 나머지 행에서 마지막 열 제거
const rows = table.getElementsByTagName('tr');
for (let i = 1; i < rows.length; i++) {
const inputContainer = rows[i].querySelector('.input-container');
if (inputContainer) {
const inputs = inputContainer.querySelectorAll('input');
if (inputs.length > 1) {
inputContainer.removeChild(inputs[inputs.length - 1]);
// 체크박스 라벨 제거
if (i === 5 || i === 6) {
const labels = inputContainer.querySelectorAll('label');
if (labels.length > 0) {
inputContainer.removeChild(labels[labels.length - 1]);
}
}
}
}
}
calculateSum();
}
document.getElementById('addColumnBtn').addEventListener('click', addColumn);
document.getElementById('removeColumnBtn').addEventListener('click', removeColumn);
</script>
</form>
<!-- 페이지로딩 -->
<script>
// 페이지 로딩
$(document).ready(function(){
var loader = document.getElementById('loadingOverlay');
loader.style.display = 'none';
});
ajaxRequest_write = null;
// 저장 버튼 클릭 시 데이터를 JSON으로 변환하여 hidden input에 저장
document.getElementById('saveBtn').addEventListener('click', function() {
// 각 리스트들을 JSON으로 변환
const inputList = [];
document.querySelectorAll('input[name="inputList[]"]').forEach(input => inputList.push(input.value));
const bendingrateList = [];
document.querySelectorAll('input[name="bendingrateList[]"]').forEach(input => bendingrateList.push(input.value));
const sumList = [];
document.querySelectorAll('input[name="sumList[]"]').forEach(input => sumList.push(input.value));
const colorList = [];
document.querySelectorAll('input[name="colorList[]"]').forEach(input => colorList.push(input.value));
const AList = [];
document.querySelectorAll('input[name="AList[]"]').forEach(input => AList.push(input.value));
// JSON 데이터를 hidden input 필드에 저장
document.getElementById('inputList').value = JSON.stringify(inputList);
document.getElementById('bendingrateList').value = JSON.stringify(bendingrateList);
document.getElementById('sumList').value = JSON.stringify(sumList);
document.getElementById('colorList').value = JSON.stringify(colorList);
document.getElementById('AList').value = JSON.stringify(AList);
// 저장 로직 호출 (AJAX)
saveData();
});
$(document).ready(function(){
// 창닫기 버튼
$("#closeBtn").on("click", function() {
self.close();
});
}); // end of ready
// 데이터 저장 함수
function saveData() {
if (ajaxRequest_write !== null) {
ajaxRequest_write.abort();
}
ajaxRequest_write = $.ajax({
url: "process.php",
type: "post",
data: $("#board_form").serialize(),
success: function(data) {
console.log(data);
Toastify({
text: '저장완료',
duration: 3000,
close: true,
gravity: "top",
position: "center",
backgroundColor: "#4fbe87",
}).showToast();
setTimeout(function() {
self.close();
}, 500);
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
}
});
}
</script>
</body>
</html>
위의 코드는 write.php 전체의 코드인데,
mysql 버전이 낮아서 json형태로 저장하는 것이 직접되지 않아서,
text형태로 json 디코드, 인코드하는 과정을 거쳐서 서버에 저장한다.
bending 테이블의 컬럼은 text로 선언된 상태이다.
위의 코드에서 서버로 보낼때 코드에 문제가 없는가?
예전의 사이트에서는 json으로 저장된 것을 아래와 같은 방식으로 form에 저장한 후 서버에 저장한다.
save를 저장하면
예시)
const formData = new FormData(document.getElementById('board_form'));
formData.set('mode', Number($("#num").val()) < 1 ? 'insert' : 'modify');
let itemList = [];
$('#itemListTable tbody tr').each(function() {
let rowData = {};
$(this).find('input, select').each(function() {
let name = $(this).attr('name').replace('[]', '');
rowData[name] = $(this).val();
});
itemList.push(rowData);
});
formData.set('itemList', JSON.stringify(itemList));
서버에서 받을때는 아래와 같은처리함.
// 테이블 데이터 JSON 파싱
if (isset($_POST['itemList'])) {
$itemList_jsondata = json_decode($_POST['itemList'], true);
} else {
$itemList_jsondata = null;
}
if ($mode == "modify") {
$updatelog = date("Y-m-d H:i:s") . " - " . $_SESSION["name"] . " " . $updatelog . "&#10";
try {
$pdo->beginTransaction();
$sql = "UPDATE " . $DB . ".{$tablename} SET
is_deleted=?, orderDate=?, secondord=?, secondordman=?, secondordmantel=?, pjnum=?, pjname=?, jobNo=?, spec=?, daesu=?,
unit=?, deadlineDate=?, drawDate=?, requestmaDate=?, stackmaDate=?, shearingDate=?, nctDate=?, bendingDate=?, assemblyDate=?,
outputDate=?, comment=?, memo=?, unitprice=?, amount=?, invoiceAmount=?, invoiceDate=?, itemList=?,
updatelog=?, status=? , searchtag=? , deliverymethod=?, address=? , makeDate=?
WHERE num=? LIMIT 1";
$stmh = $pdo->prepare($sql);
$params = [
$is_deleted, $orderDate, $secondord, $secondordman, $secondordmantel, $pjnum, $pjname, $jobNo, $spec, $daesu,
$unit, $deadlineDate, $drawDate, $requestmaDate, $stackmaDate, $shearingDate, $nctDate, $bendingDate, $assemblyDate,
$outputDate, $comment, $memo, $unitprice, $amount, $invoiceAmount, $invoiceDate, json_encode($itemList_jsondata),
$updatelog, $status, $searchtag, $deliverymethod, $address , $makeDate , $num
];
위의 자바스크립 코드를 제이쿼리 형식으로 전부 수정해주고,
null에 의한 오류가 안나도록 검사하고 실행하는 코드를 다 넣어주세요.
CREATE TABLE `instock` (
`num` int NOT NULL AUTO_INCREMENT,
`is_deleted` tinyint DEFAULT NULL,
`lot_no` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`inspection_date` date NOT NULL,
`supplier` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`item_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`specification` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`unit` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`received_qty` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`material_no` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`manufacturer` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`remarks` text CHARACTER SET utf8 COLLATE utf8_general_ci,
`purchase_price_excl_vat` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`weight_kg` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`searchtag` text CHARACTER SET utf8 COLLATE utf8_general_ci,
`update_log` text CHARACTER SET utf8 COLLATE utf8_general_ci,
PRIMARY KEY (`num`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
-- dbchandj.material_reg definition
CREATE TABLE material_reg (
num int NOT NULL AUTO_INCREMENT,
is_deleted tinyint DEFAULT NULL,
registedate date NOT NULL,
inoutdate date NOT NULL,
secondord varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
inout_item_code varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
item_name varchar(50) NOT NULL,
surang varchar(10) NOT NULL,
lotnum varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
comment text,
unitprice varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
searchtag text,
update_log text,
secondordnum varchar(10) DEFAULT NULL,
PRIMARY KEY (num)
) ENGINE=InnoDB AUTO_INCREMENT=248 DEFAULT CHARSET=utf8;
위의 형식을 기반으로, 위의 컬럼명은 무시하고,
table 'lot_sales'를 생성하려고 합니다.
컬럼은 아래와 같은데요. 한글을 영문화를 해주세요.
num, 등록일, LOT번호, 작성자, 비고, updatelog, searchtag, is_deleted
num은 고유번호로 autoincrement 적용입니다.
CREATE TABLE `lot_sales` (
`num` int NOT NULL AUTO_INCREMENT, -- 고유번호
`reg_date` date NOT NULL, -- 등록일
`lot_number` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, -- LOT번호
`author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, -- 작성자
`remark` text, -- 비고
`update_log` text, -- 업데이트 로그
`search_tag` text, -- 검색 태그
`is_deleted` tinyint DEFAULT NULL, -- 삭제 여부
PRIMARY KEY (`num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
fetch_modal.php 파일의 내용도 수정하려고 합니다. 위의 컬럼 내용으로
기존의 list.php에서 이 부분이 빠졌는데, 아래의 코드를 완성하고, list.php에서 모달창을 불러오는 과정도 들어가야 합니다.
// 테이블 데이터 JSON 파싱
if (isset($_POST['itemList'])) {
$itemList_jsondata = json_decode($_POST['itemList'], true);
} else {
$itemList_jsondata = null;
}
if ($mode == "modify") {
$updatelog = date("Y-m-d H:i:s") . " - " . $_SESSION["name"] . " " . $updatelog . "&#10";
try {
$pdo->beginTransaction();
$sql = "UPDATE " . $DB . ".{$tablename} SET itemList=? WHERE num=? LIMIT 1";
$stmh = $pdo->prepare($sql);
$params = [
json_encode($itemList_jsondata) , $num
];
// 셔터박스 자동생성 로직 개발
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
$mode = isset($_POST['mode']) ? $_POST['mode'] : '';
$num = isset($_POST['num']) ? $_POST['num'] : '';
$tablename = isset($_POST['tablename']) ? $_POST['tablename'] : '';
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();
if(!isset($DB))
$DB = 'chandj';
try {
$sql = "SELECT * FROM {$DB}.$tablename WHERE num=? ";
$stmh = $pdo->prepare($sql);
$stmh->bindValue(1, $num, PDO::PARAM_INT);
$stmh->execute();
$row = $stmh->fetch(PDO::FETCH_ASSOC);
include '_row.php';
} catch (PDOException $Exception) {
echo "오류: ".$Exception->getMessage();
exit;
}
$title_message = '셔터박스 절곡 전개';
// echo '<pre>';
// print_r($row);
// echo '</pre>';
// 기존에 저장된 값이 있는 경우 해당 값을 설정
$selected_check_typeFlat = isset($row['check_type']) ? $row['check_type'] : '양쪽 점검구';
?>
<style>
.image-container {
position: relative;
display: inline-block;
}
.image-container img {
display: block;
}
.input-overlay {
position: absolute;
background: rgba(255, 255, 255, 0.5);
border: 1px solid blue;
width: 50px;
color: blue;
/* font-weight: bold; */
}
.modal-body {
max-height: 750px; /* 원하는 높이 설정 */
max-width: 1380px; /* 원하는 너비 설정 */
overflow-x: auto; /* 가로 스크롤 가능 */
overflow-y: auto; /* 세로 스크롤 가능 */
}
</style>
<div class="container-fluid">
<div class="d-flex align-items-center justify-content-center">
<div class="card justify-content-center">
<div class="card-header text-center">
<span class="text-center fs-5"><?=$title_message?></span>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col text-center">
<label class="me-3">
<input type="radio" name="check_type_flat" value="양쪽 점검구" <?php if($selected_check_typeFlat === '양쪽 점검구') echo 'checked'; ?> readonly> 양쪽 점검구
</label>
<label class="me-3">
<input type="radio" name="check_type_flat" value="밑면 점검구" <?php if($selected_check_typeFlat === '밑면 점검구') echo 'checked'; ?> readonly> 밑면 점검구
</label>
<label>
<input type="radio" name="check_type_flat" value="후면 점검구" <?php if($selected_check_typeFlat === '후면 점검구') echo 'checked'; ?> readonly> 후면 점검구
</label>
</div>
</div>
<div class="d-flex align-items-center justify-content-center m-2">
<div class="image-container mb-5">
<img id="checkImageFlat" src="<?php
switch ($selected_check_typeFlat) {
case '양쪽 점검구':
echo '../img/box/box_both.png';
break;
case '밑면 점검구':
echo '../img/box/box_bottom.png';
break;
case '후면 점검구':
echo '../img/box/box_back.png';
break;
default:
echo '../img/box/box_both.png'; // 기본값
}
?>" alt="Image">
<input type="text" class="input-overlay" id="front_bottom_width_Flat" value="<?=$front_bottom_width?>" style="top: 370px; left: 110px;" placeholder="전면 밑">
<input type="text" class="input-overlay" id="rail_width_Flat" value="<?=$rail_width?>" style="top: 420px; left: 170px;" placeholder="레일폭">
</div>
</div>
<div class="row justify-content-center text-center">
<div class="d-flex align-items-center justify-content-center m-2">
<table class="table table-bordered">
<tbody>
<tr>
<td class="text-center fs-6 fw-bold" colspan="6" >
<div class="d-flex align-items-center justify-content-center">
<span class="text-center fs-6 ms-1 me-1"> 셔터박스 </span>
<span class="text-center fs-6 ms-1 me-1 text-primary"> 가로(폭) </span>
<input type="text" class="form-control fs-6 w50px text-primary ms-1 me-1" id="box_width_Flat" name="box_width_Flat" value="<?=$box_width?>">
<span class="text-center fs-6 ms-1 me-1"> x </span>
<span class="text-center fs-6 ms-1 me-1 text-danger"> 세로(높이) </span>
<input type="text" class="form-control fs-6 w50px text-danger" id="box_height_Flat" name="box_height_Flat" value="<?=$box_height?>">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="d-flex justify-content-center">
<button type="button" class="btn btn-outline-dark btn-sm me-2 closeBtn">
<ion-icon name="close-circle-outline"></ion-icon> 닫기
</button>
</div>
</div>
</div>
</div>
</div>
위의 코드는 fetch_flat.php 코드이다.
위의 코드에 새로운 내용을 추가할 것이다.
셔터박스의 각 부위에 대한 연산방법을 표현할때 절곡물의 형태에 따라 계산법이 있다.
위의 3가지 유형의 셔터박스의 계산법은 일부는 같고, 일부는 다르다.
그 계산하는 과정을 표현하는 코드는 아래를 참조한다.
<div class="table-container">
<table class="table table-bordered" id="dynamicTable">
<tbody id="tableBody">
<!-- 기본적으로 빈 상태로 두고, JS로 데이터를 추가 -->
</tbody>
</table>
</div>
해당 테이블의 CSS 코드
<style>
.table-container {
width: 100%;
}
#dynamicTable {
table-layout: fixed;
width: 1000px;
}
#dynamicTable th:first-child,
#dynamicTable td:first-child {
width: 100px;
min-width: 100px;
max-width: 100px;
}
#dynamicTable th:nth-child(2),
#dynamicTable td:nth-child(2) {
width: 900px;
min-width: 900px;
max-width: 900px;
}
.input-container {
width: 100%;
white-space: nowrap;
display: flex;
align-items: center;
}
.input-container input,
.input-container span {
display: inline-block;
margin-right: 10px;
}
.input-container input[type="text"] {
width: 40px;
}
.input-container input[type="checkbox"] {
width: 20px;
height: 20px;
margin-right: 10px;
margin-left: 10px;
}
.form-check {
display: flex;
align-items: center;
}
</style>
새로운 테이블은 총 6개의 행으로 구성되며, 각 열의 형성과정은 아래의 코드로 알 수 있다.
function addInitialColumn() {
const tableBody = $('#tableBody');
if (!tableBody.length) return;
const rowsData = [
{ label: '번호', type: 'span', className: 'form-control text-center', style: 'width: 40px;' },
{ label: '입력', type: 'input', className: 'form-control yellowBold text-center', style: 'width: 40px;', name: 'inputList[]', event: 'calculateSum()' },
{ label: '연신율 (-)', type: 'input', className: 'form-control text-center', style: 'width: 40px;', name: 'bendingrateList[]', event: 'calculateSum()' },
{ label: '합계', type: 'input', className: 'form-control orangeBlackBold text-center', style: 'width: 40px;', name: 'sumList[]' },
{ label: '음영', type: 'checkbox', className: 'form-check-input form-control ', style: 'width: 20px; height: 20px; margin-left: 20px; margin-right: 20px;', name: 'colorList[]' },
{ label: 'A각 표시', type: 'checkbox', className: 'form-check-input form-control ', style: 'width: 20px; height: 20px; margin-left: 20px; margin-right: 20px;', name: 'AList[]' }
];
rowsData.forEach(function(rowData) {
const row = $('<tr>');
const labelCell = $('<td>').addClass('lightgray').text(rowData.label);
row.append(labelCell);
const inputCell = $('<td>').addClass('input-container');
if (rowData.type === 'span') {
const span = $('<span>').addClass(rowData.className).css('width', '40px').text('1');
inputCell.append(span);
} else {
const input = $('<input>')
.attr('type', rowData.type)
.addClass(rowData.className)
.css('width', ( rowData.type === 'checkbox' || rowData.type === 'checkbox') ? '20px' : '40px')
.css('margin-left', ( rowData.type === 'checkbox' || rowData.type === 'checkbox') ? '10px' : '')
.css('margin-right', ( rowData.type === 'checkbox' || rowData.type === 'checkbox') ? '20px' : '')
.attr('autocomplete', 'off'); // 올바른 autocomplete 설정
if (rowData.name) input.attr('name', rowData.name);
if (rowData.event) {
input.on('input change', calculateSum);
}
inputCell.append(input);
}
row.append(inputCell);
tableBody.append(row);
});
}
내가 구현하는 것은 셔터박스 형태 3가지 종류에 대한 절곡품 1번부터 7번까지 정보를 위의 코드에서 참조해서 테이블 형태로 화면에 보여주고 싶다.
그 생성원리는 아래와 같다.
1번 전면부 : 7개의 숫자로 이뤄지는데 입력값이 20, 15, 55, 4번째요소는 연산을 해야 한다. $box_height값이 된다. , 5번째 요소는 $front_bottom_width 값이다. ,55,17 이것이 자료가 된다.
2번 린텔부는 고정치수이다. 입력값은 5개의 배열이다. 30,55,50,15,20
일단 2개까지만 만들어줘. 추가로 3번부터 7번까지는 코드의 완성도를 보고 제공하겠다.
#로그기록 함수. common.js 저장됨
function saveMenuLog(title) {
var formData = new FormData();
formData.append('menu', title);
$.ajax({
enctype: 'multipart/form-data', // file을 서버에 전송하려면 이렇게 해야 함 주의
processData: false,
contentType: false,
cache: false,
timeout: 600000,
url: "/insert_logmenu.php",
type: "post",
data: formData,
dataType: "json",
success: function(data){
console.log(data);
},
error: function(jqxhr, status, error) {
console.log(jqxhr, status, error);
alert("An error occurred: " + error); // Display error message
}
});
}
$(document).ready(function(){
// 방문기록 남김
var title = '<?php echo $title_message; ?>';
saveMenuLog(title);
});
## 테이블 기본 생성칼럼
bendingmap 테이블을 생성할 것이다.
<?php
$num = isset($_REQUEST['num']) ? $_REQUEST['num'] : '';
$is_deleted = isset($_REQUEST['is_deleted']) ? $_REQUEST['is_deleted'] : null;
$reg_date = isset($_REQUEST['reg_date']) ? $_REQUEST['reg_date'] : '';
$author = isset($_REQUEST['author']) ? $_REQUEST['author'] : '';
$remark = isset($_REQUEST['remark']) ? $_REQUEST['remark'] : '';
$update_log = isset($_REQUEST['update_log']) ? $_REQUEST['update_log'] : '';
$search_tag = isset($_REQUEST['search_tag']) ? $_REQUEST['search_tag'] : '';
?>
위의 컬럼은 기본적으로 생성한다. 레코드번호, 비고, 업데이트정보, 삭제여부, 작성자, 검색어 정보 등 기본적으로 테이블생성할때 필요한 요소이다.
echo '<td class="text-center" data-bs-toggle="tooltip" data-bs-placement="top" title="전체적용 클릭">' . htmlspecialchars($row['col1']) . '</td>';
data-bs-toggle="tooltip" data-bs-placement="bottom" title="화물회사에서 대한의 요청에 대한 다른 사항이 발생하면 기록합니다."
<!-- 부트스트랩 툴팁 -->
<script>
document.addEventListener('DOMContentLoaded', function () {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
});
</script>
<tr>
<td class="text-center fs-6 fw-bold" style="width:150px;">원자재 LOT</td>
<td colspan="3" class="text-center">
<input type="text" class="form-control fs-6 text-start noborder-input lotnumInput" id="rawLot" name="rawLot" value="<?=$rawLot?>" autocomplete="off" >
</td>
</tr>
위의 코드에서 input요소에 data-searchRaw= 형태로 제이쿼리 data 값을 읽는 형태로 만들고 싶다. 위의 값에 들어갈 것은
해당 품목의 재질을 전달하고자 한다.
품목과 종류의 조합에 따라 재질이 결정된다.
아래의 정보를 참고해 주세요.
품목 : 연기차단재, 종류 : 화이바원단 => '화이바원단'
품목 : 하단마감재(스크린), 종류 : SUS => 'SUS 1.2T'
품목 : 하단마감재(스크린), 종류 : EGI => 'EGI 1.55T'
품목 : L - Bar, 종류 : 스크린용 => 'EGI 1.15T'
품목 : 가이드레일, 종류 : SUS => 'SUS 1.2T'
품목 : 가이드레일, 종류 : D형 => 'EGI 1.55T'
품목 : 가이드레일, 종류 : C형 => 'EGI 1.55T'
품목 : 가이드레일, 종류 : 본체 => 'EGI 1.55T'
품목 : 가이드레일, 종류 : EGI => 'EGI 1.55T'
품목 : 케이스, 종류 : 후면커버 => 'EGI 1.55T'
품목 : 케이스, 종류 : 린텔부 => 'EGI 1.55T'
품목 : 케이스, 종류 : 점검구 => 'EGI 1.55T'
품목 : 케이스, 종류 : 전면부 => 'EGI 1.55T'
위의 내용이 전달되고, 이를 찾는 과정을 코드로 만들어줘.
관련코드를 공유한다.
// 품목명을 매핑하는 배열
$prodNames = [
'R' => '가이드레일(벽면형)',
'S' => '가이드레일(측면형)',
'G' => '연기차단재',
'B' => '하단마감재(스크린)',
'T' => '하단마감재(철재)',
'L' => 'L - Bar',
'C' => '케이스'
];
// 종류명을 매핑하는 배열
$specNames = [
'I' => '화이바원단',
'S' => 'SUS(마감)',
'U' => 'SUS마감2',
'E' => 'EGI(마감)',
'A' => '스크린용',
'D' => 'D형',
'C' => 'C형',
'M' => '본체',
'T' => '본체(철재)',
'B' => '후면커버',
'L' => '린텔부',
'P' => '점검구',
'F' => '전면부'
];
// 모양&길이를 매핑하는 배열
$slengthNames = [
'53' => 'W50 × 3000',
'54' => 'W50 × 4000',
'83' => 'W80 × 3000',
'84' => 'W80 × 4000',
'12' => '1219',
'24' => '2438',
'30' => '3000',
'35' => '3500',
'40' => '4000',
'41' => '4150',
'42' => '4200',
'43' => '4300'
];
위의 코드로 일부 코드가 변경되었다. 아래의 코드에 이 코드를 적용해 주세요.
// 품목별 선택 가능한 종류 목록 설정
const options = {
'G': ['I'], // 연기차단재 - 화이바원단
'B': ['S', 'E'], // 하단마감재(스크린) - SUS, EGI
'T': ['S', 'E'], // 하단마감재(철재) - SUS, EGI
'L': ['A'], // L - Bar - 스크린용
'R': ['S', 'D', 'C', 'M', 'E'], // 가이드레일 - SUS, D형, C형, 본체, EGI
'C': ['B', 'L', 'P', 'F'] // 케이스 - 후면커버, 린텔부, 점검구, 전면부
};
const prodSelect = document.getElementById('prod');
const specSelect = document.getElementById('spec');
const slengthSelect = document.getElementById('slength');
const lotNumberInput = document.getElementById('lot_number');
// 품목 변경 시
$(document).on('change', '#prod', function() {
const selectedProd = this.value;
const specOptions = options[selectedProd] || [];
// 종류 select의 옵션 초기화
specSelect.innerHTML = '<option value="" disabled>종류 선택</option>';
// 종류 select에 해당하는 품목의 옵션 추가
specOptions.forEach(spec => {
let optionText = '';
switch (spec) {
case 'I': optionText = '화이바원단'; break;
case 'S': optionText = 'SUS'; break;
case 'E': optionText = 'EGI'; break;
case 'A': optionText = '스크린용'; break;
case 'D': optionText = 'D형'; break;
case 'C': optionText = 'C형'; break;
case 'M': optionText = '본체'; break;
case 'B': optionText = '후면커버'; break;
case 'L': optionText = '린텔부'; break;
case 'P': optionText = '점검구'; break;
case 'F': optionText = '전면부'; break;
}
위의 코드에서 이런 것을 만들고 싶다.
세부 산출내역서는 각 일련번호에 대한 세부산출서를 나타낸다.
위의 수량, 면적(㎡) 길이(㎜), 면적(㎡) 길이(㎜) 단가, 단가, 즉 4개의 각 행의 요소를 input으로 입력받는다. 이때 class에 noborder-input을 지정해서 입력창의 테두리가 안나오게 할것이다.
4개의 요소의 값을 수동으로 입력해서 저장하고 싶은것이 목적이다.
각 행의 합계는 자동으로 계산되는 로직을 구현하고, 이는 소계, 합계에 영향을 미쳐야 한다.
저장하는 방식은 json형태로 각행을 col1~col4까지 저장하고 이를 json형태로 저장하고, 서버에는 text로 저장하면 된다. php7.3버전은 mysql json 저장방식을 사용할 수 없어서, encode, decode해서 사용한다.
버튼 '수정된 산출내역 저장'을 누르면 위의 수정된 자료가 서버에 전송되고, 저장된다.
최초 로딩될때 서버에 저장된 수정파일이 존재하면, 이 저장된 자료가 최초 로드되어야 한다.
// 일련번호, 검사비
$subtotal += $inspectionFee * $su;
if($option !== 'option')
{
echo '<tr>';
echo '<td class="text-center" id="dynamicRowspan-' . $counter . '" >' . $column['col1'] . '</td>';
echo '<td class="text-center"> 검사비 </td>';
// 수량 입력 필드
echo '<td class="text-center"><input type="text" class="noborder-input text-center su-input number-input" value="' . number_format($su) . '" data-row="' . $counter . '" data-type="su" oninput="inputNumber(this)" /></td>';
// 단위 및 기타 필드
echo '<td class="text-center"> SET </td>';
// 산출식 입력 필드 (예: 수량 * 단가 등으로 계산하는 필드)
echo '<td class="text-center"><input type="text" class="text-left noborder-input calc-formula-input" value="" data-row="' . $counter . '" data-type="formula" /></td>';
// 면적(㎡) 길이(㎜) 입력 필드
echo '<td class="text-center"><input type="text" class="noborder-input text-centerarea-length-input number-input" value="" data-row="' . $counter . '" data-type="area_length" oninput="inputNumber(this)" /></td>';
// 면적(㎡) 길이(㎜) 단가 입력 필드
echo '<td class="text-center"><input type="text" class="noborder-input text-center area-price-input number-input" value="" data-row="' . $counter . '" data-type="area_price" oninput="inputNumber(this)" /></td>';
// 단가 입력 필드
echo '<td class="text-end"><input type="text" class="noborder-input text-end unit-price-input number-input" value="' . number_format($inspectionFee) . '" data-row="' . $counter . '" data-type="unit_price" oninput="inputNumber(this)" /></td>';
// 합계 필드 (자동 계산, 입력 불가)
echo '<td class="text-end total-price" id="total-price-' . $counter . '">' . number_format($inspectionFee * $su) . '</td>';
echo '</tr>';
$rowCount++;
}
위의 코드에서 자바스크립트 코드로 이제 행의 합계, 일련번호의 소계, 전체 합계를 자동으로 계산되는 로직을 만들어야 한다.
계산공식은 아래와 같다. 조건에 따라 약간 다른 연산을 해야 한다.
마지막 td의 합계 금액은 연산을 할 셀의 값이 없으면 거기는 곱하기를 하지 않고,
면적(㎡)
길이(㎜) 요소의 값이 있다면, 수량 * 이 값
(면적(㎡) 길이(㎜) 단가) 이 값이 있으면 곱하기
기본적으로 수량 * 단가인데, 단가를 수동으로 입력하면, 수동입력된 단가에 수량을 곱해서 금액에 표시되어야 한다.
소계는 이런 금액들의 합이고, 전체합계는 소계의 합이 되도록 자바스크립트 코드 만들어줘.
## 혼합형 문구를 파싱해서 변수에 넣는 방법
$railtype의 값이 아래와 같이 '혼합형'이란 단어가 들어있으면 아래의 같은 형태가 된다.
예시) 혼합형(120*70)(120*120)
이 경우는 4개의 숫자를
$rail_length1 = 120;
$rail_width1 = 70;
$rail_length2 = 120;
$rail_width2 = 120;
저장하는 코드를 만들어줘.
// 감기샤프트 데이터에 품목 번호와 수량을 함께 저장
$shaft_data = [
'2인치_300' => ['item_code' => 'SHAFT2', 'quantity' => intval(0)],
'4인치_3000' => ['item_code' => 'SHAFT4', 'quantity' => intval(0)],
'4인치_4500' => ['item_code' => 'SHAFT4', 'quantity' => intval(0)],
'4인치_6000' => ['item_code' => 'SHAFT4', 'quantity' => intval(0)],
'5인치_6000' => ['item_code' => 'SHAFT5', 'quantity' => intval(0)],
'5인치_7000' => ['item_code' => 'SHAFT5', 'quantity' => intval(0)],
'5인치_8200' => ['item_code' => 'SHAFT5', 'quantity' => intval(0)],
];
// 부속자재 데이터에 품목 번호와 수량을 함께 저장
$subs_data = [
'각파이프_3000' => ['item_code' => 'RPIPE3000', 'quantity' => intval(0)],
'각파이프_6000' => ['item_code' => 'RPIPE6000', 'quantity' => intval(0)],
'앵글_2500' => ['item_code' => 'ANGLE2500', 'quantity' => intval(0)],
'마환봉_3000' => ['item_code' => 'POLE3000', 'quantity' => intval(0)],
'받침용앵글_380' => ['item_code' => 'BBR380', 'quantity' => intval(0)],
'하단무게평철_12T' => ['item_code' => 'WEIGHT12T', 'quantity' => intval(0)],
];
위의 3개의 테이블을 생성했다. 이제 모델을 CRUD하는 과정을 코드로 작성하려고 한다.
실제 다른 테이블의 CRUD 작업을 하는 코드를 공유할테니 이를 참조해서 만들어주세요.
루트/models라는 폴더를 만든 후 아래의 파일을 만들것이다.
list.php 모델을 조회하는 기능
write_form.php 모델의 상세조회,입력,수정,삭제 기능
insert.php 서버에서 입력,수정,삭제 기능 수행
_row.php write_form.php에서 저장된 컬럼을 표현한 코드
_request.php insert.php에서 저장할 컬럼을 가져오는 코드
위의 5개의 파일을 만드는 것이다.
다른 곳에서 사용하는 형태를 제공할것이니 이를 수정보완하면 좋겠다.
• list.php 모델 목록 및 검색/신규등록
• write_form.php 모델의 상세보기 및 입력/수정/삭제 폼
• insert.php 서버측에서 실제 DB INSERT/UPDATE/DELETE 수행
• _request.php 입력값을 변수로 할당
• _row.php 조회된 데이터를 폼에 채워 넣기
의 구조로 CRUD 기능을 구현할 수 있습니다.
추후 프론트엔드에서는 모델 선택 시 해당 모델의 부품 및 부품서브를 트리형태(플러스/마이너스 토글)로 확장하여 보여줄 수 있도록 추가하면 BOM 형성 과정을 직관적으로 확인할 수 있습니다.