Browse Source

Add invoice entry feature

pull/3/head
Nafies Luthfi 8 years ago
parent
commit
5d0c574387
  1. 20
      app/Http/Controllers/BackupsController.php
  2. 40
      app/Http/Controllers/InvoiceDraftsController.php
  3. 6
      app/Http/Controllers/InvoicesController.php
  4. 5
      app/Http/Controllers/Projects/FilesController.php
  5. 6
      app/Http/Controllers/Projects/InvoicesController.php
  6. 5
      app/Http/Controllers/Projects/TasksController.php
  7. 97
      app/Http/Controllers/ReportsController.php
  8. 6
      app/Http/Controllers/SubscriptionsController.php
  9. 2
      app/Http/Controllers/Users/UsersController.php
  10. 5
      app/Http/Middleware/GlobalViewVariables.php
  11. 5
      app/Http/Middleware/Role.php
  12. 7
      app/Providers/OptionServiceProvider.php
  13. 2
      app/Queries/AdminDashboardQuery.php
  14. 39
      resources/lang/id/invoice.php
  15. 37
      resources/views/invoice-drafts/index.blade.php
  16. 64
      resources/views/invoice-drafts/partials/draft-confirm.blade.php
  17. 78
      resources/views/invoice-drafts/partials/draft-item-list.blade.php
  18. 16
      resources/views/invoice-drafts/partials/form-draft-detail.blade.php
  19. 10
      resources/views/invoice-drafts/partials/invoice-draft-tabs.blade.php
  20. 29
      resources/views/invoices/create.blade.php
  21. 62
      resources/views/invoices/partials/draft-item-list.blade.php
  22. 10
      resources/views/invoices/partials/form-draft-detail.blade.php
  23. 24
      resources/views/invoices/show.blade.php
  24. 84
      resources/views/projects/invoices.blade.php
  25. 24
      routes/web/invoices.php
  26. 52
      tests/Feature/InvoiceEntryTest.php

20
app/Http/Controllers/BackupsController.php

