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\PaymentType;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportBalanceSheet implements FromView
|
class ExportBalanceSheet implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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')
|
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
|
||||||
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
||||||
->where('business_id', $businessId);
|
->where('business_id', $businessId);
|
||||||
|
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
|
||||||
$products = $productQuery->get()
|
$products = $productQuery->get()
|
||||||
->map(function ($item) {
|
->map(function ($item) {
|
||||||
$item->source = 'product';
|
$item->source = 'product';
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
|
||||||
// BANK
|
|
||||||
$bankQuery = PaymentType::where('business_id', $businessId);
|
$bankQuery = PaymentType::where('business_id', $businessId);
|
||||||
|
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
|
||||||
$banks = $bankQuery->get()
|
$banks = $bankQuery->get()
|
||||||
->map(function ($item) {
|
->map(function ($item) {
|
||||||
$item->source = 'bank';
|
$item->source = 'bank';
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
|
||||||
$asset_datas = $products->merge($banks);
|
$asset_datas = $products->merge($banks)->take($perPage);
|
||||||
|
|
||||||
// TOTAL STOCK VALUE
|
|
||||||
$total_stock_value = 0;
|
$total_stock_value = 0;
|
||||||
foreach ($products as $product) {
|
foreach ($products as $product) {
|
||||||
if (in_array($product->product_type, ['single', 'variant'])) {
|
if (in_array($product->product_type, ['single', 'variant'])) {
|
||||||
|
|||||||
@@ -3,17 +3,42 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportBillWisePofit implements FromView
|
class ExportBillWisePofit implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$profits = Sale::with('party:id,name')
|
$salesQuery = Sale::with('party:id,name')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id);
|
||||||
->latest()
|
|
||||||
->get();
|
$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'));
|
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;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportCashFlowReport implements FromView
|
class ExportCashFlowReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$cash_flows = Transaction::with([
|
$query = Transaction::with([
|
||||||
'paymentType:id,name',
|
'paymentType:id,name',
|
||||||
'sale:id,party_id',
|
'sale:id,party_id',
|
||||||
'sale.party:id,name',
|
'sale.party:id,name',
|
||||||
@@ -22,11 +25,44 @@ public function view(): View
|
|||||||
'dueCollect.party:id,name',
|
'dueCollect.party:id,name',
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('type', ['debit', 'credit'])
|
->whereIn('type', ['debit', 'credit']);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
|
// 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;
|
$opening_balance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return view('business::cash-flow.excel-csv', compact('cash_flows', 'opening_balance'));
|
return view('business::cash-flow.excel-csv', compact('cash_flows', 'opening_balance'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,39 @@ class ExportComboProduct implements FromView
|
|||||||
|
|
||||||
public function view(): View
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', 'combo')
|
->where('product_type', 'combo')
|
||||||
->withCount('combo_products as total_combo_products')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit(request('per_page') ?? 20)->get();
|
||||||
|
|
||||||
$combo_products->transform(function ($product) {
|
$combo_products->transform(function ($product) {
|
||||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||||
|
|||||||
@@ -11,12 +11,39 @@ class ExportComboProductReport implements FromView
|
|||||||
|
|
||||||
public function view(): View
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', 'combo')
|
->where('product_type', 'combo')
|
||||||
->withCount('combo_products as total_combo_products')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit(request('per_page') ?? 20)->get();
|
||||||
|
|
||||||
$combo_products->transform(function ($product) {
|
$combo_products->transform(function ($product) {
|
||||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
||||||
|
|||||||
@@ -10,21 +10,58 @@ class ExportCurrentStock implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$query = Product::with('stocks')
|
$businessId = auth()->user()->business_id;
|
||||||
->where('product_type', '!=', 'combo')
|
$alert_qty_filter = request('alert_qty');
|
||||||
->where('business_id', auth()->user()->business_id);
|
$search_term = request('search');
|
||||||
|
$per_page = request('per_page', 20);
|
||||||
|
|
||||||
if (request('alert_qty')) {
|
// Base query
|
||||||
$products = $query->get()->filter(function ($product) {
|
$query = Product::with('stocks', 'category:id,categoryName')
|
||||||
$totalStock = $product->stocks->sum('productStock');
|
->where('product_type', '!=', 'combo')
|
||||||
return $totalStock <= $product->alert_qty;
|
->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 {
|
} 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', [
|
return view('business::stocks.excel-csv', compact('products', 'total_stock_qty', 'total_stock_value'));
|
||||||
'products' => $products
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,27 @@ class ExportCurrentStockReport implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.stocks.excel-csv', [
|
$productsQuery = Product::with(['stocks' => function ($q) {
|
||||||
'stock_reports' => Product::with('stocks')
|
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
|
||||||
|
}])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', '!=', 'combo')
|
->where('product_type', '!=', 'combo');
|
||||||
->withSum('stocks', 'productStock')
|
|
||||||
|
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()
|
->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')
|
$customers = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit(request('per_page') ?? 20)->get();
|
||||||
|
|
||||||
$totalAmount = $customers->sum(function ($customer) {
|
$totalAmount = $customers->sum(function ($customer) {
|
||||||
return $customer->sales?->sum('totalAmount') ?? 0;
|
return $customer->sales?->sum('totalAmount') ?? 0;
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportDayBookReport implements FromView
|
class ExportDayBookReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$day_books = Transaction::with([
|
$query = Transaction::with([
|
||||||
'paymentType:id,name',
|
'paymentType:id,name',
|
||||||
'sale:id,user_id,party_id,totalAmount',
|
'sale:id,user_id,party_id,totalAmount',
|
||||||
'sale.party:id,name',
|
'sale.party:id,name',
|
||||||
@@ -25,9 +28,34 @@ public function view(): View
|
|||||||
'dueCollect.user:id,name',
|
'dueCollect.user:id,name',
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('type', ['debit', 'credit'])
|
->whereIn('type', ['debit', 'credit']);
|
||||||
->latest()
|
|
||||||
->get();
|
// 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'));
|
return view('business::day-book.excel-csv', compact('day_books'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,33 @@ class ExportDiscountProduct implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
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) {
|
->whereHas('product', function ($q) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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)
|
->where('discount', '>', 0)
|
||||||
|
->limit(request('per_page') ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return view('business::reports.discount-products.excel-csv', compact('discount_products'));
|
return view('business::reports.discount-products.excel-csv', compact('discount_products'));
|
||||||
|
|||||||
@@ -11,37 +11,56 @@ class ExportDue implements FromView
|
|||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
|
||||||
$activeBranch = $user->active_branch;
|
$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')
|
->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')
|
->with('sales_dues')
|
||||||
->latest();
|
->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();
|
$parties = $query->get();
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
$parties = $parties
|
||||||
$supplier->due = $supplier->sales_dues
|
->transform(function ($customer) use ($activeBranch) {
|
||||||
|
$party_due = $customer->sales_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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', [
|
return view('business::reports.due.excel-csv', compact('parties'));
|
||||||
'parties' => $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;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportExpense implements FromView
|
class ExportExpense implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.expense.excel-csv', [
|
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
'expense_reports' => Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
|
->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
|
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)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->withSum('stocks as total_stock', 'productStock')
|
->withSum('stocks as total_stock', 'productStock')
|
||||||
->whereHas('stocks', function ($query) {
|
->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', [
|
return view('business::expired-products.excel-csv', compact('expired_products'));
|
||||||
'expired_products' => $expired_products
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,52 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportExpiredProductReport implements FromView
|
class ExportExpiredProductReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.expired-products.excel-csv', [
|
$businessId = auth()->user()->business_id;
|
||||||
'expired_products' => Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
|
$expiredProductsQuery = Product::with(['unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks'])
|
||||||
->withSum('stocks', 'productStock')
|
->withSum('stocks', 'productStock')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->whereHas('stocks', function ($query) {
|
->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()
|
->orWhereHas('brand', function ($q) use ($search) {
|
||||||
->get()
|
$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;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Income;
|
use App\Models\Income;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportIncome implements FromView
|
class ExportIncome implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.income.excel-csv', [
|
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
'income_reports' => Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
|
->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;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportLossProfitHistory implements FromView
|
class ExportLossProfitHistory implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
$businessId = $user->business_id;
|
||||||
|
$perPage = request('per_page') ?? 20;
|
||||||
|
|
||||||
$branchId = null;
|
$branchId = null;
|
||||||
if (moduleCheck('MultiBranchAddon')) {
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SALES
|
$duration = request('custom_days') ?: 'today';
|
||||||
$dailySales = DB::table('sales')
|
|
||||||
|
$salesQuery = DB::table('sales')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"saleDate"::date as date'),
|
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(actual_total_amount) as total_sales'),
|
||||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"saleDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->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',
|
'type' => 'Sale',
|
||||||
'date' => $sale->date,
|
'date' => $sale->date,
|
||||||
|
'profit_type' => $sale->profit_type,
|
||||||
'total_sales' => $sale->total_sales,
|
'total_sales' => $sale->total_sales,
|
||||||
'total_incomes' => $sale->total_sale_income,
|
'total_incomes' => $sale->total_sale_income,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// INCOME
|
$incomeQuery = DB::table('incomes')
|
||||||
$dailyIncomes = DB::table('incomes')
|
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"incomeDate"::date as date'),
|
DB::raw('"incomeDate"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_incomes')
|
DB::raw('SUM(amount) as total_incomes')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"incomeDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->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',
|
'type' => 'Income',
|
||||||
'date' => $income->date,
|
'date' => $income->date,
|
||||||
'total_incomes' => $income->total_incomes,
|
'total_incomes' => $income->total_incomes,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// MERGE SALE + INCOME
|
|
||||||
$mergedIncomeSaleData = collect();
|
$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) {
|
foreach ($allDates as $date) {
|
||||||
|
|
||||||
if ($income = $income_datas->firstWhere('date', $date)) {
|
if ($income = $income_datas->firstWhere('date', $date)) {
|
||||||
$mergedIncomeSaleData->push($income);
|
$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);
|
$mergedIncomeSaleData->push($sale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PAYROLL
|
|
||||||
$dailyPayrolls = collect();
|
$dailyPayrolls = collect();
|
||||||
|
|
||||||
if (moduleCheck('HrmAddon')) {
|
if (moduleCheck('HrmAddon')) {
|
||||||
$dailyPayrolls = DB::table('payrolls')
|
$payrollQuery = DB::table('payrolls')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"date"::date as date'),
|
DB::raw('"date"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_payrolls')
|
DB::raw('SUM(amount) as total_payrolls')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"date"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->groupBy(DB::raw('"date"::date'));
|
||||||
|
|
||||||
|
$this->applyDateFilter($payrollQuery, $duration, 'date', request('from_date'), request('to_date'));
|
||||||
|
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPENSES
|
$expenseQuery = DB::table('expenses')
|
||||||
$dailyExpenses = DB::table('expenses')
|
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"expenseDate"::date as date'),
|
DB::raw('"expenseDate"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_expenses_only')
|
DB::raw('SUM(amount) as total_expenses_only')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"expenseDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->groupBy(DB::raw('"expenseDate"::date'));
|
||||||
|
|
||||||
|
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', request('from_date'), request('to_date'));
|
||||||
|
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||||
|
|
||||||
$mergedExpenseData = collect();
|
$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) {
|
foreach ($allExpenseDates as $date) {
|
||||||
|
|
||||||
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
||||||
$mergedExpenseData->push((object)[
|
$mergedExpenseData->push((object)[
|
||||||
'type' => 'Expense',
|
'type' => 'Expense',
|
||||||
@@ -101,6 +149,7 @@ public function view(): View
|
|||||||
'total_expenses' => $expense->total_expenses_only,
|
'total_expenses' => $expense->total_expenses_only,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
||||||
$mergedExpenseData->push((object)[
|
$mergedExpenseData->push((object)[
|
||||||
'type' => 'Payroll',
|
'type' => 'Payroll',
|
||||||
@@ -110,9 +159,9 @@ public function view(): View
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUMMARY
|
|
||||||
$grossSaleProfit = $sale_datas->sum('total_sales');
|
$grossSaleProfit = $sale_datas->sum('total_sales');
|
||||||
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
||||||
|
|
||||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,13 @@ public function view(): View
|
|||||||
$parties = Party::with('sales')
|
$parties = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->where('type', '!=', 'Supplier')
|
||||||
|
->when(request('search'), function ($query) {
|
||||||
|
$query->where(function ($q) {
|
||||||
|
$q->where('name', 'like', '%' . request('search') . '%');
|
||||||
|
});
|
||||||
|
})
|
||||||
->latest()
|
->latest()
|
||||||
|
->limit(request('per_page') ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return view('business::party-reports.loss-profit.excel-csv', compact('parties'));
|
return view('business::party-reports.loss-profit.excel-csv', compact('parties'));
|
||||||
|
|||||||
@@ -8,10 +8,61 @@
|
|||||||
|
|
||||||
class ExportProduct implements FromView
|
class ExportProduct implements FromView
|
||||||
{
|
{
|
||||||
|
|
||||||
public function view(): View
|
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', [
|
return view('business::products.excel-csv', [
|
||||||
'products' => $products
|
'products' => $products
|
||||||
|
|||||||
@@ -11,23 +11,35 @@ class ExportProductLossProfit implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
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')
|
$baseQuery = SaleDetails::query()
|
||||||
->whereHas('product', function ($q) {
|
->whereHas(
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
'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) {
|
->when(request('search'), function ($q) {
|
||||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
$q->whereHas('product', function ($q) {
|
||||||
$sale->where('branch_id', $branchId);
|
$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(
|
->select(
|
||||||
'product_id',
|
'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 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 loss')
|
||||||
)
|
)
|
||||||
->groupBy('product_id')
|
->groupBy('product_id')
|
||||||
|
->limit(request('per_page') ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return view('business::reports.product-loss-profit.excel-csv', compact('product_lossProfits'));
|
return view('business::reports.product-loss-profit.excel-csv', compact('product_lossProfits'));
|
||||||
|
|||||||
@@ -3,29 +3,54 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductPurchaseHistoryDetailReport implements FromView
|
class ExportProductPurchaseHistoryDetailReport implements FromView
|
||||||
{
|
{
|
||||||
protected $id;
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function __construct($id)
|
protected string $id;
|
||||||
|
|
||||||
|
public function __construct(string $id)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
|
$businessId = auth()->user()->business_id;
|
||||||
|
$duration = request('custom_days') ?: 'today';
|
||||||
|
|
||||||
$product = Product::select('id', 'business_id', 'productName')
|
$product = Product::select('id', 'business_id', 'productName')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->findOrFail($this->id);
|
->findOrFail($this->id);
|
||||||
|
|
||||||
$purchaseDetailsQuery = $product->purchaseDetails()
|
$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');
|
->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'));
|
return view('business::product-purchase-history-report.excel-csv-detail', compact('product', 'purchaseDetails'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,30 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductPurchaseHistoryReport implements FromView
|
class ExportProductPurchaseHistoryReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$businessId = auth()->user()->business_id;
|
||||||
|
$duration = request('custom_days') ?: 'today';
|
||||||
|
|
||||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
|
||||||
$products = $productQuery->get();
|
->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) {
|
$total_purchase_qty = $products->sum(function ($product) {
|
||||||
return $product->purchaseDetails->sum('quantities');
|
return $product->purchaseDetails->sum('quantities');
|
||||||
|
|||||||
@@ -2,21 +2,44 @@
|
|||||||
|
|
||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
|
||||||
use App\Models\PurchaseDetails;
|
use App\Models\PurchaseDetails;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductPurchaseReport implements FromView
|
class ExportProductPurchaseReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
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) {
|
->whereHas('purchase', function ($q) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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'));
|
return view('business::reports.product-purchase.excel-csv', compact('product_purchases'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,29 +3,53 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductSaleHistoryDetailReport implements FromView
|
class ExportProductSaleHistoryDetailReport implements FromView
|
||||||
{
|
{
|
||||||
protected $id;
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function __construct($id)
|
protected string $id;
|
||||||
|
|
||||||
|
public function __construct(string $id)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
|
$businessId = auth()->user()->business_id;
|
||||||
|
$duration = request('custom_days') ?: 'today';
|
||||||
$product = Product::select('id', 'business_id', 'productName')
|
$product = Product::select('id', 'business_id', 'productName')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->findOrFail($this->id);
|
->findOrFail($this->id);
|
||||||
|
|
||||||
$saleDetailsQuery = $product->saleDetails()
|
$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')
|
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||||
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
|
->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'));
|
return view('business::product-sale-history-report.excel-csv-detail', compact('product', 'saleDetails'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,30 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductSaleHistoryReport implements FromView
|
class ExportProductSaleHistoryReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$businessId = auth()->user()->business_id;
|
||||||
|
$duration = request('custom_days') ?: 'today';
|
||||||
|
|
||||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
|
||||||
$products = $productQuery->get();
|
->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) {
|
$total_single_sale_price = $products->sum(function ($product) {
|
||||||
return $product->saleDetails->sum('price');
|
return $product->saleDetails->sum('price');
|
||||||
|
|||||||
@@ -3,18 +3,45 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
|
use App\Models\SaleDetails;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportProductSaleReport implements FromView
|
class ExportProductSaleReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$product_sales = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
|
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->whereHas('sale', function ($q) {
|
||||||
->latest()
|
$q->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
});
|
||||||
|
|
||||||
|
// 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'));
|
return view('business::reports.product-sale.excel-csv', compact('product_sales'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Purchase;
|
use App\Models\Purchase;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportPurchaseReturn implements FromView
|
class ExportPurchaseReturn implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$purchases = Purchase::with([
|
$purchasesQuery = Purchase::with([
|
||||||
'user:id,name',
|
'user:id,name',
|
||||||
'branch:id,name',
|
'branch:id,name',
|
||||||
'party:id,name,email,phone,type',
|
'party:id,name,email,phone,type',
|
||||||
@@ -22,9 +25,32 @@ public function view(): View
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereHas('purchaseReturns')
|
->whereHas('purchaseReturns');
|
||||||
->latest()
|
|
||||||
->get();
|
$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'));
|
return view('business::reports.purchase-return.excel-csv', compact('purchases'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,46 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportSaleReport implements FromView
|
class ExportSaleReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
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)
|
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->latest()
|
->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
|
||||||
|
$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'));
|
return view('business::reports.sales.excel', compact('sales'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportSalesReturn implements FromView
|
class ExportSalesReturn implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$sales = Sale::with([
|
$salesQuery = Sale::with([
|
||||||
'user:id,name',
|
'user:id,name',
|
||||||
'party:id,name',
|
'party:id,name',
|
||||||
'branch:id,name',
|
'branch:id,name',
|
||||||
@@ -23,9 +26,30 @@ public function view(): View
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereHas('saleReturns')
|
->when(request('branch_id'), function ($q) {
|
||||||
->latest()
|
$q->where('branch_id', request('branch_id'));
|
||||||
->get();
|
})->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'));
|
return view('business::reports.sales-return.excel-csv', compact('sales'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
|
use App\Models\Party;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class ExportSingleCustomerLedger implements FromView
|
class ExportSingleCustomerLedger implements FromView
|
||||||
{
|
{
|
||||||
public $ledger;
|
public Collection $ledger;
|
||||||
public $party;
|
public Party $party;
|
||||||
|
|
||||||
public function __construct($ledger, $party)
|
public function __construct(Collection $ledger, Party $party)
|
||||||
{
|
{
|
||||||
$this->ledger = $ledger;
|
$this->ledger = $ledger;
|
||||||
$this->party = $party;
|
$this->party = $party;
|
||||||
|
|||||||
@@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
|
use App\Models\Party;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class ExportSingleSupplierLedger implements FromView
|
class ExportSingleSupplierLedger implements FromView
|
||||||
{
|
{
|
||||||
public $ledger;
|
public Collection $ledger;
|
||||||
public $party;
|
public Party $party;
|
||||||
|
|
||||||
public function __construct($ledger, $party)
|
public function __construct(Collection $ledger, Party $party)
|
||||||
{
|
{
|
||||||
$this->ledger = $ledger;
|
$this->ledger = $ledger;
|
||||||
$this->party = $party;
|
$this->party = $party;
|
||||||
|
|||||||
@@ -3,15 +3,44 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\PlanSubscribe;
|
use App\Models\PlanSubscribe;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportSubscription implements FromView
|
class ExportSubscription implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.subscription-reports.excel-csv', [
|
$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);
|
||||||
'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()
|
|
||||||
]);
|
// 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)
|
$query = Party::where('business_id', $businessId)
|
||||||
->where('type', 'Supplier')
|
->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')
|
->with('purchases_dues')
|
||||||
->latest();
|
->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();
|
$parties = $query->get();
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
$parties = $parties
|
||||||
$supplier->due = $supplier->purchases_dues
|
->transform(function ($supplier) use ($activeBranch) {
|
||||||
|
$party_due = $supplier->purchases_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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', [
|
return $supplier;
|
||||||
'parties' => $parties
|
})
|
||||||
]);
|
->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')
|
$suppliers = Party::with('purchases')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '=', 'Supplier')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit(request('per_page') ?? 20)->get();
|
||||||
|
|
||||||
$totalAmount = $suppliers->sum(function ($customer) {
|
$totalAmount = $suppliers->sum(function ($customer) {
|
||||||
return $customer->purchases?->sum('totalAmount') ?? 0;
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->where('type', '!=', 'Supplier')
|
||||||
->whereHas('sales')
|
->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')
|
->withCount('sales')
|
||||||
->withSum('sales', 'totalAmount')
|
->withSum('sales', 'totalAmount')
|
||||||
->orderByDesc('sales_count')
|
->orderByDesc('sales_count')
|
||||||
->orderByDesc('sales_sum_total_amount')
|
->orderByDesc('sales_sum_total_amount')
|
||||||
|
->when(request('type'), function ($q) {
|
||||||
|
$q->where(function ($q) {
|
||||||
|
$q->where('type', request('type'));
|
||||||
|
});
|
||||||
|
})
|
||||||
->take(5)
|
->take(5)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
|||||||
@@ -11,25 +11,38 @@ class ExportTopProduct implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
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')
|
$branchId = null;
|
||||||
->whereHas('product', function ($q) {
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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) {
|
->when($branchId, function ($q) use ($branchId) {
|
||||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||||
$sale->where('branch_id', $branchId);
|
$q->where('branch_id', $branchId);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->select(
|
->select(
|
||||||
'product_id',
|
'product_id',
|
||||||
DB::raw('SUM(quantities) as total_sold_qty'),
|
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')
|
->groupBy('product_id')
|
||||||
->orderByDesc('total_sold_qty')
|
->orderByDesc('total_sold_qty')
|
||||||
->take(5)
|
->limit(5)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return view('business::reports.top-products.excel-csv', compact('top_products'));
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('type', '=', 'Supplier')
|
->where('type', '=', 'Supplier')
|
||||||
->whereHas('purchases')
|
->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')
|
->withCount('purchases')
|
||||||
->withSum('purchases', 'totalAmount')
|
->withSum('purchases', 'totalAmount')
|
||||||
->orderByDesc('purchases_count')
|
->orderByDesc('purchases_count')
|
||||||
|
|||||||
@@ -3,15 +3,49 @@
|
|||||||
namespace Modules\Business\App\Exports;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\DueCollect;
|
use App\Models\DueCollect;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportTransaction implements FromView
|
class ExportTransaction implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::reports.transaction-history.excel-csv', [
|
$businessId = auth()->user()->business_id;
|
||||||
'transactions' => DueCollect::where('business_id', auth()->user()->business_id)->with('party:id,name,type', 'payment_type:id,name', 'transactions')->latest()->get()
|
$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;
|
namespace Modules\Business\App\Exports;
|
||||||
|
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
use Maatwebsite\Excel\Concerns\FromView;
|
||||||
|
|
||||||
class ExportTransactionReport implements FromView
|
class ExportTransactionReport implements FromView
|
||||||
{
|
{
|
||||||
|
use DateFilterTrait;
|
||||||
|
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
$transactions = Transaction::with('paymentType')
|
$businessId = auth()->user()->business_id;
|
||||||
->where('business_id', auth()->user()->business_id)
|
$transactionsQuery = Transaction::with('paymentType')
|
||||||
->latest()
|
->where('business_id', $businessId);
|
||||||
->get();
|
|
||||||
|
$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'));
|
return view('business::transactions.excel-csv', compact('transactions'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,45 @@ class ExportTransfer implements FromView
|
|||||||
{
|
{
|
||||||
public function view(): View
|
public function view(): View
|
||||||
{
|
{
|
||||||
return view('business::transfers.excel-csv', [
|
$user = auth()->user();
|
||||||
'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()
|
$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)
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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')
|
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
|
||||||
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
|
||||||
->where('business_id', $businessId);
|
->where('business_id', $businessId);
|
||||||
|
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
|
||||||
$products = $productQuery->get()
|
$products = $productQuery->get()
|
||||||
->map(function ($item) {
|
->map(function ($item) {
|
||||||
$item->source = 'product';
|
$item->source = 'product';
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
|
||||||
// BANK
|
|
||||||
$bankQuery = PaymentType::where('business_id', $businessId);
|
$bankQuery = PaymentType::where('business_id', $businessId);
|
||||||
|
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
|
||||||
$banks = $bankQuery->get()
|
$banks = $bankQuery->get()
|
||||||
->map(function ($item) {
|
->map(function ($item) {
|
||||||
$item->source = 'bank';
|
$item->source = 'bank';
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
|
||||||
$asset_datas = $products->merge($banks);
|
$asset_datas = $products->merge($banks)->take($perPage);
|
||||||
|
|
||||||
// TOTAL STOCK VALUE
|
|
||||||
$total_stock_value = 0;
|
$total_stock_value = 0;
|
||||||
foreach ($products as $product) {
|
foreach ($products as $product) {
|
||||||
if (in_array($product->product_type, ['single', 'variant'])) {
|
if (in_array($product->product_type, ['single', 'variant'])) {
|
||||||
@@ -143,6 +148,6 @@ public function exportPdf(Request $request)
|
|||||||
$totalBankBalance = $banks->sum('balance');
|
$totalBankBalance = $banks->sum('balance');
|
||||||
$total_asset = $total_stock_value + $totalBankBalance;
|
$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');
|
return Excel::download(new ExportBillWisePofit, 'bill-wise-profit.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$profits = Sale::with('party:id,name')
|
$salesQuery = Sale::with('party:id,name')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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\PaymentType;
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
use App\Http\Controllers\Controller;
|
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\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Modules\Business\App\Exports\ExportCashBalance;
|
||||||
|
|
||||||
class AcnooCashController extends Controller
|
class AcnooCashController extends Controller
|
||||||
{
|
{
|
||||||
use HasUploader;
|
use HasUploader;
|
||||||
|
|
||||||
|
use DateFilterTrait, DateRangeTrait;
|
||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$business_id = auth()->user()->business_id;
|
$business_id = auth()->user()->business_id;
|
||||||
@@ -24,37 +30,16 @@ public function index(Request $request)
|
|||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
|
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
|
||||||
|
|
||||||
// Default to today
|
// Date Filter
|
||||||
$startDate = Carbon::today()->format('Y-m-d');
|
$duration = $request->custom_days ?: 'today';
|
||||||
$endDate = Carbon::today()->format('Y-m-d');
|
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||||
|
|
||||||
if ($request->custom_days === 'yesterday') {
|
$this->applyDateFilter($cash, $duration, 'date', $request->from_date, $request->to_date);
|
||||||
$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);
|
|
||||||
|
|
||||||
$cashes = $cash->when(request('search'), function ($q) use ($request) {
|
$cashes = $cash->when(request('search'), function ($q) use ($request) {
|
||||||
$q->where(function ($q) use ($request) {
|
$q->where(function ($q) use ($request) {
|
||||||
$q->where('date', 'like', '%' . $request->search . '%')
|
$q->where('date', 'like', '%' . $request->search . '%')
|
||||||
|
->orWhere('platform', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('amount', 'like', '%' . $request->search . '%')
|
->orWhere('amount', 'like', '%' . $request->search . '%')
|
||||||
->orWhereHas('user', function ($q) use ($request) {
|
->orWhereHas('user', function ($q) use ($request) {
|
||||||
@@ -65,13 +50,30 @@ public function index(Request $request)
|
|||||||
->latest()
|
->latest()
|
||||||
->paginate($request->per_page ?? 20)->appends($request->query());
|
->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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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)
|
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)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('type', ['debit', 'credit']);
|
->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
|
// Date Filter
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
[$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);
|
$perPage = $request->input('per_page', 20);
|
||||||
$cash_flows = $query->paginate($perPage)->appends($request->query());
|
$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;
|
$firstDate = $cash_flows->first()?->date;
|
||||||
|
|
||||||
if ($firstDate) {
|
if ($firstDate) {
|
||||||
@@ -83,11 +83,14 @@ public function index(Request $request)
|
|||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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()
|
public function exportExcel()
|
||||||
@@ -100,9 +103,9 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportCashFlowReport, 'cash-flow.csv');
|
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',
|
'paymentType:id,name',
|
||||||
'sale:id,party_id',
|
'sale:id,party_id',
|
||||||
'sale.party:id,name',
|
'sale.party:id,name',
|
||||||
@@ -114,12 +117,47 @@ public function exportPdf()
|
|||||||
'dueCollect.party:id,name',
|
'dueCollect.party:id,name',
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('type', ['debit', 'credit'])
|
->whereIn('type', ['debit', 'credit']);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
|
// 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;
|
$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 App\Models\Product;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportComboProduct;
|
use Modules\Business\App\Exports\ExportComboProduct;
|
||||||
|
|
||||||
@@ -13,9 +14,14 @@ class AcnooComboProductController extends Controller
|
|||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
|
$branchId = null;
|
||||||
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
|
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||||
|
}
|
||||||
$search = $request->input('search');
|
$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('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', 'combo')
|
->where('product_type', 'combo')
|
||||||
->withCount('combo_products as total_combo_products')
|
->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()
|
->latest()
|
||||||
->paginate($request->per_page ?? 20)->appends($request->query());
|
->paginate($request->per_page ?? 20)->appends($request->query());
|
||||||
|
|
||||||
@@ -73,4 +85,55 @@ public function exportCsv()
|
|||||||
{
|
{
|
||||||
return Excel::download(new ExportComboProduct, 'combo-products.csv');
|
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');
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', 'combo')
|
->where('product_type', 'combo')
|
||||||
->withCount('combo_products as total_combo_products')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit($request->per_page ?? 20)->get();
|
||||||
|
|
||||||
$combo_products->transform(function ($product) {
|
$combo_products->transform(function ($product) {
|
||||||
$product->total_stock = $product->combo_products->sum(function ($combo) {
|
$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'));
|
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);
|
$party = Party::find($partyId);
|
||||||
$ledger = $service->list($request, $partyId);
|
$ledger = $service->list($request, $partyId);
|
||||||
@@ -78,18 +78,30 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportCustomerLedger, 'customer-ledger.csv');
|
return Excel::download(new ExportCustomerLedger, 'customer-ledger.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$customers = Party::with('sales')
|
$customers = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit($request->per_page ?? 20)->get();
|
||||||
|
|
||||||
return PdfService::render('business::party-reports.customer-ledger.pdf', compact('customers'),'customer-ledger-report.pdf');
|
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);
|
$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');
|
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);
|
$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');
|
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);
|
$party = Party::findOrFail($partyId);
|
||||||
|
|
||||||
$ledger = $service->list($request, $partyId);
|
$ledger = $service->list($request, $partyId);
|
||||||
|
|
||||||
return PdfService::render(
|
$duration = $request->custom_days ?: $request->duration ?: 'today';
|
||||||
'business::party-reports.customer-ledger.show-details.pdf',
|
|
||||||
compact('ledger', 'party'),
|
[$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'
|
strtolower($party->name).'-ledger.pdf'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,44 +60,31 @@ public function index(Request $request)
|
|||||||
$query->where('platform', $request->platform);
|
$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
|
// Paginate data
|
||||||
$perPage = $request->input('per_page', 20);
|
$perPage = $request->input('per_page', 20);
|
||||||
$day_books = $query->latest()->paginate($perPage)->appends($request->query());
|
$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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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()
|
public function exportExcel()
|
||||||
@@ -110,9 +97,9 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportDayBookReport, 'day-book.csv');
|
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',
|
'paymentType:id,name',
|
||||||
'sale:id,user_id,party_id,totalAmount',
|
'sale:id,user_id,party_id,totalAmount',
|
||||||
'sale.party:id,name',
|
'sale.party:id,name',
|
||||||
@@ -127,10 +114,37 @@ public function exportPdf()
|
|||||||
'dueCollect.user:id,name',
|
'dueCollect.user:id,name',
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereIn('type', ['debit', 'credit'])
|
->whereIn('type', ['debit', 'credit']);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
$branchId = null;
|
$branchId = null;
|
||||||
@@ -21,7 +20,7 @@ public function index(Request $request)
|
|||||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
$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) {
|
->whereHas('product', function ($q) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$q->where('business_id', auth()->user()->business_id);
|
||||||
})
|
})
|
||||||
@@ -62,13 +61,35 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportDiscountProduct, 'discount-products.csv');
|
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) {
|
->whereHas('product', function ($q) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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)
|
->where('discount', '>', 0)
|
||||||
|
->limit($request->per_page ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return PdfService::render('business::reports.discount-products.pdf', compact('discount_products'),'discount-product-report.pdf');
|
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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Services\Invoice\DueInvoiceService;
|
||||||
|
use Carbon\Carbon;
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
use App\Models\Party;
|
use App\Models\Party;
|
||||||
|
use App\Models\Business;
|
||||||
use App\Models\Purchase;
|
use App\Models\Purchase;
|
||||||
use App\Models\DueCollect;
|
use App\Models\DueCollect;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
|
use App\Models\Transaction;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
use App\Events\DuePaymentReceived;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
use App\Events\MultiPaymentProcessed;
|
use App\Events\MultiPaymentProcessed;
|
||||||
use App\Models\Transaction;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Carbon\Carbon;
|
use Modules\Business\App\Exports\ExportDueList;
|
||||||
|
use Modules\Business\App\Exports\ExportGuestDue;
|
||||||
|
|
||||||
class AcnooDueController extends Controller
|
class AcnooDueController extends Controller
|
||||||
{
|
{
|
||||||
@@ -30,29 +34,6 @@ public function index(Request $request)
|
|||||||
$businessId = auth()->user()->business_id;
|
$businessId = auth()->user()->business_id;
|
||||||
$activeBranch = auth()->user()->active_branch;
|
$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)
|
$query = Party::where('business_id', $businessId)
|
||||||
->with(['purchases_dues', 'sales_dues']);
|
->with(['purchases_dues', 'sales_dues']);
|
||||||
|
|
||||||
@@ -69,42 +50,70 @@ public function index(Request $request)
|
|||||||
->orWhere('phone', 'like', "%$search%")
|
->orWhere('phone', 'like', "%$search%")
|
||||||
->orWhere('email', 'like', "%$search%");
|
->orWhere('email', 'like', "%$search%");
|
||||||
|
|
||||||
if (!$activeBranch) {
|
if (! $activeBranch) {
|
||||||
$q->orWhere('due', 'like', "%$search%");
|
$q->orWhere('due', 'like', "%$search%");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$totalQuery = clone $query;
|
||||||
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
|
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$filtered = $parties->getCollection()
|
$total_supplier_due = (clone $totalQuery)
|
||||||
->map(function ($party) {
|
->where('type', 'Supplier')
|
||||||
|
->get()
|
||||||
|
->sum(fn ($p) => $p->purchases_dues->sum('dueAmount'));
|
||||||
|
|
||||||
$party->due = $party->type === 'Supplier'
|
$total_customer_due = (clone $totalQuery)
|
||||||
? $party->purchases_dues->sum('dueAmount')
|
->where('type', '!=', 'Supplier')
|
||||||
: $party->sales_dues->sum('dueAmount');
|
->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;
|
return $party;
|
||||||
})
|
})
|
||||||
->filter(fn($p) => $p->due > 0)
|
->filter(fn ($p) => $p->due > 0)
|
||||||
->values();
|
->values();
|
||||||
|
|
||||||
$parties->setCollection($filtered);
|
$parties->setCollection($filtered);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()->filter(fn($p) => $p->due > 0)->values()
|
$parties->getCollection()->filter(fn ($p) => $p->due > 0)->values()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => view('business::dues.datas', [
|
'data' => view('business::dues.datas', compact('parties'))->render(),
|
||||||
'parties' => $parties,
|
'total_supplier_due' => currency_format($total_supplier_due, currency: business_currency()),
|
||||||
'total_supplier_due' => $total_supplier_due,
|
'total_customer_due' => currency_format($total_customer_due, currency: business_currency())
|
||||||
'total_customer_due' => $total_customer_due
|
|
||||||
])->render()
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
$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();
|
$payment_types = PaymentType::where('business_id', auth()->user()->business_id)->whereStatus(1)->latest()->get();
|
||||||
|
|
||||||
$due_amount = 0;
|
$due_amount = 0;
|
||||||
if ($party->type == 'Supplier') {
|
if ($party->type == 'Supplier') {
|
||||||
foreach ($party->purchases_dues as $sales_due) {
|
foreach ($party->purchases_dues as $sales_due) {
|
||||||
|
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
|
||||||
$due_amount += $sales_due->dueAmount;
|
$due_amount += $sales_due->dueAmount;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($party->sales_dues as $sales_due) {
|
foreach ($party->sales_dues as $sales_due) {
|
||||||
|
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
|
||||||
$due_amount += $sales_due->dueAmount;
|
$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;
|
$party_opening_due = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$party_opening_due = $party->due - $due_amount;
|
$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'));
|
return view('business::dues.collect-due', compact('party', 'party_opening_due', 'payment_types'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function collectDueStore(Request $request)
|
public function collectDueStore(Request $request)
|
||||||
{
|
{
|
||||||
$party = Party::find($request->party_id);
|
$party = Party::find($request->party_id);
|
||||||
|
$activeBranch = auth()->user()->active_branch;
|
||||||
|
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'paymentDate' => 'required|string',
|
'paymentDate' => 'required|string',
|
||||||
'payDueAmount' => 'required|numeric',
|
'payDueAmount' => 'required|numeric',
|
||||||
'party_id' => 'required|exists:parties,id',
|
'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;
|
$business = Business::findOrFail(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
$branch_id = null;
|
$branch_id = $activeBranch?->id;
|
||||||
$invoice = null;
|
$invoice = null;
|
||||||
|
|
||||||
$payments = $request->payments ?? [];
|
$payments = $request->payments ?? [];
|
||||||
@@ -173,81 +188,104 @@ public function collectDueStore(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$payDueAmount = collect($payments)
|
$payDueAmount = collect($payments)
|
||||||
->reject(fn($p) => strtolower($p['type']) === 'cheque')
|
->reject(fn ($p) => strtolower($p['type']) === 'cheque')
|
||||||
->sum('amount');
|
->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 ($request->invoiceNumber) {
|
||||||
if ($party->type == 'Supplier') {
|
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 {
|
} 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([
|
return response()->json([
|
||||||
'message' => 'Invoice Not Found.'
|
'message' => 'Invoice Not Found.',
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!auth()->user()->active_branch) {
|
|
||||||
if (isset($invoice) && isset($invoice->branch_id)) {
|
|
||||||
$branch_id = $invoice->branch_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($invoice->dueAmount < $request->payDueAmount) {
|
if ($invoice->dueAmount < $request->payDueAmount) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Invoice due is ' . $invoice->dueAmount . '. You can not pay more then the invoice due amount.'
|
'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.')
|
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($party->opening_balance_type == 'due') {
|
$branch_id = $invoice->branch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $request->invoiceNumber && $opening_balance_due > 0) {
|
||||||
$party->update([
|
$party->update([
|
||||||
'opening_balance' => max(0, $party->opening_balance - $payDueAmount),
|
'opening_balance' => max(0, $party->opening_balance - $payDueAmount),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$data = DueCollect::create($request->except('user_id', 'business_id', 'sale_id', 'purchase_id', 'totalDue', 'dueAmountAfterPay', 'paymentDate') + [
|
$data = DueCollect::create($request->except('user_id', 'business_id', 'sale_id', 'purchase_id', 'totalDue', 'dueAmountAfterPay', 'paymentDate') + [
|
||||||
'user_id' => auth()->id(),
|
'user_id' => auth()->id(),
|
||||||
'business_id' => $business_id,
|
'business_id' => $business->id,
|
||||||
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : NULL,
|
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : null,
|
||||||
'purchase_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,
|
'totalDue' => $total_due,
|
||||||
'dueAmountAfterPay'=> isset($invoice) ? ($invoice->dueAmount - $payDueAmount) : ($party->due - $payDueAmount),
|
'dueAmountAfterPay' => $total_due - $payDueAmount,
|
||||||
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now()
|
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update invoice due
|
|
||||||
if (isset($invoice)) {
|
if (isset($invoice)) {
|
||||||
$invoice->update([
|
$invoice->update([
|
||||||
'dueAmount' => $invoice->dueAmount - $payDueAmount,
|
'dueAmount' => $invoice->dueAmount - $payDueAmount,
|
||||||
'paidAmount' => $invoice->paidAmount + $payDueAmount
|
'paidAmount' => $invoice->paidAmount + $payDueAmount,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update party due
|
|
||||||
$party->update([
|
$party->update([
|
||||||
'due' => $party->due - $payDueAmount
|
'due' => $party->due - $payDueAmount,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// update balance & adjust platform
|
|
||||||
if ($party->type == 'Supplier') {
|
if ($party->type == 'Supplier') {
|
||||||
updateBalance($payDueAmount, 'decrement', $branch_id);
|
updateBalance($payDueAmount, 'decrement', $branch_id);
|
||||||
$platform = 'due_pay';
|
$platform = 'due_pay';
|
||||||
@@ -256,7 +294,6 @@ public function collectDueStore(Request $request)
|
|||||||
$platform = 'due_collect';
|
$platform = 'due_collect';
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiPaymentProcessed event
|
|
||||||
event(new MultiPaymentProcessed(
|
event(new MultiPaymentProcessed(
|
||||||
$payments,
|
$payments,
|
||||||
$data->id,
|
$data->id,
|
||||||
@@ -265,45 +302,30 @@ public function collectDueStore(Request $request)
|
|||||||
$party->id,
|
$party->id,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Notify
|
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business->id);
|
||||||
event(new DuePaymentReceived($data));
|
|
||||||
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();
|
DB::commit();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Collect Due saved successfully'),
|
'message' => __('Collect Due saved successfully'),
|
||||||
'redirect' => route('business.dues.index'),
|
'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) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
|
||||||
return response()->json(['message' => $e->getMessage()], 404);
|
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', )
|
$data = $service->getInvoiceData($party_id);
|
||||||
->where('business_id', auth()->user()->business_id)
|
return view('business::dues.invoice', $data);
|
||||||
->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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generatePDF($id)
|
public function generatePDF($id)
|
||||||
@@ -391,10 +413,10 @@ public function partyDue(Request $request)
|
|||||||
// Apply search
|
// Apply search
|
||||||
$query->when($request->search, function ($q) use ($request) {
|
$query->when($request->search, function ($q) use ($request) {
|
||||||
$q->where(function ($q) use ($request) {
|
$q->where(function ($q) use ($request) {
|
||||||
$q->where('email', 'like', '%' . $request->search . '%')
|
$q->where('email', 'like', '%'.$request->search.'%')
|
||||||
->orWhere('name', 'like', '%' . $request->search . '%')
|
->orWhere('name', 'like', '%'.$request->search.'%')
|
||||||
->orWhere('phone', 'like', '%' . $request->search . '%')
|
->orWhere('phone', 'like', '%'.$request->search.'%')
|
||||||
->orWhere('due', '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());
|
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
// Calculate branch-wise due and replace $party->due, remove zero-due parties
|
|
||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()
|
$parties->getCollection()
|
||||||
->transform(function ($party) {
|
->transform(function ($party) use ($activeBranch) {
|
||||||
$party->due = $party->type === 'Supplier'
|
$sale_dues = $party->type === 'Supplier'
|
||||||
? $party->purchases_dues->sum('dueAmount')
|
? $party->purchases_dues->where('branch_id', $activeBranch->id)
|
||||||
: $party->sales_dues->sum('dueAmount');
|
: $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;
|
return $party;
|
||||||
})
|
})
|
||||||
->filter(fn($party) => $party->due > 0)
|
->filter(fn ($party) => $party->due > 0)
|
||||||
->values()
|
->values()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Non-active branch: ensure only parties with due > 0
|
// Non-active branch: ensure only parties with due > 0
|
||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()
|
$parties->getCollection()
|
||||||
->filter(fn($party) => $party->due > 0)
|
->filter(fn ($party) => $party->due > 0)
|
||||||
->values()
|
->values()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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'));
|
return view('business::dues.party.index', compact('parties', 'party_type'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function walk_dues(Request $request)
|
public function walk_dues(Request $request)
|
||||||
{
|
{
|
||||||
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
|
$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')
|
$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)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereNull('party_id')
|
->whereNull('party_id')
|
||||||
->latest()
|
->where('id', $id) // 🔥 FIX HERE
|
||||||
->first();
|
->firstOrFail();
|
||||||
|
|
||||||
$transactionTypes = $due_collect->transactions
|
$transactionTypes = $due_collect->transactions
|
||||||
->map(function ($transaction) {
|
->map(function ($transaction) {
|
||||||
@@ -496,7 +528,8 @@ public function walkDuesGetInvoice(string $id)
|
|||||||
->unique()
|
->unique()
|
||||||
->implode(', ');
|
->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();
|
$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();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
$branch_id = null;
|
$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) {
|
if (!$invoice) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Invoice Not Found.'
|
'message' => 'Invoice Not Found.'
|
||||||
@@ -565,23 +599,23 @@ public function collectWalkDueStore(Request $request)
|
|||||||
'sale_id' => $invoice->id,
|
'sale_id' => $invoice->id,
|
||||||
'invoiceNumber' => $request->invoiceNumber,
|
'invoiceNumber' => $request->invoiceNumber,
|
||||||
'totalDue' => $invoice->dueAmount,
|
'totalDue' => $invoice->dueAmount,
|
||||||
'dueAmountAfterPay' => $invoice->dueAmount - $request->payDueAmount,
|
'dueAmountAfterPay' => $invoice->dueAmount - $payDueAmount,
|
||||||
'payDueAmount' => $request->payDueAmount,
|
'payDueAmount' => $payDueAmount,
|
||||||
'paymentDate' => $request->paymentDate,
|
'paymentDate' => $request->paymentDate,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$invoice->update([
|
$invoice->update([
|
||||||
'dueAmount' => $invoice->dueAmount - $request->payDueAmount
|
'dueAmount' => $invoice->dueAmount - $payDueAmount
|
||||||
]);
|
]);
|
||||||
|
|
||||||
updateBalance($request->payDueAmount, 'increment', $branch_id);
|
updateBalance($payDueAmount, 'increment', $branch_id);
|
||||||
|
|
||||||
// MultiPaymentProcessed event
|
// MultiPaymentProcessed event
|
||||||
event(new MultiPaymentProcessed(
|
event(new MultiPaymentProcessed(
|
||||||
$request->payments ?? [],
|
$payments,
|
||||||
$data->id,
|
$data->id,
|
||||||
'due_collect',
|
'due_collect',
|
||||||
$request->payDueAmount,
|
$payDueAmount,
|
||||||
));
|
));
|
||||||
|
|
||||||
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);
|
||||||
@@ -591,7 +625,7 @@ public function collectWalkDueStore(Request $request)
|
|||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Collect Due saved successfully'),
|
'message' => __('Collect Due saved successfully'),
|
||||||
'redirect' => route('business.walk-dues.index'),
|
'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) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
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 . '%');
|
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->when(request('type'), function ($q) use ($request) {
|
->when($request->type, function ($q) use ($request) {
|
||||||
$q->where(function ($q) use ($request) {
|
|
||||||
$q->where('type', $request->type);
|
$q->where('type', $request->type);
|
||||||
});
|
|
||||||
})
|
})
|
||||||
->with('sales_dues')
|
->with('sales_dues')
|
||||||
->latest();
|
->latest();
|
||||||
|
|
||||||
if ($activeBranch) {
|
$parties = $query->paginate($request->per_page ?? 20)->appends($request->query());
|
||||||
$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);
|
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()
|
$parties->getCollection()
|
||||||
->transform(function ($customer) use ($activeBranch) {
|
->transform(function ($customer) use ($activeBranch) {
|
||||||
$customer->due = $customer->sales_dues
|
$party_due = $customer->sales_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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;
|
return $customer;
|
||||||
})
|
})
|
||||||
->filter(fn($customer) => $customer->due > 0)
|
->filter(fn($customer) => $customer->due > 0)
|
||||||
->values()
|
->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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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) {
|
return view('business::reports.due.due-reports', compact('parties', 'customer_total_due'));
|
||||||
// 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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportExcel()
|
public function exportExcel()
|
||||||
@@ -117,37 +94,59 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportDue, 'customer-due.csv');
|
return Excel::download(new ExportDue, 'customer-due.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
|
||||||
$activeBranch = $user->active_branch;
|
$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')
|
->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')
|
->with('sales_dues')
|
||||||
->latest();
|
->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();
|
$parties = $query->get();
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
$parties = $parties
|
||||||
$supplier->due = $supplier->sales_dues
|
->transform(function ($customer) use ($activeBranch) {
|
||||||
|
$party_due = $customer->sales_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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\Branch;
|
||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
@@ -26,10 +25,6 @@ public function index(Request $request)
|
|||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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')
|
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->where('business_id', $businessId);
|
->where('business_id', $businessId);
|
||||||
|
|
||||||
@@ -90,10 +85,40 @@ public function exportCsv()
|
|||||||
|
|
||||||
public function exportPdf(Request $request)
|
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)
|
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->latest()
|
->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
|
||||||
|
|
||||||
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 App\Models\Product;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportExpiredProduct;
|
use Modules\Business\App\Exports\ExportExpiredProduct;
|
||||||
|
|
||||||
@@ -64,4 +65,38 @@ public function exportCsv()
|
|||||||
{
|
{
|
||||||
return Excel::download(new ExportExpiredProduct, 'expired-products.csv');
|
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');
|
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')
|
->withSum('stocks', 'productStock')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->whereHas('stocks', function ($query) {
|
->whereHas('stocks', function ($query) {
|
||||||
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
|
$query->whereDate('expire_date', '<=', today())->where('productStock', '>', 0);
|
||||||
})
|
});
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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)
|
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)
|
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->latest()
|
->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
|
||||||
|
|
||||||
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 Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
|
use App\Traits\DateRangeTrait;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportLossProfitHistory;
|
use Modules\Business\App\Exports\ExportLossProfitHistory;
|
||||||
|
|
||||||
class AcnooLossProfitHistoryController extends Controller
|
class AcnooLossProfitHistoryController extends Controller
|
||||||
{
|
{
|
||||||
use DateFilterTrait;
|
use DateFilterTrait, DateRangeTrait;
|
||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
$businessId = $user->business_id;
|
||||||
|
$perPage = request('per_page') ?? 20;
|
||||||
|
|
||||||
$branchId = null;
|
$branchId = null;
|
||||||
if (moduleCheck('MultiBranchAddon')) {
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
@@ -25,10 +27,17 @@ public function index(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
|
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||||
|
|
||||||
$salesQuery = DB::table('sales')
|
$salesQuery = DB::table('sales')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"saleDate"::date as date'),
|
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(actual_total_amount) as total_sales'),
|
||||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||||
)
|
)
|
||||||
@@ -36,14 +45,24 @@ public function index(Request $request)
|
|||||||
->when($branchId, fn ($q) =>
|
->when($branchId, fn ($q) =>
|
||||||
$q->where('branch_id', $branchId)
|
$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);
|
$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)[
|
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||||
'type' => 'Sale',
|
'type' => 'Sale',
|
||||||
'date' => $sale->date,
|
'date' => $sale->date,
|
||||||
|
'profit_type' => $sale->profit_type,
|
||||||
'total_sales' => $sale->total_sales,
|
'total_sales' => $sale->total_sales,
|
||||||
'total_incomes' => $sale->total_sale_income,
|
'total_incomes' => $sale->total_sale_income,
|
||||||
]);
|
]);
|
||||||
@@ -60,7 +79,7 @@ public function index(Request $request)
|
|||||||
->groupBy(DB::raw('"incomeDate"::date'));
|
->groupBy(DB::raw('"incomeDate"::date'));
|
||||||
|
|
||||||
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_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)[
|
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
|
||||||
'type' => 'Income',
|
'type' => 'Income',
|
||||||
@@ -80,7 +99,10 @@ public function index(Request $request)
|
|||||||
$mergedIncomeSaleData->push($income);
|
$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);
|
$mergedIncomeSaleData->push($sale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +122,7 @@ public function index(Request $request)
|
|||||||
->groupBy(DB::raw('"date"::date'));
|
->groupBy(DB::raw('"date"::date'));
|
||||||
|
|
||||||
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||||
$dailyPayrolls = $payrollQuery->get();
|
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
$expenseQuery = DB::table('expenses')
|
$expenseQuery = DB::table('expenses')
|
||||||
@@ -115,7 +137,7 @@ public function index(Request $request)
|
|||||||
->groupBy(DB::raw('"expenseDate"::date'));
|
->groupBy(DB::raw('"expenseDate"::date'));
|
||||||
|
|
||||||
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
||||||
$dailyExpenses = $expenseQuery->get();
|
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||||
|
|
||||||
$mergedExpenseData = collect();
|
$mergedExpenseData = collect();
|
||||||
$allExpenseDates = $dailyExpenses->pluck('date')
|
$allExpenseDates = $dailyExpenses->pluck('date')
|
||||||
@@ -148,34 +170,6 @@ public function index(Request $request)
|
|||||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
$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(
|
return view('business::loss-profit-histories.index', compact(
|
||||||
'mergedIncomeSaleData',
|
'mergedIncomeSaleData',
|
||||||
'mergedExpenseData',
|
'mergedExpenseData',
|
||||||
@@ -183,9 +177,9 @@ public function index(Request $request)
|
|||||||
'grossIncomeProfit',
|
'grossIncomeProfit',
|
||||||
'totalExpenses',
|
'totalExpenses',
|
||||||
'netProfit',
|
'netProfit',
|
||||||
'cardGrossProfit',
|
'duration',
|
||||||
'totalCardExpenses',
|
'filter_from_date',
|
||||||
'cardNetProfit'
|
'filter_to_date'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,45 +193,71 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportLossProfitHistory, 'loss-profit-history.csv');
|
return Excel::download(new ExportLossProfitHistory, 'loss-profit-history.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
$businessId = $user->business_id;
|
||||||
|
$perPage = request('per_page') ?? 20;
|
||||||
|
|
||||||
$branchId = null;
|
$branchId = null;
|
||||||
if (moduleCheck('MultiBranchAddon')) {
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
$branchId = $user->branch_id ?? $user->active_branch_id;
|
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SALES
|
$duration = $request->custom_days ?: 'today';
|
||||||
$dailySales = DB::table('sales')
|
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||||
|
|
||||||
|
$salesQuery = DB::table('sales')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"saleDate"::date as date'),
|
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(actual_total_amount) as total_sales'),
|
||||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"saleDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->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)[
|
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||||
'type' => 'Sale',
|
'type' => 'Sale',
|
||||||
'date' => $sale->date,
|
'date' => $sale->date,
|
||||||
|
'profit_type' => $sale->profit_type,
|
||||||
'total_sales' => $sale->total_sales,
|
'total_sales' => $sale->total_sales,
|
||||||
'total_incomes' => $sale->total_sale_income,
|
'total_incomes' => $sale->total_sale_income,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// INCOME
|
$incomeQuery = DB::table('incomes')
|
||||||
$dailyIncomes = DB::table('incomes')
|
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"incomeDate"::date as date'),
|
DB::raw('"incomeDate"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_incomes')
|
DB::raw('SUM(amount) as total_incomes')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"incomeDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->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)[
|
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
|
||||||
'type' => 'Income',
|
'type' => 'Income',
|
||||||
@@ -245,46 +265,66 @@ public function exportPdf()
|
|||||||
'total_incomes' => $income->total_incomes,
|
'total_incomes' => $income->total_incomes,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// MERGE SALE + INCOME
|
|
||||||
$mergedIncomeSaleData = collect();
|
$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) {
|
foreach ($allDates as $date) {
|
||||||
|
|
||||||
if ($income = $income_datas->firstWhere('date', $date)) {
|
if ($income = $income_datas->firstWhere('date', $date)) {
|
||||||
$mergedIncomeSaleData->push($income);
|
$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);
|
$mergedIncomeSaleData->push($sale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PAYROLL
|
|
||||||
$dailyPayrolls = collect();
|
$dailyPayrolls = collect();
|
||||||
|
|
||||||
if (moduleCheck('HrmAddon')) {
|
if (moduleCheck('HrmAddon')) {
|
||||||
$dailyPayrolls = DB::table('payrolls')
|
$payrollQuery = DB::table('payrolls')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"date"::date as date'),
|
DB::raw('"date"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_payrolls')
|
DB::raw('SUM(amount) as total_payrolls')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"date"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->groupBy(DB::raw('"date"::date'));
|
||||||
|
|
||||||
|
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||||
|
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPENSES
|
$expenseQuery = DB::table('expenses')
|
||||||
$dailyExpenses = DB::table('expenses')
|
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"expenseDate"::date as date'),
|
DB::raw('"expenseDate"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_expenses_only')
|
DB::raw('SUM(amount) as total_expenses_only')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
|
->when($branchId, fn ($q) =>
|
||||||
->groupBy(DB::raw('"expenseDate"::date'))
|
$q->where('branch_id', $branchId)
|
||||||
->get();
|
)
|
||||||
|
->groupBy(DB::raw('"expenseDate"::date'));
|
||||||
|
|
||||||
|
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
|
||||||
|
$dailyExpenses = $expenseQuery->limit($perPage)->get();
|
||||||
|
|
||||||
$mergedExpenseData = collect();
|
$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) {
|
foreach ($allExpenseDates as $date) {
|
||||||
|
|
||||||
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
|
||||||
$mergedExpenseData->push((object)[
|
$mergedExpenseData->push((object)[
|
||||||
'type' => 'Expense',
|
'type' => 'Expense',
|
||||||
@@ -292,6 +332,7 @@ public function exportPdf()
|
|||||||
'total_expenses' => $expense->total_expenses_only,
|
'total_expenses' => $expense->total_expenses_only,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
|
||||||
$mergedExpenseData->push((object)[
|
$mergedExpenseData->push((object)[
|
||||||
'type' => 'Payroll',
|
'type' => 'Payroll',
|
||||||
@@ -301,9 +342,9 @@ public function exportPdf()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUMMARY
|
|
||||||
$grossSaleProfit = $sale_datas->sum('total_sales');
|
$grossSaleProfit = $sale_datas->sum('total_sales');
|
||||||
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
|
||||||
|
|
||||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
$netProfit = $grossIncomeProfit - $totalExpenses;
|
||||||
|
|
||||||
@@ -316,7 +357,10 @@ public function exportPdf()
|
|||||||
'grossSaleProfit',
|
'grossSaleProfit',
|
||||||
'grossIncomeProfit',
|
'grossIncomeProfit',
|
||||||
'totalExpenses',
|
'totalExpenses',
|
||||||
'netProfit'
|
'netProfit',
|
||||||
|
'duration',
|
||||||
|
'filter_to_date',
|
||||||
|
'filter_from_date'
|
||||||
),
|
),
|
||||||
'loss-profit-history.pdf'
|
'loss-profit-history.pdf'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,10 +6,11 @@
|
|||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Traits\DateRangeTrait;
|
||||||
|
|
||||||
class AcnooLossProfitHistoryReportController extends Controller
|
class AcnooLossProfitHistoryReportController extends Controller
|
||||||
{
|
{
|
||||||
use DateFilterTrait;
|
use DateFilterTrait, DateRangeTrait;
|
||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
@@ -22,10 +23,17 @@ public function index(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
|
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
||||||
|
|
||||||
$salesQuery = DB::table('sales')
|
$salesQuery = DB::table('sales')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('"saleDate"::date as date'),
|
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(actual_total_amount) as total_sales'),
|
||||||
DB::raw('SUM("lossProfit") as total_sale_income')
|
DB::raw('SUM("lossProfit") as total_sale_income')
|
||||||
)
|
)
|
||||||
@@ -33,14 +41,24 @@ public function index(Request $request)
|
|||||||
->when($branchId, fn ($q) =>
|
->when($branchId, fn ($q) =>
|
||||||
$q->where('branch_id', $branchId)
|
$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);
|
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
||||||
|
|
||||||
$dailySales = $salesQuery->get();
|
$dailySales = $salesQuery->get();
|
||||||
|
|
||||||
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
$sale_datas = $dailySales->map(fn ($sale) => (object)[
|
||||||
'type' => 'Sale',
|
'type' => 'Sale',
|
||||||
'date' => $sale->date,
|
'date' => $sale->date,
|
||||||
|
'profit_type' => $sale->profit_type,
|
||||||
'total_sales' => $sale->total_sales,
|
'total_sales' => $sale->total_sales,
|
||||||
'total_incomes' => $sale->total_sale_income,
|
'total_incomes' => $sale->total_sale_income,
|
||||||
]);
|
]);
|
||||||
@@ -77,7 +95,10 @@ public function index(Request $request)
|
|||||||
$mergedIncomeSaleData->push($income);
|
$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);
|
$mergedIncomeSaleData->push($sale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,14 +108,14 @@ public function index(Request $request)
|
|||||||
if (moduleCheck('HrmAddon')) {
|
if (moduleCheck('HrmAddon')) {
|
||||||
$payrollQuery = DB::table('payrolls')
|
$payrollQuery = DB::table('payrolls')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('DATE(date) as date'),
|
DB::raw('"date"::date as date'),
|
||||||
DB::raw('SUM(amount) as total_payrolls')
|
DB::raw('SUM(amount) as total_payrolls')
|
||||||
)
|
)
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
->when($branchId, fn ($q) =>
|
->when($branchId, fn ($q) =>
|
||||||
$q->where('branch_id', $branchId)
|
$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);
|
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
|
||||||
$dailyPayrolls = $payrollQuery->get();
|
$dailyPayrolls = $payrollQuery->get();
|
||||||
@@ -145,34 +166,6 @@ public function index(Request $request)
|
|||||||
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
$totalExpenses = $mergedExpenseData->sum('total_expenses');
|
||||||
$netProfit = $grossIncomeProfit - $totalExpenses;
|
$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(
|
return view('business::loss-profit-histories.index', compact(
|
||||||
'mergedIncomeSaleData',
|
'mergedIncomeSaleData',
|
||||||
'mergedExpenseData',
|
'mergedExpenseData',
|
||||||
@@ -180,9 +173,9 @@ public function index(Request $request)
|
|||||||
'grossIncomeProfit',
|
'grossIncomeProfit',
|
||||||
'totalExpenses',
|
'totalExpenses',
|
||||||
'netProfit',
|
'netProfit',
|
||||||
'cardGrossProfit',
|
'duration',
|
||||||
'totalCardExpenses',
|
'filter_from_date',
|
||||||
'cardNetProfit'
|
'filter_to_date'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,18 @@
|
|||||||
namespace Modules\Business\App\Http\Controllers;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Party;
|
use App\Models\Party;
|
||||||
|
use App\Models\PaymentType;
|
||||||
use App\Helpers\HasUploader;
|
use App\Helpers\HasUploader;
|
||||||
|
use App\Imports\PartyImport;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use Illuminate\Validation\Rule;
|
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
|
class AcnooPartyController extends Controller
|
||||||
{
|
{
|
||||||
@@ -32,12 +39,12 @@ public function index(Request $request)
|
|||||||
$query = Party::where('business_id', $business_id)
|
$query = Party::where('business_id', $business_id)
|
||||||
->when($search, function ($q) use ($search) {
|
->when($search, function ($q) use ($search) {
|
||||||
$q->where(function ($q) use ($search) {
|
$q->where(function ($q) use ($search) {
|
||||||
$q->where('name', 'like', '%' . $search . '%')
|
$q->where('name', 'like', '%'.$search.'%')
|
||||||
->orWhere('credit_limit', 'like', '%' . $search . '%')
|
->orWhere('credit_limit', 'like', '%'.$search.'%')
|
||||||
->orWhere('phone', 'like', '%' . $search . '%')
|
->orWhere('phone', 'like', '%'.$search.'%')
|
||||||
->orWhere('type', 'like', '%' . $search . '%')
|
->orWhere('type', 'like', '%'.$search.'%')
|
||||||
->orWhere('address', 'like', '%' . $search . '%')
|
->orWhere('address', 'like', '%'.$search.'%')
|
||||||
->orWhere('due', 'like', '%' . $search . '%');
|
->orWhere('due', 'like', '%'.$search.'%');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,11 +61,19 @@ public function index(Request $request)
|
|||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()
|
$parties->getCollection()
|
||||||
->transform(function ($party) use ($activeBranch) {
|
->transform(function ($party) use ($activeBranch) {
|
||||||
$party_due = $party->type === 'Supplier'
|
$originalDue = $party->getRawOriginal('due') ?? 0;
|
||||||
? $party->purchases_dues->sum('dueAmount')
|
$originalOpeningBalance = $party->opening_balance ?? 0;
|
||||||
: $party->sales_dues->sum('dueAmount');
|
|
||||||
|
|
||||||
$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;
|
return $party;
|
||||||
})
|
})
|
||||||
@@ -67,16 +82,20 @@ public function index(Request $request)
|
|||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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'));
|
return view('business::parties.index', compact('parties', 'party_type'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('business::parties.create');
|
$countries = [];
|
||||||
|
$states = [];
|
||||||
|
|
||||||
|
return view('business::parties.create', compact('countries', 'states'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
@@ -88,13 +107,12 @@ public function store(Request $request)
|
|||||||
'email' => 'nullable|email',
|
'email' => 'nullable|email',
|
||||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
||||||
'address' => 'nullable|string|max:255',
|
'address' => 'nullable|string|max:255',
|
||||||
|
'tax_no' => 'nullable|string|max:255',
|
||||||
'due' => 'nullable|numeric|min:0',
|
'due' => 'nullable|numeric|min:0',
|
||||||
'billing_address' => 'nullable|array',
|
'billing_address' => 'nullable|array',
|
||||||
'billing_address.address' => 'nullable|string|max:255',
|
'billing_address.address' => 'nullable|string|max:255',
|
||||||
'billing_address.city' => '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.zip_code' => 'nullable|string|max:20',
|
||||||
'billing_address.country' => 'nullable|string|max:255',
|
|
||||||
'shipping_address' => 'nullable|array',
|
'shipping_address' => 'nullable|array',
|
||||||
'shipping_address.address' => 'nullable|string|max:255',
|
'shipping_address.address' => 'nullable|string|max:255',
|
||||||
'shipping_address.city' => 'nullable|string|max:255',
|
'shipping_address.city' => 'nullable|string|max:255',
|
||||||
@@ -127,7 +145,10 @@ public function store(Request $request)
|
|||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$party = Party::where('business_id', auth()->user()->business_id)->findOrFail($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)
|
public function update(Request $request, $id)
|
||||||
@@ -141,13 +162,12 @@ public function update(Request $request, $id)
|
|||||||
'email' => 'nullable|email',
|
'email' => 'nullable|email',
|
||||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
|
||||||
'address' => 'nullable|string|max:255',
|
'address' => 'nullable|string|max:255',
|
||||||
|
'tax_no' => 'nullable|string|max:255',
|
||||||
'due' => 'nullable|numeric|min:0',
|
'due' => 'nullable|numeric|min:0',
|
||||||
'billing_address' => 'nullable|array',
|
'billing_address' => 'nullable|array',
|
||||||
'billing_address.address' => 'nullable|string|max:255',
|
'billing_address.address' => 'nullable|string|max:255',
|
||||||
'billing_address.city' => '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.zip_code' => 'nullable|string|max:20',
|
||||||
'billing_address.country' => 'nullable|string|max:255',
|
|
||||||
'shipping_address' => 'nullable|array',
|
'shipping_address' => 'nullable|array',
|
||||||
'shipping_address.address' => 'nullable|string|max:255',
|
'shipping_address.address' => 'nullable|string|max:255',
|
||||||
'shipping_address.city' => '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)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$party = Party::findOrFail($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 Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Party;
|
use App\Models\Party;
|
||||||
use App\Models\Sale;
|
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportPartyLossProfit;
|
use Modules\Business\App\Exports\ExportPartyLossProfit;
|
||||||
@@ -14,12 +13,6 @@ class AcnooPartyLossProfitController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(Request $request)
|
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')
|
$parties = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->where('type', '!=', 'Supplier')
|
||||||
@@ -32,13 +25,20 @@ public function index(Request $request)
|
|||||||
->paginate($request->per_page ?? 20)
|
->paginate($request->per_page ?? 20)
|
||||||
->appends($request->query());
|
->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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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()
|
public function exportExcel()
|
||||||
@@ -51,18 +51,24 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportPartyLossProfit, 'party-loss-profit.csv');
|
return Excel::download(new ExportPartyLossProfit, 'party-loss-profit.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$parties = Party::with('sales')
|
$parties = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->where('type', '!=', 'Supplier')
|
||||||
|
->when($request->search, function ($query) use ($request) {
|
||||||
|
$query->where(function ($q) use ($request) {
|
||||||
|
$q->where('name', 'like', '%' . $request->search . '%');
|
||||||
|
});
|
||||||
|
})
|
||||||
->latest()
|
->latest()
|
||||||
|
->limit($request->per_page ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return PdfService::render('business::party-reports.loss-profit.pdf', compact('parties'),'party-loss-profit-report.pdf');
|
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')
|
$party = Party::with('sales.details', 'sales.details.product')
|
||||||
->where('id', $id)
|
->where('id', $id)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Modules\Business\App\Exports\ExportProduct;
|
use Modules\Business\App\Exports\ExportProduct;
|
||||||
use Modules\Business\App\Exports\ExportExpiredProduct;
|
|
||||||
|
|
||||||
class AcnooProductController extends Controller
|
class AcnooProductController extends Controller
|
||||||
{
|
{
|
||||||
@@ -67,12 +66,13 @@ public function index(Request $request)
|
|||||||
$q->where(function ($q) use ($search) {
|
$q->where(function ($q) use ($search) {
|
||||||
$q->where('productName', 'like', "%{$search}%")
|
$q->where('productName', 'like', "%{$search}%")
|
||||||
->orWhere('productCode', 'like', "%{$search}%")
|
->orWhere('productCode', 'like', "%{$search}%")
|
||||||
|
->orWhere('hsn_code', 'like', "%{$search}%")
|
||||||
->orWhere('productPurchasePrice', 'like', "%{$search}%")
|
->orWhere('productPurchasePrice', 'like', "%{$search}%")
|
||||||
->orWhere('productSalePrice', 'like', "%{$search}%")
|
->orWhere('productSalePrice', 'like', "%{$search}%")
|
||||||
->orWhere('product_type', 'like', "%{$search}%")
|
->orWhere('product_type', 'like', "%{$search}%")
|
||||||
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
|
||||||
->orWhereHas('brand', fn($q) => $q->where('brandName', 'like', "%{$search}%"))
|
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
|
||||||
->orWhereHas('unit', fn($q) => $q->where('unitName', 'like', "%{$search}%"));
|
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->latest()
|
->latest()
|
||||||
@@ -82,11 +82,11 @@ public function index(Request $request)
|
|||||||
$products->getCollection()->transform(function ($product) {
|
$products->getCollection()->transform(function ($product) {
|
||||||
if ($product->product_type === 'combo') {
|
if ($product->product_type === 'combo') {
|
||||||
$product->total_stock = $product->combo_products->sum(
|
$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(
|
$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) {
|
$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'));
|
return view('business::products.index', compact('products'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$business_id = auth()->user()->business_id;
|
$business_id = auth()->user()->business_id;
|
||||||
@@ -122,7 +121,7 @@ public function create()
|
|||||||
$brands = Brand::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();
|
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||||
$product_id = (Product::where('business_id', $business_id)->count() ?? 0) + 1;
|
$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);
|
$code = str_pad($product_id, 4, '0', STR_PAD_LEFT);
|
||||||
$product_models = ProductModel::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();
|
$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();
|
$racks = Rack::where('business_id', $business_id)->latest()->get();
|
||||||
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
|
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
|
||||||
$profit_option = Option::where('key', 'business-settings')
|
$profit_option = Option::where('key', 'business-settings')
|
||||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||||
->get()
|
->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'));
|
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);
|
return $query->where('business_id', $business_id);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
'hsn_code' => 'nullable|string|max:255',
|
||||||
'alert_qty' => 'nullable|numeric|min:0',
|
'alert_qty' => 'nullable|numeric|min:0',
|
||||||
'size' => 'nullable|string|max:255',
|
'size' => 'nullable|string|max:255',
|
||||||
'type' => '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 = Vat::find($request->vat_id);
|
||||||
$vat_rate = $vat->rate ?? 0;
|
$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
|
// 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,
|
'business_id' => $business_id,
|
||||||
'alert_qty' => $request->alert_qty ?? 0,
|
'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,
|
'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,
|
'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)) {
|
if (in_array($request->product_type, ['single', 'variant']) && !empty($request->stocks)) {
|
||||||
$stockData = [];
|
$stockData = [];
|
||||||
foreach ($request->stocks as $stock) {
|
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[] = [
|
$stockData[] = [
|
||||||
'business_id' => $business_id,
|
'business_id' => $business_id,
|
||||||
'product_id' => $product->id,
|
'product_id' => $product->id,
|
||||||
|
'exclusive_price' => $stock['exclusive_price'] ?? 0,
|
||||||
'batch_no' => $stock['batch_no'] ?? null,
|
'batch_no' => $stock['batch_no'] ?? null,
|
||||||
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
||||||
'productStock' => $stock['productStock'] ?? 0,
|
'productStock' => $stock['productStock'] ?? 0,
|
||||||
'productPurchasePrice' => $purchasePrice,
|
'productPurchasePrice' => $stock['inclusive_price'] ?? 0, // inclusive purchase price / net cost price
|
||||||
'profit_percent' => $stock['profit_percent'] ?? 0,
|
'profit_percent' => $stock['profit_percent'] ?? 0,
|
||||||
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
||||||
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
||||||
@@ -281,16 +287,17 @@ public function edit($id)
|
|||||||
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||||
$brands = Brand::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();
|
$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();
|
$product_models = ProductModel::where('business_id', $business_id)->latest()->get();
|
||||||
$warehouses = Warehouse::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();
|
$racks = Rack::where('business_id', $business_id)->latest()->get();
|
||||||
$shelves = Shelf::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();
|
$variations = Variation::where('business_id', auth()->user()->business_id)->where('status', 1)->get();
|
||||||
$profit_option = Option::where('key', 'business-settings')
|
$profit_option = Option::where('key', 'business-settings')
|
||||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||||
->get()
|
->get()
|
||||||
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
|
->firstWhere('value.business_id', $business_id)
|
||||||
|
->value['product_profit_option'] ?? '';
|
||||||
|
|
||||||
$product = Product::with([
|
$product = Product::with([
|
||||||
'stocks' => function ($query) {
|
'stocks' => function ($query) {
|
||||||
@@ -334,6 +341,7 @@ public function update(Request $request, $id)
|
|||||||
return $query->where('business_id', $business_id);
|
return $query->where('business_id', $business_id);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
'hsn_code' => 'nullable|string|max:255',
|
||||||
'alert_qty' => 'nullable|numeric|min:0',
|
'alert_qty' => 'nullable|numeric|min:0',
|
||||||
'size' => 'nullable|string|max:255',
|
'size' => 'nullable|string|max:255',
|
||||||
'type' => '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 = Vat::find($request->vat_id);
|
||||||
$vat_rate = $vat->rate ?? 0;
|
$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
|
// 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,
|
'business_id' => $business_id,
|
||||||
'alert_qty' => $request->alert_qty ?? 0,
|
'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->profit_percent ?? 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,
|
'productPicture' => $request->productPicture ? $this->upload($request, 'productPicture', $product->productPicture) : $product->productPicture,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -406,22 +423,16 @@ function ($attribute, $value, $fail) use ($request) {
|
|||||||
|
|
||||||
// Insert or Update
|
// Insert or Update
|
||||||
foreach ($request->stocks as $stock) {
|
foreach ($request->stocks as $stock) {
|
||||||
|
|
||||||
$stockId = $stock['stock_id'] ?? null;
|
$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 = [
|
$payload = [
|
||||||
'business_id' => $business_id,
|
'business_id' => $business_id,
|
||||||
'product_id' => $product->id,
|
'product_id' => $product->id,
|
||||||
'batch_no' => $stock['batch_no'] ?? null,
|
'batch_no' => $stock['batch_no'] ?? null,
|
||||||
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
'warehouse_id' => $stock['warehouse_id'] ?? null,
|
||||||
'productStock' => $stock['productStock'] ?? 0,
|
'productStock' => $stock['productStock'] ?? 0,
|
||||||
'productPurchasePrice' => $purchasePrice,
|
'exclusive_price' => $stock['exclusive_price'] ?? 0,
|
||||||
|
'productPurchasePrice' =>$stock['inclusive_price'] ?? 0,
|
||||||
'profit_percent' => $stock['profit_percent'] ?? 0,
|
'profit_percent' => $stock['profit_percent'] ?? 0,
|
||||||
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
'productSalePrice' => $stock['productSalePrice'] ?? 0,
|
||||||
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
|
||||||
@@ -431,7 +442,7 @@ function ($attribute, $value, $fail) use ($request) {
|
|||||||
'variation_data' => $stock['variation_data'] ?? null,
|
'variation_data' => $stock['variation_data'] ?? null,
|
||||||
'variant_name' => $stock['variant_name'] ?? null,
|
'variant_name' => $stock['variant_name'] ?? null,
|
||||||
'branch_id' => auth()->user()->branch_id ?? auth()->user()->active_branch_id,
|
'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) {
|
if ($stockId) {
|
||||||
@@ -463,13 +474,12 @@ function ($attribute, $value, $fail) use ($request) {
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollback();
|
DB::rollback();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Something went wrong.'),
|
'message' => $e->getMessage(),
|
||||||
'error' => $e->getMessage(),
|
|
||||||
], 406);
|
], 406);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy($id)
|
public function destroy(string $id)
|
||||||
{
|
{
|
||||||
$product = Product::findOrFail($id);
|
$product = Product::findOrFail($id);
|
||||||
if (file_exists($product->productPicture)) {
|
if (file_exists($product->productPicture)) {
|
||||||
@@ -501,26 +511,40 @@ public function deleteAll(Request $request)
|
|||||||
|
|
||||||
public function getAllProduct()
|
public function getAllProduct()
|
||||||
{
|
{
|
||||||
|
$isTransfer = request()->is_transfer == 1;
|
||||||
|
|
||||||
$products = Product::with([
|
$products = Product::with([
|
||||||
'stocks' => function ($query) {
|
'stocks' => function ($query) use ($isTransfer) {
|
||||||
$query->where('productStock', '>', 0);
|
$query->where('productStock', '>', 0);
|
||||||
|
if (!$isTransfer) {
|
||||||
|
$query->where(function ($q) {
|
||||||
|
$q->whereNull('serial_numbers')
|
||||||
|
->orWhereJsonLength('serial_numbers', 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'category:id,categoryName',
|
'category:id,categoryName',
|
||||||
'unit:id,unitName',
|
'unit:id,unitName',
|
||||||
'stocks.warehouse:id,name',
|
'stocks.warehouse:id,name'
|
||||||
'vat:id,rate'
|
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->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()
|
->latest()
|
||||||
->get()
|
->get();
|
||||||
->where('total_stock', '>', 0)
|
|
||||||
->values();
|
|
||||||
|
|
||||||
return response()->json($products);
|
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();
|
$products = Product::where('business_id', auth()->user()->business_id)->where('category_id', $category_id)->get();
|
||||||
return response()->json($products);
|
return response()->json($products);
|
||||||
@@ -536,15 +560,63 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportProduct, 'product.csv');
|
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')
|
$user = auth()->user();
|
||||||
->where('business_id', auth()->user()->business_id)
|
$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')
|
->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()
|
->latest()
|
||||||
|
->limit($request->per_page ?? 20)
|
||||||
->get();
|
->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)
|
public function expiredProduct(Request $request)
|
||||||
@@ -561,6 +633,7 @@ public function expiredProduct(Request $request)
|
|||||||
$q->where('type', 'like', '%' . $request->search . '%')
|
$q->where('type', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('productName', 'like', '%' . $request->search . '%')
|
->orWhere('productName', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('productCode', 'like', '%' . $request->search . '%')
|
->orWhere('productCode', 'like', '%' . $request->search . '%')
|
||||||
|
->orWhere('hsn_code', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
|
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
|
||||||
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
|
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
|
||||||
->orWhereHas('unit', function ($q) use ($request) {
|
->orWhereHas('unit', function ($q) use ($request) {
|
||||||
@@ -586,103 +659,23 @@ public function expiredProduct(Request $request)
|
|||||||
return view('business::expired-products.index', compact('expired_products'));
|
return view('business::expired-products.index', compact('expired_products'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportExpireProductExcel()
|
public function show(string $id)
|
||||||
{
|
|
||||||
return Excel::download(new ExportExpiredProduct, 'expired-product.xlsx');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportExpireProductCsv()
|
|
||||||
{
|
|
||||||
return Excel::download(new ExportExpiredProduct, 'expired-product.csv');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show($id)
|
|
||||||
{
|
{
|
||||||
$business_id = auth()->user()->business_id;
|
$business_id = auth()->user()->business_id;
|
||||||
$product = Product::with('stocks')->where('business_id', $business_id)->findOrFail($id);
|
$product = Product::with('stocks')->where('business_id', $business_id)->findOrFail($id);
|
||||||
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
|
||||||
$brands = Brand::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();
|
$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')
|
$profit_option = Option::where('key', 'business-settings')
|
||||||
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
|
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
|
||||||
->get()
|
->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'));
|
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)
|
public function getShelf(Request $request)
|
||||||
{
|
{
|
||||||
$rack = Rack::with('shelves')->find($request->rack_id);
|
$rack = Rack::with('shelves')->find($request->rack_id);
|
||||||
@@ -698,4 +691,53 @@ public function getProductVariants($product_id)
|
|||||||
|
|
||||||
return response()->json($variant_stocks);
|
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;
|
$branchId = $user->branch_id ?? $user->active_branch_id;
|
||||||
|
|
||||||
$baseQuery = SaleDetails::query()
|
$baseQuery = SaleDetails::query()
|
||||||
->whereHas('product', fn ($q) =>
|
->whereHas('product', fn ($q) => $q->where('business_id', $user->business_id))
|
||||||
$q->where('business_id', $user->business_id)
|
|
||||||
)
|
|
||||||
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
|
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
|
||||||
$q->whereHas('sale', fn ($q) =>
|
$q->whereHas('sale', fn ($q) => $q->where('branch_id', $branchId));
|
||||||
$q->where('branch_id', $branchId)
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
->when($request->filled('search'), function ($q) use ($request) {
|
->when($request->filled('search'), function ($q) use ($request) {
|
||||||
$q->whereHas('product', function ($q) use ($request) {
|
$q->whereHas('product', function ($q) use ($request) {
|
||||||
$q->where('productName', 'like', "%{$request->search}%")
|
$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');
|
->sum('lossProfit');
|
||||||
|
|
||||||
$product_lossProfits = $baseQuery
|
$product_lossProfits = $baseQuery
|
||||||
->with('product:id,productName,productCode')
|
->with('product:id,productName,productCode,hsn_code')
|
||||||
->select(
|
->select(
|
||||||
'product_id',
|
'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 profit'),
|
||||||
@@ -54,17 +51,13 @@ public function index(Request $request)
|
|||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => view(
|
'data' => view('business::reports.product-loss-profit.datas', compact('product_lossProfits'))->render(),
|
||||||
'business::reports.product-loss-profit.datas',
|
'loss' => currency_format($loss, currency: business_currency()),
|
||||||
compact('product_lossProfits')
|
'profit' => currency_format($profit, currency: business_currency())
|
||||||
)->render()
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view(
|
return view('business::reports.product-loss-profit.index', compact('product_lossProfits', 'profit', 'loss'));
|
||||||
'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');
|
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')
|
$baseQuery = SaleDetails::query()
|
||||||
->whereHas('product', function ($q) {
|
->whereHas('product', fn ($q) =>
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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) {
|
->when($request->filled('search'), function ($q) use ($request) {
|
||||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
$q->whereHas('product', function ($q) use ($request) {
|
||||||
$sale->where('branch_id', $branchId);
|
$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(
|
->select(
|
||||||
'product_id',
|
'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 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 loss')
|
||||||
)
|
)
|
||||||
->groupBy('product_id')
|
->groupBy('product_id')
|
||||||
|
->limit($request->per_page ?? 20)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return PdfService::render('business::reports.product-loss-profit.pdf', compact('product_lossProfits'), 'product-loss-profit-report.pdf');
|
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'));
|
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;
|
$businessId = auth()->user()->business_id;
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
@@ -65,7 +65,7 @@ public function show(Request $request, $id)
|
|||||||
->whereHas('purchase', function ($purchase) use ($duration, $request) {
|
->whereHas('purchase', function ($purchase) use ($duration, $request) {
|
||||||
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
$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');
|
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
|
||||||
|
|
||||||
$purchaseDetailsQuery->when(filled($request->search), function ($q) use ($request) {
|
$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) {
|
->orWhereHas('purchase', function ($q) use ($search) {
|
||||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||||
->orWhere('purchaseDate', '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(
|
return view('business::product-purchase-history-report.details',
|
||||||
'business::product-purchase-history-report.details',
|
|
||||||
compact('product', 'purchaseDetails', 'filter_from_date', 'filter_to_date', 'duration')
|
compact('product', 'purchaseDetails', 'filter_from_date', 'filter_to_date', 'duration')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -108,9 +110,20 @@ public function exportCsv()
|
|||||||
public function exportPdf(Request $request)
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_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);
|
||||||
|
|
||||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
|
||||||
$products = $productQuery->get();
|
->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) {
|
$total_purchase_qty = $products->sum(function ($product) {
|
||||||
return $product->purchaseDetails->sum('quantities');
|
return $product->purchaseDetails->sum('quantities');
|
||||||
@@ -120,31 +133,54 @@ public function exportPdf(Request $request)
|
|||||||
return $product->saleDetails->sum('quantities');
|
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');
|
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');
|
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')
|
$product = Product::select('id', 'business_id', 'productName')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->findOrFail($id);
|
->findOrFail($id);
|
||||||
|
|
||||||
$purchaseDetailsQuery = $product->purchaseDetails()
|
$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');
|
->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);
|
$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) {
|
$query->when(request('search'), function ($q) use ($request) {
|
||||||
|
$q->where(function ($q) use ($request) {
|
||||||
$q->whereHas('product', function ($q) use ($request) {
|
$q->whereHas('product', function ($q) use ($request) {
|
||||||
$q->where('productName', 'like', '%' . $request->search . '%');
|
$q->where('productName', 'like', '%' . $request->search . '%');
|
||||||
})
|
})
|
||||||
@@ -34,13 +43,6 @@ public function index(Request $request)
|
|||||||
$q->where('name', 'like', '%' . $request->search . '%');
|
$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());
|
$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');
|
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) {
|
->whereHas('purchase', function ($q) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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'));
|
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;
|
$businessId = auth()->user()->business_id;
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
@@ -82,6 +82,9 @@ public function show(Request $request, $id)
|
|||||||
->orWhereHas('sale', function ($q) use ($search) {
|
->orWhereHas('sale', function ($q) use ($search) {
|
||||||
$q->where('invoiceNumber', 'like', "%{$search}%")
|
$q->where('invoiceNumber', 'like', "%{$search}%")
|
||||||
->orWhere('saleDate', '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)
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_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);
|
||||||
|
|
||||||
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
|
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
|
||||||
$products = $productQuery->get();
|
->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) {
|
$total_single_sale_price = $products->sum(function ($product) {
|
||||||
return $product->saleDetails->sum('price');
|
return $product->saleDetails->sum('price');
|
||||||
@@ -129,31 +143,54 @@ public function exportPdf(Request $request)
|
|||||||
return $product->saleDetails->sum('quantities');
|
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');
|
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');
|
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')
|
$product = Product::select('id', 'business_id', 'productName')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $businessId)
|
||||||
->findOrFail($id);
|
->findOrFail($id);
|
||||||
|
|
||||||
$saleDetailsQuery = $product->saleDetails()
|
$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')
|
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||||
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
|
->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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Sale;
|
use App\Models\SaleDetails;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
use App\Traits\DateRangeTrait;
|
use App\Traits\DateRangeTrait;
|
||||||
@@ -17,26 +17,34 @@ class AcnooProductSaleReportController extends Controller
|
|||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$query = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
|
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||||
->where('business_id', auth()->user()->business_id);
|
->whereHas('sale', function ($q) {
|
||||||
|
$q->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 . '%');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Date Filter
|
||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
[$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());
|
$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');
|
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')
|
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->whereHas('sale', function ($q) {
|
||||||
->latest()
|
$q->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
});
|
||||||
|
|
||||||
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;
|
$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')
|
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->where('business_id', $businessId);
|
->where('business_id', $businessId);
|
||||||
|
|
||||||
@@ -89,11 +85,38 @@ public function exportCsv()
|
|||||||
|
|
||||||
public function exportPdf(Request $request)
|
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')
|
$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)
|
->where('business_id', auth()->user()->business_id);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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 App\Models\Purchase;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\PurchaseReturnDetail;
|
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
use App\Traits\DateRangeTrait;
|
use App\Traits\DateRangeTrait;
|
||||||
@@ -26,12 +25,6 @@ public function index(Request $request)
|
|||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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([
|
$purchasesQuery = Purchase::with([
|
||||||
'user:id,name',
|
'user:id,name',
|
||||||
'branch:id,name',
|
'branch:id,name',
|
||||||
@@ -54,7 +47,9 @@ public function index(Request $request)
|
|||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
[$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
|
// Search Filter
|
||||||
if ($request->filled('search')) {
|
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
|
// Pagination
|
||||||
$perPage = $request->input('per_page', 20);
|
$perPage = $request->input('per_page', 20);
|
||||||
$purchases = $purchasesQuery->latest()->paginate($perPage)->appends($request->query());
|
$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
|
// Handle AJAX Request
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -105,7 +102,7 @@ public function exportCsv()
|
|||||||
|
|
||||||
public function exportPdf(Request $request)
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$purchases = Purchase::with([
|
$purchasesQuery = Purchase::with([
|
||||||
'user:id,name',
|
'user:id,name',
|
||||||
'branch:id,name',
|
'branch:id,name',
|
||||||
'party:id,name,email,phone,type',
|
'party:id,name,email,phone,type',
|
||||||
@@ -117,10 +114,35 @@ public function exportPdf(Request $request)
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereHas('purchaseReturns')
|
->whereHas('purchaseReturns');
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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\Sale;
|
||||||
use App\Models\Branch;
|
use App\Models\Branch;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
@@ -26,11 +25,8 @@ public function index(Request $request)
|
|||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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 = 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) {
|
$salesQuery->when($request->branch_id, function ($q) use ($request) {
|
||||||
$q->where('branch_id', $request->branch_id);
|
$q->where('branch_id', $request->branch_id);
|
||||||
});
|
});
|
||||||
@@ -88,10 +84,38 @@ public function exportCsv()
|
|||||||
|
|
||||||
public function exportPdf(Request $request)
|
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)
|
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
|
||||||
->latest()
|
->where('business_id', auth()->user()->business_id);
|
||||||
->get();
|
|
||||||
|
|
||||||
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\Sale;
|
||||||
use App\Models\Branch;
|
use App\Models\Branch;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\SaleReturnDetails;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
@@ -24,12 +23,6 @@ public function __construct()
|
|||||||
|
|
||||||
public function index(Request $request)
|
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;
|
$businessId = auth()->user()->business_id;
|
||||||
|
|
||||||
$salesQuery = Sale::with([
|
$salesQuery = Sale::with([
|
||||||
@@ -44,9 +37,7 @@ public function index(Request $request)
|
|||||||
->with('branch:id,name');
|
->with('branch:id,name');
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
->where('business_id', $businessId)
|
->where('business_id', $businessId)
|
||||||
|
|
||||||
->when($request->branch_id, function ($q) use ($request) {
|
->when($request->branch_id, function ($q) use ($request) {
|
||||||
$q->where('branch_id', $request->branch_id);
|
$q->where('branch_id', $request->branch_id);
|
||||||
})->whereHas('saleReturns');
|
})->whereHas('saleReturns');
|
||||||
@@ -55,7 +46,9 @@ public function index(Request $request)
|
|||||||
$duration = $request->custom_days ?: 'today';
|
$duration = $request->custom_days ?: 'today';
|
||||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
[$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
|
// Search Filter
|
||||||
if ($request->filled('search')) {
|
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);
|
$perPage = $request->input('per_page', 20);
|
||||||
$sales = $salesQuery->latest()->paginate($perPage)->appends($request->query());
|
$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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'data' => view('business::reports.sales-return.datas', compact('sales', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
'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)
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$sales = Sale::with([
|
$salesQuery = Sale::with([
|
||||||
'user:id,name',
|
'user:id,name',
|
||||||
'party:id,name',
|
'party:id,name',
|
||||||
'branch:id,name',
|
'branch:id,name',
|
||||||
@@ -116,10 +112,33 @@ public function exportPdf(Request $request)
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->whereHas('saleReturns')
|
->when($request->branch_id, function ($q) use ($request) {
|
||||||
->latest()
|
$q->where('branch_id', $request->branch_id);
|
||||||
->get();
|
})->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;
|
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\Http\Controllers\Controller;
|
||||||
|
use App\Models\Option;
|
||||||
|
use App\Models\ProductSetting;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
@@ -14,23 +14,29 @@ class AcnooSettingsManagerController extends Controller
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$businessId = auth()->user()->business_id;
|
||||||
$invoiceSettingKey = 'invoice_setting_' . $businessId;
|
$invoiceSettingKey = 'invoice_setting_'.$businessId;
|
||||||
$invoice_setting = Option::where('key', $invoiceSettingKey)->first();
|
$invoice_setting = Option::where('key', $invoiceSettingKey)->first();
|
||||||
$product_setting = ProductSetting::where('business_id', auth()->user()->business_id)->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();
|
$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)
|
public function updateInvoice(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$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(
|
Option::updateOrCreate(
|
||||||
['key' => $key],
|
['key' => $key],
|
||||||
@@ -45,8 +51,8 @@ public function updateInvoice(Request $request)
|
|||||||
public function updateProductSetting(Request $request)
|
public function updateProductSetting(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'show_product_price' => 'nullable|boolean',
|
|
||||||
'show_product_code' => 'nullable|boolean',
|
'show_product_code' => 'nullable|boolean',
|
||||||
|
'show_hsn_code' => 'nullable|boolean',
|
||||||
'show_product_stock' => 'nullable|boolean',
|
'show_product_stock' => 'nullable|boolean',
|
||||||
'show_product_sale_price' => 'nullable|boolean',
|
'show_product_sale_price' => 'nullable|boolean',
|
||||||
'show_product_dealer_price' => 'nullable|boolean',
|
'show_product_dealer_price' => 'nullable|boolean',
|
||||||
@@ -94,9 +100,9 @@ public function updateProductSetting(Request $request)
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!$request->boolean('show_product_type_single') &&
|
! $request->boolean('show_product_type_single') &&
|
||||||
!$request->boolean('show_product_type_variant') &&
|
! $request->boolean('show_product_type_variant') &&
|
||||||
!$request->boolean('show_product_type_combo')
|
! $request->boolean('show_product_type_combo')
|
||||||
) {
|
) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'product_type' => ['At least one product type must be selected: Single, Variant or Combo.'],
|
'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]
|
['modules' => $modules]
|
||||||
);
|
);
|
||||||
|
|
||||||
Cache::forget('product_setting_' . $businessId);
|
Cache::forget('product_setting_'.$businessId);
|
||||||
|
|
||||||
return response()->json(__('Product setting updated successfully.'));
|
return response()->json(__('Product setting updated successfully.'));
|
||||||
}
|
}
|
||||||
@@ -144,7 +150,7 @@ public function updateCurrency(Request $request)
|
|||||||
'currency' => 'required|string|max:100|in:us,european',
|
'currency' => 'required|string|max:100|in:us,european',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$key = 'currency_setting_' . auth()->user()->business_id;
|
$key = 'currency_setting_'.auth()->user()->business_id;
|
||||||
|
|
||||||
Option::updateOrCreate(
|
Option::updateOrCreate(
|
||||||
['key' => $key],
|
['key' => $key],
|
||||||
@@ -174,13 +180,39 @@ public function updateSerial(Request $request)
|
|||||||
$modules['show_serial'] = $request->boolean('show_serial') ? '1' : '0';
|
$modules['show_serial'] = $request->boolean('show_serial') ? '1' : '0';
|
||||||
|
|
||||||
$setting->update([
|
$setting->update([
|
||||||
'modules' => $modules
|
'modules' => $modules,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Cache::forget('product_setting_' . $businessId);
|
Cache::forget('product_setting_'.$businessId);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Serial setting updated successfully.',
|
'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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Stock;
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
|
||||||
use Modules\Business\App\Exports\ExportCurrentStock;
|
use Modules\Business\App\Exports\ExportCurrentStock;
|
||||||
|
|
||||||
class AcnooStockController extends Controller
|
class AcnooStockController extends Controller
|
||||||
@@ -25,81 +22,130 @@ public function index()
|
|||||||
$search_term = request('search');
|
$search_term = request('search');
|
||||||
$per_page = request('per_page', 20);
|
$per_page = request('per_page', 20);
|
||||||
|
|
||||||
// Base query
|
$query = Product::with('stocks', 'category:id,categoryName')
|
||||||
$query = Product::with('stocks','warehouse:id,name', 'rack:id,name', 'shelf:id,name')->where('product_type', '!=', 'combo')->where('business_id', $businessId);
|
->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) {
|
if ($search_term) {
|
||||||
$query->where(function ($q) use ($search_term) {
|
$query->where(function ($q) use ($search_term) {
|
||||||
$q->where('productName', 'like', '%' . $search_term . '%')
|
$q->where('productName', 'like', '%' . $search_term . '%')
|
||||||
->orWhere('productPurchasePrice', 'like', '%' . $search_term . '%')
|
->orWhere('productCode', 'like', '%' . $search_term . '%')
|
||||||
->orWhere('productSalePrice', '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
|
if ($alert_qty_filter) {
|
||||||
$allProducts = $query->latest()->get();
|
$products = $query
|
||||||
$filteredProducts = $allProducts->filter(function ($product) {
|
->withSum('stocks as total_stock', 'productStock')
|
||||||
$totalStock = $product->stocks->sum('productStock');
|
->whereRaw('(SELECT COALESCE(SUM("productStock"),0) FROM stocks WHERE stocks.product_id = products.id) <= products.alert_qty')
|
||||||
return $totalStock <= $product->alert_qty;
|
->latest()
|
||||||
});
|
->paginate($per_page)
|
||||||
|
->appends(request()->query());
|
||||||
|
|
||||||
// Manual pagination for filtered collection
|
$total_stock_qty = $products->sum('total_stock');
|
||||||
$currentPage = request('page', 1);
|
|
||||||
$products = new LengthAwarePaginator(
|
|
||||||
$filteredProducts->forPage($currentPage, $per_page),
|
|
||||||
$filteredProducts->count(),
|
|
||||||
$per_page,
|
|
||||||
$currentPage,
|
|
||||||
['path' => request()->url(), 'query' => request()->query()]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Calculate totals for low stock view
|
$total_stock_value = $products->sum(function ($product) {
|
||||||
$total_stock_value = $filteredProducts->sum(function ($product) {
|
|
||||||
return $product->stocks->sum(function ($stock) {
|
return $product->stocks->sum(function ($stock) {
|
||||||
return $stock->productStock * $stock->productPurchasePrice;
|
return $stock->productStock * $stock->productPurchasePrice;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$total_qty = $filteredProducts->sum(function ($product) {
|
|
||||||
return $product->stocks->sum('productStock');
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// For All Stock view - NO search, just regular pagination
|
$products = $query
|
||||||
$products = $query->latest()->paginate($per_page)->appends(request()->query());
|
->withSum('stocks as total_stock', 'productStock')
|
||||||
|
->latest()
|
||||||
|
->paginate($per_page)
|
||||||
|
->appends(request()->query());
|
||||||
|
|
||||||
// Calculate totals for all stock
|
$total_stock_qty = $products->sum('total_stock');
|
||||||
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
|
|
||||||
$q->where('business_id', $businessId);
|
|
||||||
})->sum(DB::raw('"productPurchasePrice" * "productStock"'));
|
|
||||||
|
|
||||||
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
|
$total_stock_value = $products->sum(function ($product) {
|
||||||
$q->where('business_id', $businessId);
|
return $product->stocks->sum(function ($stock) {
|
||||||
})->sum('productStock');
|
return $stock->productStock * $stock->productPurchasePrice;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle AJAX request
|
|
||||||
if (request()->ajax()) {
|
if (request()->ajax()) {
|
||||||
return response()->json([
|
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', [
|
return view('business::stocks.index', [
|
||||||
'products' => $products,
|
'products' => $products,
|
||||||
'total_stock_value' => $total_stock_value,
|
'total_stock_value' => $total_stock_value,
|
||||||
'total_qty' => $total_qty,
|
'total_stock_qty' => $total_stock_qty,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportExcel()
|
public function exportExcel()
|
||||||
{
|
{
|
||||||
return Excel::download(new ExportCurrentStock, 'current-stock.xlsx');
|
return Excel::download(new ExportCurrentStock, 'stock-list.xlsx');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportCsv()
|
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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Stock;
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\PdfService;
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
@@ -22,31 +20,42 @@ public function index(Request $request)
|
|||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$businessId = auth()->user()->business_id;
|
||||||
|
|
||||||
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
|
$productsQuery = Product::with(['stocks' => function ($q) {
|
||||||
$q->where('business_id', $businessId);
|
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
|
||||||
})->sum(DB::raw('"productPurchasePrice" * "productStock"'));
|
}])
|
||||||
|
->where('business_id', $businessId)
|
||||||
|
->where('product_type', '!=', 'combo');
|
||||||
|
|
||||||
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
|
if ($request->search) {
|
||||||
$q->where('business_id', $businessId);
|
$productsQuery->where(function ($q) use ($request) {
|
||||||
})->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) {
|
|
||||||
$q->where('productName', 'like', '%' . $request->search . '%')
|
$q->where('productName', 'like', '%' . $request->search . '%')
|
||||||
->orwhere('productSalePrice', 'like', '%' . $request->search . '%')
|
->orWhereHas('stocks', function ($stock) use ($request) {
|
||||||
->orwhere('productPurchasePrice', 'like', '%' . $request->search . '%');
|
$stock->where('productSalePrice', 'like', '%' . $request->search . '%')
|
||||||
|
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%');
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
->withSum('stocks', 'productStock')
|
}
|
||||||
|
|
||||||
|
$stock_reports = $productsQuery
|
||||||
->latest()
|
->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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
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');
|
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('business_id', auth()->user()->business_id)
|
||||||
->where('product_type', '!=', 'combo');
|
->where('product_type', '!=', 'combo');
|
||||||
|
|
||||||
if (request('alert_qty')) {
|
if ($request->search) {
|
||||||
$stock_reports = $query->get()->filter(function ($product) {
|
$productsQuery->where(function ($q) use ($request) {
|
||||||
$totalStock = $product->stocks->sum('productStock');
|
$q->where('productName', 'like', '%' . $request->search . '%')
|
||||||
return $totalStock <= $product->alert_qty;
|
->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');
|
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');
|
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)
|
$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);
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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);
|
$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'));
|
return view('business::reports.subscription-reports.invoice', compact('subscriber'));
|
||||||
|
|||||||
@@ -35,82 +35,52 @@ public function index(Request $request)
|
|||||||
->with('purchases_dues')
|
->with('purchases_dues')
|
||||||
->latest();
|
->latest();
|
||||||
|
|
||||||
// Branch-aware due filter
|
$parties = $query
|
||||||
if ($activeBranch) {
|
->paginate($request->per_page ?? 20)
|
||||||
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
|
->appends($request->query());
|
||||||
$q->where('branch_id', $activeBranch->id)
|
|
||||||
->where('dueAmount', '>', 0);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query->where('due', '>', 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$parties = $query->paginate($request->per_page ?? 20);
|
|
||||||
|
|
||||||
// Replace $supplier->due with branch-specific due if active branch exists
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->setCollection(
|
$parties->setCollection(
|
||||||
$parties->getCollection()
|
$parties->getCollection()
|
||||||
->transform(function ($supplier) use ($activeBranch) {
|
->transform(function ($supplier) use ($activeBranch) {
|
||||||
$supplier->due = $supplier->purchases_dues
|
$party_due = $supplier->purchases_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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;
|
return $supplier;
|
||||||
})
|
})
|
||||||
->filter(fn($supplier) => $supplier->due > 0)
|
->filter(fn($supplier) => $supplier->due > 0)
|
||||||
->values()
|
->values()
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$parties->setCollection(
|
||||||
|
$parties->getCollection()
|
||||||
|
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
|
||||||
|
->values()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total_due
|
$supplier_total_due = $parties->getCollection()->sum('due');
|
||||||
$total_due = $parties->sum(function ($supplier) {
|
|
||||||
return $supplier->due;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
|
|
||||||
return response()->json([
|
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) {
|
return view('business::reports.supplier-due.due-reports', compact('parties', 'supplier_total_due'));
|
||||||
// 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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportExcel()
|
public function exportExcel()
|
||||||
@@ -123,7 +93,7 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportSupplierDue, 'supplier-due.csv');
|
return Excel::download(new ExportSupplierDue, 'supplier-due.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$businessId = $user->business_id;
|
$businessId = $user->business_id;
|
||||||
@@ -131,29 +101,48 @@ public function exportPdf()
|
|||||||
|
|
||||||
$query = Party::where('business_id', $businessId)
|
$query = Party::where('business_id', $businessId)
|
||||||
->where('type', 'Supplier')
|
->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')
|
->with('purchases_dues')
|
||||||
->latest();
|
->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();
|
$parties = $query->get();
|
||||||
|
|
||||||
if ($activeBranch) {
|
if ($activeBranch) {
|
||||||
$parties->transform(function ($supplier) use ($activeBranch) {
|
$parties = $parties
|
||||||
$supplier->due = $supplier->purchases_dues
|
->transform(function ($supplier) use ($activeBranch) {
|
||||||
|
$party_due = $supplier->purchases_dues
|
||||||
->where('branch_id', $activeBranch->id)
|
->where('branch_id', $activeBranch->id)
|
||||||
->sum('dueAmount');
|
->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);
|
$party = Party::find($partyId);
|
||||||
$ledger = $service->list($request, $partyId);
|
$ledger = $service->list($request, $partyId);
|
||||||
@@ -74,18 +74,25 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportSupplierLedger, 'supplier-ledger.csv');
|
return Excel::download(new ExportSupplierLedger, 'supplier-ledger.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$suppliers = Party::with('purchases')
|
$suppliers = Party::with('purchases')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '=', 'Supplier')
|
->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()
|
->latest()
|
||||||
->get();
|
->limit($request->per_page ?? 20)->get();
|
||||||
|
|
||||||
return PdfService::render('business::party-reports.supplier-ledger.pdf', compact('suppliers'),'supplier-ledger-report.pdf');
|
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);
|
$party = Party::findOrFail($partyId);
|
||||||
$ledger = $service->list($request, $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');
|
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);
|
$party = Party::findOrFail($partyId);
|
||||||
$ledger = $service->list($request, $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');
|
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);
|
$party = Party::find($partyId);
|
||||||
$ledger = $service->list($request, $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(
|
return PdfService::render(
|
||||||
'business::party-reports.supplier-ledger.show-details.pdf',
|
'business::party-reports.supplier-ledger.show-details.pdf',
|
||||||
compact('ledger', 'party'),
|
compact('ledger', 'party', 'duration', 'fromDate', 'toDate'),
|
||||||
strtolower($party->name).'-supplier.pdf'
|
strtolower($party->name).'-supplier.pdf'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,16 +56,29 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportTopCustomer, 'top-customers.csv');
|
return Excel::download(new ExportTopCustomer, 'top-customers.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$customers = Party::with('sales')
|
$customers = Party::with('sales')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '!=', 'Supplier')
|
->where('type', '!=', 'Supplier')
|
||||||
->whereHas('sales')
|
->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')
|
->withCount('sales')
|
||||||
->withSum('sales', 'totalAmount')
|
->withSum('sales', 'totalAmount')
|
||||||
->orderByDesc('sales_count')
|
->orderByDesc('sales_count')
|
||||||
->orderByDesc('sales_sum_total_amount')
|
->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)
|
->take(5)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public function index(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$top_products = SaleDetails::query()
|
$top_products = SaleDetails::query()
|
||||||
->with('product:id,productName,productCode')
|
->with('product:id,productName,productCode,hsn_code')
|
||||||
->whereHas('product', function ($q) use ($businessId) {
|
->whereHas('product', function ($q) use ($businessId) {
|
||||||
$q->where('business_id', $businessId);
|
$q->where('business_id', $businessId);
|
||||||
})
|
})
|
||||||
@@ -67,27 +67,40 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportTopProduct, 'top-products.csv');
|
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')
|
$branchId = null;
|
||||||
->whereHas('product', function ($q) {
|
if (moduleCheck('MultiBranchAddon')) {
|
||||||
$q->where('business_id', auth()->user()->business_id);
|
$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) {
|
->when($branchId, function ($q) use ($branchId) {
|
||||||
$q->whereHas('sale', function ($sale) use ($branchId) {
|
$q->whereHas('sale', function ($q) use ($branchId) {
|
||||||
$sale->where('branch_id', $branchId);
|
$q->where('branch_id', $branchId);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
->select(
|
->select(
|
||||||
'product_id',
|
'product_id',
|
||||||
DB::raw('SUM(quantities) as total_sold_qty'),
|
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')
|
->groupBy('product_id')
|
||||||
->orderByDesc('total_sold_qty')
|
->orderByDesc('total_sold_qty')
|
||||||
->take(5)
|
->limit(5)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return PdfService::render('business::reports.top-products.pdf', compact('top_products'),'top-product-report.pdf');
|
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');
|
return Excel::download(new ExportTopSupplier, 'top-suppliers.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$suppliers = Party::with('purchases')
|
$suppliers = Party::with('purchases')
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', auth()->user()->business_id)
|
||||||
->where('type', '=', 'Supplier')
|
->where('type', '=', 'Supplier')
|
||||||
->whereHas('purchases')
|
->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')
|
->withCount('purchases')
|
||||||
->withSum('purchases', 'totalAmount')
|
->withSum('purchases', 'totalAmount')
|
||||||
->orderByDesc('purchases_count')
|
->orderByDesc('purchases_count')
|
||||||
|
|||||||
@@ -124,13 +124,78 @@ public function exportCsv()
|
|||||||
return Excel::download(new ExportTransactionReport, 'bill-wise-profit.csv');
|
return Excel::download(new ExportTransactionReport, 'bill-wise-profit.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPdf()
|
public function exportPdf(Request $request)
|
||||||
{
|
{
|
||||||
$transactions = Transaction::with('paymentType')
|
$businessId = auth()->user()->business_id;
|
||||||
->where('business_id', auth()->user()->business_id)
|
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
use App\Traits\DateRangeTrait;
|
use App\Traits\DateRangeTrait;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportTransaction;
|
use Modules\Business\App\Exports\ExportTransaction;
|
||||||
|
|
||||||
@@ -24,15 +23,6 @@ public function __construct()
|
|||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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);
|
$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');
|
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)
|
$businessId = auth()->user()->business_id;
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
|
|
||||||
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\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Services\PdfService;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportTransfer;
|
use Modules\Business\App\Exports\ExportTransfer;
|
||||||
|
|
||||||
@@ -25,11 +26,20 @@ public function __construct()
|
|||||||
|
|
||||||
public function index(Request $request)
|
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'])
|
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
|
||||||
->where('business_id', auth()->user()->business_id)
|
->where('business_id', $user->business_id)
|
||||||
->when($request->branch_id, function ($q) use ($request) {
|
->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) {
|
$q->where(function ($query) use ($request) {
|
||||||
$query->where('from_branch_id', $request->branch_id)->orWhere('to_branch_id', $request->branch_id);
|
$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)
|
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([
|
$request->validate([
|
||||||
'from_branch_id' => 'nullable|exists:branches,id',
|
'from_branch_id' => 'nullable|exists:branches,id',
|
||||||
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_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.*.unit_price' => 'required|numeric|min:0',
|
||||||
'products.*.discount' => 'nullable|numeric|min:0',
|
'products.*.discount' => 'nullable|numeric|min:0',
|
||||||
'products.*.tax' => 'nullable|numeric|min:0',
|
'products.*.tax' => 'nullable|numeric|min:0',
|
||||||
|
'products.*.serial_numbers' => 'nullable|array',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
@@ -99,72 +123,54 @@ public function store(Request $request)
|
|||||||
$fromWh = $request->from_warehouse_id;
|
$fromWh = $request->from_warehouse_id;
|
||||||
$toWh = $request->to_warehouse_id;
|
$toWh = $request->to_warehouse_id;
|
||||||
|
|
||||||
// Transfer validation logic
|
// Transfer validation
|
||||||
if ($user->active_branch_id && $toBranch && $toWh) {
|
if ($user->active_branch_id && $toBranch && $toWh) {
|
||||||
return response()->json([
|
return response()->json(['message' => 'You cannot transfer to another branch warehouse.'], 400);
|
||||||
'message' => 'You cannot transfer to another branch warehouse.'
|
|
||||||
], 400);
|
|
||||||
}
|
}
|
||||||
if (!$toBranch && !$toWh) {
|
if (!$toBranch && !$toWh) {
|
||||||
// to_branch or to_warehouse no one exist
|
return response()->json(['message' => 'Please select a destination branch or warehouse.'], 400);
|
||||||
return response()->json([
|
|
||||||
'message' => 'Invalid transfer request. Please select a destination branch or warehouse.'
|
|
||||||
], 400);
|
|
||||||
}
|
}
|
||||||
if ($fromBranch && !$fromWh) {
|
if ($fromBranch && !$fromWh && $fromBranch == $toBranch) {
|
||||||
// Branch to Branch transfer only
|
return response()->json(['message' => 'Same branch transfer is not allowed.'], 400);
|
||||||
if ($fromBranch == $toBranch) {
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Transfer not allowed: Same branch transfer is not possible.'
|
|
||||||
], 400);
|
|
||||||
}
|
}
|
||||||
} elseif (!$fromBranch && $fromWh) {
|
if ($fromWh && $fromWh == $toWh) {
|
||||||
// Warehouse to Warehouse transfer only
|
return response()->json(['message' => 'Same warehouse transfer is not allowed.'], 400);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$subTotal = 0;
|
$subTotal = $totalDiscount = $totalTax = 0;
|
||||||
$totalDiscount = 0;
|
|
||||||
$totalTax = 0;
|
|
||||||
|
|
||||||
foreach ($request->products as $item) {
|
// products re-arrange
|
||||||
$qty = $item['quantity'];
|
$products = collect($request->products)->map(function ($item, $key) {
|
||||||
$price = $item['unit_price'];
|
return array_merge($item, ['stock_id' => $item['stock_id'] ?? $key]);
|
||||||
$discount = $item['discount'] ?? 0;
|
});
|
||||||
$tax = $item['tax'] ?? 0;
|
|
||||||
|
|
||||||
$subTotal += ($qty * $price);
|
// Calculate subtotal using serial count if available
|
||||||
$totalTax += $tax;
|
foreach ($products as $item) {
|
||||||
$totalDiscount += $discount;
|
$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;
|
$shipping = $request->shipping_charge ?? 0;
|
||||||
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
|
$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') + [
|
$transfer = Transfer::create([
|
||||||
'business_id' => auth()->user()->business_id,
|
'business_id' => $user->business_id,
|
||||||
|
'user_id' => auth()->id(),
|
||||||
'from_branch_id' => $fromBranch,
|
'from_branch_id' => $fromBranch,
|
||||||
'from_warehouse_id' => $fromWh,
|
'from_warehouse_id' => $fromWh,
|
||||||
'to_branch_id' => $toBranch,
|
'to_branch_id' => $toBranch,
|
||||||
'to_warehouse_id' => $toWh,
|
'to_warehouse_id' => $toWh,
|
||||||
|
'transfer_date' => $request->transfer_date,
|
||||||
|
'status' => $request->status,
|
||||||
|
'note' => $request->note,
|
||||||
'shipping_charge' => $shipping,
|
'shipping_charge' => $shipping,
|
||||||
'sub_total' => $subTotal,
|
'sub_total' => $subTotal,
|
||||||
'total_discount' => $totalDiscount,
|
'total_discount' => $totalDiscount,
|
||||||
@@ -172,115 +178,120 @@ public function store(Request $request)
|
|||||||
'grand_total' => $grandTotal,
|
'grand_total' => $grandTotal,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$transferProductData = [];
|
$transferProducts = [];
|
||||||
|
|
||||||
foreach ($request->products as $stockId => $item) {
|
|
||||||
// Find product_id from stock_id
|
|
||||||
$stock = Stock::find($stockId);
|
|
||||||
|
|
||||||
|
foreach ($products as $item) {
|
||||||
|
$stock = Stock::find($item['stock_id']);
|
||||||
if (!$stock) {
|
if (!$stock) {
|
||||||
return response()->json([
|
return response()->json(['message' => "Invalid stock ID: {$item['stock_id']}"], 400);
|
||||||
'message' => "Invalid stock ID: {$stockId}"
|
|
||||||
], 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,
|
'transfer_id' => $transfer->id,
|
||||||
'stock_id' => $stockId,
|
'stock_id' => $stock->id,
|
||||||
'product_id' => $stock->product_id,
|
'product_id' => $stock->product_id,
|
||||||
'quantity' => $item['quantity'] ?? 0,
|
'quantity' => $quantity,
|
||||||
'unit_price' => $item['unit_price'] ?? 0,
|
'unit_price' => $item['unit_price'],
|
||||||
'discount' => $item['discount'] ?? 0,
|
'discount' => $item['discount'] ?? 0,
|
||||||
'tax' => $item['tax'] ?? 0,
|
'tax' => $item['tax'] ?? 0,
|
||||||
|
'serial_numbers' => !empty($serials) ? json_encode($serials) : null,
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now(),
|
'updated_at' => now(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($request->status === 'completed') {
|
if ($request->status === 'completed') {
|
||||||
foreach ($request->products as $stockId => $item) {
|
// FROM stock
|
||||||
// Get the actual FROM stock
|
$fromStock = Stock::where('id', $stock->id)
|
||||||
$fromStock = Stock::where('id', $stockId)
|
|
||||||
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
||||||
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
|
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$fromStock) {
|
if (!$fromStock || $fromStock->productStock < $quantity) {
|
||||||
return response()->json([
|
return response()->json(['message' => 'Insufficient stock for product ID: ' . $stock->product_id], 400);
|
||||||
'message' => "Stock not found in source (branch/warehouse) for stock ID: {$stockId}"
|
|
||||||
], 400);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($fromStock->productStock < $item['quantity']) {
|
// Remove serials from source
|
||||||
return response()->json([
|
if (!empty($serials)) {
|
||||||
'message' => "Insufficient stock in source for product ID: {$fromStock->product_id}, available: {$fromStock->productStock}"
|
$existingSerials = is_array($fromStock->serial_numbers) ? $fromStock->serial_numbers : json_decode($fromStock->serial_numbers ?? '[]', true);
|
||||||
], 400);
|
$fromStock->serial_numbers = array_values(array_diff($existingSerials, $serials));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrease FROM stock
|
$fromStock->decrement('productStock', $quantity);
|
||||||
$fromStock->decrement('productStock', $item['quantity']);
|
$fromStock->save();
|
||||||
|
|
||||||
// Get the TO stock
|
// TO stock
|
||||||
$toStock = Stock::where('product_id', $fromStock->product_id)
|
$toStock = Stock::where('product_id', $fromStock->product_id)
|
||||||
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
||||||
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
|
->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();
|
->first();
|
||||||
|
|
||||||
if (!$toStock) {
|
if (!$toStock) {
|
||||||
$toStock = new Stock([
|
$toStock = new Stock([
|
||||||
'business_id' => auth()->user()->business_id,
|
'business_id' => $user->business_id,
|
||||||
'product_id' => $fromStock->product_id,
|
'product_id' => $fromStock->product_id,
|
||||||
'warehouse_id' => $toWh,
|
'warehouse_id' => $toWh,
|
||||||
'batch_no' => $fromStock->batch_no,
|
|
||||||
'productStock' => 0,
|
'productStock' => 0,
|
||||||
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
||||||
'profit_percent' => $fromStock->profit_percent,
|
'profit_percent' => $fromStock->profit_percent,
|
||||||
'productSalePrice' => $fromStock->productSalePrice,
|
'productSalePrice' => $fromStock->productSalePrice,
|
||||||
|
'exclusive_price' => $fromStock->exclusive_price,
|
||||||
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
||||||
'productDealerPrice' => $fromStock->productDealerPrice,
|
'productDealerPrice' => $fromStock->productDealerPrice,
|
||||||
'mfg_date' => $fromStock->mfg_date,
|
'mfg_date' => $fromStock->mfg_date,
|
||||||
'expire_date' => $fromStock->expire_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
|
// Safe branch assignment
|
||||||
if ($toBranch == null && $user->active_branch_id){
|
$toStock->branch_id = $toBranch ?? $user->active_branch_id;
|
||||||
$toStock->branch_id = $user->active_branch_id;
|
|
||||||
}else{
|
|
||||||
$toStock->branch_id = $toBranch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update product_type
|
// Save without events/global scopes
|
||||||
if ($fromStock->product->product_type !== 'variant') {
|
|
||||||
$fromStock->product->update([
|
|
||||||
'product_type' => 'variant'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip booted from model
|
|
||||||
Stock::withoutEvents(function () use ($toStock) {
|
Stock::withoutEvents(function () use ($toStock) {
|
||||||
$toStock->save();
|
$toStock->save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase TO stock safely
|
// Increment destination stock safely
|
||||||
$toStock->increment('productStock', $item['quantity']);
|
$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();
|
DB::commit();
|
||||||
|
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Transfer saved successfully.'),
|
'message' => __('Transfer saved successfully.'),
|
||||||
|
'data' => $transfer,
|
||||||
'redirect' => route('business.transfers.index'),
|
'redirect' => route('business.transfers.index'),
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Error: ' . $e->getMessage(),
|
'success' => false,
|
||||||
|
'message' => $e->getMessage()
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,6 +324,19 @@ public function edit($id)
|
|||||||
|
|
||||||
public function update(Request $request, $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([
|
$request->validate([
|
||||||
'from_branch_id' => 'nullable|exists:branches,id',
|
'from_branch_id' => 'nullable|exists:branches,id',
|
||||||
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_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.*.unit_price' => 'required|numeric|min:0',
|
||||||
'products.*.discount' => 'nullable|numeric|min:0',
|
'products.*.discount' => 'nullable|numeric|min:0',
|
||||||
'products.*.tax' => 'nullable|numeric|min:0',
|
'products.*.tax' => 'nullable|numeric|min:0',
|
||||||
|
'products.*.serial_numbers' => 'nullable|array',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$transfer = Transfer::findOrFail($id);
|
$transfer = Transfer::findOrFail($id);
|
||||||
|
|
||||||
if ($request->status == 'cancelled') {
|
if ($request->status === 'cancelled') {
|
||||||
$transfer->update(['status' => 'cancelled']);
|
$transfer->update(['status' => 'cancelled']);
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Transfer cancelled successfully.'),
|
'message' => __('Transfer cancelled successfully.'),
|
||||||
@@ -345,49 +370,28 @@ public function update(Request $request, $id)
|
|||||||
$fromWh = $request->from_warehouse_id;
|
$fromWh = $request->from_warehouse_id;
|
||||||
$toWh = $request->to_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();
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$oldStatus = $transfer->status;
|
$oldStatus = $transfer->status;
|
||||||
$subTotal = $totalDiscount = $totalTax = 0;
|
$subTotal = $totalDiscount = $totalTax = 0;
|
||||||
|
|
||||||
|
// Calculate totals using serial count
|
||||||
foreach ($request->products as $item) {
|
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;
|
$totalDiscount += $item['discount'] ?? 0;
|
||||||
$totalTax += $item['tax'] ?? 0;
|
$totalTax += $item['tax'] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$shipping = $request->shipping_charge ?? 0;
|
$shipping = $request->shipping_charge ?? 0;
|
||||||
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
|
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
|
||||||
|
|
||||||
// Update transfer
|
// Update transfer
|
||||||
$transfer->update([
|
$transfer->update([
|
||||||
|
'user_id' => auth()->id(),
|
||||||
'from_branch_id' => $fromBranch,
|
'from_branch_id' => $fromBranch,
|
||||||
'to_branch_id' => $toBranch,
|
'to_branch_id' => $toBranch,
|
||||||
'from_warehouse_id' => $fromWh,
|
'from_warehouse_id' => $fromWh,
|
||||||
@@ -402,25 +406,25 @@ public function update(Request $request, $id)
|
|||||||
'grand_total' => $grandTotal,
|
'grand_total' => $grandTotal,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update TransferProduct
|
// Delete old transfer products
|
||||||
TransferProduct::where('transfer_id', $transfer->id)->delete();
|
TransferProduct::where('transfer_id', $transfer->id)->delete();
|
||||||
$transferProductData = [];
|
|
||||||
foreach ($request->products as $stockId => $item) {
|
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,
|
'transfer_id' => $transfer->id,
|
||||||
'stock_id' => $stockId,
|
'stock_id' => $stockId,
|
||||||
'quantity' => $item['quantity'] ?? 0,
|
'quantity' => $quantity,
|
||||||
'unit_price' => $item['unit_price'] ?? 0,
|
'unit_price' => $item['unit_price'] ?? 0,
|
||||||
'discount' => $item['discount'] ?? 0,
|
'discount' => $item['discount'] ?? 0,
|
||||||
'tax' => $item['tax'] ?? 0,
|
'tax' => $item['tax'] ?? 0,
|
||||||
'created_at' => now(),
|
'serial_numbers' => !empty($serials) ? $serials : null,
|
||||||
'updated_at' => now(),
|
]);
|
||||||
];
|
|
||||||
}
|
|
||||||
TransferProduct::insert($transferProductData);
|
|
||||||
|
|
||||||
// Stock Handling
|
|
||||||
foreach ($request->products as $stockId => $item) {
|
|
||||||
$fromStock = Stock::where('id', $stockId)
|
$fromStock = Stock::where('id', $stockId)
|
||||||
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
|
||||||
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
|
->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}"
|
'message' => "From stock not found for stock ID: {$stockId}"
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$toStock = Stock::where('product_id', $fromStock->product_id)
|
$toStock = Stock::where('product_id', $fromStock->product_id)
|
||||||
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
|
||||||
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
|
->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();
|
->first();
|
||||||
|
|
||||||
if (!$toStock) {
|
if (!$toStock) {
|
||||||
$toStock = new Stock([
|
$toStock = new Stock([
|
||||||
'business_id' => auth()->user()->business_id,
|
'business_id' => $user->business_id,
|
||||||
'product_id' => $fromStock->product_id,
|
'product_id' => $fromStock->product_id,
|
||||||
'warehouse_id' => $toWh,
|
'warehouse_id' => $toWh,
|
||||||
'batch_no' => $fromStock->batch_no,
|
|
||||||
'productStock' => 0,
|
'productStock' => 0,
|
||||||
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
'productPurchasePrice' => $fromStock->productPurchasePrice,
|
||||||
|
'exclusive_price' => $fromStock->exclusive_price,
|
||||||
'profit_percent' => $fromStock->profit_percent,
|
'profit_percent' => $fromStock->profit_percent,
|
||||||
'productSalePrice' => $fromStock->productSalePrice,
|
'productSalePrice' => $fromStock->productSalePrice,
|
||||||
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
|
||||||
@@ -453,31 +463,43 @@ public function update(Request $request, $id)
|
|||||||
'expire_date' => $fromStock->expire_date,
|
'expire_date' => $fromStock->expire_date,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// if active branch and to branch is null then use active branch id
|
$toStock->branch_id = $toBranch ?? $user->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'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stock::withoutEvents(fn() => $toStock->save());
|
Stock::withoutEvents(fn() => $toStock->save());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stock movement based on status change
|
// Only move stock if changing pending to completed
|
||||||
if ($oldStatus !== $request->status) {
|
|
||||||
if ($oldStatus === 'pending' && $request->status === 'completed') {
|
if ($oldStatus === 'pending' && $request->status === 'completed') {
|
||||||
if ($fromStock->productStock >= $item['quantity']) {
|
|
||||||
$fromStock->decrement('productStock', $item['quantity']);
|
// Handle serials for source
|
||||||
$toStock->increment('productStock', $item['quantity']);
|
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.'),
|
'message' => __('Transfer updated successfully.'),
|
||||||
'redirect' => route('business.transfers.index'),
|
'redirect' => route('business.transfers.index'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -494,8 +517,7 @@ public function update(Request $request, $id)
|
|||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public function destroy(string $id)
|
||||||
public function destroy($id)
|
|
||||||
{
|
{
|
||||||
$business_id = auth()->user()->business_id;
|
$business_id = auth()->user()->business_id;
|
||||||
$transfer = Transfer::with('transferProducts')->where('business_id', $business_id)->findOrFail($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)
|
$toStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||||
->where('branch_id', $transfer->to_branch_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();
|
->first();
|
||||||
|
|
||||||
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
||||||
@@ -528,8 +553,12 @@ public function destroy($id)
|
|||||||
$toStock = Stock::where('product_id', $tp->product_id)
|
$toStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||||
->where('branch_id', $transfer->to_branch_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();
|
->first();
|
||||||
|
|
||||||
if ($toStock) {
|
if ($toStock) {
|
||||||
$toStock->decrement('quantity', $tp->quantity);
|
$toStock->decrement('quantity', $tp->quantity);
|
||||||
}
|
}
|
||||||
@@ -538,8 +567,12 @@ public function destroy($id)
|
|||||||
$fromStock = Stock::where('product_id', $tp->product_id)
|
$fromStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->from_warehouse_id)
|
->where('warehouse_id', $transfer->from_warehouse_id)
|
||||||
->where('branch_id', $transfer->from_branch_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();
|
->first();
|
||||||
|
|
||||||
if ($fromStock) {
|
if ($fromStock) {
|
||||||
$fromStock->increment('quantity', $tp->quantity);
|
$fromStock->increment('quantity', $tp->quantity);
|
||||||
}
|
}
|
||||||
@@ -583,7 +616,10 @@ public function deleteAll(Request $request)
|
|||||||
$toStock = Stock::where('product_id', $tp->product_id)
|
$toStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||||
->where('branch_id', $transfer->to_branch_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();
|
->first();
|
||||||
|
|
||||||
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
if (!$toStock || $toStock->quantity < $tp->quantity) {
|
||||||
@@ -604,8 +640,12 @@ public function deleteAll(Request $request)
|
|||||||
$toStock = Stock::where('product_id', $tp->product_id)
|
$toStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->to_warehouse_id)
|
->where('warehouse_id', $transfer->to_warehouse_id)
|
||||||
->where('branch_id', $transfer->to_branch_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();
|
->first();
|
||||||
|
|
||||||
if ($toStock) {
|
if ($toStock) {
|
||||||
$toStock->decrement('quantity', $tp->quantity);
|
$toStock->decrement('quantity', $tp->quantity);
|
||||||
}
|
}
|
||||||
@@ -614,8 +654,12 @@ public function deleteAll(Request $request)
|
|||||||
$fromStock = Stock::where('product_id', $tp->product_id)
|
$fromStock = Stock::where('product_id', $tp->product_id)
|
||||||
->where('warehouse_id', $transfer->from_warehouse_id)
|
->where('warehouse_id', $transfer->from_warehouse_id)
|
||||||
->where('branch_id', $transfer->from_branch_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();
|
->first();
|
||||||
|
|
||||||
if ($fromStock) {
|
if ($fromStock) {
|
||||||
$fromStock->increment('quantity', $tp->quantity);
|
$fromStock->increment('quantity', $tp->quantity);
|
||||||
}
|
}
|
||||||
@@ -648,4 +692,49 @@ public function exportCsv()
|
|||||||
{
|
{
|
||||||
return Excel::download(new ExportTransfer, 'transfer.csv');
|
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\Http\Controllers\Controller;
|
||||||
use App\Models\Vat;
|
use App\Models\Vat;
|
||||||
|
use App\Models\VatStateItem;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
@@ -19,20 +20,39 @@ public function __construct()
|
|||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$vats = Vat::where('business_id', auth()->user()->business_id)->orderBy('status', 'desc')->whereNull('sub_vat')->latest()->paginate(20);
|
$business_id = auth()->user()->business_id;
|
||||||
$vat_groups = Vat::where('business_id', auth()->user()->business_id)->orderBy('status', 'desc')->whereNotNull('sub_vat')->latest()->paginate(20);
|
|
||||||
|
$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'));
|
return view('business::vats.index', compact('vats', 'vat_groups'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function acnooFilter(Request $request)
|
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) {
|
->when($request->search, function ($query) use ($request) {
|
||||||
$query->where(function ($q) use ($request) {
|
$query->where(function ($q) use ($request) {
|
||||||
$search = $request->search;
|
$search = $request->search;
|
||||||
$q->where('name', 'like', "%$search%");
|
$q->where('name', 'like', "%$search%");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
->where('manage_state', 0)
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(20);
|
->paginate(20);
|
||||||
|
|
||||||
@@ -47,13 +67,18 @@ public function acnooFilter(Request $request)
|
|||||||
|
|
||||||
public function VatGroupFilter(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) {
|
->when($request->search, function ($query) use ($request) {
|
||||||
$query->where(function ($q) use ($request) {
|
$query->where(function ($q) use ($request) {
|
||||||
$search = $request->search;
|
$search = $request->search;
|
||||||
$q->where('name', 'like', "%$search%");
|
$q->where('name', 'like', "%$search%");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
->with('stateVats.childVat:id,name')
|
||||||
|
->where(function ($query) {
|
||||||
|
$query->whereNotNull('sub_vat')
|
||||||
|
->orWhere('manage_state', 1);
|
||||||
|
})
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(20);
|
->paginate(20);
|
||||||
|
|
||||||
@@ -62,60 +87,115 @@ public function VatGroupFilter(Request $request)
|
|||||||
'data' => view('business::vat-groups.datas', compact('vat_groups'))->render()
|
'data' => view('business::vat-groups.datas', compact('vat_groups'))->render()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect(url()->previous());
|
return redirect(url()->previous());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Vat Group Create
|
// Vat Group Create
|
||||||
public function 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'));
|
return view('business::vat-groups.create',compact('vats'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
'vat_ids' => 'array',
|
||||||
|
'rate' => 'nullable|numeric',
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'vat_ids' => 'required_if:rate,null',
|
'manage_state' => 'nullable|integer|in:0,1',
|
||||||
'rate' => 'required_if:rate,null|numeric',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// single vat
|
$businessId = auth()->user()->business_id;
|
||||||
if ($request->rate && !$request->vat_ids) {
|
|
||||||
Vat::create($request->all() + [
|
// SINGLE VAT
|
||||||
'business_id' => auth()->user()->business_id,
|
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)
|
||||||
|
|
||||||
}
|
$vats = Vat::whereIn('id', $request->vat_ids)
|
||||||
// group vat
|
->where('business_id', $businessId)
|
||||||
elseif (!$request->rate && $request->vat_ids) {
|
->select('id', 'name', 'rate')
|
||||||
|
->get();
|
||||||
$vats = Vat::whereIn('id', $request->vat_ids)->select('id', 'name', 'rate')->get();
|
|
||||||
|
|
||||||
$tax_rate = 0;
|
$tax_rate = 0;
|
||||||
$sub_vats = [];
|
$sub_vats = [];
|
||||||
|
|
||||||
foreach ($vats as $vat) {
|
foreach ($vats as $vatItem) {
|
||||||
$sub_vats[] = [
|
$sub_vats[] = [
|
||||||
'id' => $vat->id,
|
'id' => $vatItem->id,
|
||||||
'name' => $vat->name,
|
'name' => $vatItem->name,
|
||||||
'rate' => $vat->rate,
|
'rate' => $vatItem->rate,
|
||||||
];
|
];
|
||||||
$tax_rate += $vat->rate;
|
$tax_rate += $vatItem->rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vat::create([
|
$vat = Vat::create([
|
||||||
'rate' => $tax_rate,
|
'rate' => $tax_rate,
|
||||||
'sub_vat' => $sub_vats,
|
'sub_vat' => $sub_vats,
|
||||||
'name' => $request->name,
|
'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([
|
return response()->json([
|
||||||
'message' => 'Invalid data format.',
|
'message' => 'Invalid data format.'
|
||||||
], 406);
|
], 406);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,27 +208,43 @@ public function store(Request $request)
|
|||||||
// Vat Group Edit
|
// Vat Group Edit
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$vat = Vat::where('business_id', auth()->user()->business_id)->findOrFail($id);
|
$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')->latest()->paginate(20);
|
$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'));
|
return view('business::vat-groups.edit', compact('vat', 'vats'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function update(Request $request, Vat $vat)
|
public function update(Request $request, Vat $vat)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
'vat_ids' => 'array',
|
||||||
|
'rate' => 'nullable|numeric',
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'vat_ids' => 'required_if:rate,null',
|
'manage_state' => 'nullable|integer|in:0,1',
|
||||||
'rate' => 'required_if:rate,null|numeric',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
// Single VAT update
|
$businessId = auth()->user()->business_id;
|
||||||
if ($request->rate && !$request->vat_ids) {
|
|
||||||
|
|
||||||
$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();
|
$vatGroupExist = Vat::where('sub_vat', 'LIKE', '%"id":' . $vat->id . '%')->get();
|
||||||
foreach ($vatGroupExist as $group) {
|
foreach ($vatGroupExist as $group) {
|
||||||
$subVats = collect($group->sub_vat)->map(function ($subVat) use ($vat) {
|
$subVats = collect($group->sub_vat)->map(function ($subVat) use ($vat) {
|
||||||
@@ -158,7 +254,6 @@ public function update(Request $request, Vat $vat)
|
|||||||
}
|
}
|
||||||
return $subVat;
|
return $subVat;
|
||||||
});
|
});
|
||||||
|
|
||||||
$group->update([
|
$group->update([
|
||||||
'rate' => $subVats->sum('rate'),
|
'rate' => $subVats->sum('rate'),
|
||||||
'sub_vat' => $subVats->toArray(),
|
'sub_vat' => $subVats->toArray(),
|
||||||
@@ -166,30 +261,79 @@ public function update(Request $request, Vat $vat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group VAT update
|
// GROUP VAT (OLD SYSTEM)
|
||||||
elseif (!$request->rate && $request->vat_ids) {
|
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;
|
$tax_rate = 0;
|
||||||
$sub_vats = [];
|
$sub_vats = [];
|
||||||
|
foreach ($vats as $vatItem) {
|
||||||
foreach ($vats as $single_tax) {
|
|
||||||
$sub_vats[] = [
|
$sub_vats[] = [
|
||||||
'id' => $single_tax->id,
|
'id' => $vatItem->id,
|
||||||
'name' => $single_tax->name,
|
'name' => $vatItem->name,
|
||||||
'rate' => $single_tax->rate,
|
'rate' => $vatItem->rate,
|
||||||
];
|
];
|
||||||
$tax_rate += $single_tax->rate;
|
$tax_rate += $vatItem->rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
$vat->update([
|
$vat->update([
|
||||||
|
'name' => $request->name,
|
||||||
'rate' => $tax_rate,
|
'rate' => $tax_rate,
|
||||||
'sub_vat' => $sub_vats,
|
'sub_vat' => $sub_vats,
|
||||||
'name' => $request->name,
|
|
||||||
'status' => $request->status ?? $vat->status,
|
'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();
|
DB::rollBack();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Invalid data format.',
|
'message' => 'Invalid data format.',
|
||||||
@@ -197,14 +341,17 @@ public function update(Request $request, Vat $vat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Vat updated successfully',
|
'message' => 'Vat updated successfully',
|
||||||
'redirect' => route('business.vats.index'),
|
'redirect' => route('business.vats.index'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollback();
|
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;
|
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\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\Services\PdfService;
|
||||||
use App\Traits\DateFilterTrait;
|
use App\Traits\DateFilterTrait;
|
||||||
use App\Traits\DateRangeTrait;
|
use App\Traits\DateRangeTrait;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Business\App\Exports\ExportVatReport;
|
use Modules\Business\App\Exports\ExportTaxReport;
|
||||||
|
|
||||||
class AcnooVatReportController extends Controller
|
class AcnooVatReportController extends Controller
|
||||||
{
|
{
|
||||||
@@ -25,134 +29,441 @@ public function __construct()
|
|||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$businessId = auth()->user()->business_id;
|
$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';
|
$duration = $request->custom_days ?: 'today';
|
||||||
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
|
[$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')
|
$salesQuery = Sale::where('business_id', $businessId)
|
||||||
->where('business_id', $businessId)
|
->with([
|
||||||
->where('vat_amount', '>', 0);
|
'user:id,name',
|
||||||
|
'party:id,name,email,phone,type',
|
||||||
|
'business:id,companyName',
|
||||||
|
'payment_type:id,name',
|
||||||
|
'transactions'
|
||||||
|
]);
|
||||||
|
|
||||||
// Date Filter
|
$this->applyDateFilter(
|
||||||
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
|
$salesQuery,
|
||||||
|
$duration,
|
||||||
|
'saleDate',
|
||||||
|
$request->from_date,
|
||||||
|
$request->to_date
|
||||||
|
);
|
||||||
|
|
||||||
$sales = $salesQuery->latest()->paginate(20, ['*'], 'sales');
|
if ($request->filled('search')) {
|
||||||
|
$search = $request->search;
|
||||||
$salesVatTotals = [];
|
$salesQuery->where(function ($query) use ($search) {
|
||||||
foreach ($vats as $vat) {
|
$query->where('invoiceNumber', 'like', '%' . $search . '%')
|
||||||
$salesVatTotals[$vat->id] = (clone $salesQuery)->where('vat_id', $vat->id)->sum('vat_amount');
|
->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')
|
$sales = $salesQuery->latest()->paginate($request->per_page ?? 20, ['*'], 'sales')->appends($request->query());
|
||||||
->where('business_id', $businessId)
|
|
||||||
->where('vat_amount', '>', 0);
|
|
||||||
|
|
||||||
// Date Filter
|
$salesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
|
||||||
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
|
->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 = [];
|
$saleVatRowMap = VatTransaction::where('business_id', $businessId)
|
||||||
foreach ($vats as $vat) {
|
->where('vatable_type', \App\Models\SaleDetails::class)
|
||||||
$purchasesVatTotals[$vat->id] = (clone $purchasesQuery)->where('vat_id', $vat->id)->sum('vat_amount');
|
->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()) {
|
if ($request->ajax()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'sale_data' => view('business::reports.vats.sale-datas', compact('sales', 'salesVatTotals', 'vats', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
'sale_data' => view('business::reports.vats.sale-datas', compact(
|
||||||
'purchase_data' => view('business::reports.vats.purchase-datas', compact('purchases', 'purchasesVatTotals', 'vats', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
|
'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;
|
$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();
|
$sales = collect();
|
||||||
$purchases = collect();
|
$purchases = collect();
|
||||||
|
|
||||||
if ($type === 'sales' || $type === 'all') {
|
$limit = $request->per_page ?? 20;
|
||||||
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'transactions')
|
|
||||||
->where('business_id', $businessId)
|
if ($type === 'sales') {
|
||||||
->where('vat_amount', '>', 0)
|
$sales = $salesQuery->latest()->limit($limit)->get();
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type === 'purchases' || $type === 'all') {
|
if ($type === 'purchases') {
|
||||||
$purchases = Purchase::with('details', 'party', 'details.product', 'details.product.category', 'payment_type:id,name', 'transactions')
|
$purchases = $purchasesQuery->latest()->limit($limit)->get();
|
||||||
->where('business_id', $businessId)
|
|
||||||
->where('vat_amount', '>', 0)
|
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$vats = Vat::where('business_id', $businessId)->get();
|
$vats = Vat::where('business_id', $businessId)->get();
|
||||||
|
|
||||||
$salesVatTotals = [];
|
return PdfService::render('business::reports.vats.pdf',
|
||||||
foreach ($vats as $vat) {
|
compact(
|
||||||
$salesVatTotals[$vat->id] = $sales->where('vat_id', $vat->id)->sum('vat_amount');
|
'sales',
|
||||||
}
|
'salesVatTotals',
|
||||||
|
'salesReturnVatTotals',
|
||||||
$purchasesVatTotals = [];
|
'saleVatRowMap',
|
||||||
foreach ($vats as $vat) {
|
'saleReturnVatRowMap',
|
||||||
$purchasesVatTotals[$vat->id] = $purchases->where('vat_id', $vat->id)->sum('vat_amount');
|
'purchases',
|
||||||
}
|
'purchasesVatTotals',
|
||||||
|
'purchaseReturnVatTotals',
|
||||||
$export = new ExportVatReport($sales, $purchases, $vats, $salesVatTotals, $purchasesVatTotals);
|
'purchaseVatRowMap',
|
||||||
|
'purchaseReturnVatRowMap',
|
||||||
return Excel::download($export, $filename, $format);
|
'vats',
|
||||||
}
|
'type',
|
||||||
|
'filter_from_date',
|
||||||
public function exportPdf($type = 'all')
|
'filter_to_date',
|
||||||
{
|
'duration'
|
||||||
$businessId = auth()->user()->business_id;
|
), 'tax-report.pdf', 'A4', 'L'
|
||||||
|
);
|
||||||
$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');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,65 +40,212 @@ public function store(Request $request)
|
|||||||
'warehouse_id' => 'nullable|exists:warehouses,id',
|
'warehouse_id' => 'nullable|exists:warehouses,id',
|
||||||
'type' => 'nullable|string|in:sale,purchase',
|
'type' => 'nullable|string|in:sale,purchase',
|
||||||
'id' => 'required|integer',
|
'id' => 'required|integer',
|
||||||
'name' => 'required|string',
|
'name' => 'nullable|string',
|
||||||
'quantity' => 'required|numeric',
|
'quantity' => 'required|numeric',
|
||||||
'price' => 'required|numeric',
|
'price' => 'required|numeric',
|
||||||
'product_code' => 'nullable|string',
|
'product_code' => 'nullable|string',
|
||||||
'product_unit_id' => 'nullable|integer',
|
'product_unit_id' => 'nullable|integer',
|
||||||
'product_unit_name' => 'nullable|string',
|
'product_unit_name' => 'nullable|string',
|
||||||
'product_image' => 'nullable|string',
|
'product_image' => 'nullable|string',
|
||||||
|
'profit_percent' => 'nullable|numeric',
|
||||||
'sales_price' => 'nullable|numeric',
|
'sales_price' => 'nullable|numeric',
|
||||||
'whole_sale_price' => 'nullable|numeric',
|
'whole_sale_price' => 'nullable|numeric',
|
||||||
'dealer_price' => 'nullable|numeric',
|
'dealer_price' => 'nullable|numeric',
|
||||||
'expire_date' => 'nullable|date',
|
'expire_date' => 'nullable|date',
|
||||||
'product_type' => 'nullable|in:single,variant,combo',
|
'product_type' => 'nullable|in:single,variant,combo',
|
||||||
'variant_name' => 'nullable|string',
|
'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
|
$incomingSerials = $request->serial_numbers ?? [];
|
||||||
$existingCartItem = Cart::search(
|
|
||||||
fn($item) => $item->id == $request->id &&
|
// Serial Mode
|
||||||
$item->options->type == $request->type &&
|
if (!empty($incomingSerials)) {
|
||||||
match ($request->type) {
|
// Sale
|
||||||
'purchase' => $item->options->batch_no == $request->batch_no,
|
if ($request->type === 'sale') {
|
||||||
'sale' => $item->options->stock_id == $request->stock_id,
|
|
||||||
default => false,
|
$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) {
|
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 {
|
} 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,
|
'id' => $request->id,
|
||||||
'name' => $request->name,
|
'name' => $request->name,
|
||||||
'qty' => $request->quantity,
|
'qty' => $request->quantity,
|
||||||
'price' => $request->price,
|
'price' => round($request->price, 2),
|
||||||
'options' => [
|
'options' => [
|
||||||
'type' => $request->type,
|
'type' => $request->type,
|
||||||
'product_code' => $request->product_code,
|
'product_code' => $request->product_code,
|
||||||
'product_unit_id' => $request->product_unit_id,
|
'product_unit_id' => $request->product_unit_id,
|
||||||
'product_unit_name' => $request->product_unit_name,
|
'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,
|
'stock_id' => $request->stock_id,
|
||||||
'batch_no' => $request->batch_no,
|
'batch_no' => $request->batch_no,
|
||||||
'product_image' => $request->product_image,
|
|
||||||
'expire_date' => $request->expire_date,
|
'expire_date' => $request->expire_date,
|
||||||
'purchase_price' => $request->purchase_price,
|
'purchase_price' => $request->purchase_price,
|
||||||
|
'profit_percent' => $request->profit_percent,
|
||||||
'sales_price' => $request->sales_price,
|
'sales_price' => $request->sales_price,
|
||||||
'whole_sale_price' => $request->whole_sale_price,
|
'whole_sale_price' => $request->whole_sale_price,
|
||||||
'dealer_price' => $request->dealer_price,
|
'dealer_price' => $request->dealer_price,
|
||||||
'product_type' => $request->product_type,
|
|
||||||
'warehouse_id' => $request->warehouse_id,
|
'warehouse_id' => $request->warehouse_id,
|
||||||
'variant_name' => $request->variant_name,
|
'has_serial' => $request->has_serial ?? 0,
|
||||||
'vat_percent' => $request->vat_percent,
|
'price_without_tax' => $request->price_without_tax,
|
||||||
]
|
]
|
||||||
];
|
]);
|
||||||
Cart::add($mainItemData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Item added to cart successfully.'
|
'message' => 'Item added to cart successfully.'
|
||||||
@@ -108,20 +255,45 @@ public function store(Request $request)
|
|||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
$cart = Cart::get($id);
|
$cart = Cart::get($id);
|
||||||
|
|
||||||
if (!$cart) {
|
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;
|
$qty = $request->qty ?? $cart->qty;
|
||||||
|
|
||||||
if ($qty < 0) {
|
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, [
|
Cart::update($id, [
|
||||||
'qty' => $qty,
|
'qty' => $qty,
|
||||||
'price' => $request->price ?? $cart->price,
|
'price' => round($request->price ?? $cart->price, 2),
|
||||||
'options' => [
|
'options' => [
|
||||||
'type' => $cart->options->type,
|
'type' => $cart->options->type,
|
||||||
'expire_date' => $request->expire_date ?? $cart->options->expire_date,
|
'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_id' => $cart->options->product_unit_id,
|
||||||
'product_unit_name' => $cart->options->product_unit_name,
|
'product_unit_name' => $cart->options->product_unit_name,
|
||||||
'product_image' => $cart->options->product_image,
|
'product_image' => $cart->options->product_image,
|
||||||
|
'profit_percent' => $cart->options->profit_percent,
|
||||||
'sales_price' => $cart->options->sales_price,
|
'sales_price' => $cart->options->sales_price,
|
||||||
'discount' => $request->discount ?? $cart->options->discount,
|
'discount' => $request->discount ?? $cart->options->discount,
|
||||||
'whole_sale_price' => $cart->options->whole_sale_price,
|
'whole_sale_price' => $cart->options->whole_sale_price,
|
||||||
@@ -139,7 +312,9 @@ public function update(Request $request, $id)
|
|||||||
'product_type' => $cart->options->product_type,
|
'product_type' => $cart->options->product_type,
|
||||||
'warehouse_id' => $cart->options->warehouse_id,
|
'warehouse_id' => $cart->options->warehouse_id,
|
||||||
'variant_name' => $cart->options->variant_name,
|
'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)
|
$data['loss'] = Sale::where('business_id', auth()->user()->business_id)
|
||||||
->whereYear('created_at', request('year') ?? date('Y'))
|
->whereYear('created_at', request('year') ?? date('Y'))
|
||||||
->where('lossProfit', '<', 0)
|
->where('lossProfit', '<', 0)
|
||||||
->selectRaw("TO_CHAR(created_at, 'Month') as month, SUM(ABS(\"lossProfit\")) as total")
|
->selectRaw("TO_CHAR(created_at, 'FMMonth') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||||
->orderBy('created_at')
|
->groupBy(DB::raw("TO_CHAR(created_at, 'FMMonth')"))
|
||||||
->groupBy('created_at')
|
->orderBy(DB::raw("MIN(created_at)"))
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$data['profit'] = Sale::where('business_id', auth()->user()->business_id)
|
$data['profit'] = Sale::where('business_id', auth()->user()->business_id)
|
||||||
->whereYear('created_at', request('year') ?? date('Y'))
|
->whereYear('created_at', request('year') ?? date('Y'))
|
||||||
->where('lossProfit', '>=', 0)
|
->where('lossProfit', '>=', 0)
|
||||||
->selectRaw("TO_CHAR(created_at, 'Month') as month, SUM(ABS(\"lossProfit\")) as total")
|
->selectRaw("TO_CHAR(created_at, 'FMMonth') as month, SUM(ABS(\"lossProfit\")) as total")
|
||||||
->orderBy('created_at')
|
->groupBy(DB::raw("TO_CHAR(created_at, 'FMMonth')"))
|
||||||
->groupBy('created_at')
|
->orderBy(DB::raw("MIN(created_at)"))
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return response()->json($data);
|
return response()->json($data);
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
namespace Modules\Business\App\Http\Controllers;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Events\MultiPaymentProcessed;
|
use App\Events\MultiPaymentProcessed;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Branch;
|
||||||
use App\Models\Party;
|
use App\Models\Party;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\Stock;
|
|
||||||
use App\Models\Branch;
|
|
||||||
use App\Models\Purchase;
|
use App\Models\Purchase;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Models\PurchaseReturn;
|
use App\Models\PurchaseReturn;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\PurchaseReturnDetail;
|
use App\Models\PurchaseReturnDetail;
|
||||||
|
use App\Services\PurchaseVatTransaction;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class PurchaseReturnController extends Controller
|
class PurchaseReturnController extends Controller
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,6 @@ public function index(Request $request)
|
|||||||
return view('business::purchase-returns.index', compact('purchases', 'branches'));
|
return view('business::purchase-returns.index', compact('purchases', 'branches'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$business_id = auth()->user()->business_id;
|
$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;
|
$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();
|
$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'));
|
return view('business::purchase-returns.create', compact('purchase', 'discount_per_unit_factor','payment_types'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
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([
|
$request->validate([
|
||||||
'purchase_id' => 'required|exists:purchases,id',
|
'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();
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$purchase = Purchase::with('details')
|
$business_id = auth()->user()->business_id;
|
||||||
->where('business_id', auth()->user()->business_id)
|
|
||||||
|
$purchase = Purchase::with('details.stock')
|
||||||
|
->where('business_id', $business_id)
|
||||||
->findOrFail($request->purchase_id);
|
->findOrFail($request->purchase_id);
|
||||||
|
|
||||||
// Calculate total discount factor
|
|
||||||
$total_discount = $purchase->discountAmount;
|
$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;
|
$discount_per_unit_factor = $total_purchase_amount > 0 ? $total_discount / $total_purchase_amount : 0;
|
||||||
|
|
||||||
$purchase_return = PurchaseReturn::create([
|
$purchase_return = PurchaseReturn::create([
|
||||||
'business_id' => auth()->user()->business_id,
|
'business_id' => $business_id,
|
||||||
'purchase_id' => $request->purchase_id,
|
'purchase_id' => $purchase->id,
|
||||||
'invoice_no' => $purchase->invoiceNumber,
|
'invoice_no' => $purchase->invoiceNumber,
|
||||||
'return_date' => now(),
|
'return_date' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$purchase_return_detail_data = [];
|
|
||||||
$total_return_amount = 0;
|
$total_return_amount = 0;
|
||||||
$total_return_discount = 0;
|
$total_return_discount = 0;
|
||||||
|
|
||||||
// Loop through each purchase detail and process the return
|
foreach ($request->products as $item) {
|
||||||
foreach ($purchase->details as $key => $detail) {
|
|
||||||
$requested_qty = $request->return_qty[$key];
|
|
||||||
|
|
||||||
if ($requested_qty <= 0) {
|
$detail = $purchase->details->where('id', $item['detail_id'])->first();
|
||||||
continue;
|
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) {
|
if ($requested_qty > $detail->quantities) {
|
||||||
return response()->json([
|
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);
|
], 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;
|
$unit_discount = $detail->productPurchasePrice * $discount_per_unit_factor;
|
||||||
$return_discount = $unit_discount * $requested_qty;
|
$return_discount = $unit_discount * $requested_qty;
|
||||||
$return_amount = ($detail->productPurchasePrice - $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_amount += $return_amount;
|
||||||
$total_return_discount += $return_discount;
|
$total_return_discount += $return_discount;
|
||||||
|
|
||||||
// Update stock & purchase details
|
//Update stock & purchase detail
|
||||||
Stock::where('id', $detail->stock_id)->decrement('productStock', $requested_qty);
|
$detail->stock->decrement('productStock', $requested_qty);
|
||||||
|
|
||||||
$detail->quantities -= $requested_qty;
|
$detail->quantities -= $requested_qty;
|
||||||
$detail->timestamps = false;
|
$detail->timestamps = false;
|
||||||
$detail->save();
|
$detail->save();
|
||||||
|
|
||||||
// Collect return detail data
|
// Remove serials from purchase detail
|
||||||
$purchase_return_detail_data[] = [
|
if (!empty($serials) && !empty($detail->serial_numbers)) {
|
||||||
'purchase_detail_id' => $detail->id,
|
$remainingDetailSerials = array_values(array_diff($detail->serial_numbers ?? [], $serials));
|
||||||
'purchase_return_id' => $purchase_return->id,
|
$detail->update(['serial_numbers' => $remainingDetailSerials]);
|
||||||
'return_qty' => $requested_qty,
|
|
||||||
'business_id' => auth()->user()->business_id,
|
|
||||||
'return_amount' => $return_amount,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert purchase return details
|
$returnDetail = PurchaseReturnDetail::create([
|
||||||
if (!empty($purchase_return_detail_data)) {
|
'business_id' => $business_id,
|
||||||
PurchaseReturnDetail::insert($purchase_return_detail_data);
|
'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) {
|
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);
|
$party = Party::find($purchase->party_id);
|
||||||
|
|
||||||
if ($party) {
|
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 > 0) {
|
||||||
if ($party->due >= $refund_amount) {
|
$deduct = min($party->due, $refund);
|
||||||
$party->decrement('due', $refund_amount);
|
$party->decrement('due', $deduct);
|
||||||
$refund_amount = 0;
|
$refund -= $deduct;
|
||||||
} else {
|
|
||||||
$refund_amount -= $party->due;
|
|
||||||
$party->update(['due' => 0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any remaining amount should be deducted from wallet
|
if ($refund > 0 && $party->wallet > 0) {
|
||||||
if ($refund_amount > 0 && $party->wallet > 0) {
|
$deduct = min($party->wallet, $refund);
|
||||||
$deduct = min($party->wallet, $refund_amount);
|
|
||||||
$party->decrement('wallet', $deduct);
|
$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([
|
$purchase->update([
|
||||||
'change_amount' => 0,
|
'change_amount' => 0,
|
||||||
'dueAmount' => max(0, $purchase->dueAmount - $total_return_amount),
|
'dueAmount' => max(0, $purchase->dueAmount - $total_return_amount),
|
||||||
'paidAmount' => max(0, $purchase->paidAmount - min($purchase->paidAmount, $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),
|
'discountAmount' => max(0, $purchase->discountAmount - $total_return_discount),
|
||||||
'isPaid' => $remaining_return_amount > 0 ? 1 : $purchase->isPaid,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$payments = $request->payments;
|
// Payment processing
|
||||||
|
$payments = $request->payments ?? [];
|
||||||
if (isset($payments['main'])) {
|
$payments = collect($payments)->map(fn($p) => array_merge($p, ['amount' => $total_return_amount]))->toArray();
|
||||||
$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();
|
|
||||||
|
|
||||||
event(new MultiPaymentProcessed(
|
event(new MultiPaymentProcessed(
|
||||||
$payments,
|
$payments,
|
||||||
$purchase_return->id,
|
$purchase_return->id,
|
||||||
'purchase_return',
|
'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();
|
DB::commit();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Purchase returned successfully.'),
|
'message' => __('Purchase returned successfully.'),
|
||||||
'redirect' => route('business.purchase-returns.index'),
|
'redirect' => route('business.purchase-returns.index'),
|
||||||
'secondary_redirect_url' => route('business.purchases.invoice', $purchase->id),
|
'secondary_redirect_url' => $invoice_route,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollback();
|
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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Events\MultiPaymentProcessed;
|
use App\Events\MultiPaymentProcessed;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Branch;
|
||||||
|
use App\Models\Party;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
use App\Models\Party;
|
|
||||||
use App\Models\Stock;
|
|
||||||
use App\Models\Branch;
|
|
||||||
use App\Models\SaleReturn;
|
use App\Models\SaleReturn;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Models\SaleReturnDetails;
|
use App\Models\SaleReturnDetails;
|
||||||
|
use App\Models\Stock;
|
||||||
|
use App\Services\VatTransactionService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
|
|
||||||
class SaleReturnController extends 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'));
|
return view('business::sale-returns.create', compact('sale', 'discount_per_unit_factor', 'avg_rounding_amount', 'payment_types'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function store(Request $request)
|
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([
|
$request->validate([
|
||||||
'sale_id' => 'required|exists:sales,id',
|
'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;
|
$business_id = auth()->user()->business_id;
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
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)
|
->where('business_id', $business_id)
|
||||||
->findOrFail($request->sale_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_discount = $sale->discountAmount;
|
||||||
$total_sale_amount = $sale->details->sum(fn($detail) => $detail->price * $detail->quantities);
|
$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;
|
$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;
|
$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([
|
$sale_return = SaleReturn::create([
|
||||||
|
'return_date' => now(),
|
||||||
'business_id' => $business_id,
|
'business_id' => $business_id,
|
||||||
'sale_id' => $request->sale_id,
|
'sale_id' => $request->sale_id,
|
||||||
'invoice_no' => $sale->invoiceNumber,
|
'invoice_no' => $sale->invoiceNumber,
|
||||||
'return_date' => now(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$sale_return_detail_data = [];
|
|
||||||
$total_return_amount = 0;
|
$total_return_amount = 0;
|
||||||
$total_return_discount = 0;
|
$total_return_discount = 0;
|
||||||
$total_loss_profit_adjustment = 0;
|
$total_loss_profit_adjustment = 0;
|
||||||
|
|
||||||
foreach ($sale->details as $key => $detail) {
|
foreach ($request->products as $indextem) {
|
||||||
$requested_qty = $request->return_qty[$key];
|
|
||||||
|
|
||||||
if ($requested_qty <= 0) {
|
$detail = $sale->details->where('id', $indextem['detail_id'])->first();
|
||||||
continue;
|
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) {
|
if ($requested_qty > $detail->quantities) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
@@ -131,12 +153,12 @@ public function store(Request $request)
|
|||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$product = $detail->product;
|
$return_serials = !empty($indextem['serial_numbers']) ? json_decode($indextem['serial_numbers'], true) : [];
|
||||||
|
|
||||||
// Include SaleDetails discount in return calculation
|
// Include SaleDetails discount in return calculation
|
||||||
$unit_discount = $detail->price * $discount_per_unit_factor;
|
$unit_discount = $detail->price * $discount_per_unit_factor;
|
||||||
$item_cart_discount = $detail->discount ?? 0;
|
$indextem_cart_discount = $detail->discount ?? 0;
|
||||||
$total_discount_per_unit = $unit_discount + $item_cart_discount;
|
$total_discount_per_unit = $unit_discount + $indextem_cart_discount;
|
||||||
|
|
||||||
$return_discount = $total_discount_per_unit * $requested_qty;
|
$return_discount = $total_discount_per_unit * $requested_qty;
|
||||||
$return_amount = ($detail->price - $total_discount_per_unit + $rounding_amount_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_amount += $return_amount;
|
||||||
$total_return_discount += $return_discount;
|
$total_return_discount += $return_discount;
|
||||||
|
|
||||||
if ($product && $product->product_type === 'combo') {
|
$product = $detail->product;
|
||||||
|
|
||||||
$combo_total_purchase = 0;
|
// Combo products
|
||||||
$combo_total_sale = $detail->price * $requested_qty;
|
if ($product && $product->product_type === 'combo') {
|
||||||
|
|
||||||
foreach ($product->combo_products as $comboItem) {
|
foreach ($product->combo_products as $comboItem) {
|
||||||
$stock = Stock::find($comboItem->stock_id);
|
$stock = Stock::find($comboItem->stock_id);
|
||||||
|
|
||||||
if (!$stock) {
|
if (!$stock) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __("Stock not found for combo item '{$comboItem->product->productName}'"),
|
'message' => __("Stock not found for combo item '{$comboItem->product->productName}'"),
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase stock by combo component quantity * returned qty
|
|
||||||
$restore_qty = $comboItem->quantity * $requested_qty;
|
$restore_qty = $comboItem->quantity * $requested_qty;
|
||||||
$stock->increment('productStock', $restore_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 {
|
else {
|
||||||
$stock = Stock::where('id', $detail->stock_id)->first();
|
$stock = Stock::where('id', $detail->stock_id)->first();
|
||||||
if (!$stock) {
|
if (!$stock) return response()->json(['error' => 'Stock not found.'], 404);
|
||||||
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);
|
$stock->increment('productStock', $requested_qty);
|
||||||
|
|
||||||
$loss_profit_adjustment = (($detail->price - $stock->productPurchasePrice) * $requested_qty) - $return_discount;
|
// Restore serials to stock
|
||||||
$total_loss_profit_adjustment += $loss_profit_adjustment;
|
$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->quantities -= $requested_qty;
|
||||||
$detail->lossProfit -= $loss_profit_adjustment;
|
$detail->lossProfit -= $loss_profit_adjustment;
|
||||||
$detail->timestamps = false;
|
$detail->timestamps = false;
|
||||||
$detail->save();
|
$detail->save();
|
||||||
|
|
||||||
$sale_return_detail_data[] = [
|
$returnDetail = SaleReturnDetails::create([
|
||||||
'business_id' => $business_id,
|
'business_id' => $business_id,
|
||||||
'sale_detail_id' => $detail->id,
|
'sale_detail_id' => $detail->id,
|
||||||
'sale_return_id' => $sale_return->id,
|
'sale_return_id' => $sale_return->id,
|
||||||
'return_qty' => $requested_qty,
|
'return_qty' => $requested_qty,
|
||||||
'return_amount' => $return_amount,
|
'return_amount' => $return_amount,
|
||||||
];
|
'serial_numbers' => $return_serials ?? null,
|
||||||
}
|
]);
|
||||||
|
|
||||||
if (!empty($sale_return_detail_data)) {
|
$previous_returned_qty = SaleReturnDetails::where('sale_detail_id', $detail->id)->sum('return_qty');
|
||||||
SaleReturnDetails::insert($sale_return_detail_data);
|
$totalQty = $detail->quantities + $previous_returned_qty;
|
||||||
|
|
||||||
|
VatTransactionService::productReturnVatCalculation($detail, $requested_qty, $returnDetail, $totalQty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($total_return_amount <= 0) {
|
if ($total_return_amount <= 0) {
|
||||||
return response()->json("You cannot return an empty product.", 400);
|
return response()->json("You cannot return an empty product.", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remaining refund / party logic
|
||||||
$remaining_refund = $total_return_amount;
|
$remaining_refund = $total_return_amount;
|
||||||
|
|
||||||
// Adjust Due
|
|
||||||
$new_due = $sale->dueAmount;
|
$new_due = $sale->dueAmount;
|
||||||
if ($remaining_refund > 0) {
|
if ($remaining_refund > 0) {
|
||||||
if ($remaining_refund >= $sale->dueAmount) {
|
if ($remaining_refund >= $sale->dueAmount) {
|
||||||
@@ -219,7 +262,6 @@ public function store(Request $request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust Paid (refund part)
|
|
||||||
$new_paid = $sale->paidAmount;
|
$new_paid = $sale->paidAmount;
|
||||||
if ($remaining_refund > 0) {
|
if ($remaining_refund > 0) {
|
||||||
if ($remaining_refund >= $sale->paidAmount) {
|
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);
|
$new_total_amount = max(0, $sale->totalAmount - $total_return_amount);
|
||||||
|
|
||||||
$sale->update([
|
$sale->update([
|
||||||
'change_amount' => 0,
|
'change_amount' => 0,
|
||||||
'dueAmount' => $new_due,
|
'dueAmount' => $new_due,
|
||||||
@@ -244,39 +284,38 @@ public function store(Request $request)
|
|||||||
'lossProfit' => $sale->lossProfit - $total_loss_profit_adjustment,
|
'lossProfit' => $sale->lossProfit - $total_loss_profit_adjustment,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Party Refund Logic
|
// Party refund logic
|
||||||
$party = Party::find($sale->party_id);
|
$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
|
$party = Party::where('business_id', $business_id)->find($sale->party_id);
|
||||||
$refund_amount = $remaining_refund;
|
|
||||||
|
if ($party && $remaining_refund > 0) {
|
||||||
|
|
||||||
// Reduce party due
|
|
||||||
if ($party->due > 0) {
|
if ($party->due > 0) {
|
||||||
if ($party->due >= $refund_amount) {
|
|
||||||
$party->decrement('due', $refund_amount);
|
if ($party->due >= $remaining_refund) {
|
||||||
$refund_amount = 0;
|
$party->decrement('due', $remaining_refund);
|
||||||
|
$remaining_refund = 0;
|
||||||
} else {
|
} else {
|
||||||
$refund_amount -= $party->due;
|
$remaining_refund -= $party->due;
|
||||||
$party->update(['due' => 0]);
|
$party->update(['due' => 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add leftover refund to wallet
|
if ($remaining_refund > 0) {
|
||||||
if ($refund_amount > 0) {
|
$party->increment('wallet', $remaining_refund);
|
||||||
$party->increment('wallet', $refund_amount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$payments = $request->payments;
|
// Payment event
|
||||||
|
$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) {
|
$payments = collect($payments)->map(function ($payment) use ($total_return_amount) {
|
||||||
$payment['amount'] = $total_return_amount;
|
$payment['amount'] = $total_return_amount;
|
||||||
return $payment;
|
return $payment;
|
||||||
@@ -286,20 +325,22 @@ public function store(Request $request)
|
|||||||
$payments,
|
$payments,
|
||||||
$sale_return->id,
|
$sale_return->id,
|
||||||
'sale_return',
|
'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();
|
DB::commit();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('Sale returned successfully.'),
|
'message' => __('Sale returned successfully.'),
|
||||||
'redirect' => route('business.sale-returns.index'),
|
'redirect' => route('business.sale-returns.index'),
|
||||||
'secondary_redirect_url' => route('business.sales.invoice', $sale->id),
|
'secondary_redirect_url' => $invoice_route,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollback();
|
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;
|
namespace Modules\Business\App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Option;
|
|
||||||
use App\Models\Business;
|
|
||||||
use App\Helpers\HasUploader;
|
use App\Helpers\HasUploader;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Models\BusinessCategory;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use App\Http\Controllers\Controller;
|
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\Cache;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class SettingController extends Controller
|
class SettingController extends Controller
|
||||||
{
|
{
|
||||||
@@ -18,14 +20,16 @@ class SettingController extends Controller
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$setting = Option::where('key', 'business-settings')
|
$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()
|
->get()
|
||||||
->firstWhere('value.business_id', auth()->user()->business_id);
|
->firstWhere('value.business_id', auth()->user()->business_id);
|
||||||
|
|
||||||
$business_categories = BusinessCategory::whereStatus(1)->latest()->get();
|
$business_categories = BusinessCategory::whereStatus(1)->latest()->get();
|
||||||
$business = Business::findOrFail(auth()->user()->business_id);
|
$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)
|
public function update(Request $request, $id)
|
||||||
@@ -56,6 +60,8 @@ public function update(Request $request, $id)
|
|||||||
'show_invoice_scanner_logo' => 'nullable|boolean',
|
'show_invoice_scanner_logo' => 'nullable|boolean',
|
||||||
'show_a4_invoice_logo' => 'nullable|boolean',
|
'show_a4_invoice_logo' => 'nullable|boolean',
|
||||||
'show_thermal_invoice_logo' => 'nullable|boolean',
|
'show_thermal_invoice_logo' => 'nullable|boolean',
|
||||||
|
// 'country_id' => 'nullable|exists:countries,id',
|
||||||
|
// 'state_id' => 'nullable|exists:states,id',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
@@ -71,14 +77,12 @@ public function update(Request $request, $id)
|
|||||||
'email' => $request->email,
|
'email' => $request->email,
|
||||||
'vat_name' => $request->vat_name,
|
'vat_name' => $request->vat_name,
|
||||||
'vat_no' => $request->vat_no,
|
'vat_no' => $request->vat_no,
|
||||||
|
// 'country_id' => $request->country_id,
|
||||||
|
// 'state_id' => $request->state_id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$moduleKeys = [
|
$moduleKeys = [
|
||||||
'show_company_name',
|
'show_company_name', 'show_phone_number', 'show_address', 'show_email', 'show_vat',
|
||||||
'show_phone_number',
|
|
||||||
'show_address',
|
|
||||||
'show_email',
|
|
||||||
'show_vat',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$modules = [];
|
$modules = [];
|
||||||
@@ -96,7 +100,7 @@ public function update(Request $request, $id)
|
|||||||
|
|
||||||
if ($setting) {
|
if ($setting) {
|
||||||
$setting->update($request->except($data) + [
|
$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,
|
'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),
|
'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),
|
'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_invoice_scanner_logo' => 1,
|
||||||
'show_a4_invoice_logo' => 1,
|
'show_a4_invoice_logo' => 1,
|
||||||
'show_thermal_invoice_logo' => 1,
|
'show_thermal_invoice_logo' => 1,
|
||||||
'show_warranty' => 1,
|
'show_warranty' => 1 ,
|
||||||
]),
|
]),
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_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