feat: [dev] 입고 강제생성 API 추가 (POST /dev/force-receiving)
This commit is contained in:
@@ -7,8 +7,14 @@
|
||||
use App\Http\Requests\V1\Receiving\ProcessReceivingRequest;
|
||||
use App\Http\Requests\V1\Receiving\StoreReceivingRequest;
|
||||
use App\Http\Requests\V1\Receiving\UpdateReceivingRequest;
|
||||
use App\Models\Items\Item;
|
||||
use App\Models\Qualitys\Inspection;
|
||||
use App\Models\Tenants\Receiving;
|
||||
use App\Models\Tenants\Stock;
|
||||
use App\Models\Tenants\StockLot;
|
||||
use App\Services\ReceivingService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReceivingController extends Controller
|
||||
{
|
||||
@@ -96,4 +102,179 @@ public function process(int $id, ProcessReceivingRequest $request)
|
||||
|
||||
return ApiResponse::success($receiving, __('message.receiving.processed'));
|
||||
}
|
||||
|
||||
/**
|
||||
* [개발전용] 입고 강제 생성 (입고 + 재고 + 수입검사 한번에)
|
||||
*
|
||||
* POST /api/v1/dev/force-receiving
|
||||
* Body: { item_id: number, qty?: number }
|
||||
*/
|
||||
public function forceCreate(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'item_id' => 'required|integer',
|
||||
'qty' => 'nullable|integer|min:1|max:10000',
|
||||
]);
|
||||
|
||||
$tenantId = app('tenant_id');
|
||||
$itemId = $request->input('item_id');
|
||||
$qty = $request->input('qty', 100);
|
||||
$userId = auth()->id() ?? 33;
|
||||
$date = now()->toDateString();
|
||||
|
||||
$item = Item::withoutGlobalScopes()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('id', $itemId)
|
||||
->first();
|
||||
|
||||
if (! $item) {
|
||||
return ApiResponse::error(__('error.not_found'), 404);
|
||||
}
|
||||
|
||||
$result = DB::transaction(function () use ($item, $tenantId, $qty, $userId, $date) {
|
||||
$datePrefix = date('Ymd', strtotime($date));
|
||||
$dateShort = date('ymd', strtotime($date));
|
||||
|
||||
// 채번
|
||||
$receivingSeq = (Receiving::withoutGlobalScopes()->where('tenant_id', $tenantId)
|
||||
->where('receiving_number', 'LIKE', "RV{$datePrefix}%")->count()) + 1;
|
||||
$lotSeq = (StockLot::withoutGlobalScopes()->where('tenant_id', $tenantId)
|
||||
->where('lot_no', 'LIKE', "{$dateShort}-%")->count()) + 1;
|
||||
$inspSeq = (Inspection::withoutGlobalScopes()->where('tenant_id', $tenantId)
|
||||
->where('inspection_no', 'LIKE', "IQC-{$dateShort}-%")->count()) + 1;
|
||||
|
||||
$receivingNumber = 'RV'.$datePrefix.str_pad($receivingSeq, 4, '0', STR_PAD_LEFT);
|
||||
$lotNo = $dateShort.'-'.str_pad($lotSeq, 2, '0', STR_PAD_LEFT);
|
||||
$orderNo = 'PO-'.$dateShort.'-DEV'.str_pad(rand(1, 999), 3, '0', STR_PAD_LEFT);
|
||||
|
||||
// 1. Receiving 생성
|
||||
$receiving = Receiving::withoutGlobalScopes()->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'receiving_number' => $receivingNumber,
|
||||
'order_no' => $orderNo,
|
||||
'order_date' => $date,
|
||||
'item_id' => $item->id,
|
||||
'item_code' => $item->code,
|
||||
'item_name' => $item->name,
|
||||
'supplier' => '(주)테스트공급업체',
|
||||
'order_qty' => $qty,
|
||||
'order_unit' => $item->unit ?: 'EA',
|
||||
'due_date' => $date,
|
||||
'receiving_qty' => $qty,
|
||||
'receiving_date' => $date,
|
||||
'lot_no' => $lotNo,
|
||||
'supplier_lot' => 'DEV-'.rand(1000, 9999),
|
||||
'receiving_location' => 'A-01-01',
|
||||
'receiving_manager' => '개발자',
|
||||
'status' => 'completed',
|
||||
'remark' => '[개발전용] 강제 생성 입고',
|
||||
'options' => [
|
||||
'inspection_status' => '적',
|
||||
'inspection_date' => $date,
|
||||
'inspection_result' => '합격',
|
||||
'force_created' => true,
|
||||
],
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
// 2. Stock 생성/갱신
|
||||
$itemTypeMap = ['FG' => 'purchased_part', 'PT' => 'bent_part', 'SM' => 'sub_material', 'RM' => 'raw_material', 'CS' => 'consumable'];
|
||||
$stockType = $itemTypeMap[$item->item_type] ?? 'raw_material';
|
||||
|
||||
$stock = Stock::withoutGlobalScopes()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('item_id', $item->id)
|
||||
->first();
|
||||
|
||||
if ($stock) {
|
||||
$stock->stock_qty += $qty;
|
||||
$stock->available_qty += $qty;
|
||||
$stock->lot_count += 1;
|
||||
$stock->last_receipt_date = $date;
|
||||
$stock->status = 'normal';
|
||||
$stock->updated_by = $userId;
|
||||
$stock->save();
|
||||
} else {
|
||||
$stock = Stock::withoutGlobalScopes()->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'item_id' => $item->id,
|
||||
'item_code' => $item->code,
|
||||
'item_name' => $item->name,
|
||||
'item_type' => $stockType,
|
||||
'unit' => $item->unit ?: 'EA',
|
||||
'stock_qty' => $qty,
|
||||
'safety_stock' => 10,
|
||||
'reserved_qty' => 0,
|
||||
'available_qty' => $qty,
|
||||
'lot_count' => 1,
|
||||
'oldest_lot_date' => $date,
|
||||
'location' => 'A-01-01',
|
||||
'status' => 'normal',
|
||||
'last_receipt_date' => $date,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
// 3. StockLot 생성
|
||||
$nextFifo = (StockLot::withoutGlobalScopes()->where('stock_id', $stock->id)->max('fifo_order') ?? 0) + 1;
|
||||
StockLot::withoutGlobalScopes()->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'stock_id' => $stock->id,
|
||||
'lot_no' => $lotNo,
|
||||
'fifo_order' => $nextFifo,
|
||||
'receipt_date' => $date,
|
||||
'qty' => $qty,
|
||||
'reserved_qty' => 0,
|
||||
'available_qty' => $qty,
|
||||
'unit' => $item->unit ?: 'EA',
|
||||
'supplier' => '(주)테스트공급업체',
|
||||
'supplier_lot' => $receiving->supplier_lot,
|
||||
'po_number' => $orderNo,
|
||||
'location' => 'A-01-01',
|
||||
'status' => 'available',
|
||||
'receiving_id' => $receiving->id,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 4. IQC 수입검사 생성 (합격)
|
||||
$inspectionNo = 'IQC-'.$dateShort.'-'.str_pad($inspSeq, 4, '0', STR_PAD_LEFT);
|
||||
Inspection::withoutGlobalScopes()->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'inspection_no' => $inspectionNo,
|
||||
'inspection_type' => 'IQC',
|
||||
'status' => 'completed',
|
||||
'result' => 'pass',
|
||||
'request_date' => $date,
|
||||
'inspection_date' => $date,
|
||||
'item_id' => $item->id,
|
||||
'lot_no' => $lotNo,
|
||||
'meta' => [
|
||||
'quantity' => $qty,
|
||||
'unit' => $item->unit ?: 'EA',
|
||||
'item_code' => $item->code,
|
||||
'item_name' => $item->name,
|
||||
'force_created' => true,
|
||||
],
|
||||
'items' => [
|
||||
['item' => '외관검사', 'standard' => '이상 없을 것', 'result' => '양호', 'judgment' => '적'],
|
||||
['item' => '치수검사', 'standard' => '규격 일치', 'result' => '양호', 'judgment' => '적'],
|
||||
],
|
||||
'extra' => ['remarks' => '[개발전용] 자동 합격', 'opinion' => '양호'],
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
return [
|
||||
'receiving_number' => $receivingNumber,
|
||||
'lot_no' => $lotNo,
|
||||
'item_code' => $item->code,
|
||||
'item_name' => $item->name,
|
||||
'qty' => $qty,
|
||||
'available_qty' => $stock->available_qty,
|
||||
];
|
||||
});
|
||||
|
||||
return ApiResponse::success($result, '입고 데이터가 강제 생성되었습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user