@ -2,13 +2,17 @@
namespace App\Http\Controllers;
use App\Http\Requests\BackupUploadRequest;
use BackupManager\Filesystems\Destination;
use BackupManager\Manager;
use Illuminate\Http\Request;
use League\Flysystem\FileExistsException;
use League\Flysystem\FileNotFoundException;
/**
* Database Backups Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class BackupsController extends Controller
{
public function index(Request $request)
@ -38,8 +42,8 @@ class BackupsController extends Controller
$fileName = $request->get('file_name') ?: date('Y-m-d_Hi');
$manager->makeBackup()->run('mysql', [
new Destination('local', 'backup/db/'.$fileName),
], 'gzip');
new Destination('local', 'backup/db/'.$fileName),
], 'gzip');
flash(trans('backup.created', ['filename' => $fileName.'.gz']), 'success');
@ -80,11 +84,11 @@ class BackupsController extends Controller
public function upload(Request $request)
{
$data = $request->validate([
'backup_file' => 'required|mimetypes:application/x-gzip',
], [
'backup_file.mimetypes' => 'Invalid file type, must be <strong>.gz</strong> file',
]);
$data = $request->validate([
'backup_file' => 'required|mimetypes:application/x-gzip',
], [
'backup_file.mimetypes' => 'Invalid file type, must be <strong>.gz</strong> file',
]);
$file = $data['backup_file'];
$fileName = $file->getClientOriginalName();

40
app/Http/Controllers/InvoiceDraftController.php → app/Http/Controllers/InvoiceDraftsController.php

@ -8,7 +8,12 @@ use App\Services\InvoiceDrafts\InvoiceDraftCollection;
use App\Services\InvoiceDrafts\Item;
use Illuminate\Http\Request;
class InvoiceDraftController extends Controller
/**
* Invoice Drafts Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoiceDraftsController extends Controller
{
private $draftCollection;
@ -19,10 +24,10 @@ class InvoiceDraftController extends Controller
public function index(Request $request)
{
$draft = $this->draftCollection->content()->first();
$draft = $this->draftCollection->content()->first();
$projects = Project::pluck('name', 'id');
return view('invoices.create', compact('draft', 'projects'));
return view('invoice-drafts.index', compact('draft', 'projects'));
}
public function show(Request $request, $draftKey = null)
@ -31,18 +36,18 @@ class InvoiceDraftController extends Controller
if (is_null($draft)) {
flash(trans('invoice.draft_not_found'), 'danger');
return redirect()->route('invoices.create');
return redirect()->route('invoice-drafts.index');
}
$projects = Project::pluck('name', 'id');
return view('invoices.create', compact('draft', 'projects'));
return view('invoice-drafts.index', compact('draft', 'projects'));
}
public function add(Request $request)
public function create(Request $request)
{
$this->draftCollection->add(new InvoiceDraft());
return redirect()->route('invoices.create', $this->draftCollection->content()->last()->draftKey);
return redirect()->route('invoice-drafts.show', $this->draftCollection->content()->last()->draftKey);
}
public function addDraftItem(Request $request, $draftKey)
@ -69,23 +74,24 @@ class InvoiceDraftController extends Controller
return back();
}
function empty($draftKey) {
public function emptyDraft($draftKey)
{
$this->draftCollection->emptyDraft($draftKey);
return redirect()->route('invoices.create', $draftKey);
return redirect()->route('invoice-drafts.show', $draftKey);
}
public function remove(Request $request)
public function remove(Request $request, $draftKey)
{
$this->draftCollection->removeDraft($request->draft_key);
if ($this->draftCollection->isEmpty()) {
return redirect()->route('invoices.create-empty');
return redirect()->route('invoice-drafts.index');
}
$lastDraft = $this->draftCollection->content()->last();
return redirect()->route('invoices.create', $lastDraft->draftKey);
return redirect()->route('invoice-drafts.show', $lastDraft->draftKey);
}
public function destroy()
@ -93,7 +99,7 @@ class InvoiceDraftController extends Controller
$this->draftCollection->destroy();
flash(trans('invoice.draft_destroyed'), 'warning');
return redirect()->route('cart.index');
return redirect()->route('invoice-drafts.index');
}
public function proccess(Request $request, $draftKey)
@ -108,19 +114,19 @@ class InvoiceDraftController extends Controller
if ($draft->getItemsCount() == 0) {
flash(trans('invoice.item_list_empty'), 'warning')->important();
return redirect()->route('invoices.create', [$draftKey]);
return redirect()->route('invoice-drafts.show', [$draftKey]);
}
flash(trans('invoice.confirm_instruction', ['back_link' => link_to_route('invoices.create', trans('app.back'), $draftKey)]), 'warning')->important();
flash(trans('invoice.confirm_instruction'), 'warning')->important();
return redirect()->route('invoices.create', [$draftKey, 'action' => 'confirm']);
return redirect()->route('invoice-drafts.show', [$draftKey, 'action' => 'confirm']);
}
public function store(Request $request, $draftKey)
{
$draft = $this->draftCollection->get($draftKey);
if (is_null($draft)) {
return redirect()->route('cart.index');
return redirect()->route('invoice-drafts.index');
}
$invoice = $draft->store();

6
app/Http/Controllers/InvoicesController.php

@ -3,8 +3,12 @@
namespace App\Http\Controllers;
use App\Entities\Invoices\Invoice;
use Illuminate\Http\Request;
/**
* Invoices Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoicesController extends Controller
{
public function show(Invoice $invoice)

5
app/Http/Controllers/Projects/FilesController.php

@ -7,6 +7,11 @@ use App\Http\Controllers\Controller;
use File as FileSystem;
use Illuminate\Http\Request;
/**
* Project Files Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class FilesController extends Controller
{
private $fileableTypes = [

6
app/Http/Controllers/Projects/InvoicesController.php

@ -4,8 +4,12 @@ namespace App\Http\Controllers\Projects;
use App\Entities\Projects\Project;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
/**
* Project Invoices Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class InvoicesController extends Controller
{
public function index(Project $project)

5
app/Http/Controllers/Projects/TasksController.php

@ -8,6 +8,11 @@ use App\Http\Requests\Tasks\CreateRequest;
use App\Http\Requests\Tasks\DeleteRequest;
use App\Http\Requests\Tasks\UpdateRequest;
/**
* Project Tasks Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class TasksController extends Controller
{

97
app/Http/Controllers/ReportsController.php

@ -2,63 +2,66 @@
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Entities\Reports\ReportsRepository;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ReportsController extends Controller {
private $repo;
/**
* Reports Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class ReportsController extends Controller
{
private $repo;
public function __construct(ReportsRepository $repo)
{
$this->repo = $repo;
}
public function __construct(ReportsRepository $repo)
{
$this->repo = $repo;
}
public function index(Request $req)
{
$reports = $this->repo->getAll($req->get('q'));
return view('reports.payments.index',compact('reports'));
}
public function index(Request $req)
{
$reports = $this->repo->getAll($req->get('q'));
return view('reports.payments.index', compact('reports'));
}
public function daily(Request $req)
{
$q = $req->get('q');
$date = $req->get('date',date('Y-m-d'));
public function daily(Request $req)
{
$q = $req->get('q');
$date = $req->get('date', date('Y-m-d'));
$payments = $this->repo->getDailyReports($date, $q);
return view('reports.payments.daily', compact('payments','date'));
}
$payments = $this->repo->getDailyReports($date, $q);
return view('reports.payments.daily', compact('payments', 'date'));
}
public function monthly(Request $req)
{
$year = date('Y');
$month = date('m');
if ($req->has('year') && $req->has('month'))
{
$year = $req->get('year');
$month = $req->get('month');
}
$reports = $this->repo->getMonthlyReports($year, $month);
$months = \getMonths();
$years = \getYears();
return view('reports.payments.monthly', compact('reports','months','years','month','year'));
}
public function monthly(Request $req)
{
$year = date('Y');
$month = date('m');
if ($req->has('year') && $req->has('month')) {
$year = $req->get('year');
$month = $req->get('month');
}
$reports = $this->repo->getMonthlyReports($year, $month);
$months = \getMonths();
$years = \getYears();
return view('reports.payments.monthly', compact('reports', 'months', 'years', 'month', 'year'));
}
public function yearly(Request $req)
{
$year = $req->get('year',date('Y'));
public function yearly(Request $req)
{
$year = $req->get('year', date('Y'));
$reports = $this->repo->getYearlyReports($year);
$years = \getYears();
return view('reports.payments.yearly', compact('reports','years','year'));
}
$reports = $this->repo->getYearlyReports($year);
$years = \getYears();
return view('reports.payments.yearly', compact('reports', 'years', 'year'));
}
public function currentCredits()
{
$projects = $this->repo->getCurrentCredits();
return view('reports.current-credits', compact('projects'));
}
public function currentCredits()
{
$projects = $this->repo->getCurrentCredits();
return view('reports.current-credits', compact('projects'));
}
}

6
app/Http/Controllers/SubscriptionsController.php

@ -9,9 +9,13 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\SubscriptionRequest as FormRequest;
use Illuminate\Http\Request;
/**
* Subscriptions Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class SubscriptionsController extends Controller
{
private $repo;
public function __construct(SubscriptionsRepository $repo)

2
app/Http/Controllers/Users/UsersController.php

@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
/**
* Users Controller
* Users Controller.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/

5
app/Http/Middleware/GlobalViewVariables.php

@ -6,6 +6,11 @@ use App\Entities\Projects\Project;
use Closure;
use DB;
/**
* Global View Variables Middleware.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class GlobalViewVariables
{
/**

5
app/Http/Middleware/Role.php

@ -4,6 +4,11 @@ namespace App\Http\Middleware;
use Closure;
/**
* Role Middleware.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class Role
{
/**

7
app/Providers/OptionServiceProvider.php

@ -2,9 +2,14 @@
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\Option;
use Illuminate\Support\ServiceProvider;
/**
* Option Service Provider.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/
class OptionServiceProvider extends ServiceProvider
{
/**

2
app/Queries/AdminDashboardQuery.php

@ -9,7 +9,7 @@ use App\Entities\Subscriptions\Subscription;
use Carbon\Carbon;
/**
* AdminDashboardQuery
* Admin Dashboard Query.
*
* @author Nafies Luthfi <nafiesL@gmail.com>
*/

