partial update transaction work with stock product
This commit is contained in:
@@ -9,17 +9,30 @@ use App\Models\Stock;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\User;
|
||||
use App\Models\Work;
|
||||
use App\Services\StockService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Exception;
|
||||
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
protected $stockService;
|
||||
|
||||
public function __construct(StockService $stockService)
|
||||
{
|
||||
$this->stockService = $stockService;
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$work_works = Work::leftJoin('categories as c', 'c.id', '=', 'works.category_id')->select('c.name as category_name', 'works.*')->where('c.name', 'LIKE', '%kerja%')->get();
|
||||
$work_works = Work::leftJoin('categories as c', 'c.id', '=', 'works.category_id')
|
||||
->select('c.name as category_name', 'works.*')
|
||||
->where('c.name', 'LIKE', '%kerja%')
|
||||
->orderBy('works.name', 'asc')
|
||||
->get();
|
||||
$wash_work = Work::leftJoin('categories as c', 'c.id', '=', 'works.category_id')->select('c.name as category_name', 'works.*')->where('c.name', 'LIKE', '%cuci%')->first();
|
||||
$user_sas = User::where('role_id', 4)->where('dealer_id', Auth::user()->dealer_id)->get();
|
||||
$count_transaction_users = Transaction::where("user_id", Auth::user()->id)->count();
|
||||
@@ -41,7 +54,9 @@ class TransactionController extends Controller
|
||||
|
||||
public function workcategory($category_id)
|
||||
{
|
||||
$works = Work::where('category_id', $category_id)->get();
|
||||
$works = Work::where('category_id', $category_id)
|
||||
->orderBy('name', 'asc')
|
||||
->get();
|
||||
$response = [
|
||||
"message" => "get work category successfully",
|
||||
"data" => $works,
|
||||
@@ -629,14 +644,28 @@ class TransactionController extends Controller
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
Transaction::find($id)->delete();
|
||||
|
||||
$response = [
|
||||
'message' => 'Data deleted successfully',
|
||||
'status' => 200
|
||||
];
|
||||
|
||||
return redirect()->back();
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$transaction = Transaction::find($id);
|
||||
|
||||
if (!$transaction) {
|
||||
return redirect()->back()->withErrors(['error' => 'Transaksi tidak ditemukan']);
|
||||
}
|
||||
|
||||
// Restore stock before deleting transaction
|
||||
$this->stockService->restoreStockForTransaction($transaction);
|
||||
|
||||
// Delete the transaction
|
||||
$transaction->delete();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect()->back()->with('success', 'Transaksi berhasil dihapus dan stock telah dikembalikan');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
return redirect()->back()->withErrors(['error' => 'Gagal menghapus transaksi: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
@@ -645,9 +674,19 @@ class TransactionController extends Controller
|
||||
$request->validate([
|
||||
'work_id.*' => ['required', 'integer'],
|
||||
'quantity.*' => ['required', 'integer'],
|
||||
'spk_no' => ['required', function($attribute, $value, $fail) use($request) {
|
||||
$date = explode('/', $request->date);
|
||||
$date = $date[2].'-'.$date[0].'-'.$date[1];
|
||||
'spk_no' => ['required', 'string', 'min:1', function($attribute, $value, $fail) use($request) {
|
||||
// Handle date format conversion safely for validation
|
||||
if (strpos($request->date, '/') !== false) {
|
||||
$dateParts = explode('/', $request->date);
|
||||
if (count($dateParts) === 3) {
|
||||
$date = $dateParts[2].'-'.$dateParts[0].'-'.$dateParts[1];
|
||||
} else {
|
||||
$fail('Format tanggal tidak valid');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$date = $request->date;
|
||||
}
|
||||
|
||||
if(!$request->work_id) {
|
||||
$fail('Pekerjaan harus diisi');
|
||||
@@ -665,9 +704,19 @@ class TransactionController extends Controller
|
||||
}
|
||||
}
|
||||
}],
|
||||
'police_number' => ['required', function($attribute, $value, $fail) use($request) {
|
||||
$date = explode('/', $request->date);
|
||||
$date = $date[2].'-'.$date[0].'-'.$date[1];
|
||||
'police_number' => ['required', 'string', 'min:1', function($attribute, $value, $fail) use($request) {
|
||||
// Handle date format conversion safely for validation
|
||||
if (strpos($request->date, '/') !== false) {
|
||||
$dateParts = explode('/', $request->date);
|
||||
if (count($dateParts) === 3) {
|
||||
$date = $dateParts[2].'-'.$dateParts[0].'-'.$dateParts[1];
|
||||
} else {
|
||||
$fail('Format tanggal tidak valid');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$date = $request->date;
|
||||
}
|
||||
|
||||
if(!$request->work_id) {
|
||||
$fail('Pekerjaan harus diisi');
|
||||
@@ -686,9 +735,19 @@ class TransactionController extends Controller
|
||||
}
|
||||
}],
|
||||
'warranty' => ['required'],
|
||||
'date' => ['required', function($attribute, $value, $fail) use($request) {
|
||||
$date = explode('/', $value);
|
||||
$date = $date[2].'-'.$date[0].'-'.$date[1];
|
||||
'date' => ['required', 'string', 'min:1', function($attribute, $value, $fail) use($request) {
|
||||
// Handle date format conversion safely for validation
|
||||
if (strpos($value, '/') !== false) {
|
||||
$dateParts = explode('/', $value);
|
||||
if (count($dateParts) === 3) {
|
||||
$date = $dateParts[2].'-'.$dateParts[0].'-'.$dateParts[1];
|
||||
} else {
|
||||
$fail('Format tanggal tidak valid. Gunakan format MM/DD/YYYY atau YYYY-MM-DD');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$date = $value;
|
||||
}
|
||||
|
||||
if(!$request->work_id) {
|
||||
$fail('Pekerjaan harus diisi');
|
||||
@@ -707,31 +766,117 @@ class TransactionController extends Controller
|
||||
}
|
||||
}],
|
||||
'category' => ['required'],
|
||||
'user_sa_id' => ['required', 'integer'],
|
||||
'user_sa_id' => ['required', 'integer', 'exists:users,id'],
|
||||
], [
|
||||
'spk_no.required' => 'No. SPK harus diisi',
|
||||
'spk_no.min' => 'No. SPK tidak boleh kosong',
|
||||
'police_number.required' => 'No. Polisi harus diisi',
|
||||
'police_number.min' => 'No. Polisi tidak boleh kosong',
|
||||
'date.required' => 'Tanggal Pekerjaan harus diisi',
|
||||
'date.min' => 'Tanggal Pekerjaan tidak boleh kosong',
|
||||
'user_sa_id.required' => 'Service Advisor harus dipilih',
|
||||
'user_sa_id.exists' => 'Service Advisor yang dipilih tidak valid',
|
||||
'work_id.*.required' => 'Pekerjaan harus dipilih',
|
||||
'quantity.*.required' => 'Quantity harus diisi',
|
||||
]);
|
||||
|
||||
$request['date'] = explode('/', $request->date);
|
||||
$request['date'] = $request['date'][2].'-'.$request['date'][0].'-'.$request['date'][1];
|
||||
|
||||
$data = [];
|
||||
for($i = 0; $i < count($request->work_id); $i++) {
|
||||
$data[] = [
|
||||
"user_id" => $request->mechanic_id,
|
||||
"dealer_id" => $request->dealer_id,
|
||||
"form" => $request->form,
|
||||
"work_id" => $request->work_id[$i],
|
||||
"qty" => $request->quantity[$i],
|
||||
"spk" => $request->spk_no,
|
||||
"police_number" => $request->police_number,
|
||||
"warranty" => $request->warranty,
|
||||
"user_sa_id" => $request->user_sa_id,
|
||||
"date" => $request->date,
|
||||
"created_at" => date('Y-m-d H:i:s')
|
||||
];
|
||||
// Handle date format conversion safely
|
||||
$dateValue = $request->date;
|
||||
if (strpos($dateValue, '/') !== false) {
|
||||
// If date is in MM/DD/YYYY format, convert to Y-m-d
|
||||
$dateParts = explode('/', $dateValue);
|
||||
if (count($dateParts) === 3) {
|
||||
$request['date'] = $dateParts[2].'-'.$dateParts[0].'-'.$dateParts[1];
|
||||
} else {
|
||||
// Invalid date format, use as is
|
||||
$request['date'] = $dateValue;
|
||||
}
|
||||
} else {
|
||||
// Date is already in Y-m-d format or other format, use as is
|
||||
$request['date'] = $dateValue;
|
||||
}
|
||||
|
||||
Transaction::insert($data);
|
||||
return redirect()->back()->with('success', 'Berhasil input pekerjaan');
|
||||
// Check stock availability for all works before creating transactions
|
||||
$stockErrors = [];
|
||||
for($i = 0; $i < count($request->work_id); $i++) {
|
||||
$stockCheck = $this->stockService->checkStockAvailability(
|
||||
$request->work_id[$i],
|
||||
$request->dealer_id,
|
||||
$request->quantity[$i]
|
||||
);
|
||||
|
||||
if (!$stockCheck['available']) {
|
||||
$work = Work::find($request->work_id[$i]);
|
||||
$stockErrors[] = "Pekerjaan '{$work->name}': {$stockCheck['message']}";
|
||||
|
||||
// Add detailed stock information
|
||||
if (!empty($stockCheck['details'])) {
|
||||
foreach ($stockCheck['details'] as $detail) {
|
||||
if (!$detail['is_available']) {
|
||||
$stockErrors[] = "- {$detail['product_name']}: Dibutuhkan {$detail['required_quantity']}, Tersedia {$detail['available_stock']}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are stock errors, return with error messages
|
||||
if (!empty($stockErrors)) {
|
||||
return redirect()->back()
|
||||
->withErrors(['stock' => implode('<br>', $stockErrors)])
|
||||
->withInput();
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$transactions = [];
|
||||
$data = [];
|
||||
|
||||
// Create transaction records
|
||||
for($i = 0; $i < count($request->work_id); $i++) {
|
||||
$transactionData = [
|
||||
"user_id" => $request->mechanic_id,
|
||||
"dealer_id" => $request->dealer_id,
|
||||
"form" => $request->form,
|
||||
"work_id" => $request->work_id[$i],
|
||||
"qty" => $request->quantity[$i],
|
||||
"spk" => $request->spk_no,
|
||||
"police_number" => $request->police_number,
|
||||
"warranty" => $request->warranty,
|
||||
"user_sa_id" => $request->user_sa_id,
|
||||
"date" => $request->date,
|
||||
"status" => 'completed', // Mark as completed to trigger stock reduction
|
||||
"created_at" => date('Y-m-d H:i:s'),
|
||||
"updated_at" => date('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
$data[] = $transactionData;
|
||||
}
|
||||
|
||||
// Insert all transactions
|
||||
Transaction::insert($data);
|
||||
|
||||
// Get the created transactions for stock reduction
|
||||
$createdTransactions = Transaction::where('spk', $request->spk_no)
|
||||
->where('police_number', $request->police_number)
|
||||
->where('date', $request->date)
|
||||
->where('dealer_id', $request->dealer_id)
|
||||
->get();
|
||||
|
||||
// Reduce stock for each transaction
|
||||
foreach ($createdTransactions as $transaction) {
|
||||
$this->stockService->reduceStockForTransaction($transaction);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return redirect()->back()->with('success', 'Berhasil input pekerjaan dan stock telah dikurangi otomatis');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
return redirect()->back()
|
||||
->withErrors(['error' => 'Gagal menyimpan transaksi: ' . $e->getMessage()])
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
@@ -764,4 +909,62 @@ class TransactionController extends Controller
|
||||
|
||||
return response()->json($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check stock availability for work at dealer
|
||||
*/
|
||||
public function checkStockAvailability(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'work_id' => 'required|exists:works,id',
|
||||
'dealer_id' => 'required|exists:dealers,id',
|
||||
'quantity' => 'required|integer|min:1'
|
||||
]);
|
||||
|
||||
try {
|
||||
$availability = $this->stockService->checkStockAvailability(
|
||||
$request->work_id,
|
||||
$request->dealer_id,
|
||||
$request->quantity
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'status' => 200,
|
||||
'data' => $availability
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return response()->json([
|
||||
'status' => 500,
|
||||
'message' => 'Error checking stock: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stock prediction for work
|
||||
*/
|
||||
public function getStockPrediction(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'work_id' => 'required|exists:works,id',
|
||||
'quantity' => 'required|integer|min:1'
|
||||
]);
|
||||
|
||||
try {
|
||||
$prediction = $this->stockService->getStockUsagePrediction(
|
||||
$request->work_id,
|
||||
$request->quantity
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'status' => 200,
|
||||
'data' => $prediction
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return response()->json([
|
||||
'status' => 500,
|
||||
'message' => 'Error getting prediction: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user