![]() Server : Apache/2.4.62 (Unix) OpenSSL/1.0.2k-fips System : Linux server1.richineiserver.com 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64 User : fdshops ( 1003) PHP Version : 8.2.21 Disable Function : NONE Directory : /home/fdshops/public_html/app/Http/Controllers/ |
<?php namespace App\Http\Controllers; use App\BusinessLocation; use App\PurchaseLine; use App\Transaction; use App\Utils\ModuleUtil; use App\Utils\ProductUtil; use App\Utils\TransactionUtil; use Datatables; use DB; use Illuminate\Http\Request; use Spatie\Activitylog\Models\Activity; use App\Events\StockAdjustmentCreatedOrModified; class StockAdjustmentController extends Controller { /** * All Utils instance. */ protected $productUtil; protected $transactionUtil; protected $moduleUtil; /** * Constructor * * @param ProductUtils $product * @return void */ public function __construct(ProductUtil $productUtil, TransactionUtil $transactionUtil, ModuleUtil $moduleUtil) { $this->productUtil = $productUtil; $this->transactionUtil = $transactionUtil; $this->moduleUtil = $moduleUtil; } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { if (! auth()->user()->can('purchase.view') && ! auth()->user()->can('purchase.create') && ! auth()->user()->can('view_own_purchase')) { abort(403, 'Unauthorized action.'); } if (request()->ajax()) { $business_id = request()->session()->get('user.business_id'); $stock_adjustments = Transaction::join( 'business_locations AS BL', 'transactions.location_id', '=', 'BL.id' ) ->leftJoin('users as u', 'transactions.created_by', '=', 'u.id') ->where('transactions.business_id', $business_id) ->where('transactions.type', 'stock_adjustment') ->select( 'transactions.id', 'transaction_date', 'ref_no', 'BL.name as location_name', 'adjustment_type', 'final_total', 'total_amount_recovered', 'additional_notes', 'transactions.id as DT_RowId', DB::raw("CONCAT(COALESCE(u.surname, ''),' ',COALESCE(u.first_name, ''),' ',COALESCE(u.last_name,'')) as added_by") ); $permitted_locations = auth()->user()->permitted_locations(); if ($permitted_locations != 'all') { $stock_adjustments->whereIn('transactions.location_id', $permitted_locations); } $hide = ''; $start_date = request()->get('start_date'); $end_date = request()->get('end_date'); if (! empty($start_date) && ! empty($end_date)) { $stock_adjustments->whereBetween(DB::raw('date(transaction_date)'), [$start_date, $end_date]); $hide = 'hide'; } $location_id = request()->get('location_id'); if (! empty($location_id)) { $stock_adjustments->where('transactions.location_id', $location_id); } if (! auth()->user()->can('purchase.view') && auth()->user()->can('view_own_purchase')) { $stock_adjustments->where('transactions.created_by', request()->session()->get('user.id')); } if(! auth()->user()->can('purchase.delete')){ $hide = 'hide'; } return Datatables::of($stock_adjustments) ->addColumn('action', '<button type="button" data-href="{{action([\App\Http\Controllers\StockAdjustmentController::class, \'show\'], [$id]) }}" class="tw-dw-btn tw-dw-btn-xs tw-dw-btn-outline tw-dw-btn-primary btn-modal" data-container=".view_modal"><i class="fa fa-eye" aria-hidden="true"></i> @lang("messages.view")</button> <button type="button" data-href="{{ action([\App\Http\Controllers\StockAdjustmentController::class, \'destroy\'], [$id]) }}" class="tw-dw-btn tw-dw-btn-xs tw-dw-btn-outline tw-dw-btn-error delete_stock_adjustment '.$hide.'"><i class="fa fa-trash" aria-hidden="true"></i> @lang("messages.delete")</button>') ->removeColumn('id') ->editColumn( 'final_total', function ($row) { if (auth()->user()->can('view_purchase_price')) { return $this->transactionUtil->num_f($row->final_total, true); } else { return '<span>-</span>'; } } ) ->editColumn( 'total_amount_recovered', function ($row) { if (auth()->user()->can('view_purchase_price')) { return $this->transactionUtil->num_f($row->total_amount_recovered, true); } else { return '<span>-</span>'; } } ) ->editColumn('transaction_date', '{{@format_datetime($transaction_date)}}') ->editColumn('adjustment_type', function ($row) { return __('stock_adjustment.'.$row->adjustment_type); }) ->setRowAttr([ 'data-href' => function ($row) { return action([\App\Http\Controllers\StockAdjustmentController::class, 'show'], [$row->id]); }, ]) ->rawColumns(['final_total', 'action', 'total_amount_recovered']) ->make(true); } return view('stock_adjustment.index'); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { if (! auth()->user()->can('purchase.create')) { abort(403, 'Unauthorized action.'); } $business_id = request()->session()->get('user.business_id'); //Check if subscribed or not if (! $this->moduleUtil->isSubscribed($business_id)) { return $this->moduleUtil->expiredResponse(action([\App\Http\Controllers\StockAdjustmentController::class, 'index'])); } $business_locations = BusinessLocation::forDropdown($business_id); return view('stock_adjustment.create') ->with(compact('business_locations')); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { if (! auth()->user()->can('purchase.create')) { abort(403, 'Unauthorized action.'); } try { DB::beginTransaction(); $input_data = $request->only(['location_id', 'transaction_date', 'adjustment_type', 'additional_notes', 'total_amount_recovered', 'final_total', 'ref_no']); $business_id = $request->session()->get('user.business_id'); //Check if subscribed or not if (! $this->moduleUtil->isSubscribed($business_id)) { return $this->moduleUtil->expiredResponse(action([\App\Http\Controllers\StockAdjustmentController::class, 'index'])); } $user_id = $request->session()->get('user.id'); $input_data['type'] = 'stock_adjustment'; $input_data['business_id'] = $business_id; $input_data['created_by'] = $user_id; $input_data['transaction_date'] = $this->productUtil->uf_date($input_data['transaction_date'], true); $input_data['total_amount_recovered'] = $this->productUtil->num_uf($input_data['total_amount_recovered']); //Update reference count $ref_count = $this->productUtil->setAndGetReferenceCount('stock_adjustment'); //Generate reference number if (empty($input_data['ref_no'])) { $input_data['ref_no'] = $this->productUtil->generateReferenceNumber('stock_adjustment', $ref_count); } $products = $request->input('products'); if (! empty($products)) { $product_data = []; foreach ($products as $product) { $adjustment_line = [ 'product_id' => $product['product_id'], 'variation_id' => $product['variation_id'], 'quantity' => $this->productUtil->num_uf($product['quantity']), 'unit_price' => $this->productUtil->num_uf($product['unit_price']), ]; if (! empty($product['lot_no_line_id'])) { //Add lot_no_line_id to stock adjustment line $adjustment_line['lot_no_line_id'] = $product['lot_no_line_id']; } $product_data[] = $adjustment_line; //Decrease available quantity $this->productUtil->decreaseProductQuantity( $product['product_id'], $product['variation_id'], $input_data['location_id'], $this->productUtil->num_uf($product['quantity']) ); } $stock_adjustment = Transaction::create($input_data); $stock_adjustment->stock_adjustment_lines()->createMany($product_data); //Map Stock adjustment & Purchase. $business = ['id' => $business_id, 'accounting_method' => $request->session()->get('business.accounting_method'), 'location_id' => $input_data['location_id'], ]; $this->transactionUtil->mapPurchaseSell($business, $stock_adjustment->stock_adjustment_lines, 'stock_adjustment'); event(new StockAdjustmentCreatedOrModified($stock_adjustment, 'added')); $this->transactionUtil->activityLog($stock_adjustment, 'added', null, [], false); } $output = ['success' => 1, 'msg' => __('stock_adjustment.stock_adjustment_added_successfully'), ]; DB::commit(); } catch (\Exception $e) { DB::rollBack(); \Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage()); $msg = trans('messages.something_went_wrong'); if (get_class($e) == \App\Exceptions\PurchaseSellMismatch::class) { $msg = $e->getMessage(); } $output = ['success' => 0, 'msg' => $msg, ]; } return redirect('stock-adjustments')->with('status', $output); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { if (! auth()->user()->can('purchase.view')) { abort(403, 'Unauthorized action.'); } $business_id = request()->session()->get('user.business_id'); $stock_adjustment = Transaction::where('transactions.business_id', $business_id) ->where('transactions.id', $id) ->where('transactions.type', 'stock_adjustment') ->with(['stock_adjustment_lines', 'location', 'business', 'stock_adjustment_lines.variation', 'stock_adjustment_lines.variation.product', 'stock_adjustment_lines.variation.product_variation', 'stock_adjustment_lines.lot_details']) ->first(); $lot_n_exp_enabled = false; if (request()->session()->get('business.enable_lot_number') == 1 || request()->session()->get('business.enable_product_expiry') == 1) { $lot_n_exp_enabled = true; } $activities = Activity::forSubject($stock_adjustment) ->with(['causer', 'subject']) ->latest() ->get(); return view('stock_adjustment.show') ->with(compact('stock_adjustment', 'lot_n_exp_enabled', 'activities')); } /** * Show the form for editing the specified resource. * * @param \App\Transaction $stockAdjustment * @return \Illuminate\Http\Response */ public function edit(Transaction $stockAdjustment) { // } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\Transaction $stockAdjustment * @return \Illuminate\Http\Response */ public function update(Request $request, Transaction $stockAdjustment) { // } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { if (! auth()->user()->can('purchase.delete')) { abort(403, 'Unauthorized action.'); } try { if (request()->ajax()) { DB::beginTransaction(); $stock_adjustment = Transaction::where('id', $id) ->where('type', 'stock_adjustment') ->with(['stock_adjustment_lines']) ->first(); //Add deleted product quantity to available quantity $stock_adjustment_lines = $stock_adjustment->stock_adjustment_lines; if (! empty($stock_adjustment_lines)) { $line_ids = []; foreach ($stock_adjustment_lines as $stock_adjustment_line) { $this->productUtil->updateProductQuantity( $stock_adjustment->location_id, $stock_adjustment_line->product_id, $stock_adjustment_line->variation_id, $this->productUtil->num_f($stock_adjustment_line->quantity) ); $line_ids[] = $stock_adjustment_line->id; } $this->transactionUtil->mapPurchaseQuantityForDeleteStockAdjustment($line_ids); } $stock_adjustment->delete(); event( new StockAdjustmentCreatedOrModified($stock_adjustment, 'deleted')); //Remove Mapping between stock adjustment & purchase. $output = ['success' => 1, 'msg' => __('stock_adjustment.delete_success'), ]; DB::commit(); } } catch (\Exception $e) { DB::rollBack(); \Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage()); $output = ['success' => 0, 'msg' => __('messages.something_went_wrong'), ]; } return $output; } /** * Return product rows * * @param Request $request * @return \Illuminate\Http\Response */ public function getProductRow(Request $request) { if (request()->ajax()) { $row_index = $request->input('row_index'); $variation_id = $request->input('variation_id'); $location_id = $request->input('location_id'); $business_id = $request->session()->get('user.business_id'); $product = $this->productUtil->getDetailsFromVariation($variation_id, $business_id, $location_id); $product->formatted_qty_available = $this->productUtil->num_f($product->qty_available); $type = ! empty($request->input('type')) ? $request->input('type') : 'stock_adjustment'; //Get lot number dropdown if enabled $lot_numbers = []; if (request()->session()->get('business.enable_lot_number') == 1 || request()->session()->get('business.enable_product_expiry') == 1) { $lot_number_obj = $this->transactionUtil->getLotNumbersFromVariation($variation_id, $business_id, $location_id, true); foreach ($lot_number_obj as $lot_number) { $lot_number->qty_formated = $this->productUtil->num_f($lot_number->qty_available); $lot_numbers[] = $lot_number; } } $product->lot_numbers = $lot_numbers; $sub_units = $this->productUtil->getSubUnits($business_id, $product->unit_id, false, $product->id); if ($type == 'stock_transfer') { return view('stock_transfer.partials.product_table_row') ->with(compact('product', 'row_index', 'sub_units')); } else { return view('stock_adjustment.partials.product_table_row') ->with(compact('product', 'row_index', 'sub_units')); } } } /** * Sets expired purchase line as stock adjustmnet * * @param int $purchase_line_id * @return json $output */ public function removeExpiredStock($purchase_line_id) { if (! auth()->user()->can('purchase.delete')) { abort(403, 'Unauthorized action.'); } try { $purchase_line = PurchaseLine::where('id', $purchase_line_id) ->with(['transaction']) ->first(); if (! empty($purchase_line)) { DB::beginTransaction(); $qty_unsold = $purchase_line->quantity - $purchase_line->quantity_sold - $purchase_line->quantity_adjusted - $purchase_line->quantity_returned; $final_total = $purchase_line->purchase_price_inc_tax * $qty_unsold; $user_id = request()->session()->get('user.id'); $business_id = request()->session()->get('user.business_id'); //Update reference count $ref_count = $this->productUtil->setAndGetReferenceCount('stock_adjustment'); $stock_adjstmt_data = [ 'type' => 'stock_adjustment', 'business_id' => $business_id, 'created_by' => $user_id, 'transaction_date' => \Carbon::now()->format('Y-m-d'), 'total_amount_recovered' => 0, 'location_id' => $purchase_line->transaction->location_id, 'adjustment_type' => 'normal', 'final_total' => $final_total, 'ref_no' => $this->productUtil->generateReferenceNumber('stock_adjustment', $ref_count), ]; //Create stock adjustment transaction $stock_adjustment = Transaction::create($stock_adjstmt_data); $stock_adjustment_line = [ 'product_id' => $purchase_line->product_id, 'variation_id' => $purchase_line->variation_id, 'quantity' => $qty_unsold, 'unit_price' => $purchase_line->purchase_price_inc_tax, 'removed_purchase_line' => $purchase_line->id, ]; //Create stock adjustment line with the purchase line $stock_adjustment->stock_adjustment_lines()->create($stock_adjustment_line); //Decrease available quantity $this->productUtil->decreaseProductQuantity( $purchase_line->product_id, $purchase_line->variation_id, $purchase_line->transaction->location_id, $qty_unsold ); //Map Stock adjustment & Purchase. $business = ['id' => $business_id, 'accounting_method' => request()->session()->get('business.accounting_method'), 'location_id' => $purchase_line->transaction->location_id, ]; $this->transactionUtil->mapPurchaseSell($business, $stock_adjustment->stock_adjustment_lines, 'stock_adjustment', false, $purchase_line->id); DB::commit(); $output = ['success' => 1, 'msg' => __('lang_v1.stock_removed_successfully'), ]; } } catch (\Exception $e) { DB::rollBack(); \Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage()); $msg = trans('messages.something_went_wrong'); if (get_class($e) == \App\Exceptions\PurchaseSellMismatch::class) { $msg = $e->getMessage(); } $output = ['success' => 0, 'msg' => $msg, ]; } return $output; } }