271 lines
10 KiB
PHP
271 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Business;
|
|
use App\BusinessLocation;
|
|
use App\Product;
|
|
use App\Transaction;
|
|
use App\Utils\ProductUtil;
|
|
use App\Variation;
|
|
use DB;
|
|
use Excel;
|
|
use Illuminate\Http\Request;
|
|
|
|
class ImportOpeningStockController extends Controller
|
|
{
|
|
/**
|
|
* All Utils instance.
|
|
*/
|
|
protected $productUtil;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param ProductUtils $product
|
|
* @return void
|
|
*/
|
|
public function __construct(ProductUtil $productUtil)
|
|
{
|
|
$this->productUtil = $productUtil;
|
|
}
|
|
|
|
/**
|
|
* Display import product screen.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function index()
|
|
{
|
|
if (! auth()->user()->can('product.opening_stock')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$zip_loaded = extension_loaded('zip') ? true : false;
|
|
|
|
$date_formats = Business::date_formats();
|
|
$date_format = session('business.date_format');
|
|
$date_format = isset($date_formats[$date_format]) ? $date_formats[$date_format] : $date_format;
|
|
|
|
//Check if zip extension it loaded or not.
|
|
if ($zip_loaded === false) {
|
|
$notification = ['success' => 0,
|
|
'msg' => 'Please install/enable PHP Zip archive for import',
|
|
];
|
|
|
|
return view('import_opening_stock.index')
|
|
->with(compact('notification', 'date_format'));
|
|
} else {
|
|
return view('import_opening_stock.index')
|
|
->with(compact('date_format'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Imports the uploaded file to database.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.opening_stock')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$notAllowed = $this->productUtil->notAllowedInDemo();
|
|
if (! empty($notAllowed)) {
|
|
return $notAllowed;
|
|
}
|
|
|
|
//Set maximum php execution time
|
|
ini_set('max_execution_time', 0);
|
|
ini_set('memory_limit', -1);
|
|
|
|
if ($request->hasFile('products_csv')) {
|
|
$file = $request->file('products_csv');
|
|
|
|
$parsed_array = Excel::toArray([], $file);
|
|
//Remove header row
|
|
$imported_data = array_splice($parsed_array[0], 1);
|
|
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$user_id = $request->session()->get('user.id');
|
|
|
|
$formated_data = [];
|
|
|
|
$is_valid = true;
|
|
$error_msg = '';
|
|
|
|
DB::beginTransaction();
|
|
foreach ($imported_data as $key => $value) {
|
|
$row_no = $key + 1;
|
|
|
|
//Check for product SKU, get product id, variation id.
|
|
if (! empty($value[0])) {
|
|
$sku = $value[0];
|
|
$product_info = Variation::where('sub_sku', $sku)
|
|
->join('products AS P', 'variations.product_id', '=', 'P.id')
|
|
->leftjoin('tax_rates AS TR', 'P.tax', 'TR.id')
|
|
->where('P.business_id', $business_id)
|
|
->select(['P.id', 'variations.id as variation_id',
|
|
'P.enable_stock', 'TR.amount as tax_percent',
|
|
'TR.id as tax_id', ])
|
|
->first();
|
|
if (empty($product_info)) {
|
|
$is_valid = false;
|
|
$error_msg = "Product with sku $sku not found in row no. $row_no";
|
|
break;
|
|
} elseif ($product_info->enable_stock == 0) {
|
|
$is_valid = false;
|
|
$error_msg = "Manage Stock not enabled for the product with $sku in row no. $row_no";
|
|
break;
|
|
}
|
|
} else {
|
|
$is_valid = false;
|
|
$error_msg = "PRODUCT SKU is required in row no. $row_no";
|
|
break;
|
|
}
|
|
|
|
//Get location details.
|
|
if (! empty(trim($value[1]))) {
|
|
$location_name = trim($value[1]);
|
|
$location = BusinessLocation::where('name', $location_name)
|
|
->where('business_id', $business_id)
|
|
->first();
|
|
if (empty($location)) {
|
|
$is_valid = false;
|
|
$error_msg = "Location with name '$location_name' not found in row no. $row_no";
|
|
break;
|
|
}
|
|
} else {
|
|
$location = BusinessLocation::where('business_id', $business_id)->first();
|
|
}
|
|
|
|
$opening_stock = ['quantity' => trim($value[2]),
|
|
'location_id' => $location->id,
|
|
'lot_number' => trim($value[4]),
|
|
];
|
|
if (! empty(trim($value[5]))) {
|
|
$opening_stock['exp_date'] = $this->productUtil->uf_date($value[5]);
|
|
}
|
|
|
|
if (! empty(trim($value[3]))) {
|
|
$unit_cost_before_tax = trim($value[3]);
|
|
} else {
|
|
$is_valid = false;
|
|
$error_msg = "Invalid UNIT COST in row no. $row_no";
|
|
break;
|
|
}
|
|
|
|
if (! is_numeric(trim($value[2]))) {
|
|
$is_valid = false;
|
|
$error_msg = "Invalid quantity $value[2] in row no. $row_no";
|
|
break;
|
|
}
|
|
|
|
//Check for tra, location_id, opening_stock_product_id, type=opening stock.
|
|
$os_transaction = Transaction::where('business_id', $business_id)
|
|
->where('location_id', $location->id)
|
|
->where('type', 'opening_stock')
|
|
->where('opening_stock_product_id', $product_info->id)
|
|
->first();
|
|
|
|
$this->addOpeningStock($opening_stock, $product_info, $business_id, $unit_cost_before_tax, $os_transaction);
|
|
|
|
// //If exist add to it.
|
|
// if(!empty($os_transaction)){
|
|
// //If not create new
|
|
|
|
// } else {
|
|
// //If not create new
|
|
// $this->addOpeningStock($opening_stock, $product_info, $business_id, $unit_cost_before_tax);
|
|
// }
|
|
}
|
|
}
|
|
|
|
if (! $is_valid) {
|
|
throw new \Exception($error_msg);
|
|
}
|
|
|
|
$output = ['success' => 1,
|
|
'msg' => __('product.file_imported_successfully'),
|
|
];
|
|
|
|
DB::commit();
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => 0,
|
|
'msg' => 'Message:'.$e->getMessage(),
|
|
];
|
|
|
|
return redirect('import-opening-stock')->with('notification', $output);
|
|
}
|
|
|
|
return redirect('import-opening-stock')->with('status', $output);
|
|
}
|
|
|
|
/**
|
|
* Adds opening stock of a single product
|
|
*
|
|
* @param array $opening_stock
|
|
* @param obj $product
|
|
* @param int $business_id
|
|
* @return void
|
|
*/
|
|
private function addOpeningStock($opening_stock, $product, $business_id, $unit_cost_before_tax, $transaction = null)
|
|
{
|
|
$user_id = request()->session()->get('user.id');
|
|
|
|
$transaction_date = request()->session()->get('financial_year.start');
|
|
$transaction_date = \Carbon::createFromFormat('Y-m-d', $transaction_date)->toDateTimeString();
|
|
|
|
//Get product tax
|
|
$tax_percent = ! empty($product->tax_percent) ? $product->tax_percent : 0;
|
|
$tax_id = ! empty($product->tax_id) ? $product->tax_id : null;
|
|
|
|
$item_tax = $this->productUtil->calc_percentage($unit_cost_before_tax, $tax_percent);
|
|
|
|
//total before transaction tax
|
|
$total_before_trans_tax = $opening_stock['quantity'] * ($unit_cost_before_tax + $item_tax);
|
|
|
|
//Add opening stock transaction
|
|
if (empty($transaction)) {
|
|
$transaction = new Transaction();
|
|
$transaction->type = 'opening_stock';
|
|
$transaction->status = 'received';
|
|
$transaction->opening_stock_product_id = $product->id;
|
|
$transaction->business_id = $business_id;
|
|
$transaction->transaction_date = $transaction_date;
|
|
$transaction->location_id = $opening_stock['location_id'];
|
|
$transaction->payment_status = 'paid';
|
|
$transaction->created_by = $user_id;
|
|
$transaction->total_before_tax = 0;
|
|
$transaction->final_total = 0;
|
|
}
|
|
$transaction->total_before_tax += $total_before_trans_tax;
|
|
$transaction->final_total += $total_before_trans_tax;
|
|
$transaction->save();
|
|
|
|
//Create purchase line
|
|
$transaction->purchase_lines()->create([
|
|
'product_id' => $product->id,
|
|
'variation_id' => $product->variation_id,
|
|
'quantity' => $opening_stock['quantity'],
|
|
'pp_without_discount' => $unit_cost_before_tax,
|
|
'item_tax' => $item_tax,
|
|
'tax_id' => $tax_id,
|
|
'pp_without_discount' => $unit_cost_before_tax,
|
|
'purchase_price' => $unit_cost_before_tax,
|
|
'purchase_price_inc_tax' => $unit_cost_before_tax + $item_tax,
|
|
'exp_date' => ! empty($opening_stock['exp_date']) ? $opening_stock['exp_date'] : null,
|
|
'lot_number' => ! empty($opening_stock['lot_number']) ? $opening_stock['lot_number'] : null,
|
|
]);
|
|
//Update variation location details
|
|
$this->productUtil->updateProductQuantity($opening_stock['location_id'], $product->id, $product->variation_id, $opening_stock['quantity']);
|
|
}
|
|
}
|