feat: [bending] 절곡품 전용 테이블 분리 API
- bending_items 전용 테이블 생성 (items.options → 정규 컬럼 승격) - bending_models 전용 테이블 생성 (가이드레일/케이스/하단마감재 통합) - bending_data JSON 통합 (별도 테이블 → bending_items.bending_data 컬럼) - bending_item_mappings 테이블 DROP (bending_items.code에 흡수) - BendingItemService/BendingCodeService → BendingItem 모델 전환 - GuiderailModelService component 이미지 자동 복사 - ItemsFileController bending_items/bending_models 폴백 지원 - Swagger 스키마 업데이트
This commit is contained in:
136
app/Models/BendingItem.php
Normal file
136
app/Models/BendingItem.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Commons\File;
|
||||
use App\Traits\Auditable;
|
||||
use App\Traits\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* 절곡 기초관리 마스터
|
||||
*
|
||||
* code: {제품Code}{종류Code}{YYMMDD} (예: CP260319 = 케이스 점검구)
|
||||
* bending_data: 전개도 JSON 배열 [{no, input, rate, sum, color, aAngle}]
|
||||
*/
|
||||
class BendingItem extends Model
|
||||
{
|
||||
use Auditable, BelongsToTenant, SoftDeletes;
|
||||
|
||||
protected $table = 'bending_items';
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'code',
|
||||
'legacy_code',
|
||||
'legacy_bending_id',
|
||||
'item_name',
|
||||
'item_sep',
|
||||
'item_bending',
|
||||
'material',
|
||||
'item_spec',
|
||||
'model_name',
|
||||
'model_UA',
|
||||
'rail_width',
|
||||
'exit_direction',
|
||||
'box_width',
|
||||
'box_height',
|
||||
'front_bottom',
|
||||
'inspection_door',
|
||||
'length_code',
|
||||
'length_mm',
|
||||
'bending_data',
|
||||
'options',
|
||||
'is_active',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'bending_data' => 'array',
|
||||
'options' => 'array',
|
||||
'is_active' => 'boolean',
|
||||
'rail_width' => 'decimal:2',
|
||||
'box_width' => 'decimal:2',
|
||||
'box_height' => 'decimal:2',
|
||||
'front_bottom' => 'decimal:2',
|
||||
];
|
||||
|
||||
protected $hidden = ['deleted_at'];
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// 관계
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function files(): HasMany
|
||||
{
|
||||
return $this->hasMany(File::class, 'document_id')
|
||||
->where('document_type', 'bending_item');
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// options 헬퍼
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function getOption(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return data_get($this->options, $key, $default);
|
||||
}
|
||||
|
||||
public function setOption(string $key, mixed $value): self
|
||||
{
|
||||
$options = $this->options ?? [];
|
||||
data_set($options, $key, $value);
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// 계산 accessor
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function getWidthSumAttribute(): ?float
|
||||
{
|
||||
$data = $this->bending_data ?? [];
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
$last = end($data);
|
||||
|
||||
return isset($last['sum']) ? (float) $last['sum'] : null;
|
||||
}
|
||||
|
||||
public function getBendCountAttribute(): int
|
||||
{
|
||||
$data = $this->bending_data ?? [];
|
||||
|
||||
return count(array_filter($data, fn ($d) => ($d['rate'] ?? '') !== ''));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// LOT 코드 테이블
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
public const PROD_CODES = [
|
||||
'R' => '가이드레일(벽면형)',
|
||||
'S' => '가이드레일(측면형)',
|
||||
'C' => '케이스',
|
||||
'B' => '하단마감재(스크린)',
|
||||
'T' => '하단마감재(철재)',
|
||||
'L' => 'L-Bar',
|
||||
'G' => '연기차단재',
|
||||
];
|
||||
|
||||
public const SPEC_CODES = [
|
||||
'R' => ['M' => '본체', 'T' => '본체(철재)', 'C' => 'C형', 'D' => 'D형', 'S' => 'SUS 마감재'],
|
||||
'S' => ['M' => '본체디딤', 'T' => '본체(철재)', 'C' => 'C형', 'D' => 'D형', 'S' => 'SUS 마감재①', 'U' => 'SUS 마감재②'],
|
||||
'C' => ['F' => '전면부', 'P' => '점검구', 'L' => '린텔부', 'B' => '후면코너부'],
|
||||
'B' => ['S' => 'SUS', 'E' => 'EGI'],
|
||||
'T' => ['S' => 'SUS', 'E' => 'EGI'],
|
||||
'L' => ['A' => '스크린용'],
|
||||
'G' => ['I' => '화이바원단'],
|
||||
];
|
||||
}
|
||||
68
app/Models/BendingModel.php
Normal file
68
app/Models/BendingModel.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Commons\File;
|
||||
use App\Traits\Auditable;
|
||||
use App\Traits\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class BendingModel extends Model
|
||||
{
|
||||
use Auditable, BelongsToTenant, SoftDeletes;
|
||||
|
||||
protected $table = 'bending_models';
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id', 'model_type', 'code', 'name', 'legacy_code', 'legacy_num',
|
||||
'model_name', 'model_UA', 'item_sep', 'finishing_type', 'author', 'remark',
|
||||
'check_type', 'rail_width', 'rail_length',
|
||||
'exit_direction', 'front_bottom_width', 'box_width', 'box_height',
|
||||
'bar_width', 'bar_height',
|
||||
'components', 'material_summary',
|
||||
'search_keyword', 'registration_date', 'options',
|
||||
'is_active', 'created_by', 'updated_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'components' => 'array',
|
||||
'material_summary' => 'array',
|
||||
'options' => 'array',
|
||||
'is_active' => 'boolean',
|
||||
'registration_date' => 'date',
|
||||
'rail_width' => 'decimal:2',
|
||||
'rail_length' => 'decimal:2',
|
||||
'front_bottom_width' => 'decimal:2',
|
||||
'box_width' => 'decimal:2',
|
||||
'box_height' => 'decimal:2',
|
||||
'bar_width' => 'decimal:2',
|
||||
'bar_height' => 'decimal:2',
|
||||
];
|
||||
|
||||
protected $hidden = ['deleted_at'];
|
||||
|
||||
public function files(): HasMany
|
||||
{
|
||||
return $this->hasMany(File::class, 'document_id')
|
||||
->where('document_type', 'bending_model');
|
||||
}
|
||||
|
||||
public function getOption(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return data_get($this->options, $key, $default);
|
||||
}
|
||||
|
||||
public function setOption(string $key, mixed $value): self
|
||||
{
|
||||
$options = $this->options ?? [];
|
||||
data_set($options, $key, $value);
|
||||
$this->options = $options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public const TYPE_GUIDERAIL = 'GUIDERAIL_MODEL';
|
||||
public const TYPE_SHUTTERBOX = 'SHUTTERBOX_MODEL';
|
||||
public const TYPE_BOTTOMBAR = 'BOTTOMBAR_MODEL';
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Production;
|
||||
|
||||
use App\Models\Items\Item;
|
||||
use App\Traits\BelongsToTenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class BendingItemMapping extends Model
|
||||
{
|
||||
use BelongsToTenant;
|
||||
|
||||
protected $table = 'bending_item_mappings';
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'prod_code',
|
||||
'spec_code',
|
||||
'length_code',
|
||||
'item_id',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
|
||||
public function item(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Item::class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user