17 changed files with 602 additions and 2 deletions
-
10app/Entities/Partners/Vendor.php
-
5app/Entities/Payments/Payment.php
-
100app/Http/Controllers/Partners/VendorsController.php
-
64app/Policies/Partners/VendorPolicy.php
-
1app/Providers/AuthServiceProvider.php
-
39config/simple-crud.php
-
11database/factories/VendorFactory.php
-
36database/migrations/2017_10_26_092017_create_vendors_table.php
-
1resources/lang/id/master.php
-
29resources/lang/id/vendor.php
-
60resources/views/vendors/forms.blade.php
-
67resources/views/vendors/index.blade.php
-
2routes/web.php
-
100tests/Feature/ManageVendorsTest.php
-
17tests/Unit/Models/PaymentTest.php
-
19tests/Unit/Models/VendorTest.php
-
43tests/Unit/Policies/VendorPolicyTest.php
@ -0,0 +1,10 @@ |
|||
<?php |
|||
|
|||
namespace App\Entities\Partners; |
|||
|
|||
use Illuminate\Database\Eloquent\Model; |
|||
|
|||
class Vendor extends Model |
|||
{ |
|||
protected $fillable = ['name', 'email', 'phone', 'notes', 'is_active']; |
|||
} |
|||
@ -0,0 +1,100 @@ |
|||
<?php |
|||
|
|||
namespace App\Http\Controllers\Partners; |
|||
|
|||
use App\Entities\Partners\Vendor; |
|||
use App\Http\Controllers\Controller; |
|||
use Illuminate\Http\Request; |
|||
|
|||
class VendorsController extends Controller |
|||
{ |
|||
/** |
|||
* Display a listing of the vendor. |
|||
* |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function index() |
|||
{ |
|||
$editableVendor = null; |
|||
$vendors = Vendor::where(function ($query) { |
|||
$query->where('name', 'like', '%'.request('q').'%'); |
|||
})->paginate(25); |
|||
|
|||
if (in_array(request('action'), ['edit', 'delete']) && request('id') != null) { |
|||
$editableVendor = Vendor::find(request('id')); |
|||
} |
|||
|
|||
return view('vendors.index', compact('vendors', 'editableVendor')); |
|||
} |
|||
|
|||
/** |
|||
* Store a newly created vendor in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request $request |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function store(Request $request) |
|||
{ |
|||
$newVendorData = $this->validate($request, [ |
|||
'name' => 'required|max:60', |
|||
'email' => 'nullable|email|unique:vendors,email', |
|||
'phone' => 'nullable', |
|||
'notes' => 'nullable|max:255', |
|||
]); |
|||
|
|||
Vendor::create($newVendorData); |
|||
|
|||
flash(trans('vendor.created'), 'success'); |
|||
|
|||
return redirect()->route('vendors.index'); |
|||
} |
|||
|
|||
/** |
|||
* Update the specified vendor in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request $request |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function update(Request $request, Vendor $vendor) |
|||
{ |
|||
$vendorData = $this->validate($request, [ |
|||
'name' => 'required|max:60', |
|||
'email' => 'nullable|email|unique:vendors,email,'.$vendor->id, |
|||
'phone' => 'nullable', |
|||
'notes' => 'nullable|max:255', |
|||
'is_active' => 'required|boolean', |
|||
]); |
|||
|
|||
$routeParam = request()->only('page', 'q'); |
|||
|
|||
$vendor = $vendor->update($vendorData); |
|||
|
|||
flash(trans('vendor.updated'), 'success'); |
|||
return redirect()->route('vendors.index', $routeParam); |
|||
} |
|||
|
|||
/** |
|||
* Remove the specified vendor from storage. |
|||
* |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function destroy(Vendor $vendor) |
|||
{ |
|||
// TODO: user cannot delete vendor that has been used in other table
|
|||
$this->validate(request(), [ |
|||
'vendor_id' => 'required', |
|||
]); |
|||
|
|||
$routeParam = request()->only('page', 'q'); |
|||
|
|||
if (request('vendor_id') == $vendor->id && $vendor->delete()) { |
|||
flash(trans('vendor.deleted'), 'warning'); |
|||
return redirect()->route('vendors.index', $routeParam); |
|||
} |
|||
|
|||
flash(trans('vendor.undeleted'), 'danger'); |
|||
return back(); |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
<?php |
|||
|
|||
namespace App\Policies\Partners; |
|||
|
|||
use App\Entities\Users\User; |
|||
use App\Entities\Partners\Vendor; |
|||
use Illuminate\Auth\Access\HandlesAuthorization; |
|||
|
|||
class VendorPolicy |
|||
{ |
|||
use HandlesAuthorization; |
|||
|
|||
/** |
|||
* Determine whether the user can view the project. |
|||
* |
|||
* @param \App\Entities\Users\User $user |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return mixed |
|||
*/ |
|||
public function view(User $user, Vendor $vendor) |
|||
{ |
|||
// Update $user authorization to view $vendor here.
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Determine whether the user can create projects. |
|||
* |
|||
* @param \App\Entities\Users\User $user |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return mixed |
|||
*/ |
|||
public function create(User $user, Vendor $vendor) |
|||
{ |
|||
// Update $user authorization to create $vendor here.
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Determine whether the user can update the project. |
|||
* |
|||
* @param \App\Entities\Users\User $user |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return mixed |
|||
*/ |
|||
public function update(User $user, Vendor $vendor) |
|||
{ |
|||
// Update $user authorization to update $vendor here.
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Determine whether the user can delete the project. |
|||
* |
|||
* @param \App\Entities\Users\User $user |
|||
* @param \App\Entities\Partners\Vendor $vendor |
|||
* @return mixed |
|||
*/ |
|||
public function delete(User $user, Vendor $vendor) |
|||
{ |
|||
// Update $user authorization to delete $vendor here.
|
|||
return true; |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
<?php |
|||
|
|||
return [ |
|||
|
|||
/* |
|||
|-------------------------------------------------------------------------- |
|||
| Application Base Layout View |
|||
|-------------------------------------------------------------------------- |
|||
| |
|||
| Default Laravel view layout |
|||
| |
|||
*/ |
|||
|
|||
'default_layout_view' => 'layouts.app', |
|||
|
|||
/* |
|||
|-------------------------------------------------------------------------- |
|||
| Base Test Class Path |
|||
|-------------------------------------------------------------------------- |
|||
| |
|||
| Base TestCase Path on Laravel application |
|||
| |
|||
*/ |
|||
|
|||
'base_test_path' => 'tests/TestCase.php', |
|||
|
|||
/* |
|||
|-------------------------------------------------------------------------- |
|||
| Base Test Class |
|||
|-------------------------------------------------------------------------- |
|||
| |
|||
| Base Test Class that used on Laravel application |
|||
| according to 'base_test_path' config above |
|||
| |
|||
*/ |
|||
|
|||
'base_test_class' => 'Tests\TestCase', |
|||
|
|||
]; |
|||
@ -0,0 +1,11 @@ |
|||
<?php |
|||
|
|||
use App\Entities\Partners\Vendor; |
|||
use Faker\Generator as Faker; |
|||
|
|||
$factory->define(Vendor::class, function (Faker $faker) { |
|||
|
|||
return [ |
|||
'name' => $faker->company, |
|||
]; |
|||
}); |
|||
@ -0,0 +1,36 @@ |
|||
<?php |
|||
|
|||
use Illuminate\Database\Migrations\Migration; |
|||
use Illuminate\Database\Schema\Blueprint; |
|||
use Illuminate\Support\Facades\Schema; |
|||
|
|||
class CreateVendorsTable extends Migration |
|||
{ |
|||
/** |
|||
* Run the migrations. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function up() |
|||
{ |
|||
Schema::create('vendors', function (Blueprint $table) { |
|||
$table->increments('id'); |
|||
$table->string('name', 60); |
|||
$table->string('email')->nullable()->unique(); |
|||
$table->string('phone')->nullable(); |
|||
$table->string('notes')->nullable(); |
|||
$table->boolean('is_active')->default(1); |
|||
$table->timestamps(); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Reverse the migrations. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function down() |
|||
{ |
|||
Schema::dropIfExists('vendors'); |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
return [ |
|||
// Labels
|
|||
'vendor' => 'Vendor', |
|||
'list' => 'Daftar Vendor', |
|||
'search' => 'Cari Vendor', |
|||
'not_found' => 'Vendor tidak ditemukan', |
|||
'empty' => 'Belum ada Vendor', |
|||
'back_to_show' => 'Back to Vendor Detail', |
|||
'back_to_index' => 'Kembali ke daftar Vendor', |
|||
|
|||
// Actions
|
|||
'create' => 'Input Vendor Baru', |
|||
'created' => 'Input Vendor baru telah berhasil.', |
|||
'show' => 'Detail Vendor', |
|||
'edit' => 'Edit Vendor', |
|||
'update' => 'Update Vendor', |
|||
'updated' => 'Update data Vendor telah berhasil.', |
|||
'delete' => 'Hapus Vendor', |
|||
'delete_confirm' => 'Anda yakin akan menghapus Vendor ini?', |
|||
'deleted' => 'Hapus data Vendor telah berhasil.', |
|||
'undeleted' => 'Data Vendor gagal dihapus.', |
|||
'undeleteable' => 'Data Vendor tidak dapat dihapus.', |
|||
|
|||
// Attributes
|
|||
'name' => 'Nama Vendor', |
|||
'description' => 'Deskripsi Vendor', |
|||
]; |
|||
@ -0,0 +1,60 @@ |
|||
@if (Request::get('action') == 'create') |
|||
{!! Form::open(['route' => 'vendors.store']) !!} |
|||
{!! FormField::text('name', ['required' => true]) !!} |
|||
{!! FormField::email('email') !!} |
|||
{!! FormField::text('phone') !!} |
|||
{!! FormField::textarea('notes') !!} |
|||
{!! Form::submit(trans('vendor.create'), ['class' => 'btn btn-success']) !!} |
|||
{{ link_to_route('vendors.index', trans('app.cancel'), [], ['class' => 'btn btn-default']) }} |
|||
{!! Form::close() !!} |
|||
@endif |
|||
@if (Request::get('action') == 'edit' && $editableVendor) |
|||
{!! Form::model($editableVendor, ['route' => ['vendors.update', $editableVendor->id],'method' => 'patch']) !!} |
|||
{!! FormField::text('name', ['required' => true]) !!} |
|||
{!! FormField::email('email') !!} |
|||
{!! FormField::text('phone') !!} |
|||
{!! FormField::textarea('notes') !!} |
|||
{!! FormField::radios('is_active', ['Non Aktif', 'Aktif']) !!} |
|||
@if (request('q')) |
|||
{{ Form::hidden('q', request('q')) }} |
|||
@endif |
|||
@if (request('page')) |
|||
{{ Form::hidden('page', request('page')) }} |
|||
@endif |
|||
{!! Form::submit(trans('vendor.update'), ['class' => 'btn btn-success']) !!} |
|||
{{ link_to_route('vendors.index', trans('app.cancel'), [], ['class' => 'btn btn-default']) }} |
|||
{!! Form::close() !!} |
|||
@endif |
|||
@if (Request::get('action') == 'delete' && $editableVendor) |
|||
<div class="panel panel-default"> |
|||
<div class="panel-heading"><h3 class="panel-title">{{ trans('vendor.delete') }}</h3></div> |
|||
<div class="panel-body"> |
|||
<label class="control-label">{{ trans('vendor.name') }}</label> |
|||
<p>{{ $editableVendor->name }}</p> |
|||
<label class="control-label">{{ trans('contact.email') }}</label> |
|||
<p>{{ $editableVendor->email }}</p> |
|||
<label class="control-label">{{ trans('contact.phone') }}</label> |
|||
<p>{{ $editableVendor->phone }}</p> |
|||
<label class="control-label">{{ trans('app.status') }}</label> |
|||
<p>{{ $editableVendor->is_active }}</p> |
|||
<label class="control-label">{{ trans('app.notes') }}</label> |
|||
<p>{{ $editableVendor->notes }}</p> |
|||
{!! $errors->first('vendor_id', '<span class="form-error small">:message</span>') !!} |
|||
</div> |
|||
<hr style="margin:0"> |
|||
<div class="panel-body">{{ trans('app.delete_confirm') }}</div> |
|||
<div class="panel-footer"> |
|||
{!! FormField::delete( |
|||
['route'=>['vendors.destroy',$editableVendor->id]], |
|||
trans('app.delete_confirm_button'), |
|||
['class'=>'btn btn-danger'], |
|||
[ |
|||
'vendor_id' => $editableVendor->id, |
|||
'page' => request('page'), |
|||
'q' => request('q'), |
|||
] |
|||
) !!} |
|||
{{ link_to_route('vendors.index', trans('app.cancel'), [], ['class' => 'btn btn-default']) }} |
|||
</div> |
|||
</div> |
|||
@endif |
|||
@ -0,0 +1,67 @@ |
|||
@extends('layouts.app') |
|||
|
|||
@section('title', trans('vendor.list')) |
|||
|
|||
@section('content') |
|||
<h1 class="page-header"> |
|||
<div class="pull-right"> |
|||
{{ link_to_route('vendors.index', trans('vendor.create'), ['action' => 'create'], ['class' => 'btn btn-success']) }} |
|||
</div> |
|||
{{ trans('vendor.list') }} |
|||
<small>{{ trans('app.total') }} : {{ $vendors->total() }} {{ trans('vendor.vendor') }}</small> |
|||
</h1> |
|||
<div class="row"> |
|||
<div class="col-md-9"> |
|||
<div class="panel panel-default table-responsive"> |
|||
<div class="panel-heading"> |
|||
{{ Form::open(['method' => 'get','class' => 'form-inline']) }} |
|||
{!! FormField::text('q', ['value' => request('q'), 'label' => trans('vendor.search'), 'class' => 'input-sm']) !!} |
|||
{{ Form::submit(trans('vendor.search'), ['class' => 'btn btn-sm']) }} |
|||
{{ link_to_route('vendors.index', trans('app.reset')) }} |
|||
{{ Form::close() }} |
|||
</div> |
|||
<table class="table table-condensed"> |
|||
<thead> |
|||
<tr> |
|||
<th class="text-center">{{ trans('app.table_no') }}</th> |
|||
<th>{{ trans('vendor.name') }}</th> |
|||
<th>{{ trans('contact.email') }}</th> |
|||
<th>{{ trans('contact.phone') }}</th> |
|||
<th class="text-center">{{ trans('app.status') }}</th> |
|||
<th class="text-center">{{ trans('app.action') }}</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
@foreach($vendors as $key => $vendor) |
|||
<tr> |
|||
<td class="text-center">{{ $vendors->firstItem() + $key }}</td> |
|||
<td>{{ $vendor->name }}</td> |
|||
<td>{{ $vendor->email }}</td> |
|||
<td>{{ $vendor->phone }}</td> |
|||
<td class="text-center">{{ $vendor->is_active }}</td> |
|||
<td class="text-center"> |
|||
{!! link_to_route( |
|||
'vendors.index', |
|||
trans('app.edit'), |
|||
['action' => 'edit', 'id' => $vendor->id] + Request::only('page', 'q'), |
|||
['id' => 'edit-vendor-' . $vendor->id] |
|||
) !!} | |
|||
{!! link_to_route( |
|||
'vendors.index', |
|||
trans('app.delete'), |
|||
['action' => 'delete', 'id' => $vendor->id] + Request::only('page', 'q'), |
|||
['id' => 'del-vendor-' . $vendor->id] |
|||
) !!} |
|||
</td> |
|||
</tr> |
|||
@endforeach |
|||
</tbody> |
|||
</table> |
|||
<div class="panel-body">{{ $vendors->appends(Request::except('page'))->render() }}</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
@includeWhen(Request::has('action'), 'vendors.forms') |
|||
</div> |
|||
</div> |
|||
@endsection |
|||
@ -0,0 +1,100 @@ |
|||
<?php |
|||
|
|||
namespace Tests\Feature; |
|||
|
|||
use App\Entities\Partners\Vendor; |
|||
use Illuminate\Foundation\Testing\DatabaseMigrations; |
|||
use Tests\TestCase as TestCase; |
|||
|
|||
class ManageVendorsTest extends TestCase |
|||
{ |
|||
use DatabaseMigrations; |
|||
|
|||
/** @test */ |
|||
public function user_can_see_vendor_list_in_vendor_index_page() |
|||
{ |
|||
$vendor1 = factory(Vendor::class)->create(); |
|||
$vendor2 = factory(Vendor::class)->create(); |
|||
|
|||
$this->adminUserSigningIn(); |
|||
$this->visit(route('vendors.index')); |
|||
$this->see($vendor1->name); |
|||
$this->see($vendor2->name); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_create_a_vendor() |
|||
{ |
|||
$this->adminUserSigningIn(); |
|||
$this->visit(route('vendors.index')); |
|||
|
|||
$this->click(trans('vendor.create')); |
|||
$this->seePageIs(route('vendors.index', ['action' => 'create'])); |
|||
|
|||
$this->submitForm(trans('vendor.create'), [ |
|||
'name' => 'Vendor 1 name', |
|||
'email' => 'vendor1@mail.com', |
|||
'phone' => '081234567890', |
|||
'notes' => '', |
|||
]); |
|||
|
|||
$this->seePageIs(route('vendors.index')); |
|||
|
|||
$this->seeInDatabase('vendors', [ |
|||
'name' => 'Vendor 1 name', |
|||
'email' => 'vendor1@mail.com', |
|||
'phone' => '081234567890', |
|||
'notes' => null, |
|||
]); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_edit_a_vendor_within_search_query() |
|||
{ |
|||
$this->adminUserSigningIn(); |
|||
$vendor = factory(Vendor::class)->create(['name' => 'Testing 123']); |
|||
|
|||
$this->visit(route('vendors.index', ['q' => '123'])); |
|||
$this->click('edit-vendor-'.$vendor->id); |
|||
$this->seePageIs(route('vendors.index', ['action' => 'edit', 'id' => $vendor->id, 'q' => '123'])); |
|||
|
|||
$this->submitForm(trans('vendor.update'), [ |
|||
'name' => 'Vendor 1 name', |
|||
'email' => 'vendor1@mail.com', |
|||
'phone' => '081234567890', |
|||
'notes' => '', |
|||
'is_active' => 0, |
|||
]); |
|||
|
|||
$this->seePageIs(route('vendors.index', ['q' => '123'])); |
|||
|
|||
$this->seeInDatabase('vendors', [ |
|||
'name' => 'Vendor 1 name', |
|||
'email' => 'vendor1@mail.com', |
|||
'phone' => '081234567890', |
|||
'notes' => null, |
|||
'is_active' => 0, |
|||
]); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_delete_a_vendor() |
|||
{ |
|||
$this->adminUserSigningIn(); |
|||
$vendor = factory(Vendor::class)->create(); |
|||
|
|||
$this->visit(route('vendors.index', [$vendor->id])); |
|||
$this->click('del-vendor-'.$vendor->id); |
|||
$this->seePageIs(route('vendors.index', ['action' => 'delete', 'id' => $vendor->id])); |
|||
|
|||
$this->seeInDatabase('vendors', [ |
|||
'id' => $vendor->id, |
|||
]); |
|||
|
|||
$this->press(trans('app.delete_confirm_button')); |
|||
|
|||
$this->dontSeeInDatabase('vendors', [ |
|||
'id' => $vendor->id, |
|||
]); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<?php |
|||
|
|||
namespace Tests\Unit\Models; |
|||
|
|||
use App\Entities\Payments\Payment; |
|||
use App\Entities\Users\User; |
|||
use Tests\TestCase; |
|||
|
|||
class PaymentTest extends TestCase |
|||
{ |
|||
/** @test */ |
|||
public function it_has_customer_relation() |
|||
{ |
|||
$payment = factory(Payment::class)->create(); |
|||
$this->assertTrue($payment->customer instanceof User); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<?php |
|||
|
|||
namespace Tests\Unit\Models; |
|||
|
|||
use App\Entities\Partners\Vendor; |
|||
use Illuminate\Foundation\Testing\DatabaseMigrations; |
|||
use Tests\TestCase as TestCase; |
|||
|
|||
class VendorTest extends TestCase |
|||
{ |
|||
use DatabaseMigrations; |
|||
|
|||
/** @test */ |
|||
public function it_has_name_attribute() |
|||
{ |
|||
$vendor = factory(Vendor::class)->create(['name' => 'Vendor 1 name']); |
|||
$this->assertEquals('Vendor 1 name', $vendor->name); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
<?php |
|||
|
|||
namespace Tests\Unit\Policies; |
|||
|
|||
use App\Entities\Partners\Vendor; |
|||
use Illuminate\Foundation\Testing\DatabaseMigrations; |
|||
use Tests\TestCase as TestCase; |
|||
|
|||
class VendorTest extends TestCase |
|||
{ |
|||
use DatabaseMigrations; |
|||
|
|||
/** @test */ |
|||
public function user_can_create_vendor() |
|||
{ |
|||
$user = $this->adminUserSigningIn(); |
|||
$this->assertTrue($user->can('create', new Vendor)); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_view_vendor() |
|||
{ |
|||
$user = $this->adminUserSigningIn(); |
|||
$vendor = factory(Vendor::class)->create(['name' => 'Vendor 1 name']); |
|||
$this->assertTrue($user->can('view', $vendor)); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_update_vendor() |
|||
{ |
|||
$user = $this->adminUserSigningIn(); |
|||
$vendor = factory(Vendor::class)->create(['name' => 'Vendor 1 name']); |
|||
$this->assertTrue($user->can('update', $vendor)); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function user_can_delete_vendor() |
|||
{ |
|||
$user = $this->adminUserSigningIn(); |
|||
$vendor = factory(Vendor::class)->create(['name' => 'Vendor 1 name']); |
|||
$this->assertTrue($user->can('delete', $vendor)); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue