update marketing
All checks were successful
All checks were successful
This commit is contained in:
@@ -4,36 +4,42 @@
|
||||
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportBalanceSheet implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = request('custom_days') ? : 'today';
|
||||
$fromDate = request('from_date');
|
||||
$toDate = request('to_date');
|
||||
$perPage = request('per_page') ?? 20;
|
||||
|
||||
// PRODUCT
|
||||
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
|
||||
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
||||
->where('business_id', $businessId);
|
||||
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
|
||||
$products = $productQuery->get()
|
||||
->map(function ($item) {
|
||||
$item->source = 'product';
|
||||
return $item;
|
||||
});
|
||||
|
||||
// BANK
|
||||
$bankQuery = PaymentType::where('business_id', $businessId);
|
||||
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
|
||||
$banks = $bankQuery->get()
|
||||
->map(function ($item) {
|
||||
$item->source = 'bank';
|
||||
return $item;
|
||||
});
|
||||
|
||||
$asset_datas = $products->merge($banks);
|
||||
$asset_datas = $products->merge($banks)->take($perPage);
|
||||
|
||||
// TOTAL STOCK VALUE
|
||||
$total_stock_value = 0;
|
||||
foreach ($products as $product) {
|
||||
if (in_array($product->product_type, ['single', 'variant'])) {
|
||||
|
||||
@@ -3,17 +3,42 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Sale;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportBillWisePofit implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$profits = Sale::with('party:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$salesQuery = Sale::with('party:id,name')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
$salesQuery->when(request('search'), function ($query) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('lossProfit', 'like', '%' . request('search') . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$salesQuery->when(request('party_id'), function ($query, $partyId) {
|
||||
if ($partyId === 'Guest') {
|
||||
$query->whereNull('party_id');
|
||||
} else {
|
||||
$query->where('party_id', $partyId);
|
||||
}
|
||||
});
|
||||
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
|
||||
$profits = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::bill-wise-profits.excel-csv', compact('profits'));
|
||||
}
|
||||
|
||||
42
Modules/Business/App/Exports/ExportCashBalance.php
Normal file
42
Modules/Business/App/Exports/ExportCashBalance.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Models\Transaction;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportCashBalance implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$cash = Transaction::with('user:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($cash, $duration, 'date', request('from_date'), request('to_date'));
|
||||
|
||||
$cashes = $cash->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('date', 'like', '%' . request('search') . '%')
|
||||
->orWhere('platform', 'like', '%' . request('search'). '%')
|
||||
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
|
||||
->orWhere('amount', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('user', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::cashes.excel-csv', compact('cashes'));
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,17 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Transaction;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportCashFlowReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$cash_flows = Transaction::with([
|
||||
$query = Transaction::with([
|
||||
'paymentType:id,name',
|
||||
'sale:id,party_id',
|
||||
'sale.party:id,name',
|
||||
@@ -22,11 +25,44 @@ public function view(): View
|
||||
'dueCollect.party:id,name',
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('type', ['debit', 'credit'])
|
||||
->latest()
|
||||
->get();
|
||||
->whereIn('type', ['debit', 'credit']);
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($query, $duration, 'date', request('from_date'), request('to_date'));
|
||||
|
||||
// Search filter
|
||||
if (request('search')) {
|
||||
$query->where(function ($query) {
|
||||
$query->where('date', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
|
||||
->orWhere('platform', 'like', '%' . request('search') . '%')
|
||||
->orWhere('amount', 'like', '%' . request('search') . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('paymentType', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if (request('platform')) {
|
||||
$query->where('platform', request('platform'));
|
||||
}
|
||||
|
||||
// Paginate data
|
||||
$cash_flows = $query->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$firstDate = $cash_flows->first()?->date;
|
||||
|
||||
if ($firstDate) {
|
||||
$opening_balance = (clone $query)
|
||||
->whereDate('date', '<', $firstDate)
|
||||
->selectRaw("SUM(CASE WHEN type='credit' THEN amount ELSE 0 END) - SUM(CASE WHEN type='debit' THEN amount ELSE 0 END) as balance")
|
||||
->value('balance') ?? 0;
|
||||
} else {
|
||||
$opening_balance = 0;
|
||||
}
|
||||
|
||||
return view('business::cash-flow.excel-csv', compact('cash_flows', 'opening_balance'));
|
||||
}
|
||||
|
||||
@@ -11,12 +11,39 @@ class ExportComboProduct implements FromView
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$search = request('search');
|
||||
|
||||
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', 'combo')
|
||||
->withCount('combo_products as total_combo_products')
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
|
||||
->latest()
|
||||
->get();
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$combo_products->transform(function ($product) {
|
||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||
|
||||
@@ -11,12 +11,39 @@ class ExportComboProductReport implements FromView
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$search = request('search');
|
||||
|
||||
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', 'combo')
|
||||
->withCount('combo_products as total_combo_products')
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
|
||||
->latest()
|
||||
->get();
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$combo_products->transform(function ($product) {
|
||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||
|
||||
@@ -10,21 +10,58 @@ class ExportCurrentStock implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$query = Product::with('stocks')
|
||||
->where('product_type', '!=', 'combo')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
$businessId = auth()->user()->business_id;
|
||||
$alert_qty_filter = request('alert_qty');
|
||||
$search_term = request('search');
|
||||
$per_page = request('per_page', 20);
|
||||
|
||||
if (request('alert_qty')) {
|
||||
$products = $query->get()->filter(function ($product) {
|
||||
$totalStock = $product->stocks->sum('productStock');
|
||||
return $totalStock <= $product->alert_qty;
|
||||
// Base query
|
||||
$query = Product::with('stocks', 'category:id,categoryName')
|
||||
->where('product_type', '!=', 'combo')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
if ($search_term) {
|
||||
$query->where(function ($q) use ($search_term) {
|
||||
$q->where('productName', 'like', '%' . $search_term . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search_term . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
|
||||
->orWhereHas('category', function ($q) use ($search_term) {
|
||||
$q->where('categoryName', 'like', '%' . $search_term . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if ($alert_qty_filter) {
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->havingRaw('total_stock <= alert_qty')
|
||||
->latest()
|
||||
->limit($per_page)
|
||||
->get();
|
||||
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$products = $query->latest()->get();
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->latest()
|
||||
->limit($per_page)
|
||||
->get();
|
||||
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return view('business::stocks.excel-csv', [
|
||||
'products' => $products
|
||||
]);
|
||||
return view('business::stocks.excel-csv', compact('products', 'total_stock_qty', 'total_stock_value'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,27 @@ class ExportCurrentStockReport implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.stocks.excel-csv', [
|
||||
'stock_reports' => Product::with('stocks')
|
||||
$productsQuery = Product::with(['stocks' => function ($q) {
|
||||
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
|
||||
}])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', '!=', 'combo')
|
||||
->withSum('stocks', 'productStock')
|
||||
->where('product_type', '!=', 'combo');
|
||||
|
||||
if (request('search')) {
|
||||
$productsQuery->where(function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('stocks', function ($stock) {
|
||||
$stock->where('productSalePrice', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$stock_reports = $productsQuery
|
||||
->latest()
|
||||
->get()
|
||||
]);
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return view('business::reports.stocks.excel-csv', compact('stock_reports'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,20 @@ public function view(): View
|
||||
$customers = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->when(request('type'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('type', request('type'));
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->get();
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$totalAmount = $customers->sum(function ($customer) {
|
||||
return $customer->sales?->sum('totalAmount') ?? 0;
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Transaction;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportDayBookReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$day_books = Transaction::with([
|
||||
$query = Transaction::with([
|
||||
'paymentType:id,name',
|
||||
'sale:id,user_id,party_id,totalAmount',
|
||||
'sale.party:id,name',
|
||||
@@ -25,9 +28,34 @@ public function view(): View
|
||||
'dueCollect.user:id,name',
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('type', ['debit', 'credit'])
|
||||
->latest()
|
||||
->get();
|
||||
->whereIn('type', ['debit', 'credit']);
|
||||
|
||||
// Apply date filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($query, $duration, 'date', request('from_date'), request('to_date'));
|
||||
|
||||
// Search filter
|
||||
if (request('search')) {
|
||||
$query->where(function ($query) {
|
||||
$query->where('date', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
|
||||
->orWhere('platform', 'like', '%' . request('search') . '%')
|
||||
->orWhere('amount', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('paymentType', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if (request('platform')) {
|
||||
$query->where('platform', request('platform'));
|
||||
}
|
||||
|
||||
// Paginate data
|
||||
$day_books = $query->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::day-book.excel-csv', compact('day_books'));
|
||||
}
|
||||
|
||||
@@ -10,11 +10,33 @@ class ExportDiscountProduct implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode')
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
})
|
||||
->when(request('search'), function ($q) {
|
||||
$q->whereHas('product', function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productCode', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%')
|
||||
->orWhere('price', 'like', '%' . request('search') . '%')
|
||||
->orWhere('discount', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
->where('discount', '>', 0)
|
||||
->limit(request('per_page') ?? 20)
|
||||
->get();
|
||||
|
||||
return view('business::reports.discount-products.excel-csv', compact('discount_products'));
|
||||
|
||||
@@ -11,37 +11,56 @@ class ExportDue implements FromView
|
||||
public function view(): View
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
$activeBranch = $user->active_branch;
|
||||
$business_id = $user->business_id;
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
$query = Party::where('business_id', $business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q2) {
|
||||
$q2->where('type', 'like', '%' . request('search') . '%')
|
||||
->orWhere('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('credit_limit', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->when(request('type'), function ($q) {
|
||||
$q->where('type', request('type'));
|
||||
})
|
||||
->with('sales_dues')
|
||||
->latest();
|
||||
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->sales_dues
|
||||
$parties = $parties
|
||||
->transform(function ($customer) use ($activeBranch) {
|
||||
$party_due = $customer->sales_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $supplier;
|
||||
})->filter(fn($supplier) => $supplier->due > 0);
|
||||
|
||||
if ($customer->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $customer->opening_balance_type === 'due'
|
||||
? ($customer->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$customer->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
|
||||
$customer->due = $party_due;
|
||||
}
|
||||
return $customer;
|
||||
})
|
||||
->filter(fn($customer) => $customer->due > 0)
|
||||
->take(request('per_page') ?? 20)
|
||||
->values();
|
||||
} else {
|
||||
$parties = $parties
|
||||
->filter(fn($customer) => ($customer->due ?? 0) > 0)
|
||||
->take(request('per_page') ?? 20)
|
||||
->values();
|
||||
}
|
||||
|
||||
return view('business::reports.due.excel-csv', [
|
||||
'parties' => $parties
|
||||
]);
|
||||
return view('business::reports.due.excel-csv', compact('parties'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
65
Modules/Business/App/Exports/ExportDueList.php
Normal file
65
Modules/Business/App/Exports/ExportDueList.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Party;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportDueList implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$activeBranch = auth()->user()->active_branch;
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
->with(['purchases_dues', 'sales_dues']);
|
||||
|
||||
if (request('type')) {
|
||||
$query->where('type', request('type'));
|
||||
}
|
||||
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
|
||||
$query->where(function ($q) use ($search, $activeBranch) {
|
||||
$q->where('type', 'like', "%$search%")
|
||||
->orWhere('name', 'like', "%$search%")
|
||||
->orWhere('phone', 'like', "%$search%")
|
||||
->orWhere('email', 'like', "%$search%");
|
||||
|
||||
if (!$activeBranch) {
|
||||
$q->orWhere('due', 'like', "%$search%");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$parties = $query->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties = $parties->map(function ($party) use ($activeBranch) {
|
||||
$sale_dues = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->where('branch_id', $activeBranch->id)
|
||||
: $party->sales_dues->where('branch_id', $activeBranch->id);
|
||||
|
||||
$party_due = $sale_dues->sum('dueAmount');
|
||||
|
||||
if ($party->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
|
||||
$party->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$party->due = $party_due;
|
||||
}
|
||||
|
||||
return $party;
|
||||
})->filter(fn($p) => $p->due > 0)->values();
|
||||
} else {
|
||||
$parties = $parties->filter(fn($p) => $p->due > 0)->values();
|
||||
}
|
||||
|
||||
return view('business::dues.excel-csv', [
|
||||
'parties' => $parties
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,48 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Expense;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportExpense implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.expense.excel-csv', [
|
||||
'expense_reports' => Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
|
||||
]);
|
||||
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
$expenseQuery->when(request('branch_id'), function ($q) {
|
||||
$q->where('branch_id', request('branch_id'));
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', request('from_date'), request('to_date'));
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$expenseQuery->where(function ($query) {
|
||||
$query->where('expanseFor', 'like', '%' . request('search') . '%')
|
||||
->orWhere('paymentType', 'like', '%' . request('search') . '%')
|
||||
->orWhere('referenceNo', 'like', '%' . request('search') . '%')
|
||||
->orWhere('amount', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('category', function ($q) {
|
||||
$q->where('categoryName', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$expense_reports = $expenseQuery->latest()->limit(request('per_page' ?? 20))->get();
|
||||
|
||||
return view('business::reports.expense.excel-csv', compact('expense_reports'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,16 +10,35 @@ class ExportExpiredProduct implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$expired_products = Product::with('stocks', 'unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')
|
||||
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->whereHas('stocks', function ($query) {
|
||||
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
|
||||
$query->whereDate('expire_date', '<', today())
|
||||
->where('productStock', '>', 0);
|
||||
})
|
||||
->latest()->get();
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('type', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productName', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productCode', 'like', '%' . request('search') . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('unit', function ($q) {
|
||||
$q->where('unitName', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('brand', function ($q) {
|
||||
$q->where('brandName', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('category', function ($q) {
|
||||
$q->where('categoryName', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::expired-products.excel-csv', [
|
||||
'expired_products' => $expired_products
|
||||
]);
|
||||
return view('business::expired-products.excel-csv', compact('expired_products'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,22 +3,52 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportExpiredProductReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.expired-products.excel-csv', [
|
||||
'expired_products' => Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
|
||||
$businessId = auth()->user()->business_id;
|
||||
$expiredProductsQuery = Product::with(['unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks'])
|
||||
->withSum('stocks', 'productStock')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('stocks', function ($query) {
|
||||
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
|
||||
$query->whereDate('expire_date', '<=', today())->where('productStock', '>', 0);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$expiredProductsQuery->whereHas('stocks', function ($q) use ($duration) {
|
||||
$this->applyDateFilter($q, $duration, 'expire_date', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
$expiredProductsQuery->where(function ($query) use ($search) {
|
||||
$query->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $search . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->latest()
|
||||
->get()
|
||||
]);
|
||||
->orWhereHas('brand', function ($q) use ($search) {
|
||||
$q->where('brandName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$expired_products = $expiredProductsQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.expired-products.excel-csv', compact('expired_products'));
|
||||
}
|
||||
}
|
||||
|
||||
28
Modules/Business/App/Exports/ExportGuestDue.php
Normal file
28
Modules/Business/App/Exports/ExportGuestDue.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Sale;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportGuestDue implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
|
||||
->with('dueCollect')
|
||||
->whereNull('party_id')
|
||||
->where('dueAmount', '>', 0)
|
||||
->when(request('search'), function ($query) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orwhere('dueAmount', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::walk-dues.excel-csv', compact('walk_in_customers'));
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,44 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Income;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportIncome implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.income.excel-csv', [
|
||||
'income_reports' => Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
|
||||
]);
|
||||
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
// Branch filter
|
||||
if (request('branch_id')) {
|
||||
$incomeQuery->where('branch_id', request('branch_id'));
|
||||
}
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', request('from_date'), request('to_date'));
|
||||
|
||||
// Search filter
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
$incomeQuery->where(function ($query) use ($search) {
|
||||
$query->where('incomeFor', 'like', '%' . $search . '%')
|
||||
->orWhere('paymentType', 'like', '%' . $search . '%')
|
||||
->orWhere('amount', 'like', '%' . $search . '%')
|
||||
->orWhere('referenceNo', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', '%' . $search . '%'))
|
||||
->orWhereHas('payment_type', fn($q) => $q->where('name', 'like', '%' . $search . '%'))
|
||||
->orWhereHas('branch', fn($q) => $q->where('name', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$income_reports = $incomeQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.income.excel-csv', compact('income_reports'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,98 +2,146 @@
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportLossProfitHistory implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
$perPage = request('per_page') ?? 20;
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
// SALES
|
||||
$dailySales = DB::table('sales')
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
|
||||
$salesQuery = DB::table('sales')
|
||||
->select(
|
||||
DB::raw('"saleDate"::date as date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END as profit_type
|
||||
"),
|
||||
DB::raw('SUM(actual_total_amount) as total_sales'),
|
||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"saleDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(
|
||||
DB::raw('"saleDate"::date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END
|
||||
")
|
||||
);
|
||||
|
||||
$sale_datas = $dailySales->map(fn($sale) => (object)[
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
|
||||
$dailySales = $salesQuery->limit($perPage)->get();
|
||||
|
||||
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||
'type' => 'Sale',
|
||||
'date' => $sale->date,
|
||||
'profit_type' => $sale->profit_type,
|
||||
'total_sales' => $sale->total_sales,
|
||||
'total_incomes' => $sale->total_sale_income,
|
||||
]);
|
||||
|
||||
// INCOME
|
||||
$dailyIncomes = DB::table('incomes')
|
||||
$incomeQuery = DB::table('incomes')
|
||||
->select(
|
||||
DB::raw('"incomeDate"::date as date'),
|
||||
DB::raw('SUM(amount) as total_incomes')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"incomeDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"incomeDate"::date'));
|
||||
|
||||
$income_datas = $dailyIncomes->map(fn($income) => (object)[
|
||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', request('from_date'), request('to_date'));
|
||||
$dailyIncomes = $incomeQuery->limit($perPage)->get();
|
||||
|
||||
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
|
||||
'type' => 'Income',
|
||||
'date' => $income->date,
|
||||
'total_incomes' => $income->total_incomes,
|
||||
]);
|
||||
|
||||
// MERGE SALE + INCOME
|
||||
$mergedIncomeSaleData = collect();
|
||||
$allDates = $dailySales->pluck('date')->merge($dailyIncomes->pluck('date'))->unique()->sort();
|
||||
$allDates = $dailySales->pluck('date')
|
||||
->merge($dailyIncomes->pluck('date'))
|
||||
->unique()
|
||||
->sort();
|
||||
|
||||
foreach ($allDates as $date) {
|
||||
|
||||
if ($income = $income_datas->firstWhere('date', $date)) {
|
||||
$mergedIncomeSaleData->push($income);
|
||||
}
|
||||
if ($sale = $sale_datas->firstWhere('date', $date)) {
|
||||
|
||||
// multiple sale rows handle
|
||||
$salesOfDate = $sale_datas->where('date', $date);
|
||||
|
||||
foreach ($salesOfDate as $sale) {
|
||||
$mergedIncomeSaleData->push($sale);
|
||||
}
|
||||
}
|
||||
|
||||
// PAYROLL
|
||||
$dailyPayrolls = collect();
|
||||
|
||||
if (moduleCheck('HrmAddon')) {
|
||||
$dailyPayrolls = DB::table('payrolls')
|
||||
$payrollQuery = DB::table('payrolls')
|
||||
->select(
|
||||
DB::raw('"date"::date as date'),
|
||||
DB::raw('SUM(amount) as total_payrolls')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"date"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"date"::date'));
|
||||
|
||||
$this->applyDateFilter($payrollQuery, $duration, 'date', request('from_date'), request('to_date'));
|
||||
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||
}
|
||||
|
||||
// EXPENSES
|
||||
$dailyExpenses = DB::table('expenses')
|
||||
$expenseQuery = DB::table('expenses')
|
||||
->select(
|
||||
DB::raw('"expenseDate"::date as date'),
|
||||
DB::raw('SUM(amount) as total_expenses_only')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"expenseDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"expenseDate"::date'));
|
||||
|
||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', request('from_date'), request('to_date'));
|
||||
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||
|
||||
$mergedExpenseData = collect();
|
||||
$allExpenseDates = $dailyExpenses->pluck('date')->merge($dailyPayrolls->pluck('date'))->unique()->sort();
|
||||
$allExpenseDates = $dailyExpenses->pluck('date')
|
||||
->merge($dailyPayrolls->pluck('date'))
|
||||
->unique()
|
||||
->sort();
|
||||
|
||||
foreach ($allExpenseDates as $date) {
|
||||
|
||||
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
||||
$mergedExpenseData->push((object)[
|
||||
'type' => 'Expense',
|
||||
@@ -101,6 +149,7 @@ public function view(): View
|
||||
'total_expenses' => $expense->total_expenses_only,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
||||
$mergedExpenseData->push((object)[
|
||||
'type' => 'Payroll',
|
||||
@@ -110,9 +159,9 @@ public function view(): View
|
||||
}
|
||||
}
|
||||
|
||||
// SUMMARY
|
||||
$grossSaleProfit = $sale_datas->sum('total_sales');
|
||||
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
||||
|
||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||
|
||||
|
||||
@@ -13,7 +13,13 @@ public function view(): View
|
||||
$parties = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when(request('search'), function ($query) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)
|
||||
->get();
|
||||
|
||||
return view('business::party-reports.loss-profit.excel-csv', compact('parties'));
|
||||
|
||||
@@ -8,10 +8,61 @@
|
||||
|
||||
class ExportProduct implements FromView
|
||||
{
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')->where('business_id', auth()->user()->business_id)->withSum('stocks as total_stock', 'productStock')->latest()->get();
|
||||
$user = auth()->user();
|
||||
$search = request('search');
|
||||
|
||||
$products = Product::query()
|
||||
->where('business_id', $user->business_id)
|
||||
->with([
|
||||
'stocks',
|
||||
'unit:id,unitName',
|
||||
'brand:id,brandName',
|
||||
'category:id,categoryName',
|
||||
'warehouse:id,name',
|
||||
'rack:id,name',
|
||||
'shelf:id,name',
|
||||
'combo_products.stock.product:id,productName'
|
||||
])
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->where(function ($query) {
|
||||
$query->where('product_type', '!=', 'combo')
|
||||
->orWhere(function ($q) {
|
||||
$q->where('product_type', 'combo')
|
||||
->whereHas('combo_products');
|
||||
});
|
||||
})
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', "%{$search}%")
|
||||
->orWhere('productCode', 'like', "%{$search}%")
|
||||
->orWhere('hsn_code', 'like', "%{$search}%")
|
||||
->orWhere('productPurchasePrice', 'like', "%{$search}%")
|
||||
->orWhere('productSalePrice', 'like', "%{$search}%")
|
||||
->orWhere('product_type', 'like', "%{$search}%")
|
||||
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
||||
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
|
||||
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)
|
||||
->get();
|
||||
|
||||
$products = $products->transform(function ($product) {
|
||||
if ($product->product_type === 'combo') {
|
||||
$product->total_stock = $product->combo_products->sum(
|
||||
fn ($combo) => $combo->stock?->productStock ?? 0
|
||||
);
|
||||
|
||||
$product->total_cost = $product->combo_products->sum(
|
||||
fn ($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
return $product;
|
||||
});
|
||||
|
||||
return view('business::products.excel-csv', [
|
||||
'products' => $products
|
||||
|
||||
@@ -11,23 +11,35 @@ class ExportProductLossProfit implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
|
||||
$user = auth()->user();
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
|
||||
$product_lossProfits = SaleDetails::with('product:id,productName,productCode')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
$baseQuery = SaleDetails::query()
|
||||
->whereHas(
|
||||
'product',
|
||||
fn($q) =>
|
||||
$q->where('business_id', $user->business_id)
|
||||
)
|
||||
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', fn($q) => $q->where('branch_id', $branchId));
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
||||
$sale->where('branch_id', $branchId);
|
||||
->when(request('search'), function ($q) {
|
||||
$q->whereHas('product', function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productCode', 'like', '%' . request('search') . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
$product_lossProfits = $baseQuery
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->select(
|
||||
'product_id',
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) as profit'),
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) as loss')
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) AS loss')
|
||||
)
|
||||
->groupBy('product_id')
|
||||
->limit(request('per_page') ?? 20)
|
||||
->get();
|
||||
|
||||
return view('business::reports.product-loss-profit.excel-csv', compact('product_lossProfits'));
|
||||
|
||||
@@ -3,29 +3,54 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductPurchaseHistoryDetailReport implements FromView
|
||||
{
|
||||
protected $id;
|
||||
use DateFilterTrait;
|
||||
|
||||
public function __construct($id)
|
||||
protected string $id;
|
||||
|
||||
public function __construct(string $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
|
||||
$product = Product::select('id', 'business_id', 'productName')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->findOrFail($this->id);
|
||||
|
||||
$purchaseDetailsQuery = $product->purchaseDetails()
|
||||
->with('purchase:id,invoiceNumber,purchaseDate')
|
||||
->whereHas('purchase', function ($purchase) use ($duration) {
|
||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', request('from_date'), request('to_date'));
|
||||
})
|
||||
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
|
||||
|
||||
$purchaseDetails = $purchaseDetailsQuery->get();
|
||||
$purchaseDetailsQuery->when(request('search'), function ($q) {
|
||||
$search = request('search');
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productPurchasePrice', 'like', "%{$search}%")
|
||||
->orWhere('quantities', 'like', "%{$search}%")
|
||||
->orWhereHas('purchase', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('purchaseDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('purchase.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
$purchaseDetails = $purchaseDetailsQuery->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::product-purchase-history-report.excel-csv-detail', compact('product', 'purchaseDetails'));
|
||||
}
|
||||
|
||||
@@ -3,17 +3,30 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductPurchaseHistoryReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
|
||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
||||
$products = $productQuery->get();
|
||||
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('purchaseDetails.purchase', function ($purchase) use ($duration) {
|
||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
$productQuery->when(request('search'), function ($q) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
|
||||
$products = $productQuery->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$total_purchase_qty = $products->sum(function ($product) {
|
||||
return $product->purchaseDetails->sum('quantities');
|
||||
|
||||
@@ -2,21 +2,44 @@
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\PurchaseDetails;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductPurchaseReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$product_purchases = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
$query = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
->whereHas('purchase', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$query->whereHas('purchase', function ($q) use ($duration) {
|
||||
$this->applyDateFilter($q, $duration, 'purchaseDate', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
$query->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->whereHas('product', function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->get();
|
||||
->orWhereHas('purchase', function ($q) {
|
||||
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhere('purchaseDate', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('purchase.party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$product_purchases = $query->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.product-purchase.excel-csv', compact('product_purchases'));
|
||||
}
|
||||
|
||||
@@ -3,29 +3,53 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductSaleHistoryDetailReport implements FromView
|
||||
{
|
||||
protected $id;
|
||||
use DateFilterTrait;
|
||||
|
||||
public function __construct($id)
|
||||
protected string $id;
|
||||
|
||||
public function __construct(string $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$product = Product::select('id', 'business_id', 'productName')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->findOrFail($this->id);
|
||||
|
||||
$saleDetailsQuery = $product->saleDetails()
|
||||
->whereHas('sale', function ($sale) use ($duration) {
|
||||
$this->applyDateFilter($sale, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
})
|
||||
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
|
||||
|
||||
$saleDetails = $saleDetailsQuery->get();
|
||||
$saleDetailsQuery->when(request('search'), function ($q) {
|
||||
$search = request('search');
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('price', 'like', "%{$search}%")
|
||||
->orWhere('quantities', 'like', "%{$search}%")
|
||||
->orWhereHas('sale', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('saleDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
$saleDetails = $saleDetailsQuery->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::product-sale-history-report.excel-csv-detail', compact('product', 'saleDetails'));
|
||||
}
|
||||
|
||||
@@ -3,17 +3,30 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductSaleHistoryReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
|
||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
||||
$products = $productQuery->get();
|
||||
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('saleDetails.sale', function ($sale) use ($duration) {
|
||||
$this->applyDateFilter($sale, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
$productQuery->when(request('search'), function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
|
||||
$products = $productQuery->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$total_single_sale_price = $products->sum(function ($product) {
|
||||
return $product->saleDetails->sum('price');
|
||||
|
||||
@@ -3,18 +3,45 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Sale;
|
||||
use App\Models\SaleDetails;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportProductSaleReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$product_sales = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||
->whereHas('sale', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$query->whereHas('sale', function ($q) use ($duration) {
|
||||
$this->applyDateFilter($q, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
$query->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->whereHas('product', function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('sale', function ($q) {
|
||||
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhere('saleDate', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$product_sales = $query->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.product-sale.excel-csv', compact('product_sales'));
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Purchase;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportPurchaseReturn implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$purchases = Purchase::with([
|
||||
$purchasesQuery = Purchase::with([
|
||||
'user:id,name',
|
||||
'branch:id,name',
|
||||
'party:id,name,email,phone,type',
|
||||
@@ -22,9 +25,32 @@ public function view(): View
|
||||
}
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereHas('purchaseReturns')
|
||||
->latest()
|
||||
->get();
|
||||
->whereHas('purchaseReturns');
|
||||
|
||||
$purchasesQuery->when(request('branch_id'), function ($q) {
|
||||
$q->where('branch_id', request('branch_id'));
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$purchasesQuery->where(function ($query) {
|
||||
$query->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$purchases = $purchasesQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.purchase-return.excel-csv', compact('purchases'));
|
||||
}
|
||||
|
||||
@@ -3,16 +3,46 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Sale;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportSaleReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
$salesQuery->when(request('branch_id'), function ($q) {
|
||||
$q->where('branch_id', request('branch_id'));
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$salesQuery->where(function ($query) {
|
||||
$query->where('paymentType', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$sales = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
|
||||
return view('business::reports.sales.excel', compact('sales'));
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Sale;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportSalesReturn implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$sales = Sale::with([
|
||||
$salesQuery = Sale::with([
|
||||
'user:id,name',
|
||||
'party:id,name',
|
||||
'branch:id,name',
|
||||
@@ -23,9 +26,30 @@ public function view(): View
|
||||
}
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereHas('saleReturns')
|
||||
->latest()
|
||||
->get();
|
||||
->when(request('branch_id'), function ($q) {
|
||||
$q->where('branch_id', request('branch_id'));
|
||||
})->whereHas('saleReturns');
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$salesQuery->whereHas('saleReturns', function ($query) use ($duration) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', request('from_date'), request('to_date'));
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$salesQuery->where(function ($query) {
|
||||
$query->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$sales = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.sales-return.excel-csv', compact('sales'));
|
||||
}
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Party;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ExportSingleCustomerLedger implements FromView
|
||||
{
|
||||
public $ledger;
|
||||
public $party;
|
||||
public Collection $ledger;
|
||||
public Party $party;
|
||||
|
||||
public function __construct($ledger, $party)
|
||||
public function __construct(Collection $ledger, Party $party)
|
||||
{
|
||||
$this->ledger = $ledger;
|
||||
$this->party = $party;
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Party;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ExportSingleSupplierLedger implements FromView
|
||||
{
|
||||
public $ledger;
|
||||
public $party;
|
||||
public Collection $ledger;
|
||||
public Party $party;
|
||||
|
||||
public function __construct($ledger, $party)
|
||||
public function __construct(Collection $ledger, Party $party)
|
||||
{
|
||||
$this->ledger = $ledger;
|
||||
$this->party = $party;
|
||||
|
||||
@@ -3,15 +3,44 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\PlanSubscribe;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportSubscription implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.subscription-reports.excel-csv', [
|
||||
'subscribers' => PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)->latest()->get()
|
||||
]);
|
||||
$subscriberQuery = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id);
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($subscriberQuery, $duration, 'created_at', request('from_date'), request('to_date'));
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
$subscriberQuery->where(function ($query) use ($search) {
|
||||
$query->where('duration', 'like', '%' . $search . '%')
|
||||
->orWhereHas('plan', function ($q) use ($search) {
|
||||
$q->where('subscriptionName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('gateway', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('business', function ($q) use ($search) {
|
||||
$q->where('companyName', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$subscribers = $subscriberQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::reports.subscription-reports.excel-csv', compact('subscribers'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,31 +16,48 @@ public function view(): View
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
->where('type', 'Supplier')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q2) {
|
||||
$q2->where('type', 'like', '%' . request('search') . '%')
|
||||
->orWhere('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('credit_limit', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->with('purchases_dues')
|
||||
->latest();
|
||||
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->purchases_dues
|
||||
$parties = $parties
|
||||
->transform(function ($supplier) use ($activeBranch) {
|
||||
$party_due = $supplier->purchases_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $supplier;
|
||||
})->filter(fn($supplier) => $supplier->due > 0);
|
||||
|
||||
if ($supplier->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $supplier->opening_balance_type === 'due'
|
||||
? ($supplier->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$supplier->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$supplier->due = $party_due;
|
||||
}
|
||||
|
||||
return view('business::reports.supplier-due.excel-csv', [
|
||||
'parties' => $parties
|
||||
]);
|
||||
return $supplier;
|
||||
})
|
||||
->filter(fn($supplier) => $supplier->due > 0)
|
||||
->take(request('per_page') ?? 20)
|
||||
->values();
|
||||
} else {
|
||||
$parties = $parties
|
||||
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
|
||||
->take(request('per_page') ?? 20)
|
||||
->values();
|
||||
}
|
||||
|
||||
return view('business::reports.supplier-due.excel-csv', compact('parties'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,15 @@ public function view(): View
|
||||
$suppliers = Party::with('purchases')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '=', 'Supplier')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->get();
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
$totalAmount = $suppliers->sum(function ($customer) {
|
||||
return $customer->purchases?->sum('totalAmount') ?? 0;
|
||||
|
||||
211
Modules/Business/App/Exports/ExportTaxReport.php
Normal file
211
Modules/Business/App/Exports/ExportTaxReport.php
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Purchase;
|
||||
use App\Models\PurchaseReturnDetail;
|
||||
use App\Models\Sale;
|
||||
use App\Models\SaleDetails;
|
||||
use App\Models\SaleReturnDetails;
|
||||
use App\Models\Vat;
|
||||
use App\Models\VatTransaction;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportTaxReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$type = request('type') ?? 'sales';
|
||||
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
|
||||
// SALES QUERY
|
||||
$salesQuery = Sale::with('party', 'payment_type', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
|
||||
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
$salesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$salesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleDetails::class)
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$salesReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
->join('sale_return_details', 'sale_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sale_details', 'sale_details.id', '=', 'sale_return_details.sale_detail_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$saleVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\SaleDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration) {
|
||||
$query->select('sale_details.id')
|
||||
->from('sale_details')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_days' && request('from_date') && request('to_date')) {
|
||||
$query->whereBetween('sales.saleDate', [request('from_date'), request('to_date')]);
|
||||
}
|
||||
})
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('sale_details.sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('sale_details.sale_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('sale_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$saleReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
|
||||
->join('sale_return_details','sale_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('sale_details','sale_details.id','=','sale_return_details.sale_detail_id')
|
||||
->join('sales','sales.id','=','sale_details.sale_id')
|
||||
|
||||
->selectRaw('sales.id as sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('sales.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$saleReturnVatRowMap = $saleReturnVatRows
|
||||
->groupBy('sale_id')
|
||||
->map(fn($rows)=>$rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
// PURCHASE QUERY
|
||||
$purchasesQuery = Purchase::with('party', 'payment_type', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', request('from_date'), request('to_date'));
|
||||
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
$purchasesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$purchasesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
|
||||
$purchaseReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
->join('purchase_return_details', 'purchase_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'purchase_return_details.purchase_detail_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$purchaseVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration) {
|
||||
$query->select('purchase_details.id')
|
||||
->from('purchase_details')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_date' && request('from_date') && request('to_date')) {
|
||||
$query->whereBetween('purchases.purchaseDate', [request('from_date'), request('to_date')]);
|
||||
}
|
||||
})
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('purchase_details.purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('purchase_details.purchase_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('purchase_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$purchaseReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
|
||||
->join('purchase_return_details','purchase_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('purchase_details','purchase_details.id','=','purchase_return_details.purchase_detail_id')
|
||||
->join('purchases','purchases.id','=','purchase_details.purchase_id')
|
||||
|
||||
->selectRaw('purchases.id as purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('purchases.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$purchaseReturnVatRowMap = $purchaseReturnVatRows
|
||||
->groupBy('purchase_id')
|
||||
->map(fn($rows) => $rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
// TAB CONTROL
|
||||
$sales = collect();
|
||||
$purchases = collect();
|
||||
|
||||
$limit = request('per_page') ?? 20;
|
||||
|
||||
if ($type === 'sales') {
|
||||
$sales = $salesQuery->latest()->limit($limit)->get();
|
||||
}
|
||||
|
||||
if ($type === 'purchases') {
|
||||
$purchases = $purchasesQuery->latest()->limit($limit)->get();
|
||||
}
|
||||
|
||||
$vats = Vat::where('business_id', $businessId)->get();
|
||||
|
||||
return view('business::reports.vats.excel-csv',
|
||||
compact(
|
||||
'sales',
|
||||
'salesVatTotals',
|
||||
'salesReturnVatTotals',
|
||||
'saleVatRowMap',
|
||||
'saleReturnVatRowMap',
|
||||
'purchases',
|
||||
'purchasesVatTotals',
|
||||
'purchaseReturnVatTotals',
|
||||
'purchaseVatRowMap',
|
||||
'purchaseReturnVatRowMap',
|
||||
'vats',
|
||||
'type'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,23 @@ public function view(): View
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->whereHas('sales')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('email', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->withCount('sales')
|
||||
->withSum('sales', 'totalAmount')
|
||||
->orderByDesc('sales_count')
|
||||
->orderByDesc('sales_sum_total_amount')
|
||||
->when(request('type'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('type', request('type'));
|
||||
});
|
||||
})
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
|
||||
@@ -11,25 +11,38 @@ class ExportTopProduct implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
|
||||
$top_products = SaleDetails::with('product:id,productName,productCode')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$top_products = SaleDetails::query()
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})
|
||||
->when(request('search'), function ($q) {
|
||||
$q->whereHas('product', function ($q) {
|
||||
$q->where('productName', 'like', '%' . request('search') . '%')
|
||||
->orWhere('productCode', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
||||
$sale->where('branch_id', $branchId);
|
||||
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
->select(
|
||||
'product_id',
|
||||
DB::raw('SUM(quantities) as total_sold_qty'),
|
||||
DB::raw('SUM(price * quantities) as total_sale_amount')
|
||||
DB::raw('SUM((price - discount) * quantities) as total_sale_amount')
|
||||
)
|
||||
->groupBy('product_id')
|
||||
->orderByDesc('total_sold_qty')
|
||||
->take(5)
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
return view('business::reports.top-products.excel-csv', compact('top_products'));
|
||||
|
||||
@@ -14,6 +14,14 @@ public function view(): View
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '=', 'Supplier')
|
||||
->whereHas('purchases')
|
||||
->when(request('search'), function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%')
|
||||
->orWhere('phone', 'like', '%' . request('search') . '%')
|
||||
->orWhere('email', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->withCount('purchases')
|
||||
->withSum('purchases', 'totalAmount')
|
||||
->orderByDesc('purchases_count')
|
||||
|
||||
@@ -3,15 +3,49 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\DueCollect;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportTransaction implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::reports.transaction-history.excel-csv', [
|
||||
'transactions' => DueCollect::where('business_id', auth()->user()->business_id)->with('party:id,name,type', 'payment_type:id,name', 'transactions')->latest()->get()
|
||||
]);
|
||||
$businessId = auth()->user()->business_id;
|
||||
$transactionsQuery = DueCollect::with('party:id,name,type', 'payment_type:id,name', 'transactions')->where('business_id', $businessId);
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($transactionsQuery, $duration, 'paymentDate', request('from_date'), request('to_date'));
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$transactionsQuery->where(function ($query) {
|
||||
$query->where('paymentType', 'like', '%' . request('search') . '%')
|
||||
->orWhere('totalDue', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhere('payDueAmount', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (request('type')) {
|
||||
$transactionsQuery->whereHas('party', function ($q) {
|
||||
$q->where(function ($q) {
|
||||
$q->where('type', request('type'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$transactions = $transactionsQuery->latest()->limit(request('per_page'))->get();
|
||||
|
||||
return view('business::reports.transaction-history.excel-csv', compact('transactions'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,82 @@
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Transaction;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class ExportTransactionReport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$transactions = Transaction::with('paymentType')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$businessId = auth()->user()->business_id;
|
||||
$transactionsQuery = Transaction::with('paymentType')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($transactionsQuery, $duration, 'date', request('from_date'), request('to_date'));
|
||||
|
||||
// Search filter
|
||||
if (request('search')) {
|
||||
$transactionsQuery->where(function ($query) {
|
||||
$query->where('amount', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
|
||||
->orWhere('platform', 'like', '%' . request('search') . '%')
|
||||
->orWhere('type', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if (request('platform')) {
|
||||
$transactionsQuery->where('platform', request('platform'));
|
||||
}
|
||||
|
||||
// Party Filter
|
||||
if (request('party_id')) {
|
||||
|
||||
$transactionsQuery->where(function ($q) {
|
||||
|
||||
$q->where(function ($saleQ) {
|
||||
$saleQ->where('platform', 'sale')
|
||||
->whereHas('sale', function ($s) {
|
||||
$s->where('party_id', request('party_id'));
|
||||
});
|
||||
});
|
||||
|
||||
$q->where(function ($saleRtnQ) {
|
||||
$saleRtnQ->where('platform', 'sale_return')
|
||||
->whereHas('saleReturn.sale', function ($s) {
|
||||
$s->where('party_id', request('party_id'));
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($purQ) {
|
||||
$purQ->where('platform', 'purchase')
|
||||
->whereHas('purchase', function ($p) {
|
||||
$p->where('party_id', request('party_id'));
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($purRtnQ) {
|
||||
$purRtnQ->where('platform', 'purchase_return')
|
||||
->whereHas('purchaseReturn.purchase', function ($p) {
|
||||
$p->where('party_id', request('party_id'));
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($dueQ) {
|
||||
$dueQ->where('platform', 'due_collect')
|
||||
->whereHas('dueCollect', function ($d) {
|
||||
$d->where('party_id', request('party_id'));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$transactions = $transactionsQuery->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::transactions.excel-csv', compact('transactions'));
|
||||
}
|
||||
|
||||
@@ -10,8 +10,45 @@ class ExportTransfer implements FromView
|
||||
{
|
||||
public function view(): View
|
||||
{
|
||||
return view('business::transfers.excel-csv', [
|
||||
'transfers' => Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])->where('business_id', auth()->user()->business_id)->latest()->get()
|
||||
]);
|
||||
$user = auth()->user();
|
||||
$activeBranchId = $user->active_branch_id;
|
||||
|
||||
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
|
||||
->where('business_id', $user->business_id)
|
||||
->when($activeBranchId, function ($q) use ($activeBranchId) {
|
||||
$q->where(function ($query) use ($activeBranchId) {
|
||||
$query->where('from_branch_id', $activeBranchId)
|
||||
->orWhere('to_branch_id', $activeBranchId);
|
||||
});
|
||||
})
|
||||
->when(request('branch_id') && !$activeBranchId, function ($q) {
|
||||
$q->where(function ($query) {
|
||||
$query->where('from_branch_id', request('branch_id'))->orWhere('to_branch_id', request('branch_id'));
|
||||
});
|
||||
})
|
||||
->when(request('search'), function ($q) {
|
||||
$search = request('search');
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('note', 'like', '%' . $search . '%')
|
||||
->orWhere('status', 'like', '%' . $search . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . $search . '%')
|
||||
->orWhereHas('fromWarehouse', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('toWarehouse', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('toBranch', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('fromBranch', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return view('business::transfers.excel-csv', compact('transfers'));
|
||||
}
|
||||
}
|
||||
|
||||
50
Modules/Business/App/Exports/PurchaseExport.php
Normal file
50
Modules/Business/App/Exports/PurchaseExport.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Exports;
|
||||
|
||||
use App\Models\Purchase;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
|
||||
class PurchaseExport implements FromView
|
||||
{
|
||||
use DateFilterTrait;
|
||||
|
||||
public function view(): View
|
||||
{
|
||||
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
$purchasesQuery->when(request('branch_id'), function ($q) {
|
||||
$q->where('branch_id', request('branch_id'));
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = request('custom_days') ?: 'today';
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', request('from_date'), request('to_date'));
|
||||
|
||||
// Search Filter
|
||||
if (request('search')) {
|
||||
$purchasesQuery->where(function ($query) {
|
||||
$query->where('paymentType', 'like', '%' . request('search') . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orWhereHas('party', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) {
|
||||
$q->where('name', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
|
||||
return view('business::reports.purchase.excel-csv', compact('purchases'));
|
||||
}
|
||||
|
||||
}
|
||||
0
Modules/Business/App/Http/Controllers/.gitkeep
Normal file
0
Modules/Business/App/Http/Controllers/.gitkeep
Normal file
@@ -100,28 +100,33 @@ public function exportCsv()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ? : 'today';
|
||||
$fromDate = $request->from_date;
|
||||
$toDate = $request->to_date;
|
||||
$perPage = $request->per_page ?? 20;
|
||||
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
// PRODUCT
|
||||
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
|
||||
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
||||
->where('business_id', $businessId);
|
||||
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
|
||||
$products = $productQuery->get()
|
||||
->map(function ($item) {
|
||||
$item->source = 'product';
|
||||
return $item;
|
||||
});
|
||||
|
||||
// BANK
|
||||
$bankQuery = PaymentType::where('business_id', $businessId);
|
||||
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
|
||||
$banks = $bankQuery->get()
|
||||
->map(function ($item) {
|
||||
$item->source = 'bank';
|
||||
return $item;
|
||||
});
|
||||
|
||||
$asset_datas = $products->merge($banks);
|
||||
$asset_datas = $products->merge($banks)->take($perPage);
|
||||
|
||||
// TOTAL STOCK VALUE
|
||||
$total_stock_value = 0;
|
||||
foreach ($products as $product) {
|
||||
if (in_array($product->product_type, ['single', 'variant'])) {
|
||||
@@ -143,6 +148,6 @@ public function exportPdf(Request $request)
|
||||
$totalBankBalance = $banks->sum('balance');
|
||||
$total_asset = $total_stock_value + $totalBankBalance;
|
||||
|
||||
return PdfService::render('business::balance-sheets.pdf', compact('asset_datas', 'total_asset'),'balance-sheet-report.pdf');
|
||||
return PdfService::render('business::balance-sheets.pdf', compact('asset_datas', 'total_asset', 'duration', 'filter_from_date', 'filter_to_date'),'balance-sheet-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,13 +90,37 @@ public function exportCsv()
|
||||
return Excel::download(new ExportBillWisePofit, 'bill-wise-profit.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$profits = Sale::with('party:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$salesQuery = Sale::with('party:id,name')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::bill-wise-profits.pdf', compact('profits'),'bill-wise-profit-report.pdf');
|
||||
$salesQuery->when($request->search, function ($query) use ($request) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('lossProfit', 'like', '%' . $request->search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$salesQuery->when($request->party_id, function ($query, $partyId) {
|
||||
if ($partyId === 'Guest') {
|
||||
$query->whereNull('party_id');
|
||||
} else {
|
||||
$query->where('party_id', $partyId);
|
||||
}
|
||||
});
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
|
||||
$profits = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::bill-wise-profits.pdf', compact('profits', 'duration', 'filter_from_date', 'filter_to_date'),'bill-wise-profit-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,21 @@
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Transaction;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Carbon\Carbon;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use App\Traits\DateRangeTrait;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportCashBalance;
|
||||
|
||||
class AcnooCashController extends Controller
|
||||
{
|
||||
use HasUploader;
|
||||
|
||||
use DateFilterTrait, DateRangeTrait;
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$business_id = auth()->user()->business_id;
|
||||
@@ -24,37 +30,16 @@ public function index(Request $request)
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
|
||||
|
||||
// Default to today
|
||||
$startDate = Carbon::today()->format('Y-m-d');
|
||||
$endDate = Carbon::today()->format('Y-m-d');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
if ($request->custom_days === 'yesterday') {
|
||||
$startDate = Carbon::yesterday()->format('Y-m-d');
|
||||
$endDate = Carbon::yesterday()->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'last_seven_days') {
|
||||
$startDate = Carbon::today()->subDays(6)->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'last_thirty_days') {
|
||||
$startDate = Carbon::today()->subDays(29)->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'current_month') {
|
||||
$startDate = Carbon::now()->startOfMonth()->format('Y-m-d');
|
||||
$endDate = Carbon::now()->endOfMonth()->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'last_month') {
|
||||
$startDate = Carbon::now()->subMonth()->startOfMonth()->format('Y-m-d');
|
||||
$endDate = Carbon::now()->subMonth()->endOfMonth()->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'current_year') {
|
||||
$startDate = Carbon::now()->startOfYear()->format('Y-m-d');
|
||||
$endDate = Carbon::now()->endOfYear()->format('Y-m-d');
|
||||
} elseif ($request->custom_days === 'custom_date' && $request->from_date && $request->to_date) {
|
||||
$startDate = Carbon::parse($request->from_date)->format('Y-m-d');
|
||||
$endDate = Carbon::parse($request->to_date)->format('Y-m-d');
|
||||
}
|
||||
|
||||
$cash->whereDate('date', '>=', $startDate)
|
||||
->whereDate('date', '<=', $endDate);
|
||||
$this->applyDateFilter($cash, $duration, 'date', $request->from_date, $request->to_date);
|
||||
|
||||
$cashes = $cash->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('date', 'like', '%' . $request->search . '%')
|
||||
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('user', function ($q) use ($request) {
|
||||
@@ -65,13 +50,30 @@ public function index(Request $request)
|
||||
->latest()
|
||||
->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
// Sum of all credits and bank_to_cash
|
||||
$totalCredit = (clone $cash)->where(function ($q) {
|
||||
$q->where('type', 'credit')
|
||||
->orWhere('transaction_type', 'bank_to_cash');
|
||||
})
|
||||
->sum('amount');
|
||||
|
||||
// Sum of all debits and cash_to_bank
|
||||
$totalDebit = (clone $cash)->where(function ($q) {
|
||||
$q->where('type', 'debit')
|
||||
->orWhere('transaction_type', 'cash_to_bank');
|
||||
})
|
||||
->sum('amount');
|
||||
|
||||
$cash_balance = $totalCredit - $totalDebit;
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::cashes.datas', compact('cashes'))->render()
|
||||
'data' => view('business::cashes.datas', compact('cashes', 'cash_balance', 'duration', 'filter_from_date', 'filter_to_date'))->render(),
|
||||
'cash_balance' => currency_format($cash_balance, 'icon', 2, business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::cashes.index', compact('cashes', 'banks'));
|
||||
return view('business::cashes.index', compact('cashes', 'banks', 'cash_balance', 'duration', 'filter_from_date', 'filter_to_date'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
@@ -282,5 +284,109 @@ public function destroy(string $id)
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteAll(Request $request)
|
||||
{
|
||||
$ids = $request->ids;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
|
||||
$transactions = Transaction::whereIn('id', $ids)->get();
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
|
||||
// Allow only "cash" platform transactions
|
||||
if ($transaction->platform !== 'cash') {
|
||||
return response()->json([
|
||||
'message' => 'Cannot delete here, please delete from ' . ucfirst($transaction->platform) . ' section.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$amount = $transaction->amount;
|
||||
$toBank = $transaction->to_bank ? PaymentType::find($transaction->to_bank) : null;
|
||||
|
||||
switch ($transaction->transaction_type) {
|
||||
|
||||
case 'cash_to_bank':
|
||||
|
||||
if ($toBank) {
|
||||
if ($toBank->balance < $amount) {
|
||||
return response()->json([
|
||||
'message' => 'Cannot delete: bank balance would go negative.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$toBank->decrement('balance', $amount);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'adjust_cash':
|
||||
// Cash is static, so no bank adjustments needed
|
||||
break;
|
||||
}
|
||||
|
||||
if ($transaction->image && file_exists($transaction->image)) {
|
||||
Storage::delete($transaction->image);
|
||||
}
|
||||
|
||||
$transaction->delete();
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Cash transactions reversed and deleted successfully.'),
|
||||
'redirect' => route('business.cashes.index'),
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Error: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
{
|
||||
return Excel::download(new ExportCashBalance, 'cash-balances.xlsx');
|
||||
}
|
||||
|
||||
public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportCashBalance, 'cash-balances.csv');
|
||||
}
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$cash = Transaction::with('user:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($cash, $duration, 'date', $request->from_date, $request->to_date);
|
||||
|
||||
$cashes = $cash->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('date', 'like', '%' . $request->search . '%')
|
||||
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('user', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::cashes.pdf', compact('cashes', 'duration', 'filter_from_date', 'filter_to_date'), 'cash-balances.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,16 +31,6 @@ public function index(Request $request)
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('type', ['debit', 'credit']);
|
||||
|
||||
$total_cash_in = (clone $query)
|
||||
->where('type', 'credit')
|
||||
->sum('amount');
|
||||
|
||||
$total_cash_out = (clone $query)
|
||||
->where('type', 'debit')
|
||||
->sum('amount');
|
||||
|
||||
$total_running_cash = $total_cash_in - $total_cash_out;
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
@@ -70,6 +60,16 @@ public function index(Request $request)
|
||||
$perPage = $request->input('per_page', 20);
|
||||
$cash_flows = $query->paginate($perPage)->appends($request->query());
|
||||
|
||||
$cashflow_cash_in = (clone $query)
|
||||
->where('type', 'credit')
|
||||
->sum('amount');
|
||||
|
||||
$cashflow_cash_out = (clone $query)
|
||||
->where('type', 'debit')
|
||||
->sum('amount');
|
||||
|
||||
$total_running_cash = $cashflow_cash_in - $cashflow_cash_out;
|
||||
|
||||
$firstDate = $cash_flows->first()?->date;
|
||||
|
||||
if ($firstDate) {
|
||||
@@ -83,11 +83,14 @@ public function index(Request $request)
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::cash-flow.datas', compact('cash_flows', 'total_cash_in', 'total_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'))->render()
|
||||
'data' => view('business::cash-flow.datas', compact('cash_flows', 'cashflow_cash_in', 'cashflow_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
||||
'cashflow_cash_in' => currency_format($cashflow_cash_in, 'icon', 2, business_currency()),
|
||||
'cashflow_cash_out' => currency_format($cashflow_cash_out, 'icon', 2, business_currency()),
|
||||
'total_running_cash' => currency_format($total_running_cash, 'icon', 2, business_currency()),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::cash-flow.index', compact('cash_flows', 'total_cash_in', 'total_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
return view('business::cash-flow.index', compact('cash_flows', 'cashflow_cash_in', 'cashflow_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
@@ -100,9 +103,9 @@ public function exportCsv()
|
||||
return Excel::download(new ExportCashFlowReport, 'cash-flow.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$cash_flows = Transaction::with([
|
||||
$query = Transaction::with([
|
||||
'paymentType:id,name',
|
||||
'sale:id,party_id',
|
||||
'sale.party:id,name',
|
||||
@@ -114,12 +117,47 @@ public function exportPdf()
|
||||
'dueCollect.party:id,name',
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('type', ['debit', 'credit'])
|
||||
->latest()
|
||||
->get();
|
||||
->whereIn('type', ['debit', 'credit']);
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($query, $duration, 'date', $request->from_date, $request->to_date);
|
||||
|
||||
// Search filter
|
||||
if ($request->filled('search')) {
|
||||
$query->where(function ($query) use ($request) {
|
||||
$query->where('date', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . $request->search . '%')
|
||||
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('paymentType', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if ($request->filled('platform')) {
|
||||
$query->where('platform', $request->platform);
|
||||
}
|
||||
|
||||
// Paginate data
|
||||
$cash_flows = $query->limit($request->per_page ?? 20)->get();
|
||||
|
||||
$firstDate = $cash_flows->first()?->date;
|
||||
|
||||
if ($firstDate) {
|
||||
$opening_balance = (clone $query)
|
||||
->whereDate('date', '<', $firstDate)
|
||||
->selectRaw("SUM(CASE WHEN type='credit' THEN amount ELSE 0 END) - SUM(CASE WHEN type='debit' THEN amount ELSE 0 END) as balance")
|
||||
->value('balance') ?? 0;
|
||||
} else {
|
||||
$opening_balance = 0;
|
||||
}
|
||||
|
||||
return PdfService::render('business::cash-flow.pdf', compact('cash_flows', 'opening_balance'),'cash-flow-report.pdf');
|
||||
return PdfService::render('business::cash-flow.pdf', compact('cash_flows', 'opening_balance', 'duration', 'filter_from_date', 'filter_to_date'),'cash-flow-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportComboProduct;
|
||||
|
||||
@@ -13,9 +14,14 @@ class AcnooComboProductController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
$search = $request->input('search');
|
||||
|
||||
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', 'combo')
|
||||
->withCount('combo_products as total_combo_products')
|
||||
@@ -31,6 +37,12 @@ public function index(Request $request)
|
||||
});
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
|
||||
->latest()
|
||||
->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
@@ -73,4 +85,55 @@ public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportComboProduct, 'combo-products.csv');
|
||||
}
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$search = $request->input('search');
|
||||
|
||||
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', 'combo')
|
||||
->withCount('combo_products as total_combo_products')
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
$combo_products->transform(function ($product) {
|
||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||
return optional($combo->stock)->productStock ?? 0;
|
||||
});
|
||||
|
||||
$product->total_cost = $product->combo_products->sum(function ($combo) {
|
||||
return ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0);
|
||||
});
|
||||
|
||||
return $product;
|
||||
});
|
||||
|
||||
return PdfService::render('business::products.combo-products.pdf', compact('combo_products'),'combo-products.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,14 +86,41 @@ public function exportCsv()
|
||||
return Excel::download(new ExportComboProductReport, 'combo-product-report.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$search = $request->input('search');
|
||||
|
||||
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', 'combo')
|
||||
->withCount('combo_products as total_combo_products')
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
|
||||
->latest()
|
||||
->get();
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
$combo_products->transform(function ($product) {
|
||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||
|
||||
@@ -54,7 +54,7 @@ public function index(Request $request)
|
||||
return view('business::party-reports.customer-ledger.index', compact('customers', 'totalAmount', 'totalPaid', 'totalDue'));
|
||||
}
|
||||
|
||||
public function show(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function show(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::find($partyId);
|
||||
$ledger = $service->list($request, $partyId);
|
||||
@@ -78,18 +78,30 @@ public function exportCsv()
|
||||
return Excel::download(new ExportCustomerLedger, 'customer-ledger.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$customers = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->when(request('type'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('type', $request->type);
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->get();
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::party-reports.customer-ledger.pdf', compact('customers'),'customer-ledger-report.pdf');
|
||||
}
|
||||
|
||||
public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerExcel(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::findOrFail($partyId);
|
||||
|
||||
@@ -98,7 +110,7 @@ public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService
|
||||
return Excel::download(new ExportSingleCustomerLedger($ledger, $party), 'single-customer-ledger.xlsx');
|
||||
}
|
||||
|
||||
public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerCsv(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::findOrFail($partyId);
|
||||
|
||||
@@ -107,15 +119,18 @@ public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $
|
||||
return Excel::download(new ExportSingleCustomerLedger($ledger, $party), 'single-customer-ledger.csv');
|
||||
}
|
||||
|
||||
public function exportLedgerPdf(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerPdf(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::findOrFail($partyId);
|
||||
|
||||
$ledger = $service->list($request, $partyId);
|
||||
|
||||
return PdfService::render(
|
||||
'business::party-reports.customer-ledger.show-details.pdf',
|
||||
compact('ledger', 'party'),
|
||||
$duration = $request->custom_days ?: $request->duration ?: 'today';
|
||||
|
||||
[$fromDate, $toDate] = app(PartyLedgerService::class)->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
return PdfService::render('business::party-reports.customer-ledger.show-details.pdf',
|
||||
compact('ledger', 'party', 'duration', 'fromDate', 'toDate'),
|
||||
strtolower($party->name).'-ledger.pdf'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,44 +60,31 @@ public function index(Request $request)
|
||||
$query->where('platform', $request->platform);
|
||||
}
|
||||
|
||||
// Calculate summary data
|
||||
$all_summary_records = (clone $query)->get();
|
||||
|
||||
$total_amount = $all_summary_records->sum(function ($day_book) {
|
||||
return match ($day_book->platform) {
|
||||
'sale' => $day_book->sale?->totalAmount ?? 0,
|
||||
'sale_return' => $day_book->saleReturn?->sale?->totalAmount ?? 0,
|
||||
'purchase' => $day_book->purchase?->totalAmount ?? 0,
|
||||
'purchase_return' => $day_book->purchaseReturn?->purchase?->totalAmount ?? 0,
|
||||
'due_collect', 'due_pay' => $day_book->dueCollect?->totalDue ?? 0,
|
||||
default => 0
|
||||
};
|
||||
});
|
||||
|
||||
$total_money_in = $all_summary_records->where('type', 'credit')->sum(function ($day_book) {
|
||||
return match ($day_book->platform) {
|
||||
'sale' => $day_book->sale?->totalAmount ?? 0,
|
||||
'sale_return' => $day_book->saleReturn?->sale?->totalAmount ?? 0,
|
||||
'purchase' => $day_book->purchase?->totalAmount ?? 0,
|
||||
'purchase_return' => $day_book->purchaseReturn?->purchase?->totalAmount ?? 0,
|
||||
'due_collect', 'due_pay' => $day_book->dueCollect?->totalDue ?? 0,
|
||||
default => 0
|
||||
};
|
||||
});
|
||||
|
||||
$total_money_out = $all_summary_records->where('type', 'debit')->sum('amount');
|
||||
|
||||
// Paginate data
|
||||
$perPage = $request->input('per_page', 20);
|
||||
$day_books = $query->latest()->paginate($perPage)->appends($request->query());
|
||||
|
||||
// Calculate summary data
|
||||
$total_money_in = (clone $query)
|
||||
->where('type', 'credit')
|
||||
->sum('amount');
|
||||
|
||||
$total_money_out = (clone $query)
|
||||
->where('type', 'debit')
|
||||
->sum('amount');
|
||||
|
||||
$total_money_in_out_amount = $total_money_in + $total_money_out;
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::day-book.datas', compact('day_books', 'total_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'))->render()
|
||||
'data' => view('business::day-book.datas', compact('day_books', 'total_money_in_out_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
||||
'total_money_in' => currency_format($total_money_in, 'icon', 2, business_currency()),
|
||||
'total_money_out' => currency_format($total_money_out, 'icon', 2, business_currency()),
|
||||
'total_money_in_out_amount' => currency_format($total_money_in_out_amount, 'icon', 2, business_currency()),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::day-book.index', compact('day_books', 'total_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
return view('business::day-book.index', compact('day_books', 'total_money_in_out_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
@@ -110,9 +97,9 @@ public function exportCsv()
|
||||
return Excel::download(new ExportDayBookReport, 'day-book.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$day_books = Transaction::with([
|
||||
$query = Transaction::with([
|
||||
'paymentType:id,name',
|
||||
'sale:id,user_id,party_id,totalAmount',
|
||||
'sale.party:id,name',
|
||||
@@ -127,10 +114,37 @@ public function exportPdf()
|
||||
'dueCollect.user:id,name',
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereIn('type', ['debit', 'credit'])
|
||||
->latest()
|
||||
->get();
|
||||
->whereIn('type', ['debit', 'credit']);
|
||||
|
||||
return PdfService::render('business::day-book.pdf', compact('day_books'), 'day-book-report.pdf');
|
||||
// Apply date filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($query, $duration, 'date', $request->from_date, $request->to_date);
|
||||
|
||||
// Search filter
|
||||
if ($request->filled('search')) {
|
||||
$query->where(function ($query) use ($request) {
|
||||
$query->where('date', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . $request->search . '%')
|
||||
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('paymentType', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if ($request->filled('platform')) {
|
||||
$query->where('platform', $request->platform);
|
||||
}
|
||||
|
||||
// Paginate data
|
||||
$day_books = $query->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::day-book.pdf', compact('day_books', 'duration', 'filter_from_date', 'filter_to_date'),'day-book-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ class AcnooDiscountProductReportController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
@@ -21,7 +20,7 @@ public function index(Request $request)
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode')
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
})
|
||||
@@ -62,13 +61,35 @@ public function exportCsv()
|
||||
return Excel::download(new ExportDiscountProduct, 'discount-products.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode')
|
||||
$user = auth()->user();
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
})
|
||||
->when(request('search'), function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhere('price', 'like', '%' . $request->search . '%')
|
||||
->orWhere('discount', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
->where('discount', '>', 0)
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::reports.discount-products.pdf', compact('discount_products'),'discount-product-report.pdf');
|
||||
|
||||
@@ -2,21 +2,25 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Services\Invoice\DueInvoiceService;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Sale;
|
||||
use App\Models\Party;
|
||||
use App\Models\Business;
|
||||
use App\Models\Purchase;
|
||||
use App\Models\DueCollect;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Transaction;
|
||||
use App\Services\PdfService;
|
||||
use Illuminate\Http\Request;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use App\Events\DuePaymentReceived;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Events\MultiPaymentProcessed;
|
||||
use App\Models\Transaction;
|
||||
use Carbon\Carbon;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportDueList;
|
||||
use Modules\Business\App\Exports\ExportGuestDue;
|
||||
|
||||
class AcnooDueController extends Controller
|
||||
{
|
||||
@@ -30,29 +34,6 @@ public function index(Request $request)
|
||||
$businessId = auth()->user()->business_id;
|
||||
$activeBranch = auth()->user()->active_branch;
|
||||
|
||||
if ($activeBranch) {
|
||||
$total_supplier_due = Party::where('business_id', $businessId)
|
||||
->where('type', 'Supplier')
|
||||
->with('purchases_dues')
|
||||
->get()
|
||||
->sum(fn($p) => $p->purchases_dues->sum('dueAmount'));
|
||||
|
||||
$total_customer_due = Party::where('business_id', $businessId)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->with('sales_dues')
|
||||
->get()
|
||||
->sum(fn($p) => $p->sales_dues->sum('dueAmount'));
|
||||
} else {
|
||||
|
||||
$total_supplier_due = Party::where('business_id', $businessId)
|
||||
->where('type', 'Supplier')
|
||||
->sum('due');
|
||||
|
||||
$total_customer_due = Party::where('business_id', $businessId)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->sum('due');
|
||||
}
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
->with(['purchases_dues', 'sales_dues']);
|
||||
|
||||
@@ -69,42 +50,70 @@ public function index(Request $request)
|
||||
->orWhere('phone', 'like', "%$search%")
|
||||
->orWhere('email', 'like', "%$search%");
|
||||
|
||||
if (!$activeBranch) {
|
||||
if (! $activeBranch) {
|
||||
$q->orWhere('due', 'like', "%$search%");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$totalQuery = clone $query;
|
||||
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
if ($activeBranch) {
|
||||
$filtered = $parties->getCollection()
|
||||
->map(function ($party) {
|
||||
$total_supplier_due = (clone $totalQuery)
|
||||
->where('type', 'Supplier')
|
||||
->get()
|
||||
->sum(fn ($p) => $p->purchases_dues->sum('dueAmount'));
|
||||
|
||||
$party->due = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->sum('dueAmount')
|
||||
: $party->sales_dues->sum('dueAmount');
|
||||
$total_customer_due = (clone $totalQuery)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->get()
|
||||
->sum(fn ($p) => $p->sales_dues->sum('dueAmount'));
|
||||
} else {
|
||||
$total_supplier_due = (clone $totalQuery)
|
||||
->where('type', 'Supplier')
|
||||
->sum('due');
|
||||
|
||||
$total_customer_due = (clone $totalQuery)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->sum('due');
|
||||
}
|
||||
|
||||
if ($activeBranch) {
|
||||
$filtered = $parties->getCollection()
|
||||
->map(function ($party) use ($activeBranch) {
|
||||
|
||||
$sale_dues = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->where('branch_id', $activeBranch->id)
|
||||
: $party->sales_dues->where('branch_id', $activeBranch->id);
|
||||
|
||||
$party_due = $sale_dues->sum('dueAmount');
|
||||
|
||||
if ($party->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
|
||||
$party->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$party->due = $party_due;
|
||||
}
|
||||
|
||||
return $party;
|
||||
})
|
||||
->filter(fn($p) => $p->due > 0)
|
||||
->filter(fn ($p) => $p->due > 0)
|
||||
->values();
|
||||
|
||||
$parties->setCollection($filtered);
|
||||
} else {
|
||||
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()->filter(fn($p) => $p->due > 0)->values()
|
||||
$parties->getCollection()->filter(fn ($p) => $p->due > 0)->values()
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::dues.datas', [
|
||||
'parties' => $parties,
|
||||
'total_supplier_due' => $total_supplier_due,
|
||||
'total_customer_due' => $total_customer_due
|
||||
])->render()
|
||||
'data' => view('business::dues.datas', compact('parties'))->render(),
|
||||
'total_supplier_due' => currency_format($total_supplier_due, currency: business_currency()),
|
||||
'total_customer_due' => currency_format($total_customer_due, currency: business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -115,24 +124,34 @@ public function index(Request $request)
|
||||
));
|
||||
}
|
||||
|
||||
public function collectDue($id)
|
||||
|
||||
public function collectDue(string $id)
|
||||
{
|
||||
$activeBranch = auth()->user()->active_branch;
|
||||
$party = Party::where('business_id', auth()->user()->business_id)->with(['sales_dues', 'purchases_dues'])->findOrFail($id);
|
||||
$payment_types = PaymentType::where('business_id', auth()->user()->business_id)->whereStatus(1)->latest()->get();
|
||||
|
||||
$due_amount = 0;
|
||||
if ($party->type == 'Supplier') {
|
||||
foreach ($party->purchases_dues as $sales_due) {
|
||||
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
|
||||
$due_amount += $sales_due->dueAmount;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($party->sales_dues as $sales_due) {
|
||||
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
|
||||
$due_amount += $sales_due->dueAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auth()->user()->active_branch) {
|
||||
if ($activeBranch) {
|
||||
if ($party->branch_id === $activeBranch->id && $party->opening_balance_type === 'due') {
|
||||
$party_opening_due = $party->opening_balance ?? 0;
|
||||
} else {
|
||||
$party_opening_due = 0;
|
||||
}
|
||||
} else {
|
||||
$party_opening_due = $party->due - $due_amount;
|
||||
}
|
||||
@@ -140,28 +159,24 @@ public function collectDue($id)
|
||||
return view('business::dues.collect-due', compact('party', 'party_opening_due', 'payment_types'));
|
||||
}
|
||||
|
||||
|
||||
public function collectDueStore(Request $request)
|
||||
{
|
||||
$party = Party::find($request->party_id);
|
||||
$activeBranch = auth()->user()->active_branch;
|
||||
|
||||
$request->validate([
|
||||
'paymentDate' => 'required|string',
|
||||
'payDueAmount' => 'required|numeric',
|
||||
'party_id' => 'required|exists:parties,id',
|
||||
'invoiceNumber' => 'nullable|exists:' . ($party->type == 'Supplier' ? 'purchases' : 'sales') . ',invoiceNumber',
|
||||
'invoiceNumber' => 'nullable|exists:'.($party->type == 'Supplier' ? 'purchases' : 'sales').',invoiceNumber',
|
||||
]);
|
||||
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
if (auth()->user()->active_branch && !$request->invoiceNumber) {
|
||||
return response()->json([
|
||||
'message' => __('You must select an invoice when login any branch.')
|
||||
], 400);
|
||||
}
|
||||
$business = Business::findOrFail(auth()->user()->business_id);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$branch_id = null;
|
||||
$branch_id = $activeBranch?->id;
|
||||
$invoice = null;
|
||||
|
||||
$payments = $request->payments ?? [];
|
||||
@@ -173,81 +188,104 @@ public function collectDueStore(Request $request)
|
||||
}
|
||||
|
||||
$payDueAmount = collect($payments)
|
||||
->reject(fn($p) => strtolower($p['type']) === 'cheque')
|
||||
->reject(fn ($p) => strtolower($p['type']) === 'cheque')
|
||||
->sum('amount');
|
||||
|
||||
// Get related invoice if exists
|
||||
$invoice_due = 0;
|
||||
$opening_balance_due = 0;
|
||||
|
||||
if ($activeBranch) {
|
||||
if ($party->type == 'Supplier') {
|
||||
$invoice_due = Purchase::where('party_id', $request->party_id)
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
} else {
|
||||
$invoice_due = Sale::where('party_id', $request->party_id)
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
}
|
||||
|
||||
if ($party->branch_id === $activeBranch->id && $party->opening_balance_type === 'due') {
|
||||
$opening_balance_due = $party->opening_balance ?? 0;
|
||||
}
|
||||
} else {
|
||||
if ($party->type == 'Supplier') {
|
||||
$invoice_due = Purchase::where('party_id', $request->party_id)->sum('dueAmount');
|
||||
} else {
|
||||
$invoice_due = Sale::where('party_id', $request->party_id)->sum('dueAmount');
|
||||
}
|
||||
$opening_balance_due = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
|
||||
}
|
||||
|
||||
$total_due = $invoice_due + $opening_balance_due;
|
||||
|
||||
if ($payDueAmount > $total_due) {
|
||||
return response()->json([
|
||||
'message' => __('You can pay maximum '.$total_due.' due amount.'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($activeBranch && ! $request->invoiceNumber && $invoice_due > 0 && $opening_balance_due == 0) {
|
||||
return response()->json([
|
||||
'message' => __('You must select an invoice when login any branch.'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($request->invoiceNumber) {
|
||||
if ($party->type == 'Supplier') {
|
||||
$invoice = Purchase::where('invoiceNumber', $request->invoiceNumber)->where('party_id', $request->party_id)->first();
|
||||
$invoice = Purchase::where('invoiceNumber', $request->invoiceNumber)
|
||||
->where('party_id', $request->party_id)
|
||||
->where('branch_id', $activeBranch?->id)
|
||||
->first();
|
||||
} else {
|
||||
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)->where('party_id', $request->party_id)->first();
|
||||
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)
|
||||
->where('party_id', $request->party_id)
|
||||
->where('branch_id', $activeBranch?->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!isset($invoice)) {
|
||||
if (! isset($invoice)) {
|
||||
return response()->json([
|
||||
'message' => 'Invoice Not Found.'
|
||||
'message' => 'Invoice Not Found.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
if (!auth()->user()->active_branch) {
|
||||
if (isset($invoice) && isset($invoice->branch_id)) {
|
||||
$branch_id = $invoice->branch_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($invoice->dueAmount < $request->payDueAmount) {
|
||||
return response()->json([
|
||||
'message' => 'Invoice due is ' . $invoice->dueAmount . '. You can not pay more then the invoice due amount.'
|
||||
], 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Validation for all invoices due
|
||||
if (!$request->invoiceNumber) {
|
||||
if ($party->type == 'Supplier') {
|
||||
$all_invoice_due = Purchase::where('party_id', $request->party_id)->sum('dueAmount');
|
||||
} else {
|
||||
$all_invoice_due = Sale::where('party_id', $request->party_id)->sum('dueAmount');
|
||||
}
|
||||
|
||||
if (($all_invoice_due + $request->payDueAmount) > $party->due) {
|
||||
return response()->json([
|
||||
'message' => __('You can pay only ' . $party->due - $all_invoice_due . ', without selecting an invoice.')
|
||||
'message' => 'Invoice due is '.$invoice->dueAmount.'. You can not pay more then the invoice due amount.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($party->opening_balance_type == 'due') {
|
||||
$branch_id = $invoice->branch_id;
|
||||
}
|
||||
|
||||
if (! $request->invoiceNumber && $opening_balance_due > 0) {
|
||||
$party->update([
|
||||
'opening_balance' => max(0, $party->opening_balance - $payDueAmount),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$data = DueCollect::create($request->except('user_id', 'business_id', 'sale_id', 'purchase_id', 'totalDue', 'dueAmountAfterPay', 'paymentDate') + [
|
||||
'user_id' => auth()->id(),
|
||||
'business_id' => $business_id,
|
||||
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : NULL,
|
||||
'purchase_id' => $party->type == 'Supplier' && isset($invoice) ? $invoice->id : NULL,
|
||||
'totalDue' => isset($invoice) ? $invoice->dueAmount : $party->due,
|
||||
'dueAmountAfterPay'=> isset($invoice) ? ($invoice->dueAmount - $payDueAmount) : ($party->due - $payDueAmount),
|
||||
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now()
|
||||
'business_id' => $business->id,
|
||||
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : null,
|
||||
'purchase_id' => $party->type == 'Supplier' && isset($invoice) ? $invoice->id : null,
|
||||
'totalDue' => $total_due,
|
||||
'dueAmountAfterPay' => $total_due - $payDueAmount,
|
||||
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now(),
|
||||
]);
|
||||
|
||||
// Update invoice due
|
||||
if (isset($invoice)) {
|
||||
$invoice->update([
|
||||
'dueAmount' => $invoice->dueAmount - $payDueAmount,
|
||||
'paidAmount' => $invoice->paidAmount + $payDueAmount
|
||||
'paidAmount' => $invoice->paidAmount + $payDueAmount,
|
||||
]);
|
||||
}
|
||||
|
||||
// Update party due
|
||||
$party->update([
|
||||
'due' => $party->due - $payDueAmount
|
||||
'due' => $party->due - $payDueAmount,
|
||||
]);
|
||||
|
||||
// update balance & adjust platform
|
||||
if ($party->type == 'Supplier') {
|
||||
updateBalance($payDueAmount, 'decrement', $branch_id);
|
||||
$platform = 'due_pay';
|
||||
@@ -256,7 +294,6 @@ public function collectDueStore(Request $request)
|
||||
$platform = 'due_collect';
|
||||
}
|
||||
|
||||
// MultiPaymentProcessed event
|
||||
event(new MultiPaymentProcessed(
|
||||
$payments,
|
||||
$data->id,
|
||||
@@ -265,45 +302,30 @@ public function collectDueStore(Request $request)
|
||||
$party->id,
|
||||
));
|
||||
|
||||
// Notify
|
||||
event(new DuePaymentReceived($data));
|
||||
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business_id);
|
||||
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business->id);
|
||||
|
||||
if (moduleCheck('MarketingAddon')) {
|
||||
$this->dueTransactionMessage($business, $party, $data);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Collect Due saved successfully'),
|
||||
'redirect' => route('business.dues.index'),
|
||||
'secondary_redirect_url' => route('business.collect.dues.invoice', $party->id),
|
||||
'secondary_redirect_url' => route('business.collect.dues.invoice', $data->id),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json(['message' => $e->getMessage()], 404);
|
||||
}
|
||||
}
|
||||
|
||||
public function getInvoice($id)
|
||||
public function getInvoice($party_id, DueInvoiceService $service)
|
||||
{
|
||||
$due_collect = DueCollect::with('user:id,name,role', 'party:id,name,email,phone,type', 'payment_type:id,name', 'business:id,companyName,address,phoneNumber,email,vat_name,vat_no,meta', )
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('party_id', $id)
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
$transactionTypes = $due_collect->transactions
|
||||
->map(function ($transaction) {
|
||||
if ($transaction->transaction_type === 'bank_payment' && !empty($transaction->paymentType?->name)) {
|
||||
return $transaction->paymentType->name;
|
||||
}
|
||||
return $transaction->transaction_type ? ucfirst(explode('_', $transaction->transaction_type)[0]) : '';
|
||||
})
|
||||
->unique()
|
||||
->implode(', ');
|
||||
|
||||
$party = Party::with('dueCollect.business')->find($id);
|
||||
$bank_detail = PaymentType::where('business_id', auth()->user()->business_id)->where('show_in_invoice', 1)->latest()->first();
|
||||
|
||||
return view('business::dues.invoice', compact('due_collect', 'party', 'transactionTypes', 'bank_detail'));
|
||||
$data = $service->getInvoiceData($party_id);
|
||||
return view('business::dues.invoice', $data);
|
||||
}
|
||||
|
||||
public function generatePDF($id)
|
||||
@@ -391,10 +413,10 @@ public function partyDue(Request $request)
|
||||
// Apply search
|
||||
$query->when($request->search, function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('email', 'like', '%' . $request->search . '%')
|
||||
->orWhere('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('due', 'like', '%' . $request->search . '%');
|
||||
$q->where('email', 'like', '%'.$request->search.'%')
|
||||
->orWhere('name', 'like', '%'.$request->search.'%')
|
||||
->orWhere('phone', 'like', '%'.$request->search.'%')
|
||||
->orWhere('due', 'like', '%'.$request->search.'%');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -402,36 +424,46 @@ public function partyDue(Request $request)
|
||||
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
if ($activeBranch) {
|
||||
// Calculate branch-wise due and replace $party->due, remove zero-due parties
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($party) {
|
||||
$party->due = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->sum('dueAmount')
|
||||
: $party->sales_dues->sum('dueAmount');
|
||||
->transform(function ($party) use ($activeBranch) {
|
||||
$sale_dues = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->where('branch_id', $activeBranch->id)
|
||||
: $party->sales_dues->where('branch_id', $activeBranch->id);
|
||||
|
||||
$party_due = $sale_dues->sum('dueAmount');
|
||||
|
||||
if ($party->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
|
||||
$party->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$party->due = $party_due;
|
||||
}
|
||||
|
||||
return $party;
|
||||
})
|
||||
->filter(fn($party) => $party->due > 0)
|
||||
->filter(fn ($party) => $party->due > 0)
|
||||
->values()
|
||||
);
|
||||
} else {
|
||||
// Non-active branch: ensure only parties with due > 0
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->filter(fn($party) => $party->due > 0)
|
||||
->filter(fn ($party) => $party->due > 0)
|
||||
->values()
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::dues.party.datas', compact('parties'))->render()
|
||||
'data' => view('business::dues.party.datas', compact('parties'))->render(),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::dues.party.index', compact('parties', 'party_type'));
|
||||
}
|
||||
|
||||
|
||||
public function walk_dues(Request $request)
|
||||
{
|
||||
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
|
||||
@@ -483,8 +515,8 @@ public function walkDuesGetInvoice(string $id)
|
||||
$due_collect = DueCollect::with('business:id,companyName,address,phoneNumber,email,vat_name,vat_no,meta', 'user:id,name,role', 'payment_type:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereNull('party_id')
|
||||
->latest()
|
||||
->first();
|
||||
->where('id', $id) // 🔥 FIX HERE
|
||||
->firstOrFail();
|
||||
|
||||
$transactionTypes = $due_collect->transactions
|
||||
->map(function ($transaction) {
|
||||
@@ -496,7 +528,8 @@ public function walkDuesGetInvoice(string $id)
|
||||
->unique()
|
||||
->implode(', ');
|
||||
|
||||
$walk_in_customer = Sale::with('dueCollect.business')->find($id);
|
||||
// $walk_in_customer = Sale::with('dueCollect.business')->find($id);
|
||||
$walk_in_customer = Sale::with('dueCollect.business')->find($due_collect->sale_id);
|
||||
|
||||
$bank_detail = PaymentType::where('business_id', auth()->user()->business_id)->where('show_in_invoice', 1)->latest()->first();
|
||||
|
||||
@@ -527,7 +560,8 @@ public function collectWalkDueStore(Request $request)
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$branch_id = null;
|
||||
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)->whereNull('party_id')->first();
|
||||
$invoice = Sale::where('business_id', $business_id)->where('invoiceNumber', $request->invoiceNumber)->whereNull('party_id')->first();
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'message' => 'Invoice Not Found.'
|
||||
@@ -565,23 +599,23 @@ public function collectWalkDueStore(Request $request)
|
||||
'sale_id' => $invoice->id,
|
||||
'invoiceNumber' => $request->invoiceNumber,
|
||||
'totalDue' => $invoice->dueAmount,
|
||||
'dueAmountAfterPay' => $invoice->dueAmount - $request->payDueAmount,
|
||||
'payDueAmount' => $request->payDueAmount,
|
||||
'dueAmountAfterPay' => $invoice->dueAmount - $payDueAmount,
|
||||
'payDueAmount' => $payDueAmount,
|
||||
'paymentDate' => $request->paymentDate,
|
||||
]);
|
||||
|
||||
$invoice->update([
|
||||
'dueAmount' => $invoice->dueAmount - $request->payDueAmount
|
||||
'dueAmount' => $invoice->dueAmount - $payDueAmount
|
||||
]);
|
||||
|
||||
updateBalance($request->payDueAmount, 'increment', $branch_id);
|
||||
updateBalance($payDueAmount, 'increment', $branch_id);
|
||||
|
||||
// MultiPaymentProcessed event
|
||||
event(new MultiPaymentProcessed(
|
||||
$request->payments ?? [],
|
||||
$payments,
|
||||
$data->id,
|
||||
'due_collect',
|
||||
$request->payDueAmount,
|
||||
$payDueAmount,
|
||||
));
|
||||
|
||||
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business_id);
|
||||
@@ -591,7 +625,7 @@ public function collectWalkDueStore(Request $request)
|
||||
return response()->json([
|
||||
'message' => __('Collect Due saved successfully'),
|
||||
'redirect' => route('business.walk-dues.index'),
|
||||
'secondary_redirect_url' => route('business.collect.walk-dues.invoice', $invoice->id),
|
||||
'secondary_redirect_url' => route('business.collect.walk-dues.invoice', $data->id),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@@ -660,4 +694,95 @@ public function viewDuePayment($id)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
{
|
||||
return Excel::download(new ExportDueList, 'due-list.xlsx');
|
||||
}
|
||||
|
||||
public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportDueList, 'due-list.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$activeBranch = auth()->user()->active_branch;
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
->with(['purchases_dues', 'sales_dues']);
|
||||
|
||||
if (request('type')) {
|
||||
$query->where('type', request('type'));
|
||||
}
|
||||
|
||||
if (request('search')) {
|
||||
$search = request('search');
|
||||
|
||||
$query->where(function ($q) use ($search, $activeBranch) {
|
||||
$q->where('type', 'like', "%$search%")
|
||||
->orWhere('name', 'like', "%$search%")
|
||||
->orWhere('phone', 'like', "%$search%")
|
||||
->orWhere('email', 'like', "%$search%");
|
||||
|
||||
if (!$activeBranch) {
|
||||
$q->orWhere('due', 'like', "%$search%");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$parties = $query->latest()->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties = $parties->map(function ($party) use ($activeBranch) {
|
||||
$sale_dues = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->where('branch_id', $activeBranch->id)
|
||||
: $party->sales_dues->where('branch_id', $activeBranch->id);
|
||||
|
||||
$party_due = $sale_dues->sum('dueAmount');
|
||||
|
||||
if ($party->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
|
||||
$party->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$party->due = $party_due;
|
||||
}
|
||||
|
||||
return $party;
|
||||
})->filter(fn($p) => $p->due > 0)->values();
|
||||
} else {
|
||||
$parties = $parties->filter(fn($p) => $p->due > 0)->values();
|
||||
}
|
||||
|
||||
return PdfService::render('business::dues.pdf-export', compact('parties'),'due-list.pdf');
|
||||
}
|
||||
|
||||
public function walkDueExportExcel()
|
||||
{
|
||||
return Excel::download(new ExportGuestDue, 'guest-due-list.xlsx');
|
||||
}
|
||||
|
||||
public function walkDueExportCsv()
|
||||
{
|
||||
return Excel::download(new ExportGuestDue, 'guest-due-list.csv');
|
||||
}
|
||||
|
||||
public function walkDueExportPdf(Request $request)
|
||||
{
|
||||
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
|
||||
->with('dueCollect')
|
||||
->whereNull('party_id')
|
||||
->where('dueAmount', '>', 0)
|
||||
->when(request('search'), function ($query) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
|
||||
->orwhere('dueAmount', 'like', '%' . request('search') . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::walk-dues.pdf', compact('walk_in_customers'),'guest-due-list.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,79 +32,56 @@ public function index(Request $request)
|
||||
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->when(request('type'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
->when($request->type, function ($q) use ($request) {
|
||||
$q->where('type', $request->type);
|
||||
});
|
||||
})
|
||||
->with('sales_dues')
|
||||
->latest();
|
||||
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->paginate($request->per_page ?? 20);
|
||||
$parties = $query->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($customer) use ($activeBranch) {
|
||||
$customer->due = $customer->sales_dues
|
||||
$party_due = $customer->sales_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
|
||||
if ($customer->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $customer->opening_balance_type === 'due'
|
||||
? ($customer->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$customer->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
|
||||
$customer->due = $party_due;
|
||||
}
|
||||
|
||||
return $customer;
|
||||
})
|
||||
->filter(fn($customer) => $customer->due > 0)
|
||||
->values()
|
||||
);
|
||||
} else {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->filter(fn($customer) => ($customer->due ?? 0) > 0)
|
||||
->values()
|
||||
);
|
||||
}
|
||||
|
||||
$total_due = $parties->sum(fn($customer) => $customer->due);
|
||||
$customer_total_due = $parties->getCollection()->sum('due');
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::reports.due.datas', compact('parties', 'total_due'))->render()
|
||||
'data' => view('business::reports.due.datas', compact('parties'))->render(),
|
||||
'customer_total_due' => currency_format($customer_total_due, currency: business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
if ($activeBranch) {
|
||||
// Filter customers that have branch-specific due > 0
|
||||
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
// global due > 0
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->paginate(20)->appends($request->query());
|
||||
|
||||
// Replace customer due with branch-specific due if active branch exists
|
||||
if ($activeBranch) {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($customer) use ($activeBranch) {
|
||||
$customer->due = $customer->sales_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $customer;
|
||||
})
|
||||
->filter(fn($customer) => $customer->due > 0)
|
||||
->values()
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate total_due
|
||||
$total_due = $parties->sum(fn($customer) => $customer->due);
|
||||
|
||||
return view('business::reports.due.due-reports', compact('parties', 'total_due'));
|
||||
return view('business::reports.due.due-reports', compact('parties', 'customer_total_due'));
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
@@ -117,37 +94,59 @@ public function exportCsv()
|
||||
return Excel::download(new ExportDue, 'customer-due.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
$activeBranch = $user->active_branch;
|
||||
$business_id = $user->business_id;
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
$query = Party::where('business_id', $business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when($request->search, function ($q) use ($request) {
|
||||
$q->where(function ($q2) use ($request) {
|
||||
$q2->where('type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->when($request->type, function ($q) use ($request) {
|
||||
$q->where('type', $request->type);
|
||||
})
|
||||
->with('sales_dues')
|
||||
->latest();
|
||||
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->sales_dues
|
||||
$parties = $parties
|
||||
->transform(function ($customer) use ($activeBranch) {
|
||||
$party_due = $customer->sales_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $supplier;
|
||||
})->filter(fn($supplier) => $supplier->due > 0);
|
||||
|
||||
if ($customer->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $customer->opening_balance_type === 'due'
|
||||
? ($customer->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$customer->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
|
||||
$customer->due = $party_due;
|
||||
}
|
||||
return $customer;
|
||||
})
|
||||
->filter(fn($customer) => $customer->due > 0)
|
||||
->take($request->per_page ?? 20)
|
||||
->values();
|
||||
} else {
|
||||
$parties = $parties
|
||||
->filter(fn($customer) => ($customer->due ?? 0) > 0)
|
||||
->take($request->per_page ?? 20)
|
||||
->values();
|
||||
}
|
||||
|
||||
return PdfService::render('business::reports.due.pdf', compact('parties'),'customer-due-report.pdf');
|
||||
return PdfService::render('business::reports.due.pdf', compact('parties'), 'customer-due-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AcnooEstimateController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('business::estimates.index');
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('business::estimates.create');
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return view('business::estimates.create');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
use App\Models\Branch;
|
||||
use App\Models\Expense;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
@@ -26,10 +25,6 @@ public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$total_expense = Expense::where('business_id', $businessId)
|
||||
->whereDate('expenseDate', Carbon::today()->format('Y-m-d'))
|
||||
->sum('amount');
|
||||
|
||||
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
@@ -90,10 +85,40 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$expense_reports = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::reports.expense.pdf', compact('expense_reports'),'expenses-report.pdf');
|
||||
$expenseQuery->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$expenseQuery->where(function ($query) use ($request) {
|
||||
$query->where('expanseFor', 'like', '%' . $request->search . '%')
|
||||
->orWhere('paymentType', 'like', '%' . $request->search . '%')
|
||||
->orWhere('referenceNo', 'like', '%' . $request->search . '%')
|
||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('category', function ($q) use ($request) {
|
||||
$q->where('categoryName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$expense_reports = $expenseQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.expense.pdf', compact('expense_reports', 'duration', 'filter_from_date', 'filter_to_date'),'expenses-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportExpiredProduct;
|
||||
|
||||
@@ -64,4 +65,38 @@ public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportExpiredProduct, 'expired-products.csv');
|
||||
}
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->whereHas('stocks', function ($query) {
|
||||
$query->whereDate('expire_date', '<', today())
|
||||
->where('productStock', '>', 0);
|
||||
})
|
||||
->when($request->search, function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productName', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $request->search . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('unit', function ($q) use ($request) {
|
||||
$q->where('unitName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('brand', function ($q) use ($request) {
|
||||
$q->where('brandName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('category', function ($q) use ($request) {
|
||||
$q->where('categoryName', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::expired-products.pdf', compact('expired_products'),'expired-products.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,17 +80,46 @@ public function exportCsv()
|
||||
return Excel::download(new ExportExpiredProductReport, 'expired-product-reports.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
|
||||
$businessId = auth()->user()->business_id;
|
||||
$expiredProductsQuery = Product::with(['unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks'])
|
||||
->withSum('stocks', 'productStock')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('stocks', function ($query) {
|
||||
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
|
||||
})
|
||||
->latest()
|
||||
->get();
|
||||
$query->whereDate('expire_date', '<=', today())->where('productStock', '>', 0);
|
||||
});
|
||||
|
||||
return PdfService::render('business::reports.expired-products.pdf', compact('expired_products'),'expired-product-report.pdf');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$expiredProductsQuery->whereHas('stocks', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'expire_date', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$expiredProductsQuery->where(function ($query) use ($search) {
|
||||
$query->where('productName', 'like', '%' . $search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $search . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('categoryName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('brand', function ($q) use ($search) {
|
||||
$q->where('brandName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('unit', function ($q) use ($search) {
|
||||
$q->where('unitName', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$expired_products = $expiredProductsQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.expired-products.pdf', compact('expired_products', 'duration', 'filter_from_date', 'filter_to_date'),'expired-product-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\State;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AcnooGetStateController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$states = State::where('country_id', $request->country_id)->where('status', 1)->orderBy('name')->get(['id', 'name']);
|
||||
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
'states' => $states
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -83,10 +83,36 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$income_reports = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::reports.income.pdf', compact('income_reports'),'incomes-report.pdf');
|
||||
// Branch filter
|
||||
if ($request->branch_id) {
|
||||
$incomeQuery->where('branch_id', $request->branch_id);
|
||||
}
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
|
||||
|
||||
// Search filter
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$incomeQuery->where(function ($query) use ($search) {
|
||||
$query->where('incomeFor', 'like', '%' . $search . '%')
|
||||
->orWhere('paymentType', 'like', '%' . $search . '%')
|
||||
->orWhere('amount', 'like', '%' . $search . '%')
|
||||
->orWhere('referenceNo', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', '%' . $search . '%'))
|
||||
->orWhereHas('payment_type', fn($q) => $q->where('name', 'like', '%' . $search . '%'))
|
||||
->orWhereHas('branch', fn($q) => $q->where('name', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$income_reports = $incomeQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.income.pdf', compact('income_reports', 'duration', 'filter_from_date', 'filter_to_date'),'incomes-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,19 @@
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateRangeTrait;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportLossProfitHistory;
|
||||
|
||||
class AcnooLossProfitHistoryController extends Controller
|
||||
{
|
||||
use DateFilterTrait;
|
||||
use DateFilterTrait, DateRangeTrait;
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
$perPage = request('per_page') ?? 20;
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
@@ -25,10 +27,17 @@ public function index(Request $request)
|
||||
}
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$salesQuery = DB::table('sales')
|
||||
->select(
|
||||
DB::raw('"saleDate"::date as date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END as profit_type
|
||||
"),
|
||||
DB::raw('SUM(actual_total_amount) as total_sales'),
|
||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||
)
|
||||
@@ -36,14 +45,24 @@ public function index(Request $request)
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"saleDate"::date'));
|
||||
->groupBy(
|
||||
DB::raw('"saleDate"::date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END
|
||||
")
|
||||
);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
$dailySales = $salesQuery->get();
|
||||
|
||||
$dailySales = $salesQuery->limit($perPage)->get();
|
||||
|
||||
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||
'type' => 'Sale',
|
||||
'date' => $sale->date,
|
||||
'profit_type' => $sale->profit_type,
|
||||
'total_sales' => $sale->total_sales,
|
||||
'total_incomes' => $sale->total_sale_income,
|
||||
]);
|
||||
@@ -60,7 +79,7 @@ public function index(Request $request)
|
||||
->groupBy(DB::raw('"incomeDate"::date'));
|
||||
|
||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
|
||||
$dailyIncomes = $incomeQuery->get();
|
||||
$dailyIncomes = $incomeQuery->limit($perPage)->get();
|
||||
|
||||
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
|
||||
'type' => 'Income',
|
||||
@@ -80,7 +99,10 @@ public function index(Request $request)
|
||||
$mergedIncomeSaleData->push($income);
|
||||
}
|
||||
|
||||
if ($sale = $sale_datas->firstWhere('date', $date)) {
|
||||
// multiple sale rows handle
|
||||
$salesOfDate = $sale_datas->where('date', $date);
|
||||
|
||||
foreach ($salesOfDate as $sale) {
|
||||
$mergedIncomeSaleData->push($sale);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +122,7 @@ public function index(Request $request)
|
||||
->groupBy(DB::raw('"date"::date'));
|
||||
|
||||
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||
$dailyPayrolls = $payrollQuery->get();
|
||||
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||
}
|
||||
|
||||
$expenseQuery = DB::table('expenses')
|
||||
@@ -115,7 +137,7 @@ public function index(Request $request)
|
||||
->groupBy(DB::raw('"expenseDate"::date'));
|
||||
|
||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
||||
$dailyExpenses = $expenseQuery->get();
|
||||
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||
|
||||
$mergedExpenseData = collect();
|
||||
$allExpenseDates = $dailyExpenses->pluck('date')
|
||||
@@ -148,34 +170,6 @@ public function index(Request $request)
|
||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||
|
||||
$allTimeSales = DB::table('sales')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('actual_total_amount');
|
||||
|
||||
$allTimeIncomes = DB::table('incomes')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount');
|
||||
|
||||
$allTimePayrolls = moduleCheck('HrmAddon')
|
||||
? DB::table('payrolls')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount')
|
||||
: 0;
|
||||
|
||||
$allTimeExpensesOnly = DB::table('expenses')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount');
|
||||
|
||||
$allTimeSaleProfit = DB::table('sales')->where('business_id', $businessId)->when($branchId, fn ($q) => $q->where('branch_id', $branchId))->sum('lossProfit');
|
||||
|
||||
$cardGrossProfit = $allTimeIncomes + $allTimeSaleProfit;
|
||||
$totalCardExpenses = $allTimePayrolls + $allTimeExpensesOnly;
|
||||
$cardNetProfit = $cardGrossProfit - $totalCardExpenses;
|
||||
|
||||
return view('business::loss-profit-histories.index', compact(
|
||||
'mergedIncomeSaleData',
|
||||
'mergedExpenseData',
|
||||
@@ -183,9 +177,9 @@ public function index(Request $request)
|
||||
'grossIncomeProfit',
|
||||
'totalExpenses',
|
||||
'netProfit',
|
||||
'cardGrossProfit',
|
||||
'totalCardExpenses',
|
||||
'cardNetProfit'
|
||||
'duration',
|
||||
'filter_from_date',
|
||||
'filter_to_date'
|
||||
));
|
||||
}
|
||||
|
||||
@@ -199,45 +193,71 @@ public function exportCsv()
|
||||
return Excel::download(new ExportLossProfitHistory, 'loss-profit-history.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
$perPage = request('per_page') ?? 20;
|
||||
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
// SALES
|
||||
$dailySales = DB::table('sales')
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$salesQuery = DB::table('sales')
|
||||
->select(
|
||||
DB::raw('"saleDate"::date as date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END as profit_type
|
||||
"),
|
||||
DB::raw('SUM(actual_total_amount) as total_sales'),
|
||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"saleDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(
|
||||
DB::raw('"saleDate"::date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END
|
||||
")
|
||||
);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
|
||||
$dailySales = $salesQuery->limit($perPage)->get();
|
||||
|
||||
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||
'type' => 'Sale',
|
||||
'date' => $sale->date,
|
||||
'profit_type' => $sale->profit_type,
|
||||
'total_sales' => $sale->total_sales,
|
||||
'total_incomes' => $sale->total_sale_income,
|
||||
]);
|
||||
|
||||
// INCOME
|
||||
$dailyIncomes = DB::table('incomes')
|
||||
$incomeQuery = DB::table('incomes')
|
||||
->select(
|
||||
DB::raw('"incomeDate"::date as date'),
|
||||
DB::raw('SUM(amount) as total_incomes')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"incomeDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"incomeDate"::date'));
|
||||
|
||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
|
||||
$dailyIncomes = $incomeQuery->limit($perPage)->get();
|
||||
|
||||
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
|
||||
'type' => 'Income',
|
||||
@@ -245,46 +265,66 @@ public function exportPdf()
|
||||
'total_incomes' => $income->total_incomes,
|
||||
]);
|
||||
|
||||
// MERGE SALE + INCOME
|
||||
$mergedIncomeSaleData = collect();
|
||||
$allDates = $dailySales->pluck('date')->merge($dailyIncomes->pluck('date'))->unique()->sort();
|
||||
$allDates = $dailySales->pluck('date')
|
||||
->merge($dailyIncomes->pluck('date'))
|
||||
->unique()
|
||||
->sort();
|
||||
|
||||
foreach ($allDates as $date) {
|
||||
|
||||
if ($income = $income_datas->firstWhere('date', $date)) {
|
||||
$mergedIncomeSaleData->push($income);
|
||||
}
|
||||
if ($sale = $sale_datas->firstWhere('date', $date)) {
|
||||
|
||||
// multiple sale rows handle
|
||||
$salesOfDate = $sale_datas->where('date', $date);
|
||||
|
||||
foreach ($salesOfDate as $sale) {
|
||||
$mergedIncomeSaleData->push($sale);
|
||||
}
|
||||
}
|
||||
|
||||
// PAYROLL
|
||||
$dailyPayrolls = collect();
|
||||
|
||||
if (moduleCheck('HrmAddon')) {
|
||||
$dailyPayrolls = DB::table('payrolls')
|
||||
$payrollQuery = DB::table('payrolls')
|
||||
->select(
|
||||
DB::raw('"date"::date as date'),
|
||||
DB::raw('SUM(amount) as total_payrolls')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"date"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"date"::date'));
|
||||
|
||||
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||
}
|
||||
|
||||
// EXPENSES
|
||||
$dailyExpenses = DB::table('expenses')
|
||||
$expenseQuery = DB::table('expenses')
|
||||
->select(
|
||||
DB::raw('"expenseDate"::date as date'),
|
||||
DB::raw('SUM(amount) as total_expenses_only')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->groupBy(DB::raw('"expenseDate"::date'))
|
||||
->get();
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"expenseDate"::date'));
|
||||
|
||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
||||
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||
|
||||
$mergedExpenseData = collect();
|
||||
$allExpenseDates = $dailyExpenses->pluck('date')->merge($dailyPayrolls->pluck('date'))->unique()->sort();
|
||||
$allExpenseDates = $dailyExpenses->pluck('date')
|
||||
->merge($dailyPayrolls->pluck('date'))
|
||||
->unique()
|
||||
->sort();
|
||||
|
||||
foreach ($allExpenseDates as $date) {
|
||||
|
||||
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
||||
$mergedExpenseData->push((object)[
|
||||
'type' => 'Expense',
|
||||
@@ -292,6 +332,7 @@ public function exportPdf()
|
||||
'total_expenses' => $expense->total_expenses_only,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
||||
$mergedExpenseData->push((object)[
|
||||
'type' => 'Payroll',
|
||||
@@ -301,9 +342,9 @@ public function exportPdf()
|
||||
}
|
||||
}
|
||||
|
||||
// SUMMARY
|
||||
$grossSaleProfit = $sale_datas->sum('total_sales');
|
||||
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
||||
|
||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||
|
||||
@@ -316,7 +357,10 @@ public function exportPdf()
|
||||
'grossSaleProfit',
|
||||
'grossIncomeProfit',
|
||||
'totalExpenses',
|
||||
'netProfit'
|
||||
'netProfit',
|
||||
'duration',
|
||||
'filter_to_date',
|
||||
'filter_from_date'
|
||||
),
|
||||
'loss-profit-history.pdf'
|
||||
);
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
use App\Traits\DateFilterTrait;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Traits\DateRangeTrait;
|
||||
|
||||
class AcnooLossProfitHistoryReportController extends Controller
|
||||
{
|
||||
use DateFilterTrait;
|
||||
use DateFilterTrait, DateRangeTrait;
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
@@ -22,10 +23,17 @@ public function index(Request $request)
|
||||
}
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$salesQuery = DB::table('sales')
|
||||
->select(
|
||||
DB::raw('"saleDate"::date as date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END as profit_type
|
||||
"),
|
||||
DB::raw('SUM(actual_total_amount) as total_sales'),
|
||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||
)
|
||||
@@ -33,14 +41,24 @@ public function index(Request $request)
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('"saleDate"::date'));
|
||||
->groupBy(
|
||||
DB::raw('"saleDate"::date'),
|
||||
DB::raw("
|
||||
CASE
|
||||
WHEN \"lossProfit\" >= 0 THEN 'positive'
|
||||
ELSE 'negative'
|
||||
END
|
||||
")
|
||||
);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
|
||||
$dailySales = $salesQuery->get();
|
||||
|
||||
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||
'type' => 'Sale',
|
||||
'date' => $sale->date,
|
||||
'profit_type' => $sale->profit_type,
|
||||
'total_sales' => $sale->total_sales,
|
||||
'total_incomes' => $sale->total_sale_income,
|
||||
]);
|
||||
@@ -77,7 +95,10 @@ public function index(Request $request)
|
||||
$mergedIncomeSaleData->push($income);
|
||||
}
|
||||
|
||||
if ($sale = $sale_datas->firstWhere('date', $date)) {
|
||||
// multiple sale rows handle
|
||||
$salesOfDate = $sale_datas->where('date', $date);
|
||||
|
||||
foreach ($salesOfDate as $sale) {
|
||||
$mergedIncomeSaleData->push($sale);
|
||||
}
|
||||
}
|
||||
@@ -87,14 +108,14 @@ public function index(Request $request)
|
||||
if (moduleCheck('HrmAddon')) {
|
||||
$payrollQuery = DB::table('payrolls')
|
||||
->select(
|
||||
DB::raw('DATE(date) as date'),
|
||||
DB::raw('"date"::date as date'),
|
||||
DB::raw('SUM(amount) as total_payrolls')
|
||||
)
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
)
|
||||
->groupBy(DB::raw('DATE(date)'));
|
||||
->groupBy(DB::raw('"date"::date'));
|
||||
|
||||
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||
$dailyPayrolls = $payrollQuery->get();
|
||||
@@ -145,34 +166,6 @@ public function index(Request $request)
|
||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||
|
||||
$allTimeSales = DB::table('sales')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('actual_total_amount');
|
||||
|
||||
$allTimeIncomes = DB::table('incomes')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount');
|
||||
|
||||
$allTimePayrolls = moduleCheck('HrmAddon')
|
||||
? DB::table('payrolls')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount')
|
||||
: 0;
|
||||
|
||||
$allTimeExpensesOnly = DB::table('expenses')
|
||||
->where('business_id', $businessId)
|
||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
||||
->sum('amount');
|
||||
|
||||
$allTimeSaleProfit = DB::table('sales')->where('business_id', $businessId)->when($branchId, fn ($q) => $q->where('branch_id', $branchId))->sum('lossProfit');
|
||||
|
||||
$cardGrossProfit = $allTimeIncomes + $allTimeSaleProfit;
|
||||
$totalCardExpenses = $allTimePayrolls + $allTimeExpensesOnly;
|
||||
$cardNetProfit = $cardGrossProfit - $totalCardExpenses;
|
||||
|
||||
return view('business::loss-profit-histories.index', compact(
|
||||
'mergedIncomeSaleData',
|
||||
'mergedExpenseData',
|
||||
@@ -180,9 +173,9 @@ public function index(Request $request)
|
||||
'grossIncomeProfit',
|
||||
'totalExpenses',
|
||||
'netProfit',
|
||||
'cardGrossProfit',
|
||||
'totalCardExpenses',
|
||||
'cardNetProfit'
|
||||
'duration',
|
||||
'filter_from_date',
|
||||
'filter_to_date'
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,18 @@
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Party;
|
||||
use App\Models\PaymentType;
|
||||
use App\Helpers\HasUploader;
|
||||
use App\Imports\PartyImport;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Events\MultiPaymentProcessed;
|
||||
// use App\Models\Country;
|
||||
// use App\Models\State;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class AcnooPartyController extends Controller
|
||||
{
|
||||
@@ -32,12 +39,12 @@ public function index(Request $request)
|
||||
$query = Party::where('business_id', $business_id)
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%')
|
||||
->orWhere('credit_limit', 'like', '%' . $search . '%')
|
||||
->orWhere('phone', 'like', '%' . $search . '%')
|
||||
->orWhere('type', 'like', '%' . $search . '%')
|
||||
->orWhere('address', 'like', '%' . $search . '%')
|
||||
->orWhere('due', 'like', '%' . $search . '%');
|
||||
$q->where('name', 'like', '%'.$search.'%')
|
||||
->orWhere('credit_limit', 'like', '%'.$search.'%')
|
||||
->orWhere('phone', 'like', '%'.$search.'%')
|
||||
->orWhere('type', 'like', '%'.$search.'%')
|
||||
->orWhere('address', 'like', '%'.$search.'%')
|
||||
->orWhere('due', 'like', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,11 +61,19 @@ public function index(Request $request)
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($party) use ($activeBranch) {
|
||||
$party_due = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->sum('dueAmount')
|
||||
: $party->sales_dues->sum('dueAmount');
|
||||
$originalDue = $party->getRawOriginal('due') ?? 0;
|
||||
$originalOpeningBalance = $party->opening_balance ?? 0;
|
||||
|
||||
$party->due = $party->branch_id === $activeBranch->id ? $party_due + $party->due : $party_due;
|
||||
$party_due = $party->type === 'Supplier'
|
||||
? $party->purchases_dues->where('branch_id', $activeBranch->id)->sum('dueAmount')
|
||||
: $party->sales_dues->where('branch_id', $activeBranch->id)->sum('dueAmount');
|
||||
|
||||
if ($party->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $party->opening_balance_type === 'due' ? $originalOpeningBalance : 0;
|
||||
$party->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$party->due = $party_due;
|
||||
}
|
||||
|
||||
return $party;
|
||||
})
|
||||
@@ -67,16 +82,20 @@ public function index(Request $request)
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::parties.datas', compact('parties'))->render()
|
||||
'data' => view('business::parties.datas', compact('parties'))->render(),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::parties.index', compact('parties', 'party_type'));
|
||||
}
|
||||
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('business::parties.create');
|
||||
$countries = [];
|
||||
$states = [];
|
||||
|
||||
return view('business::parties.create', compact('countries', 'states'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
@@ -88,13 +107,12 @@ public function store(Request $request)
|
||||
'email' => 'nullable|email',
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
||||
'address' => 'nullable|string|max:255',
|
||||
'tax_no' => 'nullable|string|max:255',
|
||||
'due' => 'nullable|numeric|min:0',
|
||||
'billing_address' => 'nullable|array',
|
||||
'billing_address.address' => 'nullable|string|max:255',
|
||||
'billing_address.city' => 'nullable|string|max:255',
|
||||
'billing_address.state' => 'nullable|string|max:255',
|
||||
'billing_address.zip_code' => 'nullable|string|max:20',
|
||||
'billing_address.country' => 'nullable|string|max:255',
|
||||
'shipping_address' => 'nullable|array',
|
||||
'shipping_address.address' => 'nullable|string|max:255',
|
||||
'shipping_address.city' => 'nullable|string|max:255',
|
||||
@@ -127,7 +145,10 @@ public function store(Request $request)
|
||||
public function edit($id)
|
||||
{
|
||||
$party = Party::where('business_id', auth()->user()->business_id)->findOrFail($id);
|
||||
return view('business::parties.edit', compact('party'));
|
||||
$countries = [];
|
||||
$states = [];
|
||||
|
||||
return view('business::parties.edit', compact('party', 'countries', 'states'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
@@ -141,13 +162,12 @@ public function update(Request $request, $id)
|
||||
'email' => 'nullable|email',
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
||||
'address' => 'nullable|string|max:255',
|
||||
'tax_no' => 'nullable|string|max:255',
|
||||
'due' => 'nullable|numeric|min:0',
|
||||
'billing_address' => 'nullable|array',
|
||||
'billing_address.address' => 'nullable|string|max:255',
|
||||
'billing_address.city' => 'nullable|string|max:255',
|
||||
'billing_address.state' => 'nullable|string|max:255',
|
||||
'billing_address.zip_code' => 'nullable|string|max:20',
|
||||
'billing_address.country' => 'nullable|string|max:255',
|
||||
'shipping_address' => 'nullable|array',
|
||||
'shipping_address.address' => 'nullable|string|max:255',
|
||||
'shipping_address.city' => 'nullable|string|max:255',
|
||||
@@ -210,6 +230,79 @@ public function update(Request $request, $id)
|
||||
]);
|
||||
}
|
||||
|
||||
public function advancePayment(string $id)
|
||||
{
|
||||
$party = Party::where('business_id', auth()->user()->business_id)->with(['sales_dues', 'purchases_dues'])->findOrFail($id);
|
||||
$payment_types = PaymentType::where('business_id', auth()->user()->business_id)->whereStatus(1)->latest()->get();
|
||||
|
||||
return view('business::parties.advance-payment', compact('party', 'payment_types'));
|
||||
}
|
||||
|
||||
public function advancePaymentStore(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'party_id' => 'required|exists:parties,id',
|
||||
'amount' => 'required|numeric|min:0.01',
|
||||
'date' => 'nullable|date',
|
||||
'note' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$party = Party::findOrFail($request->party_id);
|
||||
$payments = $request->payments ?? [];
|
||||
|
||||
if (isset($payments['main'])) {
|
||||
$mainPayment = $payments['main'];
|
||||
$mainPayment['amount'] = $request->amount ?? 0;
|
||||
$payments = [$mainPayment];
|
||||
}
|
||||
|
||||
// Only count actual received money (exclude cheque)
|
||||
$payAmount = collect($payments)
|
||||
->reject(fn($p) => strtolower($p['type'] ?? '') === 'cheque')
|
||||
->sum(fn($p) => $p['amount'] ?? 0);
|
||||
|
||||
if ($payAmount <= 0) {
|
||||
return response()->json([
|
||||
'message' => __('No valid payment amount received (cheques are pending).')
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Determine platform based on party type
|
||||
$platform = $party->type === 'Supplier' ? 'advance_pay' : 'advance_collect';
|
||||
|
||||
$party->increment('wallet', $payAmount);
|
||||
|
||||
event(new MultiPaymentProcessed(
|
||||
$payments,
|
||||
$party->id,
|
||||
$platform,
|
||||
$payAmount,
|
||||
$party->id,
|
||||
$request->date ?? now(),
|
||||
$request->note ?? null
|
||||
));
|
||||
|
||||
DB::commit();
|
||||
|
||||
$type = in_array($party->type, ['Retailer', 'Dealer', 'Wholesaler']) ? 'Customer' : ($party->type === 'Supplier' ? 'Supplier' : '');
|
||||
$message = $type === 'Supplier' ? __('Advance amount paid successfully.') : __('Advance amount collected successfully.');
|
||||
|
||||
return response()->json([
|
||||
'message' => $message,
|
||||
'redirect' => route('business.parties.index', ['type' => $type])
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
return response()->json([
|
||||
'error' => 'Transaction failed: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
$party = Party::findOrFail($id);
|
||||
@@ -266,4 +359,28 @@ public function deleteAll(Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
public function bulkStore(Request $request, $type)
|
||||
{
|
||||
$request->validate([
|
||||
'file' => 'required|file|mimes:xlsx,xls,csv'
|
||||
]);
|
||||
|
||||
$businessId = auth()->user()->business_id;
|
||||
$import = new PartyImport($businessId);
|
||||
|
||||
try {
|
||||
Excel::import($import, $request->file('file'));
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => __('Bulk upload successfully.'),
|
||||
'redirect' => route('business.parties.index', ['type' => $type])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Party;
|
||||
use App\Models\Sale;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportPartyLossProfit;
|
||||
@@ -14,12 +13,6 @@ class AcnooPartyLossProfitController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$sale = Sale::where('business_id', auth()->user()->business_id)->whereNotNull('party_id')->get();
|
||||
|
||||
$totalAmount = $sale->sum('totalAmount');
|
||||
$totalProfit = $sale->where('lossProfit', '>', 0)->sum('lossProfit') ?? 0;
|
||||
$totalLoss = $sale->where('lossProfit', '<', 0)->sum('lossProfit') ?? 0;
|
||||
|
||||
$parties = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
@@ -32,13 +25,20 @@ public function index(Request $request)
|
||||
->paginate($request->per_page ?? 20)
|
||||
->appends($request->query());
|
||||
|
||||
$totalSaleAmount = $parties->sum(fn($party) => $party->sales?->sum('totalAmount') ?? 0);
|
||||
$totalProfit = $parties->sum(fn($party) => $party->sales?->where('lossProfit', '>', 0)->sum('lossProfit') ?? 0);
|
||||
$totalLoss = $parties->sum(fn($party) => $party->sales?->where('lossProfit', '<', 0)->sum('lossProfit') ?? 0);
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::party-reports.loss-profit.datas', compact('parties'))->render()
|
||||
'data' => view('business::party-reports.loss-profit.datas', compact('parties', 'totalSaleAmount', 'totalProfit', 'totalLoss'))->render(),
|
||||
'totalSaleAmount' => currency_format($totalSaleAmount, currency: business_currency()),
|
||||
'totalProfit' => currency_format($totalProfit, currency: business_currency()),
|
||||
'totalLoss' => currency_format($totalLoss, currency: business_currency()),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::party-reports.loss-profit.index', compact('parties', 'totalAmount', 'totalProfit', 'totalLoss'));
|
||||
return view('business::party-reports.loss-profit.index', compact('parties', 'totalSaleAmount', 'totalProfit', 'totalLoss'));
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
@@ -51,18 +51,24 @@ public function exportCsv()
|
||||
return Excel::download(new ExportPartyLossProfit, 'party-loss-profit.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$parties = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->when($request->search, function ($query) use ($request) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::party-reports.loss-profit.pdf', compact('parties'),'party-loss-profit-report.pdf');
|
||||
}
|
||||
|
||||
public function view($id)
|
||||
public function view(string $id)
|
||||
{
|
||||
$party = Party::with('sales.details', 'sales.details.product')
|
||||
->where('id', $id)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Business\App\Exports\ExportProduct;
|
||||
use Modules\Business\App\Exports\ExportExpiredProduct;
|
||||
|
||||
class AcnooProductController extends Controller
|
||||
{
|
||||
@@ -67,12 +66,13 @@ public function index(Request $request)
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', "%{$search}%")
|
||||
->orWhere('productCode', 'like', "%{$search}%")
|
||||
->orWhere('hsn_code', 'like', "%{$search}%")
|
||||
->orWhere('productPurchasePrice', 'like', "%{$search}%")
|
||||
->orWhere('productSalePrice', 'like', "%{$search}%")
|
||||
->orWhere('product_type', 'like', "%{$search}%")
|
||||
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
||||
->orWhereHas('brand', fn($q) => $q->where('brandName', 'like', "%{$search}%"))
|
||||
->orWhereHas('unit', fn($q) => $q->where('unitName', 'like', "%{$search}%"));
|
||||
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
||||
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
|
||||
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
@@ -82,11 +82,11 @@ public function index(Request $request)
|
||||
$products->getCollection()->transform(function ($product) {
|
||||
if ($product->product_type === 'combo') {
|
||||
$product->total_stock = $product->combo_products->sum(
|
||||
fn($combo) => $combo->stock?->productStock ?? 0
|
||||
fn ($combo) => $combo->stock?->productStock ?? 0
|
||||
);
|
||||
|
||||
$product->total_cost = $product->combo_products->sum(
|
||||
fn($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
|
||||
fn ($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
|
||||
);
|
||||
|
||||
$product->combo_items = $product->combo_products->map(function ($combo) {
|
||||
@@ -114,7 +114,6 @@ public function index(Request $request)
|
||||
return view('business::products.index', compact('products'));
|
||||
}
|
||||
|
||||
|
||||
public function create()
|
||||
{
|
||||
$business_id = auth()->user()->business_id;
|
||||
@@ -122,7 +121,7 @@ public function create()
|
||||
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$product_id = (Product::where('business_id', $business_id)->count() ?? 0) + 1;
|
||||
$vats = Vat::where('business_id', $business_id)->latest()->get();
|
||||
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
|
||||
$code = str_pad($product_id, 4, '0', STR_PAD_LEFT);
|
||||
$product_models = ProductModel::where('business_id', $business_id)->latest()->get();
|
||||
$warehouses = Warehouse::where('business_id', $business_id)->latest()->get();
|
||||
@@ -130,9 +129,10 @@ public function create()
|
||||
$racks = Rack::where('business_id', $business_id)->latest()->get();
|
||||
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
|
||||
$profit_option = Option::where('key', 'business-settings')
|
||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
||||
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||
->get()
|
||||
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
|
||||
->firstWhere('value.business_id', $business_id)
|
||||
->value['product_profit_option'] ?? '';
|
||||
|
||||
return view('business::products.create', compact('categories', 'brands', 'units', 'code', 'vats', 'product_models', 'warehouses', 'racks', 'shelves', 'profit_option', 'variations'));
|
||||
}
|
||||
@@ -159,6 +159,7 @@ public function store(Request $request)
|
||||
return $query->where('business_id', $business_id);
|
||||
}),
|
||||
],
|
||||
'hsn_code' => 'nullable|string|max:255',
|
||||
'alert_qty' => 'nullable|numeric|min:0',
|
||||
'size' => 'nullable|string|max:255',
|
||||
'type' => 'nullable|string|max:255',
|
||||
@@ -206,13 +207,21 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
$vat = Vat::find($request->vat_id);
|
||||
$vat_rate = $vat->rate ?? 0;
|
||||
|
||||
$combo_tax_inclusive = $request->productSalePrice ?? 0;
|
||||
$combo_tax_exclusive = $request->productSalePrice ?? 0;
|
||||
|
||||
if ($request->vat_id && $request->product_type === 'combo') {
|
||||
$combo_tax_inclusive = number_format($combo_tax_exclusive * (1 + ($vat_rate / 100)), 3, '.', '');
|
||||
}
|
||||
|
||||
// Create the product
|
||||
$product = Product::create($request->only('productName', 'unit_id', 'brand_id', 'vat_id', 'vat_type', 'category_id', 'productCode', 'product_type', 'rack_id', 'shelf_id', 'model_id', 'variation_ids', 'warranty_guarantee_info') + [
|
||||
$product = Product::create($request->only('productName', 'unit_id', 'brand_id', 'vat_id', 'vat_type', 'category_id', 'productCode', 'hsn_code', 'product_type', 'rack_id', 'shelf_id', 'model_id', 'variation_ids', 'warranty_guarantee_info') + [
|
||||
'business_id' => $business_id,
|
||||
'alert_qty' => $request->alert_qty ?? 0,
|
||||
'is_displayed_in_pos' => $request->has('is_displayed_in_pos') ? 1 : 0,
|
||||
'has_serial' => $request->product_type == 'combo' ? 0 : ($request->has_serial ?? 0),
|
||||
'profit_percent' => $request->product_type == 'combo' ? $request->profit_percent ?? 0 : 0,
|
||||
'productSalePrice' => $request->product_type == 'combo' ? $request->productSalePrice ?? 0 : 0,
|
||||
'productSalePrice' => $request->product_type == 'combo' ? $combo_tax_inclusive : 0, // inclusive sales price
|
||||
'price_without_tax' => $request->product_type == 'combo' ? $combo_tax_exclusive : 0,
|
||||
'productPicture' => $request->productPicture ? $this->upload($request, 'productPicture') : NULL,
|
||||
]);
|
||||
|
||||
@@ -220,18 +229,15 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
if (in_array($request->product_type, ['single', 'variant']) && !empty($request->stocks)) {
|
||||
$stockData = [];
|
||||
foreach ($request->stocks as $stock) {
|
||||
$base_price = $stock['exclusive_price'] ?? 0;
|
||||
$purchasePrice = $request->vat_type === 'inclusive'
|
||||
? $base_price + ($base_price * $vat_rate / 100)
|
||||
: $base_price;
|
||||
|
||||
$stockData[] = [
|
||||
'business_id' => $business_id,
|
||||
'product_id' => $product->id,
|
||||
'exclusive_price' => $stock['exclusive_price'] ?? 0,
|
||||
'batch_no' => $stock['batch_no'] ?? null,
|
||||
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
||||
'productStock' => $stock['productStock'] ?? 0,
|
||||
'productPurchasePrice' => $purchasePrice,
|
||||
'productPurchasePrice' => $stock['inclusive_price'] ?? 0, // inclusive purchase price / net cost price
|
||||
'profit_percent' => $stock['profit_percent'] ?? 0,
|
||||
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
||||
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
||||
@@ -281,16 +287,17 @@ public function edit($id)
|
||||
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$vats = Vat::where('business_id', $business_id)->latest()->get();
|
||||
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
|
||||
$product_models = ProductModel::where('business_id', $business_id)->latest()->get();
|
||||
$warehouses = Warehouse::where('business_id', $business_id)->latest()->get();
|
||||
$racks = Rack::where('business_id', $business_id)->latest()->get();
|
||||
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
|
||||
$variations = Variation::where('business_id', auth()->user()->business_id)->where('status', 1)->get();
|
||||
$profit_option = Option::where('key', 'business-settings')
|
||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
||||
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||
->get()
|
||||
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
|
||||
->firstWhere('value.business_id', $business_id)
|
||||
->value['product_profit_option'] ?? '';
|
||||
|
||||
$product = Product::with([
|
||||
'stocks' => function ($query) {
|
||||
@@ -334,6 +341,7 @@ public function update(Request $request, $id)
|
||||
return $query->where('business_id', $business_id);
|
||||
}),
|
||||
],
|
||||
'hsn_code' => 'nullable|string|max:255',
|
||||
'alert_qty' => 'nullable|numeric|min:0',
|
||||
'size' => 'nullable|string|max:255',
|
||||
'type' => 'nullable|string|max:255',
|
||||
@@ -381,12 +389,21 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
$vat = Vat::find($request->vat_id);
|
||||
$vat_rate = $vat->rate ?? 0;
|
||||
|
||||
$combo_tax_exclusive = $request->productSalePrice ?? 0;
|
||||
$combo_tax_inclusive = $request->productSalePrice ?? 0;
|
||||
|
||||
if ($request->vat_id && $request->product_type === 'combo') {
|
||||
$combo_tax_inclusive = number_format($combo_tax_exclusive * (1 + ($vat_rate / 100)), 3, '.', '');
|
||||
}
|
||||
|
||||
// Update product
|
||||
$product->update($request->except(['productPicture', 'productPurchasePrice', 'productDealerPrice', 'productWholeSalePrice', 'alert_qty', 'stocks', 'vat_amount', 'profit_percent', 'is_displayed_in_pos']) + [
|
||||
$product->update($request->except(['productPicture', 'productPurchasePrice', 'productDealerPrice', 'productWholeSalePrice', 'alert_qty', 'stocks', 'vat_amount', 'profit_percent', 'productSalePrice', 'price_without_tax']) + [
|
||||
'business_id' => $business_id,
|
||||
'alert_qty' => $request->alert_qty ?? 0,
|
||||
'is_displayed_in_pos' => $request->has('is_displayed_in_pos') ? 1 : 0,
|
||||
'profit_percent' => $request->profit_percent ?? 0,
|
||||
'has_serial' => $request->product_type == 'combo' ? 0 : ($request->has_serial ?? 0),
|
||||
'profit_percent' => $request->product_type == 'combo' ? $request->profit_percent ?? 0 : 0,
|
||||
'productSalePrice' => $request->product_type == 'combo' ? $combo_tax_inclusive : 0, // inclusive sales price
|
||||
'price_without_tax' => $request->product_type == 'combo' ? $combo_tax_exclusive : 0,
|
||||
'productPicture' => $request->productPicture ? $this->upload($request, 'productPicture', $product->productPicture) : $product->productPicture,
|
||||
]);
|
||||
|
||||
@@ -406,22 +423,16 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
|
||||
// Insert or Update
|
||||
foreach ($request->stocks as $stock) {
|
||||
|
||||
$stockId = $stock['stock_id'] ?? null;
|
||||
|
||||
// Recalculate price
|
||||
$base_price = $stock['exclusive_price'] ?? 0;
|
||||
$purchasePrice = $request->vat_type === 'inclusive'
|
||||
? $base_price + ($base_price * $vat_rate / 100)
|
||||
: $base_price;
|
||||
|
||||
$payload = [
|
||||
'business_id' => $business_id,
|
||||
'product_id' => $product->id,
|
||||
'batch_no' => $stock['batch_no'] ?? null,
|
||||
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
||||
'productStock' => $stock['productStock'] ?? 0,
|
||||
'productPurchasePrice' => $purchasePrice,
|
||||
'exclusive_price' => $stock['exclusive_price'] ?? 0,
|
||||
'productPurchasePrice' =>$stock['inclusive_price'] ?? 0,
|
||||
'profit_percent' => $stock['profit_percent'] ?? 0,
|
||||
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
||||
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
||||
@@ -431,7 +442,7 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
'variation_data' => $stock['variation_data'] ?? null,
|
||||
'variant_name' => $stock['variant_name'] ?? null,
|
||||
'branch_id' => auth()->user()->branch_id ?? auth()->user()->active_branch_id,
|
||||
'serial_numbers' => $request->has_serial ? $stock['serial_numbers'] : null,
|
||||
'serial_numbers' => $request->has_serial ? $stock['serial_numbers'] ?? null : null,
|
||||
];
|
||||
|
||||
if ($stockId) {
|
||||
@@ -463,13 +474,12 @@ function ($attribute, $value, $fail) use ($request) {
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
return response()->json([
|
||||
'message' => __('Something went wrong.'),
|
||||
'error' => $e->getMessage(),
|
||||
'message' => $e->getMessage(),
|
||||
], 406);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
public function destroy(string $id)
|
||||
{
|
||||
$product = Product::findOrFail($id);
|
||||
if (file_exists($product->productPicture)) {
|
||||
@@ -501,26 +511,40 @@ public function deleteAll(Request $request)
|
||||
|
||||
public function getAllProduct()
|
||||
{
|
||||
$isTransfer = request()->is_transfer == 1;
|
||||
|
||||
$products = Product::with([
|
||||
'stocks' => function ($query) {
|
||||
'stocks' => function ($query) use ($isTransfer) {
|
||||
$query->where('productStock', '>', 0);
|
||||
if (!$isTransfer) {
|
||||
$query->where(function ($q) {
|
||||
$q->whereNull('serial_numbers')
|
||||
->orWhereJsonLength('serial_numbers', 0);
|
||||
});
|
||||
}
|
||||
},
|
||||
'category:id,categoryName',
|
||||
'unit:id,unitName',
|
||||
'stocks.warehouse:id,name',
|
||||
'vat:id,rate'
|
||||
'stocks.warehouse:id,name'
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->withSum(['stocks as total_stock' => function ($query) use ($isTransfer) {
|
||||
$query->where('productStock', '>', 0);
|
||||
if (!$isTransfer) {
|
||||
$query->where(function ($q) {
|
||||
$q->whereNull('serial_numbers')
|
||||
->orWhereJsonLength('serial_numbers', 0);
|
||||
});
|
||||
}
|
||||
}], 'productStock')
|
||||
->having('total_stock', '>', 0)
|
||||
->latest()
|
||||
->get()
|
||||
->where('total_stock', '>', 0)
|
||||
->values();
|
||||
->get();
|
||||
|
||||
return response()->json($products);
|
||||
}
|
||||
|
||||
public function getByCategory($category_id)
|
||||
public function getByCategory(string $category_id)
|
||||
{
|
||||
$products = Product::where('business_id', auth()->user()->business_id)->where('category_id', $category_id)->get();
|
||||
return response()->json($products);
|
||||
@@ -536,15 +560,63 @@ public function exportCsv()
|
||||
return Excel::download(new ExportProduct, 'product.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
$user = auth()->user();
|
||||
$search = $request->input('search');
|
||||
|
||||
$products = Product::query()
|
||||
->where('business_id', $user->business_id)
|
||||
->with([
|
||||
'stocks',
|
||||
'unit:id,unitName',
|
||||
'brand:id,brandName',
|
||||
'category:id,categoryName',
|
||||
'warehouse:id,name',
|
||||
'rack:id,name',
|
||||
'shelf:id,name',
|
||||
'combo_products.stock.product:id,productName'
|
||||
])
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->where(function ($query) {
|
||||
$query->where('product_type', '!=', 'combo')
|
||||
->orWhere(function ($q) {
|
||||
$q->where('product_type', 'combo')
|
||||
->whereHas('combo_products');
|
||||
});
|
||||
})
|
||||
->when($search, function ($q) use ($search) {
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productName', 'like', "%{$search}%")
|
||||
->orWhere('productCode', 'like', "%{$search}%")
|
||||
->orWhere('hsn_code', 'like', "%{$search}%")
|
||||
->orWhere('productPurchasePrice', 'like', "%{$search}%")
|
||||
->orWhere('productSalePrice', 'like', "%{$search}%")
|
||||
->orWhere('product_type', 'like', "%{$search}%")
|
||||
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
||||
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
|
||||
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::products.pdf', compact('products'), 'product-list.pdf');
|
||||
$products = $products->transform(function ($product) {
|
||||
if ($product->product_type === 'combo') {
|
||||
$product->total_stock = $product->combo_products->sum(
|
||||
fn ($combo) => $combo->stock?->productStock ?? 0
|
||||
);
|
||||
|
||||
$product->total_cost = $product->combo_products->sum(
|
||||
fn ($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
return $product;
|
||||
});
|
||||
|
||||
return PdfService::render('business::products.pdf', compact('products'),'product-list.pdf');
|
||||
}
|
||||
|
||||
public function expiredProduct(Request $request)
|
||||
@@ -561,6 +633,7 @@ public function expiredProduct(Request $request)
|
||||
$q->where('type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productName', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productCode', 'like', '%' . $request->search . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('unit', function ($q) use ($request) {
|
||||
@@ -586,103 +659,23 @@ public function expiredProduct(Request $request)
|
||||
return view('business::expired-products.index', compact('expired_products'));
|
||||
}
|
||||
|
||||
public function exportExpireProductExcel()
|
||||
{
|
||||
return Excel::download(new ExportExpiredProduct, 'expired-product.xlsx');
|
||||
}
|
||||
|
||||
public function exportExpireProductCsv()
|
||||
{
|
||||
return Excel::download(new ExportExpiredProduct, 'expired-product.csv');
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
public function show(string $id)
|
||||
{
|
||||
$business_id = auth()->user()->business_id;
|
||||
$product = Product::with('stocks')->where('business_id', $business_id)->findOrFail($id);
|
||||
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
$vats = Vat::where('business_id', $business_id)->latest()->get();
|
||||
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
|
||||
$profit_option = Option::where('key', 'business-settings')
|
||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
||||
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||
->get()
|
||||
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
|
||||
->firstWhere('value.business_id', $business_id)
|
||||
->value['product_profit_option'] ?? '';
|
||||
|
||||
return view('business::products.create-stock', compact('categories', 'brands', 'units', 'product', 'vats', 'profit_option'));
|
||||
}
|
||||
|
||||
public function CreateStock(Request $request, string $id)
|
||||
{
|
||||
$product = Product::findOrFail($id);
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
$request->validate([
|
||||
'vat_id' => 'nullable|exists:vats,id',
|
||||
'vat_type' => 'nullable|in:inclusive,exclusive',
|
||||
'productDealerPrice' => 'nullable|numeric|min:0',
|
||||
'exclusive_price' => 'required|numeric|min:0',
|
||||
'inclusive_price' => 'required|numeric|min:0',
|
||||
'profit_percent' => 'nullable|numeric',
|
||||
'productSalePrice' => 'required|numeric|min:0',
|
||||
'productWholeSalePrice' => 'nullable|numeric|min:0',
|
||||
'productStock' => 'required|numeric|min:0',
|
||||
'expire_date' => 'nullable|date',
|
||||
'batch_no' => 'nullable|string',
|
||||
'productCode' => [
|
||||
'nullable',
|
||||
'unique:products,productCode,' . $product->id . ',id,business_id,' . $business_id,
|
||||
],
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Calculate purchase price including VAT if applicable
|
||||
$vat = Vat::find($request->vat_id);
|
||||
$exclusive_price = $request->exclusive_price ?? 0;
|
||||
$vat_amount = ($exclusive_price * ($vat->rate ?? 0)) / 100;
|
||||
|
||||
// Determine final purchase price based on VAT type
|
||||
$purchase_price = $request->vat_type === 'exclusive' ? $exclusive_price : $exclusive_price + $vat_amount;
|
||||
|
||||
$batchNo = $request->batch_no ?? null;
|
||||
$stock = Stock::where(['batch_no' => $batchNo, 'product_id' => $product->id])->first();
|
||||
|
||||
if ($stock) {
|
||||
$stock->update($request->except('productStock', 'productPurchasePrice', 'productSalePrice', 'productDealerPrice', 'productWholeSalePrice') + [
|
||||
'productStock' => $stock->productStock + $request->productStock,
|
||||
'productPurchasePrice' => $purchase_price,
|
||||
'productSalePrice' => $request->productSalePrice,
|
||||
'productDealerPrice' => $request->productDealerPrice ?? 0,
|
||||
'productWholeSalePrice' => $request->productWholeSalePrice ?? 0,
|
||||
]);
|
||||
} else {
|
||||
Stock::create($request->except('productStock', 'productPurchasePrice', 'productSalePrice', 'productDealerPrice', 'productWholeSalePrice') + [
|
||||
'product_id' => $product->id,
|
||||
'branch_id' => auth()->user()->branch_id ?? auth()->user()->active_branch_id,
|
||||
'business_id' => $business_id,
|
||||
'productStock' => $request->productStock ?? 0,
|
||||
'productPurchasePrice' => $purchase_price,
|
||||
'productSalePrice' => $request->productSalePrice,
|
||||
'productDealerPrice' => $request->productDealerPrice ?? 0,
|
||||
'productWholeSalePrice' => $request->productWholeSalePrice ?? 0,
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Data saved successfully.'),
|
||||
'redirect' => route('business.products.index'),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'message' => __('Something went wrong.'),
|
||||
], 406);
|
||||
}
|
||||
}
|
||||
|
||||
public function getShelf(Request $request)
|
||||
{
|
||||
$rack = Rack::with('shelves')->find($request->rack_id);
|
||||
@@ -698,4 +691,53 @@ public function getProductVariants($product_id)
|
||||
|
||||
return response()->json($variant_stocks);
|
||||
}
|
||||
|
||||
public function checkSerial(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'product_id' => 'required|exists:products,id',
|
||||
'serial' => 'required|string'
|
||||
]);
|
||||
|
||||
$exists = Stock::where('business_id', auth()->user()->business_id)
|
||||
->where('product_id', $request->product_id)
|
||||
->whereNotNull('serial_numbers')
|
||||
->whereJsonContains('serial_numbers', $request->serial)
|
||||
->exists();
|
||||
|
||||
return response()->json([
|
||||
'exists' => $exists
|
||||
]);
|
||||
}
|
||||
|
||||
public function getProductSerials(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'product_id' => 'required|exists:products,id',
|
||||
'warehouse_id' => 'nullable|exists:warehouses,id',
|
||||
'batch_no' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
// Get all serial_numbers from stocks
|
||||
$serials = Stock::where('business_id', $business_id)
|
||||
->where('product_id', $request->product_id)
|
||||
->when($request->filled('batch_no'), function ($q) use ($request) {
|
||||
$q->where('batch_no', $request->batch_no);
|
||||
})
|
||||
->when($request->filled('warehouse_id'), function ($q) use ($request) {
|
||||
$q->where('warehouse_id', $request->warehouse_id);
|
||||
})
|
||||
->whereNotNull('serial_numbers')
|
||||
->pluck('serial_numbers')
|
||||
->flatten()
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'serials' => $serials
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,18 +18,15 @@ public function index(Request $request)
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
|
||||
$baseQuery = SaleDetails::query()
|
||||
->whereHas('product', fn ($q) =>
|
||||
$q->where('business_id', $user->business_id)
|
||||
)
|
||||
->whereHas('product', fn ($q) => $q->where('business_id', $user->business_id))
|
||||
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', fn ($q) =>
|
||||
$q->where('branch_id', $branchId)
|
||||
);
|
||||
$q->whereHas('sale', fn ($q) => $q->where('branch_id', $branchId));
|
||||
})
|
||||
->when($request->filled('search'), function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', "%{$request->search}%")
|
||||
->orWhere('productCode', 'like', "%{$request->search}%");
|
||||
->orWhere('productCode', 'like', "%{$request->search}%")
|
||||
->orWhere('hsn_code', 'like', "%{$request->search}%");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,7 +39,7 @@ public function index(Request $request)
|
||||
->sum('lossProfit');
|
||||
|
||||
$product_lossProfits = $baseQuery
|
||||
->with('product:id,productName,productCode')
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->select(
|
||||
'product_id',
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
|
||||
@@ -54,17 +51,13 @@ public function index(Request $request)
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view(
|
||||
'business::reports.product-loss-profit.datas',
|
||||
compact('product_lossProfits')
|
||||
)->render()
|
||||
'data' => view('business::reports.product-loss-profit.datas', compact('product_lossProfits'))->render(),
|
||||
'loss' => currency_format($loss, currency: business_currency()),
|
||||
'profit' => currency_format($profit, currency: business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
return view(
|
||||
'business::reports.product-loss-profit.index',
|
||||
compact('product_lossProfits', 'profit', 'loss')
|
||||
);
|
||||
return view('business::reports.product-loss-profit.index', compact('product_lossProfits', 'profit', 'loss'));
|
||||
}
|
||||
|
||||
|
||||
@@ -78,25 +71,35 @@ public function exportCsv()
|
||||
return Excel::download(new ExportProductLossProfit, 'product-lossProfit.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
|
||||
$user = auth()->user();
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
|
||||
$product_lossProfits = SaleDetails::with('product:id,productName,productCode')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
$baseQuery = SaleDetails::query()
|
||||
->whereHas('product', fn ($q) =>
|
||||
$q->where('business_id', $user->business_id)
|
||||
)
|
||||
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', fn ($q) => $q->where('branch_id', $branchId));
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
||||
$sale->where('branch_id', $branchId);
|
||||
->when($request->filled('search'), function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', "%{$request->search}%")
|
||||
->orWhere('productCode', 'like', "%{$request->search}%")
|
||||
->orWhere('hsn_code', 'like', "%{$request->search}%");
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
$product_lossProfits = $baseQuery
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->select(
|
||||
'product_id',
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) as profit'),
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) as loss')
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
|
||||
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) AS loss')
|
||||
)
|
||||
->groupBy('product_id')
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::reports.product-loss-profit.pdf', compact('product_lossProfits'), 'product-loss-profit-report.pdf');
|
||||
|
||||
@@ -51,7 +51,7 @@ public function index(Request $request)
|
||||
return view('business::product-purchase-history-report.index', compact('products', 'total_purchase_qty', 'total_sale_qty', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
}
|
||||
|
||||
public function show(Request $request, $id)
|
||||
public function show(Request $request, string $id)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
@@ -65,7 +65,7 @@ public function show(Request $request, $id)
|
||||
->whereHas('purchase', function ($purchase) use ($duration, $request) {
|
||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
})
|
||||
->with('purchase:id,invoiceNumber,purchaseDate')
|
||||
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
|
||||
|
||||
$purchaseDetailsQuery->when(filled($request->search), function ($q) use ($request) {
|
||||
@@ -76,6 +76,9 @@ public function show(Request $request, $id)
|
||||
->orWhereHas('purchase', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('purchaseDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('purchase.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -89,8 +92,7 @@ public function show(Request $request, $id)
|
||||
]);
|
||||
}
|
||||
|
||||
return view(
|
||||
'business::product-purchase-history-report.details',
|
||||
return view('business::product-purchase-history-report.details',
|
||||
compact('product', 'purchaseDetails', 'filter_from_date', 'filter_to_date', 'duration')
|
||||
);
|
||||
}
|
||||
@@ -108,9 +110,20 @@ public function exportCsv()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
||||
$products = $productQuery->get();
|
||||
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('purchaseDetails.purchase', function ($purchase) use ($duration, $request) {
|
||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
$productQuery->when($request->search, function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
|
||||
$products = $productQuery->limit($request->per_page ?? 20)->get();
|
||||
|
||||
$total_purchase_qty = $products->sum(function ($product) {
|
||||
return $product->purchaseDetails->sum('quantities');
|
||||
@@ -120,31 +133,54 @@ public function exportPdf(Request $request)
|
||||
return $product->saleDetails->sum('quantities');
|
||||
});
|
||||
|
||||
return PdfService::render('business::product-purchase-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty'), 'product-purchase-history.pdf');
|
||||
return PdfService::render('business::product-purchase-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-history.pdf');
|
||||
}
|
||||
|
||||
public function exportDetailExcel($id)
|
||||
public function exportDetailExcel(string $id)
|
||||
{
|
||||
return Excel::download(new ExportProductPurchaseHistoryDetailReport($id), 'product-purchase-history-details.xlsx');
|
||||
}
|
||||
|
||||
public function exportDetailCsv($id)
|
||||
public function exportDetailCsv(string $id)
|
||||
{
|
||||
return Excel::download(new ExportProductPurchaseHistoryDetailReport($id), 'product-purchase-history-details.csv');
|
||||
}
|
||||
|
||||
public function exportDetailPdf(Request $request, $id)
|
||||
public function exportDetailPdf(Request $request, string $id)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$product = Product::select('id', 'business_id', 'productName')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->findOrFail($id);
|
||||
|
||||
$purchaseDetailsQuery = $product->purchaseDetails()
|
||||
->with('purchase:id,invoiceNumber,purchaseDate')
|
||||
->whereHas('purchase', function ($purchase) use ($duration, $request) {
|
||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
})
|
||||
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
|
||||
|
||||
$purchaseDetails = $purchaseDetailsQuery->get();
|
||||
$purchaseDetailsQuery->when(filled($request->search), function ($q) use ($request) {
|
||||
$search = $request->search;
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('productPurchasePrice', 'like', "%{$search}%")
|
||||
->orWhere('quantities', 'like', "%{$search}%")
|
||||
->orWhereHas('purchase', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('purchaseDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('purchase.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return PdfService::render('business::product-purchase-history-report.pdf-detail', compact('product', 'purchaseDetails'), 'product-purchase-history-details.pdf');
|
||||
$purchaseDetails = $purchaseDetailsQuery->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::product-purchase-history-report.pdf-detail', compact('product', 'purchaseDetails', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-history-details.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,16 @@ public function index(Request $request)
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$query->whereHas('purchase', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
$query->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
@@ -34,13 +43,6 @@ public function index(Request $request)
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$query->whereHas('purchase', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
$product_purchases = $query->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
@@ -64,14 +66,38 @@ public function exportCsv()
|
||||
return Excel::download(new ExportProductPurchaseReport, 'product-purchase.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$product_purchases = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
$query = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
|
||||
->whereHas('purchase', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
})
|
||||
->get();
|
||||
});
|
||||
|
||||
return PdfService::render('business::reports.product-purchase.pdf', compact('product_purchases'),'product-purchase-report.pdf');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$query->whereHas('purchase', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
$query->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('purchase', function ($q) use ($request) {
|
||||
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhere('purchaseDate', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('purchase.party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$product_purchases = $query->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.product-purchase.pdf', compact('product_purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public function index(Request $request)
|
||||
return view('business::product-sale-history-report.index', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
}
|
||||
|
||||
public function show(Request $request, $id)
|
||||
public function show(Request $request, string $id)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
@@ -82,6 +82,9 @@ public function show(Request $request, $id)
|
||||
->orWhereHas('sale', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('saleDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -111,9 +114,20 @@ public function exportCsv()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
||||
$products = $productQuery->get();
|
||||
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
|
||||
->where('business_id', $businessId)
|
||||
->whereHas('saleDetails.sale', function ($sale) use ($duration, $request) {
|
||||
$this->applyDateFilter($sale, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
$productQuery->when($request->search, function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
|
||||
$products = $productQuery->limit($request->per_page ?? 20)->get();
|
||||
|
||||
$total_single_sale_price = $products->sum(function ($product) {
|
||||
return $product->saleDetails->sum('price');
|
||||
@@ -129,31 +143,54 @@ public function exportPdf(Request $request)
|
||||
return $product->saleDetails->sum('quantities');
|
||||
});
|
||||
|
||||
return PdfService::render('business::product-sale-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price'), 'product-sale-history.pdf');
|
||||
return PdfService::render('business::product-sale-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price', 'filter_from_date', 'filter_to_date', 'duration'), 'product-sale-history.pdf');
|
||||
}
|
||||
|
||||
public function exportDetailExcel($id)
|
||||
public function exportDetailExcel(string $id)
|
||||
{
|
||||
return Excel::download(new ExportProductSaleHistoryDetailReport($id), 'product-sale-history-details.xlsx');
|
||||
}
|
||||
|
||||
public function exportDetailCsv($id)
|
||||
public function exportDetailCsv(string $id)
|
||||
{
|
||||
return Excel::download(new ExportProductSaleHistoryDetailReport($id), 'product-sale-history-details.csv');
|
||||
}
|
||||
|
||||
public function exportDetailPdf(Request $request, $id)
|
||||
public function exportDetailPdf(Request $request, string $id)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$product = Product::select('id', 'business_id', 'productName')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('business_id', $businessId)
|
||||
->findOrFail($id);
|
||||
|
||||
$saleDetailsQuery = $product->saleDetails()
|
||||
->whereHas('sale', function ($sale) use ($duration, $request) {
|
||||
$this->applyDateFilter($sale, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
})
|
||||
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
|
||||
|
||||
$saleDetails = $saleDetailsQuery->get();
|
||||
$saleDetailsQuery->when(filled($request->search), function ($q) use ($request) {
|
||||
$search = $request->search;
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('price', 'like', "%{$search}%")
|
||||
->orWhere('quantities', 'like', "%{$search}%")
|
||||
->orWhereHas('sale', function ($q) use ($search) {
|
||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||
->orWhere('saleDate', 'like', "%{$search}%");
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return PdfService::render('business::product-sale-history-report.pdf-detail', compact('product', 'saleDetails'), 'product-sale-history-details.pdf');
|
||||
$saleDetails = $saleDetailsQuery->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::product-sale-history-report.pdf-detail', compact('product', 'saleDetails', 'duration', 'filter_from_date', 'filter_to_date'), 'product-sale-history-details.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Sale;
|
||||
use App\Models\SaleDetails;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use App\Traits\DateRangeTrait;
|
||||
@@ -17,26 +17,34 @@ class AcnooProductSaleReportController extends Controller
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
$query->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhere('saleDate', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('details.product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||
->whereHas('sale', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($query, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
$query->whereHas('sale', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
$query->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('sale', function ($q) use ($request) {
|
||||
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhere('saleDate', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$product_sales = $query->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
|
||||
@@ -59,13 +67,39 @@ public function exportCsv()
|
||||
return Excel::download(new ExportProductSaleReport, 'product-sales.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$product_sales = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||
->whereHas('sale', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
|
||||
return PdfService::render('business::reports.product-sale.pdf', compact('product_sales'),'product-sale-report.pdf');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$query->whereHas('sale', function ($q) use ($duration, $request) {
|
||||
$this->applyDateFilter($q, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
$query->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('sale', function ($q) use ($request) {
|
||||
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhere('saleDate', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('sale.party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$product_sales = $query->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.product-sale.pdf', compact('product_sales', 'duration', 'filter_from_date', 'filter_to_date'), 'product-sale-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,10 +26,6 @@ public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$total_purchase = Purchase::where('business_id', $businessId)
|
||||
->whereDate('purchaseDate', Carbon::today())
|
||||
->sum('totalAmount');
|
||||
|
||||
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
@@ -89,11 +85,38 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$purchases = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::reports.purchase.pdf', compact('purchases'), 'purchases-report.pdf');
|
||||
$purchasesQuery->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$purchasesQuery->where(function ($query) use ($request) {
|
||||
$query->where('paymentType', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.purchase.pdf', compact('purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'purchases-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
use App\Models\Purchase;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PurchaseReturnDetail;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use App\Traits\DateRangeTrait;
|
||||
@@ -26,12 +25,6 @@ public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$total_purchase_return = PurchaseReturnDetail::whereHas('purchaseReturn', function ($query) use ($businessId) {
|
||||
$query->whereHas('purchase', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
});
|
||||
})->sum('return_amount');
|
||||
|
||||
$purchasesQuery = Purchase::with([
|
||||
'user:id,name',
|
||||
'branch:id,name',
|
||||
@@ -54,7 +47,9 @@ public function index(Request $request)
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration, $request) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
@@ -69,17 +64,19 @@ public function index(Request $request)
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate Total Purchase Return Amount in the Selected Date Range
|
||||
$total_purchase_return = PurchaseReturnDetail::whereHas('purchaseReturn', function ($query) use ($businessId) {
|
||||
$query->whereHas('purchase', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
});
|
||||
})->sum('return_amount');
|
||||
|
||||
// Pagination
|
||||
$perPage = $request->input('per_page', 20);
|
||||
$purchases = $purchasesQuery->latest()->paginate($perPage)->appends($request->query());
|
||||
|
||||
$total_purchase_return = (clone $purchasesQuery)
|
||||
->with('purchaseReturns.details')
|
||||
->get()
|
||||
->sum(function ($sale) {
|
||||
return $sale->purchaseReturns->sum(function ($return) {
|
||||
return $return->details->sum('return_amount');
|
||||
});
|
||||
});
|
||||
|
||||
// Handle AJAX Request
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
@@ -105,7 +102,7 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$purchases = Purchase::with([
|
||||
$purchasesQuery = Purchase::with([
|
||||
'user:id,name',
|
||||
'branch:id,name',
|
||||
'party:id,name,email,phone,type',
|
||||
@@ -117,10 +114,35 @@ public function exportPdf(Request $request)
|
||||
}
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereHas('purchaseReturns')
|
||||
->latest()
|
||||
->get();
|
||||
->whereHas('purchaseReturns');
|
||||
|
||||
return PdfService::render('business::reports.purchase-return.pdf', compact('purchases'), 'purchase-return-report.pdf');
|
||||
$purchasesQuery->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration, $request) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$purchasesQuery->where(function ($query) use ($request) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.purchase-return.pdf', compact('purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'purchase-return-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@
|
||||
use App\Models\Sale;
|
||||
use App\Models\Branch;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
@@ -26,11 +25,8 @@ public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$total_sale = Sale::where('business_id', $businessId)
|
||||
->whereDate('saleDate', Carbon::today())
|
||||
->sum('totalAmount');
|
||||
|
||||
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', $businessId);
|
||||
|
||||
$salesQuery->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
});
|
||||
@@ -88,10 +84,38 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||
->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::reports.sales.pdf', compact('sales'),'sales-report.pdf');
|
||||
$salesQuery->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
});
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$salesQuery->where(function ($query) use ($request) {
|
||||
$query->where('paymentType', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$sales = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.sales.pdf', compact('sales', 'duration', 'filter_from_date', 'filter_to_date'),'sales-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
use App\Models\Sale;
|
||||
use App\Models\Branch;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\SaleReturnDetails;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
@@ -24,12 +23,6 @@ public function __construct()
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$total_sale_return = SaleReturnDetails::whereHas('saleReturn', function ($query) {
|
||||
$query->whereHas('sale', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
});
|
||||
})->sum('return_amount');
|
||||
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$salesQuery = Sale::with([
|
||||
@@ -44,9 +37,7 @@ public function index(Request $request)
|
||||
->with('branch:id,name');
|
||||
}
|
||||
])
|
||||
|
||||
->where('business_id', $businessId)
|
||||
|
||||
->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
})->whereHas('saleReturns');
|
||||
@@ -55,7 +46,9 @@ public function index(Request $request)
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
$salesQuery->whereHas('saleReturns', function ($query) use ($request, $duration) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
@@ -70,15 +63,18 @@ public function index(Request $request)
|
||||
});
|
||||
}
|
||||
|
||||
$total_sale_return = SaleReturnDetails::whereHas('saleReturn', function ($query) use ($businessId) {
|
||||
$query->whereHas('sale', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
});
|
||||
})->sum('return_amount');
|
||||
|
||||
$perPage = $request->input('per_page', 20);
|
||||
$sales = $salesQuery->latest()->paginate($perPage)->appends($request->query());
|
||||
|
||||
$total_sale_return = (clone $salesQuery)
|
||||
->with('saleReturns.details')
|
||||
->get()
|
||||
->sum(function ($sale) {
|
||||
return $sale->saleReturns->sum(function ($return) {
|
||||
return $return->details->sum('return_amount');
|
||||
});
|
||||
});
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::reports.sales-return.datas', compact('sales', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
||||
@@ -103,7 +99,7 @@ public function exportCsv()
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$sales = Sale::with([
|
||||
$salesQuery = Sale::with([
|
||||
'user:id,name',
|
||||
'party:id,name',
|
||||
'branch:id,name',
|
||||
@@ -116,10 +112,33 @@ public function exportPdf(Request $request)
|
||||
}
|
||||
])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->whereHas('saleReturns')
|
||||
->latest()
|
||||
->get();
|
||||
->when($request->branch_id, function ($q) use ($request) {
|
||||
$q->where('branch_id', $request->branch_id);
|
||||
})->whereHas('saleReturns');
|
||||
|
||||
return PdfService::render('business::reports.sales-return.pdf', compact('sales'), 'sales-return-report.pdf');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$salesQuery->whereHas('saleReturns', function ($query) use ($duration, $request) {
|
||||
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
|
||||
});
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$salesQuery->where(function ($query) use ($request) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('branch', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$sales = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.sales-return.pdf', compact('sales', 'duration', 'filter_from_date', 'filter_to_date'), 'sales-return-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Option;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\ProductSetting;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Option;
|
||||
use App\Models\ProductSetting;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
@@ -14,23 +14,29 @@ class AcnooSettingsManagerController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$invoiceSettingKey = 'invoice_setting_' . $businessId;
|
||||
$invoiceSettingKey = 'invoice_setting_'.$businessId;
|
||||
$invoice_setting = Option::where('key', $invoiceSettingKey)->first();
|
||||
$product_setting = ProductSetting::where('business_id', auth()->user()->business_id)->first();
|
||||
|
||||
$currencySettingKey = 'currency_setting_' . $businessId;
|
||||
$currencySettingKey = 'currency_setting_'.$businessId;
|
||||
$currency_setting = Option::where('key', $currencySettingKey)->first();
|
||||
|
||||
return view('business::manage-settings.index', compact('invoice_setting', 'product_setting', 'currency_setting'));
|
||||
$invoiceImgaeSettingKey = 'invoice_setting_images';
|
||||
$invoice_setting_image = Option::where('key', $invoiceImgaeSettingKey)->first();
|
||||
|
||||
$themesettingkey = 'theme_setting_'.$businessId;
|
||||
$theme_settings = Option::where('key', $themesettingkey)->first()?->value ?? [];
|
||||
|
||||
return view('business::manage-settings.index', compact('invoice_setting', 'theme_settings', 'product_setting', 'currency_setting', 'invoice_setting_image'));
|
||||
}
|
||||
|
||||
public function updateInvoice(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'invoice_size' => 'required|string|max:100|in:a4,3_inch_80mm',
|
||||
'invoice_size' => 'required|string|max:100|in:a4,3_inch_80mm,standard_a4',
|
||||
]);
|
||||
|
||||
$key = 'invoice_setting_' . auth()->user()->business_id;
|
||||
$key = 'invoice_setting_'.auth()->user()->business_id;
|
||||
|
||||
Option::updateOrCreate(
|
||||
['key' => $key],
|
||||
@@ -45,8 +51,8 @@ public function updateInvoice(Request $request)
|
||||
public function updateProductSetting(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'show_product_price' => 'nullable|boolean',
|
||||
'show_product_code' => 'nullable|boolean',
|
||||
'show_hsn_code' => 'nullable|boolean',
|
||||
'show_product_stock' => 'nullable|boolean',
|
||||
'show_product_sale_price' => 'nullable|boolean',
|
||||
'show_product_dealer_price' => 'nullable|boolean',
|
||||
@@ -94,9 +100,9 @@ public function updateProductSetting(Request $request)
|
||||
]);
|
||||
|
||||
if (
|
||||
!$request->boolean('show_product_type_single') &&
|
||||
!$request->boolean('show_product_type_variant') &&
|
||||
!$request->boolean('show_product_type_combo')
|
||||
! $request->boolean('show_product_type_single') &&
|
||||
! $request->boolean('show_product_type_variant') &&
|
||||
! $request->boolean('show_product_type_combo')
|
||||
) {
|
||||
throw ValidationException::withMessages([
|
||||
'product_type' => ['At least one product type must be selected: Single, Variant or Combo.'],
|
||||
@@ -133,7 +139,7 @@ public function updateProductSetting(Request $request)
|
||||
['modules' => $modules]
|
||||
);
|
||||
|
||||
Cache::forget('product_setting_' . $businessId);
|
||||
Cache::forget('product_setting_'.$businessId);
|
||||
|
||||
return response()->json(__('Product setting updated successfully.'));
|
||||
}
|
||||
@@ -144,7 +150,7 @@ public function updateCurrency(Request $request)
|
||||
'currency' => 'required|string|max:100|in:us,european',
|
||||
]);
|
||||
|
||||
$key = 'currency_setting_' . auth()->user()->business_id;
|
||||
$key = 'currency_setting_'.auth()->user()->business_id;
|
||||
|
||||
Option::updateOrCreate(
|
||||
['key' => $key],
|
||||
@@ -174,13 +180,39 @@ public function updateSerial(Request $request)
|
||||
$modules['show_serial'] = $request->boolean('show_serial') ? '1' : '0';
|
||||
|
||||
$setting->update([
|
||||
'modules' => $modules
|
||||
'modules' => $modules,
|
||||
]);
|
||||
|
||||
Cache::forget('product_setting_' . $businessId);
|
||||
Cache::forget('product_setting_'.$businessId);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Serial setting updated successfully.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateTheme(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'primary_color' => 'nullable|string|max:100',
|
||||
'secondary_color' => 'nullable|string|max:100',
|
||||
'sidebar_color' => 'nullable|string|max:100',
|
||||
'accent_color' => 'nullable|string|max:100',
|
||||
]);
|
||||
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$setting = Option::updateOrCreate(
|
||||
['key' => 'theme_setting_'.$businessId],
|
||||
['value' => [
|
||||
'primary_color' => $request->primary_color,
|
||||
'secondary_color' => $request->secondary_color,
|
||||
'sidebar_color' => $request->sidebar_color,
|
||||
'accent_color' => $request->accent_color,
|
||||
]]
|
||||
);
|
||||
|
||||
Cache::forget('theme_setting_'.$businessId);
|
||||
|
||||
return response()->json(__('Theme updated successfully.'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Stock;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Modules\Business\App\Exports\ExportCurrentStock;
|
||||
|
||||
class AcnooStockController extends Controller
|
||||
@@ -25,81 +22,130 @@ public function index()
|
||||
$search_term = request('search');
|
||||
$per_page = request('per_page', 20);
|
||||
|
||||
// Base query
|
||||
$query = Product::with('stocks','warehouse:id,name', 'rack:id,name', 'shelf:id,name')->where('product_type', '!=', 'combo')->where('business_id', $businessId);
|
||||
$query = Product::with('stocks', 'category:id,categoryName')
|
||||
->where('product_type', '!=', 'combo')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
// For Low Stock view - apply search if search term exists
|
||||
if ($alert_qty_filter) {
|
||||
// Apply search filter if search term exists
|
||||
if ($search_term) {
|
||||
$query->where(function ($q) use ($search_term) {
|
||||
$q->where('productName', 'like', '%' . $search_term . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $search_term . '%')
|
||||
->orWhere('productSalePrice', 'like', '%' . $search_term . '%');
|
||||
->orWhere('productCode', 'like', '%' . $search_term . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
|
||||
->orWhereHas('category', function ($q) use ($search_term) {
|
||||
$q->where('categoryName', 'like', '%' . $search_term . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Get all products (with search applied if any) then filter for low stock
|
||||
$allProducts = $query->latest()->get();
|
||||
$filteredProducts = $allProducts->filter(function ($product) {
|
||||
$totalStock = $product->stocks->sum('productStock');
|
||||
return $totalStock <= $product->alert_qty;
|
||||
});
|
||||
if ($alert_qty_filter) {
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->whereRaw('(SELECT COALESCE(SUM("productStock"),0) FROM stocks WHERE stocks.product_id = products.id) <= products.alert_qty')
|
||||
->latest()
|
||||
->paginate($per_page)
|
||||
->appends(request()->query());
|
||||
|
||||
// Manual pagination for filtered collection
|
||||
$currentPage = request('page', 1);
|
||||
$products = new LengthAwarePaginator(
|
||||
$filteredProducts->forPage($currentPage, $per_page),
|
||||
$filteredProducts->count(),
|
||||
$per_page,
|
||||
$currentPage,
|
||||
['path' => request()->url(), 'query' => request()->query()]
|
||||
);
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
// Calculate totals for low stock view
|
||||
$total_stock_value = $filteredProducts->sum(function ($product) {
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
$total_qty = $filteredProducts->sum(function ($product) {
|
||||
return $product->stocks->sum('productStock');
|
||||
});
|
||||
} else {
|
||||
// For All Stock view - NO search, just regular pagination
|
||||
$products = $query->latest()->paginate($per_page)->appends(request()->query());
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->latest()
|
||||
->paginate($per_page)
|
||||
->appends(request()->query());
|
||||
|
||||
// Calculate totals for all stock
|
||||
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})->sum(DB::raw('"productPurchasePrice" * "productStock"'));
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})->sum('productStock');
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Handle AJAX request
|
||||
if (request()->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::stocks.datas', compact('products', 'total_stock_value', 'total_qty'))->render()
|
||||
'data' => view('business::stocks.datas', compact('products', 'total_stock_value', 'total_stock_qty'))->render(),
|
||||
'total_stock_qty' => $total_stock_qty,
|
||||
'total_stock_value' => currency_format($total_stock_value, currency: business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::stocks.index', [
|
||||
'products' => $products,
|
||||
'total_stock_value' => $total_stock_value,
|
||||
'total_qty' => $total_qty,
|
||||
'total_stock_qty' => $total_stock_qty,
|
||||
]);
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
{
|
||||
return Excel::download(new ExportCurrentStock, 'current-stock.xlsx');
|
||||
return Excel::download(new ExportCurrentStock, 'stock-list.xlsx');
|
||||
}
|
||||
|
||||
public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportCurrentStock, 'current-stock.csv');
|
||||
return Excel::download(new ExportCurrentStock, 'stock-list.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$alert_qty_filter = request('alert_qty');
|
||||
$search_term = request('search');
|
||||
$per_page = request('per_page', 20);
|
||||
|
||||
$query = Product::with('stocks', 'category:id,categoryName')
|
||||
->where('product_type', '!=', 'combo')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
if ($search_term) {
|
||||
$query->where(function ($q) use ($search_term) {
|
||||
$q->where('productName', 'like', '%' . $search_term . '%')
|
||||
->orWhere('productCode', 'like', '%' . $search_term . '%')
|
||||
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
|
||||
->orWhereHas('category', function ($q) use ($search_term) {
|
||||
$q->where('categoryName', 'like', '%' . $search_term . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if ($alert_qty_filter) {
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->havingRaw('total_stock <= products.alert_qty')
|
||||
->latest()
|
||||
->limit($per_page)
|
||||
->get();
|
||||
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$products = $query
|
||||
->withSum('stocks as total_stock', 'productStock')
|
||||
->latest()
|
||||
->limit($per_page)
|
||||
->get();
|
||||
|
||||
$total_stock_qty = $products->sum('total_stock');
|
||||
|
||||
$total_stock_value = $products->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return PdfService::render('business::stocks.pdf', compact('products', 'total_stock_qty', 'total_stock_value'), 'stock-list.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Stock;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
@@ -22,31 +20,42 @@ public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})->sum(DB::raw('"productPurchasePrice" * "productStock"'));
|
||||
$productsQuery = Product::with(['stocks' => function ($q) {
|
||||
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
|
||||
}])
|
||||
->where('business_id', $businessId)
|
||||
->where('product_type', '!=', 'combo');
|
||||
|
||||
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})->sum('productStock');
|
||||
|
||||
$stock_reports = Product::with('stocks')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', '!=', 'combo')
|
||||
->when($request->search, function ($query) use ($request) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
if ($request->search) {
|
||||
$productsQuery->where(function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%')
|
||||
->orwhere('productSalePrice', 'like', '%' . $request->search . '%')
|
||||
->orwhere('productPurchasePrice', 'like', '%' . $request->search . '%');
|
||||
->orWhereHas('stocks', function ($stock) use ($request) {
|
||||
$stock->where('productSalePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->withSum('stocks', 'productStock')
|
||||
});
|
||||
}
|
||||
|
||||
$stock_reports = $productsQuery
|
||||
->latest()
|
||||
->paginate($request->per_page ?? 20)->appends($request->query());
|
||||
->paginate($request->per_page ?? 20)
|
||||
->appends($request->query());
|
||||
|
||||
$total_qty = $stock_reports->getCollection()->sum(function ($product) {
|
||||
return $product->stocks->sum('productStock');
|
||||
});
|
||||
|
||||
$total_stock_value = $stock_reports->getCollection()->sum(function ($product) {
|
||||
return $product->stocks->sum(function ($stock) {
|
||||
return $stock->productStock * $stock->productPurchasePrice;
|
||||
});
|
||||
});
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'data' => view('business::reports.stocks.datas', compact('stock_reports'))->render()
|
||||
'data' => view('business::reports.stocks.datas', compact('stock_reports'))->render(),
|
||||
'total_stock_value' => currency_format($total_stock_value, currency: business_currency()),
|
||||
'total_qty' => $total_qty
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -63,21 +72,29 @@ public function exportCsv()
|
||||
return Excel::download(new ExportCurrentStockReport, 'current-stock-report.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$query = Product::with('stocks')
|
||||
$productsQuery = Product::with(['stocks' => function ($q) {
|
||||
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
|
||||
}])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('product_type', '!=', 'combo');
|
||||
|
||||
if (request('alert_qty')) {
|
||||
$stock_reports = $query->get()->filter(function ($product) {
|
||||
$totalStock = $product->stocks->sum('productStock');
|
||||
return $totalStock <= $product->alert_qty;
|
||||
if ($request->search) {
|
||||
$productsQuery->where(function ($q) use ($request) {
|
||||
$q->where('productName', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('stocks', function ($stock) use ($request) {
|
||||
$stock->where('productSalePrice', 'like', '%' . $request->search . '%')
|
||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$stock_reports = $query->latest()->get();
|
||||
}
|
||||
|
||||
$stock_reports = $productsQuery
|
||||
->latest()
|
||||
->limit($request->per_page ?? 20)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::reports.stocks.pdf', compact('stock_reports'), 'stock-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +72,42 @@ public function exportCsv()
|
||||
return Excel::download(new ExportSubscription, 'subscribers.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$subscribers = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$subscriberQuery = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id);
|
||||
|
||||
return PdfService::render('business::reports.subscription-reports.pdf', compact('subscribers'),'subscription-reports.pdf');
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($subscriberQuery, $duration, 'created_at', $request->from_date, $request->to_date);
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$subscriberQuery->where(function ($query) use ($search) {
|
||||
$query->where('duration', 'like', '%' . $search . '%')
|
||||
->orWhereHas('plan', function ($q) use ($search) {
|
||||
$q->where('subscriptionName', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('gateway', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('business', function ($q) use ($search) {
|
||||
$q->where('companyName', 'like', '%' . $search . '%')
|
||||
->orWhereHas('category', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function getInvoice($invoice_id)
|
||||
$subscribers = $subscriberQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::reports.subscription-reports.pdf', compact('subscribers', 'duration', 'filter_from_date', 'filter_to_date'),'subscription-reports.pdf');
|
||||
}
|
||||
|
||||
public function getInvoice(string $invoice_id)
|
||||
{
|
||||
$subscriber = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl,phoneNumber,email,address,meta','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)->findOrFail($invoice_id);
|
||||
return view('business::reports.subscription-reports.invoice', compact('subscriber'));
|
||||
|
||||
@@ -35,82 +35,52 @@ public function index(Request $request)
|
||||
->with('purchases_dues')
|
||||
->latest();
|
||||
|
||||
// Branch-aware due filter
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
$parties = $query
|
||||
->paginate($request->per_page ?? 20)
|
||||
->appends($request->query());
|
||||
|
||||
$parties = $query->paginate($request->per_page ?? 20);
|
||||
|
||||
// Replace $supplier->due with branch-specific due if active branch exists
|
||||
if ($activeBranch) {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->purchases_dues
|
||||
$party_due = $supplier->purchases_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
|
||||
if ($supplier->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $supplier->opening_balance_type === 'due'
|
||||
? ($supplier->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$supplier->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$supplier->due = $party_due;
|
||||
}
|
||||
|
||||
return $supplier;
|
||||
})
|
||||
->filter(fn($supplier) => $supplier->due > 0)
|
||||
->values()
|
||||
);
|
||||
} else {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
|
||||
->values()
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate total_due
|
||||
$total_due = $parties->sum(function ($supplier) {
|
||||
return $supplier->due;
|
||||
});
|
||||
$supplier_total_due = $parties->getCollection()->sum('due');
|
||||
|
||||
if ($request->ajax()) {
|
||||
|
||||
return response()->json([
|
||||
'data' => view('business::reports.supplier-due.datas', compact('parties', 'total_due'))->render()
|
||||
'data' => view('business::reports.supplier-due.datas', compact('parties'))->render(),
|
||||
'supplier_total_due' => currency_format($supplier_total_due, currency: business_currency())
|
||||
]);
|
||||
}
|
||||
|
||||
if ($activeBranch) {
|
||||
// Filter parties that have branch-specific due > 0
|
||||
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->paginate(20)->appends($request->query());
|
||||
|
||||
// Calculate total due
|
||||
$total_due = $parties->sum(function ($supplier) use ($activeBranch) {
|
||||
if ($activeBranch) {
|
||||
return $supplier->purchases_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
}
|
||||
return $supplier->due;
|
||||
});
|
||||
|
||||
// Replace $supplier->due with branch-specific due if active branch exists
|
||||
if ($activeBranch) {
|
||||
$parties->setCollection(
|
||||
$parties->getCollection()
|
||||
->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->purchases_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $supplier;
|
||||
})
|
||||
->filter(fn($supplier) => $supplier->due > 0)
|
||||
->values()
|
||||
);
|
||||
}
|
||||
|
||||
return view('business::reports.supplier-due.due-reports', compact('parties', 'total_due'));
|
||||
return view('business::reports.supplier-due.due-reports', compact('parties', 'supplier_total_due'));
|
||||
}
|
||||
|
||||
public function exportExcel()
|
||||
@@ -123,7 +93,7 @@ public function exportCsv()
|
||||
return Excel::download(new ExportSupplierDue, 'supplier-due.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
@@ -131,29 +101,48 @@ public function exportPdf()
|
||||
|
||||
$query = Party::where('business_id', $businessId)
|
||||
->where('type', 'Supplier')
|
||||
->when($request->search, function ($q) use ($request) {
|
||||
$q->where(function ($q2) use ($request) {
|
||||
$q2->where('type', 'like', '%' . $request->search . '%')
|
||||
->orWhere('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->with('purchases_dues')
|
||||
->latest();
|
||||
|
||||
if ($activeBranch) {
|
||||
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
|
||||
$q->where('branch_id', $activeBranch->id)
|
||||
->where('dueAmount', '>', 0);
|
||||
});
|
||||
} else {
|
||||
$query->where('due', '>', 0);
|
||||
}
|
||||
|
||||
$parties = $query->get();
|
||||
|
||||
if ($activeBranch) {
|
||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
||||
$supplier->due = $supplier->purchases_dues
|
||||
$parties = $parties
|
||||
->transform(function ($supplier) use ($activeBranch) {
|
||||
$party_due = $supplier->purchases_dues
|
||||
->where('branch_id', $activeBranch->id)
|
||||
->sum('dueAmount');
|
||||
return $supplier;
|
||||
})->filter(fn($supplier) => $supplier->due > 0);
|
||||
|
||||
if ($supplier->branch_id === $activeBranch->id) {
|
||||
$openingBalanceDue = $supplier->opening_balance_type === 'due'
|
||||
? ($supplier->opening_balance ?? 0)
|
||||
: 0;
|
||||
|
||||
$supplier->due = $openingBalanceDue + $party_due;
|
||||
} else {
|
||||
$supplier->due = $party_due;
|
||||
}
|
||||
|
||||
return PdfService::render('business::reports.supplier-due.pdf', compact('parties'),'supplier-due-report.pdf');
|
||||
return $supplier;
|
||||
})
|
||||
->filter(fn($supplier) => $supplier->due > 0)
|
||||
->take($request->per_page ?? 20)
|
||||
->values();
|
||||
} else {
|
||||
$parties = $parties
|
||||
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
|
||||
->take($request->per_page ?? 20)
|
||||
->values();
|
||||
}
|
||||
|
||||
return PdfService::render('business::reports.supplier-due.pdf', compact('parties'), 'supplier-due-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public function index(Request $request)
|
||||
}
|
||||
|
||||
|
||||
public function show(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function show(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::find($partyId);
|
||||
$ledger = $service->list($request, $partyId);
|
||||
@@ -74,18 +74,25 @@ public function exportCsv()
|
||||
return Excel::download(new ExportSupplierLedger, 'supplier-ledger.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$suppliers = Party::with('purchases')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '=', 'Supplier')
|
||||
->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->get();
|
||||
->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::party-reports.supplier-ledger.pdf', compact('suppliers'),'supplier-ledger-report.pdf');
|
||||
}
|
||||
|
||||
public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerExcel(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::findOrFail($partyId);
|
||||
$ledger = $service->list($request, $partyId);
|
||||
@@ -93,7 +100,7 @@ public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService
|
||||
return Excel::download(new ExportSingleSupplierLedger($ledger, $party), 'single-supplier-ledger.xlsx');
|
||||
}
|
||||
|
||||
public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerCsv(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::findOrFail($partyId);
|
||||
$ledger = $service->list($request, $partyId);
|
||||
@@ -101,14 +108,18 @@ public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $
|
||||
return Excel::download(new ExportSingleSupplierLedger($ledger, $party), 'single-supplier-ledger.csv');
|
||||
}
|
||||
|
||||
public function exportLedgerPdf(Request $request, $partyId, PartyLedgerService $service)
|
||||
public function exportLedgerPdf(Request $request, string $partyId, PartyLedgerService $service)
|
||||
{
|
||||
$party = Party::find($partyId);
|
||||
$ledger = $service->list($request, $partyId);
|
||||
|
||||
$duration = $request->custom_days ?: $request->duration ?: 'today';
|
||||
|
||||
[$fromDate, $toDate] = app(PartyLedgerService::class)->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
return PdfService::render(
|
||||
'business::party-reports.supplier-ledger.show-details.pdf',
|
||||
compact('ledger', 'party'),
|
||||
compact('ledger', 'party', 'duration', 'fromDate', 'toDate'),
|
||||
strtolower($party->name).'-supplier.pdf'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,16 +56,29 @@ public function exportCsv()
|
||||
return Excel::download(new ExportTopCustomer, 'top-customers.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$customers = Party::with('sales')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '!=', 'Supplier')
|
||||
->whereHas('sales')
|
||||
->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('email', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->withCount('sales')
|
||||
->withSum('sales', 'totalAmount')
|
||||
->orderByDesc('sales_count')
|
||||
->orderByDesc('sales_sum_total_amount')
|
||||
->when(request('type'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('type', $request->type);
|
||||
});
|
||||
})
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public function index(Request $request)
|
||||
}
|
||||
|
||||
$top_products = SaleDetails::query()
|
||||
->with('product:id,productName,productCode')
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})
|
||||
@@ -67,27 +67,40 @@ public function exportCsv()
|
||||
return Excel::download(new ExportTopProduct, 'top-products.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
|
||||
$user = auth()->user();
|
||||
$businessId = $user->business_id;
|
||||
|
||||
$top_products = SaleDetails::with('product:id,productName,productCode')
|
||||
->whereHas('product', function ($q) {
|
||||
$q->where('business_id', auth()->user()->business_id);
|
||||
$branchId = null;
|
||||
if (moduleCheck('MultiBranchAddon')) {
|
||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||
}
|
||||
|
||||
$top_products = SaleDetails::query()
|
||||
->with('product:id,productName,productCode,hsn_code')
|
||||
->whereHas('product', function ($q) use ($businessId) {
|
||||
$q->where('business_id', $businessId);
|
||||
})
|
||||
->when($request->filled('search'), function ($q) use ($request) {
|
||||
$q->whereHas('product', function ($q) use ($request) {
|
||||
$q->where('productName', 'like', "%{$request->search}%")
|
||||
->orWhere('productCode', 'like', "%{$request->search}%");
|
||||
});
|
||||
})
|
||||
->when($branchId, function ($q) use ($branchId) {
|
||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
||||
$sale->where('branch_id', $branchId);
|
||||
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||
$q->where('branch_id', $branchId);
|
||||
});
|
||||
})
|
||||
->select(
|
||||
'product_id',
|
||||
DB::raw('SUM(quantities) as total_sold_qty'),
|
||||
DB::raw('SUM(price * quantities) as total_sale_amount')
|
||||
DB::raw('SUM((price - discount) * quantities) as total_sale_amount')
|
||||
)
|
||||
->groupBy('product_id')
|
||||
->orderByDesc('total_sold_qty')
|
||||
->take(5)
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
return PdfService::render('business::reports.top-products.pdf', compact('top_products'),'top-product-report.pdf');
|
||||
|
||||
@@ -51,12 +51,20 @@ public function exportCsv()
|
||||
return Excel::download(new ExportTopSupplier, 'top-suppliers.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$suppliers = Party::with('purchases')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->where('type', '=', 'Supplier')
|
||||
->whereHas('purchases')
|
||||
->when(request('search'), function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%')
|
||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
||||
->orWhere('email', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
})
|
||||
->withCount('purchases')
|
||||
->withSum('purchases', 'totalAmount')
|
||||
->orderByDesc('purchases_count')
|
||||
|
||||
@@ -124,13 +124,78 @@ public function exportCsv()
|
||||
return Excel::download(new ExportTransactionReport, 'bill-wise-profit.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$transactions = Transaction::with('paymentType')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
return PdfService::render('business::transactions.pdf', compact('transactions'),'transactions-report.pdf');
|
||||
$transactionsQuery = Transaction::with('paymentType')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($transactionsQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||
|
||||
// Search filter
|
||||
if ($request->filled('search')) {
|
||||
$transactionsQuery->where(function ($query) use ($request) {
|
||||
$query->where('amount', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . $request->search . '%')
|
||||
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||
->orWhere('type', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Platform filter
|
||||
if ($request->filled('platform')) {
|
||||
$transactionsQuery->where('platform', $request->platform);
|
||||
}
|
||||
|
||||
// Party Filter
|
||||
if ($request->filled('party_id')) {
|
||||
|
||||
$transactionsQuery->where(function ($q) use ($request) {
|
||||
|
||||
$q->where(function ($saleQ) use ($request) {
|
||||
$saleQ->where('platform', 'sale')
|
||||
->whereHas('sale', function ($s) use ($request) {
|
||||
$s->where('party_id', $request->party_id);
|
||||
});
|
||||
});
|
||||
|
||||
$q->where(function ($saleRtnQ) use ($request) {
|
||||
$saleRtnQ->where('platform', 'sale_return')
|
||||
->whereHas('saleReturn.sale', function ($s) use ($request) {
|
||||
$s->where('party_id', $request->party_id);
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($purQ) use ($request) {
|
||||
$purQ->where('platform', 'purchase')
|
||||
->whereHas('purchase', function ($p) use ($request) {
|
||||
$p->where('party_id', $request->party_id);
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($purRtnQ) use ($request) {
|
||||
$purRtnQ->where('platform', 'purchase_return')
|
||||
->whereHas('purchaseReturn.purchase', function ($p) use ($request) {
|
||||
$p->where('party_id', $request->party_id);
|
||||
});
|
||||
});
|
||||
|
||||
$q->orWhere(function ($dueQ) use ($request) {
|
||||
$dueQ->where('platform', 'due_collect')
|
||||
->whereHas('dueCollect', function ($d) use ($request) {
|
||||
$d->where('party_id', $request->party_id);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$transactions = $transactionsQuery->latest()->limit($request->per_page ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::transactions.pdf', compact('transactions', 'duration', 'filter_from_date', 'filter_to_date'),'transactions-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use App\Traits\DateRangeTrait;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportTransaction;
|
||||
|
||||
@@ -24,15 +23,6 @@ public function __construct()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$today = Carbon::today()->format('Y-m-d');
|
||||
|
||||
$total_due = DueCollect::where('business_id', $businessId)
|
||||
->whereDate('paymentDate', $today)
|
||||
->sum('totalDue');
|
||||
|
||||
$total_paid = DueCollect::where('business_id', $businessId)
|
||||
->whereDate('paymentDate', $today)
|
||||
->sum('payDueAmount');
|
||||
|
||||
$transactionsQuery = DueCollect::with('party:id,name,type', 'payment_type:id,name', 'transactions')->where('business_id', $businessId);
|
||||
|
||||
@@ -93,12 +83,44 @@ public function exportCsv()
|
||||
return Excel::download(new ExportTransaction, 'transaction-history.csv');
|
||||
}
|
||||
|
||||
public function exportPdf()
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$transactions = DueCollect::with('party:id,name,type', 'payment_type:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
|
||||
->latest()
|
||||
->get();
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
return PdfService::render('business::reports.transaction-history.pdf', compact('transactions'),'due-transactions-report.pdf');
|
||||
$transactionsQuery = DueCollect::with('party:id,name,type', 'payment_type:id,name', 'transactions')->where('business_id', $businessId);
|
||||
|
||||
// Date Filter
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$this->applyDateFilter($transactionsQuery, $duration, 'paymentDate', $request->from_date, $request->to_date);
|
||||
|
||||
// Search Filter
|
||||
if ($request->filled('search')) {
|
||||
$transactionsQuery->where(function ($query) use ($request) {
|
||||
$query->where('paymentType', 'like', '%' . $request->search . '%')
|
||||
->orWhere('totalDue', 'like', '%' . $request->search . '%')
|
||||
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
|
||||
->orWhere('payDueAmount', 'like', '%' . $request->search . '%')
|
||||
->orWhereHas('party', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
})
|
||||
->orWhereHas('payment_type', function ($q) use ($request) {
|
||||
$q->where('name', 'like', '%' . $request->search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->filled('type')) {
|
||||
$transactionsQuery->whereHas('party', function ($q) use ($request) {
|
||||
$q->where(function ($q) use ($request) {
|
||||
$q->where('type', $request->type);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$transactions = $transactionsQuery->latest()->limit($request->per_page)->get();
|
||||
|
||||
return PdfService::render('business::reports.transaction-history.pdf', compact('transactions', 'duration', 'filter_from_date', 'filter_to_date'),'due-transactions-report.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\PdfService;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportTransfer;
|
||||
|
||||
@@ -25,11 +26,20 @@ public function __construct()
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$branches = Branch::withTrashed()->where('business_id', auth()->user()->business_id)->latest()->get();
|
||||
$user = auth()->user();
|
||||
$activeBranchId = $user->active_branch_id;
|
||||
|
||||
$branches = Branch::withTrashed()->where('business_id', $user->business_id)->latest()->get();
|
||||
|
||||
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
->when($request->branch_id, function ($q) use ($request) {
|
||||
->where('business_id', $user->business_id)
|
||||
->when($activeBranchId, function ($q) use ($activeBranchId) {
|
||||
$q->where(function ($query) use ($activeBranchId) {
|
||||
$query->where('from_branch_id', $activeBranchId)
|
||||
->orWhere('to_branch_id', $activeBranchId);
|
||||
});
|
||||
})
|
||||
->when($request->branch_id && !$activeBranchId, function ($q) use ($request) {
|
||||
$q->where(function ($query) use ($request) {
|
||||
$query->where('from_branch_id', $request->branch_id)->orWhere('to_branch_id', $request->branch_id);
|
||||
});
|
||||
@@ -77,6 +87,19 @@ public function create()
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Normalize serial_numbers
|
||||
if ($request->has('products')) {
|
||||
$products = $request->products;
|
||||
|
||||
foreach ($products as $key => $item) {
|
||||
if (!empty($item['serial_numbers']) && is_string($item['serial_numbers'])) {
|
||||
$products[$key]['serial_numbers'] = json_decode($item['serial_numbers'], true);
|
||||
}
|
||||
}
|
||||
|
||||
$request->merge(['products' => $products]);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'from_branch_id' => 'nullable|exists:branches,id',
|
||||
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_id',
|
||||
@@ -91,6 +114,7 @@ public function store(Request $request)
|
||||
'products.*.unit_price' => 'required|numeric|min:0',
|
||||
'products.*.discount' => 'nullable|numeric|min:0',
|
||||
'products.*.tax' => 'nullable|numeric|min:0',
|
||||
'products.*.serial_numbers' => 'nullable|array',
|
||||
]);
|
||||
|
||||
$user = auth()->user();
|
||||
@@ -99,72 +123,54 @@ public function store(Request $request)
|
||||
$fromWh = $request->from_warehouse_id;
|
||||
$toWh = $request->to_warehouse_id;
|
||||
|
||||
// Transfer validation logic
|
||||
// Transfer validation
|
||||
if ($user->active_branch_id && $toBranch && $toWh) {
|
||||
return response()->json([
|
||||
'message' => 'You cannot transfer to another branch warehouse.'
|
||||
], 400);
|
||||
return response()->json(['message' => 'You cannot transfer to another branch warehouse.'], 400);
|
||||
}
|
||||
if (!$toBranch && !$toWh) {
|
||||
// to_branch or to_warehouse no one exist
|
||||
return response()->json([
|
||||
'message' => 'Invalid transfer request. Please select a destination branch or warehouse.'
|
||||
], 400);
|
||||
return response()->json(['message' => 'Please select a destination branch or warehouse.'], 400);
|
||||
}
|
||||
if ($fromBranch && !$fromWh) {
|
||||
// Branch to Branch transfer only
|
||||
if ($fromBranch == $toBranch) {
|
||||
return response()->json([
|
||||
'message' => 'Transfer not allowed: Same branch transfer is not possible.'
|
||||
], 400);
|
||||
if ($fromBranch && !$fromWh && $fromBranch == $toBranch) {
|
||||
return response()->json(['message' => 'Same branch transfer is not allowed.'], 400);
|
||||
}
|
||||
} elseif (!$fromBranch && $fromWh) {
|
||||
// Warehouse to Warehouse transfer only
|
||||
if ($fromWh == $toWh) {
|
||||
return response()->json([
|
||||
'message' => 'Transfer not allowed: Same warehouse transfer is not possible.'
|
||||
], 400);
|
||||
}
|
||||
} elseif ($fromBranch && $fromWh) {
|
||||
// Both branch and warehouse present
|
||||
if ($fromBranch == $toBranch && $fromWh == $toWh) {
|
||||
return response()->json([
|
||||
'message' => 'Transfer not allowed: Same warehouse transfer within the same branch.'
|
||||
], 400);
|
||||
}
|
||||
} else {
|
||||
return response()->json([
|
||||
'message' => 'Invalid transfer request. Please provide branch or warehouse information.'
|
||||
], 400);
|
||||
if ($fromWh && $fromWh == $toWh) {
|
||||
return response()->json(['message' => 'Same warehouse transfer is not allowed.'], 400);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$subTotal = 0;
|
||||
$totalDiscount = 0;
|
||||
$totalTax = 0;
|
||||
$subTotal = $totalDiscount = $totalTax = 0;
|
||||
|
||||
foreach ($request->products as $item) {
|
||||
$qty = $item['quantity'];
|
||||
$price = $item['unit_price'];
|
||||
$discount = $item['discount'] ?? 0;
|
||||
$tax = $item['tax'] ?? 0;
|
||||
// products re-arrange
|
||||
$products = collect($request->products)->map(function ($item, $key) {
|
||||
return array_merge($item, ['stock_id' => $item['stock_id'] ?? $key]);
|
||||
});
|
||||
|
||||
$subTotal += ($qty * $price);
|
||||
$totalTax += $tax;
|
||||
$totalDiscount += $discount;
|
||||
// Calculate subtotal using serial count if available
|
||||
foreach ($products as $item) {
|
||||
$serials = !empty($item['serial_numbers'])
|
||||
? (is_array($item['serial_numbers']) ? $item['serial_numbers'] : json_decode($item['serial_numbers'], true))
|
||||
: [];
|
||||
$qty = !empty($serials) ? count($serials) : $item['quantity'];
|
||||
$subTotal += $qty * $item['unit_price'];
|
||||
$totalTax += $item['tax'] ?? 0;
|
||||
$totalDiscount += $item['discount'] ?? 0;
|
||||
}
|
||||
|
||||
$shipping = $request->shipping_charge ?? 0;
|
||||
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
|
||||
|
||||
$transfer = Transfer::create($request->except('business_id', 'shipping_charge', 'sub_total', 'total_discount', 'total_tax', 'grand_total', 'from_warehouse_id', 'to_warehouse_id', 'to_branch_id', 'from_branch_id') + [
|
||||
'business_id' => auth()->user()->business_id,
|
||||
$transfer = Transfer::create([
|
||||
'business_id' => $user->business_id,
|
||||
'user_id' => auth()->id(),
|
||||
'from_branch_id' => $fromBranch,
|
||||
'from_warehouse_id' => $fromWh,
|
||||
'to_branch_id' => $toBranch,
|
||||
'to_warehouse_id' => $toWh,
|
||||
'transfer_date' => $request->transfer_date,
|
||||
'status' => $request->status,
|
||||
'note' => $request->note,
|
||||
'shipping_charge' => $shipping,
|
||||
'sub_total' => $subTotal,
|
||||
'total_discount' => $totalDiscount,
|
||||
@@ -172,115 +178,120 @@ public function store(Request $request)
|
||||
'grand_total' => $grandTotal,
|
||||
]);
|
||||
|
||||
$transferProductData = [];
|
||||
|
||||
foreach ($request->products as $stockId => $item) {
|
||||
// Find product_id from stock_id
|
||||
$stock = Stock::find($stockId);
|
||||
$transferProducts = [];
|
||||
|
||||
foreach ($products as $item) {
|
||||
$stock = Stock::find($item['stock_id']);
|
||||
if (!$stock) {
|
||||
return response()->json([
|
||||
'message' => "Invalid stock ID: {$stockId}"
|
||||
], 400);
|
||||
return response()->json(['message' => "Invalid stock ID: {$item['stock_id']}"], 400);
|
||||
}
|
||||
|
||||
$transferProductData[] = [
|
||||
// Ensure serial_numbers is array
|
||||
$serials = !empty($item['serial_numbers'])
|
||||
? (is_array($item['serial_numbers']) ? $item['serial_numbers'] : json_decode($item['serial_numbers'], true))
|
||||
: [];
|
||||
|
||||
$quantity = !empty($serials) ? count($serials) : $item['quantity'];
|
||||
|
||||
$transferProducts[] = [
|
||||
'transfer_id' => $transfer->id,
|
||||
'stock_id' => $stockId,
|
||||
'stock_id' => $stock->id,
|
||||
'product_id' => $stock->product_id,
|
||||
'quantity' => $item['quantity'] ?? 0,
|
||||
'unit_price' => $item['unit_price'] ?? 0,
|
||||
'quantity' => $quantity,
|
||||
'unit_price' => $item['unit_price'],
|
||||
'discount' => $item['discount'] ?? 0,
|
||||
'tax' => $item['tax'] ?? 0,
|
||||
'serial_numbers' => !empty($serials) ? json_encode($serials) : null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
|
||||
if ($request->status === 'completed') {
|
||||
foreach ($request->products as $stockId => $item) {
|
||||
// Get the actual FROM stock
|
||||
$fromStock = Stock::where('id', $stockId)
|
||||
// FROM stock
|
||||
$fromStock = Stock::where('id', $stock->id)
|
||||
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
||||
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
|
||||
->first();
|
||||
|
||||
if (!$fromStock) {
|
||||
return response()->json([
|
||||
'message' => "Stock not found in source (branch/warehouse) for stock ID: {$stockId}"
|
||||
], 400);
|
||||
if (!$fromStock || $fromStock->productStock < $quantity) {
|
||||
return response()->json(['message' => 'Insufficient stock for product ID: ' . $stock->product_id], 400);
|
||||
}
|
||||
|
||||
if ($fromStock->productStock < $item['quantity']) {
|
||||
return response()->json([
|
||||
'message' => "Insufficient stock in source for product ID: {$fromStock->product_id}, available: {$fromStock->productStock}"
|
||||
], 400);
|
||||
// Remove serials from source
|
||||
if (!empty($serials)) {
|
||||
$existingSerials = is_array($fromStock->serial_numbers) ? $fromStock->serial_numbers : json_decode($fromStock->serial_numbers ?? '[]', true);
|
||||
$fromStock->serial_numbers = array_values(array_diff($existingSerials, $serials));
|
||||
}
|
||||
|
||||
// Decrease FROM stock
|
||||
$fromStock->decrement('productStock', $item['quantity']);
|
||||
$fromStock->decrement('productStock', $quantity);
|
||||
$fromStock->save();
|
||||
|
||||
// Get the TO stock
|
||||
// TO stock
|
||||
$toStock = Stock::where('product_id', $fromStock->product_id)
|
||||
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
||||
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
|
||||
->when(!is_null($fromStock->batch_no), fn($q) => $q->where('batch_no', $fromStock->batch_no))
|
||||
->where(function ($q) use ($fromStock) {
|
||||
// if destination stock batch is NULL, skip batch compare
|
||||
$q->whereNull('batch_no')
|
||||
// otherwise match same batch
|
||||
->orWhere('batch_no', $fromStock->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$toStock) {
|
||||
$toStock = new Stock([
|
||||
'business_id' => auth()->user()->business_id,
|
||||
'business_id' => $user->business_id,
|
||||
'product_id' => $fromStock->product_id,
|
||||
'warehouse_id' => $toWh,
|
||||
'batch_no' => $fromStock->batch_no,
|
||||
'productStock' => 0,
|
||||
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
||||
'profit_percent' => $fromStock->profit_percent,
|
||||
'productSalePrice' => $fromStock->productSalePrice,
|
||||
'exclusive_price' => $fromStock->exclusive_price,
|
||||
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
||||
'productDealerPrice' => $fromStock->productDealerPrice,
|
||||
'mfg_date' => $fromStock->mfg_date,
|
||||
'expire_date' => $fromStock->expire_date,
|
||||
'serial_numbers' => !empty($serials) ? $serials : null,
|
||||
]);
|
||||
|
||||
// if active branch and to branch is null then use active branch id
|
||||
if ($toBranch == null && $user->active_branch_id){
|
||||
$toStock->branch_id = $user->active_branch_id;
|
||||
}else{
|
||||
$toStock->branch_id = $toBranch;
|
||||
}
|
||||
// Safe branch assignment
|
||||
$toStock->branch_id = $toBranch ?? $user->active_branch_id;
|
||||
|
||||
// Update product_type
|
||||
if ($fromStock->product->product_type !== 'variant') {
|
||||
$fromStock->product->update([
|
||||
'product_type' => 'variant'
|
||||
]);
|
||||
}
|
||||
|
||||
// Skip booted from model
|
||||
// Save without events/global scopes
|
||||
Stock::withoutEvents(function () use ($toStock) {
|
||||
$toStock->save();
|
||||
});
|
||||
}
|
||||
|
||||
// Increase TO stock safely
|
||||
$toStock->increment('productStock', $item['quantity']);
|
||||
// Increment destination stock safely
|
||||
$toStock->increment('productStock', $quantity);
|
||||
|
||||
// Merge serial numbers if exist
|
||||
if (!empty($serials)) {
|
||||
$toStockSerials = is_array($toStock->serial_numbers)
|
||||
? $toStock->serial_numbers
|
||||
: json_decode($toStock->serial_numbers ?? '[]', true);
|
||||
$toStock->serial_numbers = array_values(array_unique(array_merge($toStockSerials, $serials)));
|
||||
$toStock->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TransferProduct::insert($transferProductData);
|
||||
TransferProduct::insert($transferProducts);
|
||||
|
||||
DB::commit();
|
||||
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Transfer saved successfully.'),
|
||||
'data' => $transfer,
|
||||
'redirect' => route('business.transfers.index'),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'message' => 'Error: ' . $e->getMessage(),
|
||||
'success' => false,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
@@ -313,6 +324,19 @@ public function edit($id)
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
// Normalize serial_numbers
|
||||
if ($request->has('products')) {
|
||||
$products = $request->products;
|
||||
|
||||
foreach ($products as $key => $item) {
|
||||
if (!empty($item['serial_numbers']) && is_string($item['serial_numbers'])) {
|
||||
$products[$key]['serial_numbers'] = json_decode($item['serial_numbers'], true);
|
||||
}
|
||||
}
|
||||
|
||||
$request->merge(['products' => $products]);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'from_branch_id' => 'nullable|exists:branches,id',
|
||||
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_id',
|
||||
@@ -327,11 +351,12 @@ public function update(Request $request, $id)
|
||||
'products.*.unit_price' => 'required|numeric|min:0',
|
||||
'products.*.discount' => 'nullable|numeric|min:0',
|
||||
'products.*.tax' => 'nullable|numeric|min:0',
|
||||
'products.*.serial_numbers' => 'nullable|array',
|
||||
]);
|
||||
|
||||
$transfer = Transfer::findOrFail($id);
|
||||
|
||||
if ($request->status == 'cancelled') {
|
||||
if ($request->status === 'cancelled') {
|
||||
$transfer->update(['status' => 'cancelled']);
|
||||
return response()->json([
|
||||
'message' => __('Transfer cancelled successfully.'),
|
||||
@@ -345,49 +370,28 @@ public function update(Request $request, $id)
|
||||
$fromWh = $request->from_warehouse_id;
|
||||
$toWh = $request->to_warehouse_id;
|
||||
|
||||
// Transfer validation
|
||||
if ($user->active_branch_id && $toBranch && $toWh) {
|
||||
return response()->json([
|
||||
'message' => 'You cannot transfer to another branch warehouse.'
|
||||
], 400);
|
||||
}
|
||||
if (!$toBranch && !$toWh) {
|
||||
// to_branch or to_warehouse no one exist
|
||||
return response()->json([
|
||||
'message' => 'Invalid transfer request. Please select a destination branch or warehouse.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($fromBranch && !$fromWh) {
|
||||
if ($fromBranch == $toBranch) {
|
||||
return response()->json(['message' => 'Transfer not allowed: Same branch transfer is not possible.'], 400);
|
||||
}
|
||||
} elseif (!$fromBranch && $fromWh) {
|
||||
if ($fromWh == $toWh) {
|
||||
return response()->json(['message' => 'Transfer not allowed: Same warehouse transfer is not possible.'], 400);
|
||||
}
|
||||
} elseif ($fromBranch && $fromWh) {
|
||||
if ($fromBranch == $toBranch && $fromWh == $toWh) {
|
||||
return response()->json(['message' => 'Transfer not allowed: Same warehouse transfer within the same branch.'], 400);
|
||||
}
|
||||
} else {
|
||||
return response()->json(['message' => 'Invalid transfer request. Please provide branch or warehouse information.'], 400);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$oldStatus = $transfer->status;
|
||||
$subTotal = $totalDiscount = $totalTax = 0;
|
||||
|
||||
// Calculate totals using serial count
|
||||
foreach ($request->products as $item) {
|
||||
$subTotal += $item['quantity'] * $item['unit_price'];
|
||||
$serials = !empty($item['serial_numbers']) ? $item['serial_numbers'] : [];
|
||||
$qty = !empty($serials) ? count($serials) : $item['quantity'];
|
||||
|
||||
$subTotal += $qty * $item['unit_price'];
|
||||
$totalDiscount += $item['discount'] ?? 0;
|
||||
$totalTax += $item['tax'] ?? 0;
|
||||
}
|
||||
|
||||
$shipping = $request->shipping_charge ?? 0;
|
||||
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
|
||||
|
||||
// Update transfer
|
||||
$transfer->update([
|
||||
'user_id' => auth()->id(),
|
||||
'from_branch_id' => $fromBranch,
|
||||
'to_branch_id' => $toBranch,
|
||||
'from_warehouse_id' => $fromWh,
|
||||
@@ -402,25 +406,25 @@ public function update(Request $request, $id)
|
||||
'grand_total' => $grandTotal,
|
||||
]);
|
||||
|
||||
// Update TransferProduct
|
||||
// Delete old transfer products
|
||||
TransferProduct::where('transfer_id', $transfer->id)->delete();
|
||||
$transferProductData = [];
|
||||
|
||||
foreach ($request->products as $stockId => $item) {
|
||||
$transferProductData[] = [
|
||||
|
||||
$serials = !empty($item['serial_numbers']) ? $item['serial_numbers'] : [];
|
||||
$quantity = !empty($serials) ? count($serials) : $item['quantity'];
|
||||
|
||||
// Insert updated transfer product
|
||||
TransferProduct::create([
|
||||
'transfer_id' => $transfer->id,
|
||||
'stock_id' => $stockId,
|
||||
'quantity' => $item['quantity'] ?? 0,
|
||||
'quantity' => $quantity,
|
||||
'unit_price' => $item['unit_price'] ?? 0,
|
||||
'discount' => $item['discount'] ?? 0,
|
||||
'tax' => $item['tax'] ?? 0,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
}
|
||||
TransferProduct::insert($transferProductData);
|
||||
'serial_numbers' => !empty($serials) ? $serials : null,
|
||||
]);
|
||||
|
||||
// Stock Handling
|
||||
foreach ($request->products as $stockId => $item) {
|
||||
$fromStock = Stock::where('id', $stockId)
|
||||
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
||||
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
|
||||
@@ -431,20 +435,26 @@ public function update(Request $request, $id)
|
||||
'message' => "From stock not found for stock ID: {$stockId}"
|
||||
], 400);
|
||||
}
|
||||
|
||||
$toStock = Stock::where('product_id', $fromStock->product_id)
|
||||
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
||||
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
|
||||
->when(!is_null($fromStock->batch_no), fn($q) => $q->where('batch_no', $fromStock->batch_no))
|
||||
->where(function ($q) use ($fromStock) {
|
||||
// if destination stock batch is NULL, skip batch compare
|
||||
$q->whereNull('batch_no')
|
||||
// otherwise match same batch
|
||||
->orWhere('batch_no', $fromStock->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$toStock) {
|
||||
$toStock = new Stock([
|
||||
'business_id' => auth()->user()->business_id,
|
||||
'business_id' => $user->business_id,
|
||||
'product_id' => $fromStock->product_id,
|
||||
'warehouse_id' => $toWh,
|
||||
'batch_no' => $fromStock->batch_no,
|
||||
'productStock' => 0,
|
||||
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
||||
'exclusive_price' => $fromStock->exclusive_price,
|
||||
'profit_percent' => $fromStock->profit_percent,
|
||||
'productSalePrice' => $fromStock->productSalePrice,
|
||||
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
||||
@@ -453,31 +463,43 @@ public function update(Request $request, $id)
|
||||
'expire_date' => $fromStock->expire_date,
|
||||
]);
|
||||
|
||||
// if active branch and to branch is null then use active branch id
|
||||
if ($toBranch == null && $user->active_branch_id){
|
||||
$toStock->branch_id = $user->active_branch_id;
|
||||
}else{
|
||||
$toStock->branch_id = $toBranch;
|
||||
}
|
||||
|
||||
// Update product_type
|
||||
if ($fromStock->product->product_type !== 'variant') {
|
||||
$fromStock->product->update([
|
||||
'product_type' => 'variant'
|
||||
]);
|
||||
}
|
||||
|
||||
$toStock->branch_id = $toBranch ?? $user->active_branch_id;
|
||||
Stock::withoutEvents(fn() => $toStock->save());
|
||||
}
|
||||
|
||||
// Stock movement based on status change
|
||||
if ($oldStatus !== $request->status) {
|
||||
// Only move stock if changing pending to completed
|
||||
if ($oldStatus === 'pending' && $request->status === 'completed') {
|
||||
if ($fromStock->productStock >= $item['quantity']) {
|
||||
$fromStock->decrement('productStock', $item['quantity']);
|
||||
$toStock->increment('productStock', $item['quantity']);
|
||||
|
||||
// Handle serials for source
|
||||
if (!empty($serials)) {
|
||||
$existing = $fromStock->serial_numbers ?? [];
|
||||
foreach ($serials as $s) {
|
||||
if (!in_array($s, $existing)) {
|
||||
return response()->json([
|
||||
'message' => "Serial {$s} not found in source stock."
|
||||
], 400);
|
||||
}
|
||||
}
|
||||
// Remove from source
|
||||
$fromStock->serial_numbers = array_values(array_diff($existing, $serials));
|
||||
$fromStock->productStock = count($fromStock->serial_numbers);
|
||||
if ($fromStock->productStock === 0) {
|
||||
$fromStock->serial_numbers = null;
|
||||
}
|
||||
} else {
|
||||
$fromStock->decrement('productStock', $quantity);
|
||||
}
|
||||
$fromStock->save();
|
||||
|
||||
// Handle serials for destination
|
||||
if (!empty($serials)) {
|
||||
$toExisting = $toStock->serial_numbers ?? [];
|
||||
$toStock->serial_numbers = array_values(array_unique(array_merge($toExisting, $serials)));
|
||||
$toStock->productStock = count($toStock->serial_numbers);
|
||||
} else {
|
||||
$toStock->increment('productStock', $quantity);
|
||||
}
|
||||
$toStock->save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,6 +509,7 @@ public function update(Request $request, $id)
|
||||
'message' => __('Transfer updated successfully.'),
|
||||
'redirect' => route('business.transfers.index'),
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
@@ -494,8 +517,7 @@ public function update(Request $request, $id)
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
public function destroy(string $id)
|
||||
{
|
||||
$business_id = auth()->user()->business_id;
|
||||
$transfer = Transfer::with('transferProducts')->where('business_id', $business_id)->findOrFail($id);
|
||||
@@ -511,7 +533,10 @@ public function destroy($id)
|
||||
$toStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||
->where('branch_id', $transfer->to_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no') // if batch NULL → skip compare
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
||||
@@ -528,8 +553,12 @@ public function destroy($id)
|
||||
$toStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||
->where('branch_id', $transfer->to_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no')
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($toStock) {
|
||||
$toStock->decrement('quantity', $tp->quantity);
|
||||
}
|
||||
@@ -538,8 +567,12 @@ public function destroy($id)
|
||||
$fromStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->from_warehouse_id)
|
||||
->where('branch_id', $transfer->from_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no')
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($fromStock) {
|
||||
$fromStock->increment('quantity', $tp->quantity);
|
||||
}
|
||||
@@ -583,7 +616,10 @@ public function deleteAll(Request $request)
|
||||
$toStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||
->where('branch_id', $transfer->to_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no')
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
||||
@@ -604,8 +640,12 @@ public function deleteAll(Request $request)
|
||||
$toStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||
->where('branch_id', $transfer->to_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no')
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($toStock) {
|
||||
$toStock->decrement('quantity', $tp->quantity);
|
||||
}
|
||||
@@ -614,8 +654,12 @@ public function deleteAll(Request $request)
|
||||
$fromStock = Stock::where('product_id', $tp->product_id)
|
||||
->where('warehouse_id', $transfer->from_warehouse_id)
|
||||
->where('branch_id', $transfer->from_branch_id)
|
||||
->where('batch_no', optional($stock)->batch_no)
|
||||
->where(function ($q) use ($stock) {
|
||||
$q->whereNull('batch_no')
|
||||
->orWhere('batch_no', optional($stock)->batch_no);
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($fromStock) {
|
||||
$fromStock->increment('quantity', $tp->quantity);
|
||||
}
|
||||
@@ -648,4 +692,49 @@ public function exportCsv()
|
||||
{
|
||||
return Excel::download(new ExportTransfer, 'transfer.csv');
|
||||
}
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$activeBranchId = $user->active_branch_id;
|
||||
|
||||
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
|
||||
->where('business_id', $user->business_id)
|
||||
->when($activeBranchId, function ($q) use ($activeBranchId) {
|
||||
$q->where(function ($query) use ($activeBranchId) {
|
||||
$query->where('from_branch_id', $activeBranchId)
|
||||
->orWhere('to_branch_id', $activeBranchId);
|
||||
});
|
||||
})
|
||||
->when($request->branch_id && !$activeBranchId, function ($q) use ($request) {
|
||||
$q->where(function ($query) use ($request) {
|
||||
$query->where('from_branch_id', $request->branch_id)->orWhere('to_branch_id', $request->branch_id);
|
||||
});
|
||||
})
|
||||
->when($request->search, function ($q) use ($request) {
|
||||
$search = $request->search;
|
||||
|
||||
$q->where(function ($q) use ($search) {
|
||||
$q->where('note', 'like', '%' . $search . '%')
|
||||
->orWhere('status', 'like', '%' . $search . '%')
|
||||
->orWhere('invoice_no', 'like', '%' . $search . '%')
|
||||
->orWhereHas('fromWarehouse', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('toWarehouse', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('toBranch', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('fromBranch', function ($q) use ($search) {
|
||||
$q->where('name', 'like', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->latest()
|
||||
->limit(request('per_page') ?? 20)->get();
|
||||
|
||||
return PdfService::render('business::transfers.pdf', compact('transfers'),'transfers.pdf');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Vat;
|
||||
use App\Models\VatStateItem;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@@ -19,20 +20,39 @@ public function __construct()
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)->orderBy('status', 'desc')->whereNull('sub_vat')->latest()->paginate(20);
|
||||
$vat_groups = Vat::where('business_id', auth()->user()->business_id)->orderBy('status', 'desc')->whereNotNull('sub_vat')->latest()->paginate(20);
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
$vats = Vat::where('business_id', $business_id)
|
||||
->orderBy('status', 'desc')
|
||||
->whereNull('sub_vat')
|
||||
->where('manage_state', 0)
|
||||
->latest()
|
||||
->paginate(20);
|
||||
|
||||
$vat_groups = Vat::where('business_id', $business_id)
|
||||
->where(function ($query) {
|
||||
$query->whereNotNull('sub_vat')
|
||||
->orWhere('manage_state', 1);
|
||||
})
|
||||
->with('stateVats.childVat:id,name,rate')
|
||||
->orderBy('status', 'desc')
|
||||
->latest()
|
||||
->paginate(20);
|
||||
|
||||
return view('business::vats.index', compact('vats', 'vat_groups'));
|
||||
}
|
||||
|
||||
public function acnooFilter(Request $request)
|
||||
{
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)->whereNull('sub_vat')
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)
|
||||
->whereNull('sub_vat')
|
||||
->when($request->search, function ($query) use ($request) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$search = $request->search;
|
||||
$q->where('name', 'like', "%$search%");
|
||||
});
|
||||
})
|
||||
->where('manage_state', 0)
|
||||
->latest()
|
||||
->paginate(20);
|
||||
|
||||
@@ -47,13 +67,18 @@ public function acnooFilter(Request $request)
|
||||
|
||||
public function VatGroupFilter(Request $request)
|
||||
{
|
||||
$vat_groups = Vat::where('business_id', auth()->user()->business_id)->whereNotNull('sub_vat')
|
||||
$vat_groups = Vat::where('business_id', auth()->user()->business_id)
|
||||
->when($request->search, function ($query) use ($request) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$search = $request->search;
|
||||
$q->where('name', 'like', "%$search%");
|
||||
});
|
||||
})
|
||||
->with('stateVats.childVat:id,name')
|
||||
->where(function ($query) {
|
||||
$query->whereNotNull('sub_vat')
|
||||
->orWhere('manage_state', 1);
|
||||
})
|
||||
->latest()
|
||||
->paginate(20);
|
||||
|
||||
@@ -62,60 +87,115 @@ public function VatGroupFilter(Request $request)
|
||||
'data' => view('business::vat-groups.datas', compact('vat_groups'))->render()
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect(url()->previous());
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Vat Group Create
|
||||
public function create()
|
||||
{
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)->where('status','1')->whereNull('sub_vat')->latest()->get();
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)
|
||||
->where('status','1')
|
||||
->whereNull('sub_vat')
|
||||
->where('manage_state', 0)
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return view('business::vat-groups.create',compact('vats'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'vat_ids' => 'array',
|
||||
'rate' => 'nullable|numeric',
|
||||
'name' => 'required|string|max:255',
|
||||
'vat_ids' => 'required_if:rate,null',
|
||||
'rate' => 'required_if:rate,null|numeric',
|
||||
'manage_state' => 'nullable|integer|in:0,1',
|
||||
]);
|
||||
|
||||
// single vat
|
||||
if ($request->rate && !$request->vat_ids) {
|
||||
Vat::create($request->all() + [
|
||||
'business_id' => auth()->user()->business_id,
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
// SINGLE VAT
|
||||
if ($request->filled('rate') && !$request->vat_ids) {
|
||||
|
||||
$vat = Vat::create([
|
||||
'name' => $request->name,
|
||||
'rate' => $request->rate,
|
||||
'business_id' => $businessId,
|
||||
'manage_state' => 0,
|
||||
]);
|
||||
} elseif ($request->vat_ids && !$request->manage_state) { // GROUP VAT (OLD SYSTEM)
|
||||
|
||||
}
|
||||
// group vat
|
||||
elseif (!$request->rate && $request->vat_ids) {
|
||||
|
||||
$vats = Vat::whereIn('id', $request->vat_ids)->select('id', 'name', 'rate')->get();
|
||||
$vats = Vat::whereIn('id', $request->vat_ids)
|
||||
->where('business_id', $businessId)
|
||||
->select('id', 'name', 'rate')
|
||||
->get();
|
||||
|
||||
$tax_rate = 0;
|
||||
$sub_vats = [];
|
||||
|
||||
foreach ($vats as $vat) {
|
||||
foreach ($vats as $vatItem) {
|
||||
$sub_vats[] = [
|
||||
'id' => $vat->id,
|
||||
'name' => $vat->name,
|
||||
'rate' => $vat->rate,
|
||||
'id' => $vatItem->id,
|
||||
'name' => $vatItem->name,
|
||||
'rate' => $vatItem->rate,
|
||||
];
|
||||
$tax_rate += $vat->rate;
|
||||
$tax_rate += $vatItem->rate;
|
||||
}
|
||||
|
||||
Vat::create([
|
||||
$vat = Vat::create([
|
||||
'rate' => $tax_rate,
|
||||
'sub_vat' => $sub_vats,
|
||||
'name' => $request->name,
|
||||
'business_id' => auth()->user()->business_id,
|
||||
'business_id' => $businessId,
|
||||
'manage_state' => 0,
|
||||
]);
|
||||
} elseif ($request->manage_state == 1) { // STATE WISE VAT (NEW PIVOT SYSTEM)
|
||||
|
||||
$request->validate([
|
||||
'inner_vat_ids' => 'required|array',
|
||||
'outer_vat_ids' => 'required|array',
|
||||
]);
|
||||
|
||||
} else {
|
||||
$innerIds = $request->inner_vat_ids ?? [];
|
||||
$outerIds = $request->outer_vat_ids ?? [];
|
||||
|
||||
$innerRate = Vat::whereIn('id', $innerIds)
|
||||
->where('business_id', $businessId)
|
||||
->sum('rate');
|
||||
|
||||
$outerRate = Vat::whereIn('id', $outerIds)
|
||||
->where('business_id', $businessId)
|
||||
->sum('rate');
|
||||
|
||||
$vat = Vat::create([
|
||||
'name' => $request->name,
|
||||
'rate' => $innerRate ?: $outerRate,
|
||||
'business_id' => $businessId,
|
||||
'manage_state' => 1,
|
||||
]);
|
||||
|
||||
// Save pivot inner
|
||||
foreach ($innerIds as $id) {
|
||||
VatStateItem::create([
|
||||
'parent_vat_id' => $vat->id,
|
||||
'child_vat_id' => $id,
|
||||
'type' => 'inner'
|
||||
]);
|
||||
}
|
||||
|
||||
// Save pivot outer
|
||||
foreach ($outerIds as $id) {
|
||||
VatStateItem::create([
|
||||
'parent_vat_id' => $vat->id,
|
||||
'child_vat_id' => $id,
|
||||
'type' => 'outer'
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return response()->json([
|
||||
'message' => 'Invalid data format.',
|
||||
'message' => 'Invalid data format.'
|
||||
], 406);
|
||||
}
|
||||
|
||||
@@ -128,27 +208,43 @@ public function store(Request $request)
|
||||
// Vat Group Edit
|
||||
public function edit($id)
|
||||
{
|
||||
$vat = Vat::where('business_id', auth()->user()->business_id)->findOrFail($id);
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)->where('status','1')->whereNull('sub_vat')->latest()->paginate(20);
|
||||
$vat = Vat::with(['innerStateVats', 'outerStateVats'])->where('business_id', auth()->user()->business_id)->findOrFail($id);
|
||||
$vats = Vat::where('business_id', auth()->user()->business_id)
|
||||
->where('status','1')
|
||||
->whereNull('sub_vat')
|
||||
->where('manage_state', 0)
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return view('business::vat-groups.edit', compact('vat', 'vats'));
|
||||
}
|
||||
|
||||
|
||||
public function update(Request $request, Vat $vat)
|
||||
{
|
||||
$request->validate([
|
||||
'vat_ids' => 'array',
|
||||
'rate' => 'nullable|numeric',
|
||||
'name' => 'required|string|max:255',
|
||||
'vat_ids' => 'required_if:rate,null',
|
||||
'rate' => 'required_if:rate,null|numeric',
|
||||
'manage_state' => 'nullable|integer|in:0,1',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Single VAT update
|
||||
if ($request->rate && !$request->vat_ids) {
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$vat->update($request->only(['name', 'rate', 'status']));
|
||||
VatStateItem::where('parent_vat_id', $vat->id)->delete();
|
||||
|
||||
// SINGLE VAT
|
||||
if ($request->filled('rate') && !$request->vat_ids && !$request->manage_state) {
|
||||
|
||||
$vat->update([
|
||||
'name' => $request->name,
|
||||
'rate' => $request->rate,
|
||||
'status' => $request->status ?? $vat->status,
|
||||
'manage_state' => 0,
|
||||
]);
|
||||
|
||||
// Update group VATs containing this single VAT
|
||||
$vatGroupExist = Vat::where('sub_vat', 'LIKE', '%"id":' . $vat->id . '%')->get();
|
||||
foreach ($vatGroupExist as $group) {
|
||||
$subVats = collect($group->sub_vat)->map(function ($subVat) use ($vat) {
|
||||
@@ -158,7 +254,6 @@ public function update(Request $request, Vat $vat)
|
||||
}
|
||||
return $subVat;
|
||||
});
|
||||
|
||||
$group->update([
|
||||
'rate' => $subVats->sum('rate'),
|
||||
'sub_vat' => $subVats->toArray(),
|
||||
@@ -166,30 +261,79 @@ public function update(Request $request, Vat $vat)
|
||||
}
|
||||
}
|
||||
|
||||
// Group VAT update
|
||||
elseif (!$request->rate && $request->vat_ids) {
|
||||
// GROUP VAT (OLD SYSTEM)
|
||||
elseif ($request->vat_ids && !$request->manage_state) {
|
||||
|
||||
$vats = Vat::whereIn('id', $request->vat_ids)->select('id', 'name', 'rate')->get();
|
||||
$vats = Vat::whereIn('id', $request->vat_ids)
|
||||
->where('business_id', $businessId)
|
||||
->select('id', 'name', 'rate')
|
||||
->get();
|
||||
|
||||
$tax_rate = 0;
|
||||
$sub_vats = [];
|
||||
|
||||
foreach ($vats as $single_tax) {
|
||||
foreach ($vats as $vatItem) {
|
||||
$sub_vats[] = [
|
||||
'id' => $single_tax->id,
|
||||
'name' => $single_tax->name,
|
||||
'rate' => $single_tax->rate,
|
||||
'id' => $vatItem->id,
|
||||
'name' => $vatItem->name,
|
||||
'rate' => $vatItem->rate,
|
||||
];
|
||||
$tax_rate += $single_tax->rate;
|
||||
$tax_rate += $vatItem->rate;
|
||||
}
|
||||
|
||||
$vat->update([
|
||||
'name' => $request->name,
|
||||
'rate' => $tax_rate,
|
||||
'sub_vat' => $sub_vats,
|
||||
'name' => $request->name,
|
||||
'status' => $request->status ?? $vat->status,
|
||||
'manage_state' => 0,
|
||||
]);
|
||||
} else {
|
||||
}
|
||||
|
||||
// STATE-WISE VAT (NEW SYSTEM)
|
||||
elseif ($request->manage_state == 1) {
|
||||
|
||||
$innerIds = $request->inner_vat_ids ?? [];
|
||||
$outerIds = $request->outer_vat_ids ?? [];
|
||||
|
||||
$innerRate = Vat::whereIn('id', $innerIds)
|
||||
->where('business_id', $businessId)
|
||||
->sum('rate');
|
||||
|
||||
$outerRate = Vat::whereIn('id', $outerIds)
|
||||
->where('business_id', $businessId)
|
||||
->sum('rate');
|
||||
|
||||
$vat->update([
|
||||
'name' => $request->name,
|
||||
'rate' => $innerRate ?: $outerRate,
|
||||
'status' => $request->status ?? $vat->status,
|
||||
'manage_state' => 1,
|
||||
'sub_vat' => null,
|
||||
]);
|
||||
|
||||
// Delete old pivot entries
|
||||
VatStateItem::where('parent_vat_id', $vat->id)->delete();
|
||||
|
||||
// Insert inner VAT pivot
|
||||
foreach ($innerIds as $id) {
|
||||
VatStateItem::create([
|
||||
'parent_vat_id' => $vat->id,
|
||||
'child_vat_id' => $id,
|
||||
'type' => 'inner',
|
||||
]);
|
||||
}
|
||||
|
||||
// Insert outer VAT pivot
|
||||
foreach ($outerIds as $id) {
|
||||
VatStateItem::create([
|
||||
'parent_vat_id' => $vat->id,
|
||||
'child_vat_id' => $id,
|
||||
'type' => 'outer',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'message' => 'Invalid data format.',
|
||||
@@ -197,14 +341,17 @@ public function update(Request $request, Vat $vat)
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Vat updated successfully',
|
||||
'redirect' => route('business.vats.index'),
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
return response()->json(['message' => __('Somethings went wrong!')], 404);
|
||||
return response()->json([
|
||||
'message' => __('Somethings went wrong!'),
|
||||
'error' => $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,20 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Vat;
|
||||
use App\Models\Sale;
|
||||
use App\Models\Purchase;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Purchase;
|
||||
use App\Models\PurchaseReturnDetail;
|
||||
use App\Models\Sale;
|
||||
use App\Models\SaleDetails;
|
||||
use App\Models\SaleReturnDetails;
|
||||
use App\Models\Vat;
|
||||
use App\Models\VatTransaction;
|
||||
use App\Services\PdfService;
|
||||
use App\Traits\DateFilterTrait;
|
||||
use App\Traits\DateRangeTrait;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Business\App\Exports\ExportVatReport;
|
||||
use Modules\Business\App\Exports\ExportTaxReport;
|
||||
|
||||
class AcnooVatReportController extends Controller
|
||||
{
|
||||
@@ -25,134 +29,441 @@ public function __construct()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$vats = Vat::where('business_id', $businessId)->whereStatus(1)->get();
|
||||
|
||||
$vats = Vat::where('business_id', $businessId)
|
||||
->whereStatus(1)
|
||||
->get();
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'business:id,companyName', 'payment_type:id,name', 'transactions')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0);
|
||||
$salesQuery = Sale::where('business_id', $businessId)
|
||||
->with([
|
||||
'user:id,name',
|
||||
'party:id,name,email,phone,type',
|
||||
'business:id,companyName',
|
||||
'payment_type:id,name',
|
||||
'transactions'
|
||||
]);
|
||||
|
||||
// Date Filter
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
$this->applyDateFilter(
|
||||
$salesQuery,
|
||||
$duration,
|
||||
'saleDate',
|
||||
$request->from_date,
|
||||
$request->to_date
|
||||
);
|
||||
|
||||
$sales = $salesQuery->latest()->paginate(20, ['*'], 'sales');
|
||||
|
||||
$salesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$salesVatTotals[$vat->id] = (clone $salesQuery)->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$salesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$purchasesQuery = Purchase::with('details', 'party', 'details.product', 'details.product.category', 'payment_type:id,name', 'transactions')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0);
|
||||
$sales = $salesQuery->latest()->paginate($request->per_page ?? 20, ['*'], 'sales')->appends($request->query());
|
||||
|
||||
// Date Filter
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
$salesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleDetails::class)
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$purchases = $purchasesQuery->latest()->paginate(20, ['*'], 'purchases');
|
||||
$salesReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
->join('sale_return_details', 'sale_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sale_details', 'sale_details.id', '=', 'sale_return_details.sale_detail_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$purchasesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$purchasesVatTotals[$vat->id] = (clone $purchasesQuery)->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
$saleVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\SaleDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration, $request) {
|
||||
$query->select('sale_details.id')
|
||||
->from('sale_details')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_days' && $request->from_date && $request->to_date) {
|
||||
$query->whereBetween('sales.saleDate', [$request->from_date, $request->to_date]);
|
||||
}
|
||||
})
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('sale_details.sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('sale_details.sale_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('sale_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$saleReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
|
||||
->join('sale_return_details','sale_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('sale_details','sale_details.id','=','sale_return_details.sale_detail_id')
|
||||
->join('sales','sales.id','=','sale_details.sale_id')
|
||||
|
||||
->selectRaw('sales.id as sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('sales.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$saleReturnVatRowMap = $saleReturnVatRows
|
||||
->groupBy('sale_id')
|
||||
->map(fn($rows)=>$rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
$purchasesQuery = Purchase::with([
|
||||
'details',
|
||||
'party',
|
||||
'details.product',
|
||||
'details.product.category',
|
||||
'payment_type:id,name',
|
||||
'transactions'
|
||||
])
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$this->applyDateFilter(
|
||||
$purchasesQuery,
|
||||
$duration,
|
||||
'purchaseDate',
|
||||
$request->from_date,
|
||||
$request->to_date
|
||||
);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$purchasesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$purchases = $purchasesQuery->latest()->paginate($request->per_page ?? 20, ['*'], 'purchases')->appends($request->query());
|
||||
|
||||
$purchasesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
|
||||
$purchaseReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
->join('purchase_return_details', 'purchase_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'purchase_return_details.purchase_detail_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$purchaseVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration, $request) {
|
||||
$query->select('purchase_details.id')
|
||||
->from('purchase_details')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_date' && $request->from_date && $request->to_date) {
|
||||
$query->whereBetween('purchases.purchaseDate', [$request->from_date, $request->to_date]);
|
||||
}
|
||||
})
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('purchase_details.purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('purchase_details.purchase_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('purchase_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$purchaseReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
|
||||
->join('purchase_return_details','purchase_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('purchase_details','purchase_details.id','=','purchase_return_details.purchase_detail_id')
|
||||
->join('purchases','purchases.id','=','purchase_details.purchase_id')
|
||||
|
||||
->selectRaw('purchases.id as purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('purchases.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$purchaseReturnVatRowMap = $purchaseReturnVatRows
|
||||
->groupBy('purchase_id')
|
||||
->map(fn($rows) => $rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'sale_data' => view('business::reports.vats.sale-datas', compact('sales', 'salesVatTotals', 'vats', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
||||
'purchase_data' => view('business::reports.vats.purchase-datas', compact('purchases', 'purchasesVatTotals', 'vats', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
||||
'sale_data' => view('business::reports.vats.sale-datas', compact(
|
||||
'sales',
|
||||
'salesVatTotals',
|
||||
'salesReturnVatTotals',
|
||||
'saleVatRowMap',
|
||||
'saleReturnVatRowMap',
|
||||
'vats',
|
||||
'filter_from_date',
|
||||
'filter_to_date',
|
||||
'duration'
|
||||
))->render(),
|
||||
|
||||
'purchase_data' => view('business::reports.vats.purchase-datas', compact(
|
||||
'purchases',
|
||||
'purchasesVatTotals',
|
||||
'purchaseReturnVatTotals',
|
||||
'purchaseVatRowMap',
|
||||
'purchaseReturnVatRowMap',
|
||||
'vats',
|
||||
'filter_from_date',
|
||||
'filter_to_date',
|
||||
'duration'
|
||||
))->render(),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('business::reports.vats.index', compact('sales', 'salesVatTotals', 'purchases', 'purchasesVatTotals', 'vats', 'filter_from_date', 'filter_to_date', 'duration'));
|
||||
return view('business::reports.vats.index', compact(
|
||||
'sales',
|
||||
'salesVatTotals',
|
||||
'salesReturnVatTotals',
|
||||
'saleVatRowMap',
|
||||
'saleReturnVatRowMap',
|
||||
'purchases',
|
||||
'purchasesVatTotals',
|
||||
'purchaseReturnVatTotals',
|
||||
'purchaseVatRowMap',
|
||||
'purchaseReturnVatRowMap',
|
||||
'vats',
|
||||
'filter_from_date',
|
||||
'filter_to_date',
|
||||
'duration'
|
||||
));
|
||||
}
|
||||
|
||||
public function exportExcel($type = 'all')
|
||||
public function exportExcel()
|
||||
{
|
||||
return $this->exportFile($type, 'vat-report.xlsx');
|
||||
return Excel::download(new ExportTaxReport, 'tax-report.xlsx');
|
||||
}
|
||||
|
||||
public function exportCsv($type = 'all')
|
||||
public function exportCsv()
|
||||
{
|
||||
return $this->exportFile($type, 'vat-report.csv');
|
||||
return Excel::download(new ExportTaxReport, 'tax-report.csv');
|
||||
}
|
||||
|
||||
private function exportFile($type, $filename, $format = null)
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
$type = $request->type ?? 'sales';
|
||||
|
||||
$duration = $request->custom_days ?: 'today';
|
||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||
|
||||
// SALES QUERY
|
||||
$salesQuery = Sale::with('party', 'payment_type', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$salesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$salesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleDetails::class)
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$salesReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
->join('sale_return_details', 'sale_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('sale_details', 'sale_details.id', '=', 'sale_return_details.sale_detail_id')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$saleVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\SaleDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration, $request) {
|
||||
$query->select('sale_details.id')
|
||||
->from('sale_details')
|
||||
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
|
||||
->where('sales.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_days' && $request->from_date && $request->to_date) {
|
||||
$query->whereBetween('sales.saleDate', [$request->from_date, $request->to_date]);
|
||||
}
|
||||
})
|
||||
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('sale_details.sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('sale_details.sale_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('sale_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$saleReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
|
||||
|
||||
->join('sale_return_details','sale_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('sale_details','sale_details.id','=','sale_return_details.sale_detail_id')
|
||||
->join('sales','sales.id','=','sale_details.sale_id')
|
||||
|
||||
->selectRaw('sales.id as sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('sales.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$saleReturnVatRowMap = $saleReturnVatRows
|
||||
->groupBy('sale_id')
|
||||
->map(fn($rows)=>$rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
// PURCHASE QUERY
|
||||
$purchasesQuery = Purchase::with('party', 'payment_type', 'transactions')
|
||||
->where('business_id', $businessId);
|
||||
|
||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$purchasesQuery->where(function ($query) use ($search) {
|
||||
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||
->orWhere('totalAmount', 'like', '%' . $search . '%')
|
||||
->orWhere('discountAmount', 'like', '%' . $search . '%')
|
||||
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
|
||||
});
|
||||
}
|
||||
|
||||
$purchasesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total','vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
|
||||
$purchaseReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
->join('purchase_return_details', 'purchase_return_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'purchase_return_details.purchase_detail_id')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId)
|
||||
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('vat_transactions.vat_id')
|
||||
->pluck('total', 'vat_transactions.vat_id')
|
||||
->toArray();
|
||||
|
||||
$purchaseVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||
->where('vatable_type', \App\Models\PurchaseDetails::class)
|
||||
->whereIn('vatable_id', function ($query) use ($businessId, $duration, $request) {
|
||||
$query->select('purchase_details.id')
|
||||
->from('purchase_details')
|
||||
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
|
||||
->where('purchases.business_id', $businessId);
|
||||
|
||||
if ($duration === 'custom_date' && $request->from_date && $request->to_date) {
|
||||
$query->whereBetween('purchases.purchaseDate', [$request->from_date, $request->to_date]);
|
||||
}
|
||||
})
|
||||
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
|
||||
->selectRaw('purchase_details.purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
|
||||
->groupBy('purchase_details.purchase_id', 'vat_transactions.vat_id')
|
||||
->get()
|
||||
->groupBy('purchase_id')
|
||||
->map(function ($items) {
|
||||
return $items->pluck('total', 'vat_id')->toArray();
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$purchaseReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
|
||||
|
||||
->join('purchase_return_details','purchase_return_details.id','=','vat_transactions.vatable_id')
|
||||
->join('purchase_details','purchase_details.id','=','purchase_return_details.purchase_detail_id')
|
||||
->join('purchases','purchases.id','=','purchase_details.purchase_id')
|
||||
|
||||
->selectRaw('purchases.id as purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
|
||||
->groupBy('purchases.id','vat_transactions.vat_id')
|
||||
->get();
|
||||
|
||||
$purchaseReturnVatRowMap = $purchaseReturnVatRows
|
||||
->groupBy('purchase_id')
|
||||
->map(fn($rows) => $rows->pluck('vat_amount','vat_id'))
|
||||
->toArray();
|
||||
|
||||
// TAB CONTROL
|
||||
$sales = collect();
|
||||
$purchases = collect();
|
||||
|
||||
if ($type === 'sales' || $type === 'all') {
|
||||
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'transactions')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0)
|
||||
->latest()
|
||||
->get();
|
||||
$limit = $request->per_page ?? 20;
|
||||
|
||||
if ($type === 'sales') {
|
||||
$sales = $salesQuery->latest()->limit($limit)->get();
|
||||
}
|
||||
|
||||
if ($type === 'purchases' || $type === 'all') {
|
||||
$purchases = Purchase::with('details', 'party', 'details.product', 'details.product.category', 'payment_type:id,name', 'transactions')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0)
|
||||
->latest()
|
||||
->get();
|
||||
if ($type === 'purchases') {
|
||||
$purchases = $purchasesQuery->latest()->limit($limit)->get();
|
||||
}
|
||||
|
||||
$vats = Vat::where('business_id', $businessId)->get();
|
||||
|
||||
$salesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$salesVatTotals[$vat->id] = $sales->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
}
|
||||
|
||||
$purchasesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$purchasesVatTotals[$vat->id] = $purchases->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
}
|
||||
|
||||
$export = new ExportVatReport($sales, $purchases, $vats, $salesVatTotals, $purchasesVatTotals);
|
||||
|
||||
return Excel::download($export, $filename, $format);
|
||||
}
|
||||
|
||||
public function exportPdf($type = 'all')
|
||||
{
|
||||
$businessId = auth()->user()->business_id;
|
||||
|
||||
$sales = collect();
|
||||
$purchases = collect();
|
||||
|
||||
if ($type === 'sales' || $type === 'all') {
|
||||
$sales = Sale::with('party', 'payment_type')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0)
|
||||
->latest()
|
||||
->get();
|
||||
}
|
||||
|
||||
if ($type === 'purchases' || $type === 'all') {
|
||||
$purchases = Purchase::with('party', 'payment_type')
|
||||
->where('business_id', $businessId)
|
||||
->where('vat_amount', '>', 0)
|
||||
->latest()
|
||||
->get();
|
||||
}
|
||||
|
||||
$vats = Vat::where('business_id', $businessId)->get();
|
||||
|
||||
$salesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$salesVatTotals[$vat->id] = $sales->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
}
|
||||
|
||||
$purchasesVatTotals = [];
|
||||
foreach ($vats as $vat) {
|
||||
$purchasesVatTotals[$vat->id] = $purchases->where('vat_id', $vat->id)->sum('vat_amount');
|
||||
}
|
||||
|
||||
return PdfService::render('business::reports.vats.pdf', compact('sales', 'salesVatTotals', 'purchases', 'purchasesVatTotals', 'vats', 'type'),'vats-report.pdf');
|
||||
return PdfService::render('business::reports.vats.pdf',
|
||||
compact(
|
||||
'sales',
|
||||
'salesVatTotals',
|
||||
'salesReturnVatTotals',
|
||||
'saleVatRowMap',
|
||||
'saleReturnVatRowMap',
|
||||
'purchases',
|
||||
'purchasesVatTotals',
|
||||
'purchaseReturnVatTotals',
|
||||
'purchaseVatRowMap',
|
||||
'purchaseReturnVatRowMap',
|
||||
'vats',
|
||||
'type',
|
||||
'filter_from_date',
|
||||
'filter_to_date',
|
||||
'duration'
|
||||
), 'tax-report.pdf', 'A4', 'L'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,65 +40,212 @@ public function store(Request $request)
|
||||
'warehouse_id' => 'nullable|exists:warehouses,id',
|
||||
'type' => 'nullable|string|in:sale,purchase',
|
||||
'id' => 'required|integer',
|
||||
'name' => 'required|string',
|
||||
'name' => 'nullable|string',
|
||||
'quantity' => 'required|numeric',
|
||||
'price' => 'required|numeric',
|
||||
'product_code' => 'nullable|string',
|
||||
'product_unit_id' => 'nullable|integer',
|
||||
'product_unit_name' => 'nullable|string',
|
||||
'product_image' => 'nullable|string',
|
||||
'profit_percent' => 'nullable|numeric',
|
||||
'sales_price' => 'nullable|numeric',
|
||||
'whole_sale_price' => 'nullable|numeric',
|
||||
'dealer_price' => 'nullable|numeric',
|
||||
'expire_date' => 'nullable|date',
|
||||
'product_type' => 'nullable|in:single,variant,combo',
|
||||
'variant_name' => 'nullable|string',
|
||||
'vat_percent' => 'nullable|numeric',
|
||||
'serial_numbers' => 'nullable|array',
|
||||
'serial_numbers.*' => 'string',
|
||||
'has_serial' => 'nullable|boolean',
|
||||
'price_without_tax' => 'required_without:serial_numbers|numeric|nullable',
|
||||
'customer_type' => 'nullable|string'
|
||||
]);
|
||||
|
||||
// Check for existing item in cart by type
|
||||
$existingCartItem = Cart::search(
|
||||
fn($item) => $item->id == $request->id &&
|
||||
$item->options->type == $request->type &&
|
||||
match ($request->type) {
|
||||
'purchase' => $item->options->batch_no == $request->batch_no,
|
||||
'sale' => $item->options->stock_id == $request->stock_id,
|
||||
default => false,
|
||||
$incomingSerials = $request->serial_numbers ?? [];
|
||||
|
||||
// Serial Mode
|
||||
if (!empty($incomingSerials)) {
|
||||
// Sale
|
||||
if ($request->type === 'sale') {
|
||||
|
||||
$stocks = Stock::where('business_id', auth()->user()->business_id)
|
||||
->where('product_id', $request->id)
|
||||
->where(function ($query) use ($incomingSerials) {
|
||||
foreach ($incomingSerials as $serial) {
|
||||
$query->orWhereJsonContains('serial_numbers', $serial);
|
||||
}
|
||||
)->first();
|
||||
})->get();
|
||||
|
||||
// Map serial → stock
|
||||
$serialStockMap = [];
|
||||
|
||||
foreach ($stocks as $stock) {
|
||||
foreach ($incomingSerials as $serial) {
|
||||
if (in_array($serial, $stock->serial_numbers ?? [])) {
|
||||
$serialStockMap[$stock->id][] = $serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add or merge cart per stock
|
||||
foreach ($serialStockMap as $stockId => $serialsForStock) {
|
||||
|
||||
$resolvedStock = $stocks->firstWhere('id', $stockId);
|
||||
$qty = count($serialsForStock);
|
||||
|
||||
$customerType = $request->customer_type ?? 'Retailer';
|
||||
|
||||
// Determine price based on customer type
|
||||
$price = round($resolvedStock->productSalePrice ?? 0, 2);
|
||||
|
||||
if ($customerType === 'Dealer') {
|
||||
$price = round($resolvedStock->productDealerPrice ?? 0, 2);
|
||||
} elseif ($customerType === 'Wholesaler') {
|
||||
$price = round($resolvedStock->productWholeSalePrice ?? 0, 2);
|
||||
}
|
||||
|
||||
$existingCartItem = Cart::search(function ($item) use ($request, $stockId) {
|
||||
return $item->id == $request->id &&
|
||||
$item->options->type === 'sale' &&
|
||||
$item->options->stock_id == $stockId;
|
||||
})->first();
|
||||
|
||||
if ($existingCartItem) {
|
||||
$newQty = $existingCartItem->qty + $request->quantity;
|
||||
Cart::update($existingCartItem->rowId, ['qty' => $newQty]);
|
||||
|
||||
$existingSerials = $existingCartItem->options->serial_numbers ?? [];
|
||||
|
||||
// Remove already existing serials from incoming
|
||||
$newSerials = array_diff($serialsForStock, $existingSerials);
|
||||
|
||||
$duplicates = array_intersect($existingSerials, $newSerials);
|
||||
|
||||
if (!empty($duplicates)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Serial already exists in cart',
|
||||
'duplicates' => array_values($duplicates),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$mergedSerials = array_values(array_unique(
|
||||
array_merge($existingSerials, $serialsForStock)
|
||||
));
|
||||
|
||||
Cart::update($existingCartItem->rowId, [
|
||||
'qty' => count($mergedSerials),
|
||||
'options' => $existingCartItem->options->merge([
|
||||
'serial_numbers' => $mergedSerials,
|
||||
]),
|
||||
]);
|
||||
|
||||
} else {
|
||||
// Add new item to cart
|
||||
$mainItemData = [
|
||||
|
||||
Cart::add([
|
||||
'id' => $request->id,
|
||||
'name' => $request->name,
|
||||
'qty' => $qty,
|
||||
'price' => $price,
|
||||
'options' => [
|
||||
'type' => 'sale',
|
||||
'product_code' => $request->product_code,
|
||||
'product_unit_id' => $request->product_unit_id,
|
||||
'product_unit_name' => $request->product_unit_name,
|
||||
'product_image' => $request->product_image,
|
||||
'product_type' => $request->product_type,
|
||||
'variant_name' => $request->variant_name,
|
||||
'stock_id' => $resolvedStock->id,
|
||||
'warehouse_id' => $resolvedStock->warehouse_id,
|
||||
'sales_price' => $resolvedStock->productSalePrice,
|
||||
'whole_sale_price' => $resolvedStock->productWholeSalePrice,
|
||||
'dealer_price' => $resolvedStock->productDealerPrice,
|
||||
'serial_numbers' => $serialsForStock,
|
||||
'has_serial' => $request->has_serial ?? 1,
|
||||
'price_without_tax' => $resolvedStock->price_without_tax,
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Purchase
|
||||
else {
|
||||
Cart::add([
|
||||
'id' => $request->id,
|
||||
'name' => $request->name,
|
||||
'qty' => count($incomingSerials),
|
||||
'price' => round($request->price, 2),
|
||||
'options' => [
|
||||
'type' => 'purchase',
|
||||
'product_code' => $request->product_code,
|
||||
'product_unit_id' => $request->product_unit_id,
|
||||
'product_unit_name' => $request->product_unit_name,
|
||||
'product_image' => $request->product_image,
|
||||
'product_type' => $request->product_type,
|
||||
'variant_name' => $request->variant_name,
|
||||
'stock_id' => null,
|
||||
'warehouse_id' => $request->warehouse_id,
|
||||
'serial_numbers' => $incomingSerials,
|
||||
'batch_no' => $request->batch_no,
|
||||
'expire_date' => $request->expire_date,
|
||||
'purchase_price' => $request->purchase_price,
|
||||
'profit_percent' => $request->profit_percent,
|
||||
'sales_price' => $request->sales_price,
|
||||
'whole_sale_price' => $request->whole_sale_price,
|
||||
'dealer_price' => $request->dealer_price,
|
||||
'has_serial' => $request->has_serial ?? 1,
|
||||
'price_without_tax' => $request->price_without_tax,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Serial product added successfully.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Normal product ( without serial)
|
||||
$existingCartItem = Cart::search(function ($item) use ($request) {
|
||||
return $item->id == $request->id &&
|
||||
$item->options->type == $request->type;
|
||||
})->first();
|
||||
|
||||
if ($existingCartItem) {
|
||||
|
||||
Cart::update($existingCartItem->rowId, [
|
||||
'qty' => $existingCartItem->qty + $request->quantity
|
||||
]);
|
||||
|
||||
} else {
|
||||
|
||||
Cart::add([
|
||||
'id' => $request->id,
|
||||
'name' => $request->name,
|
||||
'qty' => $request->quantity,
|
||||
'price' => $request->price,
|
||||
'price' => round($request->price, 2),
|
||||
'options' => [
|
||||
'type' => $request->type,
|
||||
'product_code' => $request->product_code,
|
||||
'product_unit_id' => $request->product_unit_id,
|
||||
'product_unit_name' => $request->product_unit_name,
|
||||
'product_image' => $request->product_image,
|
||||
'product_type' => $request->product_type,
|
||||
'variant_name' => $request->variant_name,
|
||||
'stock_id' => $request->stock_id,
|
||||
'batch_no' => $request->batch_no,
|
||||
'product_image' => $request->product_image,
|
||||
'expire_date' => $request->expire_date,
|
||||
'purchase_price' => $request->purchase_price,
|
||||
'profit_percent' => $request->profit_percent,
|
||||
'sales_price' => $request->sales_price,
|
||||
'whole_sale_price' => $request->whole_sale_price,
|
||||
'dealer_price' => $request->dealer_price,
|
||||
'product_type' => $request->product_type,
|
||||
'warehouse_id' => $request->warehouse_id,
|
||||
'variant_name' => $request->variant_name,
|
||||
'vat_percent' => $request->vat_percent,
|
||||
'has_serial' => $request->has_serial ?? 0,
|
||||
'price_without_tax' => $request->price_without_tax,
|
||||
]
|
||||
];
|
||||
Cart::add($mainItemData);
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Item added to cart successfully.'
|
||||
@@ -108,20 +255,45 @@ public function store(Request $request)
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$cart = Cart::get($id);
|
||||
|
||||
if (!$cart) {
|
||||
return response()->json(['success' => false, 'message' => __('Item not found in cart')]);
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => __('Item not found in cart')
|
||||
]);
|
||||
}
|
||||
|
||||
$qty = $request->qty ?? $cart->qty;
|
||||
|
||||
if ($qty < 0) {
|
||||
return response()->json(['success' => false, 'message' => __('Enter a valid quantity')]);
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => __('Enter a valid quantity')
|
||||
]);
|
||||
}
|
||||
|
||||
// incoming serial
|
||||
$incomingSerials = $request->serial_numbers ?? null;
|
||||
|
||||
if (is_array($incomingSerials)) {
|
||||
$existingSerials = $incomingSerials;
|
||||
} else {
|
||||
$existingSerials = $cart->options->serial_numbers ?? [];
|
||||
}
|
||||
|
||||
// normalize to array
|
||||
if (!is_array($existingSerials)) {
|
||||
$existingSerials = !empty($existingSerials) ? [$existingSerials] : [];
|
||||
}
|
||||
|
||||
$hasSerial = $cart->options->has_serial ?? 0;
|
||||
|
||||
if ($hasSerial) {
|
||||
$qty = count($existingSerials);
|
||||
}
|
||||
|
||||
Cart::update($id, [
|
||||
'qty' => $qty,
|
||||
'price' => $request->price ?? $cart->price,
|
||||
'price' => round($request->price ?? $cart->price, 2),
|
||||
'options' => [
|
||||
'type' => $cart->options->type,
|
||||
'expire_date' => $request->expire_date ?? $cart->options->expire_date,
|
||||
@@ -131,6 +303,7 @@ public function update(Request $request, $id)
|
||||
'product_unit_id' => $cart->options->product_unit_id,
|
||||
'product_unit_name' => $cart->options->product_unit_name,
|
||||
'product_image' => $cart->options->product_image,
|
||||
'profit_percent' => $cart->options->profit_percent,
|
||||
'sales_price' => $cart->options->sales_price,
|
||||
'discount' => $request->discount ?? $cart->options->discount,
|
||||
'whole_sale_price' => $cart->options->whole_sale_price,
|
||||
@@ -139,7 +312,9 @@ public function update(Request $request, $id)
|
||||
'product_type' => $cart->options->product_type,
|
||||
'warehouse_id' => $cart->options->warehouse_id,
|
||||
'variant_name' => $cart->options->variant_name,
|
||||
'vat_percent' => $cart->options->vat_percent,
|
||||
'price_without_tax' => $cart->options->price_without_tax,
|
||||
'has_serial' => $hasSerial,
|
||||
'serial_numbers' => $existingSerials,
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
@@ -196,17 +196,17 @@ public function revenue()
|
||||
$data['loss'] = Sale::where('business_id', auth()->user()->business_id)
|
||||
->whereYear('created_at', request('year') ?? date('Y'))
|
||||
->where('lossProfit', '<', 0)
|
||||
->selectRaw("TO_CHAR(created_at, 'Month') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||
->orderBy('created_at')
|
||||
->groupBy('created_at')
|
||||
->selectRaw("TO_CHAR(created_at, 'FMMonth') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||
->groupBy(DB::raw("TO_CHAR(created_at, 'FMMonth')"))
|
||||
->orderBy(DB::raw("MIN(created_at)"))
|
||||
->get();
|
||||
|
||||
$data['profit'] = Sale::where('business_id', auth()->user()->business_id)
|
||||
->whereYear('created_at', request('year') ?? date('Y'))
|
||||
->where('lossProfit', '>=', 0)
|
||||
->selectRaw("TO_CHAR(created_at, 'Month') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||
->orderBy('created_at')
|
||||
->groupBy('created_at')
|
||||
->selectRaw("TO_CHAR(created_at, 'FMMonth') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||
->groupBy(DB::raw("TO_CHAR(created_at, 'FMMonth')"))
|
||||
->orderBy(DB::raw("MIN(created_at)"))
|
||||
->get();
|
||||
|
||||
return response()->json($data);
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Events\MultiPaymentProcessed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Party;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Stock;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Purchase;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PurchaseReturn;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PurchaseReturnDetail;
|
||||
use App\Services\PurchaseVatTransaction;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PurchaseReturnController extends Controller
|
||||
{
|
||||
@@ -66,7 +66,6 @@ public function index(Request $request)
|
||||
return view('business::purchase-returns.index', compact('purchases', 'branches'));
|
||||
}
|
||||
|
||||
|
||||
public function create(Request $request)
|
||||
{
|
||||
$business_id = auth()->user()->business_id;
|
||||
@@ -80,56 +79,90 @@ public function create(Request $request)
|
||||
$discount_per_unit_factor = $total_purchase_price > 0 ? $purchase->discountAmount / $total_purchase_price : 0;
|
||||
$payment_types = PaymentType::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||
|
||||
|
||||
return view('business::purchase-returns.create', compact('purchase', 'discount_per_unit_factor','payment_types'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
// split-array structure from front-end request
|
||||
$products = [];
|
||||
for ($index = 0; $index < count($request->products); $index += 3) {
|
||||
$products[] = [
|
||||
'detail_id' => $request->products[$index]['detail_id'] ?? null,
|
||||
'return_qty' => $request->products[$index + 1]['return_qty'] ?? 0,
|
||||
'serial_numbers' => $request->products[$index + 2]['serial_numbers'] ?? '[]',
|
||||
];
|
||||
}
|
||||
$request->merge(['products' => $products]);
|
||||
|
||||
$request->validate([
|
||||
'purchase_id' => 'required|exists:purchases,id',
|
||||
'return_qty' => 'required|array',
|
||||
'products' => 'required|array|min:1',
|
||||
'products.*.detail_id' => 'required|exists:purchase_details,id',
|
||||
'products.*.return_qty' => 'required|integer',
|
||||
'products.*.serial_numbers' => 'nullable|string',
|
||||
'payments' => 'nullable|array',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$purchase = Purchase::with('details')
|
||||
->where('business_id', auth()->user()->business_id)
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
$purchase = Purchase::with('details.stock')
|
||||
->where('business_id', $business_id)
|
||||
->findOrFail($request->purchase_id);
|
||||
|
||||
// Calculate total discount factor
|
||||
$total_discount = $purchase->discountAmount;
|
||||
$total_purchase_amount = $purchase->details->sum(fn($detail) => $detail->productPurchasePrice * $detail->quantities);
|
||||
$total_purchase_amount = $purchase->details->sum(fn($d) => $d->productPurchasePrice * $d->quantities);
|
||||
$discount_per_unit_factor = $total_purchase_amount > 0 ? $total_discount / $total_purchase_amount : 0;
|
||||
|
||||
$purchase_return = PurchaseReturn::create([
|
||||
'business_id' => auth()->user()->business_id,
|
||||
'purchase_id' => $request->purchase_id,
|
||||
'business_id' => $business_id,
|
||||
'purchase_id' => $purchase->id,
|
||||
'invoice_no' => $purchase->invoiceNumber,
|
||||
'return_date' => now(),
|
||||
]);
|
||||
|
||||
$purchase_return_detail_data = [];
|
||||
$total_return_amount = 0;
|
||||
$total_return_discount = 0;
|
||||
|
||||
// Loop through each purchase detail and process the return
|
||||
foreach ($purchase->details as $key => $detail) {
|
||||
$requested_qty = $request->return_qty[$key];
|
||||
foreach ($request->products as $item) {
|
||||
|
||||
if ($requested_qty <= 0) {
|
||||
continue;
|
||||
}
|
||||
$detail = $purchase->details->where('id', $item['detail_id'])->first();
|
||||
if (!$detail) continue;
|
||||
|
||||
$requested_qty = (int) $item['return_qty'];
|
||||
if ($requested_qty <= 0) continue;
|
||||
|
||||
// Check if return quantity exceeds the purchased quantity
|
||||
if ($requested_qty > $detail->quantities) {
|
||||
return response()->json([
|
||||
'message' => "You can't return more than the ordered quantity of {$detail->quantities}.",
|
||||
'message' => "You can't return more than purchased quantity ({$detail->quantities})."
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Calculate per-unit discount and return amounts
|
||||
$serials = !empty($item['serial_numbers']) ? json_decode($item['serial_numbers'], true) : [];
|
||||
|
||||
// Serial number validation and stock update
|
||||
if (!empty($serials)) {
|
||||
if (count($serials) !== $requested_qty) {
|
||||
return response()->json(['message' => 'Serial count must match return quantity.'], 400);
|
||||
}
|
||||
|
||||
$stockSerials = $detail->stock->serial_numbers ?? [];
|
||||
$invalid = array_diff($serials, $stockSerials);
|
||||
if (!empty($invalid)) {
|
||||
return response()->json([
|
||||
'message' => 'Invalid serial numbers detected.',
|
||||
'invalid_serials' => array_values($invalid),
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Remove serials from stock
|
||||
$stock_remaining = array_values(array_diff($stockSerials, $serials));
|
||||
$detail->stock->update(['serial_numbers' => $stock_remaining]);
|
||||
}
|
||||
|
||||
//Return amount calculation
|
||||
$unit_discount = $detail->productPurchasePrice * $discount_per_unit_factor;
|
||||
$return_discount = $unit_discount * $requested_qty;
|
||||
$return_amount = ($detail->productPurchasePrice - $unit_discount) * $requested_qty;
|
||||
@@ -137,100 +170,88 @@ public function store(Request $request)
|
||||
$total_return_amount += $return_amount;
|
||||
$total_return_discount += $return_discount;
|
||||
|
||||
// Update stock & purchase details
|
||||
Stock::where('id', $detail->stock_id)->decrement('productStock', $requested_qty);
|
||||
//Update stock & purchase detail
|
||||
$detail->stock->decrement('productStock', $requested_qty);
|
||||
|
||||
$detail->quantities -= $requested_qty;
|
||||
$detail->timestamps = false;
|
||||
$detail->save();
|
||||
|
||||
// Collect return detail data
|
||||
$purchase_return_detail_data[] = [
|
||||
'purchase_detail_id' => $detail->id,
|
||||
'purchase_return_id' => $purchase_return->id,
|
||||
'return_qty' => $requested_qty,
|
||||
'business_id' => auth()->user()->business_id,
|
||||
'return_amount' => $return_amount,
|
||||
];
|
||||
// Remove serials from purchase detail
|
||||
if (!empty($serials) && !empty($detail->serial_numbers)) {
|
||||
$remainingDetailSerials = array_values(array_diff($detail->serial_numbers ?? [], $serials));
|
||||
$detail->update(['serial_numbers' => $remainingDetailSerials]);
|
||||
}
|
||||
|
||||
// Insert purchase return details
|
||||
if (!empty($purchase_return_detail_data)) {
|
||||
PurchaseReturnDetail::insert($purchase_return_detail_data);
|
||||
$returnDetail = PurchaseReturnDetail::create([
|
||||
'business_id' => $business_id,
|
||||
'purchase_return_id' => $purchase_return->id,
|
||||
'purchase_detail_id' => $detail->id,
|
||||
'return_qty' => $requested_qty,
|
||||
'return_amount' => $return_amount,
|
||||
'serial_numbers' => $serials ?? null,
|
||||
]);
|
||||
|
||||
$previous_returned_qty = PurchaseReturnDetail::where('purchase_detail_id', $detail->id)->sum('return_qty');
|
||||
$totalQty = $detail->quantities + $previous_returned_qty;
|
||||
|
||||
PurchaseVatTransaction::productReturnVatCalculation($detail, $requested_qty, $returnDetail, $totalQty);
|
||||
}
|
||||
|
||||
if ($total_return_amount <= 0) {
|
||||
return response()->json("You cannot return an empty product.", 400);
|
||||
return response()->json('You cannot return empty product.', 400);
|
||||
}
|
||||
|
||||
// Update party dues (if applicable)
|
||||
// Adjust party balances
|
||||
$party = Party::find($purchase->party_id);
|
||||
|
||||
if ($party) {
|
||||
$refund_amount = $total_return_amount;
|
||||
$refund = $total_return_amount;
|
||||
|
||||
// If party has due, reduce it first
|
||||
if ($party->due > 0) {
|
||||
if ($party->due >= $refund_amount) {
|
||||
$party->decrement('due', $refund_amount);
|
||||
$refund_amount = 0;
|
||||
} else {
|
||||
$refund_amount -= $party->due;
|
||||
$party->update(['due' => 0]);
|
||||
}
|
||||
$deduct = min($party->due, $refund);
|
||||
$party->decrement('due', $deduct);
|
||||
$refund -= $deduct;
|
||||
}
|
||||
|
||||
// Any remaining amount should be deducted from wallet
|
||||
if ($refund_amount > 0 && $party->wallet > 0) {
|
||||
$deduct = min($party->wallet, $refund_amount);
|
||||
if ($refund > 0 && $party->wallet > 0) {
|
||||
$deduct = min($party->wallet, $refund);
|
||||
$party->decrement('wallet', $deduct);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate remaining return amount
|
||||
$remaining_return_amount = max(0, $total_return_amount - $purchase->dueAmount);
|
||||
$new_total_amount = max(0, $purchase->totalAmount - $total_return_amount);
|
||||
|
||||
// Update purchase record
|
||||
$purchase->update([
|
||||
'change_amount' => 0,
|
||||
'dueAmount' => max(0, $purchase->dueAmount - $total_return_amount),
|
||||
'paidAmount' => max(0, $purchase->paidAmount - min($purchase->paidAmount, $total_return_amount)),
|
||||
'totalAmount' => $new_total_amount,
|
||||
'totalAmount' => max(0, $purchase->totalAmount - $total_return_amount),
|
||||
'discountAmount' => max(0, $purchase->discountAmount - $total_return_discount),
|
||||
'isPaid' => $remaining_return_amount > 0 ? 1 : $purchase->isPaid,
|
||||
]);
|
||||
|
||||
$payments = $request->payments;
|
||||
|
||||
if (isset($payments['main'])) {
|
||||
$mainPayment = $payments['main'];
|
||||
$mainPayment['amount'] = $request->receive_amount ?? 0;
|
||||
$payments = [$mainPayment];
|
||||
}
|
||||
|
||||
$payments = collect($payments)->map(function ($payment) use ($total_return_amount) {
|
||||
$payment['amount'] = $total_return_amount;
|
||||
return $payment;
|
||||
})->toArray();
|
||||
// Payment processing
|
||||
$payments = $request->payments ?? [];
|
||||
$payments = collect($payments)->map(fn($p) => array_merge($p, ['amount' => $total_return_amount]))->toArray();
|
||||
|
||||
event(new MultiPaymentProcessed(
|
||||
$payments,
|
||||
$purchase_return->id,
|
||||
'purchase_return',
|
||||
$total_return_amount ?? 0,
|
||||
$total_return_amount
|
||||
));
|
||||
|
||||
$tax_invoice = moduleCheck('TaxInvoiceAddon') && invoice_setting($purchase->business_id) == 'standard_a4';
|
||||
$invoice_route = $tax_invoice ? route('business.purchases.tax.invoice', $purchase->id) : route('business.purchases.invoice', $purchase->id);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Purchase returned successfully.'),
|
||||
'redirect' => route('business.purchase-returns.index'),
|
||||
'secondary_redirect_url' => route('business.purchases.invoice', $purchase->id),
|
||||
'secondary_redirect_url' => $invoice_route,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
return response()->json(['message' => __('Something went wrong!')], 500);
|
||||
return response()->json(['message' => __('Something went wrong!') . ' ' . $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Events\MultiPaymentProcessed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Party;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Sale;
|
||||
use App\Models\Party;
|
||||
use App\Models\Stock;
|
||||
use App\Models\Branch;
|
||||
use App\Models\SaleReturn;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\SaleReturnDetails;
|
||||
use App\Models\Stock;
|
||||
use App\Services\VatTransactionService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class SaleReturnController extends Controller
|
||||
{
|
||||
@@ -84,46 +85,67 @@ public function create(Request $request)
|
||||
return view('business::sale-returns.create', compact('sale', 'discount_per_unit_factor', 'avg_rounding_amount', 'payment_types'));
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
// split-array structure from front-end request
|
||||
$products = [];
|
||||
for ($index = 0; $index < count($request->products); $index += 3) {
|
||||
$products[] = [
|
||||
'detail_id' => $request->products[$index]['detail_id'] ?? null,
|
||||
'return_qty' => $request->products[$index + 1]['return_qty'] ?? 0,
|
||||
'serial_numbers' => $request->products[$index + 2]['serial_numbers'] ?? '[]',
|
||||
];
|
||||
}
|
||||
$request->merge(['products' => $products]);
|
||||
|
||||
$request->validate([
|
||||
'sale_id' => 'required|exists:sales,id',
|
||||
'return_qty' => 'required|array',
|
||||
'products' => 'required|array|min:1',
|
||||
'products.*.detail_id' => 'required|exists:sale_details,id',
|
||||
'products.*.return_qty' => 'required|integer',
|
||||
'products.*.serial_numbers' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$business_id = auth()->user()->business_id;
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$sale = Sale::with('details:id,sale_id,product_id,price,discount,lossProfit,quantities,productPurchasePrice,stock_id,expire_date', 'details.product:id,product_type', 'details.product.combo_products')
|
||||
// Load sale with details and product info
|
||||
$sale = Sale::with(
|
||||
'details:id,sale_id,product_id,price,discount,lossProfit,quantities,productPurchasePrice,stock_id,expire_date,serial_numbers',
|
||||
'details.product:id,product_type,has_serial',
|
||||
'details.product.combo_products'
|
||||
)
|
||||
->where('business_id', $business_id)
|
||||
->findOrFail($request->sale_id);
|
||||
|
||||
// Calculate total discount factor with itemwise discount
|
||||
$old_sale_due = $sale->dueAmount;
|
||||
|
||||
// Calculate discount factors
|
||||
$total_discount = $sale->discountAmount;
|
||||
$total_sale_amount = $sale->details->sum(fn($detail) => $detail->price * $detail->quantities);
|
||||
$discount_per_unit_factor = $total_sale_amount > 0 ? $total_discount / $total_sale_amount : 0;
|
||||
$rounding_amount_per_unit = $sale->details->sum('quantities') > 0 ? $sale->rounding_amount / $sale->details->sum('quantities') : 0;
|
||||
|
||||
// Create sale return record
|
||||
$sale_return = SaleReturn::create([
|
||||
'return_date' => now(),
|
||||
'business_id' => $business_id,
|
||||
'sale_id' => $request->sale_id,
|
||||
'invoice_no' => $sale->invoiceNumber,
|
||||
'return_date' => now(),
|
||||
]);
|
||||
|
||||
$sale_return_detail_data = [];
|
||||
$total_return_amount = 0;
|
||||
$total_return_discount = 0;
|
||||
$total_loss_profit_adjustment = 0;
|
||||
|
||||
foreach ($sale->details as $key => $detail) {
|
||||
$requested_qty = $request->return_qty[$key];
|
||||
foreach ($request->products as $indextem) {
|
||||
|
||||
if ($requested_qty <= 0) {
|
||||
continue;
|
||||
}
|
||||
$detail = $sale->details->where('id', $indextem['detail_id'])->first();
|
||||
if (!$detail) continue; // skip if detail not found
|
||||
|
||||
$requested_qty = (int) ($indextem['return_qty'] ?? 0);
|
||||
if ($requested_qty <= 0) continue;
|
||||
|
||||
if ($requested_qty > $detail->quantities) {
|
||||
return response()->json([
|
||||
@@ -131,12 +153,12 @@ public function store(Request $request)
|
||||
], 400);
|
||||
}
|
||||
|
||||
$product = $detail->product;
|
||||
$return_serials = !empty($indextem['serial_numbers']) ? json_decode($indextem['serial_numbers'], true) : [];
|
||||
|
||||
// Include SaleDetails discount in return calculation
|
||||
$unit_discount = $detail->price * $discount_per_unit_factor;
|
||||
$item_cart_discount = $detail->discount ?? 0;
|
||||
$total_discount_per_unit = $unit_discount + $item_cart_discount;
|
||||
$indextem_cart_discount = $detail->discount ?? 0;
|
||||
$total_discount_per_unit = $unit_discount + $indextem_cart_discount;
|
||||
|
||||
$return_discount = $total_discount_per_unit * $requested_qty;
|
||||
$return_amount = ($detail->price - $total_discount_per_unit + $rounding_amount_per_unit) * $requested_qty;
|
||||
@@ -144,70 +166,91 @@ public function store(Request $request)
|
||||
$total_return_amount += $return_amount;
|
||||
$total_return_discount += $return_discount;
|
||||
|
||||
if ($product && $product->product_type === 'combo') {
|
||||
$product = $detail->product;
|
||||
|
||||
$combo_total_purchase = 0;
|
||||
$combo_total_sale = $detail->price * $requested_qty;
|
||||
// Combo products
|
||||
if ($product && $product->product_type === 'combo') {
|
||||
|
||||
foreach ($product->combo_products as $comboItem) {
|
||||
$stock = Stock::find($comboItem->stock_id);
|
||||
|
||||
if (!$stock) {
|
||||
return response()->json([
|
||||
'message' => __("Stock not found for combo item '{$comboItem->product->productName}'"),
|
||||
], 400);
|
||||
}
|
||||
|
||||
// increase stock by combo component quantity * returned qty
|
||||
$restore_qty = $comboItem->quantity * $requested_qty;
|
||||
$stock->increment('productStock', $restore_qty);
|
||||
|
||||
$combo_total_purchase += $comboItem->purchase_price * $restore_qty;
|
||||
}
|
||||
|
||||
// loss/profit adjustment for combo
|
||||
$loss_profit_adjustment = ($combo_total_sale - $combo_total_purchase) - $return_discount;
|
||||
$total_loss_profit_adjustment += $loss_profit_adjustment;
|
||||
}
|
||||
|
||||
// Single / variant products
|
||||
else {
|
||||
$stock = Stock::where('id', $detail->stock_id)->first();
|
||||
if (!$stock) {
|
||||
return response()->json(['error' => 'Stock not found.'], 404);
|
||||
if (!$stock) return response()->json(['error' => 'Stock not found.'], 404);
|
||||
|
||||
if ($product->has_serial) {
|
||||
|
||||
// Validate serial count
|
||||
if (count($return_serials) !== $requested_qty) {
|
||||
return response()->json([
|
||||
'message' => 'Serial count must match return quantity'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$sold_serials = is_array($detail->serial_numbers) ? $detail->serial_numbers : json_decode($detail->serial_numbers ?? '[]', true);
|
||||
$indexnvalid = array_diff($return_serials, $sold_serials);
|
||||
if (!empty($indexnvalid)) {
|
||||
return response()->json(['message' => 'Invalid serial detected'], 400);
|
||||
}
|
||||
|
||||
// Restore stock
|
||||
$stock->increment('productStock', $requested_qty);
|
||||
|
||||
$loss_profit_adjustment = (($detail->price - $stock->productPurchasePrice) * $requested_qty) - $return_discount;
|
||||
$total_loss_profit_adjustment += $loss_profit_adjustment;
|
||||
// Restore serials to stock
|
||||
$stock_serials = $stock->serial_numbers ?? [];
|
||||
$stock->update([
|
||||
'serial_numbers' => array_values(array_unique(array_merge($stock_serials, $return_serials)))
|
||||
]);
|
||||
|
||||
// Remove serials from sale detail
|
||||
$detail->update([
|
||||
'serial_numbers' => array_values(array_diff($sold_serials, $return_serials))
|
||||
]);
|
||||
} else {
|
||||
$stock->increment('productStock', $requested_qty);
|
||||
}
|
||||
}
|
||||
|
||||
// Update sale details
|
||||
$loss_profit_adjustment = $detail->lossProfit * ($requested_qty / $detail->quantities);
|
||||
$total_loss_profit_adjustment += $loss_profit_adjustment;
|
||||
|
||||
// Update sale detail
|
||||
$detail->quantities -= $requested_qty;
|
||||
$detail->lossProfit -= $loss_profit_adjustment;
|
||||
$detail->timestamps = false;
|
||||
$detail->save();
|
||||
|
||||
$sale_return_detail_data[] = [
|
||||
$returnDetail = SaleReturnDetails::create([
|
||||
'business_id' => $business_id,
|
||||
'sale_detail_id' => $detail->id,
|
||||
'sale_return_id' => $sale_return->id,
|
||||
'return_qty' => $requested_qty,
|
||||
'return_amount' => $return_amount,
|
||||
];
|
||||
}
|
||||
'serial_numbers' => $return_serials ?? null,
|
||||
]);
|
||||
|
||||
if (!empty($sale_return_detail_data)) {
|
||||
SaleReturnDetails::insert($sale_return_detail_data);
|
||||
$previous_returned_qty = SaleReturnDetails::where('sale_detail_id', $detail->id)->sum('return_qty');
|
||||
$totalQty = $detail->quantities + $previous_returned_qty;
|
||||
|
||||
VatTransactionService::productReturnVatCalculation($detail, $requested_qty, $returnDetail, $totalQty);
|
||||
}
|
||||
|
||||
if ($total_return_amount <= 0) {
|
||||
return response()->json("You cannot return an empty product.", 400);
|
||||
}
|
||||
|
||||
// Remaining refund / party logic
|
||||
$remaining_refund = $total_return_amount;
|
||||
|
||||
// Adjust Due
|
||||
$new_due = $sale->dueAmount;
|
||||
if ($remaining_refund > 0) {
|
||||
if ($remaining_refund >= $sale->dueAmount) {
|
||||
@@ -219,7 +262,6 @@ public function store(Request $request)
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust Paid (refund part)
|
||||
$new_paid = $sale->paidAmount;
|
||||
if ($remaining_refund > 0) {
|
||||
if ($remaining_refund >= $sale->paidAmount) {
|
||||
@@ -231,9 +273,7 @@ public function store(Request $request)
|
||||
}
|
||||
}
|
||||
|
||||
// total sale amount
|
||||
$new_total_amount = max(0, $sale->totalAmount - $total_return_amount);
|
||||
|
||||
$sale->update([
|
||||
'change_amount' => 0,
|
||||
'dueAmount' => $new_due,
|
||||
@@ -244,39 +284,38 @@ public function store(Request $request)
|
||||
'lossProfit' => $sale->lossProfit - $total_loss_profit_adjustment,
|
||||
]);
|
||||
|
||||
// Party Refund Logic
|
||||
$party = Party::find($sale->party_id);
|
||||
// Party refund logic
|
||||
$due_reduction = $old_sale_due - $new_due;
|
||||
|
||||
if ($party) {
|
||||
if ($due_reduction > 0) {
|
||||
Party::where('business_id', $business_id)
|
||||
->where('id', $sale->party_id)
|
||||
->decrement('due', $due_reduction);
|
||||
}
|
||||
|
||||
// use leftover refund after due/paid adjustments
|
||||
$refund_amount = $remaining_refund;
|
||||
$party = Party::where('business_id', $business_id)->find($sale->party_id);
|
||||
|
||||
if ($party && $remaining_refund > 0) {
|
||||
|
||||
// Reduce party due
|
||||
if ($party->due > 0) {
|
||||
if ($party->due >= $refund_amount) {
|
||||
$party->decrement('due', $refund_amount);
|
||||
$refund_amount = 0;
|
||||
|
||||
if ($party->due >= $remaining_refund) {
|
||||
$party->decrement('due', $remaining_refund);
|
||||
$remaining_refund = 0;
|
||||
} else {
|
||||
$refund_amount -= $party->due;
|
||||
$remaining_refund -= $party->due;
|
||||
$party->update(['due' => 0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add leftover refund to wallet
|
||||
if ($refund_amount > 0) {
|
||||
$party->increment('wallet', $refund_amount);
|
||||
if ($remaining_refund > 0) {
|
||||
$party->increment('wallet', $remaining_refund);
|
||||
}
|
||||
}
|
||||
|
||||
$payments = $request->payments;
|
||||
|
||||
if (isset($payments['main'])) {
|
||||
$mainPayment = $payments['main'];
|
||||
$mainPayment['amount'] = $request->receive_amount ?? 0;
|
||||
$payments = [$mainPayment];
|
||||
}
|
||||
|
||||
// Payment event
|
||||
$payments = $request->payments ?? [];
|
||||
$payments = collect($payments)->map(function ($payment) use ($total_return_amount) {
|
||||
$payment['amount'] = $total_return_amount;
|
||||
return $payment;
|
||||
@@ -286,20 +325,22 @@ public function store(Request $request)
|
||||
$payments,
|
||||
$sale_return->id,
|
||||
'sale_return',
|
||||
$total_return_amount ?? 0,
|
||||
$total_return_amount,
|
||||
));
|
||||
|
||||
$tax_invoice = moduleCheck('TaxInvoiceAddon') && invoice_setting($sale->business_id) == 'standard_a4';
|
||||
$invoice_route = $tax_invoice ? route('business.sales.tax.invoice', $sale->id) : route('business.sales.invoice', $sale->id);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Sale returned successfully.'),
|
||||
'redirect' => route('business.sale-returns.index'),
|
||||
'secondary_redirect_url' => route('business.sales.invoice', $sale->id),
|
||||
'secondary_redirect_url' => $invoice_route,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
return response()->json(['message' => __('Something went wrong!')], 500);
|
||||
return response()->json(['message' => __('Something went wrong!') . ' ' . $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
namespace Modules\Business\App\Http\Controllers;
|
||||
|
||||
use App\Models\Option;
|
||||
use App\Models\Business;
|
||||
use App\Helpers\HasUploader;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\BusinessCategory;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Business;
|
||||
use App\Models\BusinessCategory;
|
||||
// use App\Models\Country;
|
||||
use App\Models\Option;
|
||||
// use App\Models\State;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SettingController extends Controller
|
||||
{
|
||||
@@ -18,14 +20,16 @@ class SettingController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$setting = Option::where('key', 'business-settings')
|
||||
->where('value', 'LIKE', '%"business_id":%' . auth()->user()->business_id . '%')
|
||||
->where('value', 'LIKE', '%"business_id":' . auth()->user()->business_id . '%')
|
||||
->get()
|
||||
->firstWhere('value.business_id', auth()->user()->business_id);
|
||||
|
||||
$business_categories = BusinessCategory::whereStatus(1)->latest()->get();
|
||||
$business = Business::findOrFail(auth()->user()->business_id);
|
||||
$countries = [];
|
||||
$states = [];
|
||||
|
||||
return view('business::settings.general', compact('setting', 'business_categories', 'business'));
|
||||
return view('business::settings.general', compact('setting', 'business_categories', 'business', 'countries', 'states'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
@@ -56,6 +60,8 @@ public function update(Request $request, $id)
|
||||
'show_invoice_scanner_logo' => 'nullable|boolean',
|
||||
'show_a4_invoice_logo' => 'nullable|boolean',
|
||||
'show_thermal_invoice_logo' => 'nullable|boolean',
|
||||
// 'country_id' => 'nullable|exists:countries,id',
|
||||
// 'state_id' => 'nullable|exists:states,id',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
@@ -71,14 +77,12 @@ public function update(Request $request, $id)
|
||||
'email' => $request->email,
|
||||
'vat_name' => $request->vat_name,
|
||||
'vat_no' => $request->vat_no,
|
||||
// 'country_id' => $request->country_id,
|
||||
// 'state_id' => $request->state_id,
|
||||
]);
|
||||
|
||||
$moduleKeys = [
|
||||
'show_company_name',
|
||||
'show_phone_number',
|
||||
'show_address',
|
||||
'show_email',
|
||||
'show_vat',
|
||||
'show_company_name', 'show_phone_number', 'show_address', 'show_email', 'show_vat',
|
||||
];
|
||||
|
||||
$modules = [];
|
||||
@@ -96,7 +100,7 @@ public function update(Request $request, $id)
|
||||
|
||||
if ($setting) {
|
||||
$setting->update($request->except($data) + [
|
||||
'value' => $request->except('_token', '_method', 'a4_invoice_logo', 'thermal_invoice_logo', 'invoice_scanner_logo', 'address', 'companyName', 'business_category_id', 'phoneNumber', 'email', 'show_company_name', 'show_phone_number', 'show_address', 'show_email', 'show_vat') + [
|
||||
'value' => $request->except('_token', '_method', 'a4_invoice_logo', 'thermal_invoice_logo', 'invoice_scanner_logo', 'address', 'companyName', 'business_category_id', 'phoneNumber', 'email', 'show_company_name', 'show_phone_number', 'show_address', 'show_email', 'show_vat' ) + [
|
||||
'business_id' => $business->id,
|
||||
'a4_invoice_logo' => $request->a4_invoice_logo ? $this->upload($request, 'a4_invoice_logo', $setting->value['a4_invoice_logo'] ?? null) : ($setting->value['a4_invoice_logo'] ?? null),
|
||||
'thermal_invoice_logo' => $request->thermal_invoice_logo ? $this->upload($request, 'thermal_invoice_logo', $setting->value['thermal_invoice_logo'] ?? null) : ($setting->value['thermal_invoice_logo'] ?? null),
|
||||
@@ -140,7 +144,7 @@ public function update(Request $request, $id)
|
||||
'show_invoice_scanner_logo' => 1,
|
||||
'show_a4_invoice_logo' => 1,
|
||||
'show_thermal_invoice_logo' => 1,
|
||||
'show_warranty' => 1,
|
||||
'show_warranty' => 1 ,
|
||||
]),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
|
||||
0
Modules/Business/App/Providers/.gitkeep
Normal file
0
Modules/Business/App/Providers/.gitkeep
Normal file
0
Modules/Business/Database/Seeders/.gitkeep
Normal file
0
Modules/Business/Database/Seeders/.gitkeep
Normal file
0
Modules/Business/config/.gitkeep
Normal file
0
Modules/Business/config/.gitkeep
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user