Files
hub/app/Http/Controllers/Seller/Accounting/DivisionAccountingController.php
kelly c7d6ee5e21 feat: multiple UI/UX improvements and case-insensitive search
- Refactor New Quote page to enterprise data-entry layout (2-column, dense)
- Add Payment Terms dropdown (COD, NET 15, NET 30, NET 60)
- Fix sidebar menu active states and route names
- Fix brand filter badge visibility on brands page
- Remove company_name references (use business instead)
- Polish Promotions page layout
- Fix double-click issue on sidebar menu collapse
- Make all searches case-insensitive (like -> ilike for PostgreSQL)
2025-12-14 15:36:00 -07:00

158 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Seller\Accounting;
use App\Http\Controllers\Controller;
use App\Models\Accounting\ApBill;
use App\Models\Accounting\ApVendor;
use App\Models\Accounting\ArInvoice;
use App\Models\Business;
use Illuminate\Http\Request;
use Illuminate\View\View;
/**
* Read-only accounting alias controllers for child businesses (divisions).
*
* Child businesses can view limited accounting data from their parent company.
* This provides visibility without granting write access to financial systems.
*
* Requirements:
* - Business must have parent_id (be a division)
* - User must have appropriate viewing permissions
*/
class DivisionAccountingController extends Controller
{
/**
* Display vendor list (read-only from parent company).
*
* GET /s/{business}/accounting/vendors
*/
public function vendorsIndex(Request $request, Business $business): View
{
$this->authorizeChildBusiness($business);
// Get parent's vendors
$parentId = $business->parent_id;
$query = ApVendor::where('business_id', $parentId)
->where('is_active', true);
// Search filter
if ($search = $request->get('search')) {
$query->where(function ($q) use ($search) {
$q->where('name', 'ilike', "%{$search}%")
->orWhere('code', 'ilike', "%{$search}%")
->orWhere('email', 'ilike', "%{$search}%");
});
}
$vendors = $query->orderBy('name')->paginate(30)->withQueryString();
return view('seller.accounting.vendors.index', [
'business' => $business,
'vendors' => $vendors,
'filters' => $request->only(['search']),
]);
}
/**
* Display AR snapshot (read-only summary for division).
*
* GET /s/{business}/accounting/ar-snapshot
*/
public function arSnapshot(Request $request, Business $business): View
{
$this->authorizeChildBusiness($business);
$parentId = $business->parent_id;
// Get AR summary stats (scoped to this division's invoices if possible,
// otherwise show high-level parent metrics)
$stats = [
'total_outstanding' => ArInvoice::where('business_id', $business->id)
->where('status', '!=', 'paid')
->sum('balance_due'),
'overdue_count' => ArInvoice::where('business_id', $business->id)
->where('status', '!=', 'paid')
->where('due_date', '<', now())
->count(),
'overdue_amount' => ArInvoice::where('business_id', $business->id)
->where('status', '!=', 'paid')
->where('due_date', '<', now())
->sum('balance_due'),
'current_month_billed' => ArInvoice::where('business_id', $business->id)
->whereMonth('invoice_date', now()->month)
->whereYear('invoice_date', now()->year)
->sum('total_amount'),
];
// Recent invoices for this division
$recentInvoices = ArInvoice::where('business_id', $business->id)
->with('customer')
->orderByDesc('invoice_date')
->limit(10)
->get();
return view('seller.accounting.ar-snapshot', [
'business' => $business,
'stats' => $stats,
'recentInvoices' => $recentInvoices,
]);
}
/**
* Display AP snapshot (read-only summary for division).
*
* GET /s/{business}/accounting/ap-snapshot
*/
public function apSnapshot(Request $request, Business $business): View
{
$this->authorizeChildBusiness($business);
$parentId = $business->parent_id;
// Get AP summary stats scoped to this division's bills
$stats = [
'total_outstanding' => ApBill::where('business_id', $business->id)
->whereIn('status', ['approved', 'partial'])
->sum('balance_due'),
'overdue_count' => ApBill::where('business_id', $business->id)
->whereIn('status', ['approved', 'partial'])
->where('due_date', '<', now())
->count(),
'overdue_amount' => ApBill::where('business_id', $business->id)
->whereIn('status', ['approved', 'partial'])
->where('due_date', '<', now())
->sum('balance_due'),
'pending_approval' => ApBill::where('business_id', $business->id)
->whereIn('status', ['draft', 'pending'])
->count(),
];
// Recent bills for this division
$recentBills = ApBill::where('business_id', $business->id)
->with('vendor')
->orderByDesc('bill_date')
->limit(10)
->get();
return view('seller.accounting.ap-snapshot', [
'business' => $business,
'stats' => $stats,
'recentBills' => $recentBills,
]);
}
/**
* Ensure this is a child business with parent_id.
*/
protected function authorizeChildBusiness(Business $business): void
{
if ($business->parent_id === null) {
abort(404, 'This feature is only available for division businesses.');
}
}
}