Browse Source

Update 2016-07-09.13.19

Add project features with TDD
Add and fix Payment test
pull/1/head
Nafies Luthfi 10 years ago
parent
commit
08a1e44541
  1. 2
      app/Entities/Payments/PaymentsRepository.php
  2. 17
      app/Entities/Projects/Feature.php
  3. 6
      app/Entities/Projects/FeaturesRepository.php
  4. 5
      app/Entities/Projects/ProjectsRepository.php
  5. 18
      app/Http/Controllers/Projects/FeaturesController.php
  6. 3
      app/Http/Controllers/Projects/ProjectsController.php
  7. 36
      app/Http/Requests/Features/CreateRequest.php
  8. 34
      app/Http/Requests/Features/DeleteRequest.php
  9. 36
      app/Http/Requests/Features/UpdateRequest.php
  10. 4
      app/Http/routes/projects.php
  11. 5
      app/Providers/AuthServiceProvider.php
  12. 40
      database/factories/ModelFactory.php
  13. 3
      resources/lang/id/feature.php
  14. 17
      resources/views/features/create.blade.php
  15. 25
      resources/views/features/delete.blade.php
  16. 32
      resources/views/features/edit.blade.php
  17. 18
      resources/views/features/partials/feature-show.blade.php
  18. 25
      resources/views/features/show.blade.php
  19. 4
      resources/views/masters/delete.blade.php
  20. 2
      resources/views/masters/show.blade.php
  21. 8
      resources/views/payments/index.blade.php
  22. 2
      resources/views/projects/edit.blade.php
  23. 27
      resources/views/projects/features.blade.php
  24. 2
      resources/views/projects/partials/breadcrumb.blade.php
  25. 2
      resources/views/projects/partials/project-show.blade.php
  26. 135
      tests/ManageFeaturesTest.php
  27. 38
      tests/ManagePaymentsTest.php

2
app/Entities/Payments/PaymentsRepository.php

@ -18,7 +18,7 @@ class PaymentsRepository extends BaseRepository
public function getAll($q)
{
return $this->model->latest()
return $this->model->orderBy('date','desc')
->paginate($this->_paginate);
}
}

17
app/Entities/Projects/Feature.php

@ -3,6 +3,8 @@
namespace App\Entities\Projects;
use App\Entities\Projects\FeaturePresenter;
use App\Entities\Projects\Project;
use App\Entities\Users\User;
use Illuminate\Database\Eloquent\Model;
use Laracasts\Presenter\PresentableTrait;
@ -13,4 +15,19 @@ class Feature extends Model {
protected $presenter = FeaturePresenter::class;
protected $guarded = ['id','created_at','updated_at'];
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
public function worker()
{
return $this->belongsTo(User::class, 'worker_id');
}
public function tasks()
{
return $this->hasMany(Task::class);
}
}

6
app/Entities/Projects/FeaturesRepository.php