39
resources/lang/id/invoice.php

@ -6,26 +6,32 @@ return [
'list' => 'Daftar Invoice',
'search' => 'Cari Invoice',
'detail' => 'Detail Invoice',
'not_found' => 'Invoice tidak ditemukan',
'not_found' => 'Invoice tidak ditemukan.',
'empty' => 'Belum ada Invoice',
'back_to_index' => 'Kembali ke daftar Invoice',
'draft_not_found' => 'Draft Invoice tidak ditemukan',
'draft_list' => 'List Draft Invoice',
'draft_list_empty' => 'Draft Invoice kosong.',
'draft_not_found' => 'Draft Invoice tidak ditemukan.',
// Actions
'proccess' => 'Proses Invoice',
'item_list_empty' => 'List Item masih kosong.',
'create' => 'Input Invoice Baru',
'created' => 'Input Invoice baru telah berhasil.',
'show' => 'Detail Invoice',
'edit' => 'Edit Invoice',
'update' => 'Update Invoice',
'updated' => 'Update data Invoice telah berhasil.',
'delete' => 'Hapus Invoice',
'delete_confirm' => 'Anda yakin akan menghapus Invoice ini?',
'deleted' => 'Hapus data Invoice telah berhasil.',
'undeleted' => 'Data Invoice gagal dihapus.',
'undeleteable' => 'Data Invoice tidak dapat dihapus.',
'print' => 'Cetak Invoice',
'proccess' => 'Proses Invoice',
'item_list_empty' => 'List Item masih kosong.',
'create' => 'Input Invoice Baru',
'save' => 'Simpan Invoice',
'created' => 'Input Invoice baru telah berhasil.',
'show' => 'Detail Invoice',
'edit' => 'Edit Invoice',
'update' => 'Update Invoice',
'updated' => 'Update data Invoice telah berhasil.',
'delete' => 'Hapus Invoice',
'delete_confirm' => 'Anda yakin akan menghapus Invoice ini?',
'deleted' => 'Hapus data Invoice telah berhasil.',
'undeleted' => 'Data Invoice gagal dihapus.',
'undeleteable' => 'Data Invoice tidak dapat dihapus.',
'print' => 'Cetak Invoice',
'add-item' => 'Tambah Item',
'item_added' => 'Item berhasil ditambahkan.',
'confirm_instruction' => 'Silakan periksa rincian di bawah ini, jika belum sesuai, silakan klik kembali.',
// Attributes
'number' => 'No. Invoice',
@ -34,6 +40,7 @@ return [
'items' => 'Item Invoice',
'notes' => 'Catatan',
'amount' => 'Tagihan',
'total' => 'Total Tagihan',
'customer' => 'Customer',
'item_description' => 'Deskripsi',
'item_amount' => 'Biaya',

37
resources/views/invoice-drafts/index.blade.php

@ -0,0 +1,37 @@
@extends('layouts.app')
@section('title', 'Entry Invoice')
@section('content')
<h1 class="page-header">
<div class="pull-right">
{!! FormField::formButton(['route' => 'invoice-drafts.create'], trans('invoice.create'), [
'class' => 'btn btn-default',
'name' => 'create-invoice-draft',
'id' => 'invoice-draft-create-button'
] ) !!}
</div>
{{ trans('invoice.draft_list') }}
</h1>
<?php use Facades\App\Services\InvoiceDrafts\InvoiceDraftCollection;?>
@includeWhen(! InvoiceDraftCollection::isEmpty(), 'invoice-drafts.partials.invoice-draft-tabs')
@if ($draft)
@if (Request::get('action') == 'confirm')
@include('invoice-drafts.partials.draft-confirm')
@else
<div class="row" style="margin-top: 10px">
<div class="col-md-9">@include('invoice-drafts.partials.draft-item-list')</div>
<div class="col-md-3">@include('invoice-drafts.partials.form-draft-detail')</div>
</div>
@endif
@else
{{ trans('invoice.draft_list_empty') }}
{!! FormField::formButton(['route' => 'invoice-drafts.create'], trans('invoice.create'), [
'id' => 'invoice-draft-create-button',
'name' => 'create-invoice-draft',
'class' => 'btn btn-link',
'style' => 'padding:0px',
]) !!}
@endif
@endsection

64
resources/views/invoices/partials/draft-confirm.blade.php → resources/views/invoice-drafts/partials/draft-confirm.blade.php

@ -1,21 +1,44 @@
<div class="row">
<div class="row" style="margin-top: 10px">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.detail') }}</h3></div>
<table class="table">
<tbody>
<tr>
<td>{{ trans('invoice.project') }}</td>
<td>
{{ App\Entities\Projects\Project::findOrFail($draft->projectId)->name }}
</td>
</tr>
<tr><td>{{ trans('invoice.total') }}</td><th class="text-right">{{ formatRp($draft->getTotal()) }}</th></tr>
<tr><td>{{ trans('invoice.notes') }}</td><td>{{ $draft->notes }}</td></tr>
</tbody>
</table>
<div class="panel-footer">
{{ Form::open(['route' => ['invoice-drafts.store', $draft->draftKey]]) }}
{{ Form::submit(trans('invoice.save'), ['id' => 'save-invoice-draft', 'class' => 'btn btn-success']) }}
{{ link_to_route('invoice-drafts.show', trans('app.back'), $draft->draftKey, ['class' => 'btn btn-default']) }}
{{ Form::close() }}
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.confirm') }}</h3></div>
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.items') }}</h3></div>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Deskripsi</th>
<th class="text-right">Biaya</th>
<th>{{ trans('app.table_no') }}</th>
<th>{{ trans('invoice.item_description') }}</th>
<th class="text-right">{{ trans('invoice.item_amount') }}</th>
</tr>
</thead>
<tbody>
@forelse($draft->items() as $key => $item)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $item->description }}</td>
<td>{!! nl2br($item->description) !!}</td>
<td class="text-right">{{ formatRp($item->amount) }}</td>
</tr>
@empty
@ -23,7 +46,7 @@
</tbody>
<tfoot>
<tr>
<th colspan="5" class="text-right">{{ trans('invoice.total') }} :</th>
<th colspan="2" class="text-right">{{ trans('invoice.total') }} :</th>
<th class="text-right">{{ formatRp($draft->getTotal()) }}</th>
</tr>
</tfoot>
@ -31,29 +54,4 @@
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.detail') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr>
<td>{{ trans('invoice.project') }}</td>
<td>
{{ App\Entities\Projects\Project::findOrFail($draft->projectId)->name }}
</td>
</tr>
<tr><td>{{ trans('invoice.total') }}</td><th class="text-right">{{ formatRp($draft->getTotal()) }}</th></tr>
<tr><td>{{ trans('invoice.notes') }}</td><td>{{ $draft->notes }}</td></tr>
</tbody>
</table>
</div>
<div class="panel-footer">
{{ Form::open(['route' => ['invoices.store', $draft->draftKey]]) }}
{{ Form::submit(trans('invoice.save'), ['id' => 'save-invoice-draft', 'class' => 'btn btn-success']) }}
{{ link_to_route('invoices.create', trans('app.back'), $draft->draftKey, ['class' => 'btn btn-default']) }}
{{ Form::close() }}
</div>
</div>
</div>
</div>
</div>

