Files
tk-factory-services/tkpurchase/api/models/partnerModel.js
Hyungi Ahn 281f5d35d1 feat: tkpurchase 시스템 Phase 1 - 협력업체 마스터 + 당일 방문 관리
신규 독립 시스템 tkpurchase (구매/방문 관리) 구축:
- 협력업체 CRUD + 소속 작업자 관리 (마스터 데이터 소유)
- 당일 방문 등록/체크인/체크아웃 + 일괄 마감
- 업체 자동완성, CSV 내보내기, 집계 통계
- 자정 자동 체크아웃 (node-cron)
- tkuser 협력업체 읽기 전용 탭 + 권한 그리드(tkpurchase-perms) 추가
- docker-compose에 tkpurchase-api/web 서비스 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 15:45:37 +09:00

142 lines
6.0 KiB
JavaScript

const mysql = require('mysql2/promise');
let pool;
function getPool() {
if (!pool) {
pool = mysql.createPool({
host: process.env.DB_HOST || 'mariadb',
port: parseInt(process.env.DB_PORT) || 3306,
user: process.env.DB_USER || 'hyungi_user',
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME || 'hyungi',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
}
return pool;
}
// ===== 협력업체 =====
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 search(q) {
const db = getPool();
const [rows] = await db.query(
'SELECT id, company_name, business_number FROM partner_companies WHERE is_active = TRUE AND company_name LIKE ? ORDER BY company_name LIMIT 20',
[`%${q}%`]
);
return rows;
}
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]);
}
module.exports = {
getPool, findAll, findById, search, create, update, deactivate,
findWorkersByCompany, findWorkerById, createWorker, updateWorker, deactivateWorker
};