diff --git a/.travis.yml b/.travis.yml index 9e8b983e795d..083bbe4f2583 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,7 +89,8 @@ after_script: - mysql -u root -e 'select * from invoice_items;' ninja - mysql -u root -e 'select * from payments;' ninja - mysql -u root -e 'select * from credits;' ninja - - cat storage/logs/laravel.log + - cat storage/logs/laravel-error.log + - cat storage/logs/laravel-info.log notifications: email: diff --git a/app/Commands/Command.php b/app/Commands/Command.php index 5bc48501167e..d6a8d61150ae 100644 --- a/app/Commands/Command.php +++ b/app/Commands/Command.php @@ -1,4 +1,4 @@ -where('public_id', '=', $clientPublicId); + }; + $query->whereHas('client', $filter); + } + + if ( ! Utils::hasPermission('view_all')){ + if ($this->entityType == ENTITY_USER) { + $query->where('id', '=', Auth::user()->id); + } else { + $query->where('user_id', '=', Auth::user()->id); + } + } + + $transformerClass = EntityModel::getTransformerName($this->entityType); + $transformer = new $transformerClass(Auth::user()->account, Input::get('serializer')); + + $data = $this->createCollection($query, $transformer, $this->entityType); + + //return \DB::getQueryLog(); + return $this->response($data); + } + protected function createItem($data, $transformer, $entityType) { if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) { @@ -74,18 +105,19 @@ class BaseAPIController extends Controller return $this->manager->createData($resource)->toArray(); } - protected function createCollection($data, $transformer, $entityType, $paginator = false) + protected function createCollection($query, $transformer, $entityType) { if ($this->serializer && $this->serializer != API_SERIALIZER_JSON) { $entityType = null; } - $resource = new Collection($data, $transformer, $entityType); - - if ($paginator) { - $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + if (is_a($query, "Illuminate\Database\Eloquent\Builder")) { + $resource = new Collection($query->get(), $transformer, $entityType); + $resource->setPaginator(new IlluminatePaginatorAdapter($query->paginate())); + } else { + $resource = new Collection($query, $transformer, $entityType); } - + return $this->manager->createData($resource)->toArray(); } diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index a9060e47fdec..4a33946c7631 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -3,13 +3,15 @@ use App\Http\Middleware\PermissionsRequired; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Input; use Auth; +use Utils; class BaseController extends Controller { use DispatchesJobs, AuthorizesRequests; - protected $entity; + protected $entityType; /** * Setup the layout used by the controller. @@ -24,17 +26,23 @@ class BaseController extends Controller } protected function authorizeCreate() { - $this->authorize('create', $this->entity); + $this->authorize('create', $this->entityType); } + /* + protected function authorizeUpdate($entity) { + $this->authorize('edit', $entity); + } + */ + protected function authorizeUpdate($input){ $creating = empty($input['public_id']) || $input['public_id'] == '-1'; if($creating){ - $this->authorize('create', $this->entity); + $this->authorize('create', $this->entityType); } else{ - $className = ucwords($this->entity, '_'); + $className = Utils::getEntityName($this->entityType); $object = call_user_func(array("App\\Models\\{$className}", 'scope'), $input['public_id'])->firstOrFail(); $this->authorize('edit', $object); diff --git a/app/Http/Controllers/ClientApiController.php b/app/Http/Controllers/ClientApiController.php index fd3b33df6aa5..4457973c7031 100644 --- a/app/Http/Controllers/ClientApiController.php +++ b/app/Http/Controllers/ClientApiController.php @@ -18,6 +18,8 @@ class ClientApiController extends BaseAPIController protected $clientRepo; protected $clientService; + protected $entityType = ENTITY_CLIENT; + public function __construct(ClientRepository $clientRepo, ClientService $clientService) { parent::__construct(); @@ -53,26 +55,17 @@ class ClientApiController extends BaseAPIController { $clients = Client::scope() ->with($this->getIncluded()) - ->orderBy('created_at', 'desc')->withTrashed(); + ->orderBy('created_at', 'desc') + ->withTrashed(); // Filter by email - if (Input::has('email')) { - - $email = Input::get('email'); + if ($email = Input::get('email')) { $clients = $clients->whereHas('contacts', function ($query) use ($email) { $query->where('email', $email); }); - } - - $clients = $clients->paginate(); - - $transformer = new ClientTransformer(Auth::user()->account, Input::get('serializer')); - $paginator = Client::scope()->withTrashed()->paginate(); - - $data = $this->createCollection($clients, $transformer, ENTITY_CLIENT, $paginator); - - return $this->response($data); + + return $this->returnList($clients); } /** @@ -206,7 +199,6 @@ class ClientApiController extends BaseAPIController public function destroy($publicId) { - $client = Client::scope($publicId)->withTrashed()->first(); $this->clientRepo->delete($client); @@ -219,8 +211,6 @@ class ClientApiController extends BaseAPIController $data = $this->createItem($client, $transformer, ENTITY_CLIENT); return $this->response($data); - } - -} +} \ No newline at end of file diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 49988ab78b79..90aedfb897c2 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -28,6 +28,7 @@ use App\Models\Task; use App\Ninja\Repositories\ClientRepository; use App\Services\ClientService; +use App\Http\Requests\ClientRequest; use App\Http\Requests\CreateClientRequest; use App\Http\Requests\UpdateClientRequest; @@ -35,7 +36,7 @@ class ClientController extends BaseController { protected $clientService; protected $clientRepo; - protected $entity = ENTITY_CLIENT; + protected $entityType = ENTITY_CLIENT; public function __construct(ClientRepository $clientRepo, ClientService $clientService) { @@ -81,11 +82,7 @@ class ClientController extends BaseController */ public function store(CreateClientRequest $request) { - $data = $request->input(); - - $this->authorizeUpdate($data); - - $client = $this->clientService->save($data); + $client = $this->clientService->save($request->input()); Session::flash('message', trans('texts.created_client')); @@ -98,11 +95,9 @@ class ClientController extends BaseController * @param int $id * @return Response */ - public function show($publicId) + public function show(ClientRequest $request) { - $client = Client::withTrashed()->scope($publicId)->with('contacts', 'size', 'industry')->firstOrFail(); - - $this->authorize('view', $client); + $client = $request->entity(); $user = Auth::user(); Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT); @@ -151,10 +146,8 @@ class ClientController extends BaseController * * @return Response */ - public function create() + public function create(ClientRequest $request) { - $this->authorizeCreate(); - if (Client::scope()->withTrashed()->count() > Auth::user()->getMaxNumClients()) { return View::make('error', ['hideHeader' => true, 'error' => "Sorry, you've exceeded the limit of ".Auth::user()->getMaxNumClients()." clients"]); } @@ -177,16 +170,14 @@ class ClientController extends BaseController * @param int $id * @return Response */ - public function edit($publicId) + public function edit(ClientRequest $request) { - $client = Client::scope($publicId)->with('contacts')->firstOrFail(); - - $this->authorize('edit', $client); - + $client = $request->entity(); + $data = [ 'client' => $client, 'method' => 'PUT', - 'url' => 'clients/'.$publicId, + 'url' => 'clients/'.$client->public_id, 'title' => trans('texts.edit_client'), ]; @@ -225,11 +216,7 @@ class ClientController extends BaseController */ public function update(UpdateClientRequest $request) { - $data = $request->input(); - - $this->authorizeUpdate($data); - - $client = $this->clientService->save($data); + $client = $this->clientService->save($request->input(), $request->entity()); Session::flash('message', trans('texts.updated_client')); diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 23577f951389..c4250903fd32 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -12,12 +12,13 @@ use App\Models\Client; use App\Services\CreditService; use App\Ninja\Repositories\CreditRepository; use App\Http\Requests\CreateCreditRequest; +use App\Http\Requests\CreditRequest; class CreditController extends BaseController { protected $creditRepo; protected $creditService; - protected $entity = ENTITY_CREDIT; + protected $entityType = ENTITY_CREDIT; public function __construct(CreditRepository $creditRepo, CreditService $creditService) { @@ -55,23 +56,21 @@ class CreditController extends BaseController return $this->creditService->getDatatable($clientPublicId, Input::get('sSearch')); } - public function create($clientPublicId = 0) + public function create(CreditRequest $request) { - $this->authorizeCreate(); - $data = array( - 'clientPublicId' => Input::old('client') ? Input::old('client') : $clientPublicId, - //'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : $invoicePublicId, + 'clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0), 'credit' => null, 'method' => 'POST', 'url' => 'credits', 'title' => trans('texts.new_credit'), - //'invoices' => Invoice::scope()->with('client', 'invoice_status')->orderBy('invoice_number')->get(), - 'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), ); + 'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), + ); return View::make('credits.edit', $data); } + /* public function edit($publicId) { $credit = Credit::scope($publicId)->firstOrFail(); @@ -90,7 +89,8 @@ class CreditController extends BaseController return View::make('credit.edit', $data); } - + */ + public function store(CreateCreditRequest $request) { $credit = $this->creditRepo->save($request->input()); diff --git a/app/Http/Controllers/DocumentController.php b/app/Http/Controllers/DocumentController.php index c0e25e773d11..d597ba004474 100644 --- a/app/Http/Controllers/DocumentController.php +++ b/app/Http/Controllers/DocumentController.php @@ -12,10 +12,13 @@ use Response; use App\Models\Document; use App\Ninja\Repositories\DocumentRepository; +use App\Http\Requests\DocumentRequest; +use App\Http\Requests\CreateDocumentRequest; + class DocumentController extends BaseController { protected $documentRepo; - protected $entity = ENTITY_DOCUMENT; + protected $entityType = ENTITY_DOCUMENT; public function __construct(DocumentRepository $documentRepo) { @@ -24,14 +27,9 @@ class DocumentController extends BaseController $this->documentRepo = $documentRepo; } - public function get($publicId) + public function get(DocumentRequest $request) { - $document = Document::scope($publicId) - ->firstOrFail(); - - $this->authorize('view', $document); - - return static::getDownloadResponse($document); + return static::getDownloadResponse($request->entity()); } public static function getDownloadResponse($document){ @@ -60,12 +58,9 @@ class DocumentController extends BaseController return $response; } - public function getPreview($publicId) + public function getPreview(DocumentRequest $request) { - $document = Document::scope($publicId) - ->firstOrFail(); - - $this->authorize('view', $document); + $document = $request->entity(); if(empty($document->preview)){ return Response::view('error', array('error'=>'Preview does not exist!'), 404); @@ -83,16 +78,14 @@ class DocumentController extends BaseController return $response; } - public function getVFSJS($publicId, $name){ - $document = Document::scope($publicId) - ->firstOrFail(); + public function getVFSJS(DocumentRequest $request, $publicId, $name) + { + $document = $request->entity(); if(substr($name, -3)=='.js'){ $name = substr($name, 0, -3); } - $this->authorize('view', $document); - if(!$document->isPDFEmbeddable()){ return Response::view('error', array('error'=>'Image does not exist!'), 404); } @@ -106,14 +99,12 @@ class DocumentController extends BaseController return $response; } - public function postUpload() + public function postUpload(CreateDocumentRequest $request) { if (!Utils::hasFeature(FEATURE_DOCUMENTS)) { return; } - $this->authorizeCreate(); - $result = $this->documentRepo->upload(Input::all()['file'], $doc_array); if(is_string($result)){ diff --git a/app/Http/Controllers/ExpenseApiController.php b/app/Http/Controllers/ExpenseApiController.php index 88ff5497cefd..9b1a7e906244 100644 --- a/app/Http/Controllers/ExpenseApiController.php +++ b/app/Http/Controllers/ExpenseApiController.php @@ -1,5 +1,5 @@ withTrashed() ->orderBy('created_at','desc'); - $expenses = $expenses->paginate(); - - $transformer = new ExpenseTransformer(Auth::user()->account, Input::get('serializer')); - $paginator = Expense::scope()->withTrashed()->paginate(); - - $data = $this->createCollection($expenses, $transformer, ENTITY_EXPENSE, $paginator); - - return $this->response($data); - + return $this->returnList($expenses); } public function update() diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index e53122e46dcb..406613489c6b 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -17,6 +17,8 @@ use App\Models\Expense; use App\Models\Client; use App\Services\ExpenseService; use App\Ninja\Repositories\ExpenseRepository; + +use App\Http\Requests\ExpenseRequest; use App\Http\Requests\CreateExpenseRequest; use App\Http\Requests\UpdateExpenseRequest; @@ -25,7 +27,7 @@ class ExpenseController extends BaseController // Expenses protected $expenseRepo; protected $expenseService; - protected $entity = ENTITY_EXPENSE; + protected $entityType = ENTITY_EXPENSE; public function __construct(ExpenseRepository $expenseRepo, ExpenseService $expenseService) { @@ -69,17 +71,16 @@ class ExpenseController extends BaseController return $this->expenseService->getDatatableVendor($vendorPublicId); } - public function create($vendorPublicId = null, $clientPublicId = null) + public function create(ExpenseRequest $request) { - $this->authorizeCreate(); - - if($vendorPublicId != 0) { - $vendor = Vendor::scope($vendorPublicId)->with('vendorcontacts')->firstOrFail(); + if ($request->vendor_id != 0) { + $vendor = Vendor::scope($request->vendor_id)->with('vendorcontacts')->firstOrFail(); } else { $vendor = null; } + $data = array( - 'vendorPublicId' => Input::old('vendor') ? Input::old('vendor') : $vendorPublicId, + 'vendorPublicId' => Input::old('vendor') ? Input::old('vendor') : $request->vendor_id, 'expense' => null, 'method' => 'POST', 'url' => 'expenses', @@ -87,20 +88,18 @@ class ExpenseController extends BaseController 'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(), 'vendor' => $vendor, 'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), - 'clientPublicId' => $clientPublicId, - ); + 'clientPublicId' => $request->client_id, + ); $data = array_merge($data, self::getViewModel()); return View::make('expenses.edit', $data); } - public function edit($publicId) + public function edit(ExpenseRequest $request) { - $expense = Expense::scope($publicId)->with('documents')->firstOrFail(); - - $this->authorize('edit', $expense); - + $expense = $request->entity(); + $expense->expense_date = Utils::fromSqlDate($expense->expense_date); $actions = []; @@ -108,15 +107,6 @@ class ExpenseController extends BaseController $actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans("texts.view_invoice")]; } else { $actions[] = ['url' => 'javascript:submitAction("invoice")', 'label' => trans("texts.invoice_expense")]; - - /* - // check for any open invoices - $invoices = $task->client_id ? $this->invoiceRepo->findOpenInvoices($task->client_id) : []; - - foreach ($invoices as $invoice) { - $actions[] = ['url' => 'javascript:submitAction("add_to_invoice", '.$invoice->public_id.')', 'label' => trans("texts.add_to_invoice", ["invoice" => $invoice->invoice_number])]; - } - */ } $actions[] = \DropdownButton::DIVIDER; @@ -131,7 +121,7 @@ class ExpenseController extends BaseController 'vendor' => null, 'expense' => $expense, 'method' => 'PUT', - 'url' => 'expenses/'.$publicId, + 'url' => 'expenses/'.$expense->public_id, 'title' => 'Edit Expense', 'actions' => $actions, 'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(), @@ -155,10 +145,8 @@ class ExpenseController extends BaseController { $data = $request->input(); $data['documents'] = $request->file('documents'); - - $this->authorizeUpdate($data); - - $expense = $this->expenseService->save($data, true); + + $expense = $this->expenseService->save($data); Session::flash('message', trans('texts.updated_expense')); @@ -174,9 +162,7 @@ class ExpenseController extends BaseController { $data = $request->input(); $data['documents'] = $request->file('documents'); - - $this->authorizeUpdate($data); - + $expense = $this->expenseService->save($data); Session::flash('message', trans('texts.created_expense')); diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 38618475064b..fe006332ca48 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -1,4 +1,4 @@ -withTrashed(); - $invoices = Invoice::scope()->withTrashed() - ->with(array_merge(['invoice_items'], $this->getIncluded())); + $invoices = Invoice::scope() + ->withTrashed() + ->with(array_merge(['invoice_items'], $this->getIncluded())) + ->orderBy('created_at', 'desc'); - if ($clientPublicId = Input::get('client_id')) { - $filter = function($query) use ($clientPublicId) { - $query->where('public_id', '=', $clientPublicId); - }; - $invoices->whereHas('client', $filter); - $paginator->whereHas('client', $filter); - } - - $invoices = $invoices->orderBy('created_at', 'desc')->paginate(); - - /* - // Add the first invitation link to the data - foreach ($invoices as $key => $invoice) { - foreach ($invoice->invitations as $subKey => $invitation) { - $invoices[$key]['link'] = $invitation->getLink(); - } - unset($invoice['invitations']); - } - */ - - $transformer = new InvoiceTransformer(Auth::user()->account, Input::get('serializer')); - $paginator = $paginator->paginate(); - - $data = $this->createCollection($invoices, $transformer, 'invoices', $paginator); - - return $this->response($data); + return $this->returnList($invoices); } /** @@ -106,7 +84,6 @@ class InvoiceApiController extends BaseAPIController public function show($publicId) { - $invoice = Invoice::scope($publicId)->withTrashed()->first(); if(!$invoice) @@ -139,7 +116,7 @@ class InvoiceApiController extends BaseAPIController * ) * ) */ - public function store(CreateInvoiceRequest $request) + public function store(CreateInvoiceAPIRequest $request) { $data = Input::all(); $error = null; @@ -351,7 +328,7 @@ class InvoiceApiController extends BaseAPIController * ) * ) */ - public function update(UpdateInvoiceRequest $request, $publicId) + public function update(UpdateInvoiceAPIRequest $request, $publicId) { if ($request->action == ACTION_ARCHIVE) { $invoice = Invoice::scope($publicId)->firstOrFail(); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 79ce2aee93b1..1a652ae8962c 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -27,7 +27,10 @@ use App\Ninja\Repositories\ClientRepository; use App\Ninja\Repositories\DocumentRepository; use App\Services\InvoiceService; use App\Services\RecurringInvoiceService; -use App\Http\Requests\SaveInvoiceWithClientRequest; + +use App\Http\Requests\InvoiceRequest; +use App\Http\Requests\CreateInvoiceRequest; +use App\Http\Requests\UpdateInvoiceRequest; class InvoiceController extends BaseController { @@ -37,7 +40,7 @@ class InvoiceController extends BaseController protected $documentRepo; protected $invoiceService; protected $recurringInvoiceService; - protected $entity = ENTITY_INVOICE; + protected $entityType = ENTITY_INVOICE; public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, InvoiceService $invoiceService, DocumentRepository $documentRepo, RecurringInvoiceService $recurringInvoiceService) { @@ -88,18 +91,13 @@ class InvoiceController extends BaseController return $this->recurringInvoiceService->getDatatable($accountId, $clientPublicId, ENTITY_RECURRING_INVOICE, $search); } - public function edit($publicId, $clone = false) + public function edit(InvoiceRequest $request, $publicId, $clone = false) { $account = Auth::user()->account; - $invoice = Invoice::scope($publicId) - ->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items', 'documents', 'expenses', 'expenses.documents', 'payments') - ->withTrashed() - ->firstOrFail(); - - $this->authorize('edit', $invoice); + $invoice = $request->entity()->load('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items', 'documents', 'expenses', 'expenses.documents', 'payments'); $entityType = $invoice->getEntityType(); - + $contactIds = DB::table('invitations') ->join('contacts', 'contacts.id', '=', 'invitations.contact_id') ->where('invitations.invoice_id', '=', $invoice->id) @@ -120,7 +118,7 @@ class InvoiceController extends BaseController } else { Utils::trackViewed($invoice->getDisplayName().' - '.$invoice->client->getDisplayName(), $invoice->getEntityType()); $method = 'PUT'; - $url = "{$entityType}s/{$publicId}"; + $url = "{$entityType}s/{$invoice->public_id}"; $clients->whereId($invoice->client_id); } @@ -229,28 +227,27 @@ class InvoiceController extends BaseController return View::make('invoices.edit', $data); } - public function create($clientPublicId = 0, $isRecurring = false) + public function create(InvoiceRequest $request, $clientPublicId = 0, $isRecurring = false) { - $this->authorizeCreate(); - $account = Auth::user()->account; + $entityType = $isRecurring ? ENTITY_RECURRING_INVOICE : ENTITY_INVOICE; $clientId = null; - if ($clientPublicId) { - $clientId = Client::getPrivateId($clientPublicId); + if ($request->client_id) { + $clientId = Client::getPrivateId($request->client_id); } $invoice = $account->createInvoice($entityType, $clientId); $invoice->public_id = 0; - if(Session::get('expenses')){ + if (Session::get('expenses')) { $invoice->expenses = Expense::scope(Session::get('expenses'))->with('documents')->get(); } $clients = Client::scope()->with('contacts', 'country')->orderBy('name'); - if(!Auth::user()->hasPermission('view_all')){ + if (!Auth::user()->hasPermission('view_all')) { $clients = $clients->where('clients.user_id', '=', Auth::user()->id); } @@ -267,9 +264,9 @@ class InvoiceController extends BaseController return View::make('invoices.edit', $data); } - public function createRecurring($clientPublicId = 0) + public function createRecurring(InvoiceRequest $request, $clientPublicId = 0) { - return self::create($clientPublicId, true); + return self::create($request, $clientPublicId, true); } private static function getViewModel($invoice) @@ -395,7 +392,7 @@ class InvoiceController extends BaseController * * @return Response */ - public function store(SaveInvoiceWithClientRequest $request) + public function store(CreateInvoiceRequest $request) { $data = $request->input(); $data['documents'] = $request->file('documents'); @@ -405,7 +402,7 @@ class InvoiceController extends BaseController $action = Input::get('action'); $entityType = Input::get('entityType'); - $invoice = $this->invoiceService->save($data, true); + $invoice = $this->invoiceService->save($data); $entityType = $invoice->getEntityType(); $message = trans("texts.created_{$entityType}"); @@ -434,7 +431,7 @@ class InvoiceController extends BaseController * @param int $id * @return Response */ - public function update(SaveInvoiceWithClientRequest $request) + public function update(UpdateInvoiceRequest $request) { $data = $request->input(); $data['documents'] = $request->file('documents'); @@ -444,15 +441,15 @@ class InvoiceController extends BaseController $action = Input::get('action'); $entityType = Input::get('entityType'); - $invoice = $this->invoiceService->save($data, true); + $invoice = $this->invoiceService->save($data); $entityType = $invoice->getEntityType(); $message = trans("texts.updated_{$entityType}"); Session::flash('message', $message); if ($action == 'clone') { - return $this->cloneInvoice($invoice->public_id); + return $this->cloneInvoice($request, $invoice->public_id); } elseif ($action == 'convert') { - return $this->convertQuote($invoice->public_id); + return $this->convertQuote($request, $invoice->public_id); } elseif ($action == 'email') { return $this->emailInvoice($invoice, Input::get('pdfupload')); } @@ -521,7 +518,7 @@ class InvoiceController extends BaseController { Session::reflash(); - return Redirect::to("invoices/{$publicId}/edit"); + return Redirect::to("invoices/$publicId/edit"); } /** @@ -549,18 +546,18 @@ class InvoiceController extends BaseController } } - public function convertQuote($publicId) + public function convertQuote(InvoiceRequest $request) { - $invoice = Invoice::with('invoice_items')->scope($publicId)->firstOrFail(); - $clone = $this->invoiceService->convertQuote($invoice); + $clone = $this->invoiceService->convertQuote($request->entity()); Session::flash('message', trans('texts.converted_to_invoice')); - return Redirect::to('invoices/'.$clone->public_id); + + return Redirect::to('invoices/' . $clone->public_id); } - public function cloneInvoice($publicId) + public function cloneInvoice(InvoiceRequest $request, $publicId) { - return self::edit($publicId, true); + return self::edit($request, $publicId, true); } public function invoiceHistory($publicId) diff --git a/app/Http/Controllers/PaymentApiController.php b/app/Http/Controllers/PaymentApiController.php index 7022f0c3e840..a7cab011fc36 100644 --- a/app/Http/Controllers/PaymentApiController.php +++ b/app/Http/Controllers/PaymentApiController.php @@ -17,13 +17,14 @@ class PaymentApiController extends BaseAPIController { protected $paymentRepo; + protected $entityType = ENTITY_PAYMENT; + public function __construct(PaymentRepository $paymentRepo, ContactMailer $contactMailer) { parent::__construct(); $this->paymentRepo = $paymentRepo; $this->contactMailer = $contactMailer; - } /** @@ -44,85 +45,71 @@ class PaymentApiController extends BaseAPIController */ public function index() { - $paginator = Payment::scope(); $payments = Payment::scope() - ->with('client.contacts', 'invitation', 'user', 'invoice')->withTrashed(); + ->withTrashed() + ->with(array_merge(['client.contacts', 'invitation', 'user', 'invoice'], $this->getIncluded())) + ->orderBy('created_at', 'desc'); - if ($clientPublicId = Input::get('client_id')) { - $filter = function($query) use ($clientPublicId) { - $query->where('public_id', '=', $clientPublicId); - }; - $payments->whereHas('client', $filter); - $paginator->whereHas('client', $filter); - } - - $payments = $payments->orderBy('created_at', 'desc')->paginate(); - $paginator = $paginator->paginate(); - - $transformer = new PaymentTransformer(Auth::user()->account, Input::get('serializer')); - $data = $this->createCollection($payments, $transformer, 'payments', $paginator); - - return $this->response($data); + return $this->returnList($payments); } + /** + * @SWG\Put( + * path="/payments/{payment_id", + * summary="Update a payment", + * tags={"payment"}, + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Payment") + * ), + * @SWG\Response( + * response=200, + * description="Update payment", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Payment")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ - /** - * @SWG\Put( - * path="/payments/{payment_id", - * summary="Update a payment", - * tags={"payment"}, - * @SWG\Parameter( - * in="body", - * name="body", - * @SWG\Schema(ref="#/definitions/Payment") - * ), - * @SWG\Response( - * response=200, - * description="Update payment", - * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Payment")) - * ), - * @SWG\Response( - * response="default", - * description="an ""unexpected"" error" - * ) - * ) - */ + public function update(Request $request, $publicId) + { + $data = Input::all(); + $data['public_id'] = $publicId; + $error = false; - public function update(Request $request, $publicId) - { - $data = Input::all(); - $data['public_id'] = $publicId; - $error = false; - - if ($request->action == ACTION_ARCHIVE) { - $payment = Payment::scope($publicId)->withTrashed()->firstOrFail(); - $this->paymentRepo->archive($payment); - - $transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer')); - $data = $this->createItem($payment, $transformer, 'invoice'); - - return $this->response($data); - } - - $payment = $this->paymentRepo->save($data); - - if ($error) { - return $error; - } - - /* - $invoice = Invoice::scope($data['invoice_id'])->with('client', 'invoice_items', 'invitations')->with(['payments' => function($query) { - $query->withTrashed(); - }])->withTrashed()->first(); - */ + if ($request->action == ACTION_ARCHIVE) { + $payment = Payment::scope($publicId)->withTrashed()->firstOrFail(); + $this->paymentRepo->archive($payment); $transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer')); $data = $this->createItem($payment, $transformer, 'invoice'); return $this->response($data); - } + $payment = $this->paymentRepo->save($data); + + if ($error) { + return $error; + } + + /* + $invoice = Invoice::scope($data['invoice_id'])->with('client', 'invoice_items', 'invitations')->with(['payments' => function($query) { + $query->withTrashed(); + }])->withTrashed()->first(); + */ + + $transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer')); + $data = $this->createItem($payment, $transformer, 'invoice'); + + return $this->response($data); + + } + /** * @SWG\Post( @@ -190,44 +177,44 @@ class PaymentApiController extends BaseAPIController } - /** - * @SWG\Delete( - * path="/payments/{payment_id}", - * summary="Delete a payment", - * tags={"payment"}, - * @SWG\Parameter( - * in="body", - * name="body", - * @SWG\Schema(ref="#/definitions/Payment") - * ), - * @SWG\Response( - * response=200, - * description="Delete payment", - * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Payment")) - * ), - * @SWG\Response( - * response="default", - * description="an ""unexpected"" error" - * ) - * ) - */ + /** + * @SWG\Delete( + * path="/payments/{payment_id}", + * summary="Delete a payment", + * tags={"payment"}, + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Payment") + * ), + * @SWG\Response( + * response=200, + * description="Delete payment", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Payment")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ - public function destroy($publicId) - { + public function destroy($publicId) + { - $payment = Payment::scope($publicId)->withTrashed()->first(); - $invoiceId = $payment->invoice->public_id; + $payment = Payment::scope($publicId)->withTrashed()->first(); + $invoiceId = $payment->invoice->public_id; - $this->paymentRepo->delete($payment); + $this->paymentRepo->delete($payment); - /* - $invoice = Invoice::scope($invoiceId)->with('client', 'invoice_items', 'invitations')->with(['payments' => function($query) { - $query->withTrashed(); - }])->first(); - */ - $transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer')); - $data = $this->createItem($payment, $transformer, 'invoice'); + /* + $invoice = Invoice::scope($invoiceId)->with('client', 'invoice_items', 'invitations')->with(['payments' => function($query) { + $query->withTrashed(); + }])->first(); + */ + $transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer')); + $data = $this->createItem($payment, $transformer, 'invoice'); - return $this->response($data); - } + return $this->response($data); + } } diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 4654a3e69856..e3307f6f47e5 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -25,12 +25,13 @@ use App\Ninja\Repositories\AccountRepository; use App\Ninja\Mailers\ContactMailer; use App\Services\PaymentService; +use App\Http\Requests\PaymentRequest; use App\Http\Requests\CreatePaymentRequest; use App\Http\Requests\UpdatePaymentRequest; class PaymentController extends BaseController { - protected $entity = ENTITY_PAYMENT; + protected $entityType = ENTITY_PAYMENT; public function __construct(PaymentRepository $paymentRepo, InvoiceRepository $invoiceRepo, AccountRepository $accountRepo, ContactMailer $contactMailer, PaymentService $paymentService) { @@ -67,10 +68,8 @@ class PaymentController extends BaseController return $this->paymentService->getDatatable($clientPublicId, Input::get('sSearch')); } - public function create($clientPublicId = 0, $invoicePublicId = 0) + public function create(PaymentRequest $request) { - $this->authorizeCreate(); - $invoices = Invoice::scope() ->where('is_recurring', '=', false) ->where('is_quote', '=', false) @@ -79,8 +78,8 @@ class PaymentController extends BaseController ->orderBy('invoice_number')->get(); $data = array( - 'clientPublicId' => Input::old('client') ? Input::old('client') : $clientPublicId, - 'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : $invoicePublicId, + 'clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0), + 'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : ($request->invoice_id ?: 0), 'invoice' => null, 'invoices' => $invoices, 'payment' => null, @@ -94,12 +93,10 @@ class PaymentController extends BaseController return View::make('payments.edit', $data); } - public function edit($publicId) + public function edit(PaymentRequest $request) { - $payment = Payment::scope($publicId)->firstOrFail(); - - $this->authorize('edit', $payment); - + $payment = $request->entity(); + $payment->payment_date = Utils::fromSqlDate($payment->payment_date); $data = array( @@ -109,7 +106,7 @@ class PaymentController extends BaseController ->with('client', 'invoice_status')->orderBy('invoice_number')->get(), 'payment' => $payment, 'method' => 'PUT', - 'url' => 'payments/'.$publicId, + 'url' => 'payments/'.$payment->public_id, 'title' => trans('texts.edit_payment'), 'paymentTypes' => Cache::get('paymentTypes'), 'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), ); @@ -589,9 +586,7 @@ class PaymentController extends BaseController public function store(CreatePaymentRequest $request) { $input = $request->input(); - - $this->authorizeUpdate($data); - + $input['invoice_id'] = Invoice::getPrivateId($input['invoice']); $input['client_id'] = Client::getPrivateId($input['client']); $payment = $this->paymentRepo->save($input); @@ -608,11 +603,7 @@ class PaymentController extends BaseController public function update(UpdatePaymentRequest $request) { - $input = $request->input(); - - $this->authorizeUpdate($data); - - $payment = $this->paymentRepo->save($input); + $payment = $this->paymentRepo->save($request->input()); Session::flash('message', trans('texts.updated_payment')); diff --git a/app/Http/Controllers/ProductApiController.php b/app/Http/Controllers/ProductApiController.php index 87bf89403b8a..26736f5ef5c2 100644 --- a/app/Http/Controllers/ProductApiController.php +++ b/app/Http/Controllers/ProductApiController.php @@ -20,8 +20,9 @@ use App\Services\ProductService; class ProductApiController extends BaseAPIController { protected $productService; - - protected $productRepo; + protected $productRepo; + + protected $entityType = ENTITY_PRODUCT; public function __construct(ProductService $productService, ProductRepository $productRepo) { @@ -33,17 +34,11 @@ class ProductApiController extends BaseAPIController public function index() { + $products = Product::scope() + ->withTrashed() + ->orderBy('created_at', 'desc'); - $products = Product::scope()->withTrashed(); - $products = $products->paginate(); - - $paginator = Product::scope()->withTrashed()->paginate(); - - $transformer = new ProductTransformer(\Auth::user()->account, $this->serializer); - $data = $this->createCollection($products, $transformer, 'products', $paginator); - - return $this->response($data); - + return $this->returnList($products); } public function getDatatable() diff --git a/app/Http/Controllers/QuoteApiController.php b/app/Http/Controllers/QuoteApiController.php deleted file mode 100644 index 8111872b10d9..000000000000 --- a/app/Http/Controllers/QuoteApiController.php +++ /dev/null @@ -1,75 +0,0 @@ -invoiceRepo = $invoiceRepo; - } - - /** - * @SWG\Get( - * path="/quotes", - * tags={"quote"}, - * summary="List of quotes", - * @SWG\Response( - * response=200, - * description="A list with quotes", - * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Invoice")) - * ), - * @SWG\Response( - * response="default", - * description="an ""unexpected"" error" - * ) - * ) - */ - public function index() - { - $paginator = Invoice::scope(); - $invoices = Invoice::scope() - ->with('client', 'invitations', 'user', 'invoice_items') - ->where('invoices.is_quote', '=', true); - - if ($clientPublicId = Input::get('client_id')) { - $filter = function($query) use ($clientPublicId) { - $query->where('public_id', '=', $clientPublicId); - }; - $invoices->whereHas('client', $filter); - $paginator->whereHas('client', $filter); - } - - $invoices = $invoices->orderBy('created_at', 'desc')->paginate(); - - $transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer')); - $paginator = $paginator->paginate(); - - $data = $this->createCollection($invoices, $transformer, 'quotes', $paginator); - - return $this->response($data); - } - - /* - public function store() - { - $data = Input::all(); - $invoice = $this->invoiceRepo->save(false, $data, false); - - $response = json_encode($invoice, JSON_PRETTY_PRINT); - $headers = Utils::getApiHeaders(); - return Response::make($response, 200, $headers); - } - */ -} diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index e2228ab2a0c0..a8ea0beaa476 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -26,6 +26,7 @@ use App\Ninja\Repositories\InvoiceRepository; use App\Ninja\Repositories\ClientRepository; use App\Events\QuoteInvitationWasApproved; use App\Services\InvoiceService; +use App\Http\Requests\InvoiceRequest; class QuoteController extends BaseController { @@ -33,7 +34,7 @@ class QuoteController extends BaseController protected $invoiceRepo; protected $clientRepo; protected $invoiceService; - protected $entity = ENTITY_INVOICE; + protected $entityType = ENTITY_INVOICE; public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, InvoiceService $invoiceService) { @@ -78,10 +79,8 @@ class QuoteController extends BaseController return $this->invoiceService->getDatatable($accountId, $clientPublicId, ENTITY_QUOTE, $search); } - public function create($clientPublicId = 0) + public function create(InvoiceRequest $request, $clientPublicId = 0) { - $this->authorizeCreate(); - if (!Utils::hasFeature(FEATURE_QUOTES)) { return Redirect::to('/invoices/create'); } diff --git a/app/Http/Controllers/TaskApiController.php b/app/Http/Controllers/TaskApiController.php index 926ed2f98ad3..cb39e0a1f369 100644 --- a/app/Http/Controllers/TaskApiController.php +++ b/app/Http/Controllers/TaskApiController.php @@ -13,6 +13,8 @@ class TaskApiController extends BaseAPIController { protected $taskRepo; + protected $entityType = ENTITY_TASK; + public function __construct(TaskRepository $taskRepo) { parent::__construct(); @@ -38,25 +40,12 @@ class TaskApiController extends BaseAPIController */ public function index() { - $paginator = Task::scope(); - $tasks = Task::scope() - ->with($this->getIncluded()); + $payments = Task::scope() + ->withTrashed() + ->with($this->getIncluded()) + ->orderBy('created_at', 'desc'); - if ($clientPublicId = Input::get('client_id')) { - $filter = function($query) use ($clientPublicId) { - $query->where('public_id', '=', $clientPublicId); - }; - $tasks->whereHas('client', $filter); - $paginator->whereHas('client', $filter); - } - - $tasks = $tasks->orderBy('created_at', 'desc')->paginate(); - $paginator = $paginator->paginate(); - $transformer = new TaskTransformer(\Auth::user()->account, Input::get('serializer')); - - $data = $this->createCollection($tasks, $transformer, 'tasks', $paginator); - - return $this->response($data); + return $this->returnList($payments); } /** diff --git a/app/Http/Controllers/TaskController.php b/app/Http/Controllers/TaskController.php index 7ff19436ead2..229a4751116e 100644 --- a/app/Http/Controllers/TaskController.php +++ b/app/Http/Controllers/TaskController.php @@ -18,11 +18,15 @@ use App\Ninja\Repositories\TaskRepository; use App\Ninja\Repositories\InvoiceRepository; use App\Services\TaskService; +use App\Http\Requests\TaskRequest; +use App\Http\Requests\CreateTaskRequest; +use App\Http\Requests\UpdateTaskRequest; + class TaskController extends BaseController { protected $taskRepo; protected $taskService; - protected $entity = ENTITY_TASK; + protected $entityType = ENTITY_TASK; public function __construct(TaskRepository $taskRepo, InvoiceRepository $invoiceRepo, TaskService $taskService) { @@ -66,7 +70,7 @@ class TaskController extends BaseController * * @return Response */ - public function store() + public function store(CreateTaskRequest $request) { return $this->save(); } @@ -83,14 +87,13 @@ class TaskController extends BaseController * * @return Response */ - public function create($clientPublicId = 0) + public function create(TaskRequest $request) { - $this->authorizeCreate(); $this->checkTimezone(); $data = [ 'task' => null, - 'clientPublicId' => Input::old('client') ? Input::old('client') : $clientPublicId, + 'clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0), 'method' => 'POST', 'url' => 'tasks', 'title' => trans('texts.new_task'), @@ -109,13 +112,11 @@ class TaskController extends BaseController * @param int $id * @return Response */ - public function edit($publicId) + public function edit(TaskRequest $request) { $this->checkTimezone(); - $task = Task::scope($publicId)->with('client', 'invoice')->withTrashed()->firstOrFail(); - - $this->authorize('edit', $task); + $task = $request->entity(); $actions = []; if ($task->invoice) { @@ -143,7 +144,7 @@ class TaskController extends BaseController 'task' => $task, 'clientPublicId' => $task->client ? $task->client->public_id : 0, 'method' => 'PUT', - 'url' => 'tasks/'.$publicId, + 'url' => 'tasks/'.$task->public_id, 'title' => trans('texts.edit_task'), 'duration' => $task->is_running ? $task->getCurrentDuration() : $task->getDuration(), 'actions' => $actions, @@ -163,9 +164,11 @@ class TaskController extends BaseController * @param int $id * @return Response */ - public function update($publicId) + public function update(UpdateTaskRequest $request) { - return $this->save($publicId); + $task = $request->entity(); + + return $this->save($task->public_id); } private static function getViewModel() @@ -180,20 +183,10 @@ class TaskController extends BaseController { $action = Input::get('action'); - $this->authorizeUpdate(array('public_id'=>$publicId)/* Hacky, but works */); - if (in_array($action, ['archive', 'delete', 'restore'])) { return self::bulk(); } - if ($validator = $this->taskRepo->getErrors(Input::all())) { - $url = $publicId ? 'tasks/'.$publicId.'/edit' : 'tasks/create'; - Session::flash('error', trans('texts.task_errors')); - return Redirect::to($url) - ->withErrors($validator) - ->withInput(); - } - $task = $this->taskRepo->save($publicId, Input::all()); Session::flash('message', trans($publicId ? 'texts.updated_task' : 'texts.created_task')); diff --git a/app/Http/Controllers/TaxRateApiController.php b/app/Http/Controllers/TaxRateApiController.php index 7cacfcf8311b..ddc0ab4aa968 100644 --- a/app/Http/Controllers/TaxRateApiController.php +++ b/app/Http/Controllers/TaxRateApiController.php @@ -14,6 +14,8 @@ class TaxRateApiController extends BaseAPIController protected $taxRateService; protected $taxRateRepo; + protected $entityType = ENTITY_TAX_RATE; + public function __construct(TaxRateService $taxRateService, TaxRateRepository $taxRateRepo) { parent::__construct(); @@ -24,15 +26,11 @@ class TaxRateApiController extends BaseAPIController public function index() { - $taxRates = TaxRate::scope()->withTrashed(); - $taxRates = $taxRates->paginate(); - - $paginator = TaxRate::scope()->withTrashed()->paginate(); - - $transformer = new TaxRateTransformer(Auth::user()->account, $this->serializer); - $data = $this->createCollection($taxRates, $transformer, 'tax_rates', $paginator); - - return $this->response($data); + $taxRates = TaxRate::scope() + ->withTrashed() + ->orderBy('created_at', 'desc'); + + return $this->returnList($taxRates); } public function store(CreateTaxRateRequest $request) diff --git a/app/Http/Controllers/UserApiController.php b/app/Http/Controllers/UserApiController.php index fcd48787b134..8fda74b33cbd 100644 --- a/app/Http/Controllers/UserApiController.php +++ b/app/Http/Controllers/UserApiController.php @@ -14,6 +14,8 @@ class UserApiController extends BaseAPIController protected $userService; protected $userRepo; + protected $entityType = ENTITY_USER; + public function __construct(UserService $userService, UserRepository $userRepo) { parent::__construct(); @@ -24,16 +26,11 @@ class UserApiController extends BaseAPIController public function index() { - $user = Auth::user(); - $users = User::whereAccountId($user->account_id)->withTrashed(); - $users = $users->paginate(); - - $paginator = User::whereAccountId($user->account_id)->withTrashed()->paginate(); - - $transformer = new UserTransformer(Auth::user()->account, $this->serializer); - $data = $this->createCollection($users, $transformer, 'users', $paginator); - - return $this->response($data); + $users = User::whereAccountId(Auth::user()->account_id) + ->withTrashed() + ->orderBy('created_at', 'desc'); + + return $this->returnList($users); } /* diff --git a/app/Http/Controllers/VendorApiController.php b/app/Http/Controllers/VendorApiController.php index 4c32ee1eb3c5..b2487dfda2d3 100644 --- a/app/Http/Controllers/VendorApiController.php +++ b/app/Http/Controllers/VendorApiController.php @@ -14,6 +14,8 @@ class VendorApiController extends BaseAPIController { protected $vendorRepo; + protected $entityType = ENTITY_VENDOR; + public function __construct(VendorRepository $vendorRepo) { parent::__construct(); @@ -46,17 +48,12 @@ class VendorApiController extends BaseAPIController */ public function index() { - $vendors = Vendor::scope() + $vendors = Vendor::scope() ->with($this->getIncluded()) ->withTrashed() - ->orderBy('created_at', 'desc') - ->paginate(); + ->orderBy('created_at', 'desc'); - $transformer = new VendorTransformer(Auth::user()->account, Input::get('serializer')); - $paginator = Vendor::scope()->paginate(); - $data = $this->createCollection($vendors, $transformer, ENTITY_VENDOR, $paginator); - - return $this->response($data); + return $this->returnList($vendors); } /** diff --git a/app/Http/Controllers/VendorController.php b/app/Http/Controllers/VendorController.php index 00f5bbe83e4d..10c7f7f03e89 100644 --- a/app/Http/Controllers/VendorController.php +++ b/app/Http/Controllers/VendorController.php @@ -23,14 +23,15 @@ use App\Models\Country; use App\Ninja\Repositories\VendorRepository; use App\Services\VendorService; +use App\Http\Requests\VendorRequest; use App\Http\Requests\CreateVendorRequest; use App\Http\Requests\UpdateVendorRequest; -// vendor + class VendorController extends BaseController { protected $vendorService; protected $vendorRepo; - protected $entity = ENTITY_VENDOR; + protected $entityType = ENTITY_VENDOR; public function __construct(VendorRepository $vendorRepo, VendorService $vendorService) { @@ -38,8 +39,6 @@ class VendorController extends BaseController $this->vendorRepo = $vendorRepo; $this->vendorService = $vendorService; - - } /** @@ -77,11 +76,7 @@ class VendorController extends BaseController */ public function store(CreateVendorRequest $request) { - $data = $request->input(); - - $this->authorizeUpdate($data); - - $vendor = $this->vendorService->save($data); + $vendor = $this->vendorService->save($request->input()); Session::flash('message', trans('texts.created_vendor')); @@ -94,12 +89,10 @@ class VendorController extends BaseController * @param int $id * @return Response */ - public function show($publicId) + public function show(VendorRequest $request) { - $vendor = Vendor::withTrashed()->scope($publicId)->with('vendorcontacts', 'size', 'industry')->firstOrFail(); - - $this->authorize('view', $vendor); - + $vendor = $request->entity(); + Utils::trackViewed($vendor->getDisplayName(), 'vendor'); $actionLinks = [ @@ -125,10 +118,8 @@ class VendorController extends BaseController * * @return Response */ - public function create() + public function create(VendorRequest $request) { - $this->authorizeCreate(); - if (Vendor::scope()->count() > Auth::user()->getMaxNumVendors()) { return View::make('error', ['hideHeader' => true, 'error' => "Sorry, you've exceeded the limit of ".Auth::user()->getMaxNumVendors()." vendors"]); } @@ -151,16 +142,14 @@ class VendorController extends BaseController * @param int $id * @return Response */ - public function edit($publicId) + public function edit(VendorRequest $request) { - $vendor = Vendor::scope($publicId)->with('vendorcontacts')->firstOrFail(); - - $this->authorize('edit', $vendor) + $vendor = $request->entity(); $data = [ 'vendor' => $vendor, 'method' => 'PUT', - 'url' => 'vendors/'.$publicId, + 'url' => 'vendors/'.$vendor->public_id, 'title' => trans('texts.edit_vendor'), ]; @@ -193,11 +182,7 @@ class VendorController extends BaseController */ public function update(UpdateVendorRequest $request) { - $data = $request->input(); - - $this->authorizeUpdate($data); - - $vendor = $this->vendorService->save($data); + $vendor = $this->vendorService->save($request->input()); Session::flash('message', trans('texts.updated_vendor')); diff --git a/app/Http/Middleware/DuplicateSubmissionCheck.php b/app/Http/Middleware/DuplicateSubmissionCheck.php index 407ffab60071..6f3374a47ebf 100644 --- a/app/Http/Middleware/DuplicateSubmissionCheck.php +++ b/app/Http/Middleware/DuplicateSubmissionCheck.php @@ -1,4 +1,4 @@ -contacts)) { + $client->load('contacts'); + } + + return $client; + } +} \ No newline at end of file diff --git a/app/Http/Requests/CreateBankAccountRequest.php b/app/Http/Requests/CreateBankAccountRequest.php index 6c2fea62ec47..eac988349c8d 100644 --- a/app/Http/Requests/CreateBankAccountRequest.php +++ b/app/Http/Requests/CreateBankAccountRequest.php @@ -1,4 +1,4 @@ -user()->can('create', ENTITY_CLIENT); } /** diff --git a/app/Http/Requests/CreateCreditRequest.php b/app/Http/Requests/CreateCreditRequest.php index f2dc44d31aa0..b6f4fe3b37e3 100644 --- a/app/Http/Requests/CreateCreditRequest.php +++ b/app/Http/Requests/CreateCreditRequest.php @@ -1,9 +1,6 @@ -user()->can('create', ENTITY_CREDIT); } /** diff --git a/app/Http/Requests/CreateDocumentRequest.php b/app/Http/Requests/CreateDocumentRequest.php new file mode 100644 index 000000000000..33330a90895e --- /dev/null +++ b/app/Http/Requests/CreateDocumentRequest.php @@ -0,0 +1,26 @@ +user()->can('create', ENTITY_DOCUMENT); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + + ]; + } +} diff --git a/app/Http/Requests/CreateExpenseRequest.php b/app/Http/Requests/CreateExpenseRequest.php index 85a93eb1974d..dd096eebdcbf 100644 --- a/app/Http/Requests/CreateExpenseRequest.php +++ b/app/Http/Requests/CreateExpenseRequest.php @@ -1,9 +1,6 @@ -user()->can('create', ENTITY_EXPENSE); } /** diff --git a/app/Http/Requests/CreateInvoiceAPIRequest.php b/app/Http/Requests/CreateInvoiceAPIRequest.php new file mode 100644 index 000000000000..141d8788abc3 --- /dev/null +++ b/app/Http/Requests/CreateInvoiceAPIRequest.php @@ -0,0 +1,32 @@ +user()->can('create', ENTITY_INVOICE); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + $rules = [ + 'email' => 'required_without:client_id', + 'client_id' => 'required_without:email', + 'invoice_items' => 'valid_invoice_items', + 'invoice_number' => 'unique:invoices,invoice_number,,id,account_id,' . $this->user()->account_id, + 'discount' => 'positive', + ]; + + return $rules; + } +} diff --git a/app/Http/Requests/CreateInvoiceRequest.php b/app/Http/Requests/CreateInvoiceRequest.php index 4a11ea56044a..a3f556d408e9 100644 --- a/app/Http/Requests/CreateInvoiceRequest.php +++ b/app/Http/Requests/CreateInvoiceRequest.php @@ -1,11 +1,6 @@ -user()->can('create', ENTITY_INVOICE); } /** @@ -25,13 +20,18 @@ class CreateInvoiceRequest extends Request public function rules() { $rules = [ - 'email' => 'required_without:client_id', - 'client_id' => 'required_without:email', + 'client.contacts' => 'valid_contacts', 'invoice_items' => 'valid_invoice_items', - 'invoice_number' => 'unique:invoices,invoice_number,,id,account_id,'.Auth::user()->account_id, + 'invoice_number' => 'required|unique:invoices,invoice_number,,id,account_id,' . $this->user()->account_id, 'discount' => 'positive', ]; + /* There's a problem parsing the dates + if (Request::get('is_recurring') && Request::get('start_date') && Request::get('end_date')) { + $rules['end_date'] = 'after' . Request::get('start_date'); + } + */ + return $rules; } } diff --git a/app/Http/Requests/CreatePaymentRequest.php b/app/Http/Requests/CreatePaymentRequest.php index 52e9d313bf9f..d14d1ddba616 100644 --- a/app/Http/Requests/CreatePaymentRequest.php +++ b/app/Http/Requests/CreatePaymentRequest.php @@ -1,10 +1,8 @@ -user()->can('create', ENTITY_PAYMENT); } /** diff --git a/app/Http/Requests/CreatePaymentTermRequest.php b/app/Http/Requests/CreatePaymentTermRequest.php index d8581793160e..23bf3151d096 100644 --- a/app/Http/Requests/CreatePaymentTermRequest.php +++ b/app/Http/Requests/CreatePaymentTermRequest.php @@ -1,4 +1,4 @@ -user()->can('create', ENTITY_TASK); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'time_log' => 'time_log', + ]; + } +} diff --git a/app/Http/Requests/CreateTaxRateRequest.php b/app/Http/Requests/CreateTaxRateRequest.php index bcf1ad1115b7..1596c814f127 100644 --- a/app/Http/Requests/CreateTaxRateRequest.php +++ b/app/Http/Requests/CreateTaxRateRequest.php @@ -1,4 +1,4 @@ -user()->can('create', ENTITY_VENDOR); } /** diff --git a/app/Http/Requests/CreditRequest.php b/app/Http/Requests/CreditRequest.php new file mode 100644 index 000000000000..7968005555f4 --- /dev/null +++ b/app/Http/Requests/CreditRequest.php @@ -0,0 +1,7 @@ +entity) { + return $this->entity; + } + + $paramName = $this->entityType . 's'; + $publicId = $this->$paramName ?: (Input::get('public_id') ?: Input::get('id')); + + if ( ! $publicId) { + return null; + } + + $class = Utils::getEntityClass($this->entityType); + + if (method_exists($class, 'withTrashed')) { + $this->entity = $class::scope($publicId)->withTrashed()->firstOrFail(); + } else { + $this->entity = $class::scope($publicId)->firstOrFail(); + } + + return $this->entity; + } + + public function authorize() + { + if ($this->entity()) { + return $this->user()->can('view', $this->entity()); + } else { + return $this->user()->can('create', $this->entityType); + } + } + + public function rules() + { + return []; + } +} diff --git a/app/Http/Requests/ExpenseRequest.php b/app/Http/Requests/ExpenseRequest.php new file mode 100644 index 000000000000..d5e2c793c371 --- /dev/null +++ b/app/Http/Requests/ExpenseRequest.php @@ -0,0 +1,18 @@ +documents)) { + $expense->load('documents'); + } + + return $expense; + } +} \ No newline at end of file diff --git a/app/Http/Requests/InvoiceRequest.php b/app/Http/Requests/InvoiceRequest.php new file mode 100644 index 000000000000..bf24c38839a9 --- /dev/null +++ b/app/Http/Requests/InvoiceRequest.php @@ -0,0 +1,19 @@ +invoice_items)) { + $invoice->load('invoice_items'); + } + + return $invoice; + } + +} \ No newline at end of file diff --git a/app/Http/Requests/PaymentRequest.php b/app/Http/Requests/PaymentRequest.php new file mode 100644 index 000000000000..cb34349f5d20 --- /dev/null +++ b/app/Http/Requests/PaymentRequest.php @@ -0,0 +1,7 @@ + 'valid_contacts', - 'invoice_items' => 'valid_invoice_items', - 'invoice_number' => 'required|unique:invoices,invoice_number,'.$invoiceId.',id,account_id,'.Auth::user()->account_id, - 'discount' => 'positive', - ]; - - /* There's a problem parsing the dates - if (Request::get('is_recurring') && Request::get('start_date') && Request::get('end_date')) { - $rules['end_date'] = 'after' . Request::get('start_date'); - } - */ - - return $rules; - } -} diff --git a/app/Http/Requests/TaskRequest.php b/app/Http/Requests/TaskRequest.php new file mode 100644 index 000000000000..1e2783781f06 --- /dev/null +++ b/app/Http/Requests/TaskRequest.php @@ -0,0 +1,7 @@ +user()->can('edit', $this->entity()); } /** diff --git a/app/Http/Requests/UpdateExpenseRequest.php b/app/Http/Requests/UpdateExpenseRequest.php index a4d3855deaec..e64384b57a54 100644 --- a/app/Http/Requests/UpdateExpenseRequest.php +++ b/app/Http/Requests/UpdateExpenseRequest.php @@ -1,10 +1,6 @@ -user()->can('edit', $this->entity()); } /** diff --git a/app/Http/Requests/UpdateInvoiceAPIRequest.php b/app/Http/Requests/UpdateInvoiceAPIRequest.php new file mode 100644 index 000000000000..6fa3c4e92e45 --- /dev/null +++ b/app/Http/Requests/UpdateInvoiceAPIRequest.php @@ -0,0 +1,36 @@ +user()->can('edit', $this->entity()); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + if ($this->action == ACTION_ARCHIVE) { + return []; + } + + $invoiceId = $this->entity()->id; + + $rules = [ + 'invoice_items' => 'valid_invoice_items', + 'invoice_number' => 'unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id, + 'discount' => 'positive', + ]; + + return $rules; + } +} diff --git a/app/Http/Requests/UpdateInvoiceRequest.php b/app/Http/Requests/UpdateInvoiceRequest.php index 4b32bf4ccead..96d112b157c2 100644 --- a/app/Http/Requests/UpdateInvoiceRequest.php +++ b/app/Http/Requests/UpdateInvoiceRequest.php @@ -1,11 +1,6 @@ -user()->can('edit', $this->entity()); } /** @@ -24,19 +19,21 @@ class UpdateInvoiceRequest extends Request */ public function rules() { - if ($this->action == ACTION_ARCHIVE) { - return []; - } - - $publicId = $this->route('invoices'); - $invoiceId = Invoice::getPrivateId($publicId); - + $invoiceId = $this->entity()->id; + $rules = [ + 'client.contacts' => 'valid_contacts', 'invoice_items' => 'valid_invoice_items', - 'invoice_number' => 'unique:invoices,invoice_number,'.$invoiceId.',id,account_id,'.Auth::user()->account_id, + 'invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id, 'discount' => 'positive', ]; + /* There's a problem parsing the dates + if (Request::get('is_recurring') && Request::get('start_date') && Request::get('end_date')) { + $rules['end_date'] = 'after' . Request::get('start_date'); + } + */ + return $rules; } } diff --git a/app/Http/Requests/UpdatePaymentRequest.php b/app/Http/Requests/UpdatePaymentRequest.php index 29ac70e85e74..70a328d26772 100644 --- a/app/Http/Requests/UpdatePaymentRequest.php +++ b/app/Http/Requests/UpdatePaymentRequest.php @@ -1,9 +1,6 @@ -user()->can('edit', $this->entity()); } /** diff --git a/app/Http/Requests/UpdatePaymentTermRequest.php b/app/Http/Requests/UpdatePaymentTermRequest.php index b3d4f536bc6e..ea9ff80e9772 100644 --- a/app/Http/Requests/UpdatePaymentTermRequest.php +++ b/app/Http/Requests/UpdatePaymentTermRequest.php @@ -1,4 +1,4 @@ -user()->can('edit', $this->entity()); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'time_log' => 'time_log', + ]; + } +} diff --git a/app/Http/Requests/UpdateTaxRateRequest.php b/app/Http/Requests/UpdateTaxRateRequest.php index 6e562ac0d0ab..bcfa298e06c5 100644 --- a/app/Http/Requests/UpdateTaxRateRequest.php +++ b/app/Http/Requests/UpdateTaxRateRequest.php @@ -1,4 +1,4 @@ -user()->can('edit', $this->entity()); } /** diff --git a/app/Http/Requests/VendorRequest.php b/app/Http/Requests/VendorRequest.php new file mode 100644 index 000000000000..600678686c0e --- /dev/null +++ b/app/Http/Requests/VendorRequest.php @@ -0,0 +1,19 @@ +vendorcontacts)) { + $vendor->load('vendorcontacts'); + } + + return $vendor; + } + +} \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index e5915b394a2b..768c9c3d3d4c 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -48,8 +48,8 @@ Route::group(['middleware' => 'auth:client'], function() { Route::get('client/documents', 'PublicClientController@documentIndex'); Route::get('client/payments', 'PublicClientController@paymentIndex'); Route::get('client/dashboard', 'PublicClientController@dashboard'); - Route::get('client/document/js/{public_id}/{filename}', 'PublicClientController@getDocumentVFSJS'); - Route::get('client/document/{invitation_key}/{public_id}/{filename?}', 'PublicClientController@getDocument'); + Route::get('client/documents/js/{documents}/{filename}', 'PublicClientController@getDocumentVFSJS'); + Route::get('client/documents/{invitation_key}/{documents}/{filename?}', 'PublicClientController@getDocument'); Route::get('client/documents/{invitation_key}/{filename?}', 'PublicClientController@getInvoiceDocumentsZip'); Route::get('api/client.quotes', array('as'=>'api.client.quotes', 'uses'=>'PublicClientController@quoteDatatable')); @@ -134,20 +134,20 @@ Route::group(['middleware' => 'auth:user'], function() { Route::get('invoices/create/{client_id?}', 'InvoiceController@create'); Route::get('recurring_invoices/create/{client_id?}', 'InvoiceController@createRecurring'); Route::get('recurring_invoices', 'RecurringInvoiceController@index'); - Route::get('invoices/{public_id}/clone', 'InvoiceController@cloneInvoice'); + Route::get('invoices/{invoices}/clone', 'InvoiceController@cloneInvoice'); Route::post('invoices/bulk', 'InvoiceController@bulk'); Route::post('recurring_invoices/bulk', 'InvoiceController@bulk'); - Route::get('document/{public_id}/{filename?}', 'DocumentController@get'); - Route::get('document/js/{public_id}/{filename}', 'DocumentController@getVFSJS'); - Route::get('document/preview/{public_id}/{filename?}', 'DocumentController@getPreview'); + Route::get('documents/{documents}/{filename?}', 'DocumentController@get'); + Route::get('documents/js/{documents}/{filename}', 'DocumentController@getVFSJS'); + Route::get('documents/preview/{documents}/{filename?}', 'DocumentController@getPreview'); Route::post('document', 'DocumentController@postUpload'); Route::get('quotes/create/{client_id?}', 'QuoteController@create'); - Route::get('quotes/{public_id}/clone', 'InvoiceController@cloneInvoice'); - Route::get('quotes/{public_id}/edit', 'InvoiceController@edit'); - Route::put('quotes/{public_id}', 'InvoiceController@update'); - Route::get('quotes/{public_id}', 'InvoiceController@edit'); + Route::get('quotes/{invoices}/clone', 'InvoiceController@cloneInvoice'); + Route::get('quotes/{invoices}/edit', 'InvoiceController@edit'); + Route::put('quotes/{invoices}', 'InvoiceController@update'); + Route::get('quotes/{invoices}', 'InvoiceController@edit'); Route::post('quotes', 'InvoiceController@store'); Route::get('quotes', 'QuoteController@index'); Route::get('api/quotes/{client_id?}', array('as'=>'api.quotes', 'uses'=>'QuoteController@getDatatable')); @@ -253,8 +253,8 @@ Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function() Route::get('accounts', 'AccountApiController@show'); Route::put('accounts', 'AccountApiController@update'); Route::resource('clients', 'ClientApiController'); - Route::get('quotes', 'QuoteApiController@index'); - Route::resource('quotes', 'QuoteApiController'); + //Route::get('quotes', 'QuoteApiController@index'); + //Route::resource('quotes', 'QuoteApiController'); Route::get('invoices', 'InvoiceApiController@index'); Route::resource('invoices', 'InvoiceApiController'); Route::get('payments', 'PaymentApiController@index'); @@ -552,25 +552,25 @@ if (!defined('CONTACT_EMAIL')) { define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h'); define('NINJA_GATEWAY_ID', GATEWAY_STRIPE); define('NINJA_GATEWAY_CONFIG', 'NINJA_GATEWAY_CONFIG'); - define('NINJA_WEB_URL', 'https://www.invoiceninja.com'); - define('NINJA_APP_URL', 'https://app.invoiceninja.com'); + define('NINJA_WEB_URL', env('NINJA_WEB_URL', 'https://www.invoiceninja.com')); + define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com')); define('NINJA_DATE', '2000-01-01'); - define('NINJA_VERSION', '2.5.1.3'); + define('NINJA_VERSION', '2.5.1.3' . env('NINJA_VERSION_SUFFIX')); - define('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'); - define('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'); - define('SOCIAL_LINK_GITHUB', 'https://github.com/invoiceninja/invoiceninja/'); + define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja')); + define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja')); + define('SOCIAL_LINK_GITHUB', env('SOCIAL_LINK_GITHUB', 'https://github.com/invoiceninja/invoiceninja/')); - define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com'); - define('RELEASES_URL', 'https://trello.com/b/63BbiVVe/invoice-ninja'); - define('ZAPIER_URL', 'https://zapier.com/zapbook/invoice-ninja'); - define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/'); - define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html'); - define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/'); - define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php'); - define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/'); - define('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'); - define('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'); + define('NINJA_FROM_EMAIL', env('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com')); + define('RELEASES_URL', env('RELEASES_URL', 'https://trello.com/b/63BbiVVe/invoice-ninja')); + define('ZAPIER_URL', env('ZAPIER_URL', 'https://zapier.com/zapbook/invoice-ninja')); + define('OUTDATE_BROWSER_URL', env('OUTDATE_BROWSER_URL', 'http://browsehappy.com/')); + define('PDFMAKE_DOCS', env('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html')); + define('PHANTOMJS_CLOUD', env('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/')); + define('PHP_DATE_FORMATS', env('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php')); + define('REFERRAL_PROGRAM_URL', env('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/')); + define('EMAIL_MARKUP_URL', env('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup')); + define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all')); define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='); @@ -584,13 +584,13 @@ if (!defined('CONTACT_EMAIL')) { define('INVOICE_DESIGNS_AFFILIATE_KEY', 'T3RS74'); define('SELF_HOST_AFFILIATE_KEY', '8S69AD'); - define('PRO_PLAN_PRICE', 50); - define('PLAN_PRICE_PRO_MONTHLY', 5); - define('PLAN_PRICE_PRO_YEARLY', 50); - define('PLAN_PRICE_ENTERPRISE_MONTHLY', 10); - define('PLAN_PRICE_ENTERPRISE_YEARLY', 100); - define('WHITE_LABEL_PRICE', 20); - define('INVOICE_DESIGNS_PRICE', 10); + define('PRO_PLAN_PRICE', env('PRO_PLAN_PRICE', 50)); + define('PLAN_PRICE_PRO_MONTHLY', env('PLAN_PRICE_PRO_MONTHLY', 5)); + define('PLAN_PRICE_PRO_YEARLY', env('PLAN_PRICE_PRO_YEARLY', 50)); + define('PLAN_PRICE_ENTERPRISE_MONTHLY', env('PLAN_PRICE_ENTERPRISE_MONTHLY', 10)); + define('PLAN_PRICE_ENTERPRISE_YEARLY', env('PLAN_PRICE_ENTERPRISE_YEARLY', 100)); + define('WHITE_LABEL_PRICE', env('WHITE_LABEL_PRICE', 20)); + define('INVOICE_DESIGNS_PRICE', env('INVOICE_DESIGNS_PRICE', 10)); define('USER_TYPE_SELF_HOST', 'SELF_HOST'); define('USER_TYPE_CLOUD_HOST', 'CLOUD_HOST'); @@ -600,8 +600,8 @@ if (!defined('CONTACT_EMAIL')) { define('TEST_PASSWORD', 'password'); define('API_SECRET', 'API_SECRET'); - define('IOS_PRODUCTION_PUSH','ninjaIOS'); - define('IOS_DEV_PUSH','devNinjaIOS'); + define('IOS_PRODUCTION_PUSH', env('IOS_PRODUCTION_PUSH', 'ninjaIOS')); + define('IOS_DEV_PUSH', env('IOS_DEV_PUSH', 'devNinjaIOS')); define('TOKEN_BILLING_DISABLED', 1); define('TOKEN_BILLING_OPT_IN', 2); @@ -770,4 +770,4 @@ if (Utils::isNinjaDev()) //ini_set('memory_limit','1024M'); //Auth::loginUsingId(1); } -*/ \ No newline at end of file +*/ diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index e4ad99c6ce45..86107acfcd59 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -669,6 +669,11 @@ class Utils return $year + $offset; } + public static function getEntityClass($entityType) + { + return 'App\\Models\\' . static::getEntityName($entityType); + } + public static function getEntityName($entityType) { return ucwords(str_replace('_', ' ', $entityType)); diff --git a/app/Listeners/ActivityListener.php b/app/Listeners/ActivityListener.php index 52c2e26f9027..7edd065f915d 100644 --- a/app/Listeners/ActivityListener.php +++ b/app/Listeners/ActivityListener.php @@ -1,4 +1,4 @@ -getPlanDetails(); $selfHost = !Utils::isNinjaProd(); diff --git a/app/Models/Document.php b/app/Models/Document.php index 0d7fc049aac8..6d9c24857143 100644 --- a/app/Models/Document.php +++ b/app/Models/Document.php @@ -173,11 +173,11 @@ class Document extends EntityModel } public function getUrl(){ - return url('document/'.$this->public_id.'/'.$this->name); + return url('documents/'.$this->public_id.'/'.$this->name); } public function getClientUrl($invitation){ - return url('client/document/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name); + return url('client/documents/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name); } public function isPDFEmbeddable(){ @@ -186,16 +186,16 @@ class Document extends EntityModel public function getVFSJSUrl(){ if(!$this->isPDFEmbeddable())return null; - return url('document/js/'.$this->public_id.'/'.$this->name.'.js'); + return url('documents/js/'.$this->public_id.'/'.$this->name.'.js'); } public function getClientVFSJSUrl(){ if(!$this->isPDFEmbeddable())return null; - return url('client/document/js/'.$this->public_id.'/'.$this->name.'.js'); + return url('client/documents/js/'.$this->public_id.'/'.$this->name.'.js'); } public function getPreviewUrl(){ - return $this->preview?url('document/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)):null; + return $this->preview?url('documents/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)):null; } public function toArray() diff --git a/app/Models/EntityModel.php b/app/Models/EntityModel.php index 8d0da39d3fab..c2c9110fe306 100644 --- a/app/Models/EntityModel.php +++ b/app/Models/EntityModel.php @@ -101,6 +101,16 @@ class EntityModel extends Eloquent return $this->getName(); } + public static function getClassName($entityType) + { + return 'App\\Models\\' . ucwords(Utils::toCamelCase($entityType)); + } + + public static function getTransformerName($entityType) + { + return 'App\\Ninja\\Transformers\\' . ucwords(Utils::toCamelCase($entityType)) . 'Transformer'; + } + public function setNullValues() { foreach ($this->fillable as $field) { diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index c0da6b8faff6..deb65b75ab30 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -436,6 +436,7 @@ class Invoice extends EntityModel implements BalanceAffecting 'contacts', 'country', 'currency_id', + 'country_id', 'custom_value1', 'custom_value2', ]); diff --git a/app/Models/InvoiceDesign.php b/app/Models/InvoiceDesign.php index 2b53ac6383c7..51f15b035ad6 100644 --- a/app/Models/InvoiceDesign.php +++ b/app/Models/InvoiceDesign.php @@ -1,4 +1,4 @@ -with('contacts')->firstOrFail(); diff --git a/app/Ninja/Repositories/CreditRepository.php b/app/Ninja/Repositories/CreditRepository.php index 9803b4628af8..4381ae25771c 100644 --- a/app/Ninja/Repositories/CreditRepository.php +++ b/app/Ninja/Repositories/CreditRepository.php @@ -27,7 +27,7 @@ class CreditRepository extends BaseRepository DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'), DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'), 'credits.public_id', - 'clients.name as client_name', + DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), 'clients.public_id as client_public_id', 'clients.user_id as client_user_id', 'credits.amount', diff --git a/app/Ninja/Repositories/DocumentRepository.php b/app/Ninja/Repositories/DocumentRepository.php index 4da51c3797d4..094b4848ebe0 100644 --- a/app/Ninja/Repositories/DocumentRepository.php +++ b/app/Ninja/Repositories/DocumentRepository.php @@ -1,4 +1,4 @@ -addColumn('name', function ($model) { return link_to( - '/client/document/'.$model->invitation_key.'/'.$model->public_id.'/'.$model->name, + '/client/documents/'.$model->invitation_key.'/'.$model->public_id.'/'.$model->name, $model->name, ['target'=>'_blank'] )->toHtml(); diff --git a/app/Ninja/Repositories/ExpenseRepository.php b/app/Ninja/Repositories/ExpenseRepository.php index 3492740d6a94..4c67c0e7c91c 100644 --- a/app/Ninja/Repositories/ExpenseRepository.php +++ b/app/Ninja/Repositories/ExpenseRepository.php @@ -1,4 +1,4 @@ -first(); - if($document && !$checkSubPermissions || Auth::user()->can('edit', $document)){ + if($document && Auth::user()->can('edit', $document)){ $document->invoice_id = null; $document->expense_id = $expense->id; $document->save(); diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index b84536e88c9d..2ae18a738bd8 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -1,4 +1,4 @@ -join('accounts', 'accounts.id', '=', 'invitations.account_id') ->join('invoices', 'invoices.id', '=', 'invitations.invoice_id') ->join('clients', 'clients.id', '=', 'invoices.client_id') + ->join('contacts', 'contacts.client_id', '=', 'clients.id') ->where('invitations.contact_id', '=', $contactId) ->where('invitations.deleted_at', '=', null) ->where('invoices.is_quote', '=', $entityType == ENTITY_QUOTE) ->where('invoices.is_deleted', '=', false) ->where('clients.deleted_at', '=', null) + ->where('contacts.deleted_at', '=', null) + ->where('contacts.is_primary', '=', true) ->where('invoices.is_recurring', '=', false) // This needs to be a setting to also hide the activity on the dashboard page //->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT) @@ -169,7 +173,7 @@ class InvoiceRepository extends BaseRepository 'invoices.balance as balance', 'invoices.due_date', 'clients.public_id as client_public_id', - 'clients.name as client_name', + DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), 'invoices.public_id', 'invoices.amount', 'invoices.start_date', @@ -197,7 +201,7 @@ class InvoiceRepository extends BaseRepository ->make(); } - public function save($data, $checkSubPermissions = false) + public function save($data) { $account = \Auth::user()->account; $publicId = isset($data['public_id']) ? $data['public_id'] : false; @@ -419,7 +423,7 @@ class InvoiceRepository extends BaseRepository $document_ids = !empty($data['document_ids'])?array_map('intval', $data['document_ids']):array();; foreach ($document_ids as $document_id){ $document = Document::scope($document_id)->first(); - if($document && !$checkSubPermissions || Auth::user()->can('edit', $document)){ + if($document && Auth::user()->can('edit', $document)){ if($document->invoice_id && $document->invoice_id != $invoice->id){ // From a clone @@ -472,7 +476,7 @@ class InvoiceRepository extends BaseRepository $task = false; if (isset($item['task_public_id']) && $item['task_public_id']) { $task = Task::scope($item['task_public_id'])->where('invoice_id', '=', null)->firstOrFail(); - if(!$checkSubPermissions || Auth::user()->can('edit', $task)){ + if(Auth::user()->can('edit', $task)){ $task->invoice_id = $invoice->id; $task->client_id = $invoice->client_id; $task->save(); @@ -482,7 +486,7 @@ class InvoiceRepository extends BaseRepository $expense = false; if (isset($item['expense_public_id']) && $item['expense_public_id']) { $expense = Expense::scope($item['expense_public_id'])->where('invoice_id', '=', null)->firstOrFail(); - if(!$checkSubPermissions || Auth::user()->can('edit', $expense)){ + if(Auth::user()->can('edit', $expense)){ $expense->invoice_id = $invoice->id; $expense->client_id = $invoice->client_id; $expense->save(); @@ -493,7 +497,7 @@ class InvoiceRepository extends BaseRepository if (\Auth::user()->account->update_products && ! strtotime($productKey)) { $product = Product::findProductByKey($productKey); if (!$product) { - if(!$checkSubPermissions || Auth::user()->can('create', ENTITY_PRODUCT)){ + if (Auth::user()->can('create', ENTITY_PRODUCT)) { $product = Product::createNew(); $product->product_key = trim($item['product_key']); } @@ -501,7 +505,7 @@ class InvoiceRepository extends BaseRepository $product = null; } } - if($product && (!$checkSubPermissions || Auth::user()->can('edit', $product))){ + if ($product && (Auth::user()->can('edit', $product))) { $product->notes = ($task || $expense) ? '' : $item['notes']; $product->cost = $expense ? 0 : $item['cost']; $product->save(); @@ -515,7 +519,6 @@ class InvoiceRepository extends BaseRepository $invoiceItem->notes = trim($invoice->is_recurring ? $item['notes'] : Utils::processVariables($item['notes'])); $invoiceItem->cost = Utils::parseFloat($item['cost']); $invoiceItem->qty = Utils::parseFloat($item['qty']); - //$invoiceItem->tax_rate = 0; if (isset($item['custom_value1'])) { $invoiceItem->custom_value1 = $item['custom_value1']; diff --git a/app/Ninja/Repositories/PaymentRepository.php b/app/Ninja/Repositories/PaymentRepository.php index 85dfab9964f8..9b7d9787b457 100644 --- a/app/Ninja/Repositories/PaymentRepository.php +++ b/app/Ninja/Repositories/PaymentRepository.php @@ -34,7 +34,7 @@ class PaymentRepository extends BaseRepository DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'), DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'), 'payments.transaction_reference', - 'clients.name as client_name', + DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), 'clients.public_id as client_public_id', 'clients.user_id as client_user_id', 'payments.amount', @@ -101,7 +101,7 @@ class PaymentRepository extends BaseRepository 'invitations.invitation_key', 'payments.public_id', 'payments.transaction_reference', - 'clients.name as client_name', + DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), 'clients.public_id as client_public_id', 'payments.amount', 'payments.payment_date', diff --git a/app/Ninja/Repositories/TaskRepository.php b/app/Ninja/Repositories/TaskRepository.php index a7655a8abd9e..1bd0e38cb6b7 100644 --- a/app/Ninja/Repositories/TaskRepository.php +++ b/app/Ninja/Repositories/TaskRepository.php @@ -25,7 +25,7 @@ class TaskRepository ->where('clients.deleted_at', '=', null) ->select( 'tasks.public_id', - 'clients.name as client_name', + \DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"), 'clients.public_id as client_public_id', 'clients.user_id as client_user_id', 'contacts.first_name', @@ -64,20 +64,6 @@ class TaskRepository return $query; } - public function getErrors($input) - { - $rules = [ - 'time_log' => 'time_log', - ]; - $validator = \Validator::make($input, $rules); - - if ($validator->fails()) { - return $validator; - } - - return false; - } - public function save($publicId, $data) { if ($publicId) { diff --git a/app/Policies/GenericEntityPolicy.php b/app/Policies/GenericEntityPolicy.php index dab0aab1bc93..ad0e76a6baa4 100644 --- a/app/Policies/GenericEntityPolicy.php +++ b/app/Policies/GenericEntityPolicy.php @@ -3,6 +3,7 @@ namespace App\Policies; use App\Models\User; +use Utils; use Illuminate\Auth\Access\HandlesAuthorization; @@ -11,7 +12,7 @@ class GenericEntityPolicy use HandlesAuthorization; public static function editByOwner($user, $itemType, $ownerUserId) { - $itemType = ucwords($itemType, '_'); + $itemType = Utils::getEntityName($itemType); if (method_exists("App\\Policies\\{$itemType}Policy", 'editByOwner')) { return call_user_func(array("App\\Policies\\{$itemType}Policy", 'editByOwner'), $user, $ownerUserId); } @@ -20,7 +21,7 @@ class GenericEntityPolicy } public static function viewByOwner($user, $itemType, $ownerUserId) { - $itemType = ucwords($itemType, '_'); + $itemType = Utils::getEntityName($itemType); if (method_exists("App\\Policies\\{$itemType}Policy", 'viewByOwner')) { return call_user_func(array("App\\Policies\\{$itemType}Policy", 'viewByOwner'), $user, $ownerUserId); } @@ -29,7 +30,7 @@ class GenericEntityPolicy } public static function create($user, $itemType) { - $itemType = ucwords($itemType, '_'); + $itemType = Utils::getEntityName($itemType); if (method_exists("App\\Policies\\{$itemType}Policy", 'create')) { return call_user_func(array("App\\Policies\\{$itemType}Policy", 'create'), $user); } diff --git a/app/Policies/ProductPolicy.php b/app/Policies/ProductPolicy.php index d9dd62c34e9b..6bd9c56d0c6c 100644 --- a/app/Policies/ProductPolicy.php +++ b/app/Policies/ProductPolicy.php @@ -2,7 +2,7 @@ namespace App\Policies; -class VendorPolicy extends EntityPolicy { +class ProductPolicy extends EntityPolicy { public static function edit($user, $item) { return $user->hasPermission('admin'); } diff --git a/app/Services/BaseService.php b/app/Services/BaseService.php index 90a7359910c2..6bbbc729b246 100644 --- a/app/Services/BaseService.php +++ b/app/Services/BaseService.php @@ -1,5 +1,6 @@ clientRepo; } - public function save($data) + public function save($data, $client = null) { if (Auth::user()->account->isNinjaAccount() && isset($data['plan'])) { $this->ninjaRepo->updatePlanDetails($data['public_id'], $data); } - return $this->clientRepo->save($data); + return $this->clientRepo->save($data, $client); } public function getDatatable($search) diff --git a/app/Services/ExpenseService.php b/app/Services/ExpenseService.php index afec1e4f9950..0b28a7c4d6b1 100644 --- a/app/Services/ExpenseService.php +++ b/app/Services/ExpenseService.php @@ -28,7 +28,7 @@ class ExpenseService extends BaseService return $this->expenseRepo; } - public function save($data, $checkSubPermissions=false) + public function save($data) { if (isset($data['client_id']) && $data['client_id']) { $data['client_id'] = Client::getPrivateId($data['client_id']); @@ -38,7 +38,7 @@ class ExpenseService extends BaseService $data['vendor_id'] = Vendor::getPrivateId($data['vendor_id']); } - return $this->expenseRepo->save($data, $checkSubPermissions); + return $this->expenseRepo->save($data); } public function getDatatable($search) diff --git a/app/Services/InvoiceService.php b/app/Services/InvoiceService.php index 66442ac0a31b..ecf0ad2fab0b 100644 --- a/app/Services/InvoiceService.php +++ b/app/Services/InvoiceService.php @@ -30,26 +30,23 @@ class InvoiceService extends BaseService return $this->invoiceRepo; } - public function save($data, $checkSubPermissions = false) + public function save($data) { if (isset($data['client'])) { - $canSaveClient = !$checkSubPermissions; - if( ! $canSaveClient){ - $clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id'); - if (empty($clientPublicId) || $clientPublicId == '-1') { - $canSaveClient = Auth::user()->can('create', ENTITY_CLIENT); - } else { - $canSaveClient = Auth::user()->can('edit', Client::scope($clientPublicId)->first()); - } - } - + $canSaveClient = false; + $clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id'); + if (empty($clientPublicId) || $clientPublicId == '-1') { + $canSaveClient = Auth::user()->can('create', ENTITY_CLIENT); + } else { + $canSaveClient = Auth::user()->can('edit', Client::scope($clientPublicId)->first()); + } if ($canSaveClient) { $client = $this->clientRepo->save($data['client']); $data['client_id'] = $client->id; } } - $invoice = $this->invoiceRepo->save($data, $checkSubPermissions); + $invoice = $this->invoiceRepo->save($data); $client = $invoice->client; $client->load('contacts'); diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php index 9b325bd4e447..23b5f4e8f167 100644 --- a/app/Services/PaymentService.php +++ b/app/Services/PaymentService.php @@ -63,7 +63,6 @@ class PaymentService extends BaseService if ($input) { $data = self::convertInputForOmnipay($input); - $data['email'] = $invitation->contact->email; Session::put($key, $data); } elseif (Session::get($key)) { $data = Session::get($key); @@ -95,6 +94,7 @@ class PaymentService extends BaseService $data = [ 'firstName' => $input['first_name'], 'lastName' => $input['last_name'], + 'email' => $input['email'], 'number' => isset($input['card_number']) ? $input['card_number'] : null, 'expiryMonth' => isset($input['expiration_month']) ? $input['expiration_month'] : null, 'expiryYear' => isset($input['expiration_year']) ? $input['expiration_year'] : null, diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index c41dae9d08e2..2520f229465a 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -1118,8 +1118,8 @@ return array( 'first_page' => 'Erste Seite', 'all_pages' => 'Alle Seiten', 'last_page' => 'Letzte Seite', - 'all_pages_header' => 'Show header on', - 'all_pages_footer' => 'Show footer on', + 'all_pages_header' => 'Zeige Header auf', + 'all_pages_footer' => 'Zeige Footer auf', 'invoice_currency' => 'Rechnungs-Währung', 'enable_https' => 'Wir empfehlen dringend HTTPS zu verwenden, um Kreditkarten online zu akzeptieren.', 'quote_issued_to' => 'Quote issued to', @@ -1133,72 +1133,72 @@ return array( 'white_label_text' => 'Purchase a ONE YEAR white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the client portal and help support our project.', 'navigation' => 'Navigation', - 'list_invoices' => 'List Invoices', - 'list_clients' => 'List Clients', - 'list_quotes' => 'List Quotes', - 'list_tasks' => 'List Tasks', - 'list_expenses' => 'List Expenses', - 'list_recurring_invoices' => 'List Recurring Invoices', - 'list_payments' => 'List Payments', + 'list_invoices' => 'Rechnungen Auflisten', + 'list_clients' => 'Kunden Auflisten', + 'list_quotes' => 'Angebote Auflisten', + 'list_tasks' => 'Aufgaben Auflisten', + 'list_expenses' => 'Ausgaben Auflisten', + 'list_recurring_invoices' => 'Wiederkehrende Rechnungen Auflisten', + 'list_payments' => 'Zahlungen Aufllisten', 'list_credits' => 'List Credits', - 'tax_name' => 'Tax Name', - 'report_settings' => 'Report Settings', + 'tax_name' => 'Steuer-Name', + 'report_settings' => 'Bericht-Einstellungen', 'search_hotkey' => 'shortcut is /', - 'new_user' => 'New User', - 'new_product' => 'New Product', - 'new_tax_rate' => 'New Tax Rate', + 'new_user' => 'Neuer Benutzer', + 'new_product' => 'Neues Produkt', + 'new_tax_rate' => 'Neue Steuersatz', 'invoiced_amount' => 'Invoiced Amount', 'invoice_item_fields' => 'Invoice Item Fields', - 'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.', - 'recurring_invoice_number' => 'Recurring Invoice Number', + 'custom_invoice_item_fields_help' => 'Feld bei Erstellung eines Rechnungs-Elements hinzufügen, und dessen Bezeichnung und Wert im PDF anzeigen.', + 'recurring_invoice_number' => 'Wiederkehrende Rechnungsnummer', 'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices. The default value is \'R\'.', 'enable_client_portal' => 'Dashboard', - 'enable_client_portal_help' => 'Show/hide the dashboard page in the client portal.', + 'enable_client_portal_help' => 'Dashboard-Seite im Kunden-Portal anzeigen/verbergen.', // Client Passwords - 'enable_portal_password'=>'Password protect invoices', - 'enable_portal_password_help'=>'Allows you to set a password for each contact. If a password is set, the contact will be required to enter a password before viewing invoices.', - 'send_portal_password'=>'Generate password automatically', - 'send_portal_password_help'=>'If no password is set, one will be generated and sent with the first invoice.', + 'enable_portal_password'=>'Sichere Rechnungen mit einem Passwort ab', + 'enable_portal_password_help'=>'Erlaubt, ein Passwort für jeden Kontakt zu setzen. Wenn ein Passwort gesetzt ist, wird dieses vom Kontakt benötigt, um Rechnungen anzusehen.', + 'send_portal_password'=>'Passwort automatisch generieren', + 'send_portal_password_help'=>'Wenn kein Passwort gesetzt ist, wird eines erstellt und mit der ersten Rechnung mit versendet.', - 'expired' => 'Expired', - 'invalid_card_number' => 'The credit card number is not valid.', - 'invalid_expiry' => 'The expiration date is not valid.', - 'invalid_cvv' => 'The CVV is not valid.', - 'cost' => 'Cost', - 'create_invoice_for_sample' => 'Note: create your first invoice to see a preview here.', + 'expired' => 'Abgelaufen', + 'invalid_card_number' => 'Die Kreditkartennummer ist nicht gültig.', + 'invalid_expiry' => 'Das Ablaufdatum ist nicht gültig.', + 'invalid_cvv' => 'Das CVV ist nicht gültig.', + 'cost' => 'Kosten', + 'create_invoice_for_sample' => 'Info: Erstelle deine erste Rechnung, um hier eine Voransicht zu sehen.', // User Permissions - 'owner' => 'Owner', + 'owner' => 'Eigentümer', 'administrator' => 'Administrator', - 'administrator_help' => 'Allow user to manage users, change settings and modify all records', - 'user_create_all' => 'Create clients, invoices, etc.', - 'user_view_all' => 'View all clients, invoices, etc.', - 'user_edit_all' => 'Edit all clients, invoices, etc.', - 'gateway_help_20' => ':link to sign up for Sage Pay.', - 'gateway_help_21' => ':link to sign up for Sage Pay.', - 'partial_due' => 'Partial Due', - 'restore_vendor' => 'Restore Vendor', - 'restored_vendor' => 'Successfully restored vendor', - 'restored_expense' => 'Successfully restored expense', - 'permissions' => 'Permissions', - 'create_all_help' => 'Allow user to create and modify records', - 'view_all_help' => 'Allow user to view records they didn\'t create', - 'edit_all_help' => 'Allow user to modify records they didn\'t create', - 'view_payment' => 'View Payment', + 'administrator_help' => 'Erlaube Benutzern, andere Benutzer zu administrieren, Einstellungen und alle Einträge zu verändern', + 'user_create_all' => 'Kunden, Rechnungen, etc. erstellen', + 'user_view_all' => 'Kunden, Rechnungen, etc. ansehen', + 'user_edit_all' => 'Kunden, Rechnungen, etc. bearbeiten', + 'gateway_help_20' => ':link um sich bei Sage Pay zu registrieren.', + 'gateway_help_21' => ':link um sich bei Sage Pay zu registrieren.', + 'partial_due' => 'Offener Teilbetrag', + 'restore_vendor' => 'Anbieter Wiederherstellen', + 'restored_vendor' => 'Anbieter erfolgreich wiederhergestellt', + 'restored_expense' => 'Ausgabe erfolgreich wiederhergestellt', + 'permissions' => 'Berechtigungen', + 'create_all_help' => 'Erlaube Benutzer, Einträge zu erstellen und zu verändern', + 'view_all_help' => 'Erlaube Benutzer, Einträge zu sehen, die er nicht selbst erstellt hat', + 'edit_all_help' => 'Erlaube Benutzer, Einträge zu verändern, die er nicht selbst erstellt hat', + 'view_payment' => 'Zahlung Ansehen', - 'january' => 'January', - 'february' => 'February', - 'march' => 'March', + 'january' => 'Jänner', + 'february' => 'Februar', + 'march' => 'März', 'april' => 'April', - 'may' => 'May', - 'june' => 'June', - 'july' => 'July', + 'may' => 'Mai', + 'june' => 'Juni', + 'july' => 'Juli', 'august' => 'August', 'september' => 'September', - 'october' => 'October', + 'october' => 'Oktober', 'november' => 'November', - 'december' => 'December', + 'december' => 'Dezember', ); diff --git a/resources/views/payments/payment.blade.php b/resources/views/payments/payment.blade.php index 274361938bac..949723e7f17a 100644 --- a/resources/views/payments/payment.blade.php +++ b/resources/views/payments/payment.blade.php @@ -13,6 +13,7 @@ var data = { name: $('#first_name').val() + ' ' + $('#last_name').val(), + email: $('#email').val(), address_line1: $('#address1').val(), address_line2: $('#address2').val(), address_city: $('#city').val(), @@ -117,6 +118,7 @@ {{ Former::populate($client) }} {{ Former::populateField('first_name', $contact->first_name) }} {{ Former::populateField('last_name', $contact->last_name) }} + {{ Former::populateField('email', $contact->email) }} @if (!$client->country_id && $client->account->country_id) {{ Former::populateField('country_id', $client->account->country_id) }} @endif @@ -178,8 +180,7 @@ ->label('') !!} - @if (isset($paymentTitle)) -
+
{!! Former::text('email') ->placeholder(trans('texts.email')) @@ -187,7 +188,6 @@ ->label('') !!}
- @endif

 
 

