update marketing
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 5m14s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-05-14 11:55:22 +07:00
parent f80fcc4c1b
commit 05fd3230b8
448 changed files with 17545 additions and 5128 deletions

View File

@@ -10,6 +10,7 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportTransfer;
@@ -25,11 +26,20 @@ public function __construct()
public function index(Request $request)
{
$branches = Branch::withTrashed()->where('business_id', auth()->user()->business_id)->latest()->get();
$user = auth()->user();
$activeBranchId = $user->active_branch_id;
$branches = Branch::withTrashed()->where('business_id', $user->business_id)->latest()->get();
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
->where('business_id', auth()->user()->business_id)
->when($request->branch_id, function ($q) use ($request) {
->where('business_id', $user->business_id)
->when($activeBranchId, function ($q) use ($activeBranchId) {
$q->where(function ($query) use ($activeBranchId) {
$query->where('from_branch_id', $activeBranchId)
->orWhere('to_branch_id', $activeBranchId);
});
})
->when($request->branch_id && !$activeBranchId, function ($q) use ($request) {
$q->where(function ($query) use ($request) {
$query->where('from_branch_id', $request->branch_id)->orWhere('to_branch_id', $request->branch_id);
});
@@ -77,6 +87,19 @@ public function create()
public function store(Request $request)
{
// Normalize serial_numbers
if ($request->has('products')) {
$products = $request->products;
foreach ($products as $key => $item) {
if (!empty($item['serial_numbers']) && is_string($item['serial_numbers'])) {
$products[$key]['serial_numbers'] = json_decode($item['serial_numbers'], true);
}
}
$request->merge(['products' => $products]);
}
$request->validate([
'from_branch_id' => 'nullable|exists:branches,id',
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_id',
@@ -91,6 +114,7 @@ public function store(Request $request)
'products.*.unit_price' => 'required|numeric|min:0',
'products.*.discount' => 'nullable|numeric|min:0',
'products.*.tax' => 'nullable|numeric|min:0',
'products.*.serial_numbers' => 'nullable|array',
]);
$user = auth()->user();
@@ -99,72 +123,54 @@ public function store(Request $request)
$fromWh = $request->from_warehouse_id;
$toWh = $request->to_warehouse_id;
// Transfer validation logic
// Transfer validation
if ($user->active_branch_id && $toBranch && $toWh) {
return response()->json([
'message' => 'You cannot transfer to another branch warehouse.'
], 400);
return response()->json(['message' => 'You cannot transfer to another branch warehouse.'], 400);
}
if (!$toBranch && !$toWh) {
// to_branch or to_warehouse no one exist
return response()->json([
'message' => 'Invalid transfer request. Please select a destination branch or warehouse.'
], 400);
return response()->json(['message' => 'Please select a destination branch or warehouse.'], 400);
}
if ($fromBranch && !$fromWh) {
// Branch to Branch transfer only
if ($fromBranch == $toBranch) {
return response()->json([
'message' => 'Transfer not allowed: Same branch transfer is not possible.'
], 400);
}
} elseif (!$fromBranch && $fromWh) {
// Warehouse to Warehouse transfer only
if ($fromWh == $toWh) {
return response()->json([
'message' => 'Transfer not allowed: Same warehouse transfer is not possible.'
], 400);
}
} elseif ($fromBranch && $fromWh) {
// Both branch and warehouse present
if ($fromBranch == $toBranch && $fromWh == $toWh) {
return response()->json([
'message' => 'Transfer not allowed: Same warehouse transfer within the same branch.'
], 400);
}
} else {
return response()->json([
'message' => 'Invalid transfer request. Please provide branch or warehouse information.'
], 400);
if ($fromBranch && !$fromWh && $fromBranch == $toBranch) {
return response()->json(['message' => 'Same branch transfer is not allowed.'], 400);
}
if ($fromWh && $fromWh == $toWh) {
return response()->json(['message' => 'Same warehouse transfer is not allowed.'], 400);
}
DB::beginTransaction();
try {
$subTotal = 0;
$totalDiscount = 0;
$totalTax = 0;
$subTotal = $totalDiscount = $totalTax = 0;
foreach ($request->products as $item) {
$qty = $item['quantity'];
$price = $item['unit_price'];
$discount = $item['discount'] ?? 0;
$tax = $item['tax'] ?? 0;
// products re-arrange
$products = collect($request->products)->map(function ($item, $key) {
return array_merge($item, ['stock_id' => $item['stock_id'] ?? $key]);
});
$subTotal += ($qty * $price);
$totalTax += $tax;
$totalDiscount += $discount;
// Calculate subtotal using serial count if available
foreach ($products as $item) {
$serials = !empty($item['serial_numbers'])
? (is_array($item['serial_numbers']) ? $item['serial_numbers'] : json_decode($item['serial_numbers'], true))
: [];
$qty = !empty($serials) ? count($serials) : $item['quantity'];
$subTotal += $qty * $item['unit_price'];
$totalTax += $item['tax'] ?? 0;
$totalDiscount += $item['discount'] ?? 0;
}
$shipping = $request->shipping_charge ?? 0;
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
$transfer = Transfer::create($request->except('business_id', 'shipping_charge', 'sub_total', 'total_discount', 'total_tax', 'grand_total', 'from_warehouse_id', 'to_warehouse_id', 'to_branch_id', 'from_branch_id') + [
'business_id' => auth()->user()->business_id,
$transfer = Transfer::create([
'business_id' => $user->business_id,
'user_id' => auth()->id(),
'from_branch_id' => $fromBranch,
'from_warehouse_id' => $fromWh,
'to_branch_id' => $toBranch,
'to_warehouse_id' => $toWh,
'transfer_date' => $request->transfer_date,
'status' => $request->status,
'note' => $request->note,
'shipping_charge' => $shipping,
'sub_total' => $subTotal,
'total_discount' => $totalDiscount,
@@ -172,115 +178,120 @@ public function store(Request $request)
'grand_total' => $grandTotal,
]);
$transferProductData = [];
foreach ($request->products as $stockId => $item) {
// Find product_id from stock_id
$stock = Stock::find($stockId);
$transferProducts = [];
foreach ($products as $item) {
$stock = Stock::find($item['stock_id']);
if (!$stock) {
return response()->json([
'message' => "Invalid stock ID: {$stockId}"
], 400);
return response()->json(['message' => "Invalid stock ID: {$item['stock_id']}"], 400);
}
$transferProductData[] = [
// Ensure serial_numbers is array
$serials = !empty($item['serial_numbers'])
? (is_array($item['serial_numbers']) ? $item['serial_numbers'] : json_decode($item['serial_numbers'], true))
: [];
$quantity = !empty($serials) ? count($serials) : $item['quantity'];
$transferProducts[] = [
'transfer_id' => $transfer->id,
'stock_id' => $stockId,
'stock_id' => $stock->id,
'product_id' => $stock->product_id,
'quantity' => $item['quantity'] ?? 0,
'unit_price' => $item['unit_price'] ?? 0,
'quantity' => $quantity,
'unit_price' => $item['unit_price'],
'discount' => $item['discount'] ?? 0,
'tax' => $item['tax'] ?? 0,
'serial_numbers' => !empty($serials) ? json_encode($serials) : null,
'created_at' => now(),
'updated_at' => now(),
];
if ($request->status === 'completed') {
foreach ($request->products as $stockId => $item) {
// Get the actual FROM stock
$fromStock = Stock::where('id', $stockId)
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
->first();
// FROM stock
$fromStock = Stock::where('id', $stock->id)
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
->first();
if (!$fromStock) {
return response()->json([
'message' => "Stock not found in source (branch/warehouse) for stock ID: {$stockId}"
], 400);
}
if (!$fromStock || $fromStock->productStock < $quantity) {
return response()->json(['message' => 'Insufficient stock for product ID: ' . $stock->product_id], 400);
}
if ($fromStock->productStock < $item['quantity']) {
return response()->json([
'message' => "Insufficient stock in source for product ID: {$fromStock->product_id}, available: {$fromStock->productStock}"
], 400);
}
// Remove serials from source
if (!empty($serials)) {
$existingSerials = is_array($fromStock->serial_numbers) ? $fromStock->serial_numbers : json_decode($fromStock->serial_numbers ?? '[]', true);
$fromStock->serial_numbers = array_values(array_diff($existingSerials, $serials));
}
// Decrease FROM stock
$fromStock->decrement('productStock', $item['quantity']);
$fromStock->decrement('productStock', $quantity);
$fromStock->save();
// Get the TO stock
$toStock = Stock::where('product_id', $fromStock->product_id)
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
->when(!is_null($fromStock->batch_no), fn($q) => $q->where('batch_no', $fromStock->batch_no))
->first();
// TO stock
$toStock = Stock::where('product_id', $fromStock->product_id)
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
->where(function ($q) use ($fromStock) {
// if destination stock batch is NULL, skip batch compare
$q->whereNull('batch_no')
// otherwise match same batch
->orWhere('batch_no', $fromStock->batch_no);
})
->first();
if (!$toStock) {
$toStock = new Stock([
'business_id' => auth()->user()->business_id,
'product_id' => $fromStock->product_id,
'warehouse_id' => $toWh,
'batch_no' => $fromStock->batch_no,
'productStock' => 0,
'productPurchasePrice' => $fromStock->productPurchasePrice,
'profit_percent' => $fromStock->profit_percent,
'productSalePrice' => $fromStock->productSalePrice,
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
'productDealerPrice' => $fromStock->productDealerPrice,
'mfg_date' => $fromStock->mfg_date,
'expire_date' => $fromStock->expire_date,
]);
if (!$toStock) {
$toStock = new Stock([
'business_id' => $user->business_id,
'product_id' => $fromStock->product_id,
'warehouse_id' => $toWh,
'productStock' => 0,
'productPurchasePrice' => $fromStock->productPurchasePrice,
'profit_percent' => $fromStock->profit_percent,
'productSalePrice' => $fromStock->productSalePrice,
'exclusive_price' => $fromStock->exclusive_price,
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
'productDealerPrice' => $fromStock->productDealerPrice,
'mfg_date' => $fromStock->mfg_date,
'expire_date' => $fromStock->expire_date,
'serial_numbers' => !empty($serials) ? $serials : null,
]);
// if active branch and to branch is null then use active branch id
if ($toBranch == null && $user->active_branch_id){
$toStock->branch_id = $user->active_branch_id;
}else{
$toStock->branch_id = $toBranch;
}
// Safe branch assignment
$toStock->branch_id = $toBranch ?? $user->active_branch_id;
// Update product_type
if ($fromStock->product->product_type !== 'variant') {
$fromStock->product->update([
'product_type' => 'variant'
]);
}
// Save without events/global scopes
Stock::withoutEvents(function () use ($toStock) {
$toStock->save();
});
}
// Skip booted from model
Stock::withoutEvents(function () use ($toStock) {
$toStock->save();
});
}
// Increment destination stock safely
$toStock->increment('productStock', $quantity);
// Increase TO stock safely
$toStock->increment('productStock', $item['quantity']);
// Merge serial numbers if exist
if (!empty($serials)) {
$toStockSerials = is_array($toStock->serial_numbers)
? $toStock->serial_numbers
: json_decode($toStock->serial_numbers ?? '[]', true);
$toStock->serial_numbers = array_values(array_unique(array_merge($toStockSerials, $serials)));
$toStock->save();
}
}
}
TransferProduct::insert($transferProductData);
TransferProduct::insert($transferProducts);
DB::commit();
return response()->json([
'message' => __('Transfer saved successfully.'),
'data' => $transfer,
'redirect' => route('business.transfers.index'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => 'Error: ' . $e->getMessage(),
'success' => false,
'message' => $e->getMessage()
], 500);
}
}
@@ -313,6 +324,19 @@ public function edit($id)
public function update(Request $request, $id)
{
// Normalize serial_numbers
if ($request->has('products')) {
$products = $request->products;
foreach ($products as $key => $item) {
if (!empty($item['serial_numbers']) && is_string($item['serial_numbers'])) {
$products[$key]['serial_numbers'] = json_decode($item['serial_numbers'], true);
}
}
$request->merge(['products' => $products]);
}
$request->validate([
'from_branch_id' => 'nullable|exists:branches,id',
'to_branch_id' => 'nullable|exists:branches,id|required_with:from_branch_id',
@@ -327,11 +351,12 @@ public function update(Request $request, $id)
'products.*.unit_price' => 'required|numeric|min:0',
'products.*.discount' => 'nullable|numeric|min:0',
'products.*.tax' => 'nullable|numeric|min:0',
'products.*.serial_numbers' => 'nullable|array',
]);
$transfer = Transfer::findOrFail($id);
if ($request->status == 'cancelled') {
if ($request->status === 'cancelled') {
$transfer->update(['status' => 'cancelled']);
return response()->json([
'message' => __('Transfer cancelled successfully.'),
@@ -345,49 +370,28 @@ public function update(Request $request, $id)
$fromWh = $request->from_warehouse_id;
$toWh = $request->to_warehouse_id;
// Transfer validation
if ($user->active_branch_id && $toBranch && $toWh) {
return response()->json([
'message' => 'You cannot transfer to another branch warehouse.'
], 400);
}
if (!$toBranch && !$toWh) {
// to_branch or to_warehouse no one exist
return response()->json([
'message' => 'Invalid transfer request. Please select a destination branch or warehouse.'
], 400);
}
if ($fromBranch && !$fromWh) {
if ($fromBranch == $toBranch) {
return response()->json(['message' => 'Transfer not allowed: Same branch transfer is not possible.'], 400);
}
} elseif (!$fromBranch && $fromWh) {
if ($fromWh == $toWh) {
return response()->json(['message' => 'Transfer not allowed: Same warehouse transfer is not possible.'], 400);
}
} elseif ($fromBranch && $fromWh) {
if ($fromBranch == $toBranch && $fromWh == $toWh) {
return response()->json(['message' => 'Transfer not allowed: Same warehouse transfer within the same branch.'], 400);
}
} else {
return response()->json(['message' => 'Invalid transfer request. Please provide branch or warehouse information.'], 400);
}
DB::beginTransaction();
try {
$oldStatus = $transfer->status;
$subTotal = $totalDiscount = $totalTax = 0;
// Calculate totals using serial count
foreach ($request->products as $item) {
$subTotal += $item['quantity'] * $item['unit_price'];
$serials = !empty($item['serial_numbers']) ? $item['serial_numbers'] : [];
$qty = !empty($serials) ? count($serials) : $item['quantity'];
$subTotal += $qty * $item['unit_price'];
$totalDiscount += $item['discount'] ?? 0;
$totalTax += $item['tax'] ?? 0;
}
$shipping = $request->shipping_charge ?? 0;
$grandTotal = $subTotal + $totalTax - $totalDiscount + $shipping;
// Update transfer
$transfer->update([
'user_id' => auth()->id(),
'from_branch_id' => $fromBranch,
'to_branch_id' => $toBranch,
'from_warehouse_id' => $fromWh,
@@ -402,25 +406,25 @@ public function update(Request $request, $id)
'grand_total' => $grandTotal,
]);
// Update TransferProduct
// Delete old transfer products
TransferProduct::where('transfer_id', $transfer->id)->delete();
$transferProductData = [];
foreach ($request->products as $stockId => $item) {
$transferProductData[] = [
$serials = !empty($item['serial_numbers']) ? $item['serial_numbers'] : [];
$quantity = !empty($serials) ? count($serials) : $item['quantity'];
// Insert updated transfer product
TransferProduct::create([
'transfer_id' => $transfer->id,
'stock_id' => $stockId,
'quantity' => $item['quantity'] ?? 0,
'quantity' => $quantity,
'unit_price' => $item['unit_price'] ?? 0,
'discount' => $item['discount'] ?? 0,
'tax' => $item['tax'] ?? 0,
'created_at' => now(),
'updated_at' => now(),
];
}
TransferProduct::insert($transferProductData);
'serial_numbers' => !empty($serials) ? $serials : null,
]);
// Stock Handling
foreach ($request->products as $stockId => $item) {
$fromStock = Stock::where('id', $stockId)
->when($fromBranch, fn($q) => $q->where('branch_id', $fromBranch))
->when($fromWh, fn($q) => $q->where('warehouse_id', $fromWh))
@@ -431,20 +435,26 @@ public function update(Request $request, $id)
'message' => "From stock not found for stock ID: {$stockId}"
], 400);
}
$toStock = Stock::where('product_id', $fromStock->product_id)
->when($toBranch, fn($q) => $q->where('branch_id', $toBranch))
->when($toWh, fn($q) => $q->where('warehouse_id', $toWh))
->when(!is_null($fromStock->batch_no), fn($q) => $q->where('batch_no', $fromStock->batch_no))
->where(function ($q) use ($fromStock) {
// if destination stock batch is NULL, skip batch compare
$q->whereNull('batch_no')
// otherwise match same batch
->orWhere('batch_no', $fromStock->batch_no);
})
->first();
if (!$toStock) {
$toStock = new Stock([
'business_id' => auth()->user()->business_id,
'business_id' => $user->business_id,
'product_id' => $fromStock->product_id,
'warehouse_id' => $toWh,
'batch_no' => $fromStock->batch_no,
'productStock' => 0,
'productPurchasePrice' => $fromStock->productPurchasePrice,
'exclusive_price' => $fromStock->exclusive_price,
'profit_percent' => $fromStock->profit_percent,
'productSalePrice' => $fromStock->productSalePrice,
'productWholeSalePrice' => $fromStock->productWholeSalePrice,
@@ -453,31 +463,43 @@ public function update(Request $request, $id)
'expire_date' => $fromStock->expire_date,
]);
// if active branch and to branch is null then use active branch id
if ($toBranch == null && $user->active_branch_id){
$toStock->branch_id = $user->active_branch_id;
}else{
$toStock->branch_id = $toBranch;
}
// Update product_type
if ($fromStock->product->product_type !== 'variant') {
$fromStock->product->update([
'product_type' => 'variant'
]);
}
$toStock->branch_id = $toBranch ?? $user->active_branch_id;
Stock::withoutEvents(fn() => $toStock->save());
}
// Stock movement based on status change
if ($oldStatus !== $request->status) {
if ($oldStatus === 'pending' && $request->status === 'completed') {
if ($fromStock->productStock >= $item['quantity']) {
$fromStock->decrement('productStock', $item['quantity']);
$toStock->increment('productStock', $item['quantity']);
// Only move stock if changing pending to completed
if ($oldStatus === 'pending' && $request->status === 'completed') {
// Handle serials for source
if (!empty($serials)) {
$existing = $fromStock->serial_numbers ?? [];
foreach ($serials as $s) {
if (!in_array($s, $existing)) {
return response()->json([
'message' => "Serial {$s} not found in source stock."
], 400);
}
}
// Remove from source
$fromStock->serial_numbers = array_values(array_diff($existing, $serials));
$fromStock->productStock = count($fromStock->serial_numbers);
if ($fromStock->productStock === 0) {
$fromStock->serial_numbers = null;
}
} else {
$fromStock->decrement('productStock', $quantity);
}
$fromStock->save();
// Handle serials for destination
if (!empty($serials)) {
$toExisting = $toStock->serial_numbers ?? [];
$toStock->serial_numbers = array_values(array_unique(array_merge($toExisting, $serials)));
$toStock->productStock = count($toStock->serial_numbers);
} else {
$toStock->increment('productStock', $quantity);
}
$toStock->save();
}
}
@@ -487,6 +509,7 @@ public function update(Request $request, $id)
'message' => __('Transfer updated successfully.'),
'redirect' => route('business.transfers.index'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
@@ -494,8 +517,7 @@ public function update(Request $request, $id)
], 500);
}
}
public function destroy($id)
public function destroy(string $id)
{
$business_id = auth()->user()->business_id;
$transfer = Transfer::with('transferProducts')->where('business_id', $business_id)->findOrFail($id);
@@ -511,7 +533,10 @@ public function destroy($id)
$toStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->to_warehouse_id)
->where('branch_id', $transfer->to_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no') // if batch NULL → skip compare
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if (!$toStock || $toStock->quantity < $tp->quantity) {
@@ -528,8 +553,12 @@ public function destroy($id)
$toStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->to_warehouse_id)
->where('branch_id', $transfer->to_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no')
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if ($toStock) {
$toStock->decrement('quantity', $tp->quantity);
}
@@ -538,8 +567,12 @@ public function destroy($id)
$fromStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->from_warehouse_id)
->where('branch_id', $transfer->from_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no')
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if ($fromStock) {
$fromStock->increment('quantity', $tp->quantity);
}
@@ -583,7 +616,10 @@ public function deleteAll(Request $request)
$toStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->to_warehouse_id)
->where('branch_id', $transfer->to_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no')
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if (!$toStock || $toStock->quantity < $tp->quantity) {
@@ -604,8 +640,12 @@ public function deleteAll(Request $request)
$toStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->to_warehouse_id)
->where('branch_id', $transfer->to_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no')
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if ($toStock) {
$toStock->decrement('quantity', $tp->quantity);
}
@@ -614,8 +654,12 @@ public function deleteAll(Request $request)
$fromStock = Stock::where('product_id', $tp->product_id)
->where('warehouse_id', $transfer->from_warehouse_id)
->where('branch_id', $transfer->from_branch_id)
->where('batch_no', optional($stock)->batch_no)
->where(function ($q) use ($stock) {
$q->whereNull('batch_no')
->orWhere('batch_no', optional($stock)->batch_no);
})
->first();
if ($fromStock) {
$fromStock->increment('quantity', $tp->quantity);
}
@@ -648,4 +692,49 @@ public function exportCsv()
{
return Excel::download(new ExportTransfer, 'transfer.csv');
}
public function exportPdf(Request $request)
{
$user = auth()->user();
$activeBranchId = $user->active_branch_id;
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
->where('business_id', $user->business_id)
->when($activeBranchId, function ($q) use ($activeBranchId) {
$q->where(function ($query) use ($activeBranchId) {
$query->where('from_branch_id', $activeBranchId)
->orWhere('to_branch_id', $activeBranchId);
});
})
->when($request->branch_id && !$activeBranchId, function ($q) use ($request) {
$q->where(function ($query) use ($request) {
$query->where('from_branch_id', $request->branch_id)->orWhere('to_branch_id', $request->branch_id);
});
})
->when($request->search, function ($q) use ($request) {
$search = $request->search;
$q->where(function ($q) use ($search) {
$q->where('note', 'like', '%' . $search . '%')
->orWhere('status', 'like', '%' . $search . '%')
->orWhere('invoice_no', 'like', '%' . $search . '%')
->orWhereHas('fromWarehouse', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('toWarehouse', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('toBranch', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('fromBranch', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
});
});
})
->latest()
->limit(request('per_page') ?? 20)->get();
return PdfService::render('business::transfers.pdf', compact('transfers'),'transfers.pdf');
}
}