Files
services_core/app/Services/Material/MaterialService.php
T
2026-07-27 16:24:09 +07:00

314 lines
10 KiB
PHP

<?php
namespace App\Services\Material;
use App\Models\MaterialMovement;
use App\Models\TechnicianConsumable;
use App\Models\TechnicianMaterial;
use DB;
class MaterialService
{
public function list(array $filters = [])
{
$serialized = TechnicianMaterial::query()
->select([
'id',
'user_id',
'barcode_id',
'inventory_item_id',
'material_name',
'serial_number',
'status',
'assigned_at',
'assigned_by',
'created_at',
'updated_at',
DB::raw('NULL as unit'),
DB::raw('NULL as qty_received'),
DB::raw('NULL as qty_used'),
DB::raw('NULL as qty_remaining'),
DB::raw("'serialized' as type"),
]);
$consumable = TechnicianConsumable::query()
->select([
'id',
'user_id',
'barcode_id',
'inventory_item_id',
'material_name',
DB::raw('NULL as serial_number'),
'status',
'assigned_at',
'assigned_by',
'created_at',
'updated_at',
'unit',
'qty_received',
'qty_used',
'qty_remaining',
DB::raw("'consumable' as type"),
]);
if (! empty($filters['user_id'])) {
$serialized->where('user_id', $filters['user_id']);
$consumable->where('user_id', $filters['user_id']);
}
if (! empty($filters['search'])) {
$search = $filters['search'];
$serialized->where(function ($query) use ($search) {
$query->where('barcode_id', 'ILIKE', "%$search%")
->orWhere('material_name', 'ILIKE', "%$search%");
});
$consumable->where(function ($query) use ($search) {
$query->where('barcode_id', 'ILIKE', "%$search%")
->orWhere('material_name', 'ILIKE', "%$search%");
});
}
if (! empty($filters['status'])) {
$serialized->where('status', $filters['status']);
$consumable->where('status', $filters['status']);
}
if (($filters['type'] ?? null) === 'serialized') {
$consumable->whereRaw('1 = 0');
}
if (($filters['type'] ?? null) === 'consumable') {
$serialized->whereRaw('1 = 0');
}
$query = $serialized->unionAll($consumable);
return DB::query()
->fromSub($query, 'materials')
->orderByDesc('created_at')
->paginate($filters['per_page'] ?? 15);
}
/*
|--------------------------------------------------------------------------
| ASSIGN MATERIAL (AUTO DETECT TYPE)
|--------------------------------------------------------------------------
*/
public function assign($data)
{
return DB::transaction(function () use ($data) {
$type = $data['type'];
// type dari API Gudang: serialized / consumable
/*
|--------------------------------------------------------------------------
| SERIALIZED (ONT, Router, dll)
|--------------------------------------------------------------------------
*/
if ($type === 'serialized') {
$material = TechnicianMaterial::create([
'user_id' => $data['user_id'],
'barcode_id' => $data['barcode_id'],
'material_name' => $data['material_name'],
'serial_number' => $data['serial_number'] ?? null,
'status' => 'assigned',
'assigned_at' => now(),
'assigned_by' => auth()->id(),
]);
MaterialMovement::create([
'barcode_id' => $data['barcode_id'],
'user_id' => $data['user_id'],
'to_user_id' => $data['user_id'],
'movement_type' => 'assign',
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $material;
}
/*
|--------------------------------------------------------------------------
| CONSUMABLE (FO, kabel, dll)
|--------------------------------------------------------------------------
*/
$material = TechnicianConsumable::create([
'user_id' => $data['user_id'],
'barcode_id' => $data['barcode_id'],
'material_name' => $data['material_name'],
'unit' => $data['unit'] ?? 'meter',
'qty_received' => $data['qty'] ?? 0,
'qty_remaining' => $data['qty'] ?? 0,
'qty_used' => 0,
'status' => 'assigned',
'assigned_at' => now(),
'assigned_by' => auth()->id(),
]);
MaterialMovement::create([
'barcode_id' => $data['barcode_id'],
'user_id' => $data['user_id'],
'to_user_id' => $data['user_id'],
'movement_type' => 'assign',
'qty' => $data['qty'] ?? 0,
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $material;
});
}
/*
|--------------------------------------------------------------------------
| TRANSFER MATERIAL
|--------------------------------------------------------------------------
*/
public function transfer($data)
{
return DB::transaction(function () use ($data) {
$barcode = $data['barcode_id'];
// cek serialized dulu
$serialized = TechnicianMaterial::where('barcode_id', $barcode)->first();
if ($serialized) {
$serialized->update([
'user_id' => $data['to_user_id'],
]);
MaterialMovement::create([
'barcode_id' => $barcode,
'from_user_id' => $data['from_user_id'],
'to_user_id' => $data['to_user_id'],
'movement_type' => 'transfer',
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $serialized;
}
// kalau bukan serialized → consumable
$consumable = TechnicianConsumable::where('barcode_id', $barcode)->first();
$consumable->update([
'user_id' => $data['to_user_id'],
]);
MaterialMovement::create([
'barcode_id' => $barcode,
'from_user_id' => $data['from_user_id'],
'to_user_id' => $data['to_user_id'],
'movement_type' => 'transfer',
'qty' => $consumable->qty_remaining,
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $consumable;
});
}
/*
|--------------------------------------------------------------------------
| RETURN MATERIAL
|--------------------------------------------------------------------------
*/
public function return($data)
{
return DB::transaction(function () use ($data) {
$barcode = $data['barcode_id'];
$serialized = TechnicianMaterial::where('barcode_id', $barcode)->first();
if ($serialized) {
$serialized->update([
'user_id' => null,
'status' => 'returned',
]);
MaterialMovement::create([
'barcode_id' => $barcode,
'user_id' => $data['user_id'],
'from_user_id' => $data['user_id'],
'movement_type' => 'return',
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $serialized;
}
$consumable = TechnicianConsumable::where('barcode_id', $barcode)->first();
$consumable->update([
'user_id' => null,
'status' => 'returned',
]);
MaterialMovement::create([
'barcode_id' => $barcode,
'user_id' => $data['user_id'],
'from_user_id' => $data['user_id'],
'movement_type' => 'return',
'qty' => $consumable->qty_remaining,
'created_by' => auth()->id(),
'created_at' => now(),
]);
return $consumable;
});
}
public function listByUser($userId)
{
$serialized = TechnicianMaterial::where('user_id', $userId)
->get()
->map(function ($item) {
$item->type = 'serialized';
return $item;
});
$consumable = TechnicianConsumable::where('user_id', $userId)
->get()
->map(function ($item) {
$item->type = 'consumable';
return $item;
});
return $serialized
->concat($consumable)
->values();
}
public function history($barcodeId)
{
return MaterialMovement::where('barcode_id', $barcodeId)
->orderBy('created_at', 'desc')
->get()
->map(function ($item) {
return [
'barcode_id' => $item->barcode_id,
'type' => $item->movement_type,
'from_user_id' => $item->from_user_id,
'to_user_id' => $item->to_user_id,
'ticket_id' => $item->ticket_id,
'qty' => $item->qty,
'description' => $item->description,
'created_at' => $item->created_at,
];
});
}
}