78
resources/views/invoice-drafts/partials/draft-item-list.blade.php

@ -0,0 +1,78 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{{ trans('invoice.items') }}
<small class="text-muted">({{ $draft->getItemsCount() }} 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($draft->items() as $key => $item)
<tr>
<td>{{ $no }}</td>
<?php $no++;?>
{{ Form::open(['route' => ['invoice-drafts.update-draft-item', $draft->draftKey], 'method' => 'patch']) }}
{{ Form::hidden('item_key', $key) }}
<td class="col-md-8">
{!! FormField::textarea(
'description',
['id' => 'description-'.$key, 'value' => $item->description, 'label' => false]
) !!}
</td>
<td class="col-md-3">
{!! FormField::price(
'amount',
['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' => ['invoice-drafts.remove-draft-item', $draft->draftKey],
'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>
<td>&nbsp;</td>
{{ Form::open(['route' => ['invoice-drafts.add-draft-item', $draft->draftKey]]) }}
<td>
{!! FormField::textarea(
'description',
['id' => 'description', 'label' => false, 'placeholder' => 'Deskripsi Item']
) !!}
</td>
<td>
{!! FormField::price(
'amount',
['id' => 'amount', 'label' => false, 'placeholder' => 'Biaya Item']
) !!}
</td>
<td class="text-center">{{ Form::submit('add-item', ['class' => 'btn btn-primary']) }}</td>
{{ Form::close() }}
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-right">{{ trans('invoice.amount') }} :</th>
<th class="text-right">{{ formatRp($draft->getTotal()) }}</th>
<th></th>
</tr>
</tfoot>
</table>
</div>

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

@ -0,0 +1,16 @@
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.detail') }}</h3></div>
{{ Form::open(['route' => ['invoice-drafts.draft-proccess', $draft->draftKey], 'method' => 'patch']) }}
<div class="panel-body">
{!! FormField::select('project_id', $projects, [
'label' => trans('invoice.project'),
'value' => $draft->projectId,
'required' => true,
] ) !!}
{!! FormField::textarea('notes', ['label' => trans('invoice.notes'), 'value' => $draft->notes]) !!}
</div>
<div class="panel-footer">
{{ Form::submit(trans('invoice.proccess'), ['class' => 'btn btn-info']) }}
</div>
{{ Form::close() }}
</div>

10
resources/views/invoices/partials/invoice-draft-tabs.blade.php → resources/views/invoice-drafts/partials/invoice-draft-tabs.blade.php

@ -1,15 +1,15 @@
<?php use Facades\App\Services\InvoiceDrafts\InvoiceDraftCollection; ?>
<?php use Facades\App\Services\InvoiceDrafts\InvoiceDraftCollection;?>
<ul class="nav nav-tabs transaction-draft-tabs">
@foreach(InvoiceDraftCollection::content() as $key => $content)
<?php $active = ($draft->draftKey == $key) ? 'class=active' : '' ?>
<?php $active = ($draft->draftKey == $key) ? 'class=active' : ''?>
<li {{ $active }} role="presentation">
<a href="{{ route('invoices.create', $key) }}">
<a href="{{ route('invoice-drafts.show', $key) }}">
{{ trans('invoice.invoice') }} - {{ $key }}
<form action="{{ route('cart.remove') }}" method="post" style="display:inline" onsubmit="return confirm('Yakin ingin menghapus Draft Transaksi ini?')">
<form action="{{ route('invoice-drafts.remove', $key) }}" method="post" style="display:inline" onsubmit="return confirm('Yakin ingin menghapus Draft Transaksi ini?')">
{{ csrf_field() }}
{{ method_field('delete') }}
<input type="hidden" name="draft_key" value="{{ $key }}">
<input type="submit" value="x" style="margin: -2px -7px 0px 0px" class="btn-link btn-xs pull-right">
<input type="submit" id="remove_draft_{{ $key }}" value="x" style="margin: -2px -7px 0px 0px" class="btn-link btn-xs pull-right">
</form>
</a>
</li>

29
resources/views/invoices/create.blade.php

@ -1,29 +0,0 @@
@extends('layouts.app')
@section('title', 'Entry Invoice')
@section('content')
<h1 class="page-header">
<div class="pull-right">
{!! FormField::formButton(['route' => 'invoices.add'], trans('invoice.create'), [
'class' => 'btn btn-default',
'name' => 'create-invoice-draft',
'id' => 'invoice-draft-create-button'
] ) !!}
</div>
{{ trans('invoice.list') }}
</h1>
<?php use Facades\App\Services\InvoiceDrafts\InvoiceDraftCollection; ?>
@includeWhen(! InvoiceDraftCollection::isEmpty(), 'invoices.partials.invoice-draft-tabs')
@if ($draft)
@if (Request::get('action') == 'confirm')
@include('invoices.partials.draft-confirm')
@else
<div class="row">
<div class="col-md-9">@include('invoices.partials.draft-item-list')</div>
<div class="col-md-3">@include('invoices.partials.form-draft-detail')</div>
</div>
@endif
@endif
@endsection

62
resources/views/invoices/partials/draft-item-list.blade.php

@ -1,62 +0,0 @@
<legend>
{{ trans('invoice.items') }}
<small class="text-muted">
({{ $draft->getItemsCount() }} Item)
</small>
</legend>
<div class="panel panel-default">
<div class="panel-body table-responsive">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Deskripsi</th>
<th>Biaya</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php $no = 1 ?>
@forelse($draft->items() as $key => $item)
<tr>
<td>{{ $no }} <?php $no++ ?></td>
{{ Form::open(['route' => ['cart.update-draft-item', $draft->draftKey], 'method' => 'patch']) }}
{{ Form::hidden('item_key', $key) }}
<td>{{ Form::text('description', $item->description, ['id' => 'description-' . $key]) }}</td>
<td>
{{ Form::number('amount', $item->amount, ['id' => 'amount-' . $key]) }}
</td>
{{ Form::submit('update-item-' . $key, ['style'=>'display:none']) }}
{{ Form::close() }}
<td class="text-center show-on-hover-parent">
{!! FormField::delete([
'route' => ['cart.remove-draft-item', $draft->draftKey],
'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>
@empty
@endforelse
<tr>
<td></td>
{{ Form::open(['route' => ['cart.add-draft-item', $draft->draftKey]]) }}
<td>{{ Form::text('description', null, ['id' => 'description']) }}</td>
<td>
{{ Form::number('amount', null, ['id' => 'amount']) }}
</td>
<td class="text-center">{{ Form::submit('add-item', ['class' => 'btn btn-primary']) }}</td>
{{ Form::close() }}
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-right">{{ trans('invoice.amount') }} :</th>
<th class="text-right">{{ formatRp($draft->getTotal()) }}</th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>

10
resources/views/invoices/partials/form-draft-detail.blade.php

@ -1,10 +0,0 @@
<legend>{{ trans('invoice.detail') }}</legend>
{{ Form::open(['route' => ['cart.draft-proccess', $draft->draftKey], 'method' => 'patch']) }}
{!! FormField::select('project_id', $projects, [
'label' => trans('invoice.project'),
'value' => $draft->projectId,
'required' => true,
] ) !!}
{!! FormField::textarea('notes', ['label' => trans('invoice.notes'), 'value' => $draft->notes]) !!}
{{ Form::submit(trans('invoice.proccess'), ['class' => 'btn btn-info']) }}
{{ Form::close() }}

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

@ -11,19 +11,17 @@
<div class="col-sm-4">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('invoice.detail') }}</h3></div>
<div class="panel-body">
<table class="table table-condensed">
<tbody>
<tr><td>{{ trans('invoice.number') }}</td><td class="text-primary strong">{{ $invoice->number }}</td></tr>
<tr><td>{{ trans('app.date') }}</td><td>{{ $invoice->created_at->format('Y-m-d') }}</td></tr>
<tr><td>{{ trans('invoice.project') }}</td><td>{{ $invoice->project->name }}</td></tr>
<tr><td>{{ trans('invoice.customer') }}</td><td>{{ $invoice->project->customer->name }}</td></tr>
<tr><td>{{ trans('invoice.items_count') }}</td><td>{{ $invoice->items_count }}</td></tr>
<tr><td>{{ trans('invoice.creator') }}</td><td>{{ $invoice->creator->name }}</td></tr>
<tr><td>{{ trans('invoice.amount') }}</td><td class="text-right strong">{{ formatRp($invoice->amount) }}</td></tr>
</tbody>
</table>
</div>
<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.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>
</tbody>
</table>
</div>
</div>
<div class="col-sm-8">

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

@ -7,8 +7,8 @@
<h1 class="page-header">
<div class="pull-right">
{!! FormField::formButton(['route' => 'invoices.add'], trans('invoice.create'), [
'class' => 'btn btn-success',
{!! FormField::formButton(['route' => 'invoice-drafts.store'], trans('invoice.create'), [
'class' => 'btn btn-default',
'name' => 'create-invoice-draft',
'id' => 'invoice-draft-create-button'
] ) !!}
@ -18,45 +18,43 @@
@include('projects.partials.nav-tabs')
<div class="row">
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('project.invoices') }}</h3></div>
<table class="table table-condensed">
<thead>
<th>{{ 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 text-right">{{ trans('invoice.amount') }}</th>
<th>{{ trans('app.action') }}</th>
</thead>
<tbody>
@forelse($project->invoices as $key => $invoice)
<tr>
<td>{{ 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 class="text-right">{{ formatRp($invoice->amount) }}</td>
<td>
{!! 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']) !!}
</td>
</tr>
@empty
<tr><td colspan="6">{{ trans('invoice.empty') }}</td></tr>
@endforelse
</tbody>
<tfoot>
<tr>
<th colspan="4" class="text-right">{{ trans('app.total') }}</th>
<th class="text-right">{{ formatRp($project->invoices->sum('amount')) }}</th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ trans('project.invoices') }}</h3></div>
<table class="table">
<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-right">{{ trans('invoice.amount') }}</th>
<th class="col-md-2 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-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']) !!}
</td>
</tr>
@empty
<tr><td colspan="6">{{ trans('invoice.empty') }}</td></tr>
@endforelse
</tbody>
<tfoot>
<tr>
<th colspan="5" class="text-right">{{ trans('app.total') }}</th>
<th class="text-right">{{ formatRp($project->invoices->sum('amount')) }}</th>
<th></th>
</tr>
</tfoot>
</table>
</div>
@endsection
@endsection

24
routes/web/invoices.php

@ -2,19 +2,19 @@
Route::group(['middleware' => ['web', 'role:admin']], function () {
/*
* Invoice Draft Routes
* Invoice Drafts Routes
*/
Route::get('invoices/create', 'InvoiceDraftController@index')->name('invoices.create-empty');
Route::get('invoices/create/{draftKey?}', 'InvoiceDraftController@show')->name('invoices.create');
Route::post('invoices/create/{draftKey}', 'InvoiceDraftController@store')->name('invoices.store');
Route::post('invoices/add-draft', 'InvoiceDraftController@add')->name('invoices.add');
Route::post('cart/add-draft-item/{draftKey}', 'InvoiceDraftController@addDraftItem')->name('cart.add-draft-item');
Route::patch('cart/update-draft-item/{draftKey}', 'InvoiceDraftController@updateDraftItem')->name('cart.update-draft-item');
Route::patch('cart/{draftKey}/proccess', 'InvoiceDraftController@proccess')->name('cart.draft-proccess');
Route::delete('cart/remove-draft-item/{draftKey}', 'InvoiceDraftController@removeDraftItem')->name('cart.remove-draft-item');
Route::delete('cart/empty/{draftKey}', 'InvoiceDraftController@empty')->name('cart.empty');
Route::delete('cart/remove', 'InvoiceDraftController@remove')->name('cart.remove');
Route::delete('cart/destroy', 'InvoiceDraftController@destroy')->name('cart.destroy');
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');
/*
* Invoices Routes

52
tests/Feature/InvoiceEntryTest.php

@ -17,10 +17,10 @@ class InvoiceEntryTest extends TestCase
$this->adminUserSigningIn();
// Add new draft to collection
$cart = new InvoiceDraftCollection();
$cart = new InvoiceDraftCollection();
$draft = $cart->add(new InvoiceDraft());
$this->visit(route('invoices.create'));
$this->visit(route('invoice-drafts.index'));
$this->assertViewHas('draft', $draft);
}
@ -29,24 +29,24 @@ class InvoiceEntryTest extends TestCase
public function user_can_create_invoice_draft_by_invoice_create_button()
{
$this->adminUserSigningIn();
$this->visit(route('invoices.create'));
$this->visit(route('invoice-drafts.index'));
$this->press(trans('invoice.create'));
$cart = new InvoiceDraftCollection();
$cart = new InvoiceDraftCollection();
$draft = $cart->content()->last();
$this->seePageIs(route('invoices.create', $draft->draftKey));
$this->seePageIs(route('invoice-drafts.show', $draft->draftKey));
}
/** @test */
public function user_can_add_item_to_cash_draft()
public function user_can_add_item_to_invoice_draft()
{
$this->adminUserSigningIn();
$cart = new InvoiceDraftCollection();
$cart = new InvoiceDraftCollection();
$draft = new InvoiceDraft();
$cart->add($draft);
$this->visit(route('invoices.create', [$draft->draftKey]));
$this->visit(route('invoice-drafts.show', $draft->draftKey));
$this->type('Testing deskripsi invoice item', 'description');
$this->type(2000, 'amount');
@ -58,12 +58,28 @@ class InvoiceEntryTest extends TestCase
$this->type(3000, 'amount');
$this->press('add-item');
$this->seePageIs(route('invoices.create', $draft->draftKey));
$this->seePageIs(route('invoice-drafts.show', $draft->draftKey));
$this->assertEquals(5000, $draft->getTotal());
$this->see(formatRp(5000));
}
/** @test */
public function user_can_remove_an_invoice_draft()
{
$this->adminUserSigningIn();
$cart = new InvoiceDraftCollection();
$draft = new InvoiceDraft();
$cart->add($draft);
$this->visit(route('invoice-drafts.show', $draft->draftKey));
$this->press('remove_draft_'.$draft->draftKey);
$this->seePageIs(route('invoice-drafts.index'));
$this->assertTrue($cart->isEmpty());
}
/** @test */
public function user_can_update_item_attribute()
{
$cart = new InvoiceDraftCollection();
@ -78,7 +94,7 @@ class InvoiceEntryTest extends TestCase
$cart->addItemToDraft($draft->draftKey, $item2);
$this->adminUserSigningIn();
$this->visit(route('invoices.create', $draft->draftKey));
$this->visit(route('invoice-drafts.show', $draft->draftKey));
$this->submitForm('update-item-0', [
'item_key' => 0,
@ -100,9 +116,9 @@ class InvoiceEntryTest extends TestCase
/** @test */
public function user_can_update_draft_invoice_detail_and_get_confirm_page()
{
$user = $this->adminUserSigningIn();
$user = $this->adminUserSigningIn();
$project = factory(Project::class)->create();
$cart = new InvoiceDraftCollection();
$cart = new InvoiceDraftCollection();
$draft = $cart->add(new InvoiceDraft());
@ -113,15 +129,15 @@ class InvoiceEntryTest extends TestCase
$cart->addItemToDraft($draft->draftKey, $item1);
$cart->addItemToDraft($draft->draftKey, $item2);
$this->visit(route('invoices.create', $draft->draftKey));
$this->visit(route('invoice-drafts.show', $draft->draftKey));
$this->type($project->id, 'project_id');
$this->type('catatan', 'notes');
$this->press(trans('invoice.proccess'));
$this->seePageIs(route('invoices.create', [$draft->draftKey, 'action' => 'confirm']));
$this->seePageIs(route('invoice-drafts.show', [$draft->draftKey, 'action' => 'confirm']));
$this->see(trans('invoice.confirm'));
$this->see(trans('invoice.confirm_instruction'));
$this->see($project->name);
$this->see($draft->notes);
$this->see(formatRp(3000));
@ -138,9 +154,9 @@ class InvoiceEntryTest extends TestCase
$item1 = new Item(['description' => 'Deskripsi item invoice', 'amount' => 1000]);
$item2 = new Item(['description' => 'Deskripsi item invoice', 'amount' => 2000]);
$user = $this->adminUserSigningIn();
$user = $this->adminUserSigningIn();
$customer = factory(Customer::class)->create();
$project = factory(Project::class)->create(['customer_id' => $customer->id]);
$project = factory(Project::class)->create(['customer_id' => $customer->id]);
// Add items to draft
$cart->addItemToDraft($draft->draftKey, $item1);
@ -152,7 +168,7 @@ class InvoiceEntryTest extends TestCase
];
$cart->updateDraftAttributes($draft->draftKey, $draftAttributes);
$this->visit(route('invoices.create', [$draft->draftKey, 'action' => 'confirm']));
$this->visit(route('invoice-drafts.show', [$draft->draftKey, 'action' => 'confirm']));
$this->press(trans('invoice.save'));

Loading…
Cancel
Save