Browse Source

Add invoice edit feature

Move Invoice related controllers into Invoices namespace
Add date and due_date column on invoice date
pull/3/head
Nafies Luthfi 8 years ago
parent
commit
a813524f68
  1. 15
      app/Http/Controllers/Invoices/DraftsController.php
  2. 55
      app/Http/Controllers/Invoices/InvoicesController.php
  3. 75
      app/Http/Controllers/Invoices/ItemsController.php
  4. 30
      app/Http/Controllers/InvoicesController.php
  5. 6
      app/Services/InvoiceDraft/InvoiceDraft.php
  6. 8
      app/Services/InvoiceDraft/InvoiceDraftCollection.php
  7. 22
      database/factories/InvoiceFactory.php
  8. 17
      database/factories/ModelFactory.php
  9. 2
      database/migrations/2017_10_05_162758_create_invoices_table.php
  10. 5
      resources/lang/id/invoice.php
  11. 6
      resources/views/invoice-drafts/partials/form-draft-detail.blade.php
  12. 59
      resources/views/invoices/edit.blade.php
  13. 18
      resources/views/invoices/index.blade.php
  14. 77
      resources/views/invoices/partials/item-list.blade.php
  15. 68
      resources/views/invoices/show.blade.php
  16. 16
      resources/views/projects/invoices.blade.php
  17. 34
      routes/web/invoices.php
  18. 23
      tests/Feature/Invoices/InvoiceEntryTest.php
  19. 19
      tests/Feature/Invoices/ManageInvoiceTest.php
  20. 145
      tests/Feature/Invoices/ManageInvoicesTest.php

15
app/Http/Controllers/InvoiceDraftsController.php → app/Http/Controllers/Invoices/DraftsController.php

