chore: Phase H, I API 라우트 및 공통 파일 업데이트

- routes/api.php: H-1~3, I-2~8 엔드포인트 추가
- error.php: 에러 메시지 키 추가 (en/ko)
- TenantUserProfile 모델 업데이트
- LOGICAL_RELATIONSHIPS.md 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-26 15:48:37 +09:00
parent 5c0f92d74a
commit 7fc11a2215
5 changed files with 129 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
# 논리적 데이터베이스 관계 문서
> **자동 생성**: 2025-12-25 00:41:11
> **자동 생성**: 2025-12-26 15:08:36
> **소스**: Eloquent 모델 관계 분석
## 📊 모델별 관계 현황
@@ -361,6 +361,45 @@ ### popups
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
### work_orders
**모델**: `App\Models\Production\WorkOrder`
- **salesOrder()**: belongsTo → `orders`
- **assignee()**: belongsTo → `users`
- **team()**: belongsTo → `departments`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
- **items()**: hasMany → `work_order_items`
- **issues()**: hasMany → `work_order_issues`
- **bendingDetail()**: hasOne → `work_order_bending_details`
### work_order_bending_details
**모델**: `App\Models\Production\WorkOrderBendingDetail`
- **workOrder()**: belongsTo → `work_orders`
### work_order_issues
**모델**: `App\Models\Production\WorkOrderIssue`
- **workOrder()**: belongsTo → `work_orders`
- **reporter()**: belongsTo → `users`
- **resolver()**: belongsTo → `users`
### work_order_items
**모델**: `App\Models\Production\WorkOrderItem`
- **workOrder()**: belongsTo → `work_orders`
- **item()**: belongsTo → `items`
### work_results
**모델**: `App\Models\Production\WorkResult`
- **workOrder()**: belongsTo → `work_orders`
- **workOrderItem()**: belongsTo → `work_order_items`
- **worker()**: belongsTo → `users`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
### prices
**모델**: `App\Models\Products\Price`
@@ -540,6 +579,13 @@ ### deposits
- **bankAccount()**: belongsTo → `bank_accounts`
- **creator()**: belongsTo → `users`
### expected_expenses
**모델**: `App\Models\Tenants\ExpectedExpense`
- **client()**: belongsTo → `clients`
- **bankAccount()**: belongsTo → `bank_accounts`
- **creator()**: belongsTo → `users`
### leaves
**모델**: `App\Models\Tenants\Leave`
@@ -547,6 +593,7 @@ ### leaves
- **approver()**: belongsTo → `users`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
- **userProfile()**: hasOne → `tenant_user_profiles`
### leave_balances
**모델**: `App\Models\Tenants\LeaveBalance`
@@ -559,6 +606,11 @@ ### leave_grants
- **user()**: belongsTo → `users`
- **creator()**: belongsTo → `users`
### leave_policys
**모델**: `App\Models\Tenants\LeavePolicy`
- **tenant()**: belongsTo → `tenants`
### loans
**모델**: `App\Models\Tenants\Loan`
@@ -601,6 +653,20 @@ ### purchases
- **withdrawal()**: belongsTo → `withdrawals`
- **creator()**: belongsTo → `users`
### receivings
**모델**: `App\Models\Tenants\Receiving`
- **item()**: belongsTo → `items`
- **creator()**: belongsTo → `users`
### salarys
**모델**: `App\Models\Tenants\Salary`
- **employee()**: belongsTo → `users`
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
- **employeeProfile()**: hasOne → `tenant_user_profiles`
### sales
**모델**: `App\Models\Tenants\Sale`
@@ -619,6 +685,19 @@ ### sites
- **creator()**: belongsTo → `users`
- **updater()**: belongsTo → `users`
### stocks
**모델**: `App\Models\Tenants\Stock`
- **creator()**: belongsTo → `users`
- **lots()**: hasMany → `stock_lots`
### stock_lots
**모델**: `App\Models\Tenants\StockLot`
- **stock()**: belongsTo → `stocks`
- **receiving()**: belongsTo → `receivings`
- **creator()**: belongsTo → `users`
### subscriptions
**모델**: `App\Models\Tenants\Subscription`
@@ -677,6 +756,7 @@ ### withdrawals
- **client()**: belongsTo → `clients`
- **bankAccount()**: belongsTo → `bank_accounts`
- **card()**: belongsTo → `cards`
- **creator()**: belongsTo → `users`
### user_invitations

