feat: [stocks] 거래이력(사용현황) API 추가 (GET /stocks/{id}/transactions)
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
use App\Services\StockService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StockController extends Controller
|
||||
{
|
||||
@@ -126,4 +127,95 @@ public function storeAdjustment(int $id, StoreStockAdjustmentRequest $request):
|
||||
return ApiResponse::error(__('error.stock.not_found'), 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 재고 거래이력 (사용현황)
|
||||
* GET /api/v1/stocks/{id}/transactions
|
||||
*/
|
||||
public function transactions(int $id): JsonResponse
|
||||
{
|
||||
$tenantId = app('tenant_id');
|
||||
|
||||
$stock = DB::table('stocks')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('item_id', $id)
|
||||
->first();
|
||||
|
||||
if (! $stock) {
|
||||
// item_id로 직접 검색
|
||||
$stock = DB::table('stocks')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('id', $id)
|
||||
->first();
|
||||
}
|
||||
|
||||
$stockId = $stock?->id;
|
||||
$itemCode = $stock?->item_code;
|
||||
|
||||
$transactions = DB::table('stock_transactions')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where(function ($q) use ($stockId, $itemCode) {
|
||||
if ($stockId) {
|
||||
$q->where('stock_id', $stockId);
|
||||
}
|
||||
if ($itemCode) {
|
||||
$q->orWhere('item_code', $itemCode);
|
||||
}
|
||||
})
|
||||
->orderByDesc('created_at')
|
||||
->limit(100)
|
||||
->get([
|
||||
'id', 'type', 'qty', 'balance_qty', 'reference_type', 'reference_id',
|
||||
'lot_no', 'reason', 'remark', 'item_code', 'item_name', 'created_by', 'created_at',
|
||||
]);
|
||||
|
||||
// 참조 정보 보강 (work_order 번호 등)
|
||||
$woIds = $transactions->where('reference_type', 'work_order_input')
|
||||
->pluck('reference_id')->unique()->values();
|
||||
$woMap = [];
|
||||
if ($woIds->isNotEmpty()) {
|
||||
$woMap = DB::table('work_orders')
|
||||
->whereIn('id', $woIds)
|
||||
->pluck('work_order_no', 'id')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
$data = $transactions->map(function ($tx) use ($woMap) {
|
||||
$refLabel = match ($tx->reference_type) {
|
||||
'work_order_input' => '자재투입',
|
||||
'work_order_input_cancel' => '자재투입 취소',
|
||||
'work_order_input_replace' => '자재투입 교체',
|
||||
'receiving' => '입고',
|
||||
'adjustment' => '재고조정',
|
||||
'shipment' => '출하',
|
||||
default => $tx->reference_type ?? '-',
|
||||
};
|
||||
$refNo = $woMap[$tx->reference_id] ?? null;
|
||||
|
||||
return [
|
||||
'id' => $tx->id,
|
||||
'type' => $tx->type,
|
||||
'type_label' => $refLabel,
|
||||
'qty' => (float) $tx->qty,
|
||||
'balance_qty' => (float) $tx->balance_qty,
|
||||
'reference_type' => $tx->reference_type,
|
||||
'reference_id' => $tx->reference_id,
|
||||
'reference_no' => $refNo,
|
||||
'lot_no' => $tx->lot_no,
|
||||
'reason' => $tx->reason,
|
||||
'remark' => $tx->remark,
|
||||
'item_code' => $tx->item_code,
|
||||
'item_name' => $tx->item_name,
|
||||
'created_at' => $tx->created_at,
|
||||
];
|
||||
});
|
||||
|
||||
return ApiResponse::success([
|
||||
'item_code' => $stock?->item_code,
|
||||
'item_name' => $stock?->item_name,
|
||||
'current_qty' => (float) ($stock?->stock_qty ?? 0),
|
||||
'available_qty' => (float) ($stock?->available_qty ?? 0),
|
||||
'transactions' => $data,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user