Browse Source

Merge branch 'user-deletion'

pull/16/head
Nafies Luthfi 8 years ago
parent
commit
eea954f5f0
  1. 76
      app/Http/Controllers/UsersController.php
  2. 14
      app/User.php
  3. 31
      resources/lang/en/user.php
  4. 6
      resources/lang/en/validation.php
  5. 31
      resources/lang/id/user.php
  6. 6
      resources/lang/id/validation.php
  7. 54
      resources/views/users/edit.blade.php
  8. 1
      routes/web.php
  9. 256
      tests/Feature/UsersDeletionTest.php
  10. 24
      tests/Unit/UserTest.php

76
app/Http/Controllers/UsersController.php

@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use DB;
use Storage;
use App\User;
use App\Couple;
@ -106,7 +107,12 @@ class UsersController extends Controller
{
$this->authorize('edit', $user);
return view('users.edit', compact('user'));
$replacementUsers = [];
if (request('action') == 'delete') {
$replacementUsers = User::where('gender_id', $user->gender_id)->pluck('nickname', 'id');
}
return view('users.edit', compact('user', 'replacementUsers'));
}
/**
@ -161,12 +167,40 @@ class UsersController extends Controller
/**
* Remove the specified User from storage.
*
* @param \App\User $user
* @param \Illuminate\Http\Request $request
* @param \App\User $user
*
* @return \Illuminate\Http\Response
*/
public function destroy(User $user)
public function destroy(Request $request, User $user)
{
//
$this->authorize('delete', $user);
if ($request->has('replace_delete_button')) {
$attributes = $request->validate([
'replacement_user_id' => 'required|exists:users,id',
], [
'replacement_user_id.required' => __('validation.user.replacement_user_id.required'),
]);
DB::beginTransaction();
$this->replaceUserOnUsersTable($user->id, $attributes['replacement_user_id']);
$this->replaceUserOnCouplesTable($user->id, $attributes['replacement_user_id']);
$user->delete();
DB::commit();
return redirect()->route('users.show', $attributes['replacement_user_id']);
}
request()->validate([
'user_id' => 'required',
]);
if (request('user_id') == $user->id && $user->delete()) {
return redirect()->route('users.search');
}
return back();
}
/**
@ -194,4 +228,38 @@ class UsersController extends Controller
return back();
}
/**
* Replace User Ids on users table.
*
* @param string $oldUserId
* @param string $replacementUserId
*
* @return void
*/
private function replaceUserOnUsersTable($oldUserId, $replacementUserId)
{
foreach (['father_id', 'mother_id', 'manager_id'] as $field) {
DB::table('users')->where($field, $oldUserId)->update([
$field => $replacementUserId,
]);
}
}
/**
* Replace User Ids on couples table.
*
* @param string $oldUserId
* @param string $replacementUserId
*
* @return void
*/
private function replaceUserOnCouplesTable($oldUserId, $replacementUserId)
{
foreach (['husband_id', 'wife_id', 'manager_id'] as $field) {
DB::table('couples')->where($field, $oldUserId)->update([
$field => $replacementUserId,
]);
}
}
}

14
app/User.php

@ -2,9 +2,9 @@
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Ramsey\Uuid\Uuid;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
@ -218,4 +218,14 @@ class User extends Authenticatable
{
return $this->belongsTo(User::class);
}
public function managedUsers()
{
return $this->hasMany(User::class, 'manager_id');
}
public function managedCouples()
{
return $this->hasMany(Couple::class, 'manager_id');
}
}

31
resources/lang/en/user.php

