feat: 구매/안전 시스템 전면 개편 — tkpurchase 개편 + tksafety 신규 + 권한 보강

Phase 1: tkuser 협력업체 CRUD 이관 (읽기전용 → 전체 CRUD)
Phase 2: tkpurchase 개편 — 일용공 신청/확정, 작업일정, 업무현황, 계정관리, 협력업체 포털
Phase 3: tksafety 신규 시스템 — 방문관리 + 안전교육 신고
Phase 4: SSO 인증 보강 (partner_company_id JWT, 만료일 체크), 권한 테이블 기반 접근 제어

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-12 17:42:59 +09:00
parent a195dd1d50
commit b800792152
63 changed files with 5548 additions and 262 deletions

View File

@@ -0,0 +1,14 @@
const express = require('express');
const router = express.Router();
const { requireAuth } = require('../middleware/auth');
const ctrl = require('../controllers/checkinController');
router.use(requireAuth);
router.get('/schedule/:scheduleId', ctrl.list);
router.get('/my', ctrl.myCheckins); // partner portal
router.post('/', ctrl.checkIn); // partner can do this
router.put('/:id/checkout', ctrl.checkOut);
router.put('/:id', ctrl.update);
module.exports = router;

View File

@@ -0,0 +1,16 @@
const express = require('express');
const router = express.Router();
const { requireAuth, requirePage } = require('../middleware/auth');
const ctrl = require('../controllers/dayLaborController');
router.use(requireAuth);
router.get('/', ctrl.list);
router.get('/stats', ctrl.stats);
router.get('/:id', ctrl.getById);
router.post('/', ctrl.create); // any authenticated user can request
router.put('/:id/approve', requirePage('purchasing_daylabor'), ctrl.approve);
router.put('/:id/reject', requirePage('purchasing_daylabor'), ctrl.reject);
router.put('/:id/complete', requirePage('purchasing_daylabor'), ctrl.complete);
module.exports = router;

View File

@@ -0,0 +1,13 @@
const express = require('express');
const router = express.Router();
const { requireAuth, requirePage } = require('../middleware/auth');
const ctrl = require('../controllers/partnerAccountController');
router.use(requireAuth);
router.get('/company/:companyId', requirePage('purchasing_accounts'), ctrl.listByCompany);
router.post('/', requirePage('purchasing_accounts'), ctrl.create);
router.put('/:id', requirePage('purchasing_accounts'), ctrl.update);
router.delete('/:id', requirePage('purchasing_accounts'), ctrl.deactivate);
module.exports = router;

View File

@@ -1,20 +1,14 @@
const express = require('express');
const router = express.Router();
const { requireAuth, requirePage } = require('../middleware/auth');
const { requireAuth } = require('../middleware/auth');
const ctrl = require('../controllers/partnerController');
router.use(requireAuth);
// Read-only: CRUD는 tkuser로 이관됨
router.get('/search', ctrl.searchCompanies);
router.get('/', ctrl.list);
router.get('/:id', ctrl.getById);
router.post('/', requirePage('purchasing_partner'), ctrl.create);
router.put('/:id', requirePage('purchasing_partner'), ctrl.update);
router.delete('/:id', requirePage('purchasing_partner'), ctrl.deactivate);
router.get('/:id/workers', ctrl.listWorkers);
router.post('/:id/workers', requirePage('purchasing_partner'), ctrl.createWorker);
router.put('/workers/:id', requirePage('purchasing_partner'), ctrl.updateWorker);
router.delete('/workers/:id', requirePage('purchasing_partner'), ctrl.deactivateWorker);
module.exports = router;

View File

@@ -0,0 +1,16 @@
const express = require('express');
const router = express.Router();
const { requireAuth, requirePage } = require('../middleware/auth');
const ctrl = require('../controllers/scheduleController');
router.use(requireAuth);
router.get('/', ctrl.list);
router.get('/my', ctrl.mySchedules); // partner portal
router.get('/:id', ctrl.getById);
router.post('/', requirePage('purchasing_schedule'), ctrl.create);
router.put('/:id', requirePage('purchasing_schedule'), ctrl.update);
router.put('/:id/status', requirePage('purchasing_schedule'), ctrl.updateStatus);
router.delete('/:id', requirePage('purchasing_schedule'), ctrl.deleteSchedule);
module.exports = router;

View File

@@ -0,0 +1,15 @@
const express = require('express');
const router = express.Router();
const { requireAuth, requirePage } = require('../middleware/auth');
const ctrl = require('../controllers/workReportController');
router.use(requireAuth);
router.get('/', ctrl.list);
router.get('/my', ctrl.myReports); // partner portal
router.get('/:id', ctrl.getById);
router.post('/', ctrl.create); // partner can create
router.put('/:id', ctrl.update);
router.put('/:id/confirm', requirePage('purchasing_workreport'), ctrl.confirm);
module.exports = router;