Revert "feat: DB 연결 오버라이딩 및 대시보드 통계 위젯 추가"

This reverts commit bf8036a64b.
This commit is contained in:
2025-09-30 23:56:25 +09:00
parent bf8036a64b
commit 802a511aa0
81 changed files with 102 additions and 22632 deletions

View File

@@ -1,335 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Design;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Services\BomConditionRuleService;
use App\Http\Requests\Api\V1\Design\BomConditionRuleFormRequest;
use App\Http\Requests\Api\V1\BomConditionRule\IndexBomConditionRuleRequest;
/**
* @OA\Tag(name="BOM Condition Rules", description="BOM condition rule management APIs")
*/
class BomConditionRuleController extends Controller
{
public function __construct(
protected BomConditionRuleService $service
) {}
/**
* @OA\Get(
* path="/v1/design/models/{modelId}/condition-rules",
* summary="Get BOM condition rules",
* description="Retrieve all condition rules for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="page",
* description="Page number for pagination",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="per_page",
* description="Items per page",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=20)
* ),
* @OA\Parameter(
* name="search",
* description="Search by rule name or condition",
* in="query",
* required=false,
* @OA\Schema(type="string", example="bracket_selection")
* ),
* @OA\Parameter(
* name="priority",
* description="Filter by priority level",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="BOM condition rules retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/BomConditionRuleResource")
* ),
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=2),
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=30)
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function index(IndexBomConditionRuleRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->getModelConditionRules($modelId, $request->validated());
}, __('message.fetched'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/condition-rules",
* summary="Create BOM condition rule",
* description="Create a new condition rule for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/CreateBomConditionRuleRequest")
* ),
* @OA\Response(
* response=201,
* description="BOM condition rule created successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/BomConditionRuleResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401)
* )
*/
public function store(BomConditionRuleFormRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->createConditionRule($modelId, $request->validated());
}, __('message.created'));
}
/**
* @OA\Put(
* path="/v1/design/models/{modelId}/condition-rules/{ruleId}",
* summary="Update BOM condition rule",
* description="Update a specific BOM condition rule",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="ruleId",
* description="Rule ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/UpdateBomConditionRuleRequest")
* ),
* @OA\Response(
* response=200,
* description="BOM condition rule updated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/BomConditionRuleResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function update(BomConditionRuleFormRequest $request, int $modelId, int $ruleId)
{
return ApiResponse::handle(function () use ($request, $modelId, $ruleId) {
return $this->service->updateConditionRule($modelId, $ruleId, $request->validated());
}, __('message.updated'));
}
/**
* @OA\Delete(
* path="/v1/design/models/{modelId}/condition-rules/{ruleId}",
* summary="Delete BOM condition rule",
* description="Delete a specific BOM condition rule",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="ruleId",
* description="Rule ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="BOM condition rule deleted successfully",
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function destroy(int $modelId, int $ruleId)
{
return ApiResponse::handle(function () use ($modelId, $ruleId) {
$this->service->deleteConditionRule($modelId, $ruleId);
return null;
}, __('message.deleted'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/condition-rules/{ruleId}/validate",
* summary="Validate BOM condition rule",
* description="Validate condition rule expression and logic",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="ruleId",
* description="Rule ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Condition rule validation result",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(property="is_valid", type="boolean", example=true),
* @OA\Property(
* property="validation_errors",
* type="array",
* @OA\Items(type="string", example="Invalid condition syntax")
* ),
* @OA\Property(
* property="tested_scenarios",
* type="array",
* @OA\Items(
* @OA\Property(property="scenario", type="string", example="W0=1000, H0=800"),
* @OA\Property(property="result", type="boolean", example=true)
* )
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function validate(int $modelId, int $ruleId)
{
return ApiResponse::handle(function () use ($modelId, $ruleId) {
return $this->service->validateConditionRule($modelId, $ruleId);
}, __('message.condition_rule.validated'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/condition-rules/reorder",
* summary="Reorder BOM condition rules",
* description="Change the priority order of condition rules",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Condition Rules"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* @OA\Property(
* property="rule_orders",
* type="array",
* @OA\Items(
* @OA\Property(property="rule_id", type="integer", example=1),
* @OA\Property(property="priority", type="integer", example=1)
* )
* )
* )
* ),
* @OA\Response(
* response=200,
* description="BOM condition rules reordered successfully",
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function reorder(int $modelId)
{
return ApiResponse::handle(function () use ($modelId) {
$ruleOrders = request()->input('rule_orders', []);
$this->service->reorderConditionRules($modelId, $ruleOrders);
return null;
}, __('message.reordered'));
}
}

View File

@@ -1,281 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Design;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Services\BomResolverService;
use App\Http\Requests\Api\V1\Design\BomResolverFormRequest;
/**
* @OA\Tag(name="BOM Resolver", description="BOM resolution and preview APIs")
*/
class BomResolverController extends Controller
{
public function __construct(
protected BomResolverService $service
) {}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/resolve-bom",
* summary="Resolve BOM preview",
* description="Generate real-time BOM preview based on input parameters without creating actual products",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Resolver"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/ResolvePreviewRequest")
* ),
* @OA\Response(
* response=200,
* description="BOM preview generated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/BomPreviewResponse")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function resolveBom(BomResolverFormRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->generatePreview($modelId, $request->validated());
}, __('message.bom.preview_generated'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/validate-parameters",
* summary="Validate model parameters",
* description="Validate input parameters against model constraints before BOM resolution",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Resolver"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* @OA\Property(
* property="input_parameters",
* description="Input parameter values to validate",
* type="object",
* additionalProperties=@OA\Property(oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string"),
* @OA\Schema(type="boolean")
* }),
* example={"W0": 1000, "H0": 800, "installation_type": "A"}
* )
* )
* ),
* @OA\Response(
* response=200,
* description="Parameter validation result",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(property="is_valid", type="boolean", example=true),
* @OA\Property(
* property="validation_errors",
* type="array",
* @OA\Items(
* @OA\Property(property="parameter", type="string", example="W0"),
* @OA\Property(property="error", type="string", example="Value must be between 500 and 2000")
* )
* ),
* @OA\Property(
* property="warnings",
* type="array",
* @OA\Items(
* @OA\Property(property="parameter", type="string", example="H0"),
* @OA\Property(property="warning", type="string", example="Recommended range is 600-1500")
* )
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function validateParameters(int $modelId)
{
return ApiResponse::handle(function () use ($modelId) {
$inputParameters = request()->input('input_parameters', []);
return $this->service->validateParameters($modelId, $inputParameters);
}, __('message.parameters.validated'));
}
/**
* @OA\Get(
* path="/v1/design/models/{modelId}/parameter-schema",
* summary="Get model parameter schema",
* description="Retrieve the input parameter schema for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Resolver"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Model parameter schema retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(
* property="input_parameters",
* type="array",
* @OA\Items(
* @OA\Property(property="name", type="string", example="W0"),
* @OA\Property(property="label", type="string", example="Width"),
* @OA\Property(property="data_type", type="string", example="INTEGER"),
* @OA\Property(property="unit", type="string", example="mm"),
* @OA\Property(property="min_value", type="number", example=500),
* @OA\Property(property="max_value", type="number", example=3000),
* @OA\Property(property="default_value", type="string", example="1000"),
* @OA\Property(property="is_required", type="boolean", example=true),
* @OA\Property(property="description", type="string", example="Product width in millimeters")
* )
* ),
* @OA\Property(
* property="output_parameters",
* type="array",
* @OA\Items(
* @OA\Property(property="name", type="string", example="W1"),
* @OA\Property(property="label", type="string", example="Actual Width"),
* @OA\Property(property="data_type", type="string", example="INTEGER"),
* @OA\Property(property="unit", type="string", example="mm"),
* @OA\Property(property="description", type="string", example="Calculated actual width")
* )
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function getParameterSchema(int $modelId)
{
return ApiResponse::handle(function () use ($modelId) {
return $this->service->getParameterSchema($modelId);
}, __('message.fetched'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/calculate-preview",
* summary="Calculate output values preview",
* description="Calculate output parameter values based on input parameters using formulas",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"BOM Resolver"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* @OA\Property(
* property="input_parameters",
* description="Input parameter values",
* type="object",
* additionalProperties=@OA\Property(oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string"),
* @OA\Schema(type="boolean")
* }),
* example={"W0": 1000, "H0": 800, "installation_type": "A"}
* )
* )
* ),
* @OA\Response(
* response=200,
* description="Output values calculated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(
* property="calculated_values",
* type="object",
* additionalProperties=@OA\Property(oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string")
* }),
* example={"W1": 1050, "H1": 850, "area": 892500, "weight": 45.5}
* ),
* @OA\Property(
* property="calculation_steps",
* type="array",
* @OA\Items(
* @OA\Property(property="parameter", type="string", example="W1"),
* @OA\Property(property="formula", type="string", example="W0 + 50"),
* @OA\Property(property="result", oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string")
* }, example=1050)
* )
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function calculatePreview(int $modelId)
{
return ApiResponse::handle(function () use ($modelId) {
$inputParameters = request()->input('input_parameters', []);
return $this->service->calculatePreview($modelId, $inputParameters);
}, __('message.calculated'));
}
}

View File

@@ -1,278 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Design;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Services\ModelFormulaService;
use App\Http\Requests\Api\V1\Design\ModelFormulaFormRequest;
use App\Http\Requests\Api\V1\ModelFormula\IndexModelFormulaRequest;
/**
* @OA\Tag(name="Model Formulas", description="Model formula management APIs")
*/
class ModelFormulaController extends Controller
{
public function __construct(
protected ModelFormulaService $service
) {}
/**
* @OA\Get(
* path="/v1/design/models/{modelId}/formulas",
* summary="Get model formulas",
* description="Retrieve all formulas for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Formulas"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="page",
* description="Page number for pagination",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="per_page",
* description="Items per page",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=20)
* ),
* @OA\Parameter(
* name="search",
* description="Search by formula name or target parameter",
* in="query",
* required=false,
* @OA\Schema(type="string", example="calculate_area")
* ),
* @OA\Response(
* response=200,
* description="Model formulas retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/ModelFormulaResource")
* ),
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=2),
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=25)
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function index(IndexModelFormulaRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->getModelFormulas($modelId, $request->validated());
}, __('message.fetched'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/formulas",
* summary="Create model formula",
* description="Create a new formula for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Formulas"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/CreateModelFormulaRequest")
* ),
* @OA\Response(
* response=201,
* description="Model formula created successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ModelFormulaResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401)
* )
*/
public function store(ModelFormulaFormRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->createFormula($modelId, $request->validated());
}, __('message.created'));
}
/**
* @OA\Put(
* path="/v1/design/models/{modelId}/formulas/{formulaId}",
* summary="Update model formula",
* description="Update a specific model formula",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Formulas"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="formulaId",
* description="Formula ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/UpdateModelFormulaRequest")
* ),
* @OA\Response(
* response=200,
* description="Model formula updated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ModelFormulaResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function update(ModelFormulaFormRequest $request, int $modelId, int $formulaId)
{
return ApiResponse::handle(function () use ($request, $modelId, $formulaId) {
return $this->service->updateFormula($modelId, $formulaId, $request->validated());
}, __('message.updated'));
}
/**
* @OA\Delete(
* path="/v1/design/models/{modelId}/formulas/{formulaId}",
* summary="Delete model formula",
* description="Delete a specific model formula",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Formulas"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="formulaId",
* description="Formula ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Model formula deleted successfully",
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function destroy(int $modelId, int $formulaId)
{
return ApiResponse::handle(function () use ($modelId, $formulaId) {
$this->service->deleteFormula($modelId, $formulaId);
return null;
}, __('message.deleted'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/formulas/{formulaId}/validate",
* summary="Validate model formula",
* description="Validate formula expression and dependencies",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Formulas"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="formulaId",
* description="Formula ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Formula validation result",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(property="is_valid", type="boolean", example=true),
* @OA\Property(
* property="validation_errors",
* type="array",
* @OA\Items(type="string", example="Unknown variable: unknown_var")
* ),
* @OA\Property(
* property="dependency_chain",
* type="array",
* @OA\Items(type="string", example="W0")
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function validate(int $modelId, int $formulaId)
{
return ApiResponse::handle(function () use ($modelId, $formulaId) {
return $this->service->validateFormula($modelId, $formulaId);
}, __('message.formula.validated'));
}
}

View File

@@ -1,227 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Design;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Services\ModelParameterService;
use App\Http\Requests\Api\V1\Design\ModelParameterFormRequest;
use App\Http\Requests\Api\V1\ModelParameter\IndexModelParameterRequest;
/**
* @OA\Tag(name="Model Parameters", description="Model parameter management APIs")
*/
class ModelParameterController extends Controller
{
public function __construct(
protected ModelParameterService $service
) {}
/**
* @OA\Get(
* path="/v1/design/models/{modelId}/parameters",
* summary="Get model parameters",
* description="Retrieve all parameters for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Parameters"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="page",
* description="Page number for pagination",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="per_page",
* description="Items per page",
* in="query",
* required=false,
* @OA\Schema(type="integer", example=20)
* ),
* @OA\Parameter(
* name="search",
* description="Search by parameter name or label",
* in="query",
* required=false,
* @OA\Schema(type="string", example="width")
* ),
* @OA\Parameter(
* name="type",
* description="Filter by parameter type",
* in="query",
* required=false,
* @OA\Schema(type="string", enum={"INPUT", "OUTPUT"}, example="INPUT")
* ),
* @OA\Response(
* response=200,
* description="Model parameters retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/ModelParameterResource")
* ),
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=45)
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function index(IndexModelParameterRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->getModelParameters($modelId, $request->validated());
}, __('message.fetched'));
}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/parameters",
* summary="Create model parameter",
* description="Create a new parameter for a specific model",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Parameters"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/CreateModelParameterRequest")
* ),
* @OA\Response(
* response=201,
* description="Model parameter created successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ModelParameterResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401)
* )
*/
public function store(ModelParameterFormRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
return $this->service->createParameter($modelId, $request->validated());
}, __('message.created'));
}
/**
* @OA\Put(
* path="/v1/design/models/{modelId}/parameters/{parameterId}",
* summary="Update model parameter",
* description="Update a specific model parameter",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Parameters"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="parameterId",
* description="Parameter ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/UpdateModelParameterRequest")
* ),
* @OA\Response(
* response=200,
* description="Model parameter updated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ModelParameterResource")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function update(ModelParameterFormRequest $request, int $modelId, int $parameterId)
{
return ApiResponse::handle(function () use ($request, $modelId, $parameterId) {
return $this->service->updateParameter($modelId, $parameterId, $request->validated());
}, __('message.updated'));
}
/**
* @OA\Delete(
* path="/v1/design/models/{modelId}/parameters/{parameterId}",
* summary="Delete model parameter",
* description="Delete a specific model parameter",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Model Parameters"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Parameter(
* name="parameterId",
* description="Parameter ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Model parameter deleted successfully",
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function destroy(int $modelId, int $parameterId)
{
return ApiResponse::handle(function () use ($modelId, $parameterId) {
$this->service->deleteParameter($modelId, $parameterId);
return null;
}, __('message.deleted'));
}
}

View File

@@ -1,258 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Design;
use App\Helpers\ApiResponse;
use App\Http\Controllers\Controller;
use App\Services\ProductFromModelService;
use App\Http\Requests\Api\V1\Design\ProductFromModelFormRequest;
/**
* @OA\Tag(name="Product from Model", description="Product creation from model APIs")
*/
class ProductFromModelController extends Controller
{
public function __construct(
protected ProductFromModelService $service
) {}
/**
* @OA\Post(
* path="/v1/design/models/{modelId}/create-product",
* summary="Create product from model",
* description="Create actual product with resolved BOM based on model and input parameters",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Product from Model"},
* @OA\Parameter(
* name="modelId",
* description="Model ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/CreateProductFromModelRequest")
* ),
* @OA\Response(
* response=201,
* description="Product created successfully with resolved BOM",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ProductWithBomResponse")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function createProduct(ProductFromModelFormRequest $request, int $modelId)
{
return ApiResponse::handle(function () use ($request, $modelId) {
$data = $request->validated();
$data['model_id'] = $modelId;
return $this->service->createProductWithBom($data);
}, __('message.product.created_from_model'));
}
/**
* @OA\Get(
* path="/v1/products/{productId}/parameters",
* summary="Get product parameters",
* description="Retrieve parameters used to create this product",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Product from Model"},
* @OA\Parameter(
* name="productId",
* description="Product ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Product parameters retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ProductParametersResponse")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function getProductParameters(int $productId)
{
return ApiResponse::handle(function () use ($productId) {
return $this->service->getProductParameters($productId);
}, __('message.fetched'));
}
/**
* @OA\Get(
* path="/v1/products/{productId}/calculated-values",
* summary="Get product calculated values",
* description="Retrieve calculated output values for this product",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Product from Model"},
* @OA\Parameter(
* name="productId",
* description="Product ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Product calculated values retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ProductCalculatedValuesResponse")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function getCalculatedValues(int $productId)
{
return ApiResponse::handle(function () use ($productId) {
return $this->service->getCalculatedValues($productId);
}, __('message.fetched'));
}
/**
* @OA\Post(
* path="/v1/products/{productId}/recalculate",
* summary="Recalculate product values",
* description="Recalculate product BOM and values with updated parameters",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Product from Model"},
* @OA\Parameter(
* name="productId",
* description="Product ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* @OA\Property(
* property="input_parameters",
* description="Updated input parameter values",
* type="object",
* additionalProperties=@OA\Property(oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string"),
* @OA\Schema(type="boolean")
* }),
* example={"W0": 1200, "H0": 900, "installation_type": "B"}
* ),
* @OA\Property(
* property="update_bom",
* description="Whether to update the BOM components",
* type="boolean",
* example=true
* )
* )
* ),
* @OA\Response(
* response=200,
* description="Product recalculated successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/ProductWithBomResponse")
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ValidationErrorResponse", response=422),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function recalculate(int $productId)
{
return ApiResponse::handle(function () use ($productId) {
$inputParameters = request()->input('input_parameters', []);
$updateBom = request()->boolean('update_bom', true);
return $this->service->recalculateProduct($productId, $inputParameters, $updateBom);
}, __('message.product.recalculated'));
}
/**
* @OA\Get(
* path="/v1/products/{productId}/model-info",
* summary="Get product model information",
* description="Retrieve the model information used to create this product",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
* tags={"Product from Model"},
* @OA\Parameter(
* name="productId",
* description="Product ID",
* in="path",
* required=true,
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Product model information retrieved successfully",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(
* property="data",
* @OA\Property(property="model_id", type="integer", example=1),
* @OA\Property(property="model_code", type="string", example="KSS01"),
* @OA\Property(property="model_name", type="string", example="Standard Screen"),
* @OA\Property(property="model_version", type="string", example="v1.0"),
* @OA\Property(property="creation_timestamp", type="string", format="date-time"),
* @OA\Property(
* property="input_parameters_used",
* type="object",
* additionalProperties=@OA\Property(oneOf={
* @OA\Schema(type="number"),
* @OA\Schema(type="string"),
* @OA\Schema(type="boolean")
* }),
* example={"W0": 1000, "H0": 800, "installation_type": "A"}
* )
* )
* )
* }
* )
* ),
* @OA\Response(ref="#/components/responses/ErrorResponse", response=400),
* @OA\Response(ref="#/components/responses/UnauthorizedResponse", response=401),
* @OA\Response(ref="#/components/responses/NotFoundResponse", response=404)
* )
*/
public function getModelInfo(int $productId)
{
return ApiResponse::handle(function () use ($productId) {
return $this->service->getProductModelInfo($productId);
}, __('message.fetched'));
}
}