@ -19,14 +19,14 @@ return [
'marriages' => 'Marriages',
// Actions
'edit' => 'Edit Profile',
'set_father' => 'Set Father',
'set_mother' => 'Set Mother',
'set_parent' => 'Set Parent',
'add_spouse' => 'Add Spouse',
'add_wife' => 'Add Wife',
'add_husband' => 'Add Husband',
'add_child' => 'Add Child',
'edit' => 'Edit Profile',
'set_father' => 'Set Father',
'set_mother' => 'Set Mother',
'set_parent' => 'Set Parent',
'add_spouse' => 'Add Spouse',
'add_wife' => 'Add Wife',
'add_husband' => 'Add Husband',
'add_child' => 'Add Child',
'add_child_from_existing_couples' => 'Parent (select spouse of :name)',
// Attributes
@ -49,4 +49,17 @@ return [
// Photo
'reupload_photo' => 'Re-upload Photo',
'update_photo' => 'Update Photo',
];
// Deletion confirm attributes
'delete' => 'Delete User',
'delete_confirm' => 'Are you sure to delete this user?',
'delete_confirm_button' => 'Yes, I am sure',
'spouses_count' => 'Number of Spouse',
'childs_count' => 'Number of Child',
'managed_user' => 'Number of Managed Users',
'managed_couple' => 'Number of Managed Couples',
'replacement' => 'Replacement User',
'replace_confirm' => 'Aree you sure replace then delete this user?',
'replace_delete_text' => 'You must select other user as replacement.',
'replace_delete_button' => 'Replace and Delete User',
];

6
resources/lang/en/validation.php

