217 lines
9.7 KiB
JavaScript
217 lines
9.7 KiB
JavaScript
const { getPool } = require('./userModel');
|
|
|
|
// ===== 협력업체 =====
|
|
|
|
async function findAll({ search, is_active } = {}) {
|
|
const db = getPool();
|
|
let sql = 'SELECT * FROM partner_companies WHERE 1=1';
|
|
const params = [];
|
|
if (is_active !== undefined) { sql += ' AND is_active = ?'; params.push(is_active); }
|
|
if (search) { sql += ' AND (company_name LIKE ? OR business_number LIKE ?)'; params.push(`%${search}%`, `%${search}%`); }
|
|
sql += ' ORDER BY company_name';
|
|
const [rows] = await db.query(sql, params);
|
|
return rows;
|
|
}
|
|
|
|
async function findById(id) {
|
|
const db = getPool();
|
|
const [rows] = await db.query('SELECT * FROM partner_companies WHERE id = ?', [id]);
|
|
return rows[0] || null;
|
|
}
|
|
|
|
async function create(data) {
|
|
const db = getPool();
|
|
const [result] = await db.query(
|
|
`INSERT INTO partner_companies (company_name, business_number, representative, contact_name, contact_phone, address, business_type, insurance_number, insurance_expiry, notes)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[data.company_name, data.business_number || null, data.representative || null,
|
|
data.contact_name || null, data.contact_phone || null, data.address || null,
|
|
data.business_type ? JSON.stringify(data.business_type) : null,
|
|
data.insurance_number || null, data.insurance_expiry || null, data.notes || null]
|
|
);
|
|
return findById(result.insertId);
|
|
}
|
|
|
|
async function update(id, data) {
|
|
const db = getPool();
|
|
const fields = [];
|
|
const values = [];
|
|
if (data.company_name !== undefined) { fields.push('company_name = ?'); values.push(data.company_name); }
|
|
if (data.business_number !== undefined) { fields.push('business_number = ?'); values.push(data.business_number || null); }
|
|
if (data.representative !== undefined) { fields.push('representative = ?'); values.push(data.representative || null); }
|
|
if (data.contact_name !== undefined) { fields.push('contact_name = ?'); values.push(data.contact_name || null); }
|
|
if (data.contact_phone !== undefined) { fields.push('contact_phone = ?'); values.push(data.contact_phone || null); }
|
|
if (data.address !== undefined) { fields.push('address = ?'); values.push(data.address || null); }
|
|
if (data.business_type !== undefined) { fields.push('business_type = ?'); values.push(data.business_type ? JSON.stringify(data.business_type) : null); }
|
|
if (data.insurance_number !== undefined) { fields.push('insurance_number = ?'); values.push(data.insurance_number || null); }
|
|
if (data.insurance_expiry !== undefined) { fields.push('insurance_expiry = ?'); values.push(data.insurance_expiry || null); }
|
|
if (data.notes !== undefined) { fields.push('notes = ?'); values.push(data.notes || null); }
|
|
if (data.is_active !== undefined) { fields.push('is_active = ?'); values.push(data.is_active); }
|
|
if (fields.length === 0) return findById(id);
|
|
values.push(id);
|
|
await db.query(`UPDATE partner_companies SET ${fields.join(', ')} WHERE id = ?`, values);
|
|
return findById(id);
|
|
}
|
|
|
|
async function deactivate(id) {
|
|
const db = getPool();
|
|
await db.query('UPDATE partner_companies SET is_active = FALSE WHERE id = ?', [id]);
|
|
}
|
|
|
|
// ===== 작업자 =====
|
|
|
|
async function findWorkersByCompany(companyId) {
|
|
const db = getPool();
|
|
const [rows] = await db.query(
|
|
'SELECT * FROM partner_workers WHERE company_id = ? ORDER BY is_team_leader DESC, worker_name',
|
|
[companyId]
|
|
);
|
|
return rows;
|
|
}
|
|
|
|
async function findWorkerById(id) {
|
|
const db = getPool();
|
|
const [rows] = await db.query('SELECT * FROM partner_workers WHERE id = ?', [id]);
|
|
return rows[0] || null;
|
|
}
|
|
|
|
async function createWorker(companyId, data) {
|
|
const db = getPool();
|
|
const [result] = await db.query(
|
|
`INSERT INTO partner_workers (company_id, worker_name, position, is_team_leader, phone, safety_training_date, notes)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
[companyId, data.worker_name, data.position || null,
|
|
data.is_team_leader || false, data.phone || null,
|
|
data.safety_training_date || null, data.notes || null]
|
|
);
|
|
return findWorkerById(result.insertId);
|
|
}
|
|
|
|
async function updateWorker(id, data) {
|
|
const db = getPool();
|
|
const fields = [];
|
|
const values = [];
|
|
if (data.worker_name !== undefined) { fields.push('worker_name = ?'); values.push(data.worker_name); }
|
|
if (data.position !== undefined) { fields.push('position = ?'); values.push(data.position || null); }
|
|
if (data.is_team_leader !== undefined) { fields.push('is_team_leader = ?'); values.push(data.is_team_leader); }
|
|
if (data.phone !== undefined) { fields.push('phone = ?'); values.push(data.phone || null); }
|
|
if (data.safety_training_date !== undefined) { fields.push('safety_training_date = ?'); values.push(data.safety_training_date || null); }
|
|
if (data.notes !== undefined) { fields.push('notes = ?'); values.push(data.notes || null); }
|
|
if (data.is_active !== undefined) { fields.push('is_active = ?'); values.push(data.is_active); }
|
|
if (fields.length === 0) return findWorkerById(id);
|
|
values.push(id);
|
|
await db.query(`UPDATE partner_workers SET ${fields.join(', ')} WHERE id = ?`, values);
|
|
return findWorkerById(id);
|
|
}
|
|
|
|
async function deactivateWorker(id) {
|
|
const db = getPool();
|
|
await db.query('UPDATE partner_workers SET is_active = FALSE WHERE id = ?', [id]);
|
|
}
|
|
|
|
async function getDeleteInfo(companyId) {
|
|
const db = getPool();
|
|
const [[workers]] = await db.query('SELECT COUNT(*) as cnt FROM partner_workers WHERE company_id = ?', [companyId]);
|
|
const [[schedules]] = await db.query('SELECT COUNT(*) as cnt FROM partner_schedules WHERE company_id = ?', [companyId]);
|
|
const [[checkins]] = await db.query('SELECT COUNT(*) as cnt FROM partner_work_checkins WHERE company_id = ?', [companyId]);
|
|
const [[reports]] = await db.query('SELECT COUNT(*) as cnt FROM partner_work_reports WHERE company_id = ?', [companyId]);
|
|
const [[visits]] = await db.query('SELECT COUNT(*) as cnt FROM daily_visits WHERE company_id = ?', [companyId]);
|
|
const [[accounts]] = await db.query('SELECT COUNT(*) as cnt FROM sso_users WHERE partner_company_id = ?', [companyId]);
|
|
|
|
// 삭제 차단 조건: 해당 업체 SSO 계정이 구매 이력을 가지고 있는지
|
|
const [userRows] = await db.query('SELECT user_id FROM sso_users WHERE partner_company_id = ?', [companyId]);
|
|
const userIds = userRows.map(r => r.user_id);
|
|
let purchaseRequests = 0;
|
|
let purchases = 0;
|
|
if (userIds.length > 0) {
|
|
const [[pr]] = await db.query('SELECT COUNT(*) as cnt FROM purchase_requests WHERE requester_id IN (?)', [userIds]);
|
|
const [[pu]] = await db.query('SELECT COUNT(*) as cnt FROM purchases WHERE purchaser_id IN (?)', [userIds]);
|
|
purchaseRequests = pr.cnt;
|
|
purchases = pu.cnt;
|
|
}
|
|
|
|
return {
|
|
workers: workers.cnt,
|
|
schedules: schedules.cnt,
|
|
checkins: checkins.cnt,
|
|
reports: reports.cnt,
|
|
visits: visits.cnt,
|
|
accounts: accounts.cnt,
|
|
purchaseRequests,
|
|
purchases
|
|
};
|
|
}
|
|
|
|
async function permanentDelete(companyId, requestUserId) {
|
|
const db = getPool();
|
|
|
|
// 사전 체크: 구매 이력 확인
|
|
const [userRows] = await db.query('SELECT user_id FROM sso_users WHERE partner_company_id = ?', [companyId]);
|
|
const userIds = userRows.map(r => r.user_id);
|
|
if (userIds.length > 0) {
|
|
const [[pr]] = await db.query('SELECT COUNT(*) as cnt FROM purchase_requests WHERE requester_id IN (?)', [userIds]);
|
|
const [[pu]] = await db.query('SELECT COUNT(*) as cnt FROM purchases WHERE purchaser_id IN (?)', [userIds]);
|
|
if (pr.cnt > 0 || pu.cnt > 0) {
|
|
throw new Error('구매 이력이 있어 삭제할 수 없습니다. 비활성화를 이용해주세요.');
|
|
}
|
|
}
|
|
|
|
// 작업자 ID 조회
|
|
const [workerRows] = await db.query('SELECT id FROM partner_workers WHERE company_id = ?', [companyId]);
|
|
const workerIds = workerRows.map(r => r.id);
|
|
|
|
const conn = await db.getConnection();
|
|
try {
|
|
await conn.beginTransaction();
|
|
|
|
// 1. work_report_workers에서 해당 업체 작업자 참조 SET NULL
|
|
if (workerIds.length > 0) {
|
|
await conn.query('UPDATE work_report_workers SET partner_worker_id = NULL WHERE partner_worker_id IN (?)', [workerIds]);
|
|
}
|
|
|
|
// 2. partner_work_reports 삭제 (→ work_report_workers CASCADE 자동)
|
|
await conn.query('DELETE FROM partner_work_reports WHERE company_id = ?', [companyId]);
|
|
|
|
// 3. partner_work_checkins 삭제
|
|
await conn.query('DELETE FROM partner_work_checkins WHERE company_id = ?', [companyId]);
|
|
|
|
// 4. partner_schedules 삭제
|
|
await conn.query('DELETE FROM partner_schedules WHERE company_id = ?', [companyId]);
|
|
|
|
// 5. daily_visit_workers에서 해당 업체 작업자 참조 SET NULL
|
|
if (workerIds.length > 0) {
|
|
await conn.query('UPDATE daily_visit_workers SET partner_worker_id = NULL WHERE partner_worker_id IN (?)', [workerIds]);
|
|
}
|
|
|
|
// 6. daily_visits는 SET NULL 자동 (방문기록 보존)
|
|
|
|
// 7. partner_workers 삭제
|
|
await conn.query('DELETE FROM partner_workers WHERE company_id = ?', [companyId]);
|
|
|
|
// 8. 협력업체 SSO 계정 처리
|
|
if (userIds.length > 0) {
|
|
await conn.query('UPDATE sp_vacation_requests SET reviewed_by = NULL WHERE reviewed_by IN (?)', [userIds]);
|
|
await conn.query('DELETE FROM sp_vacation_requests WHERE user_id IN (?)', [userIds]);
|
|
await conn.query('UPDATE sp_vacation_balances SET created_by = ? WHERE created_by IN (?)', [requestUserId, userIds]);
|
|
await conn.query('DELETE FROM sp_vacation_balances WHERE user_id IN (?)', [userIds]);
|
|
await conn.query('DELETE FROM sso_users WHERE partner_company_id = ?', [companyId]);
|
|
}
|
|
|
|
// 9. partner_companies 삭제
|
|
await conn.query('DELETE FROM partner_companies WHERE id = ?', [companyId]);
|
|
|
|
await conn.commit();
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
throw err;
|
|
} finally {
|
|
conn.release();
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
findAll, findById, create, update, deactivate,
|
|
findWorkersByCompany, findWorkerById, createWorker, updateWorker, deactivateWorker,
|
|
getDeleteInfo, permanentDelete
|
|
};
|