View File

@@ -1,133 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Schemas;
use OpenApi\Attributes as OA;
/**
* BOM Condition Rule related Swagger schemas
*/
#[OA\Schema(
schema: 'BomConditionRuleResource',
description: 'BOM condition rule resource',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 1),
new OA\Property(property: 'bom_template_id', type: 'integer', example: 1),
new OA\Property(property: 'name', type: 'string', example: '브라켓 선택 규칙'),
new OA\Property(property: 'ref_type', type: 'string', enum: ['MATERIAL', 'PRODUCT'], example: 'MATERIAL'),
new OA\Property(property: 'ref_id', type: 'integer', example: 101),
new OA\Property(
property: 'condition_expression',
type: 'string',
example: 'W1 >= 1000 && installation_type == "A"',
description: 'Boolean expression to determine if this rule applies'
),
new OA\Property(
property: 'quantity_expression',
type: 'string',
nullable: true,
example: 'ceiling(W1 / 500)',
description: 'Expression to calculate required quantity'
),
new OA\Property(
property: 'waste_rate_expression',
type: 'string',
nullable: true,
example: '0.05',
description: 'Expression to calculate waste rate (0.0-1.0)'
),
new OA\Property(property: 'description', type: 'string', nullable: true, example: '가로 1000mm 이상, A타입 설치시 브라켓 적용'),
new OA\Property(property: 'priority', type: 'integer', example: 1),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'created_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z'),
new OA\Property(property: 'updated_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z'),
new OA\Property(
property: 'reference',
type: 'object',
description: 'Referenced material or product information',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 101),
new OA\Property(property: 'code', type: 'string', example: 'BR-001'),
new OA\Property(property: 'name', type: 'string', example: '표준 브라켓'),
new OA\Property(property: 'unit', type: 'string', example: 'EA')
]
)
]
)]
class BomConditionRuleResource {}
#[OA\Schema(
schema: 'CreateBomConditionRuleRequest',
description: 'Request schema for creating BOM condition rule',
required: ['name', 'ref_type', 'ref_id', 'condition_expression'],
properties: [
new OA\Property(property: 'name', type: 'string', maxLength: 100, example: '브라켓 선택 규칙'),
new OA\Property(property: 'ref_type', type: 'string', enum: ['MATERIAL', 'PRODUCT'], example: 'MATERIAL'),
new OA\Property(property: 'ref_id', type: 'integer', minimum: 1, example: 101),
new OA\Property(
property: 'condition_expression',
type: 'string',
maxLength: 1000,
example: 'W1 >= 1000 && installation_type == "A"',
description: 'Boolean expression to determine if this rule applies'
),
new OA\Property(
property: 'quantity_expression',
type: 'string',
maxLength: 500,
nullable: true,
example: 'ceiling(W1 / 500)',
description: 'Expression to calculate required quantity'
),
new OA\Property(
property: 'waste_rate_expression',
type: 'string',
maxLength: 500,
nullable: true,
example: '0.05',
description: 'Expression to calculate waste rate (0.0-1.0)'
),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '가로 1000mm 이상, A타입 설치시 브라켓 적용'),
new OA\Property(property: 'priority', type: 'integer', minimum: 0, example: 1),
new OA\Property(property: 'is_active', type: 'boolean', example: true)
]
)]
class CreateBomConditionRuleRequest {}
#[OA\Schema(
schema: 'UpdateBomConditionRuleRequest',
description: 'Request schema for updating BOM condition rule',
properties: [
new OA\Property(property: 'name', type: 'string', maxLength: 100, example: '브라켓 선택 규칙'),
new OA\Property(property: 'ref_type', type: 'string', enum: ['MATERIAL', 'PRODUCT'], example: 'MATERIAL'),
new OA\Property(property: 'ref_id', type: 'integer', minimum: 1, example: 101),
new OA\Property(
property: 'condition_expression',
type: 'string',
maxLength: 1000,
example: 'W1 >= 1000 && installation_type == "A"',
description: 'Boolean expression to determine if this rule applies'
),
new OA\Property(
property: 'quantity_expression',
type: 'string',
maxLength: 500,
nullable: true,
example: 'ceiling(W1 / 500)',
description: 'Expression to calculate required quantity'
),
new OA\Property(
property: 'waste_rate_expression',
type: 'string',
maxLength: 500,
nullable: true,
example: '0.05',
description: 'Expression to calculate waste rate (0.0-1.0)'
),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '가로 1000mm 이상, A타입 설치시 브라켓 적용'),
new OA\Property(property: 'priority', type: 'integer', minimum: 0, example: 1),
new OA\Property(property: 'is_active', type: 'boolean', example: true)
]
)]
class UpdateBomConditionRuleRequest {}