View File

@@ -28,6 +28,7 @@ class TenantUserProfile extends Model
'position_label',
'job_title_label',
'rank',
'hire_date',
];
protected $fillable = [

View File

@@ -95,4 +95,13 @@
'duplicate_code' => 'Duplicate item code.',
],
// Shipment management related
'shipment' => [
'not_found' => 'Shipment not found.',
'cannot_edit' => 'Cannot edit in the current status.',
'cannot_delete' => 'Cannot delete in the current status.',
'invalid_status' => 'Invalid status.',
'cannot_ship' => 'Not in a shippable state.',
],
];

View File

@@ -69,6 +69,28 @@
'in_use_cannot_delete' => '사용 중인 자재는 삭제할 수 없습니다.',
],
// 입고 관리 관련
'receiving' => [
'not_found' => '입고 정보를 찾을 수 없습니다.',
'cannot_edit' => '입고완료 상태에서는 수정할 수 없습니다.',
'cannot_delete' => '입고완료 상태에서는 삭제할 수 없습니다.',
'cannot_process' => '현재 상태에서는 입고처리할 수 없습니다.',
],
// 재고 관리 관련
'stock' => [
'not_found' => '재고 정보를 찾을 수 없습니다.',
],
// 출하 관리 관련
'shipment' => [
'not_found' => '출하 정보를 찾을 수 없습니다.',
'cannot_edit' => '현재 상태에서는 수정할 수 없습니다.',
'cannot_delete' => '현재 상태에서는 삭제할 수 없습니다.',
'invalid_status' => '유효하지 않은 상태입니다.',
'cannot_ship' => '출하 가능 상태가 아닙니다.',
],
// 파일 관리 관련
'file' => [
'not_found' => '파일을 찾을 수 없습니다.',

View File

@@ -76,6 +76,7 @@
use App\Http\Controllers\Api\V1\PurchaseController;
use App\Http\Controllers\Api\V1\ReceivingController;
use App\Http\Controllers\Api\V1\StockController;
use App\Http\Controllers\Api\V1\ShipmentController;
use App\Http\Controllers\Api\V1\PushNotificationController;
use App\Http\Controllers\Api\V1\QuoteController;
use App\Http\Controllers\Api\V1\RefreshController;
@@ -618,6 +619,21 @@
Route::get('/{id}', [StockController::class, 'show'])->whereNumber('id')->name('v1.stocks.show');
});
// Shipment API (출하 관리)
Route::prefix('shipments')->group(function () {
Route::get('', [ShipmentController::class, 'index'])->name('v1.shipments.index');
Route::get('/stats', [ShipmentController::class, 'stats'])->name('v1.shipments.stats');
Route::get('/stats-by-status', [ShipmentController::class, 'statsByStatus'])->name('v1.shipments.stats-by-status');
Route::get('/options/lots', [ShipmentController::class, 'lotOptions'])->name('v1.shipments.options.lots');
Route::get('/options/logistics', [ShipmentController::class, 'logisticsOptions'])->name('v1.shipments.options.logistics');
Route::get('/options/vehicle-tonnage', [ShipmentController::class, 'vehicleTonnageOptions'])->name('v1.shipments.options.vehicle-tonnage');
Route::post('', [ShipmentController::class, 'store'])->name('v1.shipments.store');
Route::get('/{id}', [ShipmentController::class, 'show'])->whereNumber('id')->name('v1.shipments.show');
Route::put('/{id}', [ShipmentController::class, 'update'])->whereNumber('id')->name('v1.shipments.update');
Route::patch('/{id}/status', [ShipmentController::class, 'updateStatus'])->whereNumber('id')->name('v1.shipments.status');
Route::delete('/{id}', [ShipmentController::class, 'destroy'])->whereNumber('id')->name('v1.shipments.destroy');
});
// Barobill Setting API (바로빌 설정)
Route::prefix('barobill-settings')->group(function () {
Route::get('', [BarobillSettingController::class, 'show'])->name('v1.barobill-settings.show');