325 lines
11 KiB
PHP
325 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Modules\IndustrialEngineering\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use InvalidArgumentException;
|
|
use Modules\IndustrialEngineering\Http\Controllers\Concerns\AuthorizesIndustrialEngineering;
|
|
use Modules\IndustrialEngineering\Http\Controllers\Concerns\ResolvesIeCodes;
|
|
use Modules\IndustrialEngineering\Models\Bom;
|
|
use Modules\IndustrialEngineering\Models\BomLine;
|
|
use Modules\IndustrialEngineering\Models\BomStructureTemplate;
|
|
use Modules\IndustrialEngineering\Models\ItemMaster;
|
|
use Modules\IndustrialEngineering\Services\BomTemplateService;
|
|
use Modules\IndustrialEngineering\Services\BomTreeService;
|
|
use Modules\IndustrialEngineering\Services\ErpItemLinkService;
|
|
use Modules\IndustrialEngineering\Services\AutoIntegrationService;
|
|
|
|
class BomStructureController extends Controller
|
|
{
|
|
use AuthorizesIndustrialEngineering;
|
|
use ResolvesIeCodes;
|
|
|
|
public function __construct(
|
|
protected BomTreeService $bomTreeService,
|
|
protected BomTemplateService $bomTemplateService,
|
|
protected ErpItemLinkService $erpItemLink,
|
|
protected AutoIntegrationService $autoIntegration
|
|
) {
|
|
}
|
|
|
|
public function tree($bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.view');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'tree' => $this->bomTreeService->buildEditorTree($bom),
|
|
]);
|
|
}
|
|
|
|
public function storeNode(Request $request, $bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
$data = $request->validate([
|
|
'parent_line_id' => 'nullable|exists:ie_bom_lines,id',
|
|
'item_master_id' => 'nullable|exists:ie_item_masters,id',
|
|
'item_code' => 'nullable|string|max:100',
|
|
'name' => 'required_without:item_master_id|string|max:255',
|
|
'item_type' => 'nullable|string',
|
|
'quantity' => 'nullable|numeric|min:0.0001',
|
|
'position_code' => 'nullable|string|max:100',
|
|
'find_number' => 'nullable|string|max:100',
|
|
'variation_id' => 'nullable|integer',
|
|
'product_id' => 'nullable|integer',
|
|
'standard_cost' => 'nullable|numeric|min:0',
|
|
'is_serviceable' => 'nullable|boolean',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
try {
|
|
$line = $this->bomTreeService->addNode(
|
|
$bom,
|
|
$data['parent_line_id'] ?? null,
|
|
$data
|
|
);
|
|
} catch (InvalidArgumentException $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'msg' => $e->getMessage(),
|
|
], 422);
|
|
}
|
|
|
|
$integrationMessages = $this->autoIntegration->afterBomNodeCreated($line->itemMaster, $data);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.node_added'),
|
|
'integration_messages' => $integrationMessages,
|
|
'node' => $this->bomTreeService->lineToEditorNode($line->load(['itemMaster', 'children'])),
|
|
]);
|
|
}
|
|
|
|
public function updateNode(Request $request, $lineId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$line = BomLine::forBusiness($this->businessId())->findOrFail($lineId);
|
|
|
|
$data = $request->validate([
|
|
'quantity' => 'nullable|numeric|min:0.0001',
|
|
'position_code' => 'nullable|string|max:100',
|
|
'find_number' => 'nullable|string|max:100',
|
|
'standard_cost' => 'nullable|numeric|min:0',
|
|
'is_serviceable' => 'nullable|boolean',
|
|
'notes' => 'nullable|string',
|
|
'variation_id' => 'nullable|integer',
|
|
'product_id' => 'nullable|integer',
|
|
]);
|
|
|
|
$line = $this->bomTreeService->updateNode($line, $data);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.saved'),
|
|
'node' => $this->bomTreeService->lineToEditorNode($line),
|
|
]);
|
|
}
|
|
|
|
public function move(Request $request, $bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
$data = $request->validate([
|
|
'nestable' => 'required|array',
|
|
]);
|
|
|
|
try {
|
|
$this->bomTreeService->applyNestable($bom, $data['nestable']);
|
|
} catch (InvalidArgumentException $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'msg' => $e->getMessage(),
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.tree_saved'),
|
|
'tree' => $this->bomTreeService->buildEditorTree($bom->fresh()),
|
|
]);
|
|
}
|
|
|
|
public function destroyNode($lineId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$line = BomLine::forBusiness($this->businessId())->findOrFail($lineId);
|
|
$this->bomTreeService->deleteNode($line);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.node_deleted'),
|
|
]);
|
|
}
|
|
|
|
public function duplicateBranch(Request $request, $bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
$data = $request->validate([
|
|
'source_line_id' => 'required|exists:ie_bom_lines,id',
|
|
'target_parent_line_id' => 'nullable|exists:ie_bom_lines,id',
|
|
]);
|
|
|
|
$sourceLine = BomLine::forBusiness($this->businessId())->findOrFail($data['source_line_id']);
|
|
|
|
try {
|
|
$result = $this->bomTreeService->duplicateSubtree(
|
|
$bom,
|
|
$sourceLine,
|
|
$data['target_parent_line_id'] ?? null
|
|
);
|
|
} catch (InvalidArgumentException $e) {
|
|
return response()->json(['success' => false, 'msg' => $e->getMessage()], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.branch_pasted', ['count' => $result['created_count']]),
|
|
'created_count' => $result['created_count'],
|
|
'tree' => $this->bomTreeService->buildEditorTree($bom->fresh()),
|
|
]);
|
|
}
|
|
|
|
public function listTemplates($bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.view');
|
|
Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'templates' => $this->bomTemplateService->listForBusiness($this->businessId()),
|
|
]);
|
|
}
|
|
|
|
public function applyTemplate(Request $request, $bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
$data = $request->validate([
|
|
'parent_line_id' => 'nullable|exists:ie_bom_lines,id',
|
|
'template_key' => 'required|string|max:100',
|
|
]);
|
|
|
|
try {
|
|
$result = $this->bomTemplateService->apply(
|
|
$bom,
|
|
$data['parent_line_id'] ?? null,
|
|
$data['template_key']
|
|
);
|
|
} catch (InvalidArgumentException $e) {
|
|
return response()->json(['success' => false, 'msg' => $e->getMessage()], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.bulk_nodes_added', ['count' => $result['created_count']]),
|
|
'created_count' => $result['created_count'],
|
|
'tree' => $this->bomTreeService->buildEditorTree($bom->fresh()),
|
|
]);
|
|
}
|
|
|
|
public function bulkAddNodes(Request $request, $bomId)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$bom = Bom::forBusiness($this->businessId())->findOrFail($bomId);
|
|
|
|
$data = $request->validate([
|
|
'parent_line_id' => 'nullable|exists:ie_bom_lines,id',
|
|
'nodes' => 'required|array|min:1',
|
|
'nodes.*.name' => 'required|string|max:255',
|
|
'nodes.*.item_type' => 'nullable|string',
|
|
'nodes.*.quantity' => 'nullable|numeric|min:0.0001',
|
|
'nodes.*.position_code' => 'nullable|string|max:100',
|
|
'nodes.*.find_number' => 'nullable|string|max:100',
|
|
'nodes.*.children' => 'nullable|array',
|
|
]);
|
|
|
|
try {
|
|
$result = $this->bomTemplateService->bulkAddNodes(
|
|
$bom,
|
|
$data['parent_line_id'] ?? null,
|
|
$data['nodes']
|
|
);
|
|
} catch (InvalidArgumentException $e) {
|
|
return response()->json(['success' => false, 'msg' => $e->getMessage()], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.bulk_nodes_added', ['count' => $result['created_count']]),
|
|
'created_count' => $result['created_count'],
|
|
'tree' => $this->bomTreeService->buildEditorTree($bom->fresh()),
|
|
]);
|
|
}
|
|
|
|
public function saveTemplate(Request $request)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
|
|
$data = $request->validate([
|
|
'bom_line_id' => 'required|exists:ie_bom_lines,id',
|
|
'name' => 'required|string|max:255',
|
|
'description' => 'nullable|string|max:1000',
|
|
'category' => 'nullable|string|max:50',
|
|
]);
|
|
|
|
$line = BomLine::forBusiness($this->businessId())->findOrFail($data['bom_line_id']);
|
|
$template = $this->bomTemplateService->saveFromBomLine(
|
|
$line,
|
|
$data['name'],
|
|
$data['description'] ?? null,
|
|
$data['category'] ?? 'custom'
|
|
);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.template_saved'),
|
|
'template' => [
|
|
'id' => $template->id,
|
|
'key' => 'saved:'.$template->id,
|
|
'name' => $template->name,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function destroyTemplate($id)
|
|
{
|
|
$this->authorizeIe('ie.bom.create');
|
|
$template = BomStructureTemplate::forBusiness($this->businessId())->findOrFail($id);
|
|
$template->delete();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'msg' => __('industrialengineering::lang.template_deleted'),
|
|
]);
|
|
}
|
|
|
|
public function quickCreateItem(Request $request)
|
|
{
|
|
$this->authorizeIe('ie.items.create');
|
|
|
|
$data = $request->validate([
|
|
'item_code' => 'nullable|string|max:100',
|
|
'name' => 'required|string|max:255',
|
|
'item_type' => 'required|string',
|
|
'variation_id' => 'nullable|integer',
|
|
'product_id' => 'nullable|integer',
|
|
'standard_cost' => 'nullable|numeric|min:0',
|
|
]);
|
|
|
|
$codes = $this->resolveCodes('item', $data['item_code'] ?? null, new ItemMaster(), 'item_code');
|
|
$item = ItemMaster::create(array_merge($data, $codes, [
|
|
'business_id' => $this->businessId(),
|
|
'is_serviceable' => true,
|
|
]));
|
|
$this->erpItemLink->linkItem($item, $data);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'item' => [
|
|
'id' => $item->id,
|
|
'item_code' => $item->item_code,
|
|
'name' => $item->name,
|
|
'item_type' => $item->item_type,
|
|
],
|
|
]);
|
|
}
|
|
}
|