View File

@@ -1,314 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Schemas;
use OpenApi\Attributes as OA;
/**
* BOM Resolver related Swagger schemas
*/
#[OA\Schema(
schema: 'ResolvePreviewRequest',
description: 'Request schema for BOM preview resolution',
required: ['input_parameters'],
properties: [
new OA\Property(
property: 'input_parameters',
type: 'object',
additionalProperties: new OA\Property(oneOf: [
new OA\Schema(type: 'number'),
new OA\Schema(type: 'string'),
new OA\Schema(type: 'boolean')
]),
example: [
'W0' => 1000,
'H0' => 800,
'installation_type' => 'A',
'power_source' => '220V'
],
description: 'Input parameter values for BOM resolution'
),
new OA\Property(property: 'bom_template_id', type: 'integer', minimum: 1, nullable: true, example: 1),
new OA\Property(property: 'include_calculated_values', type: 'boolean', example: true),
new OA\Property(property: 'include_bom_items', type: 'boolean', example: true)
]
)]
class ResolvePreviewRequest {}
#[OA\Schema(
schema: 'CreateProductFromModelRequest',
description: 'Request schema for creating product from model',
required: ['model_id', 'input_parameters', 'product_code', 'product_name'],
properties: [
new OA\Property(property: 'model_id', type: 'integer', minimum: 1, example: 1),
new OA\Property(
property: 'input_parameters',
type: 'object',
additionalProperties: new OA\Property(oneOf: [
new OA\Schema(type: 'number'),
new OA\Schema(type: 'string'),
new OA\Schema(type: 'boolean')
]),
example: [
'W0' => 1000,
'H0' => 800,
'installation_type' => 'A',
'power_source' => '220V'
],
description: 'Input parameter values for BOM resolution'
),
new OA\Property(property: 'bom_template_id', type: 'integer', minimum: 1, nullable: true, example: 1),
new OA\Property(
property: 'product_code',
type: 'string',
maxLength: 50,
example: 'KSS01-1000x800-A',
description: 'Product code (uppercase letters, numbers, underscore, hyphen only)'
),
new OA\Property(property: 'product_name', type: 'string', maxLength: 100, example: 'KSS01 스크린 1000x800 A타입'),
new OA\Property(property: 'category_id', type: 'integer', minimum: 1, nullable: true, example: 1),
new OA\Property(property: 'description', type: 'string', maxLength: 1000, nullable: true, example: '매개변수 기반으로 생성된 맞춤형 스크린'),
new OA\Property(property: 'unit', type: 'string', maxLength: 20, nullable: true, example: 'EA'),
new OA\Property(property: 'min_order_qty', type: 'number', minimum: 0, nullable: true, example: 1),
new OA\Property(property: 'lead_time_days', type: 'integer', minimum: 0, nullable: true, example: 7),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'create_bom_items', type: 'boolean', example: true),
new OA\Property(property: 'validate_bom', type: 'boolean', example: true)
]
)]
class CreateProductFromModelRequest {}
#[OA\Schema(
schema: 'BomPreviewResponse',
description: 'BOM preview resolution response',
properties: [
new OA\Property(
property: 'input_parameters',
type: 'object',
additionalProperties: new OA\Property(oneOf: [
new OA\Schema(type: 'number'),
new OA\Schema(type: 'string'),
new OA\Schema(type: 'boolean')
]),
example: [
'W0' => 1000,
'H0' => 800,
'installation_type' => 'A',
'power_source' => '220V'
]
),
new OA\Property(
property: 'calculated_values',
type: 'object',
additionalProperties: new OA\Property(type: 'number'),
example: [
'W1' => 1050,
'H1' => 850,
'area' => 892500,
'weight' => 25.5,
'motor_power' => 120
]
),
new OA\Property(
property: 'bom_items',
type: 'array',
items: new OA\Items(ref: '#/components/schemas/BomItemPreview')
),
new OA\Property(
property: 'summary',
type: 'object',
properties: [
new OA\Property(property: 'total_materials', type: 'integer', example: 15),
new OA\Property(property: 'total_cost', type: 'number', example: 125000.50),
new OA\Property(property: 'estimated_weight', type: 'number', example: 25.5)
]
),
new OA\Property(
property: 'validation_warnings',
type: 'array',
items: new OA\Items(
properties: [
new OA\Property(property: 'type', type: 'string', example: 'PARAMETER_OUT_OF_RANGE'),
new OA\Property(property: 'message', type: 'string', example: 'W0 값이 권장 범위를 벗어났습니다'),
new OA\Property(property: 'parameter', type: 'string', example: 'W0'),
new OA\Property(property: 'current_value', type: 'number', example: 1000),
new OA\Property(property: 'recommended_range', type: 'string', example: '600-900')
],
type: 'object'
)
)
]
)]
class BomPreviewResponse {}
#[OA\Schema(
schema: 'BomItemPreview',
description: 'BOM item preview',
properties: [
new OA\Property(property: 'ref_type', type: 'string', enum: ['MATERIAL', 'PRODUCT'], example: 'MATERIAL'),
new OA\Property(property: 'ref_id', type: 'integer', example: 101),
new OA\Property(property: 'ref_code', type: 'string', example: 'BR-001'),
new OA\Property(property: 'ref_name', type: 'string', example: '표준 브라켓'),
new OA\Property(property: 'quantity', type: 'number', example: 2.0),
new OA\Property(property: 'waste_rate', type: 'number', example: 0.05),
new OA\Property(property: 'total_quantity', type: 'number', example: 2.1),
new OA\Property(property: 'unit', type: 'string', example: 'EA'),
new OA\Property(property: 'unit_cost', type: 'number', nullable: true, example: 5000.0),
new OA\Property(property: 'total_cost', type: 'number', nullable: true, example: 10500.0),
new OA\Property(property: 'applied_rule', type: 'string', nullable: true, example: '브라켓 선택 규칙'),
new OA\Property(
property: 'calculation_details',
type: 'object',
properties: [
new OA\Property(property: 'condition_matched', type: 'boolean', example: true),
new OA\Property(property: 'quantity_expression', type: 'string', example: 'ceiling(W1 / 500)'),
new OA\Property(property: 'quantity_calculation', type: 'string', example: 'ceiling(1050 / 500) = 3')
]
)
]
)]
class BomItemPreview {}
#[OA\Schema(
schema: 'ProductWithBomResponse',
description: 'Product created with BOM response',
properties: [
new OA\Property(
property: 'product',
type: 'object',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 123),
new OA\Property(property: 'code', type: 'string', example: 'KSS01-1000x800-A'),
new OA\Property(property: 'name', type: 'string', example: 'KSS01 스크린 1000x800 A타입'),
new OA\Property(property: 'type', type: 'string', example: 'PRODUCT'),
new OA\Property(property: 'category_id', type: 'integer', nullable: true, example: 1),
new OA\Property(property: 'description', type: 'string', nullable: true, example: '매개변수 기반으로 생성된 맞춤형 스크린'),
new OA\Property(property: 'unit', type: 'string', nullable: true, example: 'EA'),
new OA\Property(property: 'min_order_qty', type: 'number', nullable: true, example: 1),
new OA\Property(property: 'lead_time_days', type: 'integer', nullable: true, example: 7),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'created_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z')
]
),
new OA\Property(
property: 'input_parameters',
type: 'object',
additionalProperties: new OA\Property(oneOf: [
new OA\Schema(type: 'number'),
new OA\Schema(type: 'string'),
new OA\Schema(type: 'boolean')
]),
example: [
'W0' => 1000,
'H0' => 800,
'installation_type' => 'A',
'power_source' => '220V'
]
),
new OA\Property(
property: 'calculated_values',
type: 'object',
additionalProperties: new OA\Property(type: 'number'),
example: [
'W1' => 1050,
'H1' => 850,
'area' => 892500,
'weight' => 25.5
]
),
new OA\Property(
property: 'bom_items',
type: 'array',
items: new OA\Items(
properties: [
new OA\Property(property: 'id', type: 'integer', example: 1),
new OA\Property(property: 'ref_type', type: 'string', enum: ['MATERIAL', 'PRODUCT'], example: 'MATERIAL'),
new OA\Property(property: 'ref_id', type: 'integer', example: 101),
new OA\Property(property: 'ref_code', type: 'string', example: 'BR-001'),
new OA\Property(property: 'ref_name', type: 'string', example: '표준 브라켓'),
new OA\Property(property: 'quantity', type: 'number', example: 2.0),
new OA\Property(property: 'waste_rate', type: 'number', example: 0.05),
new OA\Property(property: 'unit', type: 'string', example: 'EA')
],
type: 'object'
)
),
new OA\Property(
property: 'summary',
type: 'object',
properties: [
new OA\Property(property: 'total_bom_items', type: 'integer', example: 15),
new OA\Property(property: 'model_id', type: 'integer', example: 1),
new OA\Property(property: 'bom_template_id', type: 'integer', nullable: true, example: 1)
]
)
]
)]
class ProductWithBomResponse {}
#[OA\Schema(
schema: 'ProductParametersResponse',
description: 'Product parameters response',
properties: [
new OA\Property(property: 'product_id', type: 'integer', example: 123),
new OA\Property(property: 'model_id', type: 'integer', example: 1),
new OA\Property(
property: 'input_parameters',
type: 'object',
additionalProperties: new OA\Property(oneOf: [
new OA\Schema(type: 'number'),
new OA\Schema(type: 'string'),
new OA\Schema(type: 'boolean')
]),
example: [
'W0' => 1000,
'H0' => 800,
'installation_type' => 'A',
'power_source' => '220V'
]
),
new OA\Property(
property: 'parameter_definitions',
type: 'array',
items: new OA\Items(ref: '#/components/schemas/ModelParameterResource')
)
]
)]
class ProductParametersResponse {}
#[OA\Schema(
schema: 'ProductCalculatedValuesResponse',
description: 'Product calculated values response',
properties: [
new OA\Property(property: 'product_id', type: 'integer', example: 123),
new OA\Property(property: 'model_id', type: 'integer', example: 1),
new OA\Property(
property: 'calculated_values',
type: 'object',
additionalProperties: new OA\Property(type: 'number'),
example: [
'W1' => 1050,
'H1' => 850,
'area' => 892500,
'weight' => 25.5,
'motor_power' => 120
]
),
new OA\Property(
property: 'formula_applications',
type: 'array',
items: new OA\Items(
properties: [
new OA\Property(property: 'formula_name', type: 'string', example: '최종 가로 크기 계산'),
new OA\Property(property: 'target_parameter', type: 'string', example: 'W1'),
new OA\Property(property: 'expression', type: 'string', example: 'W0 + (installation_type == "A" ? 50 : 30)'),
new OA\Property(property: 'calculated_value', type: 'number', example: 1050),
new OA\Property(property: 'execution_order', type: 'integer', example: 1)
],
type: 'object'
)
)
]
)]
class ProductCalculatedValuesResponse {}