@ -1,8 +1,9 @@
<?php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Invoices;
use App\Entities\Projects\Project;
use App\Http\Controllers\Controller;
use App\Services\InvoiceDrafts\InvoiceDraft;
use App\Services\InvoiceDrafts\InvoiceDraftCollection;
use App\Services\InvoiceDrafts\Item;
@ -13,7 +14,7 @@ use Illuminate\Http\Request;
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoiceDraftsController extends Controller
class DraftsController extends Controller
{
private $draftCollection;
@ -119,14 +120,16 @@ class InvoiceDraftsController extends Controller
return redirect()->route('invoice-drafts.index');
}
public function proccess(Request $request, $draftKey)
public function proccess($draftKey)
{
$this->validate($request, [
'project_id' => 'required|exists:projects,id',
$invoiceData = request()->validate([
'date' => 'required|date',
'notes' => 'nullable|string|max:100',
'due_date' => 'nullable|date|after:date',
'project_id' => 'required|exists:projects,id',
]);
$draft = $this->draftCollection->updateDraftAttributes($draftKey, $request->only('project_id', 'notes'));
$draft = $this->draftCollection->updateDraftAttributes($draftKey, $invoiceData);
if ($draft->getItemsCount() == 0) {
flash(trans('invoice.item_list_empty'), 'warning')->important();

55
app/Http/Controllers/Invoices/InvoicesController.php

@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Invoices;
use App\Entities\Invoices\Invoice;
use App\Entities\Projects\Project;
use App\Http\Controllers\Controller;
/**
* Invoices Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoicesController extends Controller
{
public function index()
{
$invoices = Invoice::paginate();
return view('invoices.index', compact('invoices'));
}
public function show(Invoice $invoice)
{
return view('invoices.show', compact('invoice'));
}
public function edit(Invoice $invoice)
{
$projects = Project::pluck('name', 'id');
return view('invoices.edit', compact('invoice', 'projects'));
}
public function update(Invoice $invoice)
{
$invoiceData = request()->validate([
'project_id' => 'required|exists:projects,id',
'date' => 'required|date',
'due_date' => 'nullable|date|after:date',
'notes' => 'nullable|string|max:255',
]);
$invoice->update($invoiceData);
flash(trans('invoice.updated'), 'success');
return redirect()->route('invoices.show', $invoice);
}
public function pdf(Invoice $invoice)
{
return view('invoices.pdf', compact('invoice'));
}
}

75
app/Http/Controllers/Invoices/ItemsController.php

@ -0,0 +1,75 @@
<?php
namespace App\Http\Controllers\Invoices;
use App\Entities\Invoices\Invoice;
use App\Http\Controllers\Controller;
class ItemsController extends Controller
{
public function store(Invoice $invoice)
{
$itemData = request()->validate([
'new_item_description' => 'required|string|max:255',
'new_item_amount' => 'required|numeric',
]);
$items = $invoice->items;
$items[] = [
'description' => $itemData['new_item_description'],
'amount' => $itemData['new_item_amount'],
];
$invoice->items = $items;
$invoice->amount = collect($items)->sum('amount');
$invoice->save();
flash(trans('invoice.item_added'));
return back();
}
public function update(Invoice $invoice)
{
$rawItemData = request()->validate([
'item_key.*' => 'required|numeric',
'description.*' => 'required|string|max:255',
'amount.*' => 'required|numeric',
]);
$itemKey = array_shift($rawItemData['item_key']);
$amount = array_shift($rawItemData['amount']);
$description = array_shift($rawItemData['description']);
$items = $invoice->items;
$items[$itemKey] = [
'description' => $description,
'amount' => $amount,
];
$invoice->items = $items;
$invoice->amount = collect($items)->sum('amount');
$invoice->save();
flash(trans('invoice.item_updated'));
return back();
}
public function destroy(Invoice $invoice)
{
$itemData = request()->validate([
'item_index' => 'required|numeric',
]);
$itemIndex = $itemData['item_index'];
$items = $invoice->items;
unset($items[$itemIndex]);
$invoice->items = $items;
$invoice->amount = (int) collect($items)->sum('amount');
$invoice->save();
flash(trans('invoice.item_removed'));
return back();
}
}

30
app/Http/Controllers/InvoicesController.php

@ -1,30 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Entities\Invoices\Invoice;
/**
* Invoices Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoicesController extends Controller
{
public function index()
{
$invoices = Invoice::paginate();
return view('invoices.index', compact('invoices'));
}
public function show(Invoice $invoice)
{
return view('invoices.show', compact('invoice'));
}
public function pdf(Invoice $invoice)
{
return view('invoices.pdf', compact('invoice'));
}
}

6
app/Services/InvoiceDraft/InvoiceDraft.php

@ -13,8 +13,10 @@ class InvoiceDraft
{
public $items = [];
public $projectId;
public $date;
public $notes;
public $dueDate;
public $projectId;
public function items()
{
@ -66,6 +68,8 @@ class InvoiceDraft
$invoice->number = $invoice->generateNewNumber();
$invoice->items = $this->getItemsArray();
$invoice->project_id = $this->projectId;
$invoice->date = $this->date;
$invoice->due_date = $this->dueDate;
$invoice->amount = $this->getTotal();
$invoice->notes = $this->notes;
$invoice->status_id = 1;

8
app/Services/InvoiceDraft/InvoiceDraftCollection.php

@ -5,7 +5,7 @@ namespace App\Services\InvoiceDrafts;
use Illuminate\Support\Collection;
/**
* InvoiceDraft Collection Class.
* Invoice Draft Collection Class.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
@ -36,7 +36,7 @@ class InvoiceDraftCollection
public function add(InvoiceDraft $draft)
{
$content = $this->getContent();
$content = $this->getContent();
$draft->draftKey = str_random(10);
$content->put($draft->draftKey, $draft);
@ -57,8 +57,10 @@ class InvoiceDraftCollection
{
$content = $this->getContent();
$content[$draftKey]->date = $draftAttributes['date'];
$content[$draftKey]->notes = $draftAttributes['notes'];
$content[$draftKey]->dueDate = $draftAttributes['due_date'];
$content[$draftKey]->projectId = $draftAttributes['project_id'];
$content[$draftKey]->notes = $draftAttributes['notes'];
$this->session->put($this->instance, $content);

22
database/factories/InvoiceFactory.php

@ -0,0 +1,22 @@
<?php
use App\Entities\Invoices\Invoice;
use App\Entities\Projects\Project;
use App\Entities\Users\User;
use Faker\Generator as Faker;
$factory->define(Invoice::class, function (Faker $faker) {
return [
'project_id' => function () {
return factory(Project::class)->create()->id;
},
'number' => (new Invoice)->generateNewNumber(),
'items' => [],
'date' => '2010-10-10',
'amount' => 100000,
'status_id' => 1,
'creator_id' => function () {
return factory(User::class)->create()->id;
},
];
});

17
database/factories/ModelFactory.php

@ -1,6 +1,5 @@
<?php
use App\Entities\Invoices\Invoice;
use App\Entities\Projects\Job;
use App\Entities\Projects\Project;
use App\Entities\Projects\Task;
@ -63,19 +62,3 @@ $factory->define(Event::class, function (Faker\Generator $faker) {
'is_allday' => rand(0, 1),
];
});
$factory->define(Invoice::class, function (Faker\Generator $faker) {
return [
'project_id' => function () {
return factory(Project::class)->create()->id;
},
'number' => (new Invoice)->generateNewNumber(),
'items' => [],
'amount' => 100000,
'notes' => $faker->paragraph,
'status_id' => 1,
'creator_id' => function () {
return factory(User::class)->create()->id;
},
];
});

2
database/migrations/2017_10_05_162758_create_invoices_table.php

@ -17,6 +17,8 @@ class CreateInvoicesTable extends Migration
$table->increments('id');
$table->unsignedInteger('project_id');
$table->string('number', 8)->unique();
$table->date('date');
$table->date('due_date')->nullable();
$table->text('items');
$table->unsignedInteger('amount');
$table->string('notes')->nullable();

5
resources/lang/id/invoice.php

@ -8,6 +8,7 @@ return [
'detail' => 'Detail Invoice',
'not_found' => 'Invoice tidak ditemukan.',
'empty' => 'Belum ada Invoice',
'back_to_show' => 'Kembali ke Detail Invoice',
'back_to_index' => 'Kembali ke daftar Invoice',
'draft_list' => 'List Draft Invoice',
'draft_list_empty' => 'Draft Invoice kosong.',
@ -31,6 +32,8 @@ return [
'print' => 'Cetak Invoice',
'add_item' => 'Tambah Item',
'item_added' => 'Item berhasil ditambahkan.',
'item_updated' => 'Item berhasil diupdate.',
'item_removed' => 'Item berhasil dihapus.',
'confirm_instruction' => 'Silakan periksa rincian di bawah ini, jika belum sesuai, silakan klik kembali.',
// Attributes
@ -39,6 +42,8 @@ return [
'creator' => 'Dibuat Oleh',
'items' => 'Item Invoice',
'notes' => 'Catatan',
'date' => 'Tanggal',
'due_date' => 'Jatuh Tempo',
'amount' => 'Tagihan',
'total' => 'Total Tagihan',
'customer' => 'Customer',

6
resources/views/invoice-drafts/partials/form-draft-detail.blade.php

@ -6,7 +6,11 @@
'label' => trans('invoice.project'),
'value' => $draft->projectId,
'required' => true,
] ) !!}
]) !!}
<div class="row">
<div class="col-md-6">{!! FormField::text('date', ['label' => trans('invoice.date')]) !!}</div>
<div class="col-md-6">{!! FormField::text('due_date', ['label' => trans('invoice.due_date')]) !!}</div>
</div>
{!! FormField::textarea('notes', ['label' => trans('invoice.notes'), 'value' => $draft->notes]) !!}
</div>
<div class="panel-footer">

59
resources/views/invoices/edit.blade.php

@ -0,0 +1,59 @@
@extends('layouts.app')
@section('title', $invoice->number . ' - ' . trans('invoice.edit'))
@section('content')
<h1 class="page-header">
<div class="pull-right">
{{ link_to_route('invoices.show', trans('invoice.back_to_show'), $invoice, ['class' => 'btn btn-default']) }}
</div>
{{ $invoice->number }} <small>{{ trans('invoice.edit') }}</small>
</h1>
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.detail') }}</h3></div>
{{ Form::model($invoice, ['route' => ['invoices.update', $invoice], 'method' => 'patch']) }}
<div class="panel-body">
{!! FormField::select('project_id', $projects, ['label' => trans('project.project')]) !!}
<div class="row">
<div class="col-md-6">{!! FormField::text('date', ['label' => trans('invoice.date')]) !!}</div>
<div class="col-md-6">{!! FormField::text('due_date', ['label' => trans('invoice.due_date')]) !!}</div>
</div>
{!! FormField::textarea('notes', ['label' => trans('invoice.notes')]) !!}
</div>
<div class="panel-footer">
{{ Form::submit(trans('invoice.update'), ['class' => 'btn btn-info']) }}
{{ link_to_route('invoices.show', trans('invoice.back_to_show'), $invoice, ['class' => 'btn btn-default']) }}
</div>
{{ Form::close() }}
</div>
</div>
<div class="col-md-8">
@include('invoices.partials.item-list')
</div>
</div>
@endsection
@section('ext_css')
{!! Html::style(url('assets/css/plugins/jquery.datetimepicker.css')) !!}
@endsection
@section('ext_js')
{!! Html::script(url('assets/js/plugins/jquery.datetimepicker.js')) !!}
@endsection
@section('script')
<script>
(function() {
$('#date,#due_date').datetimepicker({
timepicker:false,
format:'Y-m-d',
closeOnDateSelect: true,
scrollInput: false
});
})();
</script>
@endsection

18
resources/views/invoices/index.blade.php

@ -36,8 +36,22 @@
<td>{{ $invoice->project->customer->nameLink() }}</td>
<td class="text-right">{{ formatRp($invoice->amount) }}</td>
<td class="text-center">
{!! html_link_to_route('invoices.show', '', [$invoice->number], ['class' => 'btn btn-info btn-xs','icon' => 'search','title' => 'Lihat ' . trans('invoice.show')]) !!}
{!! html_link_to_route('invoices.pdf', '', [$invoice->number], ['class' => 'btn btn-default btn-xs','icon' => 'print','title' => trans('invoice.print'), 'target' => '_blank']) !!}
{!! html_link_to_route(
'invoices.show', '', [$invoice->number],
[
'icon' => 'search',
'class' => 'btn btn-info btn-xs',
'title' => 'Lihat ' . trans('invoice.show')
]
) !!}
{!! html_link_to_route(
'invoices.pdf', '', [$invoice->number],
[
'icon' => 'print',
'class' => 'btn btn-default btn-xs',
'title' => trans('invoice.print'), 'target' => '_blank'
]
) !!}
</td>
</tr>
@empty

77
resources/views/invoices/partials/item-list.blade.php

@ -0,0 +1,77 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{{ trans('invoice.items') }}
<small class="text-muted">({{ count($invoice->items) }} Item)</small>
</h3>
</div>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Deskripsi</th>
<th class="text-center">Biaya</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php $no = 1?>
@foreach($invoice->items as $key => $item)
<tr>
<td>{{ $no }}</td>
<?php $no++;?>
{{ Form::open(['route' => ['invoices.items.update', $invoice], 'method' => 'patch']) }}
{{ Form::hidden('item_key['.$key.']', $key) }}
<td class="col-md-8">
{!! FormField::textarea(
'description['.$key.']',
['id' => 'description-'.$key, 'value' => $item['description'], 'label' => false]
) !!}
</td>
<td class="col-md-3">
{!! FormField::price(
'amount['.$key.']',
['id' => 'amount-'.$key, 'value' => $item['amount'], 'label' => false]
) !!}
{{ Form::submit('Update', ['id' => 'update-item-'.$key, 'class' => 'btn btn-success btn-xs pull-right']) }}
</td>
{{ Form::close() }}
<td class="col-md-1 text-center show-on-hover-parent">
{!! FormField::delete([
'route' => ['invoices.items.destroy', $invoice],
'onsubmit' => 'Yakin ingin menghapus Item ini?',
'class' => '',
], 'x', ['id' => 'remove-item-'.$key, 'class' => 'btn btn-danger btn-xs show-on-hover','title' => 'Hapus item ini'], ['item_index' => $key]) !!}
</td>
</tr>
@endforeach
<tr>
<th colspan="4">Tambah Item Invoice</th>
</tr>
<tr>
{{ Form::open(['route' => ['invoices.items.store', $invoice]]) }}
<td colspan="2">
{!! FormField::textarea(
'new_item_description',
['id' => 'new_item_description', 'label' => false, 'placeholder' => trans('invoice.item_description')]
) !!}
</td>
<td colspan="2">
{!! FormField::price(
'new_item_amount',
['id' => 'new_item_amount', 'label' => false, 'placeholder' => trans('invoice.item_amount')]
) !!}
{{ Form::submit(trans('invoice.add_item'), ['class' => 'btn btn-primary btn-block']) }}
</td>
{{ Form::close() }}
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-right">{{ trans('invoice.amount') }} :</th>
<th class="text-right">{{ formatRp($invoice->amount) }}</th>
<th></th>
</tr>
</tfoot>
</table>
</div>

68
resources/views/invoices/show.blade.php

@ -4,7 +4,10 @@
@section('content')
<h1 class="page-header">
<div class="pull-right">{{ link_to_route('invoices.pdf', trans('invoice.print'), [$invoice->number], ['class' => 'btn btn-default']) }}</div>
<div class="pull-right">
{{ link_to_route('invoices.edit', trans('invoice.edit'), [$invoice->number], ['class' => 'btn btn-warning']) }}
{{ link_to_route('invoices.pdf', trans('invoice.print'), [$invoice->number], ['class' => 'btn btn-default']) }}
</div>
{{ $invoice->number }} <small>{{ trans('invoice.detail') }}</small>
</h1>
<div class="row">
@ -14,9 +17,10 @@
<table class="table">
<tbody>
<tr><th>{{ trans('invoice.number') }}</th><td class="text-primary strong">{{ $invoice->number }}</td></tr>
<tr><th>{{ trans('app.date') }}</th><td>{{ $invoice->created_at->format('Y-m-d') }}</td></tr>
<tr><th>{{ trans('invoice.project') }}</th><td>{{ $invoice->project->name }}</td></tr>
<tr><th>{{ trans('invoice.customer') }}</th><td>{{ $invoice->project->customer->name }}</td></tr>
<tr><th>{{ trans('invoice.date') }}</th><td>{{ $invoice->date }}</td></tr>
<tr><th>{{ trans('invoice.due_date') }}</th><td>{{ $invoice->due_date }}</td></tr>
<tr><th>{{ trans('invoice.project') }}</th><td>{{ $invoice->project->nameLink() }}</td></tr>
<tr><th>{{ trans('invoice.customer') }}</th><td>{{ $invoice->project->customer->nameLink() }}</td></tr>
<tr><th>{{ trans('invoice.items_count') }}</th><td>{{ $invoice->items_count }}</td></tr>
<tr><th>{{ trans('invoice.creator') }}</th><td>{{ $invoice->creator->name }}</td></tr>
<tr><th>{{ trans('invoice.amount') }}</th><td class="text-right strong">{{ formatRp($invoice->amount) }}</td></tr>
@ -25,35 +29,35 @@
</div>
</div>
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.items') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>{{ trans('app.table_no') }}</th>
<th>{{ trans('invoice.item_description') }}</th>
<th class="text-right">{{ trans('invoice.item_amount') }}</th>
</tr>
</thead>
<tbody>
@foreach($invoice->items as $key => $item)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $item['description'] }}</td>
<td class="text-right">{{ formatRp($item['amount']) }}</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-right">{{ trans('app.total') }} :</th>
<th class="text-right">{{ formatRp($invoice->amount) }}</th>
</tr>
</tfoot>
</table>
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.items') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>{{ trans('app.table_no') }}</th>
<th>{{ trans('invoice.item_description') }}</th>
<th class="text-right">{{ trans('invoice.item_amount') }}</th>
</tr>
</thead>
<tbody>
@foreach($invoice->items as $key => $item)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $item['description'] }}</td>
<td class="text-right">{{ formatRp($item['amount']) }}</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-right">{{ trans('app.total') }} :</th>
<th class="text-right">{{ formatRp($invoice->amount) }}</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
@endsection

16
resources/views/projects/invoices.blade.php

@ -24,20 +24,20 @@
<thead>
<th class="text-center">{{ trans('app.table_no') }}</th>
<th class="col-md-2 text-center">{{ trans('invoice.number') }}</th>
<th class="col-md-2 text-center">{{ trans('app.date') }}</th>
<th class="col-md-2">{{ trans('invoice.customer') }}</th>
<th class="col-md-2">{{ trans('app.description') }}</th>
<th class="col-md-2 text-center">{{ trans('invoice.date') }}</th>
<th class="col-md-2 text-center">{{ trans('invoice.due_date') }}</th>
<th class="col-md-3">{{ trans('invoice.customer') }}</th>
<th class="col-md-2 text-right">{{ trans('invoice.amount') }}</th>
<th class="col-md-2 text-center">{{ trans('app.action') }}</th>
<th class="col-md-1 text-center">{{ trans('app.action') }}</th>
</thead>
<tbody>
@forelse($project->invoices as $key => $invoice)
<tr>
<td class="text-center">{{ 1 + $key }}</td>
<td class="text-center">{{ $invoice->number }}</td>
<td class="text-center">{{ $invoice->created_at->format('Y-m-d') }}</td>
<td>{{ $project->customer->name }}</td>
<td>{!! nl2br($invoice->description) !!}</td>
<td class="text-center">{{ $invoice->date }}</td>
<td class="text-center">{{ $invoice->due_date }}</td>
<td>{{ $project->customer->nameLink() }}</td>
<td class="text-right">{{ formatRp($invoice->amount) }}</td>
<td class="text-center">
{!! html_link_to_route('invoices.show', '', [$invoice->number], ['class' => 'btn btn-info btn-xs','icon' => 'search','title' => 'Lihat ' . trans('invoice.show')]) !!}
@ -52,7 +52,7 @@
<tr>
<th colspan="5" class="text-right">{{ trans('app.total') }}</th>
<th class="text-right">{{ formatRp($project->invoices->sum('amount')) }}</th>
<th></th>
<th>&nbsp;</th>
</tr>
</tfoot>
</table>

34
routes/web/invoices.php

@ -1,25 +1,31 @@
<?php
Route::group(['middleware' => ['web', 'role:admin']], function () {
Route::group(['middleware' => ['web', 'role:admin'], 'namespace' => 'Invoices'], function () {
/*
* Invoice Drafts Routes
*/
Route::get('invoice-drafts', 'InvoiceDraftsController@index')->name('invoice-drafts.index');
Route::get('invoice-drafts/{draftKey}', 'InvoiceDraftsController@show')->name('invoice-drafts.show');
Route::post('invoice-drafts', 'InvoiceDraftsController@create')->name('invoice-drafts.create');
Route::post('invoice-drafts/{draftKey}/add-draft-item', 'InvoiceDraftsController@addDraftItem')->name('invoice-drafts.add-draft-item');
Route::patch('invoice-drafts/{draftKey}/update-draft-item', 'InvoiceDraftsController@updateDraftItem')->name('invoice-drafts.update-draft-item');
Route::patch('invoice-drafts/{draftKey}/proccess', 'InvoiceDraftsController@proccess')->name('invoice-drafts.draft-proccess');
Route::delete('invoice-drafts/{draftKey}/remove-draft-item', 'InvoiceDraftsController@removeDraftItem')->name('invoice-drafts.remove-draft-item');
Route::delete('invoice-drafts/{draftKey}/empty-draft', 'InvoiceDraftsController@emptyDraft')->name('invoice-drafts.empty-draft');
Route::delete('invoice-drafts/{draftKey}/remove', 'InvoiceDraftsController@remove')->name('invoice-drafts.remove');
Route::delete('invoice-drafts/destroy', 'InvoiceDraftsController@destroy')->name('invoice-drafts.destroy');
Route::post('invoice-drafts/{draftKey}/store', 'InvoiceDraftsController@store')->name('invoice-drafts.store');
Route::get('invoice-drafts', 'DraftsController@index')->name('invoice-drafts.index');
Route::get('invoice-drafts/{draftKey}', 'DraftsController@show')->name('invoice-drafts.show');
Route::post('invoice-drafts', 'DraftsController@create')->name('invoice-drafts.create');
Route::post('invoice-drafts/{draftKey}/add-draft-item', 'DraftsController@addDraftItem')->name('invoice-drafts.add-draft-item');
Route::patch('invoice-drafts/{draftKey}/update-draft-item', 'DraftsController@updateDraftItem')->name('invoice-drafts.update-draft-item');
Route::patch('invoice-drafts/{draftKey}/proccess', 'DraftsController@proccess')->name('invoice-drafts.draft-proccess');
Route::delete('invoice-drafts/{draftKey}/remove-draft-item', 'DraftsController@removeDraftItem')->name('invoice-drafts.remove-draft-item');
Route::delete('invoice-drafts/{draftKey}/empty-draft', 'DraftsController@emptyDraft')->name('invoice-drafts.empty-draft');
Route::delete('invoice-drafts/{draftKey}/remove', 'DraftsController@remove')->name('invoice-drafts.remove');
Route::delete('invoice-drafts/destroy', 'DraftsController@destroy')->name('invoice-drafts.destroy');
Route::post('invoice-drafts/{draftKey}/store', 'DraftsController@store')->name('invoice-drafts.store');
/*
* Invoices Routes
*/
Route::get('invoices', ['as' => 'invoices.index', 'uses' => 'InvoicesController@index']);
Route::get('invoices/{invoice}', ['as' => 'invoices.show', 'uses' => 'InvoicesController@show']);
Route::get('invoices/{invoice}/pdf', ['as' => 'invoices.pdf', 'uses' => 'InvoicesController@pdf']);
Route::resource('invoices', 'InvoicesController');
/**
* Invoice Items Routes
*/
Route::post('invoices/{invoice}/items', ['as' => 'invoices.items.store', 'uses' => 'ItemsController@store']);
Route::patch('invoices/{invoice}/items', ['as' => 'invoices.items.update', 'uses' => 'ItemsController@update']);
Route::delete('invoices/{invoice}/items', ['as' => 'invoices.items.destroy', 'uses' => 'ItemsController@destroy']);
});

23
tests/Feature/Invoices/InvoiceEntryTest.php

@ -10,7 +10,7 @@ use App\Services\InvoiceDrafts\Item;
use Tests\TestCase;
/**
* Invoice Entry Feature Test
* Invoice Entry Feature Test.
*
* @author Nafies Luthfi <nafiesl@gmail.com>
*/
@ -136,9 +136,12 @@ class InvoiceEntryTest extends TestCase
$this->visit(route('invoice-drafts.show', $draft->draftKey));
$this->type($project->id, 'project_id');
$this->type('catatan', 'notes');
$this->press(trans('invoice.proccess'));
$this->submitForm(trans('invoice.proccess'), [
'project_id' => $project->id,
'date' => '2017-01-01',
'due_date' => '2017-01-30',
'notes' => 'catatan',
]);
$this->seePageIs(route('invoice-drafts.show', [$draft->draftKey, 'action' => 'confirm']));
@ -169,6 +172,8 @@ class InvoiceEntryTest extends TestCase
$draftAttributes = [
'project_id' => $project->id,
'date' => '2010-10-10',
'due_date' => '2010-10-30',
'notes' => 'Catatan',
];
$cart->updateDraftAttributes($draft->draftKey, $draftAttributes);
@ -177,17 +182,19 @@ class InvoiceEntryTest extends TestCase
$this->press(trans('invoice.save'));
// $this->seePageIs(route('invoices.show', date('ym').'0001'));
// $this->see(trans('invoice.created', ['invoice_no' => date('ym').'0001']));
$this->seePageIs(route('invoices.show', date('ym').'001'));
$this->see(trans('invoice.created', ['invoice_no' => date('ym').'001']));
$this->seeInDatabase('invoices', [
'project_id' => $project->id,
'number' => date('ym').'001',
'date' => '2010-10-10',
'due_date' => '2010-10-30',
'items' => '[{"description":"Deskripsi item invoice","amount":1000},{"description":"Deskripsi item invoice","amount":2000}]',
'project_id' => $project->id,
'amount' => 3000,
'notes' => 'Catatan',
'creator_id' => $user->id,
'status_id' => 1,
'creator_id' => $user->id,
]);
}
}

