Fixes #1044 - adds suppliers and image to accessories (#4266)

* Ignore accesories uploads

* API: Allow searching accessories by supplier id

* Adds suppliers and image upload to accessories

* Allow sorting by counts for suppliers

* Validate supplier image uploads

* Remove purchase_date from protected accessory array, it was converting it to datetime in datepicker
This commit is contained in:
snipe 2017-10-19 16:25:24 -07:00 committed by GitHub
parent 1f247ff541
commit 4215a3257b
17 changed files with 209 additions and 22 deletions

1
.gitignore vendored
View file

@ -27,6 +27,7 @@ public/uploads/logo.png
public/uploads/logo.svg public/uploads/logo.svg
public/uploads/models/* public/uploads/models/*
public/uploads/suppliers/* public/uploads/suppliers/*
public/uploads/accessories/*
public/uploads/users/* public/uploads/users/*
storage/app/private_uploads/users/* storage/app/private_uploads/users/*
storage/debugbar/ storage/debugbar/

View file

@ -18,6 +18,8 @@ use Illuminate\Http\Request;
use Slack; use Slack;
use Str; use Str;
use View; use View;
use Image;
use App\Http\Requests\ImageUploadRequest;
/** This controller handles all actions related to Accessories for /** This controller handles all actions related to Accessories for
* the Snipe-IT Asset Management application. * the Snipe-IT Asset Management application.
@ -57,6 +59,7 @@ class AccessoriesController extends Controller
->with('item', new Accessory) ->with('item', new Accessory)
->with('category_list', Helper::categoryList('accessory')) ->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList()) ->with('company_list', Helper::companyList())
->with('supplier_list', Helper::suppliersList())
->with('location_list', Helper::locationsList()) ->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList()); ->with('manufacturer_list', Helper::manufacturerList());
} }
@ -68,7 +71,7 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>] * @author [A. Gianotto] [<snipe@snipe.net>]
* @return Redirect * @return Redirect
*/ */
public function store(Request $request) public function store(ImageUploadRequest $request)
{ {
$this->authorize(Accessory::class); $this->authorize(Accessory::class);
// create a new model instance // create a new model instance
@ -87,6 +90,28 @@ class AccessoriesController extends Controller
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost')); $accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
$accessory->qty = request('qty'); $accessory->qty = request('qty');
$accessory->user_id = Auth::user()->id; $accessory->user_id = Auth::user()->id;
$accessory->supplier_id = request('supplier_id');
if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$accessory->image = $file_name;
}
}
// Was the accessory created? // Was the accessory created?
if ($accessory->save()) { if ($accessory->save()) {
@ -116,6 +141,7 @@ class AccessoriesController extends Controller
->with('category_list', Helper::categoryList('accessory')) ->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList()) ->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList()) ->with('location_list', Helper::locationsList())
->with('supplier_list', Helper::suppliersList())
->with('manufacturer_list', Helper::manufacturerList()); ->with('manufacturer_list', Helper::manufacturerList());
} }
@ -127,7 +153,7 @@ class AccessoriesController extends Controller
* @param int $accessoryId * @param int $accessoryId
* @return Redirect * @return Redirect
*/ */
public function update(Request $request, $accessoryId = null) public function update(ImageUploadRequest $request, $accessoryId = null)
{ {
if (is_null($accessory = Accessory::find($accessoryId))) { if (is_null($accessory = Accessory::find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist')); return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
@ -144,11 +170,38 @@ class AccessoriesController extends Controller
$accessory->manufacturer_id = request('manufacturer_id'); $accessory->manufacturer_id = request('manufacturer_id');
$accessory->order_number = request('order_number'); $accessory->order_number = request('order_number');
$accessory->model_number = request('model_number'); $accessory->model_number = request('model_number');
$accessory->purchase_date = request('purchase_date'); $accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost'); $accessory->purchase_cost = request('purchase_cost');
$accessory->qty = request('qty'); $accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
// Was the accessory updated? if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
unlink($path.'/'.$accessory->image);
}
$accessory->image = $file_name;
}
}
// Was the accessory updated?
if ($accessory->save()) { if ($accessory->save()) {
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success')); return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
} }

View file

@ -38,6 +38,10 @@ class AccessoriesController extends Controller
$accessories->where('manufacturer_id','=',$request->input('manufacturer_id')); $accessories->where('manufacturer_id','=',$request->input('manufacturer_id'));
} }
if ($request->has('supplier_id')) {
$accessories->where('supplier_id','=',$request->input('supplier_id'));
}
$offset = $request->input('offset', 0); $offset = $request->input('offset', 0);
$limit = $request->input('limit', 50); $limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc'; $order = $request->input('order') === 'asc' ? 'asc' : 'desc';

