Browse Source

Add invoice duplication feature - closes #9

In this commit, we have added:
1. Duplicate Invoice button on invoice detail page
2. Invoice duplication will created as Invoice Draft in session
3. Invoice items, project, and customer same with old invoice
4. User can change invoice item as needed
5. Invoice will be saved with new invoice number
pull/12/head
Nafies Luthfi 8 years ago
parent
commit
1bec6337ee
  1. 35
      app/Http/Controllers/Invoices/DuplicationController.php
  2. 1
      resources/lang/de/invoice.php
  3. 1
      resources/lang/en/invoice.php
  4. 1
      resources/lang/id/invoice.php
  5. 1
      resources/views/invoices/show.blade.php
  6. 5
      routes/web/invoices.php
  7. 39
      tests/Feature/Invoices/InvoiceDuplicateTest.php

35
app/Http/Controllers/Invoices/DuplicationController.php

@ -0,0 +1,35 @@
<?php
namespace App\Http\Controllers\Invoices;
use App\Entities\Invoices\Invoice;
use App\Http\Controllers\Controller;
use App\Services\InvoiceDrafts\Item;
use App\Services\InvoiceDrafts\InvoiceDraft;
use App\Services\InvoiceDrafts\InvoiceDraftCollection;
class DuplicationController extends Controller
{
private $draftCollection;
public function __construct()
{
$this->draftCollection = new InvoiceDraftCollection();
}
public function store(Invoice $invoice)
{
$draft = new InvoiceDraft();
$this->draftCollection->add($draft);
foreach ($invoice->items as $existingItem) {
$item = new Item(['description' => $existingItem['description'], 'amount' => $existingItem['amount']]);
$this->draftCollection->addItemToDraft($draft->draftKey, $item);
}
$draft->date = today()->format('Y-m-d');
$draft->projectId = $invoice->project_id;
$draft->notes = $invoice->notes;
return redirect()->route('invoice-drafts.show', $draft->draftKey);
}
}

1
resources/lang/de/invoice.php

@ -22,6 +22,7 @@ return [
'save' => 'Rechnung speichern', 'save' => 'Rechnung speichern',
'created' => 'Neue Rechnung wurde erstellt.', 'created' => 'Neue Rechnung wurde erstellt.',
'show' => 'Rechnungsdetails', 'show' => 'Rechnungsdetails',
'duplicate' => 'Duplicate Invoice',
'edit' => 'Rechnung bearbeiten', 'edit' => 'Rechnung bearbeiten',
'update' => 'Rechnung aktualisieren', 'update' => 'Rechnung aktualisieren',
'updated' => 'Rechnungsdetails wurden aktualisiert.', 'updated' => 'Rechnungsdetails wurden aktualisiert.',

1
resources/lang/en/invoice.php

@ -22,6 +22,7 @@ return [
'save' => 'Save Invoice', 'save' => 'Save Invoice',
'created' => 'New Invoice has been created.', 'created' => 'New Invoice has been created.',
'show' => 'View Invoice Detail', 'show' => 'View Invoice Detail',
'duplicate' => 'Duplicate Invoice',
'edit' => 'Edit Invoice', 'edit' => 'Edit Invoice',
'update' => 'Update Invoice', 'update' => 'Update Invoice',
'updated' => 'Invoice data has been updated.', 'updated' => 'Invoice data has been updated.',

1
resources/lang/id/invoice.php

@ -22,6 +22,7 @@ return [
'save' => 'Simpan Invoice', 'save' => 'Simpan Invoice',
'created' => 'Input Invoice baru telah berhasil.', 'created' => 'Input Invoice baru telah berhasil.',
'show' => 'Lihat Detail Invoice', 'show' => 'Lihat Detail Invoice',
'duplicate' => 'Duplikat Invoice',
'edit' => 'Edit Invoice', 'edit' => 'Edit Invoice',
'update' => 'Update Invoice', 'update' => 'Update Invoice',
'updated' => 'Update data Invoice telah berhasil.', 'updated' => 'Update data Invoice telah berhasil.',

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

@ -5,6 +5,7 @@
@section('content') @section('content')
<h1 class="page-header"> <h1 class="page-header">
<div class="pull-right"> <div class="pull-right">
{!! FormField::formButton(['route' => ['invoices.duplication.store', $invoice]], __('invoice.duplicate'), ['class' => 'btn btn-default']) !!}
{{ link_to_route('invoices.edit', trans('invoice.edit'), [$invoice], ['class' => 'btn btn-warning']) }} {{ link_to_route('invoices.edit', trans('invoice.edit'), [$invoice], ['class' => 'btn btn-warning']) }}
{{ link_to_route('invoices.pdf', trans('invoice.print'), [$invoice], ['class' => 'btn btn-default']) }} {{ link_to_route('invoices.pdf', trans('invoice.print'), [$invoice], ['class' => 'btn btn-default']) }}
{{ link_to_route('projects.invoices', trans('invoice.back_to_project'), [$invoice->project_id], ['class' => 'btn btn-default']) }} {{ link_to_route('projects.invoices', trans('invoice.back_to_project'), [$invoice->project_id], ['class' => 'btn btn-default']) }}

5
routes/web/invoices.php

@ -28,4 +28,9 @@ Route::group(['middleware' => ['web', 'role:admin'], 'namespace' => 'Invoices'],
Route::post('invoices/{invoice}/items', ['as' => 'invoices.items.store', 'uses' => 'ItemsController@store']); 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::patch('invoices/{invoice}/items', ['as' => 'invoices.items.update', 'uses' => 'ItemsController@update']);
Route::delete('invoices/{invoice}/items', ['as' => 'invoices.items.destroy', 'uses' => 'ItemsController@destroy']); Route::delete('invoices/{invoice}/items', ['as' => 'invoices.items.destroy', 'uses' => 'ItemsController@destroy']);
/*
* Invoice Duplication Route
*/
Route::post('invoices/{invoice}/duplicate', ['as' => 'invoices.duplication.store', 'uses' => 'DuplicationController@store']);
}); });

39
tests/Feature/Invoices/InvoiceDuplicateTest.php

@ -0,0 +1,39 @@
<?php
namespace Tests\Feature\Invoices;
use Tests\TestCase;
use App\Entities\Invoices\Invoice;
use App\Services\InvoiceDrafts\InvoiceDraftCollection;
/**
* Invoice Duplicate Feature Test.
*
* @author Nafies Luthfi <nafiesl@gmail.com>
*/
class InvoiceDuplicateTest extends TestCase
{
/** @test */
public function user_can_create_invoice_draft_by_duplicate_existing_invoice()
{
$this->adminUserSigningIn();
$invoice = factory(Invoice::class)->create([
'items' => [
[
'description' => 'Item 1 description',
'amount' => 100000,
],
[
'description' => 'Item 1 description',
'amount' => 150000,
],
],
]);
$this->visit(route('invoices.show', $invoice));
$this->press(trans('invoice.duplicate'));
$invoiceDrafts = new InvoiceDraftCollection();
$draft = $invoiceDrafts->content()->last();
$this->seePageIs(route('invoice-drafts.show', $draft->draftKey));
}
}
Loading…
Cancel
Save