feat(purchase): 구매 취소/반품 + 입고일 기준 월별 분석
- 상태 추가: cancelled(구매취소), returned(반품) - API: PUT /:id/cancel, /:id/return, /:id/revert-cancel - 데스크탑: 구매완료→취소 버튼, 입고완료→반품 버튼, 취소→되돌리기 - 분석 페이지: 구매일/입고일 기준 전환 토글, 입고일 기준 월간 분류 집계 + 입고 목록 - Settlement API: GET /received-summary, /received-list (입고일 기준) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -233,6 +233,43 @@ const PurchaseRequestModel = {
|
||||
[batchId]
|
||||
);
|
||||
return rows.map(r => r.requester_id);
|
||||
},
|
||||
|
||||
// 구매 취소 (purchased → pending 복원, batch에서도 제거)
|
||||
async cancelPurchase(requestId, { cancelledBy, cancelReason }) {
|
||||
const db = await getDb();
|
||||
await db.query(
|
||||
`UPDATE purchase_requests
|
||||
SET status = 'cancelled', cancelled_at = NOW(), cancelled_by = ?, cancel_reason = ?,
|
||||
batch_id = NULL
|
||||
WHERE request_id = ? AND status = 'purchased'`,
|
||||
[cancelledBy, cancelReason || null, requestId]
|
||||
);
|
||||
return this.getById(requestId);
|
||||
},
|
||||
|
||||
// 반품 (received → returned)
|
||||
async returnItem(requestId, { cancelledBy, cancelReason }) {
|
||||
const db = await getDb();
|
||||
await db.query(
|
||||
`UPDATE purchase_requests
|
||||
SET status = 'returned', cancelled_at = NOW(), cancelled_by = ?, cancel_reason = ?
|
||||
WHERE request_id = ? AND status = 'received'`,
|
||||
[cancelledBy, cancelReason || null, requestId]
|
||||
);
|
||||
return this.getById(requestId);
|
||||
},
|
||||
|
||||
// 취소/반품에서 원래 상태로 되돌리기
|
||||
async revertCancel(requestId) {
|
||||
const db = await getDb();
|
||||
await db.query(
|
||||
`UPDATE purchase_requests
|
||||
SET status = 'pending', cancelled_at = NULL, cancelled_by = NULL, cancel_reason = NULL
|
||||
WHERE request_id = ? AND status = 'cancelled'`,
|
||||
[requestId]
|
||||
);
|
||||
return this.getById(requestId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user