diff --git a/resources/views/tasks/edit.blade.php b/resources/views/tasks/edit.blade.php index fb3648206c6c..0a42f343b6bf 100644 --- a/resources/views/tasks/edit.blade.php +++ b/resources/views/tasks/edit.blade.php @@ -19,6 +19,11 @@ + @if ($errors->first('time_log')) +
  • {{ trans('texts.task_errors') }}
  • + @endif + + {!! Former::open($url)->addClass('col-md-10 col-md-offset-1 warn-on-exit task-form')->method($method)->rules(array()) !!} @if ($task) {!! Former::populate($task) !!} @@ -455,7 +460,7 @@ @endif @endif - @if (Session::has('error')) + @if ($errors->first('time_log')) loadTimeLog({!! json_encode(Input::old('time_log')) !!}); model.showTimeOverlaps(); showTimeDetails(); diff --git a/tests/_support/_generated/AcceptanceTesterActions.php b/tests/_support/_generated/AcceptanceTesterActions.php index 82427d1e2a5e..d219111f887c 100644 --- a/tests/_support/_generated/AcceptanceTesterActions.php +++ b/tests/_support/_generated/AcceptanceTesterActions.php @@ -1,4 +1,4 @@ -amOnPage('/'); * // opens /register page * $I->amOnPage('/register'); - * ?> * ``` * * @param $page @@ -217,16 +216,31 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that the current page contains the given string. - * Specify a locator as the second parameter to match a specific region. + * Checks that the current page contains the given string (case insensitive). + * + * You can specify a specific HTML element (via CSS or XPath) as the second + * parameter to only search within that element. * * ``` php * see('Logout'); // I can suppose user is logged in - * $I->see('Sign Up','h1'); // I can suppose it's a signup page - * $I->see('Sign Up','//body/h1'); // with XPath - * ?> + * $I->see('Logout'); // I can suppose user is logged in + * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page + * $I->see('Sign Up', '//body/h1'); // with XPath * ``` + * + * Note that the search is done after stripping all HTML tags from the body, + * so `$I->see('strong')` will return true for strings like: + * + * - `

    I am Stronger than thou

    ` + * - `` + * + * But will *not* be true for strings like: + * + * - `Home` + * - `
    Home` + * - `` + * + * For checking the raw source code, use `seeInSource()`. * * @param $text * @param null $selector @@ -239,16 +253,31 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that the current page contains the given string. - * Specify a locator as the second parameter to match a specific region. + * Checks that the current page contains the given string (case insensitive). + * + * You can specify a specific HTML element (via CSS or XPath) as the second + * parameter to only search within that element. * * ``` php * see('Logout'); // I can suppose user is logged in - * $I->see('Sign Up','h1'); // I can suppose it's a signup page - * $I->see('Sign Up','//body/h1'); // with XPath - * ?> + * $I->see('Logout'); // I can suppose user is logged in + * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page + * $I->see('Sign Up', '//body/h1'); // with XPath * ``` + * + * Note that the search is done after stripping all HTML tags from the body, + * so `$I->see('strong')` will return true for strings like: + * + * - `

    I am Stronger than thou

    ` + * - `` + * + * But will *not* be true for strings like: + * + * - `Home` + * - `
    Home` + * - `` + * + * For checking the raw source code, use `seeInSource()`. * * @param $text * @param null $selector @@ -262,16 +291,29 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that the current page doesn't contain the text specified. + * Checks that the current page doesn't contain the text specified (case insensitive). * Give a locator as the second parameter to match a specific region. * * ```php * dontSee('Login'); // I can suppose user is already logged in - * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page - * $I->dontSee('Sign Up','//body/h1'); // with XPath - * ?> + * $I->dontSee('Login'); // I can suppose user is already logged in + * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page + * $I->dontSee('Sign Up','//body/h1'); // with XPath * ``` + * + * Note that the search is done after stripping all HTML tags from the body, + * so `$I->dontSee('strong')` will fail on strings like: + * + * - `

    I am Stronger than thou

    ` + * - `` + * + * But will ignore strings like: + * + * - `Home` + * - `
    Home` + * - `` + * + * For checking the raw source code, use `seeInSource()`. * * @param $text * @param null $selector @@ -284,16 +326,29 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that the current page doesn't contain the text specified. + * Checks that the current page doesn't contain the text specified (case insensitive). * Give a locator as the second parameter to match a specific region. * * ```php * dontSee('Login'); // I can suppose user is already logged in - * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page - * $I->dontSee('Sign Up','//body/h1'); // with XPath - * ?> + * $I->dontSee('Login'); // I can suppose user is already logged in + * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page + * $I->dontSee('Sign Up','//body/h1'); // with XPath * ``` + * + * Note that the search is done after stripping all HTML tags from the body, + * so `$I->dontSee('strong')` will fail on strings like: + * + * - `

    I am Stronger than thou

    ` + * - `` + * + * But will ignore strings like: + * + * - `Home` + * - `
    Home` + * - `` + * + * For checking the raw source code, use `seeInSource()`. * * @param $text * @param null $selector @@ -304,6 +359,80 @@ trait FunctionalTesterActions } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string in its + * raw source code. + * + * ``` php + * seeInSource('

    Green eggs & ham

    '); + * ``` + * + * @param $raw + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::seeInSource() + */ + public function canSeeInSource($raw) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string in its + * raw source code. + * + * ``` php + * seeInSource('

    Green eggs & ham

    '); + * ``` + * + * @param $raw + * @see \Codeception\Lib\InnerBrowser::seeInSource() + */ + public function seeInSource($raw) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string in its + * raw source code. + * + * ```php + * dontSeeInSource('

    Green eggs & ham

    '); + * ``` + * + * @param $raw + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Lib\InnerBrowser::dontSeeInSource() + */ + public function cantSeeInSource($raw) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that the current page contains the given string in its + * raw source code. + * + * ```php + * dontSeeInSource('

    Green eggs & ham

    '); + * ``` + * + * @param $raw + * @see \Codeception\Lib\InnerBrowser::dontSeeInSource() + */ + public function dontSeeInSource($raw) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInSource', func_get_args())); + } + + /** * [!] Method is generated. Documentation taken from corresponding module. * @@ -645,7 +774,6 @@ trait FunctionalTesterActions * * @param null $uri * - * @internal param $url * @return mixed * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl() */ @@ -1074,15 +1202,28 @@ trait FunctionalTesterActions * [!] Method is generated. Documentation taken from corresponding module. * * Submits the given form on the page, optionally with the given form - * values. Give the form fields values as an array. + * values. Pass the form field's values as an array in the second + * parameter. * - * Skipped fields will be filled by their values from the page. + * Although this function can be used as a short-hand version of + * `fillField()`, `selectOption()`, `click()` etc. it has some important + * differences: + * + * * Only field *names* may be used, not CSS/XPath selectors nor field labels + * * If a field is sent to this function that does *not* exist on the page, + * it will silently be added to the HTTP request. This is helpful for testing + * some types of forms, but be aware that you will *not* get an exception + * like you would if you called `fillField()` or `selectOption()` with + * a missing field. + * + * Fields that are not provided will be filled by their values from the page, + * or from any previous calls to `fillField()`, `selectOption()` etc. * You don't need to click the 'Submit' button afterwards. * This command itself triggers the request to form's action. * - * You can optionally specify what button's value to include - * in the request with the last parameter as an alternative to - * explicitly setting its value in the second parameter, as + * You can optionally specify which button's value to include + * in the request with the last parameter (as an alternative to + * explicitly setting its value in the second parameter), as * button values are not otherwise included in the request. * * Examples: @@ -1156,7 +1297,8 @@ trait FunctionalTesterActions * ); * ``` * - * Pair this with seeInFormFields for quick testing magic. + * This function works well when paired with `seeInFormFields()` + * for quickly testing CRUD interfaces and form validation logic. * * ``` php * true, * // ... * ]; - * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); + * $I->submitForm('#my-form', $form, 'submitButton'); * // $I->amOnPage('/path/to/form-page') may be needed - * $I->seeInFormFields('//form[@id=my-form]', $form); - * ?> + * $I->seeInFormFields('#my-form', $form); * ``` * * Parameter values can be set to arrays for multiple input fields * of the same name, or multi-select combo boxes. For checkboxes, - * either the string value can be used, or boolean values which will + * you can use either the string value or boolean `true`/`false` which will * be replaced by the checkbox's value in the DOM. * * ``` php @@ -1183,7 +1324,7 @@ trait FunctionalTesterActions * 'field1' => 'value', * 'checkbox' => [ * 'value of first checkbox', - * 'value of second checkbox, + * 'value of second checkbox', * ], * 'otherCheckboxes' => [ * true, @@ -1195,27 +1336,29 @@ trait FunctionalTesterActions * 'second option value' * ] * ]); - * ?> * ``` * * Mixing string and boolean values for a checkbox's value is not supported * and may produce unexpected results. * - * Field names ending in "[]" must be passed without the trailing square + * Field names ending in `[]` must be passed without the trailing square * bracket characters, and must contain an array for its value. This allows * submitting multiple values with the same name, consider: * * ```php + * submitForm('#my-form', [ * 'field[]' => 'value', - * 'field[]' => 'another value', // 'field[]' is already a defined key + * 'field[]' => 'another value', // 'field[]' is already a defined key * ]); * ``` * * The solution is to pass an array value: * * ```php - * // this way both values are submitted + * submitForm('#my-form', [ * 'field' => [ * 'value', @@ -1454,7 +1597,7 @@ trait FunctionalTesterActions * * @param $cssOrXpath * @param $attribute - * @internal param $element + * * @return mixed * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom() */ @@ -1466,7 +1609,28 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * + * Grabs either the text content, or attribute values, of nodes + * matched by $cssOrXpath and returns them as an array. + * + * ```html + * First + * Second + * Third + * ``` + * + * ```php + * grabMultiple('a'); + * + * // would return ['#first', '#second', '#third'] + * $aLinks = $I->grabMultiple('a', 'href'); + * ?> + * ``` + * + * @param $cssOrXpath + * @param $attribute + * @return string[] * @see \Codeception\Lib\InnerBrowser::grabMultiple() */ public function grabMultiple($cssOrXpath, $attribute = null) { @@ -1491,7 +1655,7 @@ trait FunctionalTesterActions * [!] Method is generated. Documentation taken from corresponding module. * * Sets a cookie with the given name and value. - * You can set additional cookie params like `domain`, `path`, `expire`, `secure` in array passed as last argument. + * You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. * * ``` php * + * ``` + * + * ``` php + * switchToIframe("another_frame"); + * ``` + * + * @param string $name + * @see \Codeception\Lib\InnerBrowser::switchToIframe() + */ + public function switchToIframe($name) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('switchToIframe', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Moves back in history. + * + * @param int $numberOfSteps (default value 1) + * @see \Codeception\Lib\InnerBrowser::moveBack() + */ + public function moveBack($numberOfSteps = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('moveBack', func_get_args())); + } + + /** * [!] Method is generated. Documentation taken from corresponding module. * @@ -1996,6 +2197,40 @@ trait FunctionalTesterActions } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Enable Laravel exception handling. + * + * ``` php + * enableExceptionHandling(); + * ?> + * ``` + * @see \Codeception\Module\Laravel5::enableExceptionHandling() + */ + public function enableExceptionHandling() { + return $this->getScenario()->runStep(new \Codeception\Step\Action('enableExceptionHandling', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Disable Laravel exception handling. + * + * ``` php + * disableExceptionHandling(); + * ?> + * ``` + * @see \Codeception\Module\Laravel5::disableExceptionHandling() + */ + public function disableExceptionHandling() { + return $this->getScenario()->runStep(new \Codeception\Step\Action('disableExceptionHandling', func_get_args())); + } + + /** * [!] Method is generated. Documentation taken from corresponding module. * @@ -2016,17 +2251,99 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Enable middleware for the next requests. + * Disable events for the next requests. * * ``` php * enableMiddleware(); + * $I->disableEvents(); * ?> * ``` - * @see \Codeception\Module\Laravel5::enableMiddleware() + * @see \Codeception\Module\Laravel5::disableEvents() */ - public function enableMiddleware() { - return $this->getScenario()->runStep(new \Codeception\Step\Action('enableMiddleware', func_get_args())); + public function disableEvents() { + return $this->getScenario()->runStep(new \Codeception\Step\Action('disableEvents', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Make sure events fired during the test. + * + * ``` php + * seeEventTriggered('App\MyEvent'); + * $I->seeEventTriggered(new App\Events\MyEvent()); + * $I->seeEventTriggered('App\MyEvent', 'App\MyOtherEvent'); + * $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); + * ?> + * ``` + * @param $events + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Laravel5::seeEventTriggered() + */ + public function canSeeEventTriggered($events) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeEventTriggered', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Make sure events fired during the test. + * + * ``` php + * seeEventTriggered('App\MyEvent'); + * $I->seeEventTriggered(new App\Events\MyEvent()); + * $I->seeEventTriggered('App\MyEvent', 'App\MyOtherEvent'); + * $I->seeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); + * ?> + * ``` + * @param $events + * @see \Codeception\Module\Laravel5::seeEventTriggered() + */ + public function seeEventTriggered($events) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeEventTriggered', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Make sure events did not fire during the test. + * + * ``` php + * dontSeeEventTriggered('App\MyEvent'); + * $I->dontSeeEventTriggered(new App\Events\MyEvent()); + * $I->dontSeeEventTriggered('App\MyEvent', 'App\MyOtherEvent'); + * $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); + * ?> + * ``` + * @param $events + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Laravel5::dontSeeEventTriggered() + */ + public function cantSeeEventTriggered($events) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeEventTriggered', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Make sure events did not fire during the test. + * + * ``` php + * dontSeeEventTriggered('App\MyEvent'); + * $I->dontSeeEventTriggered(new App\Events\MyEvent()); + * $I->dontSeeEventTriggered('App\MyEvent', 'App\MyOtherEvent'); + * $I->dontSeeEventTriggered(['App\MyEvent', 'App\MyOtherEvent']); + * ?> + * ``` + * @param $events + * @see \Codeception\Module\Laravel5::dontSeeEventTriggered() + */ + public function dontSeeEventTriggered($events) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeEventTriggered', func_get_args())); } @@ -2050,6 +2367,41 @@ trait FunctionalTesterActions } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current url matches route + * + * ``` php + * seeCurrentRouteIs('posts.index'); + * ?> + * ``` + * @param $routeName + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Laravel5::seeCurrentRouteIs() + */ + public function canSeeCurrentRouteIs($routeName) { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentRouteIs', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Checks that current url matches route + * + * ``` php + * seeCurrentRouteIs('posts.index'); + * ?> + * ``` + * @param $routeName + * @see \Codeception\Module\Laravel5::seeCurrentRouteIs() + */ + public function seeCurrentRouteIs($routeName) { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentRouteIs', func_get_args())); + } + + /** * [!] Method is generated. Documentation taken from corresponding module. * @@ -2070,43 +2422,6 @@ trait FunctionalTesterActions } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that current url matches route - * - * ``` php - * seeCurrentRouteIs('posts.index'); - * ?> - * ``` - * @param $route - * @param array $params - * Conditional Assertion: Test won't be stopped on fail - * @see \Codeception\Module\Laravel5::seeCurrentRouteIs() - */ - public function canSeeCurrentRouteIs($route, $params = null) { - return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentRouteIs', func_get_args())); - } - /** - * [!] Method is generated. Documentation taken from corresponding module. - * - * Checks that current url matches route - * - * ``` php - * seeCurrentRouteIs('posts.index'); - * ?> - * ``` - * @param $route - * @param array $params - * @see \Codeception\Module\Laravel5::seeCurrentRouteIs() - */ - public function seeCurrentRouteIs($route, $params = null) { - return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentRouteIs', func_get_args())); - } - - /** * [!] Method is generated. Documentation taken from corresponding module. * @@ -2119,11 +2434,10 @@ trait FunctionalTesterActions * ``` * * @param $action - * @param array $params * Conditional Assertion: Test won't be stopped on fail * @see \Codeception\Module\Laravel5::seeCurrentActionIs() */ - public function canSeeCurrentActionIs($action, $params = null) { + public function canSeeCurrentActionIs($action) { return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentActionIs', func_get_args())); } /** @@ -2138,10 +2452,9 @@ trait FunctionalTesterActions * ``` * * @param $action - * @param array $params * @see \Codeception\Module\Laravel5::seeCurrentActionIs() */ - public function seeCurrentActionIs($action, $params = null) { + public function seeCurrentActionIs($action) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentActionIs', func_get_args())); } @@ -2159,7 +2472,7 @@ trait FunctionalTesterActions * ``` * * @param string|array $key - * @param mixed $value + * @param mixed|null $value * @return void * Conditional Assertion: Test won't be stopped on fail * @see \Codeception\Module\Laravel5::seeInSession() @@ -2180,7 +2493,7 @@ trait FunctionalTesterActions * ``` * * @param string|array $key - * @param mixed $value + * @param mixed|null $value * @return void * @see \Codeception\Module\Laravel5::seeInSession() */ @@ -2270,16 +2583,53 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Assert that specific form error messages are set in the view. - * - * Useful for validation messages e.g. - * return `Redirect::to('register')->withErrors($validator);` - * - * Example of Usage + * Assert that there are no form errors bound to the View. * * ``` php * seeFormErrorMessages(array('username'=>'Invalid Username')); + * $I->dontSeeFormErrors(); + * ?> + * ``` + * + * @return bool + * Conditional Assertion: Test won't be stopped on fail + * @see \Codeception\Module\Laravel5::dontSeeFormErrors() + */ + public function cantSeeFormErrors() { + return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFormErrors', func_get_args())); + } + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Assert that there are no form errors bound to the View. + * + * ``` php + * dontSeeFormErrors(); + * ?> + * ``` + * + * @return bool + * @see \Codeception\Module\Laravel5::dontSeeFormErrors() + */ + public function dontSeeFormErrors() { + return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeFormErrors', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Assert that specific form error messages are set in the view. + * + * This method calls `seeFormErrorMessage` for each entry in the `$bindings` array. + * + * ``` php + * seeFormErrorMessages([ + * 'username' => 'Invalid Username', + * 'password' => null, + * ]); * ?> * ``` * @param array $bindings @@ -2294,14 +2644,14 @@ trait FunctionalTesterActions * * Assert that specific form error messages are set in the view. * - * Useful for validation messages e.g. - * return `Redirect::to('register')->withErrors($validator);` - * - * Example of Usage + * This method calls `seeFormErrorMessage` for each entry in the `$bindings` array. * * ``` php * seeFormErrorMessages(array('username'=>'Invalid Username')); + * $I->seeFormErrorMessages([ + * 'username' => 'Invalid Username', + * 'password' => null, + * ]); * ?> * ``` * @param array $bindings @@ -2315,48 +2665,50 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Assert that specific form error message is set in the view. + * Assert that a specific form error message is set in the view. * - * Useful for validation messages and generally messages array - * e.g. - * return `Redirect::to('register')->withErrors($validator);` + * If you want to assert that there is a form error message for a specific key + * but don't care about the actual error message you can omit `$expectedErrorMessage`. * - * Example of Usage + * If you do pass `$expectedErrorMessage`, this method checks if the actual error message for a key + * contains `$expectedErrorMessage`. * * ``` php * seeFormErrorMessage('username'); * $I->seeFormErrorMessage('username', 'Invalid Username'); * ?> * ``` * @param string $key - * @param string $errorMessage + * @param string|null $expectedErrorMessage * Conditional Assertion: Test won't be stopped on fail * @see \Codeception\Module\Laravel5::seeFormErrorMessage() */ - public function canSeeFormErrorMessage($key, $errorMessage) { + public function canSeeFormErrorMessage($key, $expectedErrorMessage = null) { return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFormErrorMessage', func_get_args())); } /** * [!] Method is generated. Documentation taken from corresponding module. * - * Assert that specific form error message is set in the view. + * Assert that a specific form error message is set in the view. * - * Useful for validation messages and generally messages array - * e.g. - * return `Redirect::to('register')->withErrors($validator);` + * If you want to assert that there is a form error message for a specific key + * but don't care about the actual error message you can omit `$expectedErrorMessage`. * - * Example of Usage + * If you do pass `$expectedErrorMessage`, this method checks if the actual error message for a key + * contains `$expectedErrorMessage`. * * ``` php * seeFormErrorMessage('username'); * $I->seeFormErrorMessage('username', 'Invalid Username'); * ?> * ``` * @param string $key - * @param string $errorMessage + * @param string|null $expectedErrorMessage * @see \Codeception\Module\Laravel5::seeFormErrorMessage() */ - public function seeFormErrorMessage($key, $errorMessage) { + public function seeFormErrorMessage($key, $expectedErrorMessage = null) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFormErrorMessage', func_get_args())); } @@ -2368,8 +2720,19 @@ trait FunctionalTesterActions * Takes either an object that implements the User interface or * an array of credentials. * + * ``` php + * amLoggedAs(['username' => 'jane@example.com', 'password' => 'password']); + * + * // provide User object + * $I->amLoggedAs( new User ); + * + * // can be verified with $I->seeAuthentication(); + * ?> + * ``` * @param \Illuminate\Contracts\Auth\User|array $user - * @param string $driver + * @param string|null $driver The authentication driver for Laravel <= 5.1.*, guard name for Laravel >= 5.2 * @return void * @see \Codeception\Module\Laravel5::amLoggedAs() */ @@ -2381,7 +2744,7 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Logs user out + * Logout user. * @see \Codeception\Module\Laravel5::logout() */ public function logout() { @@ -2392,20 +2755,24 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that user is authenticated + * Checks that a user is authenticated. + * You can specify the guard that should be use for Laravel >= 5.2. + * @param string|null $guard * Conditional Assertion: Test won't be stopped on fail * @see \Codeception\Module\Laravel5::seeAuthentication() */ - public function canSeeAuthentication() { + public function canSeeAuthentication($guard = null) { return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeAuthentication', func_get_args())); } /** * [!] Method is generated. Documentation taken from corresponding module. * - * Checks that user is authenticated + * Checks that a user is authenticated. + * You can specify the guard that should be use for Laravel >= 5.2. + * @param string|null $guard * @see \Codeception\Module\Laravel5::seeAuthentication() */ - public function seeAuthentication() { + public function seeAuthentication($guard = null) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeAuthentication', func_get_args())); } @@ -2413,20 +2780,24 @@ trait FunctionalTesterActions /** * [!] Method is generated. Documentation taken from corresponding module. * - * Check that user is not authenticated + * Check that user is not authenticated. + * You can specify the guard that should be use for Laravel >= 5.2. + * @param string|null $guard * Conditional Assertion: Test won't be stopped on fail * @see \Codeception\Module\Laravel5::dontSeeAuthentication() */ - public function cantSeeAuthentication() { + public function cantSeeAuthentication($guard = null) { return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeAuthentication', func_get_args())); } /** * [!] Method is generated. Documentation taken from corresponding module. * - * Check that user is not authenticated + * Check that user is not authenticated. + * You can specify the guard that should be use for Laravel >= 5.2. + * @param string|null $guard * @see \Codeception\Module\Laravel5::dontSeeAuthentication() */ - public function dontSeeAuthentication() { + public function dontSeeAuthentication($guard = null) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeAuthentication', func_get_args())); } @@ -2437,7 +2808,6 @@ trait FunctionalTesterActions * Return an instance of a class from the IoC Container. * (http://laravel.com/docs/ioc) * - * Example * ``` php * getScenario()->runStep(new \Codeception\Step\Action('grabRecord', func_get_args())); } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * + * @see \Codeception\Module\Laravel5::haveModel() + */ + public function haveModel($model, $attributes = null, $name = null, $times = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('haveModel', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Use Laravel's model factory to create a model. + * Can only be used with Laravel 5.1 and later. + * + * ``` php + * createModel('App\User'); + * $I->createModel('App\User', ['name' => 'John Doe']); + * $I->createModel('App\User', [], 'admin'); + * $I->createModel('App\User', [], 'admin', 3); + * ?> + * ``` + * + * @see http://laravel.com/docs/5.1/testing#model-factories + * @param string $model + * @param array $attributes + * @param string $name + * @param int $times + * @return mixed + * @see \Codeception\Module\Laravel5::createModel() + */ + public function createModel($model, $attributes = null, $name = null, $times = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('createModel', func_get_args())); + } + + + /** + * [!] Method is generated. Documentation taken from corresponding module. + * + * Use Laravel's model factory to make a model. + * Can only be used with Laravel 5.1 and later. + * + * ``` php + * makeModel('App\User'); + * $I->makeModel('App\User', ['name' => 'John Doe']); + * $I->makeModel('App\User', [], 'admin'); + * $I->makeModel('App\User', [], 'admin', 3); + * ?> + * ``` + * + * @see http://laravel.com/docs/5.1/testing#model-factories + * @param string $model + * @param array $attributes + * @param string $name + * @param int $times + * @return mixed + * @see \Codeception\Module\Laravel5::makeModel() + */ + public function makeModel($model, $attributes = null, $name = null, $times = null) { + return $this->getScenario()->runStep(new \Codeception\Step\Action('makeModel', func_get_args())); + } } diff --git a/tests/acceptance/CheckBalanceCest.php b/tests/acceptance/CheckBalanceCest.php index 33378baab0ba..68cae45c3154 100644 --- a/tests/acceptance/CheckBalanceCest.php +++ b/tests/acceptance/CheckBalanceCest.php @@ -46,7 +46,7 @@ class CheckBalanceCest $I->fillField('table.invoice-table tbody tr:nth-child(1) #product_key', $productKey); $I->click('table.invoice-table tbody tr:nth-child(1) .tt-selectable'); $I->click('Save'); - $I->wait(1); + $I->wait(2); $I->see($clientEmail); $invoiceId = $I->grabFromCurrentUrl('~invoices/(\d+)~'); $I->amOnPage("/clients/{$clientId}"); diff --git a/tests/acceptance/InvoiceCest.php b/tests/acceptance/InvoiceCest.php index 2d8b818d161d..07ac60e24215 100644 --- a/tests/acceptance/InvoiceCest.php +++ b/tests/acceptance/InvoiceCest.php @@ -64,7 +64,7 @@ class InvoiceCest $this->fillItems($I); $I->executeJS("submitAction('email')"); - $I->wait(1); + $I->wait(2); $I->see($clientEmail); $invoiceNumber = $I->grabAttributeFrom('#invoice_number', 'value'); diff --git a/tests/acceptance/TaxRatesCest.php b/tests/acceptance/TaxRatesCest.php index 75f7de7a7508..ebe68f7b5880 100644 --- a/tests/acceptance/TaxRatesCest.php +++ b/tests/acceptance/TaxRatesCest.php @@ -78,7 +78,7 @@ class TaxRatesCest // check total is right before saving $I->see("\${$total}"); $I->click('Save'); - $I->wait(2); + $I->wait(3); $I->see($clientEmail); // check total is right after saving