feat: supplier modal wizard, pipeline delete, sidebar cleanup
- Replace two-tab supplier selector with two-step wizard (method select → suppliers → summary) - Add per-item channel picker (Email / WhatsApp / Both) in By Item mode - Add confirmation summary step before submitting By Item supplier assignments - Add type-to-confirm delete on pipeline list rows - Redirect purchase.requests.index to pipeline (same data, single entry point) - Remove Purchase Requests from sidebar nav - Add edit-request-modal, supplier-invite-list components - Add address coordinates migration for settings_locations Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
dd924904c5
commit
d8cab94bcb
18 files changed
+1943
-840
No files matched your search
@@ -12,9 +12,7 @@ class PurchaseRequestController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$requests = PurchaseRequest::with(['requestedBy', 'items'])->latest()->paginate(15);
|
||||
|
||||
return view('purchase.requests.index', compact('requests'));
|
||||
return redirect()->route('purchase.pipeline.index');
|
||||
}
|
||||
|
||||
public function create()
|
||||
|
||||
@@ -11,53 +11,106 @@ class ProjectSettingController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$projects = ProjectSetting::with('locations')->orderBy('name')->get();
|
||||
return view('settings.projects.index', compact('projects'));
|
||||
$projects = ProjectSetting::with(['locations' => function ($q) {
|
||||
$q->orderBy('name');
|
||||
}])->orderBy('name')->get();
|
||||
|
||||
$stats = [
|
||||
'total_projects' => $projects->count(),
|
||||
'active_projects' => $projects->where('is_active', true)->count(),
|
||||
'total_locations' => $projects->sum(fn ($p) => $p->locations->count()),
|
||||
'active_locations' => $projects->sum(fn ($p) => $p->locations->where('is_active', true)->count()),
|
||||
];
|
||||
|
||||
return view('settings.projects.index', compact('projects', 'stats'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate(['name' => 'required|string|max:255|unique:settings_projects,name']);
|
||||
ProjectSetting::create(['name' => $request->name, 'is_active' => true]);
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Project added.');
|
||||
$validated = $request->validate(['name' => 'required|string|max:255|unique:settings_projects,name']);
|
||||
$project = ProjectSetting::create(['name' => $validated['name'], 'is_active' => true]);
|
||||
return response()->json(['project' => [
|
||||
'id' => $project->id,
|
||||
'name' => $project->name,
|
||||
'is_active' => $project->is_active,
|
||||
]]);
|
||||
}
|
||||
|
||||
public function update(Request $request, ProjectSetting $project)
|
||||
{
|
||||
$request->validate(['name' => 'required|string|max:255|unique:settings_projects,name,' . $project->id]);
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255|unique:settings_projects,name,' . $project->id,
|
||||
]);
|
||||
$project->update([
|
||||
'name' => $request->name,
|
||||
'name' => $validated['name'],
|
||||
'is_active' => $request->boolean('is_active', true),
|
||||
]);
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Project updated.');
|
||||
return response()->json(['project' => [
|
||||
'id' => $project->id,
|
||||
'name' => $project->name,
|
||||
'is_active' => $project->is_active,
|
||||
]]);
|
||||
}
|
||||
|
||||
public function destroy(ProjectSetting $project)
|
||||
{
|
||||
$project->delete();
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Project deleted.');
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
public function storeLocation(Request $request, ProjectSetting $project)
|
||||
{
|
||||
$request->validate(['name' => 'required|string|max:255']);
|
||||
$project->locations()->create(['name' => $request->name, 'is_active' => true]);
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Location added.');
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'address' => 'nullable|string|max:500',
|
||||
'latitude' => 'nullable|numeric|between:-90,90',
|
||||
'longitude' => 'nullable|numeric|between:-180,180',
|
||||
]);
|
||||
$location = $project->locations()->create([
|
||||
'name' => $validated['name'],
|
||||
'address' => $validated['address'] ?? null,
|
||||
'latitude' => $validated['latitude'] ?? null,
|
||||
'longitude' => $validated['longitude'] ?? null,
|
||||
'is_active' => true,
|
||||
]);
|
||||
return response()->json(['location' => [
|
||||
'id' => $location->id,
|
||||
'name' => $location->name,
|
||||
'address' => $location->address,
|
||||
'latitude' => $location->latitude,
|
||||
'longitude' => $location->longitude,
|
||||
'is_active' => $location->is_active,
|
||||
]]);
|
||||
}
|
||||
|
||||
public function updateLocation(Request $request, ProjectSetting $project, Location $location)
|
||||
{
|
||||
$request->validate(['name' => 'required|string|max:255']);
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'address' => 'nullable|string|max:500',
|
||||
'latitude' => 'nullable|numeric|between:-90,90',
|
||||
'longitude' => 'nullable|numeric|between:-180,180',
|
||||
]);
|
||||
$location->update([
|
||||
'name' => $request->name,
|
||||
'name' => $validated['name'],
|
||||
'address' => $validated['address'] ?? null,
|
||||
'latitude' => $validated['latitude'] ?? null,
|
||||
'longitude' => $validated['longitude'] ?? null,
|
||||
'is_active' => $request->boolean('is_active', true),
|
||||
]);
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Location updated.');
|
||||
return response()->json(['location' => [
|
||||
'id' => $location->id,
|
||||
'name' => $location->name,
|
||||
'address' => $location->address,
|
||||
'latitude' => $location->latitude,
|
||||
'longitude' => $location->longitude,
|
||||
'is_active' => $location->is_active,
|
||||
]]);
|
||||
}
|
||||
|
||||
public function destroyLocation(ProjectSetting $project, Location $location)
|
||||
{
|
||||
$location->delete();
|
||||
return redirect()->route('settings.projects.index')->with('success', 'Location deleted.');
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ class Location extends Model
|
||||
{
|
||||
protected $table = 'settings_locations';
|
||||
|
||||
protected $fillable = ['name', 'project_id', 'is_active'];
|
||||
protected $fillable = ['name', 'project_id', 'is_active', 'address', 'latitude', 'longitude'];
|
||||
|
||||
protected $casts = ['is_active' => 'boolean'];
|
||||
protected $casts = ['is_active' => 'boolean', 'latitude' => 'float', 'longitude' => 'float'];
|
||||
|
||||
public function scopeActive($query)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user