mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Working on Quotes
This commit is contained in:
parent
0102d1a22b
commit
6d14821528
47
app/Factory/QuoteFactory.php
Normal file
47
app/Factory/QuoteFactory.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Models\Quote;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class QuoteFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :Quote
|
||||
{
|
||||
$quote = new Quote();
|
||||
$quote->status_id = Quote::STATUS_DRAFT;
|
||||
$quote->quote_number = '';
|
||||
$quote->discount = 0;
|
||||
$quote->is_amount_discount = true;
|
||||
$quote->po_number = '';
|
||||
$quote->footer = '';
|
||||
$quote->terms = '';
|
||||
$quote->public_notes = '';
|
||||
$quote->private_notes = '';
|
||||
$quote->quote_date = null;
|
||||
$quote->valid_until = null;
|
||||
$quote->partial_due_date = null;
|
||||
$quote->is_deleted = false;
|
||||
$quote->line_items = json_encode([]);
|
||||
$quote->settings = ClientSettings::buildClientSettings(new CompanySettings(CompanySettings::defaults()), new ClientSettings(ClientSettings::defaults())); //todo need to embed the settings here
|
||||
$quote->backup = json_encode([]);
|
||||
$quote->tax_name1 = '';
|
||||
$quote->tax_rate1 = 0;
|
||||
$quote->tax_name2 = '';
|
||||
$quote->tax_rate2 = 0;
|
||||
$quote->custom_value1 = 0;
|
||||
$quote->custom_value2 = 0;
|
||||
$quote->custom_value3 = 0;
|
||||
$quote->custom_value4 = 0;
|
||||
$quote->amount = 0;
|
||||
$quote->balance = 0;
|
||||
$quote->partial = 0;
|
||||
$quote->user_id = $user_id;
|
||||
$quote->company_id = $company_id;
|
||||
|
||||
return $quote;
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* ProductFilters
|
||||
* InvoiceFilters
|
||||
*/
|
||||
class InvoiceFilters extends QueryFilters
|
||||
{
|
||||
@ -45,7 +45,7 @@ class InvoiceFilters extends QueryFilters
|
||||
if(strlen($filter) == 0)
|
||||
return $this->builder;
|
||||
|
||||
$table = 'products';
|
||||
$table = 'invoices';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
|
111
app/Filters/QuoteFilters.php
Normal file
111
app/Filters/QuoteFilters.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* QuoteFilters
|
||||
*/
|
||||
class QuoteFilters extends QueryFilters
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Filter based on search text
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
* @deprecated
|
||||
*
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if(strlen($filter) == 0)
|
||||
return $this->builder;
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('quotes.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value2', 'like' , '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value3', 'like' , '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value4', 'like' , '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted
|
||||
*
|
||||
* @param string filter
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if(strlen($filter) == 0)
|
||||
return $this->builder;
|
||||
|
||||
$table = 'quotes';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table . '.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table . '.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table . '.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table . '.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table . '.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode("|", $sort);
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query
|
||||
*
|
||||
* @param int company_id
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID
|
||||
*
|
||||
* @param $company_id The company Id
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
|
||||
return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -2,18 +2,67 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Factory\QuoteFactory;
|
||||
use App\Filters\QuoteFilters;
|
||||
use App\Http\Requests\Quote\ActionQuoteRequest;
|
||||
use App\Http\Requests\Quote\CreateQuoteRequest;
|
||||
use App\Http\Requests\Quote\DestroyQuoteRequest;
|
||||
use App\Http\Requests\Quote\EditQuoteRequest;
|
||||
use App\Http\Requests\Quote\ShowQuoteRequest;
|
||||
use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||
use App\Http\Requests\Quote\UpdateQuoteRequest;
|
||||
use App\Models\Quote;
|
||||
use App\Repositories\QuoteRepository;
|
||||
use App\Transformers\QuoteTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class QuoteController
|
||||
* @package App\Http\Controllers\QuoteController
|
||||
*/
|
||||
|
||||
class QuoteController extends BaseController
|
||||
{
|
||||
|
||||
use MakesHash;
|
||||
|
||||
protected $entity_type = Quote::class;
|
||||
|
||||
protected $entity_transformer = QuoteTransformer::class;
|
||||
|
||||
/**
|
||||
* @var QuoteRepository
|
||||
*/
|
||||
protected $quote_repo;
|
||||
|
||||
protected $base_repo;
|
||||
|
||||
/**
|
||||
* QuoteController constructor.
|
||||
*
|
||||
* @param \App\Repositories\QuoteRepository $Quote_repo The Quote repo
|
||||
*/
|
||||
public function __construct(QuoteRepository $quote_repo)
|
||||
{
|
||||
|
||||
parent::__construct();
|
||||
|
||||
$this->quote_repo = $quote_repo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
public function index(QuoteFilters $filters)
|
||||
{
|
||||
//
|
||||
|
||||
$quotes = Quote::filter($filters);
|
||||
|
||||
return $this->listResponse($quotes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -21,64 +70,156 @@ class QuoteController extends BaseController
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
public function create(CreateQuoteRequest $request)
|
||||
{
|
||||
//
|
||||
|
||||
$quote = QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Http\Requests\Quote\StoreQuoteRequest $request The request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(StoreQuoteRequest $request)
|
||||
{
|
||||
//
|
||||
|
||||
$quote = $this->quote_repo->save($request, QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param \App\Http\Requests\Quote\ShowQuoteRequest $request The request
|
||||
* @param \App\Models\Quote $quote The quote
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show($id)
|
||||
public function show(ShowQuoteRequest $request, Quote $quote)
|
||||
{
|
||||
//
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param \App\Http\Requests\Quote\EditQuoteRequest $request The request
|
||||
* @param \App\Models\Quote $quote The quote
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
public function edit(EditQuoteRequest $request, Quote $quote)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @param \App\Http\Requests\Quote\UpdateQuoteRequest $request The request
|
||||
* @param \App\Models\Quote $quote The quote
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(UpdateQuoteRequest $request, Quote $quote)
|
||||
{
|
||||
//
|
||||
|
||||
$quote = $this->quote_repo->save(request(), $quote);
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \App\Http\Requests\Quote\DestroyQuoteRequest $request
|
||||
* @param \App\Models\Quote $quote
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
public function destroy(DestroyQuoteRequest $request, Quote $quote)
|
||||
{
|
||||
//
|
||||
|
||||
$quote->delete();
|
||||
|
||||
return response()->json([], 200);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
|
||||
$action = request()->input('action');
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$quotes = Quote::withTrashed()->find($ids);
|
||||
|
||||
$quotes->each(function ($quote, $key) use($action){
|
||||
|
||||
if(auth()->user()->can('edit', $quote))
|
||||
$this->quote_repo->{$action}($quote);
|
||||
|
||||
});
|
||||
|
||||
//todo need to return the updated dataset
|
||||
return $this->listResponse(Quote::withTrashed()->whereIn('id', $ids));
|
||||
|
||||
}
|
||||
|
||||
public function action(ActionQuoteRequest $request, Quote $quote, $action)
|
||||
{
|
||||
|
||||
switch ($action) {
|
||||
case 'clone_to_invoice':
|
||||
//$quote = CloneInvoiceFactory::create($quote, auth()->user()->id);
|
||||
return $this->itemResponse($quote);
|
||||
break;
|
||||
case 'clone_to_quote':
|
||||
//$quote = CloneInvoiceToQuoteFactory::create($quote, auth()->user()->id);
|
||||
// todo build the quote transformer and return response here
|
||||
break;
|
||||
case 'history':
|
||||
# code...
|
||||
break;
|
||||
case 'delivery_note':
|
||||
# code...
|
||||
break;
|
||||
case 'mark_paid':
|
||||
# code...
|
||||
break;
|
||||
case 'archive':
|
||||
# code...
|
||||
break;
|
||||
case 'delete':
|
||||
# code...
|
||||
break;
|
||||
case 'email':
|
||||
//dispatch email to queue
|
||||
break;
|
||||
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
app/Http/Requests/Quote/ActionQuoteRequest.php
Normal file
21
app/Http/Requests/Quote/ActionQuoteRequest.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class ActionQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->quote);
|
||||
}
|
||||
|
||||
}
|
21
app/Http/Requests/Quote/CreateQuoteRequest.php
Normal file
21
app/Http/Requests/Quote/CreateQuoteRequest.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class CreateQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', Quote::class);
|
||||
}
|
||||
|
||||
}
|
21
app/Http/Requests/Quote/DestroyQuoteRequest.php
Normal file
21
app/Http/Requests/Quote/DestroyQuoteRequest.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class DestroyQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->quote);
|
||||
}
|
||||
|
||||
}
|
40
app/Http/Requests/Quote/EditQuoteRequest.php
Normal file
40
app/Http/Requests/Quote/EditQuoteRequest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class EditQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->user()->can('edit', $this->quote);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
public function sanitize()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
//$input['id'] = $this->encodePrimaryKey($input['id']);
|
||||
|
||||
//$this->replace($input);
|
||||
|
||||
return $this->all();
|
||||
}
|
||||
|
||||
}
|
21
app/Http/Requests/Quote/ShowQuoteRequest.php
Normal file
21
app/Http/Requests/Quote/ShowQuoteRequest.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class ShowQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('view', $this->quote);
|
||||
}
|
||||
|
||||
}
|
41
app/Http/Requests/Quote/StoreQuoteRequest.php
Normal file
41
app/Http/Requests/Quote/StoreQuoteRequest.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Quote;
|
||||
|
||||
class StoreQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', Quote::class);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function sanitize()
|
||||
{
|
||||
//do post processing of Quote request here, ie. Quote_items
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
32
app/Http/Requests/Quote/UpdateQuoteRequest.php
Normal file
32
app/Http/Requests/Quote/UpdateQuoteRequest.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateQuoteRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
|
||||
return auth()->user()->can('edit', $this->quote);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
25
app/Policies/QuotePolicy.php
Normal file
25
app/Policies/QuotePolicy.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* Class QuotePolicy
|
||||
* @package App\Policies
|
||||
*/
|
||||
class QuotePolicy extends EntityPolicy
|
||||
{
|
||||
/**
|
||||
* Checks if the user has create permissions
|
||||
*
|
||||
* @param User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function create(User $user) : bool
|
||||
{
|
||||
return $user->isAdmin() || $user->hasPermission('create_quote');
|
||||
}
|
||||
|
||||
}
|
@ -5,10 +5,12 @@ namespace App\Providers;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\Models\Quote;
|
||||
use App\Models\User;
|
||||
use App\Policies\ClientPolicy;
|
||||
use App\Policies\InvoicePolicy;
|
||||
use App\Policies\ProductPolicy;
|
||||
use App\Policies\QuotePolicy;
|
||||
use Auth;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
@ -24,6 +26,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
Client::class => ClientPolicy::class,
|
||||
Product::class => ProductPolicy::class,
|
||||
Invoice::class => InvoicePolicy::class,
|
||||
Quote::class => QuotePolicy::class,
|
||||
User::class => UserPolicy::class,
|
||||
];
|
||||
|
||||
|
38
app/Repositories/QuoteRepository.php
Normal file
38
app/Repositories/QuoteRepository.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Helpers\Invoice\InvoiceCalc;
|
||||
use App\Models\Quote;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* QuoteRepository
|
||||
*/
|
||||
class QuoteRepository extends BaseRepository
|
||||
{
|
||||
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return Quote::class;
|
||||
}
|
||||
|
||||
public function save(Request $request, Quote $quote) : ?Quote
|
||||
{
|
||||
$quote->fill($request->input());
|
||||
|
||||
$quote->save();
|
||||
|
||||
|
||||
$invoice_calc = new InvoiceCalc($quote, $quote->settings);
|
||||
|
||||
$quote = $invoice_calc->build()->getInvoice();
|
||||
|
||||
//fire events here that cascading from the saving of an invoice
|
||||
//ie. client balance update...
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
}
|
158
app/Transformers/QuoteTransformer.php
Normal file
158
app/Transformers/QuoteTransformer.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
* @SWG\Definition(definition="quote", required={"quote_number"}, @SWG\Xml(name="quote"))
|
||||
*/
|
||||
class QuoteTransformer extends EntityTransformer
|
||||
{
|
||||
use MakesHash;
|
||||
/**
|
||||
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="amount", type="number", format="float", example=10, readOnly=true)
|
||||
* @SWG\Property(property="balance", type="number", format="float", example=10, readOnly=true)
|
||||
* @SWG\Property(property="updated_at", type="integer", example=1451160233, readOnly=true)
|
||||
* @SWG\Property(property="archived_at", type="integer", example=1451160233, readOnly=true)
|
||||
* @SWG\Property(property="is_deleted", type="boolean", example=false, readOnly=true)
|
||||
* @SWG\Property(property="client_id", type="integer", example=1)
|
||||
* @SWG\Property(property="status_id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="quote_number", type="string", example="0001")
|
||||
* @SWG\Property(property="discount", type="number", format="float", example=10)
|
||||
* @SWG\Property(property="po_number", type="string", example="0001")
|
||||
* @SWG\Property(property="quote_date", type="string", format="date", example="2018-01-01")
|
||||
* @SWG\Property(property="due_date", type="string", format="date", example="2018-01-01")
|
||||
* @SWG\Property(property="terms", type="string", example="sample")
|
||||
* @SWG\Property(property="private_notes", type="string", example="Notes")
|
||||
* @SWG\Property(property="public_notes", type="string", example="Notes")
|
||||
* @SWG\Property(property="quote_type_id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="is_recurring", type="boolean", example=false)
|
||||
* @SWG\Property(property="frequency_id", type="integer", example=1)
|
||||
* @SWG\Property(property="start_date", type="string", format="date", example="2018-01-01")
|
||||
* @SWG\Property(property="end_date", type="string", format="date", example="2018-01-01")
|
||||
* @SWG\Property(property="last_sent_date", type="string", format="date", example="2018-01-01", readOnly=true)
|
||||
* @SWG\Property(property="recurring_quote_id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="tax_name1", type="string", example="VAT")
|
||||
* @SWG\Property(property="tax_name2", type="string", example="Upkeep")
|
||||
* @SWG\Property(property="tax_rate1", type="number", format="float", example="17.5")
|
||||
* @SWG\Property(property="tax_rate2", type="number", format="float", example="30.0")
|
||||
* @SWG\Property(property="is_amount_discount", type="boolean", example=false)
|
||||
* @SWG\Property(property="quote_footer", type="string", example="Footer")
|
||||
* @SWG\Property(property="partial", type="number",format="float", example=10)
|
||||
* @SWG\Property(property="partial_due_date", type="string", format="date", example="2018-01-01")
|
||||
* @SWG\Property(property="has_tasks", type="boolean", example=false, readOnly=true)
|
||||
* @SWG\Property(property="auto_bill", type="boolean", example=false)
|
||||
* @SWG\Property(property="custom_value1", type="number",format="float", example=10)
|
||||
* @SWG\Property(property="custom_value2", type="number",format="float", example=10)
|
||||
* @SWG\Property(property="custom_taxes1", type="boolean", example=false)
|
||||
* @SWG\Property(property="custom_taxes2", type="boolean", example=false)
|
||||
* @SWG\Property(property="has_expenses", type="boolean", example=false, readOnly=true)
|
||||
* @SWG\Property(property="quote_quote_id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="custom_text_value1", type="string", example="Custom Text Value")
|
||||
* @SWG\Property(property="custom_text_value2", type="string", example="Custom Text Value")
|
||||
* @SWG\Property(property="is_quote", type="boolean", example=false, readOnly=true)
|
||||
* @SWG\Property(property="is_public", type="boolean", example=false)
|
||||
* @SWG\Property(property="filename", type="string", example="Filename", readOnly=true)
|
||||
*/
|
||||
protected $defaultIncludes = [
|
||||
// 'quote_items',
|
||||
];
|
||||
|
||||
protected $availableIncludes = [
|
||||
// 'invitations',
|
||||
// 'payments',
|
||||
// 'client',
|
||||
// 'documents',
|
||||
];
|
||||
|
||||
/*
|
||||
public function includequoteItems(quote $quote)
|
||||
{
|
||||
$transformer = new quoteItemTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($quote->quote_items, $transformer, ENTITY_quote_ITEM);
|
||||
}
|
||||
|
||||
public function includeInvitations(quote $quote)
|
||||
{
|
||||
$transformer = new InvitationTransformer($this->account, $this->serializer);
|
||||
|
||||
return $this->includeCollection($quote->invitations, $transformer, ENTITY_INVITATION);
|
||||
}
|
||||
|
||||
public function includePayments(quote $quote)
|
||||
{
|
||||
$transformer = new PaymentTransformer($this->account, $this->serializer, $quote);
|
||||
|
||||
return $this->includeCollection($quote->payments, $transformer, ENTITY_PAYMENT);
|
||||
}
|
||||
|
||||
public function includeClient(quote $quote)
|
||||
{
|
||||
$transformer = new ClientTransformer($this->account, $this->serializer);
|
||||
|
||||
return $this->includeItem($quote->client, $transformer, ENTITY_CLIENT);
|
||||
}
|
||||
|
||||
public function includeExpenses(quote $quote)
|
||||
{
|
||||
$transformer = new ExpenseTransformer($this->account, $this->serializer);
|
||||
|
||||
return $this->includeCollection($quote->expenses, $transformer, ENTITY_EXPENSE);
|
||||
}
|
||||
|
||||
public function includeDocuments(quote $quote)
|
||||
{
|
||||
$transformer = new DocumentTransformer($this->account, $this->serializer);
|
||||
|
||||
$quote->documents->each(function ($document) use ($quote) {
|
||||
$document->setRelation('quote', $quote);
|
||||
});
|
||||
|
||||
return $this->includeCollection($quote->documents, $transformer, ENTITY_DOCUMENT);
|
||||
}
|
||||
*/
|
||||
public function transform(Quote $quote)
|
||||
{
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($quote->id),
|
||||
'amount' => (float) $quote->amount,
|
||||
'balance' => (float) $quote->balance,
|
||||
'client_id' => (int) $quote->client_id,
|
||||
'status_id' => (int) ($quote->status_id ?: 1),
|
||||
'updated_at' => $quote->updated_at,
|
||||
'archived_at' => $quote->deleted_at,
|
||||
'quote_number' => $quote->quote_number,
|
||||
'discount' => (float) $quote->discount,
|
||||
'po_number' => $quote->po_number,
|
||||
'quote_date' => $quote->quote_date ?: '',
|
||||
'valid_until' => $quote->valid_until ?: '',
|
||||
'terms' => $quote->terms ?: '',
|
||||
'public_notes' => $quote->public_notes ?: '',
|
||||
'private_notes' => $quote->private_notes ?: '',
|
||||
'is_deleted' => (bool) $quote->is_deleted,
|
||||
'quote_type_id' => (int) $quote->quote_type_id,
|
||||
'tax_name1' => $quote->tax_name1 ? $quote->tax_name1 : '',
|
||||
'tax_rate1' => (float) $quote->tax_rate1,
|
||||
'tax_name2' => $quote->tax_name2 ? $quote->tax_name2 : '',
|
||||
'tax_rate2' => (float) $quote->tax_rate2,
|
||||
'is_amount_discount' => (bool) ($quote->is_amount_discount ?: false),
|
||||
'quote_footer' => $quote->quote_footer ?: '',
|
||||
'partial' => (float) ($quote->partial ?: 0.0),
|
||||
'partial_due_date' => $quote->partial_due_date ?: '',
|
||||
'custom_value1' => (float) $quote->custom_value1,
|
||||
'custom_value2' => (float) $quote->custom_value2,
|
||||
'custom_taxes1' => (bool) $quote->custom_taxes1,
|
||||
'custom_taxes2' => (bool) $quote->custom_taxes2,
|
||||
'has_tasks' => (bool) $quote->has_tasks,
|
||||
'has_expenses' => (bool) $quote->has_expenses,
|
||||
'custom_text_value1' => $quote->custom_text_value1 ?: '',
|
||||
'custom_text_value2' => $quote->custom_text_value2 ?: '',
|
||||
'backup' => $quote->backup ?: '',
|
||||
'settings' => $quote->settings,
|
||||
];
|
||||
}
|
||||
}
|
28
database/factories/QuoteFactory.php
Normal file
28
database/factories/QuoteFactory.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(App\Models\Quote::class, function (Faker $faker) {
|
||||
return [
|
||||
'status_id' => App\Models\Quote::STATUS_DRAFT,
|
||||
'quote_number' => $faker->text(256),
|
||||
'discount' => $faker->numberBetween(1,10),
|
||||
'is_amount_discount' => $faker->boolean(),
|
||||
'tax_name1' => 'GST',
|
||||
'tax_rate1' => 10,
|
||||
'tax_name2' => 'VAT',
|
||||
'tax_rate2' => 17.5,
|
||||
'custom_value1' => $faker->numberBetween(1,4),
|
||||
'custom_value2' => $faker->numberBetween(1,4),
|
||||
'custom_value3' => $faker->numberBetween(1,4),
|
||||
'custom_value4' => $faker->numberBetween(1,4),
|
||||
'is_deleted' => false,
|
||||
'po_number' => $faker->text(10),
|
||||
'quote_date' => $faker->date(),
|
||||
'valid_until' => $faker->date(),
|
||||
'line_items' => false,
|
||||
'backup' => '',
|
||||
];
|
||||
});
|
@ -485,7 +485,7 @@ class CreateUsersTable extends Migration
|
||||
|
||||
$t->string('po_number');
|
||||
$t->date('quote_date')->nullable();
|
||||
$t->date('due_date')->nullable();
|
||||
$t->date('valid_until')->nullable();
|
||||
|
||||
$t->boolean('is_deleted')->default(false);
|
||||
|
||||
|
@ -189,7 +189,7 @@ class GenerateNumberTest extends TestCase
|
||||
$this->assertEquals($this->client->getNextNumber($this->client), date('j') . '-1');
|
||||
}
|
||||
|
||||
public function testClientNumberPatternWithDate()
|
||||
public function testClientNumberPatternWithDate2()
|
||||
{
|
||||
$settings = $this->client->getSettingsByKey('client_number_pattern');
|
||||
$settings->client_number_pattern = '{$date:d M Y}-{$counter}';
|
||||
|
Loading…
Reference in New Issue
Block a user