tkuser: 업체(공급업체) CRUD + 소모품 마스터 CRUD (사진 업로드 포함) tkfb: 구매신청 → 구매 처리 → 월간 분석/정산 전체 워크플로 설비(equipment) 분류 구매 시 자동 등록 + 실패 시 admin 알림 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
4.0 KiB
JavaScript
105 lines
4.0 KiB
JavaScript
const PurchaseModel = require('../models/purchaseModel');
|
|
const PurchaseRequestModel = require('../models/purchaseRequestModel');
|
|
const logger = require('../utils/logger');
|
|
|
|
const PurchaseController = {
|
|
// 구매 처리 (신청 → 구매)
|
|
create: async (req, res) => {
|
|
try {
|
|
const { request_id, item_id, vendor_id, quantity, unit_price, purchase_date, update_base_price, notes } = req.body;
|
|
|
|
if (!item_id) return res.status(400).json({ success: false, message: '소모품을 선택해주세요.' });
|
|
if (!unit_price) return res.status(400).json({ success: false, message: '구매 단가를 입력해주세요.' });
|
|
if (!purchase_date) return res.status(400).json({ success: false, message: '구매일을 입력해주세요.' });
|
|
|
|
// 구매 내역 생성
|
|
const purchaseId = await PurchaseModel.createFromRequest({
|
|
request_id: request_id || null,
|
|
item_id,
|
|
vendor_id: vendor_id || null,
|
|
quantity: quantity || 1,
|
|
unit_price,
|
|
purchase_date,
|
|
purchaser_id: req.user.id,
|
|
notes
|
|
});
|
|
|
|
// 기준가 업데이트 요청 시
|
|
if (update_base_price) {
|
|
const items = await PurchaseModel.getConsumableItems(false);
|
|
const item = items.find(i => i.item_id === parseInt(item_id));
|
|
if (item) {
|
|
await PurchaseModel.updateBasePrice(item_id, unit_price, item.base_price, req.user.id);
|
|
}
|
|
}
|
|
|
|
// 설비 자동 등록 (category='equipment')
|
|
let equipmentResult = null;
|
|
if (request_id) {
|
|
const requestData = await PurchaseRequestModel.getById(request_id);
|
|
if (requestData && requestData.category === 'equipment') {
|
|
equipmentResult = await PurchaseModel.tryAutoRegisterEquipment({
|
|
item_name: requestData.item_name,
|
|
maker: requestData.maker,
|
|
vendor_name: null,
|
|
unit_price,
|
|
purchase_date,
|
|
purchase_id: purchaseId,
|
|
purchaser_id: req.user.id
|
|
});
|
|
}
|
|
} else {
|
|
// 직접 구매 시에도 category 확인
|
|
const items = await PurchaseModel.getConsumableItems(false);
|
|
const item = items.find(i => i.item_id === parseInt(item_id));
|
|
if (item && item.category === 'equipment') {
|
|
const vendors = await PurchaseModel.getVendors();
|
|
const vendor = vendors.find(v => v.vendor_id === parseInt(vendor_id));
|
|
equipmentResult = await PurchaseModel.tryAutoRegisterEquipment({
|
|
item_name: item.item_name,
|
|
maker: item.maker,
|
|
vendor_name: vendor ? vendor.vendor_name : null,
|
|
unit_price,
|
|
purchase_date,
|
|
purchase_id: purchaseId,
|
|
purchaser_id: req.user.id
|
|
});
|
|
}
|
|
}
|
|
|
|
const result = { purchase_id: purchaseId };
|
|
if (equipmentResult) result.equipment = equipmentResult;
|
|
|
|
res.status(201).json({ success: true, data: result, message: '구매 처리가 완료되었습니다.' });
|
|
} catch (err) {
|
|
logger.error('Purchase create error:', err);
|
|
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
|
|
}
|
|
},
|
|
|
|
// 구매 내역 목록
|
|
getAll: async (req, res) => {
|
|
try {
|
|
const { vendor_id, category, from_date, to_date, year_month } = req.query;
|
|
const rows = await PurchaseModel.getAll({ vendor_id, category, from_date, to_date, year_month });
|
|
res.json({ success: true, data: rows });
|
|
} catch (err) {
|
|
logger.error('Purchase getAll error:', err);
|
|
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
|
|
}
|
|
},
|
|
|
|
// 가격 변동 이력
|
|
getPriceHistory: async (req, res) => {
|
|
try {
|
|
const rows = await PurchaseModel.getPriceHistory(req.params.itemId);
|
|
res.json({ success: true, data: rows });
|
|
} catch (err) {
|
|
logger.error('PriceHistory get error:', err);
|
|
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = PurchaseController;
|