View File

@@ -1,80 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Schemas;
use OpenApi\Attributes as OA;
/**
* Model Formula related Swagger schemas
*/
#[OA\Schema(
schema: 'ModelFormulaResource',
description: 'Model formula resource',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 1),
new OA\Property(property: 'model_id', type: 'integer', example: 1),
new OA\Property(property: 'name', type: 'string', example: '최종 가로 크기 계산'),
new OA\Property(property: 'target_parameter', type: 'string', example: 'W1'),
new OA\Property(property: 'expression', type: 'string', example: 'W0 + (installation_type == "A" ? 50 : 30)'),
new OA\Property(property: 'description', type: 'string', nullable: true, example: '설치 타입에 따른 최종 가로 크기 계산'),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'execution_order', type: 'integer', example: 1),
new OA\Property(property: 'created_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z'),
new OA\Property(property: 'updated_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z')
]
)]
class ModelFormulaResource {}
#[OA\Schema(
schema: 'CreateModelFormulaRequest',
description: 'Request schema for creating model formula',
required: ['name', 'target_parameter', 'expression'],
properties: [
new OA\Property(property: 'name', type: 'string', maxLength: 100, example: '최종 가로 크기 계산'),
new OA\Property(
property: 'target_parameter',
type: 'string',
maxLength: 50,
example: 'W1',
description: 'Target parameter name (alphanumeric with underscore, must start with letter)'
),
new OA\Property(
property: 'expression',
type: 'string',
maxLength: 1000,
example: 'W0 + (installation_type == "A" ? 50 : 30)',
description: 'Mathematical expression for calculating the target parameter'
),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '설치 타입에 따른 최종 가로 크기 계산'),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'execution_order', type: 'integer', minimum: 0, example: 1)
]
)]
class CreateModelFormulaRequest {}
#[OA\Schema(
schema: 'UpdateModelFormulaRequest',
description: 'Request schema for updating model formula',
properties: [
new OA\Property(property: 'name', type: 'string', maxLength: 100, example: '최종 가로 크기 계산'),
new OA\Property(
property: 'target_parameter',
type: 'string',
maxLength: 50,
example: 'W1',
description: 'Target parameter name (alphanumeric with underscore, must start with letter)'
),
new OA\Property(
property: 'expression',
type: 'string',
maxLength: 1000,
example: 'W0 + (installation_type == "A" ? 50 : 30)',
description: 'Mathematical expression for calculating the target parameter'
),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '설치 타입에 따른 최종 가로 크기 계산'),
new OA\Property(property: 'is_active', type: 'boolean', example: true),
new OA\Property(property: 'execution_order', type: 'integer', minimum: 0, example: 1)
]
)]
class UpdateModelFormulaRequest {}