@ -3,6 +3,7 @@
namespace App\Entities\Projects;
use App\Entities\BaseRepository;
use App\Entities\Projects\Project;
/**
* Features Repository Class
@ -21,10 +22,9 @@ class FeaturesRepository extends BaseRepository
return Project::findOrFail($projectId);
}
public function create($featureData)
public function createFeature($featureData, $projectId)
{
dd($featureData);
$featureData['feature_value'] = $featureData['proposal_value'];
$featureData['project_id'] = $projectId;
return $this->storeArray($featureData);
}
}

5
app/Entities/Projects/ProjectsRepository.php

@ -77,4 +77,9 @@ class ProjectsRepository extends BaseRepository
return $project->delete();
}
public function getProjectFeatures($projectId)
{
return Feature::whereProjectId($projectId)->with('worker')->get();
}
}

18
app/Http/Controllers/Projects/FeaturesController.php

@ -26,11 +26,11 @@ class FeaturesController extends Controller {
return view('features.create',compact('project','workers'));
}
public function store(CreateRequest $req)
public function store(CreateRequest $req, $projectId)
{
$feature = $this->repo->create($req->except('_token'));
$feature = $this->repo->createFeature($req->except('_token'), $projectId);
flash()->success(trans('feature.created'));
return redirect()->route('features.show', $feature->id);
return redirect()->route('projects.features', $feature->project_id);
}
public function show($featureId)
@ -42,14 +42,15 @@ class FeaturesController extends Controller {
public function edit($featureId)
{
$feature = $this->repo->requireById($featureId);
return view('features.edit',compact('feature'));
$workers = $this->repo->getWorkersList();
return view('features.edit',compact('feature','workers'));
}
public function update(UpdateRequest $req, $featureId)
{
$feature = $this->repo->update($req->except(['_method','_token']), $featureId);
flash()->success(trans('feature.updated'));
return redirect()->route('features.edit', $featureId);
return redirect()->route('projects.features', $feature->project_id);
}
public function delete($featureId)
@ -60,15 +61,18 @@ class FeaturesController extends Controller {
public function destroy(DeleteRequest $req, $featureId)
{
$feature = $this->repo->requireById($featureId);
$projectId = $feature->project_id;
if ($featureId == $req->get('feature_id'))
{
$this->repo->delete($featureId);
// $feature->tasks()->delete();
$feature->delete();
flash()->success(trans('feature.deleted'));
}
else
flash()->error(trans('feature.undeleted'));
return redirect()->route('features.index');
return redirect()->route('projects.features', $projectId);
}
public function tasks($featureId)

3
app/Http/Controllers/Projects/ProjectsController.php

@ -87,7 +87,8 @@ class ProjectsController extends Controller {
public function features($projectId)
{
$project = $this->repo->requireById($projectId);
return view('projects.features', compact('project'));
$features = $this->repo->getProjectFeatures($projectId);
return view('projects.features', compact('project','features'));
}
public function payments($projectId)

36
app/Http/Requests/Features/CreateRequest.php

@ -0,0 +1,36 @@
<?php
namespace App\Http\Requests\Features;
use App\Entities\Projects\Project;
use App\Http\Requests\Request;
class CreateRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$project = Project::findOrFail($this->segment(2));
return auth()->user()->can('manage_features', $project);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:60',
'worker_id' => 'required|numeric',
'price' => 'required|numeric',
'description' => 'max:255',
];
}
}

34
app/Http/Requests/Features/DeleteRequest.php

@ -0,0 +1,34 @@
<?php
namespace App\Http\Requests\Features;
use App\Entities\Projects\Project;
use App\Http\Requests\Request;
class DeleteRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$project = Project::findOrFail($this->get('project_id'));
return auth()->user()->can('manage_features', $project);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'feature_id' => 'required',
'project_id' => 'required',
];
}
}

36
app/Http/Requests/Features/UpdateRequest.php

@ -0,0 +1,36 @@
<?php
namespace App\Http\Requests\Features;
use App\Entities\Projects\Project;
use App\Http\Requests\Request;
class UpdateRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$project = Project::findOrFail($this->get('project_id'));
return auth()->user()->can('manage_features', $project);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:60',
'worker_id' => 'required|numeric',
'price' => 'required|numeric',
'description' => 'max:255',
];
}
}

4
app/Http/routes/projects.php

@ -13,5 +13,7 @@ Route::group(['middleware' => ['web','role:admin'], 'namespace' => 'Projects'],
* Features Routes
*/
Route::get('projects/{id}/features/create', ['as'=>'features.create', 'uses'=>'FeaturesController@create']);
Route::resource('features','FeaturesController',['except' => ['index','create']]);
Route::post('projects/{id}/features', ['as'=>'features.store', 'uses'=>'FeaturesController@store']);
Route::get('features/{id}/delete', ['as'=>'features.delete', 'uses'=>'FeaturesController@delete']);
Route::resource('features','FeaturesController',['except' => ['index','create','store']]);
});

5
app/Providers/AuthServiceProvider.php

