2426 lines
102 KiB
PHP
2426 lines
102 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Brands;
|
|
use App\Business;
|
|
use App\BusinessLocation;
|
|
use App\Category;
|
|
use App\Exports\ProductsExport;
|
|
use App\Media;
|
|
use App\Product;
|
|
use App\ProductVariation;
|
|
use App\PurchaseLine;
|
|
use App\SellingPriceGroup;
|
|
use App\TaxRate;
|
|
use App\Unit;
|
|
use App\Utils\ModuleUtil;
|
|
use App\Utils\ProductUtil;
|
|
use App\Variation;
|
|
use App\VariationGroupPrice;
|
|
use App\VariationLocationDetails;
|
|
use App\VariationTemplate;
|
|
use App\Warranty;
|
|
use Excel;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Yajra\DataTables\Facades\DataTables;
|
|
use App\Events\ProductsCreatedOrModified;
|
|
use App\TransactionSellLine;
|
|
|
|
class ProductController extends Controller
|
|
{
|
|
/**
|
|
* All Utils instance.
|
|
*/
|
|
protected $productUtil;
|
|
|
|
protected $moduleUtil;
|
|
|
|
private $barcode_types;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param ProductUtils $product
|
|
* @return void
|
|
*/
|
|
public function __construct(ProductUtil $productUtil, ModuleUtil $moduleUtil)
|
|
{
|
|
$this->productUtil = $productUtil;
|
|
$this->moduleUtil = $moduleUtil;
|
|
|
|
//barcode types
|
|
$this->barcode_types = $this->productUtil->barcode_types();
|
|
}
|
|
|
|
/**
|
|
* Display a listing of the resource.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function index()
|
|
{
|
|
if (! auth()->user()->can('product.view') && ! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$selling_price_group_count = SellingPriceGroup::countSellingPriceGroups($business_id);
|
|
$is_woocommerce = $this->moduleUtil->isModuleInstalled('Woocommerce');
|
|
|
|
if (request()->ajax()) {
|
|
//Filter by location
|
|
$location_id = request()->get('location_id', null);
|
|
$permitted_locations = auth()->user()->permitted_locations();
|
|
|
|
$query = Product::with(['media'])
|
|
->leftJoin('brands', 'products.brand_id', '=', 'brands.id')
|
|
->join('units', 'products.unit_id', '=', 'units.id')
|
|
->leftJoin('categories as c1', 'products.category_id', '=', 'c1.id')
|
|
->leftJoin('categories as c2', 'products.sub_category_id', '=', 'c2.id')
|
|
->leftJoin('tax_rates', 'products.tax', '=', 'tax_rates.id')
|
|
->join('variations as v', 'v.product_id', '=', 'products.id')
|
|
->leftJoin('variation_location_details as vld', function ($join) use ($permitted_locations) {
|
|
$join->on('vld.variation_id', '=', 'v.id');
|
|
if ($permitted_locations != 'all') {
|
|
$join->whereIn('vld.location_id', $permitted_locations);
|
|
}
|
|
})
|
|
->whereNull('v.deleted_at')
|
|
->where('products.business_id', $business_id)
|
|
->where('products.type', '!=', 'modifier');
|
|
|
|
if (! empty($location_id) && $location_id != 'none') {
|
|
if ($permitted_locations == 'all' || in_array($location_id, $permitted_locations)) {
|
|
$query->whereHas('product_locations', function ($query) use ($location_id) {
|
|
$query->where('product_locations.location_id', '=', $location_id);
|
|
});
|
|
}
|
|
} elseif ($location_id == 'none') {
|
|
$query->doesntHave('product_locations');
|
|
} else {
|
|
if ($permitted_locations != 'all') {
|
|
$query->whereHas('product_locations', function ($query) use ($permitted_locations) {
|
|
$query->whereIn('product_locations.location_id', $permitted_locations);
|
|
});
|
|
} else {
|
|
$query->with('product_locations');
|
|
}
|
|
}
|
|
|
|
$products = $query->select(
|
|
'products.id',
|
|
'products.name as product',
|
|
'products.type',
|
|
'c1.name as category',
|
|
'c2.name as sub_category',
|
|
'units.actual_name as unit',
|
|
'brands.name as brand',
|
|
'tax_rates.name as tax',
|
|
'products.sku',
|
|
'products.image',
|
|
'products.enable_stock',
|
|
'products.is_inactive',
|
|
'products.not_for_selling',
|
|
'products.product_custom_field1', 'products.product_custom_field2', 'products.product_custom_field3', 'products.product_custom_field4', 'products.product_custom_field5', 'products.product_custom_field6',
|
|
'products.product_custom_field7', 'products.product_custom_field8', 'products.product_custom_field9',
|
|
'products.product_custom_field10', 'products.product_custom_field11', 'products.product_custom_field12',
|
|
'products.product_custom_field13', 'products.product_custom_field14', 'products.product_custom_field15',
|
|
'products.product_custom_field16', 'products.product_custom_field17', 'products.product_custom_field18',
|
|
'products.product_custom_field19', 'products.product_custom_field20',
|
|
'products.alert_quantity',
|
|
DB::raw('SUM(vld.qty_available) as current_stock'),
|
|
DB::raw('MAX(v.sell_price_inc_tax) as max_price'),
|
|
DB::raw('MIN(v.sell_price_inc_tax) as min_price'),
|
|
DB::raw('MAX(v.dpp_inc_tax) as max_purchase_price'),
|
|
DB::raw('MIN(v.dpp_inc_tax) as min_purchase_price')
|
|
);
|
|
|
|
//if woocomerce enabled add field to query
|
|
if ($is_woocommerce) {
|
|
$products->addSelect('woocommerce_disable_sync');
|
|
}
|
|
|
|
$products->groupBy('products.id');
|
|
|
|
$type = request()->get('type', null);
|
|
if (! empty($type)) {
|
|
$products->where('products.type', $type);
|
|
}
|
|
|
|
$category_id = request()->get('category_id', null);
|
|
if (! empty($category_id)) {
|
|
$products->where('products.category_id', $category_id);
|
|
}
|
|
|
|
$brand_id = request()->get('brand_id', null);
|
|
if (! empty($brand_id)) {
|
|
$products->where('products.brand_id', $brand_id);
|
|
}
|
|
|
|
$unit_id = request()->get('unit_id', null);
|
|
if (! empty($unit_id)) {
|
|
$products->where('products.unit_id', $unit_id);
|
|
}
|
|
|
|
$tax_id = request()->get('tax_id', null);
|
|
if (! empty($tax_id)) {
|
|
$products->where('products.tax', $tax_id);
|
|
}
|
|
|
|
$active_state = request()->get('active_state', null);
|
|
if ($active_state == 'active') {
|
|
$products->Active();
|
|
}
|
|
if ($active_state == 'inactive') {
|
|
$products->Inactive();
|
|
}
|
|
$not_for_selling = request()->get('not_for_selling', null);
|
|
if ($not_for_selling == 'true') {
|
|
$products->ProductNotForSales();
|
|
}
|
|
|
|
$woocommerce_enabled = request()->get('woocommerce_enabled', 0);
|
|
if ($woocommerce_enabled == 1) {
|
|
$products->where('products.woocommerce_disable_sync', 0);
|
|
}
|
|
|
|
if (! empty(request()->get('repair_model_id'))) {
|
|
$products->where('products.repair_model_id', request()->get('repair_model_id'));
|
|
}
|
|
|
|
return Datatables::of($products)
|
|
->addColumn(
|
|
'product_locations',
|
|
function ($row) {
|
|
return $row->product_locations->implode('name', ', ');
|
|
}
|
|
)
|
|
->editColumn('category', '{{$category}} @if(!empty($sub_category))<br/> -- {{$sub_category}}@endif')
|
|
->addColumn(
|
|
'action',
|
|
function ($row) use ($selling_price_group_count) {
|
|
$html =
|
|
'<div class="btn-group"><button type="button" class="tw-dw-btn tw-dw-btn-xs tw-dw-btn-outline tw-dw-btn-info tw-w-max dropdown-toggle" data-toggle="dropdown" aria-expanded="false">'.__('messages.actions').'<span class="caret"></span><span class="sr-only">Toggle Dropdown</span></button><ul class="dropdown-menu dropdown-menu-left" role="menu"><li><a href="'.action([\App\Http\Controllers\LabelsController::class, 'show']).'?product_id='.$row->id.'" data-toggle="tooltip" title="'.__('lang_v1.label_help').'"><i class="fa fa-barcode"></i> '.__('barcode.labels').'</a></li>';
|
|
|
|
if (auth()->user()->can('product.view')) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'view'], [$row->id]).'" class="view-product"><i class="fa fa-eye"></i> '.__('messages.view').'</a></li>';
|
|
}
|
|
|
|
if (auth()->user()->can('product.update')) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'edit'], [$row->id]).'"><i class="glyphicon glyphicon-edit"></i> '.__('messages.edit').'</a></li>';
|
|
}
|
|
|
|
if (auth()->user()->can('product.delete')) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'destroy'], [$row->id]).'" class="delete-product"><i class="fa fa-trash"></i> '.__('messages.delete').'</a></li>';
|
|
}
|
|
|
|
if ($row->is_inactive == 1) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'activate'], [$row->id]).'" class="activate-product"><i class="fas fa-check-circle"></i> '.__('lang_v1.reactivate').'</a></li>';
|
|
}
|
|
|
|
$html .= '<li class="divider"></li>';
|
|
|
|
if ($row->enable_stock == 1 && auth()->user()->can('product.opening_stock')) {
|
|
$html .=
|
|
'<li><a href="#" data-href="'.action([\App\Http\Controllers\OpeningStockController::class, 'add'], ['product_id' => $row->id]).'" class="add-opening-stock"><i class="fa fa-database"></i> '.__('lang_v1.add_edit_opening_stock').'</a></li>';
|
|
}
|
|
|
|
if (auth()->user()->can('product.view')) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'productStockHistory'], [$row->id]).'"><i class="fas fa-history"></i> '.__('lang_v1.product_stock_history').'</a></li>';
|
|
}
|
|
|
|
if (auth()->user()->can('product.create')) {
|
|
if ($selling_price_group_count > 0) {
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'addSellingPrices'], [$row->id]).'"><i class="fas fa-money-bill-alt"></i> '.__('lang_v1.add_selling_price_group_prices').'</a></li>';
|
|
}
|
|
|
|
$html .=
|
|
'<li><a href="'.action([\App\Http\Controllers\ProductController::class, 'create'], ['d' => $row->id]).'"><i class="fa fa-copy"></i> '.__('lang_v1.duplicate_product').'</a></li>';
|
|
}
|
|
|
|
if (! empty($row->media->first())) {
|
|
$html .=
|
|
'<li><a href="'.$row->media->first()->display_url.'" download="'.$row->media->first()->display_name.'"><i class="fas fa-download"></i> '.__('lang_v1.product_brochure').'</a></li>';
|
|
}
|
|
|
|
$html .= '</ul></div>';
|
|
|
|
return $html;
|
|
}
|
|
)
|
|
->editColumn('product', function ($row) use ($is_woocommerce) {
|
|
$product = $row->is_inactive == 1 ? e($row->product).' <span class="label bg-gray">'.__('lang_v1.inactive').'</span>' : e($row->product);
|
|
|
|
$product = $row->not_for_selling == 1 ? $product.' <span class="label bg-gray">'.__('lang_v1.not_for_selling').
|
|
'</span>' : $product;
|
|
|
|
if ($is_woocommerce && ! $row->woocommerce_disable_sync) {
|
|
$product = $product.'<br><i class="fab fa-wordpress"></i>';
|
|
}
|
|
|
|
return $product;
|
|
})
|
|
->editColumn('image', function ($row) {
|
|
return '<div style="display: flex;"><img src="'.$row->image_url.'" alt="Product image" class="product-thumbnail-small"></div>';
|
|
})
|
|
->editColumn('type', '@lang("lang_v1." . $type)')
|
|
->addColumn('mass_delete', function ($row) {
|
|
return '<input type="checkbox" class="row-select" value="'.$row->id.'">';
|
|
})
|
|
->editColumn('current_stock', function ($row) {
|
|
if ($row->enable_stock) {
|
|
$stock = $this->productUtil->num_f($row->current_stock, false, null, true);
|
|
|
|
return $stock.' '.$row->unit;
|
|
} else {
|
|
return '--';
|
|
}
|
|
})
|
|
->addColumn(
|
|
'purchase_price',
|
|
'<div style="white-space: nowrap;">@format_currency($min_purchase_price) @if($max_purchase_price != $min_purchase_price && $type == "variable") - @format_currency($max_purchase_price)@endif </div>'
|
|
)
|
|
->addColumn(
|
|
'selling_price',
|
|
'<div style="white-space: nowrap;">@format_currency($min_price) @if($max_price != $min_price && $type == "variable") - @format_currency($max_price)@endif </div>'
|
|
)
|
|
->filterColumn('products.sku', function ($query, $keyword) {
|
|
$query->whereHas('variations', function ($q) use ($keyword) {
|
|
$q->where('sub_sku', 'like', "%{$keyword}%");
|
|
})
|
|
->orWhere('products.sku', 'like', "%{$keyword}%");
|
|
})
|
|
->setRowAttr([
|
|
'data-href' => function ($row) {
|
|
if (auth()->user()->can('product.view')) {
|
|
return action([\App\Http\Controllers\ProductController::class, 'view'], [$row->id]);
|
|
} else {
|
|
return '';
|
|
}
|
|
}, ])
|
|
->rawColumns(['action', 'image', 'mass_delete', 'product', 'selling_price', 'purchase_price', 'category', 'current_stock'])
|
|
->make(true);
|
|
}
|
|
|
|
$rack_enabled = (request()->session()->get('business.enable_racks') || request()->session()->get('business.enable_row') || request()->session()->get('business.enable_position'));
|
|
|
|
$categories = Category::forDropdown($business_id, 'product');
|
|
|
|
$brands = Brands::forDropdown($business_id);
|
|
|
|
$units = Unit::forDropdown($business_id);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, false);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
$business_locations->prepend(__('lang_v1.none'), 'none');
|
|
|
|
if ($this->moduleUtil->isModuleInstalled('Manufacturing') && (auth()->user()->can('superadmin') || $this->moduleUtil->hasThePermissionInSubscription($business_id, 'manufacturing_module'))) {
|
|
$show_manufacturing_data = true;
|
|
} else {
|
|
$show_manufacturing_data = false;
|
|
}
|
|
|
|
//list product screen filter from module
|
|
$pos_module_data = $this->moduleUtil->getModuleData('get_filters_for_list_product_screen');
|
|
|
|
$is_admin = $this->productUtil->is_admin(auth()->user());
|
|
|
|
return view('product.index')
|
|
->with(compact(
|
|
'rack_enabled',
|
|
'categories',
|
|
'brands',
|
|
'units',
|
|
'taxes',
|
|
'business_locations',
|
|
'show_manufacturing_data',
|
|
'pos_module_data',
|
|
'is_woocommerce',
|
|
'is_admin'
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Show the form for creating a new resource.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function create()
|
|
{
|
|
if (! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
//Check if subscribed or not, then check for products quota
|
|
if (! $this->moduleUtil->isSubscribed($business_id)) {
|
|
return $this->moduleUtil->expiredResponse();
|
|
} elseif (! $this->moduleUtil->isQuotaAvailable('products', $business_id)) {
|
|
return $this->moduleUtil->quotaExpiredResponse('products', $business_id, action([\App\Http\Controllers\ProductController::class, 'index']));
|
|
}
|
|
|
|
$categories = Category::forDropdown($business_id, 'product');
|
|
|
|
$brands = Brands::forDropdown($business_id);
|
|
$units = Unit::forDropdown($business_id, true);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, true, true);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
$tax_attributes = $tax_dropdown['attributes'];
|
|
|
|
$barcode_types = $this->barcode_types;
|
|
$barcode_default = $this->productUtil->barcode_default();
|
|
|
|
$default_profit_percent = request()->session()->get('business.default_profit_percent');
|
|
|
|
//Get all business locations
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
//Duplicate product
|
|
$duplicate_product = null;
|
|
$rack_details = null;
|
|
|
|
$sub_categories = [];
|
|
if (! empty(request()->input('d'))) {
|
|
$duplicate_product = Product::where('business_id', $business_id)->find(request()->input('d'));
|
|
$duplicate_product->name .= ' (copy)';
|
|
|
|
if (! empty($duplicate_product->category_id)) {
|
|
$sub_categories = Category::where('business_id', $business_id)
|
|
->where('parent_id', $duplicate_product->category_id)
|
|
->pluck('name', 'id')
|
|
->toArray();
|
|
}
|
|
|
|
//Rack details
|
|
if (! empty($duplicate_product->id)) {
|
|
$rack_details = $this->productUtil->getRackDetails($business_id, $duplicate_product->id);
|
|
}
|
|
}
|
|
|
|
$selling_price_group_count = SellingPriceGroup::countSellingPriceGroups($business_id);
|
|
|
|
$module_form_parts = $this->moduleUtil->getModuleData('product_form_part');
|
|
$product_types = $this->product_types();
|
|
|
|
$common_settings = session()->get('business.common_settings');
|
|
$warranties = Warranty::forDropdown($business_id);
|
|
|
|
//product screen view from module
|
|
$pos_module_data = $this->moduleUtil->getModuleData('get_product_screen_top_view');
|
|
|
|
return view('product.create')
|
|
->with(compact('categories', 'brands', 'units', 'taxes', 'barcode_types', 'default_profit_percent', 'tax_attributes', 'barcode_default', 'business_locations', 'duplicate_product', 'sub_categories', 'rack_details', 'selling_price_group_count', 'module_form_parts', 'product_types', 'common_settings', 'warranties', 'pos_module_data'));
|
|
}
|
|
|
|
private function product_types()
|
|
{
|
|
//Product types also includes modifier.
|
|
return ['single' => __('lang_v1.single'),
|
|
'variable' => __('lang_v1.variable'),
|
|
'combo' => __('lang_v1.combo'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 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('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
try {
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$form_fields = ['name', 'brand_id', 'unit_id', 'category_id', 'tax', 'type', 'barcode_type', 'sku', 'manual_id', 'alert_quantity', 'tax_type', 'weight', 'product_description', 'sub_unit_ids', 'preparation_time_in_minutes', 'product_custom_field1', 'product_custom_field2', 'product_custom_field3', 'product_custom_field4', 'product_custom_field5', 'product_custom_field6', 'product_custom_field7', 'product_custom_field8', 'product_custom_field9', 'product_custom_field10', 'product_custom_field11', 'product_custom_field12', 'product_custom_field13', 'product_custom_field14', 'product_custom_field15', 'product_custom_field16', 'product_custom_field17', 'product_custom_field18', 'product_custom_field19', 'product_custom_field20',];
|
|
|
|
$module_form_fields = $this->moduleUtil->getModuleFormField('product_form_fields');
|
|
if (! empty($module_form_fields)) {
|
|
$form_fields = array_merge($form_fields, $module_form_fields);
|
|
}
|
|
|
|
$product_details = $request->only($form_fields);
|
|
$product_details['business_id'] = $business_id;
|
|
$product_details['created_by'] = $request->session()->get('user.id');
|
|
|
|
$product_details['enable_stock'] = (! empty($request->input('enable_stock')) && $request->input('enable_stock') == 1) ? 1 : 0;
|
|
$product_details['not_for_selling'] = (! empty($request->input('not_for_selling')) && $request->input('not_for_selling') == 1) ? 1 : 0;
|
|
|
|
if (! empty($request->input('sub_category_id'))) {
|
|
$product_details['sub_category_id'] = $request->input('sub_category_id');
|
|
}
|
|
|
|
if (! empty($request->input('secondary_unit_id'))) {
|
|
$product_details['secondary_unit_id'] = $request->input('secondary_unit_id');
|
|
}
|
|
|
|
if (empty($product_details['sku'])) {
|
|
$product_details['sku'] = ' ';
|
|
}
|
|
|
|
if (! empty($product_details['alert_quantity'])) {
|
|
$product_details['alert_quantity'] = $this->productUtil->num_uf($product_details['alert_quantity']);
|
|
}
|
|
|
|
$expiry_enabled = $request->session()->get('business.enable_product_expiry');
|
|
if (! empty($request->input('expiry_period_type')) && ! empty($request->input('expiry_period')) && ! empty($expiry_enabled) && ($product_details['enable_stock'] == 1)) {
|
|
$product_details['expiry_period_type'] = $request->input('expiry_period_type');
|
|
$product_details['expiry_period'] = $this->productUtil->num_uf($request->input('expiry_period'));
|
|
}
|
|
|
|
if (! empty($request->input('enable_sr_no')) && $request->input('enable_sr_no') == 1) {
|
|
$product_details['enable_sr_no'] = 1;
|
|
}
|
|
|
|
//upload document
|
|
$product_details['image'] = $this->productUtil->uploadFile($request, 'image', config('constants.product_img_path'), 'image');
|
|
$common_settings = session()->get('business.common_settings');
|
|
|
|
$product_details['warranty_id'] = ! empty($request->input('warranty_id')) ? $request->input('warranty_id') : null;
|
|
|
|
DB::beginTransaction();
|
|
|
|
$product = Product::create($product_details);
|
|
|
|
event(new ProductsCreatedOrModified($product_details, 'added'));
|
|
|
|
$sku = $this->productUtil->generateProductSku($product->id);
|
|
$product->sku = $sku;
|
|
$product->save();
|
|
|
|
//Add product locations
|
|
$product_locations = $request->input('product_locations');
|
|
if (! empty($product_locations)) {
|
|
$product->product_locations()->sync($product_locations);
|
|
}
|
|
|
|
if ($product->type == 'single') {
|
|
$this->productUtil->createSingleProductVariation($product->id, $product->sku, $request->input('single_dpp'), $request->input('single_dpp_inc_tax'), $request->input('profit_percent'), $request->input('single_dsp'), $request->input('single_dsp_inc_tax'));
|
|
} elseif ($product->type == 'variable') {
|
|
if (! empty($request->input('product_variation'))) {
|
|
$input_variations = $request->input('product_variation');
|
|
|
|
$this->productUtil->createVariableProductVariations($product->id, $input_variations, $request->input('sku_type'));
|
|
}
|
|
} elseif ($product->type == 'combo') {
|
|
|
|
//Create combo_variations array by combining variation_id and quantity.
|
|
$combo_variations = [];
|
|
if (! empty($request->input('composition_variation_id'))) {
|
|
$composition_variation_id = $request->input('composition_variation_id');
|
|
$quantity = $request->input('quantity');
|
|
$unit = $request->input('unit');
|
|
|
|
foreach ($composition_variation_id as $key => $value) {
|
|
$combo_variations[] = [
|
|
'variation_id' => $value,
|
|
'quantity' => $this->productUtil->num_uf($quantity[$key]),
|
|
'unit_id' => $unit[$key],
|
|
];
|
|
}
|
|
}
|
|
|
|
$this->productUtil->createSingleProductVariation($product->id, $product->sku, $request->input('item_level_purchase_price_total'), $request->input('purchase_price_inc_tax'), $request->input('profit_percent'), $request->input('selling_price'), $request->input('selling_price_inc_tax'), $combo_variations);
|
|
}
|
|
|
|
//Add product racks details.
|
|
$product_racks = $request->get('product_racks', null);
|
|
if (! empty($product_racks)) {
|
|
$this->productUtil->addRackDetails($business_id, $product->id, $product_racks);
|
|
}
|
|
|
|
//Set Module fields
|
|
if (! empty($request->input('has_module_data'))) {
|
|
$this->moduleUtil->getModuleData('after_product_saved', ['product' => $product, 'request' => $request]);
|
|
}
|
|
|
|
Media::uploadMedia($product->business_id, $product, $request, 'product_brochure', true);
|
|
|
|
DB::commit();
|
|
$output = ['success' => 1,
|
|
'msg' => __('product.product_added_success'),
|
|
];
|
|
} 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 redirect('products')->with('status', $output);
|
|
}
|
|
|
|
if ($request->input('submit_type') == 'submit_n_add_opening_stock') {
|
|
return redirect()->action([\App\Http\Controllers\OpeningStockController::class, 'add'],
|
|
['product_id' => $product->id]
|
|
);
|
|
} elseif ($request->input('submit_type') == 'submit_n_add_selling_prices') {
|
|
return redirect()->action([\App\Http\Controllers\ProductController::class, 'addSellingPrices'],
|
|
[$product->id]
|
|
);
|
|
} elseif ($request->input('submit_type') == 'save_n_add_another') {
|
|
return redirect()->action([\App\Http\Controllers\ProductController::class, 'create']
|
|
)->with('status', $output);
|
|
}
|
|
|
|
return redirect('products')->with('status', $output);
|
|
}
|
|
|
|
/**
|
|
* Display the specified resource.
|
|
*
|
|
* @param \App\Product $product
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function show($id)
|
|
{
|
|
if (! auth()->user()->can('product.view')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$details = $this->productUtil->getRackDetails($business_id, $id, true);
|
|
|
|
return view('product.show')->with(compact('details'));
|
|
}
|
|
|
|
/**
|
|
* Show the form for editing the specified resource.
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function edit($id)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$categories = Category::forDropdown($business_id, 'product');
|
|
$brands = Brands::forDropdown($business_id);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, true, true);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
$tax_attributes = $tax_dropdown['attributes'];
|
|
|
|
$barcode_types = $this->barcode_types;
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['product_locations'])
|
|
->where('id', $id)
|
|
->firstOrFail();
|
|
|
|
//Sub-category
|
|
$sub_categories = [];
|
|
$sub_categories = Category::where('business_id', $business_id)
|
|
->where('parent_id', $product->category_id)
|
|
->pluck('name', 'id')
|
|
->toArray();
|
|
$sub_categories = ['' => 'None'] + $sub_categories;
|
|
|
|
$default_profit_percent = request()->session()->get('business.default_profit_percent');
|
|
|
|
//Get units.
|
|
$units = Unit::forDropdown($business_id, true);
|
|
$sub_units = $this->productUtil->getSubUnits($business_id, $product->unit_id, true);
|
|
|
|
//Get all business locations
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
//Rack details
|
|
$rack_details = $this->productUtil->getRackDetails($business_id, $id);
|
|
|
|
$selling_price_group_count = SellingPriceGroup::countSellingPriceGroups($business_id);
|
|
|
|
$module_form_parts = $this->moduleUtil->getModuleData('product_form_part');
|
|
$product_types = $this->product_types();
|
|
$common_settings = session()->get('business.common_settings');
|
|
$warranties = Warranty::forDropdown($business_id);
|
|
|
|
//product screen view from module
|
|
$pos_module_data = $this->moduleUtil->getModuleData('get_product_screen_top_view');
|
|
|
|
$alert_quantity = ! is_null($product->alert_quantity) ? $this->productUtil->num_f($product->alert_quantity, false, null, true) : null;
|
|
|
|
return view('product.edit')
|
|
->with(compact('categories', 'brands', 'units', 'sub_units', 'taxes', 'tax_attributes', 'barcode_types', 'product', 'sub_categories', 'default_profit_percent', 'business_locations', 'rack_details', 'selling_price_group_count', 'module_form_parts', 'product_types', 'common_settings', 'warranties', 'pos_module_data', 'alert_quantity'));
|
|
}
|
|
|
|
/**
|
|
* Update the specified resource in storage.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function update(Request $request, $id)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$product_details = $request->only(['name', 'brand_id', 'unit_id', 'category_id', 'tax', 'barcode_type', 'sku', 'manual_id', 'alert_quantity', 'tax_type', 'weight', 'product_description', 'sub_unit_ids', 'preparation_time_in_minutes', 'product_custom_field1', 'product_custom_field2', 'product_custom_field3', 'product_custom_field4', 'product_custom_field5', 'product_custom_field6', 'product_custom_field7', 'product_custom_field8', 'product_custom_field9', 'product_custom_field10', 'product_custom_field11', 'product_custom_field12', 'product_custom_field13', 'product_custom_field14', 'product_custom_field15', 'product_custom_field16', 'product_custom_field17', 'product_custom_field18', 'product_custom_field19', 'product_custom_field20',]);
|
|
|
|
DB::beginTransaction();
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->where('id', $id)
|
|
->with(['product_variations'])
|
|
->first();
|
|
|
|
$module_form_fields = $this->moduleUtil->getModuleFormField('product_form_fields');
|
|
if (! empty($module_form_fields)) {
|
|
foreach ($module_form_fields as $column) {
|
|
$product->$column = $request->input($column);
|
|
}
|
|
}
|
|
|
|
$product->name = $product_details['name'];
|
|
$product->brand_id = $product_details['brand_id'];
|
|
$product->unit_id = $product_details['unit_id'];
|
|
$product->category_id = $product_details['category_id'];
|
|
$product->tax = $product_details['tax'];
|
|
$product->barcode_type = $product_details['barcode_type'];
|
|
$product->sku = $product_details['sku'];
|
|
$product->manual_id = $product_details['manual_id'] ?? '';
|
|
$product->alert_quantity = ! empty($product_details['alert_quantity']) ? $this->productUtil->num_uf($product_details['alert_quantity']) : $product_details['alert_quantity'];
|
|
$product->tax_type = $product_details['tax_type'];
|
|
$product->weight = $product_details['weight'];
|
|
$product->product_custom_field1 = $product_details['product_custom_field1'] ?? '';
|
|
$product->product_custom_field2 = $product_details['product_custom_field2'] ?? '';
|
|
$product->product_custom_field3 = $product_details['product_custom_field3'] ?? '';
|
|
$product->product_custom_field4 = $product_details['product_custom_field4'] ?? '';
|
|
$product->product_custom_field5 = $product_details['product_custom_field5'] ?? '';
|
|
$product->product_custom_field6 = $product_details['product_custom_field6'] ?? '';
|
|
$product->product_custom_field7 = $product_details['product_custom_field7'] ?? '';
|
|
$product->product_custom_field8 = $product_details['product_custom_field8'] ?? '';
|
|
$product->product_custom_field9 = $product_details['product_custom_field9'] ?? '';
|
|
$product->product_custom_field10 = $product_details['product_custom_field10'] ?? '';
|
|
$product->product_custom_field11 = $product_details['product_custom_field11'] ?? '';
|
|
$product->product_custom_field12 = $product_details['product_custom_field12'] ?? '';
|
|
$product->product_custom_field13 = $product_details['product_custom_field13'] ?? '';
|
|
$product->product_custom_field14 = $product_details['product_custom_field14'] ?? '';
|
|
$product->product_custom_field15 = $product_details['product_custom_field15'] ?? '';
|
|
$product->product_custom_field16 = $product_details['product_custom_field16'] ?? '';
|
|
$product->product_custom_field17 = $product_details['product_custom_field17'] ?? '';
|
|
$product->product_custom_field18 = $product_details['product_custom_field18'] ?? '';
|
|
$product->product_custom_field19 = $product_details['product_custom_field19'] ?? '';
|
|
$product->product_custom_field20 = $product_details['product_custom_field20'] ?? '';
|
|
|
|
$product->product_description = $product_details['product_description'];
|
|
$product->sub_unit_ids = ! empty($product_details['sub_unit_ids']) ? $product_details['sub_unit_ids'] : null;
|
|
$product->preparation_time_in_minutes = $product_details['preparation_time_in_minutes'];
|
|
$product->warranty_id = ! empty($request->input('warranty_id')) ? $request->input('warranty_id') : null;
|
|
$product->secondary_unit_id = ! empty($request->input('secondary_unit_id')) ? $request->input('secondary_unit_id') : null;
|
|
|
|
if (! empty($request->input('enable_stock')) && $request->input('enable_stock') == 1) {
|
|
$product->enable_stock = 1;
|
|
} else {
|
|
$product->enable_stock = 0;
|
|
}
|
|
|
|
$product->not_for_selling = (! empty($request->input('not_for_selling')) && $request->input('not_for_selling') == 1) ? 1 : 0;
|
|
|
|
if (! empty($request->input('sub_category_id'))) {
|
|
$product->sub_category_id = $request->input('sub_category_id');
|
|
} else {
|
|
$product->sub_category_id = null;
|
|
}
|
|
|
|
$expiry_enabled = $request->session()->get('business.enable_product_expiry');
|
|
if (! empty($expiry_enabled)) {
|
|
if (! empty($request->input('expiry_period_type')) && ! empty($request->input('expiry_period')) && ($product->enable_stock == 1)) {
|
|
$product->expiry_period_type = $request->input('expiry_period_type');
|
|
$product->expiry_period = $this->productUtil->num_uf($request->input('expiry_period'));
|
|
} else {
|
|
$product->expiry_period_type = null;
|
|
$product->expiry_period = null;
|
|
}
|
|
}
|
|
|
|
if (! empty($request->input('enable_sr_no')) && $request->input('enable_sr_no') == 1) {
|
|
$product->enable_sr_no = 1;
|
|
} else {
|
|
$product->enable_sr_no = 0;
|
|
}
|
|
|
|
//upload document
|
|
$file_name = $this->productUtil->uploadFile($request, 'image', config('constants.product_img_path'), 'image');
|
|
if (! empty($file_name)) {
|
|
|
|
//If previous image found then remove
|
|
if (! empty($product->image_path) && file_exists($product->image_path)) {
|
|
unlink($product->image_path);
|
|
}
|
|
|
|
$product->image = $file_name;
|
|
//If product image is updated update woocommerce media id
|
|
if (! empty($product->woocommerce_media_id)) {
|
|
$product->woocommerce_media_id = null;
|
|
}
|
|
}
|
|
|
|
$product->save();
|
|
$product->touch();
|
|
|
|
event(new ProductsCreatedOrModified($product, 'updated'));
|
|
|
|
//Add product locations
|
|
$product_locations = ! empty($request->input('product_locations')) ?
|
|
$request->input('product_locations') : [];
|
|
|
|
$permitted_locations = auth()->user()->permitted_locations();
|
|
//If not assigned location exists don't remove it
|
|
if ($permitted_locations != 'all') {
|
|
$existing_product_locations = $product->product_locations()->pluck('id');
|
|
|
|
foreach ($existing_product_locations as $pl) {
|
|
if (! in_array($pl, $permitted_locations)) {
|
|
$product_locations[] = $pl;
|
|
}
|
|
}
|
|
}
|
|
|
|
$product->product_locations()->sync($product_locations);
|
|
|
|
if ($product->type == 'single') {
|
|
$single_data = $request->only(['single_variation_id', 'single_dpp', 'single_dpp_inc_tax', 'single_dsp_inc_tax', 'profit_percent', 'single_dsp']);
|
|
$variation = Variation::find($single_data['single_variation_id']);
|
|
|
|
$variation->sub_sku = $product->sku;
|
|
$variation->default_purchase_price = $this->productUtil->num_uf($single_data['single_dpp']);
|
|
$variation->dpp_inc_tax = $this->productUtil->num_uf($single_data['single_dpp_inc_tax']);
|
|
$variation->profit_percent = $this->productUtil->num_uf($single_data['profit_percent']);
|
|
$variation->default_sell_price = $this->productUtil->num_uf($single_data['single_dsp']);
|
|
$variation->sell_price_inc_tax = $this->productUtil->num_uf($single_data['single_dsp_inc_tax']);
|
|
$variation->save();
|
|
|
|
Media::uploadMedia($product->business_id, $variation, $request, 'variation_images');
|
|
} elseif ($product->type == 'variable') {
|
|
//Update existing variations
|
|
$input_variations_edit = $request->get('product_variation_edit');
|
|
if (! empty($input_variations_edit)) {
|
|
$this->productUtil->updateVariableProductVariations($product->id, $input_variations_edit,$request->input('sku_type'));
|
|
}
|
|
|
|
//Add new variations created.
|
|
$input_variations = $request->input('product_variation');
|
|
if (! empty($input_variations)) {
|
|
$this->productUtil->createVariableProductVariations($product->id, $input_variations, $request->input('sku_type'));
|
|
}
|
|
} elseif ($product->type == 'combo') {
|
|
|
|
//Create combo_variations array by combining variation_id and quantity.
|
|
$combo_variations = [];
|
|
if (! empty($request->input('composition_variation_id'))) {
|
|
$composition_variation_id = $request->input('composition_variation_id');
|
|
$quantity = $request->input('quantity');
|
|
$unit = $request->input('unit');
|
|
|
|
foreach ($composition_variation_id as $key => $value) {
|
|
$combo_variations[] = [
|
|
'variation_id' => $value,
|
|
'quantity' => $quantity[$key],
|
|
'unit_id' => $unit[$key],
|
|
];
|
|
}
|
|
}
|
|
|
|
$variation = Variation::find($request->input('combo_variation_id'));
|
|
$variation->sub_sku = $product->sku;
|
|
$variation->default_purchase_price = $this->productUtil->num_uf($request->input('item_level_purchase_price_total'));
|
|
$variation->dpp_inc_tax = $this->productUtil->num_uf($request->input('purchase_price_inc_tax'));
|
|
$variation->profit_percent = $this->productUtil->num_uf($request->input('profit_percent'));
|
|
$variation->default_sell_price = $this->productUtil->num_uf($request->input('selling_price'));
|
|
$variation->sell_price_inc_tax = $this->productUtil->num_uf($request->input('selling_price_inc_tax'));
|
|
$variation->combo_variations = $combo_variations;
|
|
$variation->save();
|
|
}
|
|
|
|
//Add product racks details.
|
|
$product_racks = $request->get('product_racks', null);
|
|
if (! empty($product_racks)) {
|
|
$this->productUtil->addRackDetails($business_id, $product->id, $product_racks);
|
|
}
|
|
|
|
$product_racks_update = $request->get('product_racks_update', null);
|
|
if (! empty($product_racks_update)) {
|
|
$this->productUtil->updateRackDetails($business_id, $product->id, $product_racks_update);
|
|
}
|
|
|
|
//Set Module fields
|
|
if (! empty($request->input('has_module_data'))) {
|
|
$this->moduleUtil->getModuleData('after_product_saved', ['product' => $product, 'request' => $request]);
|
|
}
|
|
|
|
Media::uploadMedia($product->business_id, $product, $request, 'product_brochure', true);
|
|
|
|
DB::commit();
|
|
$output = ['success' => 1,
|
|
'msg' => __('product.product_updated_success'),
|
|
];
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => 0,
|
|
'msg' => $e->getMessage(),
|
|
];
|
|
}
|
|
|
|
if ($request->input('submit_type') == 'update_n_edit_opening_stock') {
|
|
return redirect()->action([\App\Http\Controllers\OpeningStockController::class, 'add'],
|
|
['product_id' => $product->id]
|
|
);
|
|
} elseif ($request->input('submit_type') == 'submit_n_add_selling_prices') {
|
|
return redirect()->action([\App\Http\Controllers\ProductController::class, 'addSellingPrices'],
|
|
[$product->id]
|
|
);
|
|
} elseif ($request->input('submit_type') == 'save_n_add_another') {
|
|
return redirect()->action([\App\Http\Controllers\ProductController::class, 'create']
|
|
)->with('status', $output);
|
|
}
|
|
|
|
return redirect('products')->with('status', $output);
|
|
}
|
|
|
|
/**
|
|
* Remove the specified resource from storage.
|
|
*
|
|
* @param \App\Product $product
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function destroy($id)
|
|
{
|
|
if (! auth()->user()->can('product.delete')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
if (request()->ajax()) {
|
|
try {
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
$can_be_deleted = true;
|
|
$error_msg = '';
|
|
|
|
//Check if any purchase or transfer exists
|
|
$count = PurchaseLine::join(
|
|
'transactions as T',
|
|
'purchase_lines.transaction_id',
|
|
'=',
|
|
'T.id'
|
|
)
|
|
->whereIn('T.type', ['purchase'])
|
|
->where('T.business_id', $business_id)
|
|
->where('purchase_lines.product_id', $id)
|
|
->count();
|
|
if ($count > 0) {
|
|
$can_be_deleted = false;
|
|
$error_msg = __('lang_v1.purchase_already_exist');
|
|
} else {
|
|
//Check if any opening stock sold
|
|
$count = PurchaseLine::join(
|
|
'transactions as T',
|
|
'purchase_lines.transaction_id',
|
|
'=',
|
|
'T.id'
|
|
)
|
|
->where('T.type', 'opening_stock')
|
|
->where('T.business_id', $business_id)
|
|
->where('purchase_lines.product_id', $id)
|
|
->where('purchase_lines.quantity_sold', '>', 0)
|
|
->count();
|
|
if ($count > 0) {
|
|
$can_be_deleted = false;
|
|
$error_msg = __('lang_v1.opening_stock_sold');
|
|
} else {
|
|
//Check if any stock is adjusted
|
|
$count = PurchaseLine::join(
|
|
'transactions as T',
|
|
'purchase_lines.transaction_id',
|
|
'=',
|
|
'T.id'
|
|
)
|
|
->where('T.business_id', $business_id)
|
|
->where('purchase_lines.product_id', $id)
|
|
->where('purchase_lines.quantity_adjusted', '>', 0)
|
|
->count();
|
|
if ($count > 0) {
|
|
$can_be_deleted = false;
|
|
$error_msg = __('lang_v1.stock_adjusted');
|
|
}
|
|
}
|
|
}
|
|
|
|
$product = Product::where('id', $id)
|
|
->where('business_id', $business_id)
|
|
->with('variations')
|
|
->first();
|
|
|
|
// check for enable stock = 0 product
|
|
if($product->enable_stock == 0){
|
|
$t_count = TransactionSellLine::join(
|
|
'transactions as T',
|
|
'transaction_sell_lines.transaction_id',
|
|
'=',
|
|
'T.id'
|
|
)
|
|
->where('T.business_id', $business_id)
|
|
->where('transaction_sell_lines.product_id', $id)
|
|
->count();
|
|
|
|
if ($t_count > 0) {
|
|
$can_be_deleted = false;
|
|
$error_msg = "can't delete product exit in sell";
|
|
}
|
|
}
|
|
|
|
//Check if product is added as an ingredient of any recipe
|
|
if ($this->moduleUtil->isModuleInstalled('Manufacturing')) {
|
|
$variation_ids = $product->variations->pluck('id');
|
|
|
|
$exists_as_ingredient = \Modules\Manufacturing\Entities\MfgRecipeIngredient::whereIn('variation_id', $variation_ids)
|
|
->exists();
|
|
if ($exists_as_ingredient) {
|
|
$can_be_deleted = false;
|
|
$error_msg = __('manufacturing::lang.added_as_ingredient');
|
|
}
|
|
}
|
|
|
|
if ($can_be_deleted) {
|
|
if (! empty($product)) {
|
|
DB::beginTransaction();
|
|
//Delete variation location details
|
|
VariationLocationDetails::where('product_id', $id)
|
|
->delete();
|
|
$product->delete();
|
|
event(new ProductsCreatedOrModified($product, 'deleted'));
|
|
DB::commit();
|
|
}
|
|
|
|
$output = ['success' => true,
|
|
'msg' => __('lang_v1.product_delete_success'),
|
|
];
|
|
} else {
|
|
$output = ['success' => false,
|
|
'msg' => $error_msg,
|
|
];
|
|
}
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => false,
|
|
'msg' => __('messages.something_went_wrong'),
|
|
];
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get subcategories list for a category.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getSubCategories(Request $request)
|
|
{
|
|
if (! empty($request->input('cat_id'))) {
|
|
$category_id = $request->input('cat_id');
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$sub_categories = Category::where('business_id', $business_id)
|
|
->where('parent_id', $category_id)
|
|
->select(['name', 'id'])
|
|
->get();
|
|
$html = '<option value="">None</option>';
|
|
if (! empty($sub_categories)) {
|
|
foreach ($sub_categories as $sub_category) {
|
|
$html .= '<option value="'.$sub_category->id.'">'.$sub_category->name.'</option>';
|
|
}
|
|
}
|
|
echo $html;
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get product form parts.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getProductVariationFormPart(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$business = Business::findorfail($business_id);
|
|
$profit_percent = $business->default_profit_percent;
|
|
|
|
$action = $request->input('action');
|
|
if ($request->input('action') == 'add') {
|
|
if ($request->input('type') == 'single') {
|
|
return view('product.partials.single_product_form_part')
|
|
->with(['profit_percent' => $profit_percent]);
|
|
} elseif ($request->input('type') == 'variable') {
|
|
$variation_templates = VariationTemplate::where('business_id', $business_id)->pluck('name', 'id')->toArray();
|
|
$variation_templates = ['' => __('messages.please_select')] + $variation_templates;
|
|
|
|
return view('product.partials.variable_product_form_part')
|
|
->with(compact('variation_templates', 'profit_percent', 'action'));
|
|
} elseif ($request->input('type') == 'combo') {
|
|
return view('product.partials.combo_product_form_part')
|
|
->with(compact('profit_percent', 'action'));
|
|
}
|
|
} elseif ($request->input('action') == 'edit' || $request->input('action') == 'duplicate') {
|
|
$product_id = $request->input('product_id');
|
|
$action = $request->input('action');
|
|
if ($request->input('type') == 'single') {
|
|
$product_deatails = ProductVariation::where('product_id', $product_id)
|
|
->with(['variations', 'variations.media'])
|
|
->first();
|
|
|
|
return view('product.partials.edit_single_product_form_part')
|
|
->with(compact('product_deatails', 'action'));
|
|
} elseif ($request->input('type') == 'variable') {
|
|
$product_variations = ProductVariation::where('product_id', $product_id)
|
|
->with(['variations', 'variations.media'])
|
|
->get();
|
|
|
|
return view('product.partials.variable_product_form_part')
|
|
->with(compact('product_variations', 'profit_percent', 'action'));
|
|
} elseif ($request->input('type') == 'combo') {
|
|
$product_deatails = ProductVariation::where('product_id', $product_id)
|
|
->with(['variations', 'variations.media'])
|
|
->first();
|
|
$combo_variations = $this->productUtil->__getComboProductDetails($product_deatails['variations'][0]->combo_variations, $business_id);
|
|
|
|
$variation_id = $product_deatails['variations'][0]->id;
|
|
$profit_percent = $product_deatails['variations'][0]->profit_percent;
|
|
|
|
return view('product.partials.combo_product_form_part')
|
|
->with(compact('combo_variations', 'profit_percent', 'action', 'variation_id'));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get product form parts.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getVariationValueRow(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$business = Business::findorfail($business_id);
|
|
$profit_percent = $business->default_profit_percent;
|
|
|
|
$variation_index = $request->input('variation_row_index');
|
|
$value_index = $request->input('value_index') + 1;
|
|
|
|
$row_type = $request->input('row_type', 'add');
|
|
|
|
return view('product.partials.variation_value_row')
|
|
->with(compact('profit_percent', 'variation_index', 'value_index', 'row_type'));
|
|
}
|
|
|
|
/**
|
|
* Get product form parts.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getProductVariationRow(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$business = Business::findorfail($business_id);
|
|
$profit_percent = $business->default_profit_percent;
|
|
|
|
$variation_templates = VariationTemplate::where('business_id', $business_id)
|
|
->pluck('name', 'id')->toArray();
|
|
$variation_templates = ['' => __('messages.please_select')] + $variation_templates;
|
|
|
|
$row_index = $request->input('row_index', 0);
|
|
$action = $request->input('action');
|
|
|
|
return view('product.partials.product_variation_row')
|
|
->with(compact('variation_templates', 'row_index', 'action', 'profit_percent'));
|
|
}
|
|
|
|
/**
|
|
* Get product form parts.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getVariationTemplate(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$business = Business::findorfail($business_id);
|
|
$profit_percent = $business->default_profit_percent;
|
|
|
|
$template = VariationTemplate::where('id', $request->input('template_id'))
|
|
->with(['values'])
|
|
->first();
|
|
$row_index = $request->input('row_index');
|
|
|
|
$values = [];
|
|
foreach ($template->values as $v) {
|
|
$values[] = [
|
|
'id' => $v->id,
|
|
'text' => $v->name,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'html' => view('product.partials.product_variation_template')
|
|
->with(compact('template', 'row_index', 'profit_percent'))->render(),
|
|
'values' => $values,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Return the view for combo product row
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getComboProductEntryRow(Request $request)
|
|
{
|
|
if (request()->ajax()) {
|
|
$product_id = $request->input('product_id');
|
|
$variation_id = $request->input('variation_id');
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
if (! empty($product_id)) {
|
|
$product = Product::where('id', $product_id)
|
|
->with(['unit'])
|
|
->first();
|
|
|
|
$query = Variation::where('product_id', $product_id)
|
|
->with(['product_variation']);
|
|
|
|
if ($variation_id !== '0') {
|
|
$query->where('id', $variation_id);
|
|
}
|
|
$variations = $query->get();
|
|
|
|
$sub_units = $this->productUtil->getSubUnits($business_id, $product['unit']->id);
|
|
|
|
return view('product.partials.combo_product_entry_row')
|
|
->with(compact('product', 'variations', 'sub_units'));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves products list.
|
|
*
|
|
* @param string $q
|
|
* @param bool $check_qty
|
|
* @return JSON
|
|
*/
|
|
public function getProducts()
|
|
{
|
|
if (request()->ajax()) {
|
|
$search_term = request()->input('term', '');
|
|
$location_id = request()->input('location_id', null);
|
|
$check_qty = request()->input('check_qty', false);
|
|
$price_group_id = request()->input('price_group', null);
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$not_for_selling = request()->get('not_for_selling', null);
|
|
$price_group_id = request()->input('price_group', '');
|
|
$product_types = request()->get('product_types', []);
|
|
|
|
$search_fields = request()->get('search_fields', ['name', 'sku']);
|
|
if (in_array('sku', $search_fields)) {
|
|
$search_fields[] = 'sub_sku';
|
|
}
|
|
|
|
$result = $this->productUtil->filterProduct($business_id, $search_term, $location_id, $not_for_selling, $price_group_id, $product_types, $search_fields, $check_qty);
|
|
|
|
return json_encode($result);
|
|
}
|
|
}
|
|
|
|
public function getVarationDetail($variation_id, $location_id){
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$product = $this->productUtil->getDetailsFromVariation($variation_id, $business_id, $location_id, null);
|
|
return $product;
|
|
}
|
|
|
|
/**
|
|
* Retrieves products list without variation list
|
|
*
|
|
* @param string $q
|
|
* @param bool $check_qty
|
|
* @return JSON
|
|
*/
|
|
public function getProductsWithoutVariations()
|
|
{
|
|
if (request()->ajax()) {
|
|
$term = request()->input('term', '');
|
|
//$location_id = request()->input('location_id', '');
|
|
|
|
//$check_qty = request()->input('check_qty', false);
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
$products = Product::join('variations', 'products.id', '=', 'variations.product_id')
|
|
->where('products.business_id', $business_id)
|
|
->where('products.type', '!=', 'modifier');
|
|
|
|
//Include search
|
|
if (! empty($term)) {
|
|
$products->where(function ($query) use ($term) {
|
|
$query->where('products.name', 'like', '%'.$term.'%');
|
|
$query->orWhere('sku', 'like', '%'.$term.'%');
|
|
$query->orWhere('sub_sku', 'like', '%'.$term.'%');
|
|
});
|
|
}
|
|
|
|
//Include check for quantity
|
|
// if($check_qty){
|
|
// $products->where('VLD.qty_available', '>', 0);
|
|
// }
|
|
|
|
$products = $products->groupBy('products.id')
|
|
->select(
|
|
'products.id as product_id',
|
|
'products.name',
|
|
'products.type',
|
|
'products.enable_stock',
|
|
'products.sku',
|
|
'products.id as id',
|
|
DB::raw('CONCAT(products.name, " - ", products.sku) as text')
|
|
)
|
|
->orderBy('products.name')
|
|
->get();
|
|
|
|
return json_encode($products);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if product sku already exists.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function checkProductSku(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$sku = $request->input('sku');
|
|
$product_id = $request->input('product_id');
|
|
|
|
//check in products table
|
|
$query = Product::where('business_id', $business_id)
|
|
->where('sku', $sku);
|
|
if (! empty($product_id)) {
|
|
$query->where('id', '!=', $product_id);
|
|
}
|
|
$count = $query->count();
|
|
|
|
//check in variation table if $count = 0
|
|
if ($count == 0) {
|
|
$query2 = Variation::where('sub_sku', $sku)
|
|
->join('products', 'variations.product_id', '=', 'products.id')
|
|
->where('business_id', $business_id);
|
|
|
|
if (! empty($product_id)) {
|
|
$query2->where('product_id', '!=', $product_id);
|
|
}
|
|
|
|
if (! empty($request->input('variation_id'))) {
|
|
$query2->where('variations.id', '!=', $request->input('variation_id'));
|
|
}
|
|
$count = $query2->count();
|
|
}
|
|
if ($count == 0) {
|
|
echo 'true';
|
|
exit;
|
|
} else {
|
|
echo 'false';
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if product name already exists.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function checkProductName(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$name = $request->input('name');
|
|
$product_id = $request->input('product_id');
|
|
|
|
//check in products table
|
|
$query = Product::where('business_id', $business_id)
|
|
->where('name', $name);
|
|
if (! empty($product_id)) {
|
|
$query->where('id', '!=', $product_id);
|
|
}
|
|
$count = $query->count();
|
|
|
|
//check in variation table if $count = 0
|
|
|
|
if ($count == 0) {
|
|
echo 'true';
|
|
exit;
|
|
} else {
|
|
echo 'false';
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates multiple variation skus
|
|
*/
|
|
public function validateVaritionSkus(Request $request)
|
|
{
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$all_skus = $request->input('skus');
|
|
|
|
$skus = [];
|
|
foreach ($all_skus as $key => $value) {
|
|
$skus[] = $value['sku'];
|
|
}
|
|
|
|
//check product table is sku present
|
|
$product = Product::where('business_id', $business_id)
|
|
->whereIn('sku', $skus)
|
|
->first();
|
|
|
|
if (! empty($product)) {
|
|
return ['success' => 0, 'sku' => $product->sku];
|
|
}
|
|
|
|
foreach ($all_skus as $key => $value) {
|
|
$query = Variation::where('sub_sku', $value['sku'])
|
|
->join('products', 'variations.product_id', '=', 'products.id')
|
|
->where('business_id', $business_id);
|
|
|
|
if (! empty($value['variation_id'])) {
|
|
$query->where('variations.id', '!=', $value['variation_id']);
|
|
}
|
|
$variation = $query->first();
|
|
|
|
if (! empty($variation)) {
|
|
return ['success' => 0, 'sku' => $variation->sub_sku];
|
|
}
|
|
}
|
|
|
|
return ['success' => 1];
|
|
}
|
|
|
|
/**
|
|
* Loads quick add product modal.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function quickAdd()
|
|
{
|
|
if (! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$product_name = ! empty(request()->input('product_name')) ? request()->input('product_name') : '';
|
|
|
|
$product_for = ! empty(request()->input('product_for')) ? request()->input('product_for') : null;
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$categories = Category::forDropdown($business_id, 'product');
|
|
$brands = Brands::forDropdown($business_id);
|
|
$units = Unit::forDropdown($business_id, true);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, true, true);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
$tax_attributes = $tax_dropdown['attributes'];
|
|
|
|
$barcode_types = $this->barcode_types;
|
|
|
|
$default_profit_percent = Business::where('id', $business_id)->value('default_profit_percent');
|
|
|
|
$locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
$enable_expiry = request()->session()->get('business.enable_product_expiry');
|
|
$enable_lot = request()->session()->get('business.enable_lot_number');
|
|
|
|
$module_form_parts = $this->moduleUtil->getModuleData('product_form_part');
|
|
|
|
//Get all business locations
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
$common_settings = session()->get('business.common_settings');
|
|
$warranties = Warranty::forDropdown($business_id);
|
|
|
|
return view('product.partials.quick_add_product')
|
|
->with(compact('categories', 'brands', 'units', 'taxes', 'barcode_types', 'default_profit_percent', 'tax_attributes', 'product_name', 'locations', 'product_for', 'enable_expiry', 'enable_lot', 'module_form_parts', 'business_locations', 'common_settings', 'warranties'));
|
|
}
|
|
|
|
/**
|
|
* Store a newly created resource in storage.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function saveQuickProduct(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
// check for products quota
|
|
if(! $this->moduleUtil->isQuotaAvailable('products', $business_id)) {
|
|
return $output = ['success' => 0,
|
|
'msg' => __('superadmin::lang.max_products'),
|
|
];
|
|
}
|
|
|
|
try {
|
|
$form_fields = ['name', 'brand_id', 'unit_id', 'category_id', 'tax', 'barcode_type', 'tax_type', 'sku', 'manual_id',
|
|
'alert_quantity', 'type', 'sub_unit_ids', 'sub_category_id', 'weight', 'product_description', 'product_custom_field1', 'product_custom_field2', 'product_custom_field3', 'product_custom_field4', 'product_custom_field5', 'product_custom_field6', 'product_custom_field7', 'product_custom_field8', 'product_custom_field9', 'product_custom_field10', 'product_custom_field11', 'product_custom_field12', 'product_custom_field13', 'product_custom_field14', 'product_custom_field15', 'product_custom_field16', 'product_custom_field17', 'product_custom_field18', 'product_custom_field19', 'product_custom_field20'];
|
|
|
|
$module_form_fields = $this->moduleUtil->getModuleData('product_form_fields');
|
|
if (! empty($module_form_fields)) {
|
|
foreach ($module_form_fields as $key => $value) {
|
|
if (! empty($value) && is_array($value)) {
|
|
$form_fields = array_merge($form_fields, $value);
|
|
}
|
|
}
|
|
}
|
|
$product_details = $request->only($form_fields);
|
|
|
|
$product_details['type'] = empty($product_details['type']) ? 'single' : $product_details['type'];
|
|
$product_details['business_id'] = $business_id;
|
|
$product_details['created_by'] = $request->session()->get('user.id');
|
|
if (! empty($request->input('enable_stock')) && $request->input('enable_stock') == 1) {
|
|
$product_details['enable_stock'] = 1;
|
|
//TODO: Save total qty
|
|
//$product_details['total_qty_available'] = 0;
|
|
}
|
|
if (! empty($request->input('not_for_selling')) && $request->input('not_for_selling') == 1) {
|
|
$product_details['not_for_selling'] = 1;
|
|
}
|
|
if (empty($product_details['sku'])) {
|
|
$product_details['sku'] = ' ';
|
|
}
|
|
|
|
if (! empty($product_details['alert_quantity'])) {
|
|
$product_details['alert_quantity'] = $this->productUtil->num_uf($product_details['alert_quantity']);
|
|
}
|
|
|
|
$expiry_enabled = $request->session()->get('business.enable_product_expiry');
|
|
if (! empty($request->input('expiry_period_type')) && ! empty($request->input('expiry_period')) && ! empty($expiry_enabled)) {
|
|
$product_details['expiry_period_type'] = $request->input('expiry_period_type');
|
|
$product_details['expiry_period'] = $this->productUtil->num_uf($request->input('expiry_period'));
|
|
}
|
|
|
|
if (! empty($request->input('enable_sr_no')) && $request->input('enable_sr_no') == 1) {
|
|
$product_details['enable_sr_no'] = 1;
|
|
}
|
|
|
|
$product_details['warranty_id'] = ! empty($request->input('warranty_id')) ? $request->input('warranty_id') : null;
|
|
|
|
DB::beginTransaction();
|
|
|
|
$product = Product::create($product_details);
|
|
event(new ProductsCreatedOrModified($product_details, 'added'));
|
|
|
|
$sku = $this->productUtil->generateProductSku($product->id);
|
|
$product->sku = $sku;
|
|
$product->save();
|
|
|
|
$this->productUtil->createSingleProductVariation(
|
|
$product->id,
|
|
$product->sku,
|
|
$request->input('single_dpp'),
|
|
$request->input('single_dpp_inc_tax'),
|
|
$request->input('profit_percent'),
|
|
$request->input('single_dsp'),
|
|
$request->input('single_dsp_inc_tax')
|
|
);
|
|
|
|
if ($product->enable_stock == 1 && ! empty($request->input('opening_stock'))) {
|
|
$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();
|
|
|
|
$this->productUtil->addSingleProductOpeningStock($business_id, $product, $request->input('opening_stock'), $transaction_date, $user_id);
|
|
}
|
|
|
|
//Add product locations
|
|
$product_locations = $request->input('product_locations');
|
|
if (! empty($product_locations)) {
|
|
$product->product_locations()->sync($product_locations);
|
|
}
|
|
|
|
DB::commit();
|
|
|
|
$output = ['success' => 1,
|
|
'msg' => __('product.product_added_success'),
|
|
'product' => $product,
|
|
'variation' => $product->variations->first(),
|
|
'locations' => $product_locations,
|
|
];
|
|
} 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;
|
|
}
|
|
|
|
/**
|
|
* Display the specified resource.
|
|
*
|
|
* @param \App\Product $product
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function view($id)
|
|
{
|
|
if (! auth()->user()->can('product.view')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['brand', 'unit', 'category', 'sub_category', 'product_tax', 'variations', 'variations.product_variation', 'variations.group_prices', 'variations.media', 'product_locations', 'warranty', 'media'])
|
|
->findOrFail($id);
|
|
|
|
$price_groups = SellingPriceGroup::where('business_id', $business_id)->active()->pluck('name', 'id');
|
|
|
|
$allowed_group_prices = [];
|
|
foreach ($price_groups as $key => $value) {
|
|
if (auth()->user()->can('selling_price_group.'.$key)) {
|
|
$allowed_group_prices[$key] = $value;
|
|
}
|
|
}
|
|
|
|
$group_price_details = [];
|
|
|
|
foreach ($product->variations as $variation) {
|
|
foreach ($variation->group_prices as $group_price) {
|
|
$group_price_details[$variation->id][$group_price->price_group_id] = ['price' => $group_price->price_inc_tax, 'price_type' => $group_price->price_type, 'calculated_price' => $group_price->calculated_price];
|
|
}
|
|
}
|
|
|
|
$rack_details = $this->productUtil->getRackDetails($business_id, $id, true);
|
|
|
|
$combo_variations = [];
|
|
if ($product->type == 'combo') {
|
|
$combo_variations = $this->productUtil->__getComboProductDetails($product['variations'][0]->combo_variations, $business_id);
|
|
}
|
|
|
|
return view('product.view-modal')->with(compact(
|
|
'product',
|
|
'rack_details',
|
|
'allowed_group_prices',
|
|
'group_price_details',
|
|
'combo_variations'
|
|
));
|
|
} catch (\Exception $e) {
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mass deletes products.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function massDestroy(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.delete')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
try {
|
|
$purchase_exist = false;
|
|
|
|
if (! empty($request->input('selected_rows'))) {
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
$selected_rows = explode(',', $request->input('selected_rows'));
|
|
|
|
$products = Product::where('business_id', $business_id)
|
|
->whereIn('id', $selected_rows)
|
|
->with(['purchase_lines', 'variations'])
|
|
->get();
|
|
$deletable_products = [];
|
|
|
|
$is_mfg_installed = $this->moduleUtil->isModuleInstalled('Manufacturing');
|
|
|
|
DB::beginTransaction();
|
|
|
|
foreach ($products as $product) {
|
|
$can_be_deleted = true;
|
|
//Check if product is added as an ingredient of any recipe
|
|
if ($is_mfg_installed) {
|
|
$variation_ids = $product->variations->pluck('id');
|
|
|
|
$exists_as_ingredient = \Modules\Manufacturing\Entities\MfgRecipeIngredient::whereIn('variation_id', $variation_ids)
|
|
->exists();
|
|
$can_be_deleted = ! $exists_as_ingredient;
|
|
}
|
|
|
|
//Delete if no purchase found
|
|
if (empty($product->purchase_lines->toArray()) && $can_be_deleted) {
|
|
//Delete variation location details
|
|
VariationLocationDetails::where('product_id', $product->id)
|
|
->delete();
|
|
$product->delete();
|
|
event(new ProductsCreatedOrModified($product, 'Deleted'));
|
|
} else {
|
|
$purchase_exist = true;
|
|
}
|
|
}
|
|
|
|
DB::commit();
|
|
}
|
|
|
|
if (! $purchase_exist) {
|
|
$output = ['success' => 1,
|
|
'msg' => __('lang_v1.deleted_success'),
|
|
];
|
|
} else {
|
|
$output = ['success' => 0,
|
|
'msg' => __('lang_v1.products_could_not_be_deleted'),
|
|
];
|
|
}
|
|
} 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 redirect()->back()->with(['status' => $output]);
|
|
}
|
|
|
|
/**
|
|
* Shows form to add selling price group prices for a product.
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function addSellingPrices($id)
|
|
{
|
|
if (! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['variations', 'variations.group_prices', 'variations.product_variation'])
|
|
->findOrFail($id);
|
|
|
|
$price_groups = SellingPriceGroup::where('business_id', $business_id)
|
|
->active()
|
|
->get();
|
|
$variation_prices = [];
|
|
foreach ($product->variations as $variation) {
|
|
foreach ($variation->group_prices as $group_price) {
|
|
$variation_prices[$variation->id][$group_price->price_group_id] = ['price' => $group_price->price_inc_tax, 'price_type' => $group_price->price_type];
|
|
}
|
|
}
|
|
|
|
return view('product.add-selling-prices')->with(compact('product', 'price_groups', 'variation_prices'));
|
|
}
|
|
|
|
/**
|
|
* Saves selling price group prices for a product.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function saveSellingPrices(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.create')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['variations'])
|
|
->findOrFail($request->input('product_id'));
|
|
DB::beginTransaction();
|
|
foreach ($product->variations as $variation) {
|
|
$variation_group_prices = [];
|
|
foreach ($request->input('group_prices') as $key => $value) {
|
|
if (isset($value[$variation->id])) {
|
|
$variation_group_price =
|
|
VariationGroupPrice::where('variation_id', $variation->id)
|
|
->where('price_group_id', $key)
|
|
->first();
|
|
if (empty($variation_group_price)) {
|
|
$variation_group_price = new VariationGroupPrice([
|
|
'variation_id' => $variation->id,
|
|
'price_group_id' => $key,
|
|
]);
|
|
}
|
|
|
|
$variation_group_price->price_inc_tax = $this->productUtil->num_uf($value[$variation->id]['price']);
|
|
$variation_group_price->price_type = $value[$variation->id]['price_type'];
|
|
$variation_group_prices[] = $variation_group_price;
|
|
}
|
|
}
|
|
|
|
if (! empty($variation_group_prices)) {
|
|
$variation->group_prices()->saveMany($variation_group_prices);
|
|
}
|
|
}
|
|
//Update product updated_at timestamp
|
|
$product->touch();
|
|
|
|
DB::commit();
|
|
$output = ['success' => 1,
|
|
'msg' => __('lang_v1.updated_success'),
|
|
];
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => 0,
|
|
'msg' => __('messages.something_went_wrong'),
|
|
];
|
|
}
|
|
|
|
if ($request->input('submit_type') == 'submit_n_add_opening_stock') {
|
|
return redirect()->action([\App\Http\Controllers\OpeningStockController::class, 'add'],
|
|
['product_id' => $product->id]
|
|
);
|
|
} elseif ($request->input('submit_type') == 'save_n_add_another') {
|
|
return redirect()->action([\App\Http\Controllers\ProductController::class, 'create']
|
|
)->with('status', $output);
|
|
}
|
|
|
|
return redirect('products')->with('status', $output);
|
|
}
|
|
|
|
public function viewGroupPrice($id)
|
|
{
|
|
if (! auth()->user()->can('product.view')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->where('id', $id)
|
|
->with(['variations', 'variations.product_variation', 'variations.group_prices'])
|
|
->first();
|
|
|
|
$price_groups = SellingPriceGroup::where('business_id', $business_id)->active()->pluck('name', 'id');
|
|
|
|
$allowed_group_prices = [];
|
|
foreach ($price_groups as $key => $value) {
|
|
if (auth()->user()->can('selling_price_group.'.$key)) {
|
|
$allowed_group_prices[$key] = $value;
|
|
}
|
|
}
|
|
|
|
$group_price_details = [];
|
|
|
|
foreach ($product->variations as $variation) {
|
|
foreach ($variation->group_prices as $group_price) {
|
|
$group_price_details[$variation->id][$group_price->price_group_id] = $group_price->price_inc_tax;
|
|
}
|
|
}
|
|
|
|
return view('product.view-product-group-prices')->with(compact('product', 'allowed_group_prices', 'group_price_details'));
|
|
}
|
|
|
|
/**
|
|
* Mass deactivates products.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function massDeactivate(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
try {
|
|
if (! empty($request->input('selected_products'))) {
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
$selected_products = explode(',', $request->input('selected_products'));
|
|
|
|
DB::beginTransaction();
|
|
|
|
$products = Product::where('business_id', $business_id)
|
|
->whereIn('id', $selected_products)
|
|
->update(['is_inactive' => 1]);
|
|
|
|
DB::commit();
|
|
}
|
|
|
|
$output = ['success' => 1,
|
|
'msg' => __('lang_v1.products_deactivated_success'),
|
|
];
|
|
} 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;
|
|
}
|
|
|
|
/**
|
|
* Activates the specified resource from storage.
|
|
*
|
|
* @param \App\Product $product
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function activate($id)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
if (request()->ajax()) {
|
|
try {
|
|
$business_id = request()->session()->get('user.business_id');
|
|
$product = Product::where('id', $id)
|
|
->where('business_id', $business_id)
|
|
->update(['is_inactive' => 0]);
|
|
|
|
$output = ['success' => true,
|
|
'msg' => __('lang_v1.updated_success'),
|
|
];
|
|
} catch (\Exception $e) {
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => false,
|
|
'msg' => __('messages.something_went_wrong'),
|
|
];
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes a media file from storage and database.
|
|
*
|
|
* @param int $media_id
|
|
* @return json
|
|
*/
|
|
public function deleteMedia($media_id)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
if (request()->ajax()) {
|
|
try {
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
Media::deleteMedia($business_id, $media_id);
|
|
|
|
$output = ['success' => true,
|
|
'msg' => __('lang_v1.file_deleted_successfully'),
|
|
];
|
|
} catch (\Exception $e) {
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
$output = ['success' => false,
|
|
'msg' => __('messages.something_went_wrong'),
|
|
];
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|
|
|
|
public function getProductsApi($id = null)
|
|
{
|
|
try {
|
|
$api_token = request()->header('API-TOKEN');
|
|
$filter_string = request()->header('FILTERS');
|
|
$order_by = request()->header('ORDER-BY');
|
|
|
|
parse_str($filter_string, $filters);
|
|
|
|
$api_settings = $this->moduleUtil->getApiSettings($api_token);
|
|
|
|
$limit = ! empty(request()->input('limit')) ? request()->input('limit') : 10;
|
|
|
|
$location_id = $api_settings->location_id;
|
|
|
|
$query = Product::where('business_id', $api_settings->business_id)
|
|
->active()
|
|
->with(['brand', 'unit', 'category', 'sub_category',
|
|
'product_variations', 'product_variations.variations', 'product_variations.variations.media',
|
|
'product_variations.variations.variation_location_details' => function ($q) use ($location_id) {
|
|
$q->where('location_id', $location_id);
|
|
}, ]);
|
|
|
|
if (! empty($filters['categories'])) {
|
|
$query->whereIn('category_id', $filters['categories']);
|
|
}
|
|
|
|
if (! empty($filters['brands'])) {
|
|
$query->whereIn('brand_id', $filters['brands']);
|
|
}
|
|
|
|
if (! empty($filters['category'])) {
|
|
$query->where('category_id', $filters['category']);
|
|
}
|
|
|
|
if (! empty($filters['sub_category'])) {
|
|
$query->where('sub_category_id', $filters['sub_category']);
|
|
}
|
|
|
|
if ($order_by == 'name') {
|
|
$query->orderBy('name', 'asc');
|
|
} elseif ($order_by == 'date') {
|
|
$query->orderBy('created_at', 'desc');
|
|
}
|
|
|
|
if (empty($id)) {
|
|
$products = $query->paginate($limit);
|
|
} else {
|
|
$products = $query->find($id);
|
|
}
|
|
} catch (\Exception $e) {
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
return $this->respondWentWrong($e);
|
|
}
|
|
|
|
return $this->respond($products);
|
|
}
|
|
|
|
public function getVariationsApi()
|
|
{
|
|
try {
|
|
$api_token = request()->header('API-TOKEN');
|
|
$variations_string = request()->header('VARIATIONS');
|
|
|
|
if (is_numeric($variations_string)) {
|
|
$variation_ids = intval($variations_string);
|
|
} else {
|
|
parse_str($variations_string, $variation_ids);
|
|
}
|
|
|
|
$api_settings = $this->moduleUtil->getApiSettings($api_token);
|
|
$location_id = $api_settings->location_id;
|
|
$business_id = $api_settings->business_id;
|
|
|
|
$query = Variation::with([
|
|
'product_variation',
|
|
'product' => function ($q) use ($business_id) {
|
|
$q->where('business_id', $business_id);
|
|
},
|
|
'product.unit',
|
|
'variation_location_details' => function ($q) use ($location_id) {
|
|
$q->where('location_id', $location_id);
|
|
},
|
|
]);
|
|
|
|
$variations = is_array($variation_ids) ? $query->whereIn('id', $variation_ids)->get() : $query->where('id', $variation_ids)->first();
|
|
} catch (\Exception $e) {
|
|
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
|
|
|
|
return $this->respondWentWrong($e);
|
|
}
|
|
|
|
return $this->respond($variations);
|
|
}
|
|
|
|
/**
|
|
* Shows form to edit multiple products at once.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function bulkEdit(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$selected_products_string = $request->input('selected_products');
|
|
if (! empty($selected_products_string)) {
|
|
$selected_products = explode(',', $selected_products_string);
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
$products = Product::where('business_id', $business_id)
|
|
->whereIn('id', $selected_products)
|
|
->with(['variations', 'variations.product_variation', 'variations.group_prices', 'product_locations'])
|
|
->get();
|
|
|
|
$all_categories = Category::catAndSubCategories($business_id);
|
|
|
|
$categories = [];
|
|
$sub_categories = [];
|
|
foreach ($all_categories as $category) {
|
|
$categories[$category['id']] = $category['name'];
|
|
|
|
if (! empty($category['sub_categories'])) {
|
|
foreach ($category['sub_categories'] as $sub_category) {
|
|
$sub_categories[$category['id']][$sub_category['id']] = $sub_category['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
$brands = Brands::forDropdown($business_id);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, true, true);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
$tax_attributes = $tax_dropdown['attributes'];
|
|
|
|
$price_groups = SellingPriceGroup::where('business_id', $business_id)->active()->pluck('name', 'id');
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
return view('product.bulk-edit')->with(compact(
|
|
'products',
|
|
'categories',
|
|
'brands',
|
|
'taxes',
|
|
'tax_attributes',
|
|
'sub_categories',
|
|
'price_groups',
|
|
'business_locations'
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates multiple products at once.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function bulkUpdate(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$products = $request->input('products');
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
DB::beginTransaction();
|
|
foreach ($products as $id => $product_data) {
|
|
$update_data = [
|
|
'category_id' => $product_data['category_id'],
|
|
'sub_category_id' => $product_data['sub_category_id'],
|
|
'brand_id' => $product_data['brand_id'],
|
|
'tax' => $product_data['tax'],
|
|
];
|
|
|
|
//Update product
|
|
$product = Product::where('business_id', $business_id)
|
|
->findOrFail($id);
|
|
|
|
$product->update($update_data);
|
|
|
|
//Add product locations
|
|
$product_locations = ! empty($product_data['product_locations']) ?
|
|
$product_data['product_locations'] : [];
|
|
$product->product_locations()->sync($product_locations);
|
|
|
|
$variations_data = [];
|
|
|
|
//Format variations data
|
|
foreach ($product_data['variations'] as $key => $value) {
|
|
$variation = Variation::where('product_id', $product->id)->findOrFail($key);
|
|
$variation->default_purchase_price = $this->productUtil->num_uf($value['default_purchase_price']);
|
|
$variation->dpp_inc_tax = $this->productUtil->num_uf($value['dpp_inc_tax']);
|
|
$variation->profit_percent = $this->productUtil->num_uf($value['profit_percent']);
|
|
$variation->default_sell_price = $this->productUtil->num_uf($value['default_sell_price']);
|
|
$variation->sell_price_inc_tax = $this->productUtil->num_uf($value['sell_price_inc_tax']);
|
|
$variations_data[] = $variation;
|
|
|
|
//Update price groups
|
|
if (! empty($value['group_prices'])) {
|
|
foreach ($value['group_prices'] as $k => $v) {
|
|
VariationGroupPrice::updateOrCreate(
|
|
['price_group_id' => $k, 'variation_id' => $variation->id],
|
|
['price_inc_tax' => $this->productUtil->num_uf($v)]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
$product->variations()->saveMany($variations_data);
|
|
}
|
|
DB::commit();
|
|
|
|
$output = ['success' => 1,
|
|
'msg' => __('lang_v1.updated_success'),
|
|
];
|
|
} 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 redirect('products')->with('status', $output);
|
|
}
|
|
|
|
/**
|
|
* Adds product row to edit in bulk edit product form
|
|
*
|
|
* @param int $product_id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getProductToEdit($product_id)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['variations', 'variations.product_variation', 'variations.group_prices'])
|
|
->findOrFail($product_id);
|
|
$all_categories = Category::catAndSubCategories($business_id);
|
|
|
|
$categories = [];
|
|
$sub_categories = [];
|
|
foreach ($all_categories as $category) {
|
|
$categories[$category['id']] = $category['name'];
|
|
|
|
if (! empty($category['sub_categories'])) {
|
|
foreach ($category['sub_categories'] as $sub_category) {
|
|
$sub_categories[$category['id']][$sub_category['id']] = $sub_category['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
$brands = Brands::forDropdown($business_id);
|
|
|
|
$tax_dropdown = TaxRate::forBusinessDropdown($business_id, true, true);
|
|
$taxes = $tax_dropdown['tax_rates'];
|
|
$tax_attributes = $tax_dropdown['attributes'];
|
|
|
|
$price_groups = SellingPriceGroup::where('business_id', $business_id)->active()->pluck('name', 'id');
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
return view('product.partials.bulk_edit_product_row')->with(compact(
|
|
'product',
|
|
'categories',
|
|
'brands',
|
|
'taxes',
|
|
'tax_attributes',
|
|
'sub_categories',
|
|
'price_groups',
|
|
'business_locations'
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Gets the sub units for the given unit.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @param int $unit_id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function getSubUnits(Request $request)
|
|
{
|
|
if (! empty($request->input('unit_id'))) {
|
|
$unit_id = $request->input('unit_id');
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$sub_units = $this->productUtil->getSubUnits($business_id, $unit_id, true);
|
|
|
|
//$html = '<option value="">' . __('lang_v1.all') . '</option>';
|
|
$html = '';
|
|
if (! empty($sub_units)) {
|
|
foreach ($sub_units as $id => $sub_unit) {
|
|
$html .= '<option value="'.$id.'">'.$sub_unit['name'].'</option>';
|
|
}
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
}
|
|
|
|
public function updateProductLocation(Request $request)
|
|
{
|
|
if (! auth()->user()->can('product.update')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
try {
|
|
$selected_products = $request->input('products');
|
|
$update_type = $request->input('update_type');
|
|
$location_ids = $request->input('product_location');
|
|
|
|
$business_id = $request->session()->get('user.business_id');
|
|
|
|
$product_ids = explode(',', $selected_products);
|
|
|
|
$products = Product::where('business_id', $business_id)
|
|
->whereIn('id', $product_ids)
|
|
->with(['product_locations'])
|
|
->get();
|
|
DB::beginTransaction();
|
|
foreach ($products as $product) {
|
|
$product_locations = $product->product_locations->pluck('id')->toArray();
|
|
|
|
if ($update_type == 'add') {
|
|
$product_locations = array_unique(array_merge($location_ids, $product_locations));
|
|
$product->product_locations()->sync($product_locations);
|
|
} elseif ($update_type == 'remove') {
|
|
foreach ($product_locations as $key => $value) {
|
|
if (in_array($value, $location_ids)) {
|
|
unset($product_locations[$key]);
|
|
}
|
|
}
|
|
$product->product_locations()->sync($product_locations);
|
|
}
|
|
}
|
|
DB::commit();
|
|
$output = ['success' => 1,
|
|
'msg' => __('lang_v1.updated_success'),
|
|
];
|
|
} 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;
|
|
}
|
|
|
|
public function productStockHistory($id)
|
|
{
|
|
if (! auth()->user()->can('product.view')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = request()->session()->get('user.business_id');
|
|
|
|
if (request()->ajax()) {
|
|
|
|
//for ajax call $id is variation id else it is product id
|
|
$stock_details = $this->productUtil->getVariationStockDetails($business_id, $id, request()->input('location_id'));
|
|
$stock_history = $this->productUtil->getVariationStockHistory($business_id, $id, request()->input('location_id'));
|
|
|
|
//if mismach found update stock in variation location details
|
|
if (isset($stock_history[0]) && (float) $stock_details['current_stock'] != (float) $stock_history[0]['stock']) {
|
|
VariationLocationDetails::where('variation_id',
|
|
$id)
|
|
->where('location_id', request()->input('location_id'))
|
|
->update(['qty_available' => $stock_history[0]['stock']]);
|
|
$stock_details['current_stock'] = $stock_history[0]['stock'];
|
|
}
|
|
|
|
return view('product.stock_history_details')
|
|
->with(compact('stock_details', 'stock_history'));
|
|
}
|
|
|
|
$product = Product::where('business_id', $business_id)
|
|
->with(['variations', 'variations.product_variation'])
|
|
->findOrFail($id);
|
|
|
|
//Get all business locations
|
|
$business_locations = BusinessLocation::forDropdown($business_id);
|
|
|
|
return view('product.stock_history')
|
|
->with(compact('product', 'business_locations'));
|
|
}
|
|
|
|
/**
|
|
* Toggle WooComerce sync
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function toggleWooCommerceSync(Request $request)
|
|
{
|
|
try {
|
|
$selected_products = $request->input('woocommerce_products_sync');
|
|
$woocommerce_disable_sync = $request->input('woocommerce_disable_sync');
|
|
|
|
$business_id = $request->session()->get('user.business_id');
|
|
$product_ids = explode(',', $selected_products);
|
|
|
|
DB::beginTransaction();
|
|
if ($this->moduleUtil->isModuleInstalled('Woocommerce')) {
|
|
Product::where('business_id', $business_id)
|
|
->whereIn('id', $product_ids)
|
|
->update(['woocommerce_disable_sync' => $woocommerce_disable_sync]);
|
|
}
|
|
DB::commit();
|
|
$output = [
|
|
'success' => 1,
|
|
'msg' => __('lang_v1.success'),
|
|
];
|
|
} 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;
|
|
}
|
|
|
|
/**
|
|
* Function to download all products in xlsx format
|
|
*/
|
|
public function downloadExcel()
|
|
{
|
|
$is_admin = $this->productUtil->is_admin(auth()->user());
|
|
if (! $is_admin) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$filename = 'products-export-'.\Carbon::now()->format('Y-m-d').'.xlsx';
|
|
|
|
return Excel::download(new ProductsExport, $filename);
|
|
}
|
|
}
|