19
tests/Feature/Invoices/ManageInvoiceTest.php

@ -1,19 +0,0 @@
<?php
namespace Tests\Feature\Invoices;
use Tests\TestCase;
class ManageInvoiceTest extends TestCase
{
/** @test */
public function user_can_browse_invoice_list_page()
{
$this->adminUserSigningIn();
$this->visit(route('invoices.index'));
$this->seePageIs(route('invoices.index'));
$this->see(trans('invoice.list'));
}
}

145
tests/Feature/Invoices/ManageInvoicesTest.php

@ -0,0 +1,145 @@
<?php
namespace Tests\Feature\Invoices;
use App\Entities\Invoices\Invoice;
use Tests\TestCase;
/**
* Manage Invoices Feature Test.
*
* @author Nafies Luthfi <nafiesl@gmail.com>
*/
class ManageInvoicesTest extends TestCase
{
/** @test */
public function user_can_browse_invoice_list_page()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create();
$this->visit(route('invoices.index'));
$this->seePageIs(route('invoices.index'));
$this->see(trans('invoice.list'));
$this->see($invoice->number);
}
/** @test */
public function user_can_edit_invoice_data()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create();
$this->visit(route('invoices.edit', $invoice));
$this->submitForm(trans('invoice.update'), [
'project_id' => $invoice->project_id,
'date' => '2011-01-01',
'due_date' => '2011-01-30',
'notes' => 'Catatan invoice 123',
]);
$this->see(trans('invoice.updated'));
$this->seePageIs(route('invoices.show', $invoice));
$this->seeInDatabase('invoices', [
'id' => $invoice->id,
'notes' => 'Catatan invoice 123',
'date' => '2011-01-01',
'due_date' => '2011-01-30',
]);
}
/** @test */
public function user_can_add_invoice_item()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create();
$this->visit(route('invoices.edit', $invoice));
$this->submitForm(trans('invoice.add_item'), [
'new_item_description' => 'Testing deskripsi invoice item',
'new_item_amount' => 2000,
]);
$this->see(trans('invoice.item_added'));
$this->submitForm(trans('invoice.add_item'), [
'new_item_description' => 'Testing deskripsi invoice item',
'new_item_amount' => 3000,
]);
$this->see(trans('invoice.item_added'));
$this->seePageIs(route('invoices.edit', $invoice));
$this->seeInDatabase('invoices', [
'id' => $invoice->id,
'items' => '[{"description":"Testing deskripsi invoice item","amount":"2000"},{"description":"Testing deskripsi invoice item","amount":"3000"}]',
'amount' => 5000,
]);
}
/** @test */
public function user_can_update_invoice_item()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create([
'items' => [
['description' => 'Testing deskripsi invoice item', 'amount' => '1111'],
['description' => 'Testing deskripsi invoice item', 'amount' => '2222'],
],
]);
$this->visit(route('invoices.edit', $invoice));
$this->submitForm('update-item-1', [
'item_key[1]' => 1,
'description[1]' => 'Testing deskripsi Update',
'amount[1]' => 100,
]);
$this->see(trans('invoice.item_updated'));
$this->seePageIs(route('invoices.edit', $invoice));
$this->seeInDatabase('invoices', [
'id' => $invoice->id,
'items' => '[{"description":"Testing deskripsi invoice item","amount":"1111"},{"description":"Testing deskripsi Update","amount":"100"}]',
'amount' => 1211,
]);
}
/** @test */
public function user_can_remove_invoice_item()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create([
'items' => [
['description' => 'Testing deskripsi invoice item', 'amount' => '1111'],
['description' => 'Testing deskripsi invoice item', 'amount' => '2222'],
],
]);
$this->visit(route('invoices.edit', $invoice));
$this->submitForm('remove-item-1', [
'item_index' => 1,
]);
$this->see(trans('invoice.item_removed'));
$this->seePageIs(route('invoices.edit', $invoice));
$this->seeInDatabase('invoices', [
'id' => $invoice->id,
'items' => '[{"description":"Testing deskripsi invoice item","amount":"1111"}]',
'amount' => 1111,
]);
}
}
Loading…
Cancel
Save