Files
sam-api/app/Models/Orders/OrderItem.php
kent 1410cf725a feat(API): 견적-주문 연동 필드 및 마이그레이션 추가
- Order, OrderItem 모델에 견적 연동 필드 추가
- Quote 모델에 order_id 관계 추가
- QuoteService 개선
- 관련 마이그레이션 파일 추가

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 15:56:46 +09:00

184 lines
4.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Models\Orders;
use App\Models\Items\Item;
use App\Models\Quote\Quote;
use App\Models\Quote\QuoteItem;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* 수주 상세 (Order Items)
*
* @mixin IdeHelperOrderItem
*/
class OrderItem extends Model
{
use BelongsToTenant, SoftDeletes;
protected $table = 'order_items';
protected $fillable = [
'tenant_id',
'order_id',
'quote_id',
'quote_item_id',
'serial_no',
// 품목 정보
'item_id',
'item_code',
'item_name',
'specification',
'unit',
// 수량/금액
'quantity',
'unit_price',
'supply_amount',
'tax_amount',
'total_amount',
// 할인
'discount_rate',
'discount_amount',
// 기타
'status_code',
'design_code',
'remarks',
'note',
'sort_order',
'attributes',
// 감사
'created_by',
'updated_by',
'deleted_by',
];
protected $casts = [
'quantity' => 'decimal:4',
'unit_price' => 'decimal:2',
'supply_amount' => 'decimal:2',
'tax_amount' => 'decimal:2',
'total_amount' => 'decimal:2',
'discount_rate' => 'decimal:2',
'discount_amount' => 'decimal:2',
'attributes' => 'array',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
/**
* 수주 마스터
*/
public function order(): BelongsTo
{
return $this->belongsTo(Order::class);
}
/**
* 품목 마스터
*/
public function item(): BelongsTo
{
return $this->belongsTo(Item::class, 'item_id');
}
/**
* 원본 견적
*/
public function quote(): BelongsTo
{
return $this->belongsTo(Quote::class);
}
/**
* 원본 견적 품목
*/
public function quoteItem(): BelongsTo
{
return $this->belongsTo(QuoteItem::class);
}
/**
* 투입 구성 (자재/BOM 등)
*/
public function components(): HasMany
{
return $this->hasMany(OrderItemComponent::class);
}
/**
* 공급가액 계산 (수량 × 단가 - 할인)
*/
public function calculateSupplyAmount(): float
{
$gross = $this->quantity * $this->unit_price;
$discount = $this->discount_amount ?: ($gross * ($this->discount_rate / 100));
return round($gross - $discount, 2);
}
/**
* 세액 계산 (공급가액 × 10%)
*/
public function calculateTaxAmount(): float
{
return round($this->supply_amount * 0.1, 2);
}
/**
* 총액 계산 (공급가액 + 세액)
*/
public function calculateTotalAmount(): float
{
return round($this->supply_amount + $this->tax_amount, 2);
}
/**
* 금액 재계산 및 저장
*/
public function recalculateAmounts(): self
{
$this->supply_amount = $this->calculateSupplyAmount();
$this->tax_amount = $this->calculateTaxAmount();
$this->total_amount = $this->calculateTotalAmount();
return $this;
}
/**
* 견적 품목에서 수주 품목 생성
*
* @param int $serialIndex 품목 순번 (1부터 시작)
*/
public static function createFromQuoteItem(QuoteItem $quoteItem, int $orderId, int $serialIndex = 1): self
{
$qty = $quoteItem->calculated_quantity ?? 1;
$supplyAmount = $quoteItem->unit_price * $qty;
$taxAmount = round($supplyAmount * 0.1, 2);
return new self([
'tenant_id' => $quoteItem->tenant_id,
'order_id' => $orderId,
'quote_id' => $quoteItem->quote_id,
'quote_item_id' => $quoteItem->id,
'serial_no' => str_pad($serialIndex, 3, '0', STR_PAD_LEFT),
'item_id' => $quoteItem->item_id,
'item_code' => $quoteItem->item_code,
'item_name' => $quoteItem->item_name,
'specification' => $quoteItem->specification,
'unit' => $quoteItem->unit ?? 'EA',
'quantity' => $qty,
'unit_price' => $quoteItem->unit_price,
'supply_amount' => $supplyAmount,
'tax_amount' => $taxAmount,
'total_amount' => $supplyAmount + $taxAmount,
'note' => $quoteItem->note,
'sort_order' => $quoteItem->sort_order ?? 0,
]);
}
}