mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-21 19:00:57 -04:00
Merge branch 'release-2.9.0'
This commit is contained in:
commit
42f7d65aff
@ -81,3 +81,6 @@ WEPAY_FEE_PAYER=payee
|
||||
WEPAY_APP_FEE_MULTIPLIER=0.002
|
||||
WEPAY_APP_FEE_FIXED=0
|
||||
WEPAY_THEME='{"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}' # See https://www.wepay.com/developer/reference/structures#theme
|
||||
|
||||
BLUEVINE_PARTNER_UNIQUE_ID=
|
||||
BLUEVINE_PARTNER_TOKEN=
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ Thumbs.db
|
||||
/error_log
|
||||
/auth.json
|
||||
/public/error_log
|
||||
/Modules
|
||||
|
||||
/ninja.sublime-project
|
||||
/ninja.sublime-workspace
|
||||
|
@ -73,12 +73,16 @@ class CheckData extends Command {
|
||||
$this->logMessage('Done');
|
||||
$errorEmail = env('ERROR_EMAIL');
|
||||
|
||||
if ( ! $this->isValid && $errorEmail) {
|
||||
Mail::raw($this->log, function ($message) use ($errorEmail) {
|
||||
$message->to($errorEmail)
|
||||
->from(CONTACT_EMAIL)
|
||||
->subject('Check-Data');
|
||||
});
|
||||
if ( ! $this->isValid) {
|
||||
if ($errorEmail) {
|
||||
Mail::raw($this->log, function ($message) use ($errorEmail) {
|
||||
$message->to($errorEmail)
|
||||
->from(CONTACT_EMAIL)
|
||||
->subject('Check-Data');
|
||||
});
|
||||
} else {
|
||||
$this->info($this->log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +213,7 @@ class CheckData extends Command {
|
||||
->where('accounts.id', '!=', 20432)
|
||||
->where('clients.is_deleted', '=', 0)
|
||||
->where('invoices.is_deleted', '=', 0)
|
||||
->where('invoices.is_public', '=', 1)
|
||||
->where('invoices.invoice_type_id', '=', INVOICE_TYPE_STANDARD)
|
||||
->where('invoices.is_recurring', '=', 0)
|
||||
->havingRaw('abs(clients.balance - sum(invoices.balance)) > .01 and clients.balance != 999999999.9999');
|
||||
|
174
app/Console/Commands/MakeClass.php
Normal file
174
app/Console/Commands/MakeClass.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
use Nwidart\Modules\Commands\GeneratorCommand;
|
||||
use Nwidart\Modules\Support\Stub;
|
||||
use Nwidart\Modules\Traits\ModuleCommandTrait;
|
||||
|
||||
class MakeClass extends GeneratorCommand
|
||||
{
|
||||
use ModuleCommandTrait;
|
||||
|
||||
protected $argumentName = 'name';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'ninja:make-class';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create class stub';
|
||||
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['name', InputArgument::REQUIRED, 'The name of the module.'],
|
||||
['module', InputArgument::REQUIRED, 'The name of module will be used.'],
|
||||
['class', InputArgument::REQUIRED, 'The name of the class.'],
|
||||
['prefix', InputArgument::OPTIONAL, 'The prefix of the class.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return array(
|
||||
array('fields', null, InputOption::VALUE_OPTIONAL, 'The model attributes.', null),
|
||||
array('filename', null, InputOption::VALUE_OPTIONAL, 'The class filename.', null),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getTemplateContents()
|
||||
{
|
||||
$module = $this->laravel['modules']->findOrFail($this->getModuleName());
|
||||
$path = str_replace('/', '\\', config('modules.paths.generator.' . $this->argument('class')));
|
||||
|
||||
return (new Stub('/' . $this->argument('prefix') . $this->argument('class') . '.stub', [
|
||||
'NAMESPACE' => $this->getClassNamespace($module) . "\\" . $path,
|
||||
'LOWER_NAME' => $module->getLowerName(),
|
||||
'CLASS' => $this->getClass(),
|
||||
'STUDLY_NAME' => Str::studly($module->getLowerName()),
|
||||
'DATATABLE_COLUMNS' => $this->getColumns(),
|
||||
'FORM_FIELDS' => $this->getFormFields(),
|
||||
'DATABASE_FIELDS' => $this->getDatabaseFields($module),
|
||||
'TRANSFORMER_FIELDS' => $this->getTransformerFields($module),
|
||||
]))->render();
|
||||
}
|
||||
|
||||
public function getDestinationFilePath()
|
||||
{
|
||||
$path = $this->laravel['modules']->getModulePath($this->getModuleName());
|
||||
$seederPath = $this->laravel['modules']->config('paths.generator.' . $this->argument('class'));
|
||||
|
||||
return $path . $seederPath . '/' . $this->getFileName() . '.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getFileName()
|
||||
{
|
||||
if ($this->option('filename')) {
|
||||
return $this->option('filename');
|
||||
}
|
||||
return studly_case($this->argument('prefix')) . studly_case($this->argument('name')) . Str::studly($this->argument('class'));
|
||||
}
|
||||
|
||||
protected function getColumns()
|
||||
{
|
||||
$fields = $this->option('fields');
|
||||
$fields = explode(',', $fields);
|
||||
$str = '';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ( ! $field) {
|
||||
continue;
|
||||
}
|
||||
$field = explode(':', $field)[0];
|
||||
$str .= '[
|
||||
\''. $field . '\',
|
||||
function ($model) {
|
||||
return $model->' . $field . ';
|
||||
}
|
||||
],';
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
protected function getFormFields()
|
||||
{
|
||||
$fields = $this->option('fields');
|
||||
$fields = explode(',', $fields);
|
||||
$str = '';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ( ! $field) {
|
||||
continue;
|
||||
}
|
||||
$parts = explode(':', $field);
|
||||
$field = $parts[0];
|
||||
$type = $parts[1];
|
||||
|
||||
if ($type == 'text') {
|
||||
$str .= "{!! Former::textarea('" . $field . "') !!}\n";
|
||||
} else {
|
||||
$str .= "{!! Former::text('" . $field . "') !!}\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
protected function getDatabaseFields($module)
|
||||
{
|
||||
$fields = $this->option('fields');
|
||||
$fields = explode(',', $fields);
|
||||
$str = '';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ( ! $field) {
|
||||
continue;
|
||||
}
|
||||
$field = explode(':', $field)[0];
|
||||
$str .= "'" . $module->getLowerName() . ".{$field}', ";
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
protected function getTransformerFields($module)
|
||||
{
|
||||
$fields = $this->option('fields');
|
||||
$fields = explode(',', $fields);
|
||||
$str = '';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ( ! $field) {
|
||||
continue;
|
||||
}
|
||||
$field = explode(':', $field)[0];
|
||||
$str .= "'{$field}' => $" . $module->getLowerName() . "->$field,\n ";
|
||||
}
|
||||
|
||||
return rtrim($str);
|
||||
|
||||
}
|
||||
}
|
98
app/Console/Commands/MakeModule.php
Normal file
98
app/Console/Commands/MakeModule.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class MakeModule extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:make-module {name} {fields?} {--migrate=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Generate Module CRUD';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$name = $this->argument('name');
|
||||
$fields = $this->argument('fields');
|
||||
$migrate = $this->option('migrate');
|
||||
$lower = strtolower($name);
|
||||
|
||||
// convert 'name:string,description:text' to 'name,description'
|
||||
$fillable = explode(',', $fields);
|
||||
$fillable = array_map(function($item) {
|
||||
return explode(':', $item)[0];
|
||||
}, $fillable);
|
||||
$fillable = join(',', $fillable);
|
||||
|
||||
$this->info("Creating module: {$name}...");
|
||||
|
||||
Artisan::call('module:make', ['name' => [$name]]);
|
||||
Artisan::call('module:make-migration', ['name' => "create_{$lower}_table", '--fields' => $fields, 'module' => $name]);
|
||||
Artisan::call('module:make-model', ['model' => $name, 'module' => $name, '--fillable' => $fillable]);
|
||||
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'views', '--fields' => $fields, '--filename' => 'edit.blade']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'datatable', '--fields' => $fields]);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'repository', '--fields' => $fields]);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'policy']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'auth-provider']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'presenter']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request', 'prefix' => 'create']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'request', 'prefix' => 'update']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'api-controller']);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'transformer', '--fields' => $fields]);
|
||||
Artisan::call('ninja:make-class', ['name' => $name, 'module' => $name, 'class' => 'lang', '--filename' => 'texts']);
|
||||
|
||||
if ($migrate == 'false') {
|
||||
$this->info("Use the following command to run the migrations:\nphp artisan module:migrate $name");
|
||||
} else {
|
||||
Artisan::call('module:migrate', ['module' => $name]);
|
||||
}
|
||||
|
||||
Artisan::call('module:dump');
|
||||
|
||||
$this->info("Done");
|
||||
}
|
||||
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['name', InputArgument::REQUIRED, 'The name of the module.'],
|
||||
['fields', InputArgument::OPTIONAL, 'The fields of the module.']
|
||||
];
|
||||
}
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
return array(
|
||||
array('migrate', null, InputOption::VALUE_OPTIONAL, 'The model attributes.', null),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -58,7 +58,7 @@ class SendRecurringInvoices extends Command
|
||||
$today = new DateTime();
|
||||
|
||||
$invoices = Invoice::with('account.timezone', 'invoice_items', 'client', 'user')
|
||||
->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
|
||||
->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND is_public IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
|
||||
->orderBy('id', 'asc')
|
||||
->get();
|
||||
$this->info(count($invoices).' recurring invoice(s) found');
|
||||
@ -81,7 +81,7 @@ class SendRecurringInvoices extends Command
|
||||
}
|
||||
|
||||
$delayedAutoBillInvoices = Invoice::with('account.timezone', 'recurring_invoice', 'invoice_items', 'client', 'user')
|
||||
->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS FALSE
|
||||
->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS FALSE AND is_public IS TRUE
|
||||
AND balance > 0 AND due_date = ? AND recurring_invoice_id IS NOT NULL',
|
||||
[$today->format('Y-m-d')])
|
||||
->orderBy('invoices.id', 'asc')
|
||||
|
164
app/Console/Commands/stubs/api-controller.stub
Normal file
164
app/Console/Commands/stubs/api-controller.stub
Normal file
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Http\Controllers\BaseAPIController;
|
||||
use Modules\$STUDLY_NAME$\Repositories\$STUDLY_NAME$Repository;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\$STUDLY_NAME$Request;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\Create$STUDLY_NAME$Request;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\Update$STUDLY_NAME$Request;
|
||||
|
||||
class $STUDLY_NAME$ApiController extends BaseAPIController
|
||||
{
|
||||
protected $$STUDLY_NAME$Repo;
|
||||
protected $entityType = '$LOWER_NAME$';
|
||||
|
||||
public function __construct($STUDLY_NAME$Repository $$LOWER_NAME$Repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->$LOWER_NAME$Repo = $$LOWER_NAME$Repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SWG\Get(
|
||||
* path="/$LOWER_NAME$",
|
||||
* summary="List of $LOWER_NAME$",
|
||||
* tags={"$LOWER_NAME$"},
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="A list with $LOWER_NAME$",
|
||||
* @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/$STUDLY_NAME$"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$data = $this->$LOWER_NAME$Repo->all();
|
||||
|
||||
return $this->listResponse($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @SWG\Get(
|
||||
* path="/$LOWER_NAME$/{$LOWER_NAME$_id}",
|
||||
* summary="Individual $STUDLY_NAME$",
|
||||
* tags={"$LOWER_NAME$"},
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="A single $LOWER_NAME$",
|
||||
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
|
||||
public function show($STUDLY_NAME$Request $request)
|
||||
{
|
||||
return $this->itemResponse($request->entity());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @SWG\Post(
|
||||
* path="/$LOWER_NAME$",
|
||||
* tags={"$LOWER_NAME$"},
|
||||
* summary="Create a $LOWER_NAME$",
|
||||
* @SWG\Parameter(
|
||||
* in="body",
|
||||
* name="body",
|
||||
* @SWG\Schema(ref="#/definitions/$STUDLY_NAME$")
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="New $LOWER_NAME$",
|
||||
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function store(Create$STUDLY_NAME$Request $request)
|
||||
{
|
||||
$$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input());
|
||||
|
||||
return $this->itemResponse($$LOWER_NAME$);
|
||||
}
|
||||
|
||||
/**
|
||||
* @SWG\Put(
|
||||
* path="/$LOWER_NAME$/{$LOWER_NAME$_id}",
|
||||
* tags={"$LOWER_NAME$"},
|
||||
* summary="Update a $LOWER_NAME$",
|
||||
* @SWG\Parameter(
|
||||
* in="body",
|
||||
* name="body",
|
||||
* @SWG\Schema(ref="#/definitions/$STUDLY_NAME$")
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Update $LOWER_NAME$",
|
||||
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
|
||||
public function update(Update$STUDLY_NAME$Request $request, $publicId)
|
||||
{
|
||||
if ($request->action) {
|
||||
return $this->handleAction($request);
|
||||
}
|
||||
|
||||
$$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input(), $request->entity());
|
||||
|
||||
return $this->itemResponse($$LOWER_NAME$);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @SWG\Delete(
|
||||
* path="/$LOWER_NAME$/{$LOWER_NAME$_id}",
|
||||
* tags={"$LOWER_NAME$"},
|
||||
* summary="Delete a $LOWER_NAME$",
|
||||
* @SWG\Parameter(
|
||||
* in="body",
|
||||
* name="body",
|
||||
* @SWG\Schema(ref="#/definitions/$STUDLY_NAME$")
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Delete $LOWER_NAME$",
|
||||
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/$STUDLY_NAME$"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
|
||||
public function destroy(Update$STUDLY_NAME$Request $request)
|
||||
{
|
||||
$$LOWER_NAME$ = $request->entity();
|
||||
|
||||
$this->$LOWER_NAME$Repo->delete($$LOWER_NAME$);
|
||||
|
||||
return $this->itemResponse($$LOWER_NAME$);
|
||||
}
|
||||
|
||||
}
|
17
app/Console/Commands/stubs/auth-provider.stub
Normal file
17
app/Console/Commands/stubs/auth-provider.stub
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Providers\AuthServiceProvider;
|
||||
|
||||
class $STUDLY_NAME$AuthProvider extends AuthServiceProvider
|
||||
{
|
||||
/**
|
||||
* The policy mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
\Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$::class => \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class,
|
||||
];
|
||||
}
|
68
app/Console/Commands/stubs/command.stub
Executable file
68
app/Console/Commands/stubs/command.stub
Executable file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
class $CLASS$ extends Command
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = '$COMMAND_NAME$';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['example', InputArgument::REQUIRED, 'An example argument.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null],
|
||||
];
|
||||
}
|
||||
}
|
15
app/Console/Commands/stubs/composer.stub
Executable file
15
app/Console/Commands/stubs/composer.stub
Executable file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "$VENDOR$/$LOWER_NAME$",
|
||||
"description": "",
|
||||
"authors": [
|
||||
{
|
||||
"name": "$AUTHOR_NAME$",
|
||||
"email": "$AUTHOR_EMAIL$"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\": ""
|
||||
}
|
||||
}
|
||||
}
|
9
app/Console/Commands/stubs/controller-plain.stub
Executable file
9
app/Console/Commands/stubs/controller-plain.stub
Executable file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace $CLASS_NAMESPACE$;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class $CLASS$ extends Controller
|
||||
{
|
||||
}
|
131
app/Console/Commands/stubs/controller.stub
Executable file
131
app/Console/Commands/stubs/controller.stub
Executable file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace $CLASS_NAMESPACE$;
|
||||
|
||||
use Auth;
|
||||
use App\Http\Controllers\BaseController;
|
||||
use App\Services\DatatableService;
|
||||
use Modules\$STUDLY_NAME$\Datatables\$STUDLY_NAME$Datatable;
|
||||
use Modules\$STUDLY_NAME$\Repositories\$STUDLY_NAME$Repository;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\$STUDLY_NAME$Request;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\Create$STUDLY_NAME$Request;
|
||||
use Modules\$STUDLY_NAME$\Http\Requests\Update$STUDLY_NAME$Request;
|
||||
|
||||
class $CLASS$ extends BaseController
|
||||
{
|
||||
protected $$STUDLY_NAME$Repo;
|
||||
//protected $entityType = '$LOWER_NAME$';
|
||||
|
||||
public function __construct($STUDLY_NAME$Repository $$LOWER_NAME$Repo)
|
||||
{
|
||||
//parent::__construct();
|
||||
|
||||
$this->$LOWER_NAME$Repo = $$LOWER_NAME$Repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('list_wrapper', [
|
||||
'entityType' => '$LOWER_NAME$',
|
||||
'datatable' => new $STUDLY_NAME$Datatable(),
|
||||
'title' => mtrans('$LOWER_NAME$', '$LOWER_NAME$_list'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable(DatatableService $datatableService)
|
||||
{
|
||||
$search = request()->input('test');
|
||||
$userId = Auth::user()->filterId();
|
||||
|
||||
$datatable = new $STUDLY_NAME$Datatable();
|
||||
$query = $this->$LOWER_NAME$Repo->find($search, $userId);
|
||||
|
||||
return $datatableService->createDatatable($datatable, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
* @return Response
|
||||
*/
|
||||
public function create($STUDLY_NAME$Request $request)
|
||||
{
|
||||
$data = [
|
||||
'$LOWER_NAME$' => null,
|
||||
'method' => 'POST',
|
||||
'url' => '$LOWER_NAME$',
|
||||
'title' => mtrans('$LOWER_NAME$', 'new_$LOWER_NAME$'),
|
||||
];
|
||||
|
||||
return view('$LOWER_NAME$::edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Create$STUDLY_NAME$Request $request)
|
||||
{
|
||||
$$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input());
|
||||
|
||||
return redirect()->to($$LOWER_NAME$->present()->editUrl)
|
||||
->with('message', mtrans('$LOWER_NAME$', 'created_$LOWER_NAME$'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
* @return Response
|
||||
*/
|
||||
public function edit($STUDLY_NAME$Request $request)
|
||||
{
|
||||
$$LOWER_NAME$ = $request->entity();
|
||||
|
||||
$data = [
|
||||
'$LOWER_NAME$' => $$LOWER_NAME$,
|
||||
'method' => 'PUT',
|
||||
'url' => '$LOWER_NAME$/' . $$LOWER_NAME$->public_id,
|
||||
'title' => mtrans('$LOWER_NAME$', 'edit_$LOWER_NAME$'),
|
||||
];
|
||||
|
||||
return view('$LOWER_NAME$::edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing a resource.
|
||||
* @return Response
|
||||
*/
|
||||
public function show($STUDLY_NAME$Request $request)
|
||||
{
|
||||
return redirect()->to("$LOWER_NAME$/{$request->$LOWER_NAME$}/edit");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Update$STUDLY_NAME$Request $request)
|
||||
{
|
||||
$$LOWER_NAME$ = $this->$LOWER_NAME$Repo->save($request->input(), $request->entity());
|
||||
|
||||
return redirect()->to($$LOWER_NAME$->present()->editUrl)
|
||||
->with('message', mtrans('$LOWER_NAME$', 'updated_$LOWER_NAME$'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update multiple resources
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
$action = request()->input('action');
|
||||
$ids = request()->input('public_id') ?: request()->input('ids');
|
||||
$count = $this->$LOWER_NAME$Repo->bulk($ids, $action);
|
||||
|
||||
return redirect()->to('$LOWER_NAME$')
|
||||
->with('message', mtrans('$LOWER_NAME$', $action . '_$LOWER_NAME$_complete'));
|
||||
}
|
||||
}
|
28
app/Console/Commands/stubs/createrequest.stub
Normal file
28
app/Console/Commands/stubs/createrequest.stub
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
class Create$CLASS$Request extends $CLASS$Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('create', '$LOWER_NAME$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
43
app/Console/Commands/stubs/datatable.stub
Normal file
43
app/Console/Commands/stubs/datatable.stub
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Utils;
|
||||
use URL;
|
||||
use Auth;
|
||||
use App\Ninja\Datatables\EntityDatatable;
|
||||
|
||||
class $CLASS$Datatable extends EntityDatatable
|
||||
{
|
||||
public $entityType = '$LOWER_NAME$';
|
||||
public $sortCol = 1;
|
||||
|
||||
public function columns()
|
||||
{
|
||||
return [
|
||||
$DATATABLE_COLUMNS$
|
||||
[
|
||||
'created_at',
|
||||
function ($model) {
|
||||
return Utils::fromSqlDateTime($model->created_at);
|
||||
}
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
[
|
||||
mtrans('$LOWER_NAME$', 'edit_$LOWER_NAME$'),
|
||||
function ($model) {
|
||||
return URL::to("$LOWER_NAME$/{$model->public_id}/edit");
|
||||
},
|
||||
function ($model) {
|
||||
return Auth::user()->can('editByOwner', ['$LOWER_NAME$', $model->user_id]);
|
||||
}
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
30
app/Console/Commands/stubs/event.stub
Executable file
30
app/Console/Commands/stubs/event.stub
Executable file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class $CLASS$
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should be broadcast on.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
33
app/Console/Commands/stubs/job.stub
Executable file
33
app/Console/Commands/stubs/job.stub
Executable file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Bus\Queueable;
|
||||
|
||||
class $CLASS$ implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels, Queueable;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
17
app/Console/Commands/stubs/json.stub
Executable file
17
app/Console/Commands/stubs/json.stub
Executable file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "$STUDLY_NAME$",
|
||||
"alias": "$LOWER_NAME$",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"active": 1,
|
||||
"order": 0,
|
||||
"providers": [
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Providers\\$STUDLY_NAME$ServiceProvider"
|
||||
],
|
||||
"aliases":{},
|
||||
"files": [
|
||||
"start.php"
|
||||
],
|
||||
"icon": "th-large",
|
||||
"plural": "$LOWER_NAME$"
|
||||
}
|
19
app/Console/Commands/stubs/lang.stub
Normal file
19
app/Console/Commands/stubs/lang.stub
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
$LANG = array(
|
||||
|
||||
'$LOWER_NAME$' => '$STUDLY_NAME$',
|
||||
'$LOWER_NAME$_list' => '$STUDLY_NAME$ List',
|
||||
'archive_$LOWER_NAME$' => 'Archive $STUDLY_NAME$',
|
||||
'delete_$LOWER_NAME$' => 'Delete $STUDLY_NAME$',
|
||||
'edit_$LOWER_NAME$' => 'Edit $STUDLY_NAME$',
|
||||
'restore_$LOWER_NAME$' => 'Restore $STUDLY_NAME$',
|
||||
'new_$LOWER_NAME$' => 'New $STUDLY_NAME$',
|
||||
'created_$LOWER_NAME$' => 'Successfully created $LOWER_NAME$',
|
||||
'updated_$LOWER_NAME$' => 'Successfully updated $LOWER_NAME$',
|
||||
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
||||
?>
|
31
app/Console/Commands/stubs/listener.stub
Executable file
31
app/Console/Commands/stubs/listener.stub
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use $EVENTNAME$;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class $CLASS$
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \$EVENTNAME$ $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(\$EVENTNAME$ $event)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
33
app/Console/Commands/stubs/mail.stub
Executable file
33
app/Console/Commands/stubs/mail.stub
Executable file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class $CLASS$ extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->view('view.name');
|
||||
}
|
||||
}
|
21
app/Console/Commands/stubs/middleware.stub
Executable file
21
app/Console/Commands/stubs/middleware.stub
Executable file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class $CLASS$
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
return $next($request);
|
||||
}
|
||||
}
|
31
app/Console/Commands/stubs/migration/add.stub
Executable file
31
app/Console/Commands/stubs/migration/add.stub
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class $CLASS$ extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('$TABLE$', function (Blueprint $table) {
|
||||
$FIELDS_UP$
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('$TABLE$', function (Blueprint $table) {
|
||||
$FIELDS_DOWN$
|
||||
});
|
||||
}
|
||||
}
|
44
app/Console/Commands/stubs/migration/create.stub
Executable file
44
app/Console/Commands/stubs/migration/create.stub
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class $CLASS$ extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create(strtolower('$TABLE$'), function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('user_id')->index();
|
||||
$table->unsignedInteger('account_id')->index();
|
||||
$table->unsignedInteger('client_id')->index()->nullable();
|
||||
|
||||
$FIELDS$
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
$table->boolean('is_deleted')->default(false);
|
||||
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||
|
||||
$table->unsignedInteger('public_id')->index();
|
||||
$table->unique( ['account_id', 'public_id'] );
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists(strtolower('$TABLE$'));
|
||||
}
|
||||
}
|
31
app/Console/Commands/stubs/migration/delete.stub
Executable file
31
app/Console/Commands/stubs/migration/delete.stub
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class $CLASS$ extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('$TABLE$', function (Blueprint $table) {
|
||||
$FIELDS_UP$
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('$TABLE$', function (Blueprint $table) {
|
||||
$FIELDS_DOWN$
|
||||
});
|
||||
}
|
||||
}
|
31
app/Console/Commands/stubs/migration/drop.stub
Executable file
31
app/Console/Commands/stubs/migration/drop.stub
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class $CLASS$ extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('$TABLE$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::create('$TABLE$', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$FIELDS$
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
}
|
27
app/Console/Commands/stubs/migration/plain.stub
Executable file
27
app/Console/Commands/stubs/migration/plain.stub
Executable file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class $CLASS$ extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
34
app/Console/Commands/stubs/model.stub
Executable file
34
app/Console/Commands/stubs/model.stub
Executable file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Models\EntityModel;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class $CLASS$ extends EntityModel
|
||||
{
|
||||
use PresentableTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'Modules\$CLASS$\Presenters\$CLASS$Presenter';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $fillable = $FILLABLE$;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = '$LOWER_NAME$';
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return '$LOWER_NAME$';
|
||||
}
|
||||
|
||||
}
|
61
app/Console/Commands/stubs/notification.stub
Executable file
61
app/Console/Commands/stubs/notification.stub
Executable file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class $CLASS$ extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', 'https://laravel.com')
|
||||
->line('Thank you for using our application!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
10
app/Console/Commands/stubs/policy.stub
Normal file
10
app/Console/Commands/stubs/policy.stub
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Policies\EntityPolicy;
|
||||
|
||||
class $STUDLY_NAME$Policy extends EntityPolicy
|
||||
{
|
||||
|
||||
}
|
10
app/Console/Commands/stubs/presenter.stub
Normal file
10
app/Console/Commands/stubs/presenter.stub
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Ninja\Presenters\EntityPresenter;
|
||||
|
||||
class $STUDLY_NAME$Presenter extends EntityPresenter
|
||||
{
|
||||
|
||||
}
|
44
app/Console/Commands/stubs/provider.stub
Executable file
44
app/Console/Commands/stubs/provider.stub
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Providers\AuthServiceProvider;
|
||||
|
||||
class $CLASS$ extends AuthServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* The policy mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
\Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$::class => \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
71
app/Console/Commands/stubs/repository.stub
Normal file
71
app/Console/Commands/stubs/repository.stub
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use DB;
|
||||
use Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$;
|
||||
use App\Ninja\Repositories\BaseRepository;
|
||||
//use App\Events\$STUDLY_NAME$WasCreated;
|
||||
//use App\Events\$STUDLY_NAME$WasUpdated;
|
||||
|
||||
class $STUDLY_NAME$Repository extends BaseRepository
|
||||
{
|
||||
public function getClassName()
|
||||
{
|
||||
return 'Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$';
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $STUDLY_NAME$::scope()
|
||||
->orderBy('created_at', 'desc')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function find($filter = null, $userId = false)
|
||||
{
|
||||
$query = DB::table('$LOWER_NAME$')
|
||||
->where('$LOWER_NAME$.account_id', '=', \Auth::user()->account_id)
|
||||
->select(
|
||||
$DATABASE_FIELDS$
|
||||
'$LOWER_NAME$.public_id',
|
||||
'$LOWER_NAME$.deleted_at',
|
||||
'$LOWER_NAME$.created_at',
|
||||
'$LOWER_NAME$.is_deleted',
|
||||
'$LOWER_NAME$.user_id'
|
||||
);
|
||||
|
||||
$this->applyFilters($query, '$LOWER_NAME$');
|
||||
|
||||
if ($userId) {
|
||||
$query->where('clients.user_id', '=', $userId);
|
||||
}
|
||||
|
||||
/*
|
||||
if ($filter) {
|
||||
$query->where();
|
||||
}
|
||||
*/
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function save($data, $$LOWER_NAME$ = null)
|
||||
{
|
||||
$entity = $$LOWER_NAME$ ?: $STUDLY_NAME$::createNew();
|
||||
|
||||
$entity->fill($data);
|
||||
$entity->save();
|
||||
|
||||
/*
|
||||
if (!$publicId || $publicId == '-1') {
|
||||
event(new ClientWasCreated($client));
|
||||
} else {
|
||||
event(new ClientWasUpdated($client));
|
||||
}
|
||||
*/
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
}
|
10
app/Console/Commands/stubs/request.stub
Executable file
10
app/Console/Commands/stubs/request.stub
Executable file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Http\Requests\EntityRequest;
|
||||
|
||||
class $CLASS$Request extends EntityRequest
|
||||
{
|
||||
protected $entityType = '$LOWER_NAME$';
|
||||
}
|
39
app/Console/Commands/stubs/route-provider.stub
Executable file
39
app/Console/Commands/stubs/route-provider.stub
Executable file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace $MODULE_NAMESPACE$\$MODULE$\Providers;
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
|
||||
class $NAME$ extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The root namespace to assume when generating URLs to actions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rootUrlNamespace = '$MODULE_NAMESPACE$\$MODULE$\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @param Router $router
|
||||
* @return void
|
||||
*/
|
||||
public function before(Router $router)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map(Router $router)
|
||||
{
|
||||
// require __DIR__ . '/../Http/routes.php';
|
||||
}
|
||||
}
|
13
app/Console/Commands/stubs/routes.stub
Executable file
13
app/Console/Commands/stubs/routes.stub
Executable file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
Route::group(['middleware' => 'auth', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\Controllers'], function()
|
||||
{
|
||||
Route::resource('$LOWER_NAME$', '$STUDLY_NAME$Controller');
|
||||
Route::post('$LOWER_NAME$/bulk', '$STUDLY_NAME$Controller@bulk');
|
||||
Route::get('api/$LOWER_NAME$', '$STUDLY_NAME$Controller@datatable');
|
||||
});
|
||||
|
||||
Route::group(['middleware' => 'api', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\ApiControllers', 'prefix' => 'api/v1'], function()
|
||||
{
|
||||
Route::resource('$LOWER_NAME$', '$STUDLY_NAME$ApiController');
|
||||
});
|
5
app/Console/Commands/stubs/scaffold/config.stub
Executable file
5
app/Console/Commands/stubs/scaffold/config.stub
Executable file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'name' => '$STUDLY_NAME$'
|
||||
];
|
110
app/Console/Commands/stubs/scaffold/provider.stub
Executable file
110
app/Console/Commands/stubs/scaffold/provider.stub
Executable file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use App\Providers\AuthServiceProvider;
|
||||
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
|
||||
|
||||
class $CLASS$ extends AuthServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* The policy mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
\Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$::class => \Modules\$STUDLY_NAME$\Policies\$STUDLY_NAME$Policy::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot(GateContract $gate)
|
||||
{
|
||||
parent::boot($gate);
|
||||
|
||||
$this->registerTranslations();
|
||||
$this->registerConfig();
|
||||
$this->registerViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Register config.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConfig()
|
||||
{
|
||||
$this->publishes([
|
||||
__DIR__.'/../$PATH_CONFIG$/config.php' => config_path('$LOWER_NAME$.php'),
|
||||
]);
|
||||
$this->mergeConfigFrom(
|
||||
__DIR__.'/../$PATH_CONFIG$/config.php', '$LOWER_NAME$'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register views.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerViews()
|
||||
{
|
||||
$viewPath = base_path('resources/views/modules/$LOWER_NAME$');
|
||||
|
||||
$sourcePath = __DIR__.'/../$PATH_VIEWS$';
|
||||
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath
|
||||
]);
|
||||
|
||||
$this->loadViewsFrom(array_merge(array_map(function ($path) {
|
||||
return $path . '/modules/$LOWER_NAME$';
|
||||
}, \Config::get('view.paths')), [$sourcePath]), '$LOWER_NAME$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register translations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerTranslations()
|
||||
{
|
||||
$langPath = base_path('resources/lang/modules/$LOWER_NAME$');
|
||||
|
||||
if (is_dir($langPath)) {
|
||||
$this->loadTranslationsFrom($langPath, '$LOWER_NAME$');
|
||||
} else {
|
||||
$this->loadTranslationsFrom(__DIR__ .'/../$PATH_LANG$', '$LOWER_NAME$');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
21
app/Console/Commands/stubs/seeder.stub
Executable file
21
app/Console/Commands/stubs/seeder.stub
Executable file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class $NAME$ extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Model::unguard();
|
||||
|
||||
// $this->call("OthersTableSeeder");
|
||||
}
|
||||
}
|
15
app/Console/Commands/stubs/start.stub
Executable file
15
app/Console/Commands/stubs/start.stub
Executable file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Namespaces And Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When a module starting, this file will executed automatically. This helps
|
||||
| to register some namespaces like translator or view. Also this file
|
||||
| will load the routes file for each module. You may also modify
|
||||
| this file as you want.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__ . '/Http/routes.php';
|
35
app/Console/Commands/stubs/transformer.stub
Normal file
35
app/Console/Commands/stubs/transformer.stub
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Modules\$STUDLY_NAME$\Models\$STUDLY_NAME$;
|
||||
use App\Ninja\Transformers\EntityTransformer;
|
||||
|
||||
/**
|
||||
* @SWG\Definition(definition="$STUDLY_NAME$", @SWG\Xml(name="$STUDLY_NAME$"))
|
||||
*/
|
||||
|
||||
class $STUDLY_NAME$Transformer extends EntityTransformer
|
||||
{
|
||||
/**
|
||||
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="user_id", type="integer", example=1)
|
||||
* @SWG\Property(property="account_key", type="string", example="123456")
|
||||
* @SWG\Property(property="updated_at", type="timestamp", example="")
|
||||
* @SWG\Property(property="archived_at", type="timestamp", example="1451160233")
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param $STUDLY_NAME$ $$LOWER_NAME$
|
||||
* @return array
|
||||
*/
|
||||
public function transform($STUDLY_NAME$ $$LOWER_NAME$)
|
||||
{
|
||||
return array_merge($this->getDefaults($$LOWER_NAME$), [
|
||||
$TRANSFORMER_FIELDS$
|
||||
'id' => (int) $$LOWER_NAME$->public_id,
|
||||
'updated_at' => $this->getTimestamp($$LOWER_NAME$->updated_at),
|
||||
'archived_at' => $this->getTimestamp($$LOWER_NAME$->deleted_at),
|
||||
]);
|
||||
}
|
||||
}
|
28
app/Console/Commands/stubs/updaterequest.stub
Normal file
28
app/Console/Commands/stubs/updaterequest.stub
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
class Update$CLASS$Request extends $CLASS$Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('edit', $this->entity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
57
app/Console/Commands/stubs/views.stub
Executable file
57
app/Console/Commands/stubs/views.stub
Executable file
@ -0,0 +1,57 @@
|
||||
@extends('header')
|
||||
|
||||
@section('content')
|
||||
|
||||
{!! Former::open($url)
|
||||
->addClass('col-md-10 col-md-offset-1 warn-on-exit')
|
||||
->method($method)
|
||||
->rules([]) !!}
|
||||
|
||||
@if ($$LOWER_NAME$)
|
||||
{!! Former::populate($$LOWER_NAME$) !!}
|
||||
<div style="display:none">
|
||||
{!! Former::text('public_id') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
$FORM_FIELDS$
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<center class="buttons">
|
||||
|
||||
{!! Button::normal(trans('texts.cancel'))
|
||||
->large()
|
||||
->asLinkTo(URL::to('/$LOWER_NAME$'))
|
||||
->appendIcon(Icon::create('remove-circle')) !!}
|
||||
|
||||
{!! Button::success(trans('texts.save'))
|
||||
->submit()
|
||||
->large()
|
||||
->appendIcon(Icon::create('floppy-disk')) !!}
|
||||
|
||||
</center>
|
||||
|
||||
{!! Former::close() !!}
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$(function() {
|
||||
$(".warn-on-exit input").first().focus();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@stop
|
12
app/Console/Commands/stubs/views/master.stub
Executable file
12
app/Console/Commands/stubs/views/master.stub
Executable file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Module $STUDLY_NAME$</title>
|
||||
</head>
|
||||
<body>
|
||||
@yield('content')
|
||||
</body>
|
||||
</html>
|
@ -23,6 +23,8 @@ class Kernel extends ConsoleKernel
|
||||
'App\Console\Commands\SendReminders',
|
||||
'App\Console\Commands\GenerateResources',
|
||||
'App\Console\Commands\TestOFX',
|
||||
'App\Console\Commands\MakeModule',
|
||||
'App\Console\Commands\MakeClass',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ class AccountApiController extends BaseAPIController
|
||||
$updatedAt = $request->updated_at ? date('Y-m-d H:i:s', $request->updated_at) : false;
|
||||
|
||||
$transformer = new AccountTransformer(null, $request->serializer);
|
||||
$account->load($transformer->getDefaultIncludes());
|
||||
$account->load(array_merge($transformer->getDefaultIncludes(), ['projects.client']));
|
||||
$account = $this->createItem($account, $transformer, 'account');
|
||||
|
||||
return $this->response($account);
|
||||
@ -192,7 +192,7 @@ class AccountApiController extends BaseAPIController
|
||||
$provider = $request->input('provider');
|
||||
|
||||
try {
|
||||
$user = Socialite::driver($provider)->userFromToken($token);
|
||||
$user = Socialite::driver($provider)->stateless()->userFromToken($token);
|
||||
} catch (Exception $exception) {
|
||||
return $this->errorResponse(['message' => $exception->getMessage()], 401);
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ class AccountController extends BaseController
|
||||
|
||||
$days_total = $planDetails['paid']->diff($planDetails['expires'])->days;
|
||||
$percent_used = $days_used / $days_total;
|
||||
$credit = $planDetails['plan_price'] * (1 - $percent_used);
|
||||
$credit = floatval($company->payment->amount) * (1 - $percent_used);
|
||||
}
|
||||
|
||||
if ($newPlan['price'] > $credit) {
|
||||
@ -224,7 +224,9 @@ class AccountController extends BaseController
|
||||
}
|
||||
} else {
|
||||
|
||||
if ($plan != PLAN_FREE) {
|
||||
if ($plan == PLAN_FREE) {
|
||||
$company->discount = 0;
|
||||
} else {
|
||||
$company->plan_term = $term;
|
||||
$company->plan_price = $newPlan['price'];
|
||||
$company->num_users = $numUsers;
|
||||
@ -244,9 +246,26 @@ class AccountController extends BaseController
|
||||
* @param $visible
|
||||
* @return mixed
|
||||
*/
|
||||
public function setTrashVisible($entityType, $visible)
|
||||
public function setEntityFilter($entityType, $filter = '')
|
||||
{
|
||||
Session::put("show_trash:{$entityType}", $visible == 'true');
|
||||
if ($filter == 'true') {
|
||||
$filter = '';
|
||||
}
|
||||
|
||||
// separate state and status filters
|
||||
$filters = explode(',', $filter);
|
||||
$stateFilter = [];
|
||||
$statusFilter = [];
|
||||
foreach ($filters as $filter) {
|
||||
if (in_array($filter, \App\Models\EntityModel::$statuses)) {
|
||||
$stateFilter[] = $filter;
|
||||
} else {
|
||||
$statusFilter[] = $filter;
|
||||
}
|
||||
}
|
||||
|
||||
Session::put("entity_state_filter:{$entityType}", join(',', $stateFilter));
|
||||
Session::put("entity_status_filter:{$entityType}", join(',', $statusFilter));
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@ -720,9 +739,27 @@ class AccountController extends BaseController
|
||||
*/
|
||||
private function saveAccountManagement()
|
||||
{
|
||||
$account = Auth::user()->account;
|
||||
$user = Auth::user();
|
||||
$account = $user->account;
|
||||
$modules = Input::get('modules');
|
||||
|
||||
$user->force_pdfjs = Input::get('force_pdfjs') ? true : false;
|
||||
$user->save();
|
||||
|
||||
$account->live_preview = Input::get('live_preview') ? true : false;
|
||||
|
||||
// Automatically disable live preview when using a large font
|
||||
$fonts = Cache::get('fonts')->filter(function($font) use ($account) {
|
||||
if ($font->google_font) {
|
||||
return false;
|
||||
}
|
||||
return $font->id == $account->header_font_id || $font->id == $account->body_font_id;
|
||||
});
|
||||
if ($account->live_preview && count($fonts)) {
|
||||
$account->live_preview = false;
|
||||
Session::flash('warning', trans('texts.live_preview_disabled'));
|
||||
}
|
||||
|
||||
$account->enabled_modules = $modules ? array_sum($modules) : 0;
|
||||
$account->save();
|
||||
|
||||
@ -880,27 +917,29 @@ class AccountController extends BaseController
|
||||
|
||||
if (Input::get('custom_link') == 'subdomain') {
|
||||
$subdomain = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', substr(strtolower(Input::get('subdomain')), 0, MAX_SUBDOMAIN_LENGTH));
|
||||
$exclude = [
|
||||
'www',
|
||||
'app',
|
||||
'mail',
|
||||
'admin',
|
||||
'blog',
|
||||
'user',
|
||||
'contact',
|
||||
'payment',
|
||||
'payments',
|
||||
'billing',
|
||||
'invoice',
|
||||
'business',
|
||||
'owner',
|
||||
'info',
|
||||
'ninja',
|
||||
'docs',
|
||||
'doc',
|
||||
'documents'
|
||||
];
|
||||
$rules['subdomain'] = "unique:accounts,subdomain,{$user->account_id},id|not_in:" . implode(',', $exclude);
|
||||
if (Utils::isNinja()) {
|
||||
$exclude = [
|
||||
'www',
|
||||
'app',
|
||||
'mail',
|
||||
'admin',
|
||||
'blog',
|
||||
'user',
|
||||
'contact',
|
||||
'payment',
|
||||
'payments',
|
||||
'billing',
|
||||
'invoice',
|
||||
'business',
|
||||
'owner',
|
||||
'info',
|
||||
'ninja',
|
||||
'docs',
|
||||
'doc',
|
||||
'documents'
|
||||
];
|
||||
$rules['subdomain'] = "unique:accounts,subdomain,{$user->account_id},id|not_in:" . implode(',', $exclude);
|
||||
}
|
||||
} else {
|
||||
$iframeURL = preg_replace('/[^a-zA-Z0-9_\-\:\/\.]/', '', substr(strtolower(Input::get('iframe_url')), 0, MAX_IFRAME_URL_LENGTH));
|
||||
$iframeURL = rtrim($iframeURL, '/');
|
||||
@ -1035,19 +1074,6 @@ class AccountController extends BaseController
|
||||
$account->invoice_design_id = Input::get('invoice_design_id');
|
||||
$account->font_size = intval(Input::get('font_size'));
|
||||
$account->page_size = Input::get('page_size');
|
||||
$account->live_preview = Input::get('live_preview') ? true : false;
|
||||
|
||||
// Automatically disable live preview when using a large font
|
||||
$fonts = Cache::get('fonts')->filter(function($font) use ($account) {
|
||||
if ($font->google_font) {
|
||||
return false;
|
||||
}
|
||||
return $font->id == $account->header_font_id || $font->id == $account->body_font_id;
|
||||
});
|
||||
if ($account->live_preview && count($fonts)) {
|
||||
$account->live_preview = false;
|
||||
Session::flash('warning', trans('texts.live_preview_disabled'));
|
||||
}
|
||||
|
||||
$labels = [];
|
||||
foreach (['item', 'description', 'unit_cost', 'quantity', 'line_total', 'terms', 'balance_due', 'partial_due', 'subtotal', 'paid_to_date', 'discount', 'tax'] as $field) {
|
||||
|
@ -411,6 +411,7 @@ class AccountGatewayController extends BaseController
|
||||
'description' => trans('texts.wepay_account_description'),
|
||||
'theme_object' => json_decode(WEPAY_THEME),
|
||||
'callback_uri' => $accountGateway->getWebhookUrl(),
|
||||
'rbits' => $account->present()->rBits,
|
||||
];
|
||||
|
||||
if (WEPAY_ENABLE_CANADA) {
|
||||
|
@ -60,10 +60,7 @@ class AppController extends BaseController
|
||||
$database = Input::get('database');
|
||||
$dbType = 'mysql'; // $database['default'];
|
||||
$database['connections'] = [$dbType => $database['type']];
|
||||
|
||||
$mail = Input::get('mail');
|
||||
$email = $mail['username'];
|
||||
$mail['from']['address'] = $email;
|
||||
|
||||
if ($test == 'mail') {
|
||||
return self::testMail($mail);
|
||||
@ -97,6 +94,7 @@ class AppController extends BaseController
|
||||
$_ENV['MAIL_HOST'] = $mail['host'];
|
||||
$_ENV['MAIL_USERNAME'] = $mail['username'];
|
||||
$_ENV['MAIL_FROM_NAME'] = $mail['from']['name'];
|
||||
$_ENV['MAIL_FROM_ADDRESS'] = $mail['from']['address'];
|
||||
$_ENV['MAIL_PASSWORD'] = $mail['password'];
|
||||
$_ENV['PHANTOMJS_CLOUD_KEY'] = 'a-demo-key-with-low-quota-per-ip-address';
|
||||
$_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
|
||||
@ -173,8 +171,8 @@ class AppController extends BaseController
|
||||
$_ENV['MAIL_HOST'] = $mail['host'];
|
||||
$_ENV['MAIL_USERNAME'] = $mail['username'];
|
||||
$_ENV['MAIL_FROM_NAME'] = $mail['from']['name'];
|
||||
$_ENV['MAIL_FROM_ADDRESS'] = $mail['from']['address'];
|
||||
$_ENV['MAIL_PASSWORD'] = $mail['password'];
|
||||
$_ENV['MAIL_FROM_ADDRESS'] = $mail['username'];
|
||||
$_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
|
||||
$_ENV['MAILGUN_SECRET'] = $mail['mailgun_secret'];
|
||||
}
|
||||
@ -218,7 +216,7 @@ class AppController extends BaseController
|
||||
|
||||
private function testMail($mail)
|
||||
{
|
||||
$email = $mail['username'];
|
||||
$email = $mail['from']['address'];
|
||||
$fromName = $mail['from']['name'];
|
||||
|
||||
foreach ($mail as $key => $val) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php namespace App\Http\Controllers;
|
||||
|
||||
use Utils;
|
||||
use Request;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
|
||||
@ -27,14 +28,20 @@ class BaseController extends Controller
|
||||
if ( ! is_array($ids)) {
|
||||
$ids = [$ids];
|
||||
}
|
||||
|
||||
|
||||
$isDatatable = filter_var(request()->datatable, FILTER_VALIDATE_BOOLEAN);
|
||||
$referer = Request::server('HTTP_REFERER');
|
||||
$entityTypes = Utils::pluralizeEntityType($entityType);
|
||||
|
||||
// when restoring redirect to entity
|
||||
if ($action == 'restore' && count($ids) == 1) {
|
||||
return redirect("{$entityTypes}/" . $ids[0]);
|
||||
// when viewing from a datatable list
|
||||
} elseif (strpos($referer, '/clients/')) {
|
||||
return redirect($referer);
|
||||
} elseif ($isDatatable || ($action == 'archive' || $action == 'delete')) {
|
||||
return redirect("{$entityTypes}");
|
||||
// when viewing individual entity
|
||||
} elseif (count($ids)) {
|
||||
return redirect("{$entityTypes}/" . $ids[0]);
|
||||
} else {
|
||||
|
88
app/Http/Controllers/BlueVineController.php
Normal file
88
app/Http/Controllers/BlueVineController.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use URL;
|
||||
use Session;
|
||||
|
||||
class BlueVineController extends BaseController {
|
||||
public function signup() {
|
||||
$user = Auth::user();
|
||||
|
||||
$data = array(
|
||||
'personal_user_full_name' => Input::get( 'name' ),
|
||||
'business_phone_number' => Input::get( 'phone' ),
|
||||
'email' => Input::get( 'email' ),
|
||||
'personal_fico_score' => intval( Input::get( 'fico_score' ) ),
|
||||
'business_annual_revenue' => intval( Input::get( 'annual_revenue' ) ),
|
||||
'business_monthly_average_bank_balance' => intval( Input::get( 'average_bank_balance' ) ),
|
||||
'business_inception_date' => date( 'Y-m-d', strtotime( Input::get( 'business_inception' ) ) ),
|
||||
'partner_internal_business_id' => 'ninja_account_' . $user->account_id,
|
||||
);
|
||||
|
||||
if ( ! empty( Input::get( 'quote_type_factoring' ) ) ) {
|
||||
$data['invoice_factoring_offer'] = true;
|
||||
$data['desired_credit_line'] = intval( Input::get( 'desired_credit_limit' )['invoice_factoring'] );
|
||||
}
|
||||
|
||||
if ( ! empty( Input::get( 'quote_type_loc' ) ) ) {
|
||||
$data['line_of_credit_offer'] = true;
|
||||
$data['desired_credit_line_for_loc'] = intval( Input::get( 'desired_credit_limit' )['line_of_credit'] );
|
||||
}
|
||||
|
||||
|
||||
$api_client = new \GuzzleHttp\Client();
|
||||
try {
|
||||
$response = $api_client->request( 'POST',
|
||||
'https://app.bluevine.com/api/v1/user/register_external?' . http_build_query( array(
|
||||
'external_register_token' => env( 'BLUEVINE_PARTNER_TOKEN' ),
|
||||
'c' => env( 'BLUEVINE_PARTNER_UNIQUE_ID' ),
|
||||
'signup_parent_url' => URL::to( '/bluevine/completed' ),
|
||||
) ), array(
|
||||
'json' => $data
|
||||
)
|
||||
);
|
||||
} catch ( \GuzzleHttp\Exception\RequestException $ex ) {
|
||||
if ( $ex->getCode() == 403 ) {
|
||||
$response_body = $ex->getResponse()->getBody( true );
|
||||
$response_data = json_decode( $response_body );
|
||||
|
||||
return response()->json( [
|
||||
'error' => true,
|
||||
'message' => $response_data->reason
|
||||
] );
|
||||
} else {
|
||||
return response()->json( [
|
||||
'error' => true
|
||||
] );
|
||||
}
|
||||
}
|
||||
|
||||
$user->account->bluevine_status = 'signed_up';
|
||||
$user->account->save();
|
||||
|
||||
$quote_data = json_decode( $response->getBody() );
|
||||
|
||||
return response()->json( $quote_data );
|
||||
}
|
||||
|
||||
public function hideMessage() {
|
||||
$user = Auth::user();
|
||||
|
||||
if ( $user ) {
|
||||
$user->account->bluevine_status = 'ignored';
|
||||
$user->account->save();
|
||||
}
|
||||
|
||||
return 'success';
|
||||
}
|
||||
|
||||
public function handleCompleted() {
|
||||
Session::flash( 'message', trans( 'texts.bluevine_completed' ) );
|
||||
|
||||
return Redirect::to( '/dashboard' );
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ use App\Services\ClientService;
|
||||
use App\Http\Requests\ClientRequest;
|
||||
use App\Http\Requests\CreateClientRequest;
|
||||
use App\Http\Requests\UpdateClientRequest;
|
||||
use App\Ninja\Datatables\ClientDatatable;
|
||||
|
||||
class ClientController extends BaseController
|
||||
{
|
||||
@ -41,20 +42,11 @@ class ClientController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_CLIENT,
|
||||
'datatable' => new ClientDatatable(),
|
||||
'title' => trans('texts.clients'),
|
||||
'sortCol' => '4',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'client',
|
||||
'contact',
|
||||
'email',
|
||||
'date_created',
|
||||
'last_login',
|
||||
'balance',
|
||||
''
|
||||
]),
|
||||
'statuses' => Client::getStatuses(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -123,9 +115,9 @@ class ClientController extends BaseController
|
||||
'client' => $client,
|
||||
'credit' => $client->getTotalCredit(),
|
||||
'title' => trans('texts.view_client'),
|
||||
'hasRecurringInvoices' => Invoice::scope()->where('is_recurring', '=', true)->whereClientId($client->id)->count() > 0,
|
||||
'hasQuotes' => Invoice::scope()->invoiceType(INVOICE_TYPE_QUOTE)->whereClientId($client->id)->count() > 0,
|
||||
'hasTasks' => Task::scope()->whereClientId($client->id)->count() > 0,
|
||||
'hasRecurringInvoices' => Invoice::scope()->recurring()->withArchived()->whereClientId($client->id)->count() > 0,
|
||||
'hasQuotes' => Invoice::scope()->quotes()->withArchived()->whereClientId($client->id)->count() > 0,
|
||||
'hasTasks' => Task::scope()->withArchived()->whereClientId($client->id)->count() > 0,
|
||||
'gatewayLink' => $token ? $token->gatewayLink() : false,
|
||||
'gatewayName' => $token ? $token->gatewayName() : false,
|
||||
];
|
||||
|
@ -203,7 +203,7 @@ class ClientPortalController extends BaseController
|
||||
if (!$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
$invitation->signature_base64 = Input::get('signature');
|
||||
$invitation->signature_date = date_create();
|
||||
$invitation->save();
|
||||
|
@ -7,10 +7,13 @@ use URL;
|
||||
use Utils;
|
||||
use View;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Services\CreditService;
|
||||
use App\Ninja\Repositories\CreditRepository;
|
||||
use App\Http\Requests\UpdateCreditRequest;
|
||||
use App\Http\Requests\CreateCreditRequest;
|
||||
use App\Http\Requests\CreditRequest;
|
||||
use App\Ninja\Datatables\CreditDatatable;
|
||||
|
||||
class CreditController extends BaseController
|
||||
{
|
||||
@ -33,19 +36,10 @@ class CreditController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_CREDIT,
|
||||
'datatable' => new CreditDatatable(),
|
||||
'title' => trans('texts.credits'),
|
||||
'sortCol' => '4',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'client',
|
||||
'credit_amount',
|
||||
'credit_balance',
|
||||
'credit_date',
|
||||
'private_notes',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -62,40 +56,53 @@ class CreditController extends BaseController
|
||||
'method' => 'POST',
|
||||
'url' => 'credits',
|
||||
'title' => trans('texts.new_credit'),
|
||||
'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();
|
||||
$credit = Credit::withTrashed()->scope($publicId)->firstOrFail();
|
||||
|
||||
$this->authorize('edit', $credit);
|
||||
|
||||
$credit->credit_date = Utils::fromSqlDate($credit->credit_date);
|
||||
|
||||
$data = array(
|
||||
'client' => null,
|
||||
'client' => $credit->client,
|
||||
'clientPublicId' => $credit->client->public_id,
|
||||
'credit' => $credit,
|
||||
'method' => 'PUT',
|
||||
'url' => 'credits/'.$publicId,
|
||||
'title' => 'Edit Credit',
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), );
|
||||
'clients' => null,
|
||||
);
|
||||
|
||||
return View::make('credit.edit', $data);
|
||||
return View::make('credits.edit', $data);
|
||||
}
|
||||
|
||||
public function update(UpdateCreditRequest $request)
|
||||
{
|
||||
$credit = $request->entity();
|
||||
|
||||
return $this->save($credit);
|
||||
}
|
||||
*/
|
||||
|
||||
public function store(CreateCreditRequest $request)
|
||||
{
|
||||
$credit = $this->creditRepo->save($request->input());
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
Session::flash('message', trans('texts.created_credit'));
|
||||
private function save($credit = null)
|
||||
{
|
||||
$credit = $this->creditService->save(Input::all(), $credit);
|
||||
|
||||
return redirect()->to($credit->client->getRoute());
|
||||
$message = $credit->wasRecentlyCreated ? trans('texts.created_credit') : trans('texts.updated_credit');
|
||||
Session::flash('message', $message);
|
||||
|
||||
return redirect()->to("clients/{$credit->client->public_id}#credits");
|
||||
}
|
||||
|
||||
public function bulk()
|
||||
@ -109,6 +116,6 @@ class CreditController extends BaseController
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return Redirect::to('credits');
|
||||
return $this->returnBulk(ENTITY_CREDIT, $action, $ids);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class DashboardController extends BaseController
|
||||
$metrics = $dashboardRepo->totals($accountId, $userId, $viewAll);
|
||||
$paidToDate = $dashboardRepo->paidToDate($account, $userId, $viewAll);
|
||||
$averageInvoice = $dashboardRepo->averages($account, $userId, $viewAll);
|
||||
$balances = $dashboardRepo->balances($accountId, $userId, $viewAll);
|
||||
$balances = $dashboardRepo->balances($accountId, $userId, $viewAll);
|
||||
$activities = $dashboardRepo->activities($accountId, $userId, $viewAll);
|
||||
$pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll);
|
||||
$upcoming = $dashboardRepo->upcoming($accountId, $userId, $viewAll);
|
||||
@ -43,6 +43,10 @@ class DashboardController extends BaseController
|
||||
$expenses = $dashboardRepo->expenses($accountId, $userId, $viewAll);
|
||||
$tasks = $dashboardRepo->tasks($accountId, $userId, $viewAll);
|
||||
|
||||
$showBlueVinePromo = ! $account->bluevine_status
|
||||
&& env('BLUEVINE_PARTNER_UNIQUE_ID')
|
||||
&& $account->created_at <= date( 'Y-m-d', strtotime( '-1 month' ));
|
||||
|
||||
// check if the account has quotes
|
||||
$hasQuotes = false;
|
||||
foreach ([$upcoming, $pastDue] as $data) {
|
||||
@ -75,6 +79,7 @@ class DashboardController extends BaseController
|
||||
|
||||
$data = [
|
||||
'account' => $user->account,
|
||||
'user' => $user,
|
||||
'paidToDate' => $paidToDate,
|
||||
'balances' => $balances,
|
||||
'averageInvoice' => $averageInvoice,
|
||||
@ -90,8 +95,29 @@ class DashboardController extends BaseController
|
||||
'currencies' => $currencies,
|
||||
'expenses' => $expenses,
|
||||
'tasks' => $tasks,
|
||||
'showBlueVinePromo' => $showBlueVinePromo,
|
||||
];
|
||||
|
||||
if ($showBlueVinePromo) {
|
||||
$usdLast12Months = 0;
|
||||
$pastYear = date( 'Y-m-d', strtotime( '-1 year' ));
|
||||
$paidLast12Months = $dashboardRepo->paidToDate( $account, $userId, $viewAll, $pastYear );
|
||||
|
||||
foreach ( $paidLast12Months as $item ) {
|
||||
if ( $item->currency_id == null ) {
|
||||
$currency = $user->account->currency_id ?: DEFAULT_CURRENCY;
|
||||
} else {
|
||||
$currency = $item->currency_id;
|
||||
}
|
||||
|
||||
if ( $currency == CURRENCY_DOLLAR ) {
|
||||
$usdLast12Months += $item->value;
|
||||
}
|
||||
}
|
||||
|
||||
$data['usdLast12Months'] = $usdLast12Months;
|
||||
}
|
||||
|
||||
return View::make('dashboard', $data);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ use Input;
|
||||
use Session;
|
||||
use App\Services\ExpenseCategoryService;
|
||||
use App\Ninja\Repositories\ExpenseCategoryRepository;
|
||||
use App\Ninja\Datatables\ExpenseCategoryDatatable;
|
||||
use App\Http\Requests\ExpenseCategoryRequest;
|
||||
use App\Http\Requests\CreateExpenseCategoryRequest;
|
||||
use App\Http\Requests\UpdateExpenseCategoryRequest;
|
||||
@ -29,15 +30,10 @@ class ExpenseCategoryController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_EXPENSE_CATEGORY,
|
||||
'datatable' => new ExpenseCategoryDatatable(),
|
||||
'title' => trans('texts.expense_categories'),
|
||||
'sortCol' => '1',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'name',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -78,7 +74,7 @@ class ExpenseCategoryController extends BaseController
|
||||
|
||||
Session::flash('message', trans('texts.created_expense_category'));
|
||||
|
||||
return redirect()->to($category->getRoute());
|
||||
return redirect()->to('/expense_categories');
|
||||
}
|
||||
|
||||
public function update(UpdateExpenseCategoryRequest $request)
|
||||
|
@ -19,6 +19,7 @@ use App\Ninja\Repositories\ExpenseRepository;
|
||||
use App\Http\Requests\ExpenseRequest;
|
||||
use App\Http\Requests\CreateExpenseRequest;
|
||||
use App\Http\Requests\UpdateExpenseRequest;
|
||||
use App\Ninja\Datatables\ExpenseDatatable;
|
||||
|
||||
class ExpenseController extends BaseController
|
||||
{
|
||||
@ -48,21 +49,10 @@ class ExpenseController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_EXPENSE,
|
||||
'datatable' => new ExpenseDatatable(),
|
||||
'title' => trans('texts.expenses'),
|
||||
'sortCol' => '3',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'vendor',
|
||||
'client',
|
||||
'expense_date',
|
||||
'amount',
|
||||
'category',
|
||||
'public_notes',
|
||||
'status',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -262,7 +252,7 @@ class ExpenseController extends BaseController
|
||||
'countries' => Cache::get('countries'),
|
||||
'customLabel1' => Auth::user()->account->custom_vendor_label1,
|
||||
'customLabel2' => Auth::user()->account->custom_vendor_label2,
|
||||
'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->orderBy('name')->get(),
|
||||
'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(),
|
||||
'taxRates' => TaxRate::scope()->orderBy('name')->get(),
|
||||
];
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ use App\Models\Contact;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Task;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
|
||||
@ -212,6 +214,19 @@ class ExportController extends BaseController
|
||||
->get();
|
||||
}
|
||||
|
||||
if ($request->input('include') === 'all' || $request->input('expenses')) {
|
||||
$data['expenses'] = Expense::scope()
|
||||
->with('user', 'vendor.vendor_contacts', 'client.contacts', 'expense_category')
|
||||
->withArchived()
|
||||
->get();
|
||||
}
|
||||
|
||||
if ($request->input('include') === 'all' || $request->input('products')) {
|
||||
$data['products'] = Product::scope()
|
||||
->withArchived()
|
||||
->get();
|
||||
}
|
||||
|
||||
if ($request->input('include') === 'all' || $request->input('vendors')) {
|
||||
$data['vendors'] = Vendor::scope()
|
||||
->with('user', 'vendor_contacts', 'country')
|
||||
|
@ -38,6 +38,6 @@ class IntegrationController extends Controller
|
||||
return Response::json('Failed to create subscription', 500);
|
||||
}
|
||||
|
||||
return Response::json('{"id":'.$subscription->id.'}', 201);
|
||||
return Response::json(['id' => $subscription->id], 201);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use App\Ninja\Mailers\ContactMailer as Mailer;
|
||||
use App\Ninja\Repositories\InvoiceRepository;
|
||||
use App\Ninja\Repositories\ClientRepository;
|
||||
use App\Ninja\Repositories\DocumentRepository;
|
||||
use App\Ninja\Datatables\InvoiceDatatable;
|
||||
use App\Services\InvoiceService;
|
||||
use App\Services\PaymentService;
|
||||
use App\Services\RecurringInvoiceService;
|
||||
@ -57,21 +58,11 @@ class InvoiceController extends BaseController
|
||||
$data = [
|
||||
'title' => trans('texts.invoices'),
|
||||
'entityType' => ENTITY_INVOICE,
|
||||
'sortCol' => '3',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'invoice_number',
|
||||
'client',
|
||||
'invoice_date',
|
||||
'invoice_total',
|
||||
'balance_due',
|
||||
'due_date',
|
||||
'status',
|
||||
''
|
||||
]),
|
||||
'statuses' => Invoice::getStatuses(),
|
||||
'datatable' => new InvoiceDatatable(),
|
||||
];
|
||||
|
||||
return response()->view('list', $data);
|
||||
return response()->view('list_wrapper', $data);
|
||||
}
|
||||
|
||||
public function getDatatable($clientPublicId = null)
|
||||
@ -108,6 +99,7 @@ class InvoiceController extends BaseController
|
||||
|
||||
if ($clone) {
|
||||
$invoice->id = $invoice->public_id = null;
|
||||
$invoice->is_public = false;
|
||||
$invoice->invoice_number = $account->getNextInvoiceNumber($invoice);
|
||||
$invoice->balance = $invoice->amount;
|
||||
$invoice->invoice_status_id = 0;
|
||||
@ -138,10 +130,6 @@ class InvoiceController extends BaseController
|
||||
DropdownButton::DIVIDER
|
||||
];
|
||||
|
||||
if ($invoice->invoice_status_id < INVOICE_STATUS_SENT && !$invoice->is_recurring) {
|
||||
$actions[] = ['url' => 'javascript:onMarkClick()', 'label' => trans('texts.mark_sent')];
|
||||
}
|
||||
|
||||
if ($entityType == ENTITY_QUOTE) {
|
||||
if ($invoice->quote_invoice_id) {
|
||||
$actions[] = ['url' => URL::to("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')];
|
||||
@ -153,7 +141,8 @@ class InvoiceController extends BaseController
|
||||
$actions[] = ['url' => URL::to("quotes/{$invoice->quote_id}/edit"), 'label' => trans('texts.view_quote')];
|
||||
}
|
||||
|
||||
if (!$invoice->is_recurring && $invoice->balance > 0) {
|
||||
if (!$invoice->is_recurring && $invoice->balance > 0 && $invoice->is_public) {
|
||||
$actions[] = ['url' => 'javascript:submitBulkAction("markPaid")', 'label' => trans('texts.mark_paid')];
|
||||
$actions[] = ['url' => 'javascript:onPaymentClick()', 'label' => trans('texts.enter_payment')];
|
||||
}
|
||||
|
||||
@ -203,7 +192,7 @@ class InvoiceController extends BaseController
|
||||
}
|
||||
|
||||
// Set the invitation data on the client's contacts
|
||||
if (!$clone) {
|
||||
if ($invoice->is_public && ! $clone) {
|
||||
$clients = $data['clients'];
|
||||
foreach ($clients as $client) {
|
||||
if ($client->id != $invoice->client->id) {
|
||||
@ -523,7 +512,13 @@ class InvoiceController extends BaseController
|
||||
$count = $this->invoiceService->bulk($ids, $action);
|
||||
|
||||
if ($count > 0) {
|
||||
$key = $action == 'markSent' ? "updated_{$entityType}" : "{$action}d_{$entityType}";
|
||||
if ($action == 'markSent') {
|
||||
$key = 'marked_sent_invoice';
|
||||
} elseif ($action == 'markPaid') {
|
||||
$key = 'created_payment';
|
||||
} else {
|
||||
$key = "{$action}d_{$entityType}";
|
||||
}
|
||||
$message = Utils::pluralize($key, $count);
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
@ -117,7 +117,8 @@ class OnlinePaymentController extends BaseController
|
||||
} else {
|
||||
Session::flash('message', trans('texts.applied_payment'));
|
||||
}
|
||||
return redirect()->to('view/' . $invitation->invitation_key);
|
||||
|
||||
return $this->completePurchase($invitation);
|
||||
} catch (Exception $exception) {
|
||||
return $this->error($paymentDriver, $exception, true);
|
||||
}
|
||||
@ -152,12 +153,27 @@ class OnlinePaymentController extends BaseController
|
||||
if ($paymentDriver->completeOffsitePurchase(Input::all())) {
|
||||
Session::flash('message', trans('texts.applied_payment'));
|
||||
}
|
||||
return redirect()->to($invitation->getLink());
|
||||
return $this->completePurchase($invitation, true);
|
||||
} catch (Exception $exception) {
|
||||
return $this->error($paymentDriver, $exception);
|
||||
}
|
||||
}
|
||||
|
||||
private function completePurchase($invitation, $isOffsite = false)
|
||||
{
|
||||
if ($redirectUrl = session('redirect_url:' . $invitation->invitation_key)) {
|
||||
$separator = strpos($redirectUrl, '?') === false ? '?' : '&';
|
||||
return redirect()->to($redirectUrl . $separator . 'invoice_id=' . $invitation->invoice->public_id);
|
||||
} else {
|
||||
// Allow redirecting to iFrame for offsite payments
|
||||
if ($isOffsite) {
|
||||
return redirect()->to($invitation->getLink());
|
||||
} else {
|
||||
return redirect()->to('view/' . $invitation->invitation_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $paymentDriver
|
||||
* @param $exception
|
||||
@ -253,17 +269,18 @@ class OnlinePaymentController extends BaseController
|
||||
}
|
||||
|
||||
$account = Account::whereAccountKey(Input::get('account_key'))->first();
|
||||
$redirectUrl = Input::get('redirect_url', URL::previous());
|
||||
$redirectUrl = Input::get('redirect_url');
|
||||
$failureUrl = URL::previous();
|
||||
|
||||
if ( ! $account || ! $account->enable_buy_now_buttons || ! $account->hasFeature(FEATURE_BUY_NOW_BUTTONS)) {
|
||||
return redirect()->to("{$redirectUrl}/?error=invalid account");
|
||||
return redirect()->to("{$failureUrl}/?error=invalid account");
|
||||
}
|
||||
|
||||
Auth::onceUsingId($account->users[0]->id);
|
||||
$product = Product::scope(Input::get('product_id'))->first();
|
||||
|
||||
if ( ! $product) {
|
||||
return redirect()->to("{$redirectUrl}/?error=invalid product");
|
||||
return redirect()->to("{$failureUrl}/?error=invalid product");
|
||||
}
|
||||
|
||||
$rules = [
|
||||
@ -274,7 +291,7 @@ class OnlinePaymentController extends BaseController
|
||||
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
return redirect()->to("{$redirectUrl}/?error=" . $validator->errors()->first());
|
||||
return redirect()->to("{$failureUrl}/?error=" . $validator->errors()->first());
|
||||
}
|
||||
|
||||
$data = [
|
||||
@ -300,6 +317,10 @@ class OnlinePaymentController extends BaseController
|
||||
$invitation = $invoice->invitations[0];
|
||||
$link = $invitation->getLink();
|
||||
|
||||
if ($redirectUrl) {
|
||||
session(['redirect_url:' . $invitation->invitation_key => $redirectUrl]);
|
||||
}
|
||||
|
||||
if ($gatewayTypeAlias) {
|
||||
return redirect()->to($invitation->getLink('payment') . "/{$gatewayTypeAlias}");
|
||||
} else {
|
||||
|
@ -13,6 +13,7 @@ use App\Services\PaymentService;
|
||||
use App\Http\Requests\PaymentRequest;
|
||||
use App\Http\Requests\CreatePaymentRequest;
|
||||
use App\Http\Requests\UpdatePaymentRequest;
|
||||
use App\Ninja\Datatables\PaymentDatatable;
|
||||
|
||||
class PaymentController extends BaseController
|
||||
{
|
||||
@ -59,22 +60,10 @@ class PaymentController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_PAYMENT,
|
||||
'datatable' => new PaymentDatatable(),
|
||||
'title' => trans('texts.payments'),
|
||||
'sortCol' => '7',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'invoice',
|
||||
'client',
|
||||
'transaction_reference',
|
||||
'method',
|
||||
'source',
|
||||
'payment_amount',
|
||||
'payment_date',
|
||||
'status',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -94,8 +83,8 @@ class PaymentController extends BaseController
|
||||
public function create(PaymentRequest $request)
|
||||
{
|
||||
$invoices = Invoice::scope()
|
||||
->invoiceType(INVOICE_TYPE_STANDARD)
|
||||
->where('is_recurring', '=', false)
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->where('invoices.balance', '>', 0)
|
||||
->with('client', 'invoice_status')
|
||||
->orderBy('invoice_number')->get();
|
||||
@ -139,8 +128,11 @@ class PaymentController extends BaseController
|
||||
$data = [
|
||||
'client' => null,
|
||||
'invoice' => null,
|
||||
'invoices' => Invoice::scope()->invoiceType(INVOICE_TYPE_STANDARD)->where('is_recurring', '=', false)
|
||||
->with('client', 'invoice_status')->orderBy('invoice_number')->get(),
|
||||
'invoices' => Invoice::scope()
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->with('client', 'invoice_status')
|
||||
->orderBy('invoice_number')->get(),
|
||||
'payment' => $payment,
|
||||
'entity' => $payment,
|
||||
'method' => 'PUT',
|
||||
@ -172,7 +164,7 @@ class PaymentController extends BaseController
|
||||
Session::flash('message', trans('texts.created_payment'));
|
||||
}
|
||||
|
||||
return redirect()->to($payment->client->getRoute());
|
||||
return redirect()->to($payment->client->getRoute() . '#payments');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,6 +195,6 @@ class PaymentController extends BaseController
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return redirect()->to('payments');
|
||||
return $this->returnBulk(ENTITY_PAYMENT, $action, $ids);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use Redirect;
|
||||
use App\Models\Product;
|
||||
use App\Models\TaxRate;
|
||||
use App\Services\ProductService;
|
||||
use App\Ninja\Datatables\ProductDatatable;
|
||||
|
||||
/**
|
||||
* Class ProductController
|
||||
@ -38,23 +39,11 @@ class ProductController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$columns = [
|
||||
'checkbox',
|
||||
'product',
|
||||
'description',
|
||||
'unit_cost'
|
||||
];
|
||||
|
||||
if (Auth::user()->account->invoice_item_taxes) {
|
||||
$columns[] = 'tax_rate';
|
||||
}
|
||||
$columns[] = 'action';
|
||||
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_PRODUCT,
|
||||
'datatable' => new ProductDatatable(),
|
||||
'title' => trans('texts.products'),
|
||||
'sortCol' => '4',
|
||||
'columns' => Utils::trans($columns),
|
||||
'statuses' => Product::getStatuses(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -166,7 +155,8 @@ class ProductController extends BaseController
|
||||
$ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
|
||||
$count = $this->productService->bulk($ids, $action);
|
||||
|
||||
Session::flash('message', trans('texts.archived_product'));
|
||||
$message = Utils::pluralize($action.'d_product', $count);
|
||||
Session::flash('message', $message);
|
||||
|
||||
return $this->returnBulk(ENTITY_PRODUCT, $action, $ids);
|
||||
}
|
||||
|
113
app/Http/Controllers/ProjectController.php
Normal file
113
app/Http/Controllers/ProjectController.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php namespace App\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use View;
|
||||
use Utils;
|
||||
use Input;
|
||||
use Session;
|
||||
use App\Models\Client;
|
||||
use App\Services\ProjectService;
|
||||
use App\Ninja\Repositories\ProjectRepository;
|
||||
use App\Ninja\Datatables\ProjectDatatable;
|
||||
use App\Http\Requests\ProjectRequest;
|
||||
use App\Http\Requests\CreateProjectRequest;
|
||||
use App\Http\Requests\UpdateProjectRequest;
|
||||
|
||||
class ProjectController extends BaseController
|
||||
{
|
||||
protected $projectRepo;
|
||||
protected $projectService;
|
||||
protected $entityType = ENTITY_PROJECT;
|
||||
|
||||
public function __construct(ProjectRepository $projectRepo, ProjectService $projectService)
|
||||
{
|
||||
$this->projectRepo = $projectRepo;
|
||||
$this->projectService = $projectService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_PROJECT,
|
||||
'datatable' => new ProjectDatatable(),
|
||||
'title' => trans('texts.projects'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getDatatable($expensePublicId = null)
|
||||
{
|
||||
$search = Input::get('sSearch');
|
||||
$userId = Auth::user()->filterId();
|
||||
|
||||
return $this->projectService->getDatatable($search, $userId);
|
||||
}
|
||||
|
||||
public function create(ProjectRequest $request)
|
||||
{
|
||||
$data = [
|
||||
'project' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'projects',
|
||||
'title' => trans('texts.new_project'),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'clientPublicId' => $request->client_id,
|
||||
];
|
||||
|
||||
return View::make('projects.edit', $data);
|
||||
}
|
||||
|
||||
public function edit(ProjectRequest $request)
|
||||
{
|
||||
$project = $request->entity();
|
||||
|
||||
$data = [
|
||||
'project' => $project,
|
||||
'method' => 'PUT',
|
||||
'url' => 'projects/' . $project->public_id,
|
||||
'title' => trans('texts.edit_project'),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'clientPublicId' => $project->client ? $project->client->public_id : null,
|
||||
];
|
||||
|
||||
return View::make('projects.edit', $data);
|
||||
}
|
||||
|
||||
public function store(CreateProjectRequest $request)
|
||||
{
|
||||
$project = $this->projectService->save($request->input());
|
||||
|
||||
Session::flash('message', trans('texts.created_project'));
|
||||
|
||||
return redirect()->to($project->getRoute());
|
||||
}
|
||||
|
||||
public function update(UpdateProjectRequest $request)
|
||||
{
|
||||
$project = $this->projectService->save($request->input(), $request->entity());
|
||||
|
||||
Session::flash('message', trans('texts.updated_project'));
|
||||
|
||||
return redirect()->to($project->getRoute());
|
||||
}
|
||||
|
||||
public function bulk()
|
||||
{
|
||||
$action = Input::get('action');
|
||||
$ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
|
||||
$count = $this->projectService->bulk($ids, $action);
|
||||
|
||||
if ($count > 0) {
|
||||
$field = $count == 1 ? "{$action}d_project" : "{$action}d_projects";
|
||||
$message = trans("texts.$field", ['count' => $count]);
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return redirect()->to('/projects');
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,7 @@ use App\Ninja\Repositories\InvoiceRepository;
|
||||
use App\Ninja\Repositories\ClientRepository;
|
||||
use App\Services\InvoiceService;
|
||||
use App\Http\Requests\InvoiceRequest;
|
||||
use App\Ninja\Datatables\InvoiceDatatable;
|
||||
|
||||
class QuoteController extends BaseController
|
||||
{
|
||||
@ -41,23 +42,16 @@ class QuoteController extends BaseController
|
||||
|
||||
public function index()
|
||||
{
|
||||
$datatable = new InvoiceDatatable();
|
||||
$datatable->entityType = ENTITY_QUOTE;
|
||||
|
||||
$data = [
|
||||
'title' => trans('texts.quotes'),
|
||||
'entityType' => ENTITY_QUOTE,
|
||||
'sortCol' => '3',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'quote_number',
|
||||
'client',
|
||||
'quote_date',
|
||||
'quote_total',
|
||||
'valid_until',
|
||||
'status',
|
||||
'action'
|
||||
]),
|
||||
'datatable' => $datatable,
|
||||
];
|
||||
|
||||
return response()->view('list', $data);
|
||||
return response()->view('list_wrapper', $data);
|
||||
}
|
||||
|
||||
public function getDatatable($clientPublicId = null)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use Utils;
|
||||
use App\Ninja\Repositories\InvoiceRepository;
|
||||
use App\Ninja\Datatables\RecurringInvoiceDatatable;
|
||||
|
||||
/**
|
||||
* Class RecurringInvoiceController
|
||||
@ -32,18 +33,10 @@ class RecurringInvoiceController extends BaseController
|
||||
$data = [
|
||||
'title' => trans('texts.recurring_invoices'),
|
||||
'entityType' => ENTITY_RECURRING_INVOICE,
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'frequency',
|
||||
'client',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'invoice_total',
|
||||
'action'
|
||||
])
|
||||
'datatable' => new RecurringInvoiceDatatable(),
|
||||
];
|
||||
|
||||
return response()->view('list', $data);
|
||||
return response()->view('list_wrapper', $data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\UpdateTaskRequest;
|
||||
use Auth;
|
||||
use Response;
|
||||
use Input;
|
||||
@ -40,6 +41,7 @@ class TaskApiController extends BaseAPIController
|
||||
{
|
||||
$tasks = Task::scope()
|
||||
->withTrashed()
|
||||
->with('client', 'invoice', 'project')
|
||||
->orderBy('created_at', 'desc');
|
||||
|
||||
return $this->listResponse($tasks);
|
||||
@ -84,4 +86,38 @@ class TaskApiController extends BaseAPIController
|
||||
return $this->response($data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @SWG\Put(
|
||||
* path="/task/{task_id}",
|
||||
* tags={"task"},
|
||||
* summary="Update a task",
|
||||
* @SWG\Parameter(
|
||||
* in="body",
|
||||
* name="body",
|
||||
* @SWG\Schema(ref="#/definitions/Task")
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Update task",
|
||||
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Task"))
|
||||
* ),
|
||||
* @SWG\Response(
|
||||
* response="default",
|
||||
* description="an ""unexpected"" error"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
|
||||
public function update(UpdateTaskRequest $request)
|
||||
{
|
||||
$task = $request->entity();
|
||||
|
||||
$task = $this->taskRepo->save($task->public_id, \Illuminate\Support\Facades\Input::all());
|
||||
|
||||
return $this->itemResponse($task);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,12 +10,14 @@ use Session;
|
||||
use DropdownButton;
|
||||
use App\Models\Client;
|
||||
use App\Models\Task;
|
||||
use App\Models\Project;
|
||||
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;
|
||||
use App\Ninja\Datatables\TaskDatatable;
|
||||
|
||||
/**
|
||||
* Class TaskController
|
||||
@ -66,19 +68,10 @@ class TaskController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_TASK,
|
||||
'datatable' => new TaskDatatable(),
|
||||
'title' => trans('texts.tasks'),
|
||||
'sortCol' => '2',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'client',
|
||||
'date',
|
||||
'duration',
|
||||
'description',
|
||||
'status',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -128,6 +121,7 @@ class TaskController extends BaseController
|
||||
$data = [
|
||||
'task' => null,
|
||||
'clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0),
|
||||
'projectPublicId' => Input::old('project_id') ? Input::old('project_id') : ($request->project_id ?: 0),
|
||||
'method' => 'POST',
|
||||
'url' => 'tasks',
|
||||
'title' => trans('texts.new_task'),
|
||||
@ -179,6 +173,7 @@ class TaskController extends BaseController
|
||||
'task' => $task,
|
||||
'entity' => $task,
|
||||
'clientPublicId' => $task->client ? $task->client->public_id : 0,
|
||||
'projectPublicId' => $task->project ? $task->project->public_id : 0,
|
||||
'method' => 'PUT',
|
||||
'url' => 'tasks/'.$task->public_id,
|
||||
'title' => trans('texts.edit_task'),
|
||||
@ -214,6 +209,7 @@ class TaskController extends BaseController
|
||||
return [
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'account' => Auth::user()->account,
|
||||
'projects' => Project::scope()->with('client.contacts')->orderBy('name')->get(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ class UserController extends BaseController
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
|
||||
return Redirect::to('users/' . $user->public_id . '/edit');
|
||||
}
|
||||
|
||||
public function sendConfirmation($userPublicId)
|
||||
|
@ -15,6 +15,7 @@ use App\Services\VendorService;
|
||||
use App\Http\Requests\VendorRequest;
|
||||
use App\Http\Requests\CreateVendorRequest;
|
||||
use App\Http\Requests\UpdateVendorRequest;
|
||||
use App\Ninja\Datatables\VendorDatatable;
|
||||
|
||||
class VendorController extends BaseController
|
||||
{
|
||||
@ -37,19 +38,10 @@ class VendorController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', [
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => 'vendor',
|
||||
'datatable' => new VendorDatatable(),
|
||||
'title' => trans('texts.vendors'),
|
||||
'sortCol' => '4',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'vendor',
|
||||
'city',
|
||||
'phone',
|
||||
'email',
|
||||
'date_created',
|
||||
''
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,6 @@ class VerifyCsrfToken extends BaseVerifier
|
||||
'complete/*',
|
||||
'signup/register',
|
||||
'api/v1/*',
|
||||
'api/v1/login',
|
||||
'api/v1/clients/*',
|
||||
'api/v1/clients',
|
||||
'api/v1/invoices/*',
|
||||
'api/v1/invoices',
|
||||
'api/v1/quotes',
|
||||
'api/v1/payments',
|
||||
'api/v1/tasks',
|
||||
'api/v1/email_invoice',
|
||||
'api/v1/hooks',
|
||||
'api/v1/users',
|
||||
'api/v1/users/*',
|
||||
'hook/email_opened',
|
||||
'hook/email_bounced',
|
||||
'reseller_stats',
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
use App\Models\Invoice;
|
||||
|
||||
|
||||
|
||||
class CreatePaymentAPIRequest extends PaymentRequest
|
||||
{
|
||||
/**
|
||||
@ -9,6 +11,9 @@ class CreatePaymentAPIRequest extends PaymentRequest
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('create', ENTITY_PAYMENT);
|
||||
@ -30,6 +35,7 @@ class CreatePaymentAPIRequest extends PaymentRequest
|
||||
|
||||
$invoice = Invoice::scope($this->invoice_id)
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->firstOrFail();
|
||||
|
||||
$this->merge([
|
||||
@ -47,4 +53,7 @@ class CreatePaymentAPIRequest extends PaymentRequest
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ class CreatePaymentRequest extends PaymentRequest
|
||||
$input = $this->input();
|
||||
$invoice = Invoice::scope($input['invoice'])
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->firstOrFail();
|
||||
|
||||
$rules = [
|
||||
|
27
app/Http/Requests/CreateProjectRequest.php
Normal file
27
app/Http/Requests/CreateProjectRequest.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
class CreateProjectRequest extends ProjectRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('create', ENTITY_PROJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => sprintf('required|unique:projects,name,,id,account_id,%s', $this->user()->account_id),
|
||||
'client_id' => 'required',
|
||||
];
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
use Input;
|
||||
use Utils;
|
||||
use App\Libraries\HistoryUtils;
|
||||
use App\Models\EntityModel;
|
||||
|
||||
class EntityRequest extends Request {
|
||||
|
||||
@ -34,13 +35,13 @@ class EntityRequest extends Request {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = Utils::getEntityClass($this->entityType);
|
||||
$class = EntityModel::getClassName($this->entityType);
|
||||
|
||||
if (method_exists($class, 'trashed')) {
|
||||
$this->entity = $class::scope($publicId)->withTrashed()->firstOrFail();
|
||||
} else {
|
||||
$this->entity = $class::scope($publicId)->firstOrFail();
|
||||
}
|
||||
if (method_exists($class, 'trashed')) {
|
||||
$this->entity = $class::scope($publicId)->withTrashed()->firstOrFail();
|
||||
} else {
|
||||
$this->entity = $class::scope($publicId)->firstOrFail();
|
||||
}
|
||||
|
||||
return $this->entity;
|
||||
}
|
||||
|
7
app/Http/Requests/ProjectRequest.php
Normal file
7
app/Http/Requests/ProjectRequest.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
class ProjectRequest extends EntityRequest {
|
||||
|
||||
protected $entityType = ENTITY_PROJECT;
|
||||
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Request as InputRequest;
|
||||
use Response;
|
||||
use App\Libraries\Utils;
|
||||
|
||||
// https://laracasts.com/discuss/channels/general-discussion/laravel-5-modify-input-before-validation/replies/34366
|
||||
abstract class Request extends FormRequest {
|
||||
@ -8,6 +11,11 @@ abstract class Request extends FormRequest {
|
||||
// populate in subclass to auto load record
|
||||
protected $autoload = [];
|
||||
|
||||
public function __construct(InputRequest $req)
|
||||
{
|
||||
$this->req = $req;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the input.
|
||||
*
|
||||
@ -48,4 +56,23 @@ abstract class Request extends FormRequest {
|
||||
|
||||
return $this->all();
|
||||
}
|
||||
|
||||
public function response(array $errors)
|
||||
{
|
||||
/* If the user is not validating from a mobile app - pass through parent::response */
|
||||
if(!isset($this->req->api_secret))
|
||||
return parent::response($errors);
|
||||
|
||||
/* If the user is validating from a mobile app - pass through first error string and return error */
|
||||
foreach($errors as $error) {
|
||||
foreach ($error as $key => $value) {
|
||||
|
||||
$message['error'] = ['message'=>$value];
|
||||
$message = json_encode($message, JSON_PRETTY_PRINT);
|
||||
$headers = Utils::getApiHeaders();
|
||||
|
||||
return Response::make($message, 400, $headers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
app/Http/Requests/UpdateCreditRequest.php
Normal file
26
app/Http/Requests/UpdateCreditRequest.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
class UpdateCreditRequest extends CreditRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('edit', $this->entity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'amount' => 'required|positive',
|
||||
];
|
||||
}
|
||||
}
|
26
app/Http/Requests/UpdateProjectRequest.php
Normal file
26
app/Http/Requests/UpdateProjectRequest.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
|
||||
class UpdateProjectRequest extends ProjectRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('edit', $this->entity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => sprintf('required|unique:projects,name,%s,id,account_id,%s', $this->entity()->id, $this->user()->account_id),
|
||||
];
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ class ClientPortalHeaderComposer
|
||||
->join('documents', 'documents.invoice_id', '=', 'invoices.id')
|
||||
->count();
|
||||
|
||||
$view->with('hasQuotes', $client->quotes->count());
|
||||
$view->with('hasQuotes', $client->publicQuotes->count());
|
||||
$view->with('hasCredits', $client->creditsWithBalance->count());
|
||||
$view->with('hasDocuments', $hasDocuments);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ if (Utils::isReseller()) {
|
||||
Route::group(['middleware' => 'auth:user'], function() {
|
||||
Route::get('dashboard', 'DashboardController@index');
|
||||
Route::get('dashboard_chart_data/{group_by}/{start_date}/{end_date}/{currency_id}/{include_expenses}', 'DashboardController@chartData');
|
||||
Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible');
|
||||
Route::get('set_entity_filter/{entity_type}/{filter?}', 'AccountController@setEntityFilter');
|
||||
Route::get('hide_message', 'HomeController@hideMessage');
|
||||
Route::get('force_inline_pdf', 'UserController@forcePDFJS');
|
||||
Route::get('account/get_search_data', ['as' => 'get_search_data', 'uses' => 'AccountController@getSearchData']);
|
||||
@ -138,22 +138,29 @@ Route::group(['middleware' => 'auth:user'], function() {
|
||||
Route::post('users/change_password', 'UserController@changePassword');
|
||||
|
||||
Route::resource('clients', 'ClientController');
|
||||
Route::get('api/clients', ['as'=>'api.clients', 'uses'=>'ClientController@getDatatable']);
|
||||
Route::get('api/activities/{client_id?}', ['as'=>'api.activities', 'uses'=>'ActivityController@getDatatable']);
|
||||
Route::get('api/clients', 'ClientController@getDatatable');
|
||||
Route::get('api/activities/{client_id?}', 'ActivityController@getDatatable');
|
||||
Route::post('clients/bulk', 'ClientController@bulk');
|
||||
|
||||
Route::resource('tasks', 'TaskController');
|
||||
Route::get('api/tasks/{client_id?}', ['as'=>'api.tasks', 'uses'=>'TaskController@getDatatable']);
|
||||
Route::get('api/tasks/{client_id?}', 'TaskController@getDatatable');
|
||||
Route::get('tasks/create/{client_id?}', 'TaskController@create');
|
||||
Route::post('tasks/bulk', 'TaskController@bulk');
|
||||
Route::get('projects', 'ProjectController@index');
|
||||
Route::get('api/projects', 'ProjectController@getDatatable');
|
||||
Route::get('projects/create/{client_id?}', 'ProjectController@create');
|
||||
Route::post('projects', 'ProjectController@store');
|
||||
Route::put('projects/{projects}', 'ProjectController@update');
|
||||
Route::get('projects/{projects}/edit', 'ProjectController@edit');
|
||||
Route::post('projects/bulk', 'ProjectController@bulk');
|
||||
|
||||
Route::get('api/recurring_invoices/{client_id?}', ['as'=>'api.recurring_invoices', 'uses'=>'InvoiceController@getRecurringDatatable']);
|
||||
Route::get('api/recurring_invoices/{client_id?}', 'InvoiceController@getRecurringDatatable');
|
||||
|
||||
Route::get('invoices/invoice_history/{invoice_id}', 'InvoiceController@invoiceHistory');
|
||||
Route::get('quotes/quote_history/{invoice_id}', 'InvoiceController@invoiceHistory');
|
||||
|
||||
Route::resource('invoices', 'InvoiceController');
|
||||
Route::get('api/invoices/{client_id?}', ['as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable']);
|
||||
Route::get('api/invoices/{client_id?}', 'InvoiceController@getDatatable');
|
||||
Route::get('invoices/create/{client_id?}', 'InvoiceController@create');
|
||||
Route::get('recurring_invoices/create/{client_id?}', 'InvoiceController@createRecurring');
|
||||
Route::get('recurring_invoices', 'RecurringInvoiceController@index');
|
||||
@ -175,20 +182,20 @@ Route::group(['middleware' => 'auth:user'], function() {
|
||||
Route::get('quotes/{invoices}', 'InvoiceController@edit');
|
||||
Route::post('quotes', 'InvoiceController@store');
|
||||
Route::get('quotes', 'QuoteController@index');
|
||||
Route::get('api/quotes/{client_id?}', ['as'=>'api.quotes', 'uses'=>'QuoteController@getDatatable']);
|
||||
Route::get('api/quotes/{client_id?}', 'QuoteController@getDatatable');
|
||||
Route::post('quotes/bulk', 'QuoteController@bulk');
|
||||
|
||||
Route::resource('payments', 'PaymentController');
|
||||
Route::get('payments/create/{client_id?}/{invoice_id?}', 'PaymentController@create');
|
||||
Route::get('api/payments/{client_id?}', ['as'=>'api.payments', 'uses'=>'PaymentController@getDatatable']);
|
||||
Route::get('api/payments/{client_id?}', 'PaymentController@getDatatable');
|
||||
Route::post('payments/bulk', 'PaymentController@bulk');
|
||||
|
||||
Route::resource('credits', 'CreditController');
|
||||
Route::get('credits/create/{client_id?}/{invoice_id?}', 'CreditController@create');
|
||||
Route::get('api/credits/{client_id?}', ['as'=>'api.credits', 'uses'=>'CreditController@getDatatable']);
|
||||
Route::get('api/credits/{client_id?}', 'CreditController@getDatatable');
|
||||
Route::post('credits/bulk', 'CreditController@bulk');
|
||||
|
||||
Route::get('api/products', ['as'=>'api.products', 'uses'=>'ProductController@getDatatable']);
|
||||
Route::get('api/products', 'ProductController@getDatatable');
|
||||
Route::resource('products', 'ProductController');
|
||||
Route::post('products/bulk', 'ProductController@bulk');
|
||||
|
||||
@ -199,29 +206,34 @@ Route::group(['middleware' => 'auth:user'], function() {
|
||||
|
||||
// vendor
|
||||
Route::resource('vendors', 'VendorController');
|
||||
Route::get('api/vendor', ['as'=>'api.vendors', 'uses'=>'VendorController@getDatatable']);
|
||||
Route::get('api/vendors', 'VendorController@getDatatable');
|
||||
Route::post('vendors/bulk', 'VendorController@bulk');
|
||||
|
||||
// Expense
|
||||
Route::resource('expenses', 'ExpenseController');
|
||||
Route::get('expenses/create/{vendor_id?}/{client_id?}', 'ExpenseController@create');
|
||||
Route::get('api/expense', ['as'=>'api.expenses', 'uses'=>'ExpenseController@getDatatable']);
|
||||
Route::get('api/vendor_expense/{id}', ['as'=>'api.expense', 'uses'=>'ExpenseController@getDatatableVendor']);
|
||||
Route::get('api/expenses', 'ExpenseController@getDatatable');
|
||||
Route::get('api/expenses/{id}', 'ExpenseController@getDatatableVendor');
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk');
|
||||
Route::get('expense_categories', 'ExpenseCategoryController@index');
|
||||
Route::get('api/expense_categories', ['as'=>'api.expense_categories', 'uses'=>'ExpenseCategoryController@getDatatable']);
|
||||
Route::get('api/expense_categories', 'ExpenseCategoryController@getDatatable');
|
||||
Route::get('expense_categories/create', 'ExpenseCategoryController@create');
|
||||
Route::post('expense_categories', 'ExpenseCategoryController@store');
|
||||
Route::put('expense_categories/{expense_categories}', 'ExpenseCategoryController@update');
|
||||
Route::get('expense_categories/{expense_categories}/edit', 'ExpenseCategoryController@edit');
|
||||
Route::post('expense_categories/bulk', 'ExpenseCategoryController@bulk');
|
||||
|
||||
// BlueVine
|
||||
Route::post('bluevine/signup', 'BlueVineController@signup');
|
||||
Route::get('bluevine/hide_message', 'BlueVineController@hideMessage');
|
||||
Route::get('bluevine/completed', 'BlueVineController@handleCompleted');
|
||||
});
|
||||
|
||||
Route::group([
|
||||
'middleware' => ['auth:user', 'permissions.required'],
|
||||
'permissions' => 'admin',
|
||||
], function() {
|
||||
Route::get('api/users', ['as'=>'api.users', 'uses'=>'UserController@getDatatable']);
|
||||
Route::get('api/users', 'UserController@getDatatable');
|
||||
Route::resource('users', 'UserController');
|
||||
Route::post('users/bulk', 'UserController@bulk');
|
||||
Route::get('send_confirmation/{user_id}', 'UserController@sendConfirmation');
|
||||
@ -231,11 +243,11 @@ Route::group([
|
||||
Route::get('/unlink_account/{user_account_id}/{user_id}', 'UserController@unlinkAccount');
|
||||
Route::get('/manage_companies', 'UserController@manageCompanies');
|
||||
|
||||
Route::get('api/tokens', ['as'=>'api.tokens', 'uses'=>'TokenController@getDatatable']);
|
||||
Route::get('api/tokens', 'TokenController@getDatatable');
|
||||
Route::resource('tokens', 'TokenController');
|
||||
Route::post('tokens/bulk', 'TokenController@bulk');
|
||||
|
||||
Route::get('api/tax_rates', ['as'=>'api.tax_rates', 'uses'=>'TaxRateController@getDatatable']);
|
||||
Route::get('api/tax_rates', 'TaxRateController@getDatatable');
|
||||
Route::resource('tax_rates', 'TaxRateController');
|
||||
Route::post('tax_rates/bulk', 'TaxRateController@bulk');
|
||||
|
||||
@ -260,13 +272,13 @@ Route::group([
|
||||
Route::get('gateways/create/{show_wepay?}', 'AccountGatewayController@create');
|
||||
Route::resource('gateways', 'AccountGatewayController');
|
||||
Route::get('gateways/{public_id}/resend_confirmation', 'AccountGatewayController@resendConfirmation');
|
||||
Route::get('api/gateways', ['as'=>'api.gateways', 'uses'=>'AccountGatewayController@getDatatable']);
|
||||
Route::get('api/gateways', 'AccountGatewayController@getDatatable');
|
||||
Route::post('account_gateways/bulk', 'AccountGatewayController@bulk');
|
||||
|
||||
Route::get('bank_accounts/import_ofx', 'BankAccountController@showImportOFX');
|
||||
Route::post('bank_accounts/import_ofx', 'BankAccountController@doImportOFX');
|
||||
Route::resource('bank_accounts', 'BankAccountController');
|
||||
Route::get('api/bank_accounts', ['as'=>'api.bank_accounts', 'uses'=>'BankAccountController@getDatatable']);
|
||||
Route::get('api/bank_accounts', 'BankAccountController@getDatatable');
|
||||
Route::post('bank_accounts/bulk', 'BankAccountController@bulk');
|
||||
Route::post('bank_accounts/validate', 'BankAccountController@validateAccount');
|
||||
Route::post('bank_accounts/import_expenses/{bank_id}', 'BankAccountController@importExpenses');
|
||||
@ -294,7 +306,6 @@ Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function()
|
||||
Route::get('invoices', 'InvoiceApiController@index');
|
||||
Route::get('download/{invoice_id}', 'InvoiceApiController@download');
|
||||
Route::resource('invoices', 'InvoiceApiController');
|
||||
Route::get('payments', 'PaymentApiController@index');
|
||||
Route::resource('payments', 'PaymentApiController');
|
||||
Route::get('tasks', 'TaskApiController@index');
|
||||
Route::resource('tasks', 'TaskApiController');
|
||||
@ -349,9 +360,9 @@ Route::get('/comments/feed', function() {
|
||||
});
|
||||
|
||||
if (!defined('CONTACT_EMAIL')) {
|
||||
define('CONTACT_EMAIL', Config::get('mail.from.address'));
|
||||
define('CONTACT_NAME', Config::get('mail.from.name'));
|
||||
define('SITE_URL', Config::get('app.url'));
|
||||
define('CONTACT_EMAIL', config('mail.from.address'));
|
||||
define('CONTACT_NAME', config('mail.from.name'));
|
||||
define('SITE_URL', config('app.url'));
|
||||
|
||||
define('ENV_DEVELOPMENT', 'local');
|
||||
define('ENV_STAGING', 'staging');
|
||||
@ -383,6 +394,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('ENTITY_BANK_ACCOUNT', 'bank_account');
|
||||
define('ENTITY_BANK_SUBACCOUNT', 'bank_subaccount');
|
||||
define('ENTITY_EXPENSE_CATEGORY', 'expense_category');
|
||||
define('ENTITY_PROJECT', 'project');
|
||||
|
||||
define('INVOICE_TYPE_STANDARD', 1);
|
||||
define('INVOICE_TYPE_QUOTE', 2);
|
||||
@ -516,12 +528,17 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('MAX_NUM_VENDORS', 100);
|
||||
define('MAX_NUM_VENDORS_PRO', 20000);
|
||||
|
||||
define('STATUS_ACTIVE', 'active');
|
||||
define('STATUS_ARCHIVED', 'archived');
|
||||
define('STATUS_DELETED', 'deleted');
|
||||
|
||||
define('INVOICE_STATUS_DRAFT', 1);
|
||||
define('INVOICE_STATUS_SENT', 2);
|
||||
define('INVOICE_STATUS_VIEWED', 3);
|
||||
define('INVOICE_STATUS_APPROVED', 4);
|
||||
define('INVOICE_STATUS_PARTIAL', 5);
|
||||
define('INVOICE_STATUS_PAID', 6);
|
||||
define('INVOICE_STATUS_OVERDUE', 7);
|
||||
|
||||
define('PAYMENT_STATUS_PENDING', 1);
|
||||
define('PAYMENT_STATUS_VOIDED', 2);
|
||||
@ -530,6 +547,15 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('PAYMENT_STATUS_PARTIALLY_REFUNDED', 5);
|
||||
define('PAYMENT_STATUS_REFUNDED', 6);
|
||||
|
||||
define('TASK_STATUS_LOGGED', 1);
|
||||
define('TASK_STATUS_RUNNING', 2);
|
||||
define('TASK_STATUS_INVOICED', 3);
|
||||
define('TASK_STATUS_PAID', 4);
|
||||
|
||||
define('EXPENSE_STATUS_LOGGED', 1);
|
||||
define('EXPENSE_STATUS_INVOICED', 2);
|
||||
define('EXPENSE_STATUS_PAID', 3);
|
||||
|
||||
define('CUSTOM_DESIGN', 11);
|
||||
|
||||
define('FREQUENCY_WEEKLY', 1);
|
||||
@ -619,12 +645,14 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
|
||||
define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
|
||||
define('NINJA_DATE', '2000-01-01');
|
||||
define('NINJA_VERSION', '2.8.2' . env('NINJA_VERSION_SUFFIX'));
|
||||
define('NINJA_VERSION', '2.9.0' . env('NINJA_VERSION_SUFFIX'));
|
||||
|
||||
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_FORUM_URL', env('NINJA_FORUM_URL', 'https://www.invoiceninja.com/forums/forum/support/'));
|
||||
define('NINJA_CONTACT_URL', env('NINJA_CONTACT_URL', 'https://www.invoiceninja.com/contact/'));
|
||||
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'));
|
||||
@ -637,6 +665,8 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'));
|
||||
define('GOOGLE_ANALYITCS_URL', env('GOOGLE_ANALYITCS_URL', 'https://www.google-analytics.com/collect'));
|
||||
define('TRANSIFEX_URL', env('TRANSIFEX_URL', 'https://www.transifex.com/invoice-ninja/invoice-ninja'));
|
||||
define('CHROME_PDF_HELP_URL', 'https://support.google.com/chrome/answer/6213030?hl=en');
|
||||
define('FIREFOX_PDF_HELP_URL', 'https://support.mozilla.org/en-US/kb/view-pdf-files-firefox');
|
||||
|
||||
define('MSBOT_LOGIN_URL', 'https://login.microsoftonline.com/common/oauth2/v2.0/token');
|
||||
define('MSBOT_LUIS_URL', 'https://api.projectoxford.ai/luis/v1/application');
|
||||
@ -879,8 +909,23 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
return $string != $english ? $string : '';
|
||||
}
|
||||
}
|
||||
|
||||
// include modules in translations
|
||||
function mtrans($entityType, $text = false)
|
||||
{
|
||||
if ( ! $text) {
|
||||
$text = $entityType;
|
||||
}
|
||||
|
||||
if ( ! Utils::isNinjaProd() && $module = Module::find($entityType)) {
|
||||
return trans("{$module->getLowerName()}::texts.{$text}");
|
||||
} else {
|
||||
return trans("texts.{$text}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (Utils::isNinjaDev())
|
||||
{
|
||||
|
@ -29,6 +29,11 @@ class CurlUtils
|
||||
|
||||
curl_setopt_array($curl, $opts);
|
||||
$response = curl_exec($curl);
|
||||
|
||||
if ($error = curl_error($curl)) {
|
||||
Utils::logError('CURL Error #' . curl_errno($curl) . ': ' . $error);
|
||||
}
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
return $response;
|
||||
|
@ -431,6 +431,12 @@ class Utils
|
||||
|
||||
public static function pluralizeEntityType($type)
|
||||
{
|
||||
if ( ! Utils::isNinjaProd()) {
|
||||
if ($module = \Module::find($type)) {
|
||||
return $module->get('plural', $type);
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === ENTITY_EXPENSE_CATEGORY) {
|
||||
return 'expense_categories';
|
||||
} else {
|
||||
@ -708,11 +714,6 @@ class Utils
|
||||
return $year + $offset;
|
||||
}
|
||||
|
||||
public static function getEntityClass($entityType)
|
||||
{
|
||||
return 'App\\Models\\' . static::getEntityName($entityType);
|
||||
}
|
||||
|
||||
public static function getEntityName($entityType)
|
||||
{
|
||||
return ucwords(Utils::toCamelCase($entityType));
|
||||
@ -725,7 +726,7 @@ class Utils
|
||||
} elseif ($model->first_name || $model->last_name) {
|
||||
return $model->first_name.' '.$model->last_name;
|
||||
} else {
|
||||
return $model->email;
|
||||
return $model->email ?: '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1066,6 +1067,22 @@ class Utils
|
||||
});
|
||||
}
|
||||
|
||||
public static function getReadableUrl($path)
|
||||
{
|
||||
$url = static::getDocsUrl($path);
|
||||
|
||||
$parts = explode('/', $url);
|
||||
$part = $parts[count($parts) - 1];
|
||||
$part = str_replace('#', '> ', $part);
|
||||
$part = str_replace(['.html', '-', '_'], ' ', $part);
|
||||
|
||||
if ($part) {
|
||||
return trans('texts.user_guide') . ': ' . ucwords($part);
|
||||
} else {
|
||||
return trans('texts.user_guide');
|
||||
}
|
||||
}
|
||||
|
||||
public static function getDocsUrl($path)
|
||||
{
|
||||
$page = '';
|
||||
|
@ -41,27 +41,7 @@ class CreditListener
|
||||
$credit->client_id = $payment->client_id;
|
||||
$credit->credit_date = Carbon::now()->toDateTimeString();
|
||||
$credit->balance = $credit->amount = $payment->getCompletedAmount();
|
||||
$credit->private_notes = $payment->transaction_reference;
|
||||
$credit->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PaymentWasRefunded $event
|
||||
*/
|
||||
public function refundedPayment(PaymentWasRefunded $event)
|
||||
{
|
||||
$payment = $event->payment;
|
||||
|
||||
// if the payment was from a credit we need to refund the credit
|
||||
if ($payment->payment_type_id != PAYMENT_TYPE_CREDIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$credit = Credit::createNew();
|
||||
$credit->client_id = $payment->client_id;
|
||||
$credit->credit_date = Carbon::now()->toDateTimeString();
|
||||
$credit->balance = $credit->amount = $event->refundAmount;
|
||||
$credit->private_notes = $payment->transaction_reference;
|
||||
$credit->private_notes = trans('texts.refunded_credit_payment');
|
||||
$credit->save();
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,10 @@ class NotificationListener
|
||||
*/
|
||||
public function viewedInvoice(InvoiceInvitationWasViewed $event)
|
||||
{
|
||||
if ( ! floatval($event->invoice->balance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sendEmails($event->invoice, 'viewed');
|
||||
$this->pushService->sendNotification($event->invoice, 'viewed');
|
||||
}
|
||||
@ -89,6 +93,10 @@ class NotificationListener
|
||||
*/
|
||||
public function viewedQuote(QuoteInvitationWasViewed $event)
|
||||
{
|
||||
if ($event->quote->quote_invoice_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sendEmails($event->quote, 'viewed');
|
||||
$this->pushService->sendNotification($event->quote, 'viewed');
|
||||
}
|
||||
@ -118,4 +126,4 @@ class NotificationListener
|
||||
$this->pushService->sendNotification($event->payment->invoice, 'paid');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use DateTime;
|
||||
use Event;
|
||||
use Cache;
|
||||
use App;
|
||||
use Carbon;
|
||||
use App\Events\UserSettingsChanged;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@ -303,6 +304,14 @@ class Account extends Eloquent
|
||||
return $this->hasMany('App\Models\ExpenseCategory','account_id','id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function projects()
|
||||
{
|
||||
return $this->hasMany('App\Models\Project','account_id','id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
@ -1387,7 +1396,7 @@ class Account extends Eloquent
|
||||
$date = date_create();
|
||||
}
|
||||
|
||||
return $date->format('Y-m-d');
|
||||
return Carbon::instance($date);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,6 +173,14 @@ class Client extends EntityModel
|
||||
return $this->hasMany('App\Models\Invoice')->where('invoice_type_id', '=', INVOICE_TYPE_QUOTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function publicQuotes()
|
||||
{
|
||||
return $this->hasMany('App\Models\Invoice')->where('invoice_type_id', '=', INVOICE_TYPE_QUOTE)->whereIsPublic(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
|
@ -1,7 +1,10 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Carbon;
|
||||
use Utils;
|
||||
use Eloquent;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
/**
|
||||
* Class Company
|
||||
@ -9,11 +12,21 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
class Company extends Eloquent
|
||||
{
|
||||
use SoftDeletes;
|
||||
use PresentableTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\CompanyPresenter';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
protected $dates = [
|
||||
'deleted_at',
|
||||
'promo_expires',
|
||||
'discount_expires',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
@ -30,4 +43,66 @@ class Company extends Eloquent
|
||||
{
|
||||
return $this->belongsTo('App\Models\Payment');
|
||||
}
|
||||
|
||||
public function hasActivePromo()
|
||||
{
|
||||
if ($this->discount_expires) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->promo_expires && $this->promo_expires->gte(Carbon::today());
|
||||
}
|
||||
|
||||
// handle promos and discounts
|
||||
public function hasActiveDiscount(Carbon $date = null)
|
||||
{
|
||||
if ( ! $this->discount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$date = $date ?: Carbon::today();
|
||||
|
||||
return $this->discount_expires && $this->discount_expires->gt($date);
|
||||
}
|
||||
|
||||
public function discountedPrice($price)
|
||||
{
|
||||
if ( ! $this->hasActivePromo() && ! $this->hasActiveDiscount()) {
|
||||
return $price;
|
||||
}
|
||||
|
||||
return $price - ($price * $this->discount);
|
||||
}
|
||||
|
||||
public function hasEarnedPromo()
|
||||
{
|
||||
if ( ! Utils::isNinjaProd() || Utils::isPro()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if they've already had a discount or a promotion is active return false
|
||||
if ($this->discount_expires || $this->hasActivePromo()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// after 52 weeks, offer a 50% discount for 3 days
|
||||
$discounts = [
|
||||
52 => [.5, 3],
|
||||
16 => [.5, 3],
|
||||
10 => [.25, 5],
|
||||
];
|
||||
|
||||
foreach ($discounts as $weeks => $promo) {
|
||||
list($discount, $validFor) = $promo;
|
||||
$difference = $this->created_at->diffInWeeks();
|
||||
if ($difference >= $weeks) {
|
||||
$this->discount = $discount;
|
||||
$this->promo_expires = date_create()->modify($validFor . ' days')->format('Y-m-d');
|
||||
$this->save();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,14 @@ class Credit extends EntityModel
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return "/credits/{$this->public_id}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -31,6 +31,15 @@ class EntityModel extends Eloquent
|
||||
*/
|
||||
public static $notifySubscriptions = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $statuses = [
|
||||
STATUS_ACTIVE,
|
||||
STATUS_ARCHIVED,
|
||||
STATUS_DELETED,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param null $context
|
||||
* @return mixed
|
||||
@ -63,7 +72,6 @@ class EntityModel extends Eloquent
|
||||
$lastEntity = $className::whereAccountId($entity->account_id);
|
||||
}
|
||||
|
||||
|
||||
if (static::$hasPublicId) {
|
||||
$lastEntity = $lastEntity->orderBy('public_id', 'DESC')
|
||||
->first();
|
||||
@ -184,6 +192,16 @@ class EntityModel extends Eloquent
|
||||
*/
|
||||
public static function getClassName($entityType)
|
||||
{
|
||||
if ( ! Utils::isNinjaProd()) {
|
||||
if ($module = \Module::find($entityType)) {
|
||||
return "Modules\\{$module->getName()}\\Models\\{$module->getName()}";
|
||||
}
|
||||
}
|
||||
|
||||
if ($entityType == ENTITY_QUOTE || $entityType == ENTITY_RECURRING_INVOICE) {
|
||||
$entityType = ENTITY_INVOICE;
|
||||
}
|
||||
|
||||
return 'App\\Models\\' . ucwords(Utils::toCamelCase($entityType));
|
||||
}
|
||||
|
||||
@ -193,6 +211,12 @@ class EntityModel extends Eloquent
|
||||
*/
|
||||
public static function getTransformerName($entityType)
|
||||
{
|
||||
if ( ! Utils::isNinjaProd()) {
|
||||
if ($module = \Module::find($entityType)) {
|
||||
return "Modules\\{$module->getName()}\\Transformers\\{$module->getName()}Transformer";
|
||||
}
|
||||
}
|
||||
|
||||
return 'App\\Ninja\\Transformers\\' . ucwords(Utils::toCamelCase($entityType)) . 'Transformer';
|
||||
}
|
||||
|
||||
@ -281,4 +305,34 @@ class EntityModel extends Eloquent
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getStates($entityType = false)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach (static::$statuses as $status) {
|
||||
$data[$status] = trans("texts.{$status}");
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getStatuses($entityType = false)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function getStatesFor($entityType = false)
|
||||
{
|
||||
$class = static::getClassName($entityType);
|
||||
|
||||
return $class::getStates($entityType);
|
||||
}
|
||||
|
||||
public static function getStatusesFor($entityType = false)
|
||||
{
|
||||
$class = static::getClassName($entityType);
|
||||
|
||||
return $class::getStatuses($entityType);
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +211,16 @@ class Expense extends EntityModel
|
||||
{
|
||||
return Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
|
||||
}
|
||||
|
||||
public static function getStatuses($entityType = false)
|
||||
{
|
||||
$statuses = [];
|
||||
$statuses[EXPENSE_STATUS_LOGGED] = trans('texts.logged');
|
||||
$statuses[EXPENSE_STATUS_INVOICED] = trans('texts.invoiced');
|
||||
$statuses[EXPENSE_STATUS_PAID] = trans('texts.paid');
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
}
|
||||
|
||||
Expense::creating(function ($expense) {
|
||||
|
@ -47,5 +47,4 @@ class ExpenseCategory extends EntityModel
|
||||
{
|
||||
return "/expense_categories/{$this->public_id}/edit";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -97,8 +97,8 @@ class Invitation extends EntityModel
|
||||
if ($this->$field && $this->field != '0000-00-00 00:00:00') {
|
||||
$date = Utils::dateToString($this->$field);
|
||||
$hasValue = true;
|
||||
$parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date;
|
||||
}
|
||||
$parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date;
|
||||
}
|
||||
|
||||
return $hasValue ? implode($parts, '<br/>') : false;
|
||||
@ -123,6 +123,11 @@ class Invitation extends EntityModel
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function isSent()
|
||||
{
|
||||
return $this->sent_date && $this->sent_date != '0000-00-00 00:00:00';
|
||||
}
|
||||
|
||||
public function markViewed()
|
||||
{
|
||||
$invoice = $this->invoice;
|
||||
|
@ -153,7 +153,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
public function affectsBalance()
|
||||
{
|
||||
return $this->isType(INVOICE_TYPE_STANDARD) && !$this->is_recurring;
|
||||
return $this->isType(INVOICE_TYPE_STANDARD) && !$this->is_recurring && $this->is_public;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +161,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
public function getAdjustment()
|
||||
{
|
||||
if (!$this->affectsBalance()) {
|
||||
if ( ! $this->affectsBalance()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -173,6 +173,11 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
private function getRawAdjustment()
|
||||
{
|
||||
// if we've just made the invoice public then apply the full amount
|
||||
if ($this->is_public && ! $this->getOriginal('is_public')) {
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
return floatval($this->amount) - floatval($this->getOriginal('amount'));
|
||||
}
|
||||
|
||||
@ -353,6 +358,16 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
->where('is_recurring', '=', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @return mixed
|
||||
*/
|
||||
public function scopeRecurring($query)
|
||||
{
|
||||
return $query->where('invoice_type_id', '=', INVOICE_TYPE_STANDARD)
|
||||
->where('is_recurring', '=', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @return mixed
|
||||
@ -400,11 +415,30 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
public function markInvitationsSent($notify = false)
|
||||
{
|
||||
if ( ! $this->relationLoaded('invitations')) {
|
||||
$this->load('invitations');
|
||||
}
|
||||
|
||||
foreach ($this->invitations as $invitation) {
|
||||
$this->markInvitationSent($invitation, false, $notify);
|
||||
}
|
||||
}
|
||||
|
||||
public function areInvitationsSent()
|
||||
{
|
||||
if ( ! $this->relationLoaded('invitations')) {
|
||||
$this->load('invitations');
|
||||
}
|
||||
|
||||
foreach ($this->invitations as $invitation) {
|
||||
if ( ! $invitation->isSent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invitation
|
||||
* @param bool $messageId
|
||||
@ -1249,6 +1283,35 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
|
||||
return $recurInvoice->auto_bill == AUTO_BILL_ALWAYS || ($recurInvoice->auto_bill != AUTO_BILL_OFF && $recurInvoice->client_enable_auto_bill);
|
||||
}
|
||||
|
||||
public static function getStatuses($entityType = false)
|
||||
{
|
||||
$statuses = [];
|
||||
|
||||
if ($entityType == ENTITY_RECURRING_INVOICE) {
|
||||
return $statuses;
|
||||
}
|
||||
|
||||
foreach (\Cache::get('invoiceStatus') as $status) {
|
||||
if ($entityType == ENTITY_QUOTE) {
|
||||
if (in_array($status->id, [INVOICE_STATUS_PAID, INVOICE_STATUS_PARTIAL])) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entityType == ENTITY_INVOICE) {
|
||||
if (in_array($status->id, [INVOICE_STATUS_APPROVED])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$statuses[$status->id] = trans('texts.status_' . strtolower($status->name));
|
||||
}
|
||||
|
||||
if ($entityType == ENTITY_INVOICE) {
|
||||
$statuses[INVOICE_STATUS_OVERDUE] = trans('texts.overdue');
|
||||
}
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
}
|
||||
|
||||
Invoice::creating(function ($invoice) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
@ -7,7 +8,14 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
*/
|
||||
class InvoiceItem extends EntityModel
|
||||
{
|
||||
use PresentableTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\InvoiceItemPresenter';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
|
64
app/Models/Project.php
Normal file
64
app/Models/Project.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
/**
|
||||
* Class ExpenseCategory
|
||||
*/
|
||||
class Project extends EntityModel
|
||||
{
|
||||
// Expense Categories
|
||||
use SoftDeletes;
|
||||
use PresentableTrait;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\EntityPresenter';
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return ENTITY_PROJECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return "/projects/{$this->public_id}/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Client')->withTrashed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Project::creating(function ($project) {
|
||||
$project->setNullValues();
|
||||
});
|
||||
|
||||
Project::updating(function ($project) {
|
||||
$project->setNullValues();
|
||||
});
|
@ -69,6 +69,14 @@ class Task extends EntityModel
|
||||
return $this->belongsTo('App\Models\Client')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function project()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Project')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $task
|
||||
* @return string
|
||||
@ -195,6 +203,18 @@ class Task extends EntityModel
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function getStatuses($entityType = false)
|
||||
{
|
||||
$statuses = [];
|
||||
$statuses[TASK_STATUS_LOGGED] = trans('texts.logged');
|
||||
$statuses[TASK_STATUS_RUNNING] = trans('texts.running');
|
||||
$statuses[TASK_STATUS_INVOICED] = trans('texts.invoiced');
|
||||
$statuses[TASK_STATUS_PAID] = trans('texts.paid');
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,6 +7,7 @@ use Auth;
|
||||
class ClientDatatable extends EntityDatatable
|
||||
{
|
||||
public $entityType = ENTITY_CLIENT;
|
||||
public $sortCol = 4;
|
||||
|
||||
public function columns()
|
||||
{
|
||||
@ -18,9 +19,9 @@ class ClientDatatable extends EntityDatatable
|
||||
}
|
||||
],
|
||||
[
|
||||
'first_name',
|
||||
'contact',
|
||||
function ($model) {
|
||||
return link_to("clients/{$model->public_id}", $model->first_name.' '.$model->last_name)->toHtml();
|
||||
return link_to("clients/{$model->public_id}", $model->contact ?: '')->toHtml();
|
||||
}
|
||||
],
|
||||
[
|
||||
@ -30,7 +31,7 @@ class ClientDatatable extends EntityDatatable
|
||||
}
|
||||
],
|
||||
[
|
||||
'clients.created_at',
|
||||
'client_created_at',
|
||||
function ($model) {
|
||||
return Utils::timestampToDateString(strtotime($model->created_at));
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use Auth;
|
||||
class CreditDatatable extends EntityDatatable
|
||||
{
|
||||
public $entityType = ENTITY_CREDIT;
|
||||
public $sortCol = 4;
|
||||
|
||||
public function columns()
|
||||
{
|
||||
@ -37,7 +38,11 @@ class CreditDatatable extends EntityDatatable
|
||||
[
|
||||
'credit_date',
|
||||
function ($model) {
|
||||
return Utils::fromSqlDate($model->credit_date);
|
||||
if ( ! Auth::user()->can('viewByOwner', [ENTITY_CREDIT, $model->user_id])){
|
||||
return Utils::fromSqlDate($model->credit_date);
|
||||
}
|
||||
|
||||
return link_to("credits/{$model->public_id}/edit", Utils::fromSqlDate($model->credit_date))->toHtml();
|
||||
}
|
||||
],
|
||||
[
|
||||
@ -52,6 +57,15 @@ class CreditDatatable extends EntityDatatable
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
[
|
||||
trans('texts.edit_credit'),
|
||||
function ($model) {
|
||||
return URL::to("credits/{$model->public_id}/edit");
|
||||
},
|
||||
function ($model) {
|
||||
return Auth::user()->can('editByOwner', [ENTITY_CREDIT, $model->user_id]);
|
||||
}
|
||||
],
|
||||
[
|
||||
trans('texts.apply_credit'),
|
||||
function ($model) {
|
||||
|
@ -5,11 +5,16 @@ class EntityDatatable
|
||||
public $entityType;
|
||||
public $isBulkEdit;
|
||||
public $hideClient;
|
||||
public $sortCol = 1;
|
||||
|
||||
public function __construct($isBulkEdit = true, $hideClient = false)
|
||||
public function __construct($isBulkEdit = true, $hideClient = false, $entityType = false)
|
||||
{
|
||||
$this->isBulkEdit = $isBulkEdit;
|
||||
$this->hideClient = $hideClient;
|
||||
|
||||
if ($entityType) {
|
||||
$this->entityType = $entityType;
|
||||
}
|
||||
}
|
||||
|
||||
public function columns()
|
||||
@ -21,4 +26,42 @@ class EntityDatatable
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function bulkActions()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'label' => mtrans($this->entityType, 'archive_'.$this->entityType),
|
||||
'url' => 'javascript:submitForm_'.$this->entityType.'("archive")',
|
||||
],
|
||||
[
|
||||
'label' => mtrans($this->entityType, 'delete_'.$this->entityType),
|
||||
'url' => 'javascript:submitForm_'.$this->entityType.'("delete")',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function columnFields()
|
||||
{
|
||||
$data = [];
|
||||
$columns = $this->columns();
|
||||
|
||||
if ($this->isBulkEdit) {
|
||||
$data[] = 'checkbox';
|
||||
}
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if (count($column) == 3) {
|
||||
// third column is optionally used to determine visibility
|
||||
if (!$column[2]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$data[] = $column[0];
|
||||
}
|
||||
|
||||
$data[] = '';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use Auth;
|
||||
class ExpenseCategoryDatatable extends EntityDatatable
|
||||
{
|
||||
public $entityType = ENTITY_EXPENSE_CATEGORY;
|
||||
public $sortCol = 1;
|
||||
|
||||
public function columns()
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user