View File

@@ -1,107 +0,0 @@
<?php
namespace App\Http\Controllers\Api\V1\Schemas;
use OpenApi\Attributes as OA;
/**
* Model Parameter related Swagger schemas
*/
#[OA\Schema(
schema: 'ModelParameterResource',
description: 'Model parameter resource',
properties: [
new OA\Property(property: 'id', type: 'integer', example: 1),
new OA\Property(property: 'model_id', type: 'integer', example: 1),
new OA\Property(property: 'name', type: 'string', example: 'W0'),
new OA\Property(property: 'label', type: 'string', example: '가로 크기'),
new OA\Property(property: 'type', type: 'string', enum: ['INPUT', 'OUTPUT'], example: 'INPUT'),
new OA\Property(property: 'data_type', type: 'string', enum: ['INTEGER', 'DECIMAL', 'STRING', 'BOOLEAN'], example: 'DECIMAL'),
new OA\Property(property: 'unit', type: 'string', nullable: true, example: 'mm'),
new OA\Property(property: 'default_value', type: 'string', nullable: true, example: '1000'),
new OA\Property(property: 'min_value', type: 'number', nullable: true, example: 500),
new OA\Property(property: 'max_value', type: 'number', nullable: true, example: 2000),
new OA\Property(
property: 'enum_values',
type: 'array',
items: new OA\Items(type: 'string'),
nullable: true,
example: ['A', 'B', 'C']
),
new OA\Property(property: 'validation_rules', type: 'string', nullable: true, example: 'required|numeric|min:500'),
new OA\Property(property: 'description', type: 'string', nullable: true, example: '제품의 가로 크기를 입력하세요'),
new OA\Property(property: 'is_required', type: 'boolean', example: true),
new OA\Property(property: 'display_order', type: 'integer', example: 1),
new OA\Property(property: 'created_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z'),
new OA\Property(property: 'updated_at', type: 'string', format: 'date-time', example: '2024-01-01T00:00:00Z')
]
)]
class ModelParameterResource {}
#[OA\Schema(
schema: 'CreateModelParameterRequest',
description: 'Request schema for creating model parameter',
required: ['name', 'label', 'type', 'data_type'],
properties: [
new OA\Property(
property: 'name',
type: 'string',
maxLength: 50,
example: 'W0',
description: 'Parameter name (alphanumeric with underscore, must start with letter)'
),
new OA\Property(property: 'label', type: 'string', maxLength: 100, example: '가로 크기'),
new OA\Property(property: 'type', type: 'string', enum: ['INPUT', 'OUTPUT'], example: 'INPUT'),
new OA\Property(property: 'data_type', type: 'string', enum: ['INTEGER', 'DECIMAL', 'STRING', 'BOOLEAN'], example: 'DECIMAL'),
new OA\Property(property: 'unit', type: 'string', maxLength: 20, nullable: true, example: 'mm'),
new OA\Property(property: 'default_value', type: 'string', maxLength: 255, nullable: true, example: '1000'),
new OA\Property(property: 'min_value', type: 'number', nullable: true, example: 500),
new OA\Property(property: 'max_value', type: 'number', nullable: true, example: 2000),
new OA\Property(
property: 'enum_values',
type: 'array',
items: new OA\Items(type: 'string'),
nullable: true,
example: ['A', 'B', 'C']
),
new OA\Property(property: 'validation_rules', type: 'string', maxLength: 500, nullable: true, example: 'required|numeric|min:500'),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '제품의 가로 크기를 입력하세요'),
new OA\Property(property: 'is_required', type: 'boolean', example: true),
new OA\Property(property: 'display_order', type: 'integer', minimum: 0, example: 1)
]
)]
class CreateModelParameterRequest {}
#[OA\Schema(
schema: 'UpdateModelParameterRequest',
description: 'Request schema for updating model parameter',
properties: [
new OA\Property(
property: 'name',
type: 'string',
maxLength: 50,
example: 'W0',
description: 'Parameter name (alphanumeric with underscore, must start with letter)'
),
new OA\Property(property: 'label', type: 'string', maxLength: 100, example: '가로 크기'),
new OA\Property(property: 'type', type: 'string', enum: ['INPUT', 'OUTPUT'], example: 'INPUT'),
new OA\Property(property: 'data_type', type: 'string', enum: ['INTEGER', 'DECIMAL', 'STRING', 'BOOLEAN'], example: 'DECIMAL'),
new OA\Property(property: 'unit', type: 'string', maxLength: 20, nullable: true, example: 'mm'),
new OA\Property(property: 'default_value', type: 'string', maxLength: 255, nullable: true, example: '1000'),
new OA\Property(property: 'min_value', type: 'number', nullable: true, example: 500),
new OA\Property(property: 'max_value', type: 'number', nullable: true, example: 2000),
new OA\Property(
property: 'enum_values',
type: 'array',
items: new OA\Items(type: 'string'),
nullable: true,
example: ['A', 'B', 'C']
),
new OA\Property(property: 'validation_rules', type: 'string', maxLength: 500, nullable: true, example: 'required|numeric|min:500'),
new OA\Property(property: 'description', type: 'string', maxLength: 500, nullable: true, example: '제품의 가로 크기를 입력하세요'),
new OA\Property(property: 'is_required', type: 'boolean', example: true),
new OA\Property(property: 'display_order', type: 'integer', minimum: 0, example: 1)
]
)]
class UpdateModelParameterRequest {}