View file

@ -20,11 +20,11 @@ class SuppliersController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
$this->authorize('view', Supplier::class); $this->authorize('view', Supplier::class);
$allowed_columns = ['id','name','address','phone','contact','fax','email']; $allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count'];
$suppliers = Supplier::select( $suppliers = Supplier::select(
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at') array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at')
)->withCount('assets')->withCount('licenses')->whereNull('deleted_at'); )->withCount('assets')->withCount('licenses')->withCount('accessories')->whereNull('deleted_at');
if ($request->has('search')) { if ($request->has('search')) {

View file

@ -13,6 +13,7 @@ use Str;
use View; use View;
use Auth; use Auth;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
@ -56,7 +57,7 @@ class SuppliersController extends Controller
* @param Request $request * @param Request $request
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function store(Request $request) public function store(ImageUploadRequest $request)
{ {
// Create a new supplier // Create a new supplier
$supplier = new Supplier; $supplier = new Supplier;
@ -135,7 +136,7 @@ class SuppliersController extends Controller
* @param int $supplierId * @param int $supplierId
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update($supplierId = null, Request $request) public function update($supplierId = null, ImageUploadRequest $request)
{ {
// Check if the supplier exists // Check if the supplier exists
if (is_null($supplier = Supplier::find($supplierId))) { if (is_null($supplier = Supplier::find($supplierId))) {
@ -158,18 +159,17 @@ class SuppliersController extends Controller
$supplier->url = $supplier->addhttp(request('url')); $supplier->url = $supplier->addhttp(request('url'));
$supplier->notes = request('notes'); $supplier->notes = request('notes');
if (Input::file('image')) { if (Input::file('image')) {
$image = $request->file('image'); $image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension(); $file_name = 'suppliers-'.str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/suppliers/'.$file_name); $path = public_path('uploads/suppliers/'.$file_name);
Image::make($image->getRealPath())->resize(300, null, function ($constraint) { Image::make($image->getRealPath())->resize(300, null, function ($constraint) {
$constraint->aspectRatio(); $constraint->aspectRatio();
$constraint->upsize(); $constraint->upsize();
})->save($path); })->save($path);
$supplier->image = $file_name; $supplier->image = $file_name;
} } elseif (request('image_delete') == 1) {
if (request('image_delete') == 1 && $request->file('image') == "") {
$supplier->image = null; $supplier->image = null;
} }

View file

@ -25,6 +25,7 @@ class AccessoriesTransformer
'name' => e($accessory->name), 'name' => e($accessory->name),
'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null, 'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null,
'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null, 'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null,
'supplier' => ($accessory->supplier) ? ['id' => $accessory->supplier->id,'name'=> e($accessory->supplier->name)] : null,
'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null, 'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null,
'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : null, 'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : null,
'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : null, 'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : null,
@ -35,6 +36,7 @@ class AccessoriesTransformer
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null, 'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null, 'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => $accessory->numRemaining(), 'remaining_qty' => $accessory->numRemaining(),
'image' => ($accessory->image) ? url('/').'/uploads/accessories/'.e($accessory->image) : null,
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'), 'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),

View file

@ -36,8 +36,9 @@ class SuppliersTransformer
'email' => ($supplier->email) ? e($supplier->email) : null, 'email' => ($supplier->email) ? e($supplier->email) : null,
'contact' => ($supplier->contact) ? e($supplier->contact) : null, 'contact' => ($supplier->contact) ? e($supplier->contact) : null,
'assets_count' => (int) $supplier->assets_count, 'assets_count' => (int) $supplier->assets_count,
'accessories_count' => (int) $supplier->accessories_count,
'licenses_count' => (int) $supplier->licenses_count, 'licenses_count' => (int) $supplier->licenses_count,
'image' => ($supplier->image) ? e($supplier->image) : null, 'image' => ($supplier->image) ? url('/').'/uploads/suppliers/'.e($supplier->image) : null,
'notes' => ($supplier->notes) ? e($supplier->notes) : null, 'notes' => ($supplier->notes) ? e($supplier->notes) : null,
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'), 'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),
@ -46,7 +47,7 @@ class SuppliersTransformer
$permissions_array['available_actions'] = [ $permissions_array['available_actions'] = [
'update' => Gate::allows('update', Supplier::class) ? true : false, 'update' => Gate::allows('update', Supplier::class) ? true : false,
'delete' => Gate::allows('delete', Supplier::class) ? true : false, 'delete' => (Gate::allows('delete', Supplier::class) && ($supplier->assets_count == 0) && ($supplier->licenses_count == 0) && ($supplier->accessories_count == 0)) ? true : false,
]; ];
$array += $permissions_array; $array += $permissions_array;

View file

@ -17,7 +17,7 @@ class Accessory extends SnipeModel
use Loggable, Presentable; use Loggable, Presentable;
use SoftDeletes; use SoftDeletes;
protected $dates = ['deleted_at', 'purchase_date']; protected $dates = ['deleted_at'];
protected $table = 'accessories'; protected $table = 'accessories';
protected $casts = [ protected $casts = [
'requestable' => 'boolean' 'requestable' => 'boolean'
@ -61,10 +61,19 @@ class Accessory extends SnipeModel
'purchase_date', 'purchase_date',
'model_number', 'model_number',
'manufacturer_id', 'manufacturer_id',
'supplier_id',
'image',
'qty', 'qty',
'requestable' 'requestable'
]; ];
public function supplier()
{
return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
}
public function setRequestableAttribute($value) public function setRequestableAttribute($value)
{ {
if ($value == '') { if ($value == '') {

View file

@ -68,6 +68,11 @@ class Supplier extends SnipeModel
return $this->hasMany('\App\Models\Asset', 'supplier_id'); return $this->hasMany('\App\Models\Asset', 'supplier_id');
} }
public function accessories()
{
return $this->hasMany('\App\Models\Accessory', 'supplier_id');
}
public function asset_maintenances() public function asset_maintenances()
{ {
return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id'); return $this->hasMany('\App\Models\AssetMaintenance', 'supplier_id');

View file

@ -31,6 +31,14 @@ class AccessoryPresenter extends Presenter
"switchable" => true, "switchable" => true,
"title" => trans('general.id'), "title" => trans('general.id'),
"visible" => false "visible" => false
],[
"field" => "image",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/hardware/table.image'),
"visible" => true,
"formatter" => "imageFormatter"
], [ ], [
"field" => "company", "field" => "company",
"searchable" => true, "searchable" => true,
@ -63,6 +71,14 @@ class AccessoryPresenter extends Presenter
"sortable" => true, "sortable" => true,
"title" => trans('general.manufacturer'), "title" => trans('general.manufacturer'),
"formatter" => "manufacturersLinkObjFormatter", "formatter" => "manufacturersLinkObjFormatter",
], [
"field" => "supplier",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('general.supplier'),
"visible" => false,
"formatter" => "suppliersLinkObjFormatter"
], [ ], [
"field" => "location", "field" => "location",
"searchable" => true, "searchable" => true,

View file

@ -24,7 +24,8 @@ $factory->state(App\Models\Accessory::class, 'apple-bt-keyboard', function ($fak
'category_id' => 8, 'category_id' => 8,
'manufacturer_id' => 1, 'manufacturer_id' => 1,
'qty' => 10, 'qty' => 10,
'min_amt' => 2 'min_amt' => 2,
'supplier_id' => rand(1,5)
]; ];
}); });
@ -36,7 +37,8 @@ $factory->state(App\Models\Accessory::class, 'apple-usb-keyboard', function ($fa
'category_id' => 8, 'category_id' => 8,
'manufacturer_id' => 1, 'manufacturer_id' => 1,
'qty' => 15, 'qty' => 15,
'min_amt' => 2 'min_amt' => 2,
'supplier_id' => rand(1,5)
]; ];
}); });
@ -48,7 +50,8 @@ $factory->state(App\Models\Accessory::class, 'apple-mouse', function ($faker) {
'category_id' => 9, 'category_id' => 9,
'manufacturer_id' => 1, 'manufacturer_id' => 1,
'qty' => 13, 'qty' => 13,
'min_amt' => 2 'min_amt' => 2,
'supplier_id' => rand(1,5)
]; ];
}); });
@ -56,7 +59,7 @@ $factory->state(App\Models\Accessory::class, 'apple-mouse', function ($faker) {
$factory->state(App\Models\Accessory::class, 'microsoft-mouse', function ($faker) { $factory->state(App\Models\Accessory::class, 'microsoft-mouse', function ($faker) {
return [ return [
'name' => 'Sculpt Comfort Mouse\'', 'name' => 'Sculpt Comfort Mouse',
'category_id' => 9, 'category_id' => 9,
'manufacturer_id' => 2, 'manufacturer_id' => 2,
'qty' => 13, 'qty' => 13,

View file

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddImageAndSupplierToAccessories extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accessories', function (Blueprint $table) {
$table->string('image')->nullable()->default(null);
$table->integer('supplier_id')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accessories', function (Blueprint $table) {
$table->dropColumn('image');
$table->dropColumn('supplier_id');
});
}
}

1
public/uploads/accessories/.gitignore vendored Executable file
View file

@ -0,0 +1 @@
!.gitignore

View file

View file

@ -12,6 +12,7 @@
@include ('partials.forms.edit.company') @include ('partials.forms.edit.company')
@include ('partials.forms.edit.name', ['translated_name' => trans('admin/accessories/general.accessory_name')]) @include ('partials.forms.edit.name', ['translated_name' => trans('admin/accessories/general.accessory_name')])
@include ('partials.forms.edit.category') @include ('partials.forms.edit.category')
@include ('partials.forms.edit.supplier')
@include ('partials.forms.edit.manufacturer') @include ('partials.forms.edit.manufacturer')
@include ('partials.forms.edit.location') @include ('partials.forms.edit.location')
@include ('partials.forms.edit.model_number') @include ('partials.forms.edit.model_number')
@ -21,4 +22,20 @@
@include ('partials.forms.edit.quantity') @include ('partials.forms.edit.quantity')
@include ('partials.forms.edit.minimum_quantity') @include ('partials.forms.edit.minimum_quantity')
<!-- Image -->
<div class="form-group {{ $errors->has('image') ? ' has-error' : '' }}">
{{ Form::label('image', trans('general.image_upload'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7">
@if (config('app.lock_passwords'))
<p class="help-block">{{ trans('general.lock_passwords') }}</p>
@else
{{ Form::file('image') }}
{!! $errors->first('image', '<span class="alert-msg">:message</span>') !!}
@endif
</div>
</div>
@stop @stop

View file

@ -30,14 +30,16 @@
<thead> <thead>
<tr> <tr>
<th data-sortable="true" data-field="id" data-visible="false">{{ trans('admin/suppliers/table.id') }}</th> <th data-sortable="true" data-field="id" data-visible="false">{{ trans('admin/suppliers/table.id') }}</th>
<th data-formatter="imageFormatter" data-sortable="true" data-field="image" data-visible="false" data-searchable="false">Image</th>
<th data-sortable="true" data-field="name" data-formatter="suppliersLinkFormatter">{{ trans('admin/suppliers/table.name') }}</th> <th data-sortable="true" data-field="name" data-formatter="suppliersLinkFormatter">{{ trans('admin/suppliers/table.name') }}</th>
<th data-sortable="true" data-field="address">{{ trans('admin/suppliers/table.address') }}</th> <th data-sortable="true" data-field="address">{{ trans('admin/suppliers/table.address') }}</th>
<th data-searchable="true" data-sortable="true" data-field="contact">{{ trans('admin/suppliers/table.contact') }}</th> <th data-searchable="true" data-sortable="true" data-field="contact">{{ trans('admin/suppliers/table.contact') }}</th>
<th data-searchable="true" data-sortable="true" data-field="email" data-formatter="emailFormatter">{{ trans('admin/suppliers/table.email') }}</th> <th data-searchable="true" data-sortable="true" data-field="email" data-formatter="emailFormatter">{{ trans('admin/suppliers/table.email') }}</th>
<th data-searchable="true" data-sortable="true" data-field="phone">{{ trans('admin/suppliers/table.phone') }}</th> <th data-searchable="true" data-sortable="true" data-field="phone">{{ trans('admin/suppliers/table.phone') }}</th>
<th data-searchable="true" data-sortable="true" data-field="fax" data-visible="false">{{ trans('admin/suppliers/table.fax') }}</th> <th data-searchable="true" data-sortable="true" data-field="fax" data-visible="false">{{ trans('admin/suppliers/table.fax') }}</th>
<th data-searchable="false" data-sortable="false" data-field="assets_count">{{ trans('admin/suppliers/table.assets') }}</th> <th data-searchable="false" data-sortable="true" data-field="assets_count">{{ trans('admin/suppliers/table.assets') }}</th>
<th data-searchable="false" data-sortable="false" data-field="licenses_count">{{ trans('admin/suppliers/table.licenses') }}</th> <th data-searchable="false" data-sortable="true" data-field="accessories_count">{{ trans('general.accessories') }}</th>
<th data-searchable="false" data-sortable="true" data-field="licenses_count">{{ trans('admin/suppliers/table.licenses') }}</th>
<th data-switchable="false" data-formatter="suppliersActionsFormatter" data-searchable="false" data-sortable="false" data-field="actions">{{ trans('table.actions') }}</th> <th data-switchable="false" data-formatter="suppliersActionsFormatter" data-searchable="false" data-sortable="false" data-field="actions">{{ trans('table.actions') }}</th>
</tr> </tr>
</thead> </thead>

View file

@ -137,6 +137,40 @@
<div class="row"> <div class="row">
<div class="col-md-9"> <div class="col-md-9">
<div class="box box-default">
<div class="box-header with-border">
<div class="box-heading">
<h3 class="box-title">Accessories</h3>
</div>
</div><!-- /.box-header -->
<div class="box-body">
<div class="table-responsive">
<table
name="suppliersAccessories"
id="table"
class="snipe-table"
data-url="{{ route('api.accessories.index', ['supplier_id' => $supplier->id]) }}"
data-cookie="true"
data-export-options='{"fileName": "testo"}'
data-click-to-select="true"
data-cookie-id-table="suppliersAccessories-{{ config('version.hash_version') }}">
<thead>
<tr>
<th class="col-md-4" data-field="name" data-formatter="accessoriesLinkFormatter">Name</th>
<th class="col-md-4" data-field="model_number">Model Number</th>
<th class="col-md-4" data-field="purchase_cost" data-footer-formatter="sumFormatter">Purchase_cost</th>
<th class="col-md-4" data-field="actions" data-formatter="accessoriesActionsFormatter">Actions</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<div class="box box-default"> <div class="box box-default">
@if ($supplier->id) @if ($supplier->id)
@ -239,3 +273,8 @@
</div> <!-- /.row--> </div> <!-- /.row-->
@stop @stop
@section('moar_scripts')
@include ('partials.bootstrap-table', [
'showFooter' => true,
])
@stop