@ -34,6 +34,11 @@ class AuthServiceProvider extends ServiceProvider
});
}
$gate->define('manage_features', function ($user, $project) {
return $user->id == $project->owner_id;
});
}
/**

40
database/factories/ModelFactory.php

@ -1,6 +1,7 @@
<?php
use App\Entities\Payments\Payment;
use App\Entities\Projects\Feature;
use App\Entities\Projects\Project;
use App\Entities\Subscriptions\Subscription;
use App\Entities\Users\User;
@ -27,14 +28,17 @@ $factory->define(User::class, function (Faker\Generator $faker) {
});
$factory->define(Project::class, function (Faker\Generator $faker) {
$proposalDate = $faker->dateTimeBetween('-1 year', '-1 month')->format('Y-m-d');
$startDate = Carbon::parse($proposalDate)->addDays(10);
$endDate = $startDate->addDays(rand(1,13) * 7);
$owner = factory(User::class)->create();
$owner->assignRole('admin');
$customer = factory(User::class)->create();
$customer->assignRole('customer');
return [
'name' => $faker->sentence,
'name' => $faker->sentence(3),
'description' => $faker->paragraph,
'proposal_date' => $proposalDate,
'start_date' => $startDate->format('Y-m-d'),
@ -42,29 +46,28 @@ $factory->define(Project::class, function (Faker\Generator $faker) {
'project_value' => $projectValue = rand(1,10) * 500000,
'proposal_value' => $projectValue,
'status_id' => rand(1,6),
'owner_id' => $owner->id,
'customer_id' => $customer->id
];
});
$factory->define(Payment::class, function (Faker\Generator $faker) {
$projectId = factory(Project::class)->create()->id;
$customer = factory(User::class)->create();
$customer->assignRole('customer');
$customerId = $customer->id;
return [
'project_id' => $projectId,
'project_id' => function() {
return factory(Project::class)->create()->id;
},
'amount' => rand(1,5) * 500000,
'type' => rand(0,1),
'date' => $faker->dateTimeBetween('-1 year', '-1 month')->format('Y-m-d'),
'description' => $faker->paragraph,
'customer_id' => $customerId,
'customer_id' => function() {
return factory(User::class)->create()->id;
},
];
});
$factory->define(Subscription::class, function (Faker\Generator $faker) {
$projectId = factory(Project::class)->create()->id;
$customer = factory(User::class)->create();
$customer->assignRole('customer');
@ -72,7 +75,9 @@ $factory->define(Subscription::class, function (Faker\Generator $faker) {
$startDate = Carbon::parse($faker->dateTimeBetween('-1 year', '-1 month')->format('Y-m-d'));
return [
'project_id' => $projectId,
'project_id' => function() {
return factory(Project::class)->create()->id;
},
'domain_name' => 'www.' . str_random(10) . '.com',
'domain_price' => 125000,
'epp_code' => str_random(10),
@ -83,4 +88,19 @@ $factory->define(Subscription::class, function (Faker\Generator $faker) {
'remark' => $faker->paragraph,
'customer_id' => $customerId,
];
});
$factory->define(Feature::class, function (Faker\Generator $faker) {
return [
'project_id' => function() {
return factory(Project::class)->create()->id;
},
'name' => $faker->sentence(3),
'price' => rand(1,10) * 100000,
'description' => $faker->paragraph,
'worker_id' => function() {
return factory(User::class)->create()->id;
},
];
});

3
resources/lang/id/feature.php

@ -6,7 +6,7 @@ return [
'name' => 'Nama Fitur',
'create' => 'Input Fitur Baru',
'created' => 'Input Fitur baru telah berhasil.',
'show' => 'Edit Fitur',
'show' => 'Detail Fitur',
'edit' => 'Edit Fitur',
'update' => 'Update Fitur',
'updated' => 'Update data Fitur telah berhasil.',
@ -21,6 +21,7 @@ return [
'progress' => 'Progress',
'worker' => 'Pekerja',
'price' => 'Nilai Fitur',
'price_total' => 'Nilai Fitur Total',
'empty' => 'Belum ada Fitur',
'back_to_index' => 'Kembali ke daftar Fitur',
];

17
resources/views/features/create.blade.php

@ -6,15 +6,21 @@
@include('projects.partials.breadcrumb',['title' => trans('feature.create')])
<div class="row">
<div class="col-md-4">
{!! Form::open(['route'=>'features.store']) !!}
<div class="col-sm-6">
{!! Form::open(['route'=>['features.store', $project->id]]) !!}
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('feature.create') }}</h3></div>
<div class="panel-body">
{!! FormField::text('name',['label'=> trans('feature.name')]) !!}
{!! FormField::textarea('description',['label'=> trans('feature.description')]) !!}
{!! FormField::price('price', ['label'=> trans('feature.price')]) !!}
{!! FormField::select('worker_id', $workers, ['label'=> trans('feature.worker')]) !!}
<div class="row">
<div class="col-sm-6">
{!! FormField::price('price', ['label'=> trans('feature.price')]) !!}
</div>
<div class="col-sm-6">
{!! FormField::select('worker_id', $workers, ['label'=> trans('feature.worker'),'value' => 1]) !!}
</div>
</div>
</div>
<div class="panel-footer">
@ -24,5 +30,8 @@
</div>
{!! Form::close() !!}
</div>
<div class="col-sm-6">
@include('projects.partials.project-show')
</div>
</div>
@endsection

25
resources/views/features/delete.blade.php

@ -1,28 +1,25 @@
@extends('layouts.app')
@section('title', trans('master.delete'))
@section('title', trans('feature.delete'))
@section('content')
<h1 class="page-header">
<div class="pull-right">
{!! delete_button(['route'=>['masters.destroy',$master->id]], trans('app.delete_confirm_button'), ['class'=>'btn btn-danger'], ['master_id'=>$master->id]) !!}
{!! FormField::delete([
'route'=>['features.destroy',$feature->id]],
trans('app.delete_confirm_button'),
['class'=>'btn btn-danger'],
[
'feature_id'=>$feature->id,
'project_id'=>$feature->project_id,
]) !!}
</div>
{{ trans('app.delete_confirm') }}
{!! link_to_route('masters.show', trans('app.cancel'), [$master->id], ['class' => 'btn btn-default']) !!}
{!! link_to_route('features.show', trans('app.cancel'), [$feature->id], ['class' => 'btn btn-default']) !!}
</h1>
<div class="row">
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading"><h3 class="panel-title">{{ trans('master.masters') }} Detail</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><th>{{ trans('app.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('app.description') }}</th><td>{{ $master->description }}</td></tr>
</tbody>
</table>
</div>
</div>
@include('features.partials.feature-show')
</div>
</div>
@endsection

32
resources/views/features/edit.blade.php

@ -1,26 +1,38 @@
@extends('layouts.app')
@section('title', trans('master.edit'))
@section('title', trans('feature.edit'))
@section('content')
<div class="row"><br>
<div class="col-md-4">
{!! Form::model($master, ['route'=>['masters.update', $master->id], 'method' => 'patch']) !!}
<div class="col-md-6">
{!! Form::model($feature, ['route'=>['features.update', $feature->id], 'method' => 'patch']) !!}
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ $master->name }} <small>{{ trans('master.edit') }}</small></h3></div>
<div class="panel-heading"><h3 class="panel-title">{{ $feature->name }} <small>{{ trans('feature.edit') }}</small></h3></div>
<div class="panel-body">
{!! FormField::text('name',['label'=> trans('app.name')]) !!}
{!! FormField::textarea('description',['label'=> trans('app.description')]) !!}
{!! FormField::text('name',['label'=> trans('feature.name')]) !!}
{!! FormField::textarea('description',['label'=> trans('feature.description')]) !!}
<div class="row">
<div class="col-sm-6">
{!! FormField::price('price', ['label'=> trans('feature.price')]) !!}
</div>
<div class="col-sm-6">
{!! FormField::select('worker_id', $workers, ['label'=> trans('feature.worker'),'value' => 1]) !!}
</div>
</div>
</div>
<div class="panel-footer">
{!! Form::submit(trans('master.update'), ['class'=>'btn btn-primary']) !!}
{!! link_to_route('masters.show', trans('app.show'), [$master->id], ['class' => 'btn btn-info']) !!}
{!! link_to_route('masters.index', trans('master.back_to_index'), [], ['class' => 'btn btn-default']) !!}
{!! link_to_route('masters.delete', trans('app.delete'), [$master->id], ['class'=>'btn btn-danger pull-right']) !!}
{!! Form::hidden('project_id', $feature->project_id) !!}
{!! Form::submit(trans('feature.update'), ['class'=>'btn btn-primary']) !!}
{!! link_to_route('features.show', trans('app.show'), [$feature->id], ['class' => 'btn btn-info']) !!}
{!! link_to_route('projects.features', trans('feature.back_to_index'), [$feature->project_id], ['class' => 'btn btn-default']) !!}
{!! link_to_route('features.delete', trans('feature.delete'), [$feature->id], ['class'=>'btn btn-danger pull-right']) !!}
</div>
</div>
{!! Form::close() !!}
</div>
<div class="col-sm-6">
@include('projects.partials.project-show', ['project' => $feature->project])
</div>
</div>
@endsection

18
resources/views/features/partials/feature-show.blade.php

@ -0,0 +1,18 @@
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('feature.show') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><th>{{ trans('feature.name') }}</th><td>{{ $feature->name }}</td></tr>
<tr><th>{{ trans('feature.price') }}</th><td>{{ formatRp($feature->price) }}</td></tr>
<tr><th>{{ trans('feature.tasks_count') }}</th><td>10</td></tr>
<tr><th>{{ trans('feature.progress') }}</th><td>100%</td></tr>
<tr><th>{{ trans('feature.worker') }}</th><td>{{ $feature->worker->name }}</td></tr>
</tbody>
</table>
</div>
<div class="panel-footer">
{!! link_to_route('features.edit', trans('feature.edit'), [$feature->id], ['class' => 'btn btn-warning']) !!}
{!! link_to_route('projects.features', trans('feature.back_to_index'), [$feature->project_id], ['class' => 'btn btn-default']) !!}
</div>
</div>

25
resources/views/features/show.blade.php

@ -1,26 +1,15 @@
@extends('layouts.app')
@section('title', trans('master.show'))
@section('title', trans('feature.show'))
@section('content')
<h1 class="page-header">{{ $master->name }} <small>{{ trans('master.show') }}</small></h1>
<h1 class="page-header">{{ $feature->name }} <small>{{ trans('feature.show') }}</small></h1>
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('master.show') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><th>{{ trans('app.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('app.description') }}</th><td>{{ $master->description }}</td></tr>
</tbody>
</table>
</div>
<div class="panel-footer">
{!! link_to_route('masters.edit', trans('app.edit'), [$master->id], ['class' => 'btn btn-warning']) !!}
{!! link_to_route('masters.index', trans('master.back_to_index'), [], ['class' => 'btn btn-default']) !!}
</div>
</div>
<div class="col-md-6">
@include('features.partials.feature-show')
</div>
<div class="col-sm-6">
@include('projects.partials.project-show', ['project' => $feature->project])
</div>
</div>
@endsection

4
resources/views/masters/delete.blade.php

@ -13,11 +13,11 @@
<div class="row">
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading"><h3 class="panel-title">{{ trans('master.masters') }} Detail</h3></div>
<div class="panel-heading"><h3 class="panel-title">{{ trans('master.show') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><th>{{ trans('app.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('master.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('app.description') }}</th><td>{{ $master->description }}</td></tr>
</tbody>
</table>

2
resources/views/masters/show.blade.php

@ -11,7 +11,7 @@
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><th>{{ trans('app.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('master.name') }}</th><td>{{ $master->name }}</td></tr>
<tr><th>{{ trans('app.description') }}</th><td>{{ $master->description }}</td></tr>
</tbody>
</table>

8
resources/views/payments/index.blade.php

@ -20,8 +20,9 @@
<th class="col-md-3">{{ trans('payment.project') }}</th>
<th class="col-md-1 text-center">{{ trans('app.date') }}</th>
<th class="col-md-2 text-right">{{ trans('payment.amount') }}</th>
<th class="col-md-4">{{ trans('payment.description') }}</th>
<th class="col-md-2">{{ trans('app.action') }}</th>
<th class="col-md-3">{{ trans('payment.description') }}</th>
<th class="col-md-2">{{ trans('payment.customer') }}</th>
<th class="col-md-1">{{ trans('app.action') }}</th>
</thead>
<tbody>
@forelse($payments as $key => $payment)
@ -31,8 +32,9 @@
<td class="text-center">{{ $payment->date }}</td>
<td class="text-right">{{ formatRp($payment->amount) }}</td>
<td>{{ $payment->description }}</td>
<td>{{ $payment->customer->name }}</td>
<td>
{!! link_to_route('payments.show',trans('app.show'),[$payment->id],['class'=>'btn btn-info btn-xs']) !!}
{!! link_to_route('payments.show','Lihat',[$payment->id],['class'=>'btn btn-info btn-xs']) !!}
{!! link_to_route('payments.edit',trans('app.edit'),[$payment->id],['class'=>'btn btn-warning btn-xs']) !!}
</td>
</tr>

2
resources/views/projects/edit.blade.php

@ -46,7 +46,7 @@
<div class="panel-footer">
{!! Form::submit(trans('project.update'), ['class'=>'btn btn-primary']) !!}
{!! link_to_route('projects.show', trans('app.show'), [$project->id], ['class' => 'btn btn-info']) !!}
{!! link_to_route('projects.index', trans('project.back_to_index'), [], ['class' => 'btn btn-default']) !!}
{!! link_to_route('projects.index', trans('project.back_to_index'), ['status' => $project->status_id], ['class' => 'btn btn-default']) !!}
{!! link_to_route('projects.delete', trans('app.delete'), [$project->id], ['class'=>'btn btn-danger pull-right']) !!}
</div>
</div>

27
resources/views/projects/features.blade.php

@ -14,20 +14,37 @@
<thead>
<th>{{ trans('app.table_no') }}</th>
<th>{{ trans('feature.name') }}</th>
<th>{{ trans('feature.tasks_count') }}</th>
<th>{{ trans('feature.progress') }}</th>
<th class="text-center">{{ trans('feature.tasks_count') }}</th>
<th class="text-center">{{ trans('feature.progress') }}</th>
<th class="text-right">{{ trans('feature.price') }}</th>
<th>{{ trans('feature.worker') }}</th>
<th>{{ trans('app.action') }}</th>
</thead>
<tbody>
@forelse($project->features as $feature)
@forelse($features as $key => $feature)
<tr>
<td>{{ 1 + $key }}</td>
<td>{{ $feature->name }}</td>
<td class="text-center">{{ $feature->tasks_count = rand(3, 7) }}</td>
<td class="text-center">{{ $feature->progress = rand(70, 100) }} %</td>
<td class="text-right">{{ formatRp($feature->price) }}</td>
<td>{{ $feature->worker->name }}</td>
<td>{!! link_to_route('features.show', trans('app.show'),[$feature->id],['class' => 'btn btn-info btn-xs']) !!}</td>
</tr>
@empty
<tr><td colspan="5">{{ trans('feature.empty') }}</td></tr>
<tr><td colspan="7">{{ trans('feature.empty') }}</td></tr>
@endforelse
<tr><td colspan="5">{!! html_link_to_route('features.create', trans('feature.create'), [$project->id], ['class' => 'btn btn-primary','icon' => 'plus']) !!}</td></tr>
</tbody>
<tfoot>
<tr>
<th class="text-right" colspan="2">Total</th>
<th class="text-center">{{ $features->sum('tasks_count') }}</th>
<th class="text-center">{{ formatDecimal($features->avg('progress')) }} %</th>
<th class="text-right">{{ formatRp($features->sum('price')) }}</th>
<th colspan="2"></th>
</tr>
<tr><td colspan="7">{!! html_link_to_route('features.create', trans('feature.create'), [$project->id], ['class' => 'btn btn-primary','icon' => 'plus']) !!}</td></tr>
</tfoot>
</table>
</div>
@endsection

2
resources/views/projects/partials/breadcrumb.blade.php

@ -1,5 +1,5 @@
<ul class="breadcrumb hidden-print">
<li>{{ link_to_route('projects.index',trans('project.projects')) }}</li>
<li>{{ link_to_route('projects.index',trans('project.projects'), ['status' => Request::get('status', $project->status_id)]) }}</li>
<li>{{ $project->present()->projectLink }}</li>
<li class="active">{{ isset($title) ? $title : trans('project.show') }}</li>
</ul>

2
resources/views/projects/partials/project-show.blade.php

@ -24,6 +24,6 @@
</div>
<div class="panel-footer">
{!! link_to_route('projects.edit', trans('project.edit'), [$project->id], ['class' => 'btn btn-warning']) !!}
{!! link_to_route('projects.index', trans('project.back_to_index'), [], ['class' => 'btn btn-default']) !!}
{!! link_to_route('projects.index', trans('project.back_to_index'), ['status' => $project->status_id], ['class' => 'btn btn-default']) !!}
</div>
</div>

135
tests/ManageFeaturesTest.php

@ -0,0 +1,135 @@
<?php
use App\Entities\Projects\Feature;
use App\Entities\Projects\Project;
use App\Entities\Users\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class ManageFeaturesTest extends TestCase
{
use DatabaseTransactions;
/** @test */
public function admin_can_entry_feature()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$project = factory(Project::class)->create(['owner_id' => $user->id]);
$worker = factory(User::class)->create();
$worker->assignRole('worker');
$this->visit('projects/' . $project->id . '/features');
$this->seePageIs('projects/' . $project->id . '/features');
$this->see(trans('project.features'));
$this->click(trans('feature.create'));
$this->seePageIs('projects/' . $project->id . '/features/create');
// Fill Form
$this->type('Nama Fitur Baru','name');
$this->type(100000,'price');
$this->select($worker->id, 'worker_id');
$this->type('Similique, eligendi fuga animi? Ipsam magnam laboriosam distinctio officia facere sapiente eius corporis','description');
$this->press(trans('feature.create'));
$this->seePageIs('projects/' . $project->id . '/features');
$this->see(trans('feature.created'));
$this->seeInDatabase('features', [
'name' => 'Nama Fitur Baru',
'price' => 100000,
'worker_id' => $worker->id,
'project_id' => $project->id
]);
}
/** @test */
public function admin_can_edit_feature_data()
{
$user = factory(User::class, 3)->create();
$user[0]->assignRole('admin');
$user[1]->assignRole('worker');
$user[2]->assignRole('worker');
$this->actingAs($user[0]);
$project = factory(Project::class)->create(['owner_id' => $user[0]->id]);
$feature = factory(Feature::class)->create(['worker_id' => $user[1]->id, 'project_id' => $project->id]);
$this->visit('features/' . $feature->id . '/edit');
$this->seePageIs('features/' . $feature->id . '/edit');
// Fill Form
$this->type('Nama Fitur Edit','name');
$this->type(33333,'price');
$this->select($user[2]->id,'worker_id');
$this->press(trans('feature.update'));
$this->seePageIs('projects/' . $project->id . '/features');
$this->see(trans('feature.updated'));
$this->seeInDatabase('features', [
'name' => 'Nama Fitur Edit',
'price' => 33333,
'worker_id' => $user[2]->id,
'project_id' => $project->id
]);
}
/** @test */
public function admin_can_delete_a_feature()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$project = factory(Project::class)->create(['owner_id' => $user->id]);
$feature = factory(Feature::class)->create(['project_id' => $project->id]);
$this->visit('projects/' . $feature->project_id . '/features');
$this->click(trans('app.show'));
$this->click(trans('app.edit'));
$this->click(trans('feature.delete'));
$this->press(trans('app.delete_confirm_button'));
$this->seePageIs('projects/' . $project->id . '/features');
$this->see(trans('feature.deleted'));
}
/** @test */
public function admin_can_see_a_feature()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$project = factory(Project::class)->create(['owner_id' => $user->id]);
$feature = factory(Feature::class)->create(['project_id' => $project->id]);
$this->visit('projects/' . $project->id . '/features');
$this->click(trans('app.show'));
$this->seePageIs('features/' . $feature->id);
$this->see(trans('feature.show'));
$this->see($feature->name);
$this->see(formatRp($feature->price));
$this->see($feature->worker->name);
}
/** @test */
public function admin_can_see_all_features()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$project = factory(Project::class)->create(['owner_id' => $user->id]);
$features = factory(Feature::class, 10)->create(['project_id' => $project->id]);
$this->assertEquals(10, $features->count());
$this->visit('projects/' . $project->id . '/features');
$this->see($features[1]->name);
$this->see($features[1]->worker->name);
$this->see(formatRp($features[1]->price));
}
}

38
tests/ManagePaymentsTest.php

@ -87,4 +87,42 @@ class ManagePaymentsTest extends TestCase
$this->seePageIs('payments');
$this->see(trans('payment.deleted'));
}
/** @test */
public function admin_can_see_a_payment()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$project = factory(Project::class)->create(['owner_id' => $user->id]);
$payment = factory(Payment::class)->create(['project_id' => $project->id]);
$this->visit('/payments');
$this->click('Lihat');
$this->seePageIs('payments/' . $payment->id);
$this->see(trans('payment.show'));
$this->see($payment->date);
$this->see(formatRp($payment->amount));
$this->see($payment->description);
$this->see($payment->customer->name);
}
/** @test */
public function admin_can_see_all_payments()
{
$user = factory(User::class)->create();
$user->assignRole('admin');
$this->actingAs($user);
$payments = factory(Payment::class, 10)->create();
$this->assertEquals(10, $payments->count());
$this->visit('/payments');
$this->see($payments[9]->project->name);
$this->see($payments[9]->date);
$this->see(formatRp($payments[9]->amount));
$this->see($payments[9]->description);
$this->see($payments[9]->customer->name);
}
}
Loading…
Cancel
Save