@ -99,9 +99,9 @@ return [
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
'user' => [
'replacement_user_id' => [
'required' => 'Please select one.',
],
],

31
resources/lang/id/user.php

@ -19,14 +19,14 @@ return [
'marriages' => 'Pernikahan',
// Actions
'edit' => 'Edit Profil',
'set_father' => 'Set Ayah',
'set_mother' => 'Set Ibu',
'set_parent' => 'Set Orang Tua',
'add_spouse' => 'Tambah Pasangan',
'add_wife' => 'Tambah Isteri',
'add_husband' => 'Tambah Suami',
'add_child' => 'Tambah Anak',
'edit' => 'Edit Profil',
'set_father' => 'Set Ayah',
'set_mother' => 'Set Ibu',
'set_parent' => 'Set Orang Tua',
'add_spouse' => 'Tambah Pasangan',
'add_wife' => 'Tambah Isteri',
'add_husband' => 'Tambah Suami',
'add_child' => 'Tambah Anak',
'add_child_from_existing_couples' => 'Dari Pernikahan (pilih pasangan :name)',
// Attributes
@ -49,4 +49,17 @@ return [
// Photo
'reupload_photo' => 'Upload ulang Foto',
'update_photo' => 'Update Foto',
];
// Deletion confirm attributes
'delete' => 'Hapus User',
'delete_confirm' => 'Anda yakin akan menghapus user ini?',
'delete_confirm_button' => 'Saya yakin hapus user ini',
'spouses_count' => 'Jumlah Pasangan',
'childs_count' => 'Jumlah Anak',
'managed_user' => 'Jumlah User Dikelola',
'managed_couple' => 'Jumlah Pasangan Dikelola',
'replacement' => 'User Pengganti',
'replace_confirm' => 'Anda yakin mengganti dan menghapus user ini?',
'replace_delete_text' => 'Anda harus memilih user lain sebagai pengganti.',
'replace_delete_button' => 'Ganti dan Hapus User',
];

6
resources/lang/id/validation.php

@ -99,9 +99,9 @@ return [
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
'user' => [
'replacement_user_id' => [
'required' => 'Wajib dipilih.',
],
],

54
resources/views/users/edit.blade.php

@ -1,6 +1,56 @@
@extends('layouts.app')
@section('content')
@if (request('action') == 'delete' && $user)
@can('delete', $user)
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ __('user.delete') }} : {{ $user->name }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tr><td>{{ __('user.name') }}</td><td>{{ $user->name }}</td></tr>
<tr><td>{{ __('user.nickname') }}</td><td>{{ $user->nickname }}</td></tr>
<tr><td>{{ __('user.gender') }}</td><td>{{ $user->gender }}</td></tr>
<tr><td>{{ __('user.father') }}</td><td>{{ $user->father_id ? $user->father->name : '' }}</td></tr>
<tr><td>{{ __('user.mother') }}</td><td>{{ $user->mother_id ? $user->mother->name : '' }}</td></tr>
<tr><td>{{ __('user.childs_count') }}</td><td>{{ $dependentCount = $user->childs()->count() }}</td></tr>
<tr><td>{{ __('user.spouses_count') }}</td><td>{{ $dependentCount += $user->marriages()->count() }}</td></tr>
<tr><td>{{ __('user.managed_user') }}</td><td>{{ $dependentCount += $user->managedUsers()->count() }}</td></tr>
<tr><td>{{ __('user.managed_couple') }}</td><td>{{ $dependentCount += $user->managedCouples()->count() }}</td></tr>
</table>
@if ($dependentCount)
{{ __('user.replace_delete_text') }}
{{ Form::open([
'route' => ['users.destroy', $user],
'method' => 'delete',
'onsubmit' => 'return confirm("'.__('user.replace_confirm').'")',
]) }}
{!! FormField::select('replacement_user_id', $replacementUsers, [
'label' => false,
'placeholder' => __('user.replacement'),
]) !!}
{{ Form::submit(__('user.replace_delete_button'), [
'name' => 'replace_delete_button',
'class' => 'btn btn-danger',
]) }}
{{ link_to_route('users.edit', __('app.cancel'), [$user], ['class' => 'btn btn-default pull-right']) }}
{{ Form::close() }}
@else
{!! FormField::delete(
['route' => ['users.destroy', $user]],
__('user.delete_confirm_button'),
['class' => 'btn btn-danger'],
['user_id' => $user->id]
) !!}
{{ link_to_route('users.edit', __('app.cancel'), [$user], ['class' => 'btn btn-default']) }}
@endif
</div>
</div>
</div>
</div>
@endcan
@else
<h2 class="page-header">
<div class="pull-right">
{{ link_to_route('users.show', trans('app.show_profile').' '.$user->name, [$user->id], ['class' => 'btn btn-default']) }}
@ -64,6 +114,10 @@
</div>
{{ Form::close() }}
</div>
@can('delete', $user)
{{ link_to_route('users.edit', __('user.delete'), [$user, 'action' => 'delete'], ['class' => 'btn btn-danger pull-right', 'id' => 'del-user-'.$user->id]) }}
@endcan
</div>
</div>
@endif
@endsection

1
routes/web.php

@ -31,6 +31,7 @@ Route::patch('users/{user}', 'UsersController@update')->name('users.update');
Route::get('users/{user}/chart', 'UsersController@chart')->name('users.chart');
Route::get('users/{user}/tree', 'UsersController@tree')->name('users.tree');
Route::patch('users/{user}/photo-upload', 'UsersController@photoUpload')->name('users.photo-upload');
Route::delete('users/{user}', 'UsersController@destroy')->name('users.destroy');
Route::get('users/{user}/marriages', 'UserMarriagesController@index')->name('users.marriages');

256
tests/Feature/UsersDeletionTest.php

@ -0,0 +1,256 @@
<?php
namespace Tests\Feature;
use App\User;
use App\Couple;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UsersDeletionTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function manager_can_delete_a_user()
{
$manager = $this->loginAsUser();
$user = factory(User::class)->create(['manager_id' => $manager->id]);
$this->visit(route('users.edit', $user));
$this->seeElement('a', ['id' => 'del-user-'.$user->id]);
$this->click('del-user-'.$user->id);
$this->seePageIs(route('users.edit', [$user, 'action' => 'delete']));
$this->see(__('user.delete_confirm_button'));
$this->press(__('user.delete_confirm_button'));
$this->dontSeeInDatabase('users', [
'id' => $user->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_childs_father_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$oldUserChild = factory(User::class)->create(['father_id' => $oldUser->id]);
$replacementUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('users', [
'father_id' => $oldUser->id,
]);
$this->seeInDatabase('users', [
'id' => $oldUserChild->id,
'father_id' => $replacementUser->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_childs_mother_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('female')->create([
'manager_id' => $manager->id,
]);
$oldUserChild = factory(User::class)->create(['mother_id' => $oldUser->id]);
$replacementUser = factory(User::class)->states('female')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('users', [
'mother_id' => $oldUser->id,
]);
$this->seeInDatabase('users', [
'id' => $oldUserChild->id,
'mother_id' => $replacementUser->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_users_manager_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$oldUserManagedUser = factory(User::class)->create(['manager_id' => $oldUser->id]);
$replacementUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('users', [
'manager_id' => $oldUser->id,
]);
$this->seeInDatabase('users', [
'id' => $oldUserManagedUser->id,
'manager_id' => $replacementUser->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_couples_husband_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$oldUserCouple = factory(Couple::class)->create([
'husband_id' => $oldUser->id,
]);
$replacementUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('couples', [
'husband_id' => $oldUser->id,
]);
$this->seeInDatabase('couples', [
'id' => $oldUserCouple->id,
'husband_id' => $replacementUser->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_couples_wife_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('female')->create([
'manager_id' => $manager->id,
]);
$oldUserCouple = factory(Couple::class)->create([
'wife_id' => $oldUser->id,
]);
$replacementUser = factory(User::class)->states('female')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('couples', [
'wife_id' => $oldUser->id,
]);
$this->seeInDatabase('couples', [
'id' => $oldUserCouple->id,
'wife_id' => $replacementUser->id,
]);
}
/** @test */
public function manager_can_delete_a_user_the_replace_couples_manager_id()
{
$manager = $this->loginAsUser();
$oldUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$oldCoupleManagedCouple = factory(Couple::class)->create([
'manager_id' => $oldUser->id,
]);
$replacementUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$this->visit(route('users.edit', [$oldUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->submitForm(__('user.replace_delete_button'), [
'replacement_user_id' => $replacementUser->id,
]);
$this->dontSeeInDatabase('users', [
'id' => $oldUser->id,
]);
$this->dontSeeInDatabase('couples', [
'manager_id' => $oldUser->id,
]);
$this->seeInDatabase('couples', [
'id' => $oldCoupleManagedCouple->id,
'manager_id' => $replacementUser->id,
]);
}
/** @test */
public function user_replacement_options_only_available_on_same_gender()
{
$manager = $this->loginAsUser();
$maleUser = factory(User::class)->states('male')->create([
'manager_id' => $manager->id,
]);
$maleUserChild = factory(User::class)->create(['father_id' => $maleUser->id]);
$replacementMaleUser = factory(User::class)->states('male')->create();
$femaleUser = factory(User::class)->states('female')->create();
$this->visit(route('users.edit', [$maleUser, 'action' => 'delete']));
$this->see(__('user.replace_delete_text'));
$this->seeElement('option', ['value' => $replacementMaleUser->id]);
$this->dontSeeElement('option', ['value' => $femaleUser->id]);
}
}

24
tests/Unit/UserTest.php

@ -3,8 +3,10 @@
namespace Tests\Unit;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Couple;
use Tests\TestCase;
use Illuminate\Support\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
@ -81,4 +83,24 @@ class UserTest extends TestCase
$this->assertTrue($user->manager instanceof User);
}
/** @test */
public function a_user_has_many_managed_users_relation()
{
$user = factory(User::class)->create();
$managedUser = factory(User::class)->create(['manager_id' => $user->id]);
$this->assertInstanceOf(Collection::class, $user->managedUsers);
$this->assertInstanceOf(User::class, $user->managedUsers->first());
}
/** @test */
public function a_user_has_many_managed_couples_relation()
{
$user = factory(User::class)->create();
$managedCouple = factory(Couple::class)->create(['manager_id' => $user->id]);
$this->assertInstanceOf(Collection::class, $user->managedCouples);
$this->assertInstanceOf(Couple::class, $user->managedCouples->first());
}
}
Loading…
Cancel
Save