입출고 처리까지

This commit is contained in:
choibk 2025-12-06 23:46:48 +09:00
parent 83c569b231
commit 3958ed8b80
8 changed files with 137 additions and 4 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\StockLog;
use Illuminate\Http\Request;
class StockLogController extends Controller
{
public function Input(Request $request, $id)
{
// queryString action 의 default value 는 in 으로 한다.
$action = $request->query('action','in');
if(!in_array($action, ['in','out']))
{
abort(400, '잘못된 action 값 입니다.');
}
$title = ($action == 'in') ? '입고 등록' : '출고 등록';
// Product 조회 ( or 404)
$product = Product::findOrFail($id);
// Blade 뷰에 Product 전달
return view('stock.input', compact('product', 'title', 'action'));
}
public function Store(Request $request, $id)
{
$action = $request->query('action', 'in');
if(!in_array($action, ['in','out']))
{
abort(400, '잘못된 action 값 입니다.');
}
$product = Product::findOrFail($id);
$validated = $request->validate([
'amount' => ['required', 'integer', 'min:1']
]);
StockLog::create([
'product_id' => $product->id,
'change_type' => $action,
'change_amount' => $validated['amount']
]);
return redirect()->route('product')->with('success', $action == 'in' ? '입고처리 완료' : '출고처리 완료');
}
}

View File

@ -13,4 +13,9 @@ class Product extends Model
$return = self::select('id', 'name', 'sku', 'price', 'quantity', 'created_at'); $return = self::select('id', 'name', 'sku', 'price', 'quantity', 'created_at');
return $return->paginate(1); return $return->paginate(1);
} }
public function stockLogs()
{
return $this->hasMany(StockLog::class);
}
} }

16
app/Models/StockLog.php Normal file
View File

@ -0,0 +1,16 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class StockLog extends Model
{
protected $table = 'stock_logs';
protected $guarded = [];
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}
}

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('stock_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('product_id');
$table->foreign('product_id')
->references('id')
->on('products')
->onDelete('cascade');
$table->enum('change_type', ['in', 'out'])->comment('입출고 구분');
$table->integer('change_amount')->comment('입출고 수량');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('stock_logs');
}
};

View File

@ -19,9 +19,9 @@ class DatabaseSeeder extends Seeder
// User::factory(10)->create(); // User::factory(10)->create();
User::factory()->create([ User::factory()->create([
'name' => 'sokuree', 'name' => '관리자',
'email' => 'sokuree@sokuree.com', 'email' => 'sokuree@sokuree.com',
'password' => Hash::make('password') 'password' => Hash::make('^Ocean1472bk')
]); ]);
} }
} }

View File

@ -57,8 +57,8 @@
<div class="btn-group btn-group-sm" role="group"> <div class="btn-group btn-group-sm" role="group">
<a href="{{ route('product.edit', $product) }}" class="btn btn-outline-primary">수정</a> <a href="{{ route('product.edit', $product) }}" class="btn btn-outline-primary">수정</a>
<a href="#" class="btn btn-outline-danger btn_del" data-id="{{ $product->id }}">삭제</a> <a href="#" class="btn btn-outline-danger btn_del" data-id="{{ $product->id }}">삭제</a>
<a href="" class="btn btn-outline-success">입고</a> <a href="{{ route('stock.input', ['id' => $product->id, 'action' => 'in']) }}" class="btn btn-outline-success">입고</a>
<a href="" class="btn btn-outline-warning">출고</a> <a href="{{ route('stock.input', ['id' => $product->id, 'action' => 'out']) }}" class="btn btn-outline-warning">출고</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -0,0 +1,24 @@
@extends('layout')
@section('main')
<h4>입고 처리</h4>
<div class="alert alert-danger">에러메시지</div>
<form method="post" action="">
@csrf
<input type="hidden" name="action" value="{{ $action }}">
<div class="mb-3">
<label>상품명</label>
<h3>{{ $product->name }}</h3>
</div>
<div class="mb-3">
<label>수량</label>
<input type="number" name="amount" class="form-control" min="1" required>
</div>
<button class="btn btn-primary">처리</button>
<a href="/" class="btn btn-secondary">취소</a>
</form>
@endsection

View File

@ -2,6 +2,7 @@
use App\Http\Controllers\LoginController; use App\Http\Controllers\LoginController;
use App\Http\Controllers\ProductController; use App\Http\Controllers\ProductController;
use App\Http\Controllers\StockLogController;
use App\Http\Middleware\Authenticate; use App\Http\Middleware\Authenticate;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -44,4 +45,10 @@ Route::get('/product/{product}/edit', [ProductController::class, 'edit'])
Route::put('/product/{product}', [ProductController::class, 'update']) Route::put('/product/{product}', [ProductController::class, 'update'])
->name('product.update'); ->name('product.update');
// 입출고 등록
Route::get('/stock/input/{id}', [StockLogController::class, 'input'])
->name('stock.input');
Route::post('/stock/input/{id}', [StockLogController::class, 'store'])
->name('stock.store');