- Fix all CRM controllers to explicitly pass $business to views - Add scopeOutstanding() to CrmInvoice model - Add fallback in CRM layout to get $business from route - Reorder sidebar menu sections (Overview, Inbox, Commerce, etc.) - Add delivery location selector to quote create form - Add migration for location_id on crm_quotes table
257 lines
8.9 KiB
PHP
257 lines
8.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Seller\Crm;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Business;
|
|
use App\Models\Crm\CrmAutomation;
|
|
use App\Models\Crm\CrmAutomationAction;
|
|
use App\Models\Crm\CrmAutomationCondition;
|
|
use Illuminate\Http\Request;
|
|
|
|
class AutomationController extends Controller
|
|
{
|
|
/**
|
|
* List automations
|
|
*/
|
|
public function index(Request $request, Business $business)
|
|
{
|
|
$automations = CrmAutomation::forBusiness($business->id)
|
|
->with('creator')
|
|
->withCount(['logs as successful_runs' => fn ($q) => $q->completed()])
|
|
->orderByDesc('created_at')
|
|
->paginate(25);
|
|
|
|
return view('seller.crm.automations.index', compact('automations', 'business'));
|
|
}
|
|
|
|
/**
|
|
* Show automation builder
|
|
*/
|
|
public function create(Request $request, Business $business)
|
|
{
|
|
$triggers = CrmAutomation::TRIGGERS;
|
|
$operators = CrmAutomationCondition::OPERATORS;
|
|
$actionTypes = CrmAutomationAction::TYPES;
|
|
|
|
return view('seller.crm.automations.create', compact('triggers', 'operators', 'actionTypes', 'business'));
|
|
}
|
|
|
|
/**
|
|
* Store automation
|
|
*/
|
|
public function store(Request $request, Business $business)
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'description' => 'nullable|string|max:1000',
|
|
'trigger_type' => 'required|string',
|
|
'trigger_config' => 'nullable|array',
|
|
'is_active' => 'boolean',
|
|
'stop_on_error' => 'boolean',
|
|
'max_runs_per_day' => 'nullable|integer|min:1',
|
|
'conditions' => 'nullable|array',
|
|
'conditions.*.field' => 'required|string',
|
|
'conditions.*.operator' => 'required|string',
|
|
'conditions.*.value' => 'nullable',
|
|
'conditions.*.logic_operator' => 'nullable|in:AND,OR',
|
|
'actions' => 'required|array|min:1',
|
|
'actions.*.type' => 'required|string',
|
|
'actions.*.config' => 'nullable|array',
|
|
]);
|
|
|
|
$automation = CrmAutomation::create([
|
|
'business_id' => $business->id,
|
|
'created_by' => $request->user()->id,
|
|
'name' => $validated['name'],
|
|
'description' => $validated['description'],
|
|
'trigger_type' => $validated['trigger_type'],
|
|
'trigger_config' => $validated['trigger_config'] ?? [],
|
|
'is_active' => $validated['is_active'] ?? false,
|
|
'stop_on_error' => $validated['stop_on_error'] ?? true,
|
|
'max_runs_per_day' => $validated['max_runs_per_day'],
|
|
]);
|
|
|
|
// Create conditions
|
|
if (! empty($validated['conditions'])) {
|
|
foreach ($validated['conditions'] as $index => $condition) {
|
|
CrmAutomationCondition::create([
|
|
'automation_id' => $automation->id,
|
|
'field' => $condition['field'],
|
|
'operator' => $condition['operator'],
|
|
'value' => $condition['value'],
|
|
'logic_operator' => $condition['logic_operator'] ?? 'AND',
|
|
'order' => $index,
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Create actions
|
|
foreach ($validated['actions'] as $index => $action) {
|
|
CrmAutomationAction::create([
|
|
'automation_id' => $automation->id,
|
|
'type' => $action['type'],
|
|
'config' => $action['config'] ?? [],
|
|
'order' => $index,
|
|
'is_active' => true,
|
|
]);
|
|
}
|
|
|
|
return redirect()->route('seller.business.crm.automations.show', [$business, $automation])
|
|
->with('success', 'Automation created successfully.');
|
|
}
|
|
|
|
/**
|
|
* Show automation details
|
|
*/
|
|
public function show(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$automation->load(['conditions', 'actions', 'logs' => fn ($q) => $q->latest()->limit(50)]);
|
|
|
|
return view('seller.crm.automations.show', compact('automation', 'business'));
|
|
}
|
|
|
|
/**
|
|
* Edit automation
|
|
*/
|
|
public function edit(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$automation->load(['conditions', 'actions']);
|
|
|
|
$triggers = CrmAutomation::TRIGGERS;
|
|
$operators = CrmAutomationCondition::OPERATORS;
|
|
$actionTypes = CrmAutomationAction::TYPES;
|
|
|
|
return view('seller.crm.automations.edit', compact('automation', 'triggers', 'operators', 'actionTypes', 'business'));
|
|
}
|
|
|
|
/**
|
|
* Update automation
|
|
*/
|
|
public function update(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'description' => 'nullable|string|max:1000',
|
|
'trigger_type' => 'required|string',
|
|
'trigger_config' => 'nullable|array',
|
|
'is_active' => 'boolean',
|
|
'stop_on_error' => 'boolean',
|
|
'max_runs_per_day' => 'nullable|integer|min:1',
|
|
'conditions' => 'nullable|array',
|
|
'conditions.*.field' => 'required|string',
|
|
'conditions.*.operator' => 'required|string',
|
|
'conditions.*.value' => 'nullable',
|
|
'conditions.*.logic_operator' => 'nullable|in:AND,OR',
|
|
'actions' => 'required|array|min:1',
|
|
'actions.*.type' => 'required|string',
|
|
'actions.*.config' => 'nullable|array',
|
|
]);
|
|
|
|
$automation->update([
|
|
'name' => $validated['name'],
|
|
'description' => $validated['description'],
|
|
'trigger_type' => $validated['trigger_type'],
|
|
'trigger_config' => $validated['trigger_config'] ?? [],
|
|
'is_active' => $validated['is_active'] ?? false,
|
|
'stop_on_error' => $validated['stop_on_error'] ?? true,
|
|
'max_runs_per_day' => $validated['max_runs_per_day'],
|
|
]);
|
|
|
|
// Clear error if reactivating
|
|
if ($validated['is_active'] ?? false) {
|
|
$automation->clearError();
|
|
}
|
|
|
|
// Replace conditions
|
|
$automation->conditions()->delete();
|
|
if (! empty($validated['conditions'])) {
|
|
foreach ($validated['conditions'] as $index => $condition) {
|
|
CrmAutomationCondition::create([
|
|
'automation_id' => $automation->id,
|
|
'field' => $condition['field'],
|
|
'operator' => $condition['operator'],
|
|
'value' => $condition['value'],
|
|
'logic_operator' => $condition['logic_operator'] ?? 'AND',
|
|
'order' => $index,
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Replace actions
|
|
$automation->actions()->delete();
|
|
foreach ($validated['actions'] as $index => $action) {
|
|
CrmAutomationAction::create([
|
|
'automation_id' => $automation->id,
|
|
'type' => $action['type'],
|
|
'config' => $action['config'] ?? [],
|
|
'order' => $index,
|
|
'is_active' => true,
|
|
]);
|
|
}
|
|
|
|
return redirect()->route('seller.business.crm.automations.show', [$business, $automation])
|
|
->with('success', 'Automation updated successfully.');
|
|
}
|
|
|
|
/**
|
|
* Toggle automation active status
|
|
*/
|
|
public function toggle(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$automation->update(['is_active' => ! $automation->is_active]);
|
|
|
|
if ($automation->is_active) {
|
|
$automation->clearError();
|
|
}
|
|
|
|
return back()->with('success', $automation->is_active ? 'Automation activated.' : 'Automation deactivated.');
|
|
}
|
|
|
|
/**
|
|
* Duplicate automation
|
|
*/
|
|
public function duplicate(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$copy = $automation->duplicate();
|
|
|
|
return redirect()->route('seller.business.crm.automations.edit', [$business, $copy])
|
|
->with('success', 'Automation duplicated. Make your changes and activate when ready.');
|
|
}
|
|
|
|
/**
|
|
* Delete automation
|
|
*/
|
|
public function destroy(Request $request, Business $business, CrmAutomation $automation)
|
|
{
|
|
if ($automation->business_id !== $business->id) {
|
|
abort(404);
|
|
}
|
|
|
|
$automation->delete();
|
|
|
|
return redirect()->route('seller.business.crm.automations.index', $business)
|
|
->with('success', 'Automation deleted.');
|
|
}
|
|
}
|