remove status pending and complete
This commit is contained in:
97
app/Console/Commands/CleanMutationsData.php
Normal file
97
app/Console/Commands/CleanMutationsData.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CleanMutationsData extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'mutations:clean {--force : Force cleanup without confirmation}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clean mutations data to allow migration rollback';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (!$this->option('force')) {
|
||||
if (!$this->confirm('This will delete ALL mutations data. Are you sure?')) {
|
||||
$this->info('Operation cancelled.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
// Delete mutations data in proper order (foreign key constraints)
|
||||
$this->info('Cleaning mutations data...');
|
||||
|
||||
// 1. Delete stock logs related to mutations
|
||||
if (Schema::hasTable('stock_logs')) {
|
||||
$deleted = DB::table('stock_logs')
|
||||
->where('source_type', 'App\\Models\\Mutation')
|
||||
->delete();
|
||||
$this->info("Deleted {$deleted} stock logs related to mutations");
|
||||
}
|
||||
|
||||
// 2. Delete mutation details
|
||||
if (Schema::hasTable('mutation_details')) {
|
||||
$deleted = DB::table('mutation_details')->delete();
|
||||
$this->info("Deleted {$deleted} mutation details");
|
||||
}
|
||||
|
||||
// 3. Delete mutations
|
||||
if (Schema::hasTable('mutations')) {
|
||||
$deleted = DB::table('mutations')->delete();
|
||||
$this->info("Deleted {$deleted} mutations");
|
||||
}
|
||||
|
||||
// 4. Reset auto increment
|
||||
if (Schema::hasTable('mutations')) {
|
||||
DB::statement('ALTER TABLE mutations AUTO_INCREMENT = 1');
|
||||
$this->info('Reset mutations auto increment');
|
||||
}
|
||||
|
||||
if (Schema::hasTable('mutation_details')) {
|
||||
DB::statement('ALTER TABLE mutation_details AUTO_INCREMENT = 1');
|
||||
$this->info('Reset mutation_details auto increment');
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
$this->info('✅ Mutations data cleaned successfully!');
|
||||
$this->info('You can now rollback and re-run migrations.');
|
||||
|
||||
return 0;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
$this->error('❌ Error cleaning mutations data: ' . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,23 +4,19 @@ namespace App\Enums;
|
||||
|
||||
enum MutationStatus: string
|
||||
{
|
||||
case PENDING = 'pending';
|
||||
case SENT = 'sent';
|
||||
case RECEIVED = 'received';
|
||||
case APPROVED = 'approved';
|
||||
case REJECTED = 'rejected';
|
||||
case COMPLETED = 'completed';
|
||||
case CANCELLED = 'cancelled';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::PENDING => 'Menunggu Konfirmasi',
|
||||
self::SENT => 'Terkirim ke Dealer',
|
||||
self::RECEIVED => 'Diterima Dealer',
|
||||
self::APPROVED => 'Disetujui',
|
||||
self::APPROVED => 'Disetujui & Stock Dipindahkan',
|
||||
self::REJECTED => 'Ditolak',
|
||||
self::COMPLETED => 'Selesai',
|
||||
self::CANCELLED => 'Dibatalkan',
|
||||
};
|
||||
}
|
||||
@@ -28,12 +24,10 @@ enum MutationStatus: string
|
||||
public function color(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::PENDING => 'warning',
|
||||
self::SENT => 'primary',
|
||||
self::RECEIVED => 'info',
|
||||
self::APPROVED => 'brand',
|
||||
self::REJECTED => 'danger',
|
||||
self::COMPLETED => 'success',
|
||||
self::CANCELLED => 'secondary',
|
||||
};
|
||||
}
|
||||
@@ -55,12 +49,10 @@ enum MutationStatus: string
|
||||
public static function getOptions(): array
|
||||
{
|
||||
return [
|
||||
self::PENDING->value => self::PENDING->label(),
|
||||
self::SENT->value => self::SENT->label(),
|
||||
self::RECEIVED->value => self::RECEIVED->label(),
|
||||
self::APPROVED->value => self::APPROVED->label(),
|
||||
self::REJECTED->value => self::REJECTED->label(),
|
||||
self::COMPLETED->value => self::COMPLETED->label(),
|
||||
self::CANCELLED->value => self::CANCELLED->label(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -182,8 +182,18 @@ class MutationsController extends Controller
|
||||
$mutation->receive(auth()->id(), $request->reception_notes);
|
||||
|
||||
DB::commit();
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil diterima dan menunggu persetujuan pengirim');
|
||||
|
||||
// Check user role and redirect accordingly
|
||||
if (!auth()->user()->dealer_id) {
|
||||
// Users without dealer_id are likely admin, redirect to mutations index
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil diterima dan siap untuk disetujui. Stock akan dipindahkan setelah disetujui.');
|
||||
} else {
|
||||
// Dealer users redirect back to transaction page
|
||||
return redirect()->route('transaction')
|
||||
->with('success', 'Mutasi berhasil diterima. Silakan setujui mutasi ini untuk memindahkan stock.')
|
||||
->with('active_tab', 'penerimaan');
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
@@ -202,11 +212,25 @@ class MutationsController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
// Approve mutation (quantity_approved sudah diisi saat receive)
|
||||
// Approve mutation (stock will move automatically)
|
||||
$mutation->approve(auth()->id(), $request->approval_notes);
|
||||
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil disetujui');
|
||||
// Check user role and redirect accordingly
|
||||
if (!auth()->user()->dealer_id) {
|
||||
// Admin users redirect to mutations index
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil disetujui dan stock telah dipindahkan');
|
||||
} else {
|
||||
// Dealer users
|
||||
if ($request->has('from_transaction_page') || str_contains($request->header('referer', ''), '/transaction')) {
|
||||
return redirect()->route('transaction')
|
||||
->with('success', 'Mutasi berhasil disetujui dan stock telah dipindahkan')
|
||||
->with('active_tab', 'penerimaan');
|
||||
} else {
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil disetujui dan stock telah dipindahkan');
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return back()->withErrors(['error' => 'Gagal menyetujui mutasi: ' . $e->getMessage()]);
|
||||
@@ -226,30 +250,29 @@ class MutationsController extends Controller
|
||||
try {
|
||||
$mutation->reject(auth()->id(), $request->rejection_reason);
|
||||
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil ditolak');
|
||||
// Check user role and redirect accordingly
|
||||
if (!auth()->user()->dealer_id) {
|
||||
// Admin users redirect to mutations index
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil ditolak');
|
||||
} else {
|
||||
// Dealer users
|
||||
if ($request->has('from_transaction_page') || str_contains($request->header('referer', ''), '/transaction')) {
|
||||
return redirect()->route('transaction')
|
||||
->with('success', 'Mutasi berhasil ditolak')
|
||||
->with('active_tab', 'penerimaan');
|
||||
} else {
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil ditolak');
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return back()->withErrors(['error' => 'Gagal menolak mutasi: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function complete(Mutation $mutation)
|
||||
{
|
||||
if (!$mutation->canBeCompleted()) {
|
||||
return back()->withErrors(['error' => 'Mutasi tidak dapat diselesaikan dalam status saat ini']);
|
||||
}
|
||||
|
||||
try {
|
||||
$mutation->complete();
|
||||
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil diselesaikan dan stock telah dipindahkan');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return back()->withErrors(['error' => 'Gagal menyelesaikan mutasi: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
// Complete method removed - Stock moves automatically after approval
|
||||
|
||||
public function cancel(Request $request, Mutation $mutation)
|
||||
{
|
||||
@@ -294,9 +317,20 @@ class MutationsController extends Controller
|
||||
{
|
||||
$dealerId = $request->dealer_id;
|
||||
|
||||
// Get mutations that need action from this dealer:
|
||||
// 1. 'sent' status where this dealer is the recipient (need to receive)
|
||||
// 2. 'received' status where this dealer is the recipient (need to approve) - CORRECTED LOGIC
|
||||
$data = Mutation::with(['fromDealer', 'toDealer', 'requestedBy.role'])
|
||||
->where('to_dealer_id', $dealerId)
|
||||
->where('status', 'sent')
|
||||
->where(function($query) use ($dealerId) {
|
||||
// Mutations sent to this dealer that need to be received
|
||||
$query->where('to_dealer_id', $dealerId)
|
||||
->where('status', 'sent');
|
||||
// OR mutations received by this dealer that need approval from recipient
|
||||
$query->orWhere(function($subQuery) use ($dealerId) {
|
||||
$subQuery->where('to_dealer_id', $dealerId)
|
||||
->where('status', 'received');
|
||||
});
|
||||
})
|
||||
->select('mutations.*');
|
||||
|
||||
return DataTables::of($data)
|
||||
@@ -307,6 +341,9 @@ class MutationsController extends Controller
|
||||
->addColumn('from_dealer', function($row) {
|
||||
return $row->fromDealer->name ?? '-';
|
||||
})
|
||||
->addColumn('to_dealer', function($row) {
|
||||
return $row->toDealer->name ?? '-';
|
||||
})
|
||||
->addColumn('status', function($row) {
|
||||
$statusColor = $row->status_color;
|
||||
$statusLabel = $row->status_label;
|
||||
@@ -330,10 +367,28 @@ class MutationsController extends Controller
|
||||
->addColumn('created_at', function($row) {
|
||||
return $row->created_at->format('d/m/Y H:i');
|
||||
})
|
||||
->addColumn('action', function($row) {
|
||||
return '<button type="button" class="btn btn-info btn-sm btn-detail" onclick="showMutationDetail('.$row->id.')">
|
||||
Detail
|
||||
</button>';
|
||||
->addColumn('action', function($row) use ($dealerId) {
|
||||
$buttons = '';
|
||||
|
||||
if ($row->status->value === 'sent' && $row->to_dealer_id == $dealerId) {
|
||||
// For sent mutations where current dealer is recipient - show detail button for receiving
|
||||
$buttons .= '<button type="button" class="btn btn-info btn-sm btn-detail" onclick="showMutationDetail('.$row->id.')">
|
||||
Detail & Terima
|
||||
</button>';
|
||||
} elseif ($row->status->value === 'received' && $row->to_dealer_id == $dealerId) {
|
||||
// For received mutations where current dealer is recipient - show approve/reject buttons
|
||||
$buttons .= '<button type="button" class="btn btn-info btn-sm btn-detail mr-1" onclick="showMutationDetail('.$row->id.')">
|
||||
Detail
|
||||
</button>';
|
||||
$buttons .= '<button type="button" class="btn btn-success btn-sm btn-approve-mutation mr-1" data-id="'.$row->id.'">
|
||||
Setujui
|
||||
</button>';
|
||||
$buttons .= '<button type="button" class="btn btn-danger btn-sm btn-reject-mutation" data-id="'.$row->id.'">
|
||||
Tolak
|
||||
</button>';
|
||||
}
|
||||
|
||||
return $buttons;
|
||||
})
|
||||
->rawColumns(['status', 'action'])
|
||||
->make(true);
|
||||
|
||||
@@ -116,11 +116,6 @@ class Mutation extends Model
|
||||
return $this->mutationDetails()->sum('quantity_approved');
|
||||
}
|
||||
|
||||
public function canBeSent()
|
||||
{
|
||||
return $this->status === MutationStatus::PENDING;
|
||||
}
|
||||
|
||||
public function canBeReceived()
|
||||
{
|
||||
return $this->status === MutationStatus::SENT;
|
||||
@@ -131,28 +126,9 @@ class Mutation extends Model
|
||||
return $this->status === MutationStatus::RECEIVED;
|
||||
}
|
||||
|
||||
public function canBeCompleted()
|
||||
{
|
||||
return $this->status === MutationStatus::APPROVED;
|
||||
}
|
||||
|
||||
public function canBeCancelled()
|
||||
{
|
||||
return in_array($this->status, [MutationStatus::PENDING, MutationStatus::SENT]);
|
||||
}
|
||||
|
||||
// Send mutation to destination dealer
|
||||
public function send($userId)
|
||||
{
|
||||
if (!$this->canBeSent()) {
|
||||
throw new \Exception('Mutasi tidak dapat dikirim dalam status saat ini');
|
||||
}
|
||||
|
||||
$this->update([
|
||||
'status' => MutationStatus::SENT
|
||||
]);
|
||||
|
||||
return $this;
|
||||
return $this->status === MutationStatus::SENT;
|
||||
}
|
||||
|
||||
// Receive mutation by destination dealer
|
||||
@@ -172,19 +148,37 @@ class Mutation extends Model
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Approve mutation
|
||||
// Approve mutation and move stock immediately
|
||||
public function approve($userId, $approvalNotes = null)
|
||||
{
|
||||
if (!$this->canBeApproved()) {
|
||||
throw new \Exception('Mutasi tidak dapat disetujui dalam status saat ini');
|
||||
}
|
||||
|
||||
$this->update([
|
||||
'status' => MutationStatus::APPROVED,
|
||||
'approved_by' => $userId,
|
||||
'approved_at' => now(),
|
||||
'approval_notes' => $approvalNotes
|
||||
]);
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Update status to approved first
|
||||
$this->update([
|
||||
'status' => MutationStatus::APPROVED,
|
||||
'approved_by' => $userId,
|
||||
'approved_at' => now(),
|
||||
'approval_notes' => $approvalNotes
|
||||
]);
|
||||
|
||||
// Immediately move stock after approval
|
||||
foreach ($this->mutationDetails as $detail) {
|
||||
// Process all details that have quantity_requested > 0
|
||||
// because goods have been sent from source dealer
|
||||
if ($detail->quantity_requested > 0) {
|
||||
$this->processStockMovement($detail);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -223,32 +217,7 @@ class Mutation extends Model
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Complete mutation (actually move the stock)
|
||||
public function complete()
|
||||
{
|
||||
if (!$this->canBeCompleted()) {
|
||||
throw new \Exception('Mutasi tidak dapat diselesaikan dalam status saat ini');
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
foreach ($this->mutationDetails as $detail) {
|
||||
// Proses semua detail yang memiliki quantity_requested > 0
|
||||
// karena barang sudah dikirim dari dealer asal
|
||||
if ($detail->quantity_requested > 0) {
|
||||
$this->processStockMovement($detail);
|
||||
}
|
||||
}
|
||||
|
||||
$this->update(['status' => MutationStatus::COMPLETED]);
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
// Complete method removed - Stock moves automatically after approval
|
||||
|
||||
private function processStockMovement(MutationDetail $detail)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ class MutationDetail extends Model
|
||||
{
|
||||
// Hanya dianggap ditolak jika mutasi sudah di-approve/reject dan quantity_approved = 0
|
||||
$mutationStatus = $this->mutation->status->value ?? null;
|
||||
return in_array($mutationStatus, ['approved', 'completed', 'rejected']) && $this->quantity_approved == 0;
|
||||
return in_array($mutationStatus, ['approved', 'rejected']) && $this->quantity_approved == 0;
|
||||
}
|
||||
|
||||
public function getApprovalStatusAttribute()
|
||||
@@ -60,11 +60,11 @@ class MutationDetail extends Model
|
||||
$mutationStatus = $this->mutation->status->value ?? null;
|
||||
|
||||
// Jika mutasi belum di-approve, semua detail statusnya "Menunggu"
|
||||
if (!in_array($mutationStatus, ['approved', 'completed', 'rejected'])) {
|
||||
if (!in_array($mutationStatus, ['approved', 'rejected'])) {
|
||||
return 'Menunggu';
|
||||
}
|
||||
|
||||
// Jika mutasi sudah di-approve/complete, baru cek quantity_approved
|
||||
// Jika mutasi sudah di-approve, baru cek quantity_approved
|
||||
if ($this->isFullyApproved()) {
|
||||
return 'Disetujui Penuh';
|
||||
} elseif ($this->isPartiallyApproved()) {
|
||||
@@ -81,11 +81,11 @@ class MutationDetail extends Model
|
||||
$mutationStatus = $this->mutation->status->value ?? null;
|
||||
|
||||
// Jika mutasi belum di-approve, semua detail statusnya "info" (menunggu)
|
||||
if (!in_array($mutationStatus, ['approved', 'completed', 'rejected'])) {
|
||||
if (!in_array($mutationStatus, ['approved', 'rejected'])) {
|
||||
return 'info';
|
||||
}
|
||||
|
||||
// Jika mutasi sudah di-approve/complete, baru cek quantity_approved
|
||||
// Jika mutasi sudah di-approve, baru cek quantity_approved
|
||||
if ($this->isFullyApproved()) {
|
||||
return 'success';
|
||||
} elseif ($this->isPartiallyApproved()) {
|
||||
|
||||
Reference in New Issue
Block a user