mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-09-19 16:01:34 +02:00
Working on recurring expenses
This commit is contained in:
parent
29ae0c3f76
commit
4a55e26117
@ -37,6 +37,7 @@ if (! defined('APP_NAME')) {
|
||||
define('ENTITY_BANK_SUBACCOUNT', 'bank_subaccount');
|
||||
define('ENTITY_EXPENSE_CATEGORY', 'expense_category');
|
||||
define('ENTITY_PROJECT', 'project');
|
||||
define('ENTITY_RECURRING_EXPENSE', 'recurring_expense');
|
||||
|
||||
define('INVOICE_TYPE_STANDARD', 1);
|
||||
define('INVOICE_TYPE_QUOTE', 2);
|
||||
|
@ -266,6 +266,7 @@ class ExpenseController extends BaseController
|
||||
'customLabel2' => Auth::user()->account->custom_vendor_label2,
|
||||
'categories' => ExpenseCategory::whereAccountId(Auth::user()->account_id)->withArchived()->orderBy('name')->get(),
|
||||
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
|
||||
'isRecurring' => false,
|
||||
];
|
||||
}
|
||||
|
||||
|
164
app/Http/Controllers/RecurringExpenseController.php
Normal file
164
app/Http/Controllers/RecurringExpenseController.php
Normal file
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\CreateRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpenseRequest;
|
||||
use App\Http\Requests\UpdateRecurringExpenseRequest;
|
||||
use App\Models\Client;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\Vendor;
|
||||
use App\Ninja\Datatables\RecurringExpenseDatatable;
|
||||
use App\Ninja\Repositories\RecurringExpenseRepository;
|
||||
use App\Services\RecurringExpenseService;
|
||||
use Auth;
|
||||
use Input;
|
||||
use Session;
|
||||
use View;
|
||||
use Cache;
|
||||
|
||||
class RecurringExpenseController extends BaseController
|
||||
{
|
||||
protected $recurringExpenseRepo;
|
||||
protected $recurringExpenseService;
|
||||
protected $entityType = ENTITY_RECURRING_EXPENSE;
|
||||
|
||||
public function __construct(RecurringExpenseRepository $recurringExpenseRepo, RecurringExpenseService $recurringExpenseService)
|
||||
{
|
||||
$this->recurringExpenseRepo = $recurringExpenseRepo;
|
||||
$this->recurringExpenseService = $recurringExpenseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list_wrapper', [
|
||||
'entityType' => ENTITY_RECURRING_EXPENSE,
|
||||
'datatable' => new RecurringExpenseDatatable(),
|
||||
'title' => trans('texts.recurring_expenses'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getDatatable($expensePublicId = null)
|
||||
{
|
||||
$search = Input::get('sSearch');
|
||||
$userId = Auth::user()->filterId();
|
||||
|
||||
return $this->recurringExpenseService->getDatatable($search, $userId);
|
||||
}
|
||||
|
||||
public function create(RecurringExpenseRequest $request)
|
||||
{
|
||||
if ($request->vendor_id != 0) {
|
||||
$vendor = Vendor::scope($request->vendor_id)->with('vendor_contacts')->firstOrFail();
|
||||
} else {
|
||||
$vendor = null;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'vendorPublicId' => Input::old('vendor') ? Input::old('vendor') : $request->vendor_id,
|
||||
'expense' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'recurring_expenses',
|
||||
'title' => trans('texts.new_expense'),
|
||||
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
|
||||
'vendor' => $vendor,
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'clientPublicId' => $request->client_id,
|
||||
'categoryPublicId' => $request->category_id,
|
||||
];
|
||||
|
||||
$data = array_merge($data, self::getViewModel());
|
||||
|
||||
return View::make('expenses.edit', $data);
|
||||
}
|
||||
|
||||
public function edit(RecurringExpenseRequest $request)
|
||||
{
|
||||
$expense = $request->entity();
|
||||
|
||||
$actions = [];
|
||||
if (! $expense->trashed()) {
|
||||
$actions[] = ['url' => 'javascript:submitAction("archive")', 'label' => trans('texts.archive_expense')];
|
||||
$actions[] = ['url' => 'javascript:onDeleteClick()', 'label' => trans('texts.delete_expense')];
|
||||
} else {
|
||||
$actions[] = ['url' => 'javascript:submitAction("restore")', 'label' => trans('texts.restore_expense')];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'vendor' => null,
|
||||
'expense' => $expense,
|
||||
'entity' => $expense,
|
||||
'method' => 'PUT',
|
||||
'url' => 'recurring_expenses/'.$expense->public_id,
|
||||
'title' => 'Edit Expense',
|
||||
'actions' => $actions,
|
||||
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
|
||||
'vendorPublicId' => $expense->vendor ? $expense->vendor->public_id : null,
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'clientPublicId' => $expense->client ? $expense->client->public_id : null,
|
||||
'categoryPublicId' => $expense->expense_category ? $expense->expense_category->public_id : null,
|
||||
];
|
||||
|
||||
$data = array_merge($data, self::getViewModel());
|
||||
|
||||
return View::make('expenses.edit', $data);
|
||||
}
|
||||
|
||||
private static function getViewModel()
|
||||
{
|
||||
return [
|
||||
'data' => Input::old('data'),
|
||||
'account' => Auth::user()->account,
|
||||
'sizes' => Cache::get('sizes'),
|
||||
'paymentTerms' => Cache::get('paymentTerms'),
|
||||
'industries' => Cache::get('industries'),
|
||||
'currencies' => Cache::get('currencies'),
|
||||
'languages' => Cache::get('languages'),
|
||||
'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)->withArchived()->orderBy('name')->get(),
|
||||
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->orderBy('name')->get(),
|
||||
'isRecurring' => true,
|
||||
];
|
||||
}
|
||||
|
||||
public function store(CreateRecurringExpenseRequest $request)
|
||||
{
|
||||
$recurringExpense = $this->recurringExpenseService->save($request->input());
|
||||
|
||||
Session::flash('message', trans('texts.created_recurring_expense'));
|
||||
|
||||
return redirect()->to($recurringExpense->getRoute());
|
||||
}
|
||||
|
||||
public function update(UpdateRecurringExpenseRequest $request)
|
||||
{
|
||||
$recurringExpense = $this->recurringExpenseService->save($request->input(), $request->entity());
|
||||
|
||||
Session::flash('message', trans('texts.updated_recurring_expense'));
|
||||
|
||||
return redirect()->to($recurringExpense->getRoute());
|
||||
}
|
||||
|
||||
public function bulk()
|
||||
{
|
||||
$action = Input::get('action');
|
||||
$ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
|
||||
$count = $this->recurringExpenseService->bulk($ids, $action);
|
||||
|
||||
if ($count > 0) {
|
||||
$field = $count == 1 ? "{$action}d_recurring_expense" : "{$action}d_recurring_expenses";
|
||||
$message = trans("texts.$field", ['count' => $count]);
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return redirect()->to('/recurring_expenses');
|
||||
}
|
||||
}
|
28
app/Http/Requests/CreateRecurringExpenseRequest.php
Normal file
28
app/Http/Requests/CreateRecurringExpenseRequest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class CreateRecurringExpenseRequest extends RecurringExpenseRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->can('create', ENTITY_RECURRING_EXPENSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'amount' => 'numeric',
|
||||
];
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ class ExpenseRequest extends EntityRequest
|
||||
$expense = parent::entity();
|
||||
|
||||
// eager load the documents
|
||||
if ($expense && ! $expense->relationLoaded('documents')) {
|
||||
if ($expense && method_exists($expense, 'documents') && ! $expense->relationLoaded('documents')) {
|
||||
$expense->load('documents');
|
||||
}
|
||||
|
||||
|
8
app/Http/Requests/RecurringExpenseRequest.php
Normal file
8
app/Http/Requests/RecurringExpenseRequest.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class RecurringExpenseRequest extends ExpenseRequest
|
||||
{
|
||||
protected $entityType = ENTITY_RECURRING_EXPENSE;
|
||||
}
|
28
app/Http/Requests/UpdateRecurringExpenseRequest.php
Normal file
28
app/Http/Requests/UpdateRecurringExpenseRequest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class UpdateRecurringExpenseRequest extends RecurringExpenseRequest
|
||||
{
|
||||
/**
|
||||
* 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' => 'numeric',
|
||||
];
|
||||
}
|
||||
}
|
@ -179,6 +179,14 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () {
|
||||
Route::post('invoices/bulk', 'InvoiceController@bulk');
|
||||
Route::post('recurring_invoices/bulk', 'InvoiceController@bulk');
|
||||
|
||||
Route::get('recurring_expenses', 'RecurringExpenseController@index');
|
||||
Route::get('api/recurring_expenses', 'RecurringExpenseController@getDatatable');
|
||||
Route::get('recurring_expenses/create/{vendor_id?}/{client_id?}/{category_id?}', 'RecurringExpenseController@create');
|
||||
Route::post('recurring_expenses', 'RecurringExpenseController@store');
|
||||
Route::put('recurring_expenses/{recurring_expenses}', 'RecurringExpenseController@update');
|
||||
Route::get('recurring_expenses/{recurring_expenses}/edit', 'RecurringExpenseController@edit');
|
||||
Route::post('recurring_expenses/bulk', 'RecurringExpenseController@bulk');
|
||||
|
||||
Route::get('documents/{documents}/{filename?}', 'DocumentController@get');
|
||||
Route::get('documents/js/{documents}/{filename}', 'DocumentController@getVFSJS');
|
||||
Route::get('documents/preview/{documents}/{filename?}', 'DocumentController@getPreview');
|
||||
|
148
app/Models/RecurringExpense.php
Normal file
148
app/Models/RecurringExpense.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
//use App\Events\ExpenseWasCreated;
|
||||
//use App\Events\ExpenseWasUpdated;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use Utils;
|
||||
|
||||
/**
|
||||
* Class Expense.
|
||||
*/
|
||||
class RecurringExpense extends EntityModel
|
||||
{
|
||||
// Expenses
|
||||
use SoftDeletes;
|
||||
use PresentableTrait;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\ExpensePresenter';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'client_id',
|
||||
'vendor_id',
|
||||
'expense_currency_id',
|
||||
//'invoice_currency_id',
|
||||
//'exchange_rate',
|
||||
'amount',
|
||||
'private_notes',
|
||||
'public_notes',
|
||||
'expense_category_id',
|
||||
'tax_rate1',
|
||||
'tax_name1',
|
||||
'tax_rate2',
|
||||
'tax_name2',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function expense_category()
|
||||
{
|
||||
return $this->belongsTo('App\Models\ExpenseCategory')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\Models\User')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Vendor')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Client')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
if ($this->public_notes) {
|
||||
return Utils::truncateString($this->public_notes, 16);
|
||||
} else {
|
||||
return '#' . $this->public_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDisplayName()
|
||||
{
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return "/recurring_expenses/{$this->public_id}/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return ENTITY_RECURRING_EXPENSE;
|
||||
}
|
||||
|
||||
public function amountWithTax()
|
||||
{
|
||||
return Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
|
||||
}
|
||||
}
|
||||
|
||||
RecurringExpense::creating(function ($expense) {
|
||||
$expense->setNullValues();
|
||||
});
|
||||
|
||||
RecurringExpense::created(function ($expense) {
|
||||
//event(new ExpenseWasCreated($expense));
|
||||
});
|
||||
|
||||
RecurringExpense::updating(function ($expense) {
|
||||
$expense->setNullValues();
|
||||
});
|
||||
|
||||
RecurringExpense::updated(function ($expense) {
|
||||
//event(new ExpenseWasUpdated($expense));
|
||||
});
|
||||
|
||||
RecurringExpense::deleting(function ($expense) {
|
||||
$expense->setNullValues();
|
||||
});
|
112
app/Ninja/Datatables/RecurringExpenseDatatable.php
Normal file
112
app/Ninja/Datatables/RecurringExpenseDatatable.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ninja\Datatables;
|
||||
|
||||
use App\Models\Expense;
|
||||
use Auth;
|
||||
use URL;
|
||||
use Utils;
|
||||
|
||||
class RecurringExpenseDatatable extends EntityDatatable
|
||||
{
|
||||
public $entityType = ENTITY_RECURRING_EXPENSE;
|
||||
public $sortCol = 3;
|
||||
|
||||
public function columns()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'vendor_name',
|
||||
function ($model) {
|
||||
if ($model->vendor_public_id) {
|
||||
if (! Auth::user()->can('viewByOwner', [ENTITY_VENDOR, $model->vendor_user_id])) {
|
||||
return $model->vendor_name;
|
||||
}
|
||||
|
||||
return link_to("vendors/{$model->vendor_public_id}", $model->vendor_name)->toHtml();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
! $this->hideClient,
|
||||
],
|
||||
[
|
||||
'client_name',
|
||||
function ($model) {
|
||||
if ($model->client_public_id) {
|
||||
if (! Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])) {
|
||||
return Utils::getClientDisplayName($model);
|
||||
}
|
||||
|
||||
return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
! $this->hideClient,
|
||||
],
|
||||
/*
|
||||
[
|
||||
'expense_date',
|
||||
function ($model) {
|
||||
if (! Auth::user()->can('viewByOwner', [ENTITY_EXPENSE, $model->user_id])) {
|
||||
return Utils::fromSqlDate($model->expense_date_sql);
|
||||
}
|
||||
|
||||
return link_to("expenses/{$model->public_id}/edit", Utils::fromSqlDate($model->expense_date_sql))->toHtml();
|
||||
},
|
||||
],
|
||||
*/
|
||||
[
|
||||
'amount',
|
||||
function ($model) {
|
||||
$amount = Utils::calculateTaxes($model->amount, $model->tax_rate1, $model->tax_rate2);
|
||||
$str = Utils::formatMoney($amount, $model->expense_currency_id);
|
||||
|
||||
/*
|
||||
// show both the amount and the converted amount
|
||||
if ($model->exchange_rate != 1) {
|
||||
$converted = round($amount * $model->exchange_rate, 2);
|
||||
$str .= ' | ' . Utils::formatMoney($converted, $model->invoice_currency_id);
|
||||
}
|
||||
*/
|
||||
|
||||
return $str;
|
||||
},
|
||||
],
|
||||
[
|
||||
'category',
|
||||
function ($model) {
|
||||
$category = $model->category != null ? substr($model->category, 0, 100) : '';
|
||||
if (! Auth::user()->can('editByOwner', [ENTITY_EXPENSE_CATEGORY, $model->category_user_id])) {
|
||||
return $category;
|
||||
}
|
||||
|
||||
return $model->category_public_id ? link_to("expense_categories/{$model->category_public_id}/edit", $category)->toHtml() : '';
|
||||
},
|
||||
],
|
||||
[
|
||||
'public_notes',
|
||||
function ($model) {
|
||||
return $model->public_notes != null ? substr($model->public_notes, 0, 100) : '';
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
[
|
||||
trans('texts.edit_recurring_expense'),
|
||||
function ($model) {
|
||||
return URL::to("recurring_expenses/{$model->public_id}/edit");
|
||||
},
|
||||
function ($model) {
|
||||
return Auth::user()->can('editByOwner', [ENTITY_RECURRING_EXPENSE, $model->user_id]);
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
141
app/Ninja/Repositories/RecurringExpenseRepository.php
Normal file
141
app/Ninja/Repositories/RecurringExpenseRepository.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ninja\Repositories;
|
||||
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Models\Vendor;
|
||||
use Auth;
|
||||
use DB;
|
||||
use Utils;
|
||||
|
||||
class RecurringExpenseRepository extends BaseRepository
|
||||
{
|
||||
// Expenses
|
||||
public function getClassName()
|
||||
{
|
||||
return 'App\Models\RecurringExpense';
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return RecurringExpense::scope()
|
||||
->with('user')
|
||||
->withTrashed()
|
||||
->where('is_deleted', '=', false)
|
||||
->get();
|
||||
}
|
||||
|
||||
public function find($filter = null)
|
||||
{
|
||||
$accountid = \Auth::user()->account_id;
|
||||
$query = DB::table('recurring_expenses')
|
||||
->join('accounts', 'accounts.id', '=', 'recurring_expenses.account_id')
|
||||
->leftjoin('clients', 'clients.id', '=', 'recurring_expenses.client_id')
|
||||
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
|
||||
->leftjoin('vendors', 'vendors.id', '=', 'recurring_expenses.vendor_id')
|
||||
->leftJoin('expense_categories', 'recurring_expenses.expense_category_id', '=', 'expense_categories.id')
|
||||
->where('recurring_expenses.account_id', '=', $accountid)
|
||||
->where('contacts.deleted_at', '=', null)
|
||||
->where('vendors.deleted_at', '=', null)
|
||||
->where('clients.deleted_at', '=', null)
|
||||
->where(function ($query) { // handle when client isn't set
|
||||
$query->where('contacts.is_primary', '=', true)
|
||||
->orWhere('contacts.is_primary', '=', null);
|
||||
})
|
||||
->select(
|
||||
'recurring_expenses.account_id',
|
||||
'recurring_expenses.amount',
|
||||
'recurring_expenses.deleted_at',
|
||||
'recurring_expenses.id',
|
||||
'recurring_expenses.is_deleted',
|
||||
'recurring_expenses.private_notes',
|
||||
'recurring_expenses.public_id',
|
||||
'recurring_expenses.public_notes',
|
||||
'recurring_expenses.should_be_invoiced',
|
||||
'recurring_expenses.vendor_id',
|
||||
'recurring_expenses.expense_currency_id',
|
||||
'recurring_expenses.invoice_currency_id',
|
||||
'recurring_expenses.user_id',
|
||||
'recurring_expenses.tax_rate1',
|
||||
'recurring_expenses.tax_rate2',
|
||||
'expense_categories.name as category',
|
||||
'expense_categories.user_id as category_user_id',
|
||||
'expense_categories.public_id as category_public_id',
|
||||
'vendors.name as vendor_name',
|
||||
'vendors.public_id as vendor_public_id',
|
||||
'vendors.user_id as vendor_user_id',
|
||||
DB::raw("COALESCE(NULLIF(clients.name,''), NULLIF(CONCAT(contacts.first_name, ' ', contacts.last_name),''), NULLIF(contacts.email,'')) client_name"),
|
||||
'clients.public_id as client_public_id',
|
||||
'clients.user_id as client_user_id',
|
||||
'contacts.first_name',
|
||||
'contacts.email',
|
||||
'contacts.last_name',
|
||||
'clients.country_id as client_country_id'
|
||||
);
|
||||
|
||||
$this->applyFilters($query, ENTITY_RECURRING_EXPENSE);
|
||||
|
||||
if ($filter) {
|
||||
$query->where(function ($query) use ($filter) {
|
||||
$query->where('recurring_expenses.public_notes', 'like', '%'.$filter.'%')
|
||||
->orWhere('clients.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('expense_categories.name', 'like', '%'.$filter.'%');
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function save($input, $expense = null)
|
||||
{
|
||||
$publicId = isset($input['public_id']) ? $input['public_id'] : false;
|
||||
|
||||
if ($expense) {
|
||||
// do nothing
|
||||
} elseif ($publicId) {
|
||||
$expense = RecurringExpense::scope($publicId)->firstOrFail();
|
||||
if (Utils::isNinjaDev()) {
|
||||
\Log::warning('Entity not set in expense repo save');
|
||||
}
|
||||
} else {
|
||||
$expense = RecurringExpense::createNew();
|
||||
}
|
||||
|
||||
if ($expense->is_deleted) {
|
||||
return $expense;
|
||||
}
|
||||
|
||||
// First auto fill
|
||||
$expense->fill($input);
|
||||
|
||||
/*
|
||||
if (isset($input['expense_date'])) {
|
||||
$expense->expense_date = Utils::toSqlDate($input['expense_date']);
|
||||
}
|
||||
if (isset($input['payment_date'])) {
|
||||
$expense->payment_date = Utils::toSqlDate($input['payment_date']);
|
||||
}
|
||||
|
||||
$expense->should_be_invoiced = isset($input['should_be_invoiced']) && floatval($input['should_be_invoiced']) || $expense->client_id ? true : false;
|
||||
|
||||
if (! $expense->expense_currency_id) {
|
||||
$expense->expense_currency_id = \Auth::user()->account->getCurrencyId();
|
||||
}
|
||||
if (! $expense->invoice_currency_id) {
|
||||
$expense->invoice_currency_id = \Auth::user()->account->getCurrencyId();
|
||||
}
|
||||
|
||||
$rate = isset($input['exchange_rate']) ? Utils::parseFloat($input['exchange_rate']) : 1;
|
||||
$expense->exchange_rate = round($rate, 4);
|
||||
if (isset($input['amount'])) {
|
||||
$expense->amount = round(Utils::parseFloat($input['amount']), 2);
|
||||
}
|
||||
*/
|
||||
|
||||
$expense->save();
|
||||
|
||||
return $expense;
|
||||
}
|
||||
}
|
23
app/Policies/RecurringExpensePolicy.php
Normal file
23
app/Policies/RecurringExpensePolicy.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class RecurringExpensePolicy extends EntityPolicy
|
||||
{
|
||||
/**
|
||||
* @param User $user
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function create(User $user, $item)
|
||||
{
|
||||
if (! parent::create($user, $item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user->hasFeature(FEATURE_EXPENSES);
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
\App\Models\Credit::class => \App\Policies\CreditPolicy::class,
|
||||
\App\Models\Document::class => \App\Policies\DocumentPolicy::class,
|
||||
\App\Models\Expense::class => \App\Policies\ExpensePolicy::class,
|
||||
\App\Models\RecurringExpense::class => \App\Policies\RecurringExpensePolicy::class,
|
||||
\App\Models\ExpenseCategory::class => \App\Policies\ExpenseCategoryPolicy::class,
|
||||
\App\Models\Invoice::class => \App\Policies\InvoicePolicy::class,
|
||||
\App\Models\Payment::class => \App\Policies\PaymentPolicy::class,
|
||||
|
82
app/Services/RecurringExpenseService.php
Normal file
82
app/Services/RecurringExpenseService.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Utils;
|
||||
use App\Models\Client;
|
||||
use App\Models\Vendor;
|
||||
use App\Ninja\Datatables\RecurringExpenseDatatable;
|
||||
use App\Ninja\Repositories\RecurringExpenseRepository;
|
||||
|
||||
/**
|
||||
* Class RecurringExpenseService.
|
||||
*/
|
||||
class RecurringExpenseService extends BaseService
|
||||
{
|
||||
/**
|
||||
* @var RecurringExpenseRepository
|
||||
*/
|
||||
protected $recurringExpenseRepo;
|
||||
|
||||
/**
|
||||
* @var DatatableService
|
||||
*/
|
||||
protected $datatableService;
|
||||
|
||||
/**
|
||||
* CreditService constructor.
|
||||
*
|
||||
* @param RecurringExpenseRepository $creditRepo
|
||||
* @param DatatableService $datatableService
|
||||
*/
|
||||
public function __construct(RecurringExpenseRepository $recurringExpenseRepo, DatatableService $datatableService)
|
||||
{
|
||||
$this->recurringExpenseRepo = $recurringExpenseRepo;
|
||||
$this->datatableService = $datatableService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CreditRepository
|
||||
*/
|
||||
protected function getRepo()
|
||||
{
|
||||
return $this->recurringExpenseRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param mixed $recurringExpense
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function save($data, $recurringExpense = false)
|
||||
{
|
||||
if (isset($data['client_id']) && $data['client_id']) {
|
||||
$data['client_id'] = Client::getPrivateId($data['client_id']);
|
||||
}
|
||||
|
||||
if (isset($data['vendor_id']) && $data['vendor_id']) {
|
||||
$data['vendor_id'] = Vendor::getPrivateId($data['vendor_id']);
|
||||
}
|
||||
|
||||
return $this->recurringExpenseRepo->save($data, $recurringExpense);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $clientPublicId
|
||||
* @param $search
|
||||
* @param mixed $userId
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getDatatable($search, $userId)
|
||||
{
|
||||
$query = $this->recurringExpenseRepo->find($search);
|
||||
|
||||
if (! Utils::hasPermission('view_all')) {
|
||||
$query->where('recurring_expenses.user_id', '=', Auth::user()->id);
|
||||
}
|
||||
|
||||
return $this->datatableService->createDatatable(new RecurringExpenseDatatable(), $query);
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ class UpdateDarkMode extends Migration
|
||||
$table->decimal('amount', 13, 2);
|
||||
$table->text('private_notes');
|
||||
$table->text('public_notes');
|
||||
$table->unsignedInteger('invoice_currency_id')->nullable(false);
|
||||
$table->unsignedInteger('invoice_currency_id')->nullable()->index();
|
||||
$table->unsignedInteger('expense_currency_id')->nullable()->index();
|
||||
$table->boolean('should_be_invoiced')->default(true);
|
||||
$table->unsignedInteger('expense_category_id')->nullable()->index();
|
||||
@ -47,6 +47,11 @@ class UpdateDarkMode extends Migration
|
||||
$table->string('tax_name2')->nullable();
|
||||
$table->decimal('tax_rate2', 13, 3);
|
||||
|
||||
$table->unsignedInteger('frequency_id');
|
||||
$table->date('start_date')->nullable();
|
||||
$table->date('end_date')->nullable();
|
||||
$table->timestamp('last_created_date')->nullable();
|
||||
|
||||
// Relations
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
@ -59,6 +64,10 @@ class UpdateDarkMode extends Migration
|
||||
$table->unique(['account_id', 'public_id']);
|
||||
});
|
||||
|
||||
Schema::table('expenses', function ($table) {
|
||||
$table->unsignedInteger('recurring_expense_id')->nullable();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,5 +78,9 @@ class UpdateDarkMode extends Migration
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('recurring_expenses');
|
||||
|
||||
Schema::table('expenses', function ($table) {
|
||||
$table->dropColumn('recurring_expense_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2272,6 +2272,22 @@ $LANG = array(
|
||||
'update_payment_details' => 'Update payment details',
|
||||
'updated_payment_details' => 'Successfully updated payment details',
|
||||
'update_credit_card' => 'Update Credit Card',
|
||||
'recurring_expenses' => 'Recurring Expenses',
|
||||
'recurring_expense' => 'Recurring Expense',
|
||||
'new_recurring_expense' => 'New Recurring Expense',
|
||||
'edit_recurring_expense' => 'Edit Recurring Expense',
|
||||
'archive_recurring_expense' => 'Archive Recurring Expense',
|
||||
'list_recurring_expense' => 'List Recurring Expenses',
|
||||
'updated_recurring_expense' => 'Successfully updated recurring expense',
|
||||
'created_recurring_expense' => 'Successfully created recurring expense',
|
||||
'archived_recurring_expense' => 'Successfully archived recurring expense',
|
||||
'archived_recurring_expense' => 'Successfully archived :count recurring expenses',
|
||||
'restore_recurring_expense' => 'Restore Recurring Expense',
|
||||
'restored_recurring_expense' => 'Successfully restored recurring expense',
|
||||
'delete_recurring_expense' => 'Delete Recurring Expense',
|
||||
'deleted_recurring_expense' => 'Successfully deleted project',
|
||||
'deleted_recurring_expense' => 'Successfully deleted :count projects',
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
@ -76,74 +76,6 @@
|
||||
->addGroupClass('client-select') !!}
|
||||
@endif
|
||||
|
||||
@if (!$expense || ($expense && !$expense->invoice_id))
|
||||
{!! Former::checkbox('should_be_invoiced')
|
||||
->text(trans('texts.mark_billable'))
|
||||
->data_bind('checked: should_be_invoiced()')
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
@if (! $expense || ! $expense->transaction_id)
|
||||
|
||||
@if (! $expense || ! $expense->isPaid())
|
||||
{!! Former::checkbox('mark_paid')
|
||||
->data_bind('checked: mark_paid')
|
||||
->text(trans('texts.mark_expense_paid'))
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
<div style="display:none" data-bind="visible: mark_paid">
|
||||
{!! Former::select('payment_type_id')
|
||||
->addOption('','')
|
||||
->fromQuery($paymentTypes, 'name', 'id')
|
||||
->addGroupClass('payment-type-select') !!}
|
||||
|
||||
{!! Former::text('payment_date')
|
||||
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
|
||||
->addGroupClass('payment_date')
|
||||
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||
|
||||
{!! Former::text('transaction_reference') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!$expense || ($expense && ! $expense->isExchanged()))
|
||||
{!! Former::checkbox('convert_currency')
|
||||
->text(trans('texts.convert_currency'))
|
||||
->data_bind('checked: convert_currency')
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
|
||||
<div style="display:none" data-bind="visible: enableExchangeRate">
|
||||
<br/>
|
||||
<span style="display:none" data-bind="visible: !client_id()">
|
||||
{!! Former::select('invoice_currency_id')->addOption('','')
|
||||
->label(trans('texts.invoice_currency'))
|
||||
->data_placeholder(Utils::getFromCache($account->getCurrencyId(), 'currencies')->name)
|
||||
->data_bind('combobox: invoice_currency_id, disable: true')
|
||||
->fromQuery($currencies, 'name', 'id') !!}
|
||||
</span>
|
||||
<span style="display:none;" data-bind="visible: client_id">
|
||||
{!! Former::plaintext('')
|
||||
->value('<span data-bind="html: invoiceCurrencyName"></span>')
|
||||
->style('min-height:46px')
|
||||
->label(trans('texts.invoice_currency')) !!}
|
||||
</span>
|
||||
|
||||
{!! Former::text('exchange_rate')
|
||||
->data_bind("value: exchange_rate, enable: enableExchangeRate, valueUpdate: 'afterkeydown'") !!}
|
||||
|
||||
{!! Former::text('invoice_amount')
|
||||
->addGroupClass('converted-amount')
|
||||
->data_bind("value: convertedAmount, enable: enableExchangeRate")
|
||||
->append('<span data-bind="html: invoiceCurrencyCode"></span>') !!}
|
||||
</div>
|
||||
|
||||
|
||||
@if (count($taxRates))
|
||||
@if (!$expense || ($expense && (!$expense->tax_name1 && !$expense->tax_name2)))
|
||||
{!! Former::checkbox('apply_taxes')
|
||||
@ -159,22 +91,110 @@
|
||||
@include('partials.tax_rates')
|
||||
</div>
|
||||
|
||||
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||
{!! Former::checkbox('invoice_documents')
|
||||
->text(trans('texts.add_documents_to_invoice'))
|
||||
->onchange('onInvoiceDocumentsChange()')
|
||||
->data_bind('checked: invoice_documents')
|
||||
@if (!$expense || ($expense && !$expense->invoice_id))
|
||||
{!! Former::checkbox('should_be_invoiced')
|
||||
->text(trans('texts.mark_billable'))
|
||||
->data_bind('checked: should_be_invoiced()')
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
@if ($isRecurring)
|
||||
|
||||
{!! Former::select('frequency_id')
|
||||
->label('frequency')
|
||||
->options(\App\Models\Frequency::selectOptions())
|
||||
->data_bind("value: frequency_id") !!}
|
||||
{!! Former::text('start_date')
|
||||
->data_bind("datePicker: start_date, valueUpdate: 'afterkeydown'")
|
||||
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))
|
||||
->appendIcon('calendar')
|
||||
->addGroupClass('start_date') !!}
|
||||
{!! Former::text('end_date')
|
||||
->data_bind("datePicker: end_date, valueUpdate: 'afterkeydown'")
|
||||
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))
|
||||
->appendIcon('calendar')
|
||||
->addGroupClass('end_date') !!}
|
||||
|
||||
@else
|
||||
@if ((! $expense || ! $expense->transaction_id))
|
||||
|
||||
@if (! $expense || ! $expense->isPaid())
|
||||
{!! Former::checkbox('mark_paid')
|
||||
->data_bind('checked: mark_paid')
|
||||
->text(trans('texts.mark_expense_paid'))
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
<div style="display:none" data-bind="visible: mark_paid">
|
||||
{!! Former::select('payment_type_id')
|
||||
->addOption('','')
|
||||
->fromQuery($paymentTypes, 'name', 'id')
|
||||
->addGroupClass('payment-type-select') !!}
|
||||
|
||||
{!! Former::text('payment_date')
|
||||
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
|
||||
->addGroupClass('payment_date')
|
||||
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
|
||||
|
||||
{!! Former::text('transaction_reference') !!}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (!$expense || ($expense && ! $expense->isExchanged()))
|
||||
{!! Former::checkbox('convert_currency')
|
||||
->text(trans('texts.convert_currency'))
|
||||
->data_bind('checked: convert_currency')
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
|
||||
<div style="display:none" data-bind="visible: enableExchangeRate">
|
||||
<br/>
|
||||
<span style="display:none" data-bind="visible: !client_id()">
|
||||
{!! Former::select('invoice_currency_id')->addOption('','')
|
||||
->label(trans('texts.invoice_currency'))
|
||||
->data_placeholder(Utils::getFromCache($account->getCurrencyId(), 'currencies')->name)
|
||||
->data_bind('combobox: invoice_currency_id, disable: true')
|
||||
->fromQuery($currencies, 'name', 'id') !!}
|
||||
</span>
|
||||
<span style="display:none;" data-bind="visible: client_id">
|
||||
{!! Former::plaintext('')
|
||||
->value('<span data-bind="html: invoiceCurrencyName"></span>')
|
||||
->style('min-height:46px')
|
||||
->label(trans('texts.invoice_currency')) !!}
|
||||
</span>
|
||||
|
||||
{!! Former::text('exchange_rate')
|
||||
->data_bind("value: exchange_rate, enable: enableExchangeRate, valueUpdate: 'afterkeydown'") !!}
|
||||
|
||||
{!! Former::text('invoice_amount')
|
||||
->addGroupClass('converted-amount')
|
||||
->data_bind("value: convertedAmount, enable: enableExchangeRate")
|
||||
->append('<span data-bind="html: invoiceCurrencyCode"></span>') !!}
|
||||
</div>
|
||||
|
||||
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||
{!! Former::checkbox('invoice_documents')
|
||||
->text(trans('texts.add_documents_to_invoice'))
|
||||
->onchange('onInvoiceDocumentsChange()')
|
||||
->data_bind('checked: invoice_documents')
|
||||
->label(' ')
|
||||
->value(1) !!}
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
||||
{!! Former::textarea('public_notes')->rows(6) !!}
|
||||
{!! Former::textarea('private_notes')->rows(6) !!}
|
||||
|
||||
@if ($account->hasFeature(FEATURE_DOCUMENTS))
|
||||
@if (! $isRecurring && $account->hasFeature(FEATURE_DOCUMENTS))
|
||||
<div class="form-group">
|
||||
<label for="public_notes" class="control-label col-lg-4 col-sm-4">
|
||||
{{trans('texts.documents')}}
|
||||
@ -351,78 +371,78 @@
|
||||
$('#amount').focus();
|
||||
@endif
|
||||
|
||||
@if (Auth::user()->account->hasFeature(FEATURE_DOCUMENTS))
|
||||
$('.main-form').submit(function(){
|
||||
if($('#document-upload .fallback input').val())$(this).attr('enctype', 'multipart/form-data')
|
||||
else $(this).removeAttr('enctype')
|
||||
})
|
||||
@if (! $isRecurring && Auth::user()->account->hasFeature(FEATURE_DOCUMENTS))
|
||||
$('.main-form').submit(function(){
|
||||
if($('#document-upload .fallback input').val())$(this).attr('enctype', 'multipart/form-data')
|
||||
else $(this).removeAttr('enctype')
|
||||
})
|
||||
|
||||
$('#payment_type_id').combobox();
|
||||
$('#mark_paid').click(function(event) {
|
||||
if ($('#mark_paid').is(':checked')) {
|
||||
$('#payment_date').datepicker('update', new Date());
|
||||
@if ($account->payment_type_id)
|
||||
setComboboxValue($('.payment-type-select'), {{ $account->payment_type_id }}, "{{ trans('texts.payment_type_' . $account->payment_type->name) }}");
|
||||
@endif
|
||||
} else {
|
||||
$('#payment_date').datepicker('update', false);
|
||||
setComboboxValue($('.payment-type-select'), '', '');
|
||||
}
|
||||
})
|
||||
|
||||
@if ($expense && $expense->payment_date)
|
||||
$('#payment_date').datepicker('update', '{{ Utils::fromSqlDate($expense->payment_date) }}');
|
||||
@endif
|
||||
|
||||
$('.payment_date .input-group-addon').click(function() {
|
||||
toggleDatePicker('payment_date');
|
||||
});
|
||||
|
||||
// Initialize document upload
|
||||
dropzone = new Dropzone('#document-upload', {
|
||||
url:{!! json_encode(url('documents')) !!},
|
||||
params:{
|
||||
_token:"{{ Session::getToken() }}"
|
||||
},
|
||||
acceptedFiles:{!! json_encode(implode(',',\App\Models\Document::$allowedMimes)) !!},
|
||||
addRemoveLinks:true,
|
||||
dictRemoveFileConfirmation:"{{trans('texts.are_you_sure')}}",
|
||||
@foreach(['default_message', 'fallback_message', 'fallback_text', 'file_too_big', 'invalid_file_type', 'response_error', 'cancel_upload', 'cancel_upload_confirmation', 'remove_file'] as $key)
|
||||
"dict{{strval($key)}}":"{{trans('texts.dropzone_'.Utils::toClassCase($key))}}",
|
||||
@endforeach
|
||||
maxFilesize:{{floatval(MAX_DOCUMENT_SIZE/1000)}},
|
||||
});
|
||||
if(dropzone instanceof Dropzone){
|
||||
dropzone.on("addedfile",handleDocumentAdded);
|
||||
dropzone.on("removedfile",handleDocumentRemoved);
|
||||
dropzone.on("success",handleDocumentUploaded);
|
||||
dropzone.on("canceled",handleDocumentCanceled);
|
||||
dropzone.on("error",handleDocumentError);
|
||||
for (var i=0; i<model.documents().length; i++) {
|
||||
var document = model.documents()[i];
|
||||
var mockFile = {
|
||||
name:document.name(),
|
||||
size:document.size(),
|
||||
type:document.type(),
|
||||
public_id:document.public_id(),
|
||||
status:Dropzone.SUCCESS,
|
||||
accepted:true,
|
||||
url:document.url(),
|
||||
mock:true,
|
||||
index:i
|
||||
};
|
||||
|
||||
dropzone.emit('addedfile', mockFile);
|
||||
dropzone.emit('complete', mockFile);
|
||||
if(document.preview_url()){
|
||||
dropzone.emit('thumbnail', mockFile, document.preview_url()||document.url());
|
||||
$('#payment_type_id').combobox();
|
||||
$('#mark_paid').click(function(event) {
|
||||
if ($('#mark_paid').is(':checked')) {
|
||||
$('#payment_date').datepicker('update', new Date());
|
||||
@if ($account->payment_type_id)
|
||||
setComboboxValue($('.payment-type-select'), {{ $account->payment_type_id }}, "{{ trans('texts.payment_type_' . $account->payment_type->name) }}");
|
||||
@endif
|
||||
} else {
|
||||
$('#payment_date').datepicker('update', false);
|
||||
setComboboxValue($('.payment-type-select'), '', '');
|
||||
}
|
||||
else if(document.type()=='jpeg' || document.type()=='png' || document.type()=='svg'){
|
||||
dropzone.emit('thumbnail', mockFile, document.url());
|
||||
})
|
||||
|
||||
@if ($expense && $expense->payment_date)
|
||||
$('#payment_date').datepicker('update', '{{ Utils::fromSqlDate($expense->payment_date) }}');
|
||||
@endif
|
||||
|
||||
$('.payment_date .input-group-addon').click(function() {
|
||||
toggleDatePicker('payment_date');
|
||||
});
|
||||
|
||||
// Initialize document upload
|
||||
dropzone = new Dropzone('#document-upload', {
|
||||
url:{!! json_encode(url('documents')) !!},
|
||||
params:{
|
||||
_token:"{{ Session::getToken() }}"
|
||||
},
|
||||
acceptedFiles:{!! json_encode(implode(',',\App\Models\Document::$allowedMimes)) !!},
|
||||
addRemoveLinks:true,
|
||||
dictRemoveFileConfirmation:"{{trans('texts.are_you_sure')}}",
|
||||
@foreach(['default_message', 'fallback_message', 'fallback_text', 'file_too_big', 'invalid_file_type', 'response_error', 'cancel_upload', 'cancel_upload_confirmation', 'remove_file'] as $key)
|
||||
"dict{{strval($key)}}":"{{trans('texts.dropzone_'.Utils::toClassCase($key))}}",
|
||||
@endforeach
|
||||
maxFilesize:{{floatval(MAX_DOCUMENT_SIZE/1000)}},
|
||||
});
|
||||
if(dropzone instanceof Dropzone){
|
||||
dropzone.on("addedfile",handleDocumentAdded);
|
||||
dropzone.on("removedfile",handleDocumentRemoved);
|
||||
dropzone.on("success",handleDocumentUploaded);
|
||||
dropzone.on("canceled",handleDocumentCanceled);
|
||||
dropzone.on("error",handleDocumentError);
|
||||
for (var i=0; i<model.documents().length; i++) {
|
||||
var document = model.documents()[i];
|
||||
var mockFile = {
|
||||
name:document.name(),
|
||||
size:document.size(),
|
||||
type:document.type(),
|
||||
public_id:document.public_id(),
|
||||
status:Dropzone.SUCCESS,
|
||||
accepted:true,
|
||||
url:document.url(),
|
||||
mock:true,
|
||||
index:i
|
||||
};
|
||||
|
||||
dropzone.emit('addedfile', mockFile);
|
||||
dropzone.emit('complete', mockFile);
|
||||
if(document.preview_url()){
|
||||
dropzone.emit('thumbnail', mockFile, document.preview_url()||document.url());
|
||||
}
|
||||
else if(document.type()=='jpeg' || document.type()=='png' || document.type()=='svg'){
|
||||
dropzone.emit('thumbnail', mockFile, document.url());
|
||||
}
|
||||
dropzone.files.push(mockFile);
|
||||
}
|
||||
dropzone.files.push(mockFile);
|
||||
}
|
||||
}
|
||||
@endif
|
||||
});
|
||||
|
||||
@ -435,10 +455,13 @@
|
||||
self.amount = ko.observable();
|
||||
self.exchange_rate = ko.observable(1);
|
||||
self.should_be_invoiced = ko.observable();
|
||||
self.mark_paid = ko.observable({{ $expense && $expense->isPaid() ? 'true' : 'false' }});
|
||||
self.convert_currency = ko.observable({{ ($expense && $expense->isExchanged()) ? 'true' : 'false' }});
|
||||
self.apply_taxes = ko.observable({{ ($expense && ($expense->tax_name1 || $expense->tax_name2)) ? 'true' : 'false' }});
|
||||
|
||||
@if (! $isRecurring)
|
||||
self.convert_currency = ko.observable({{ ($expense && $expense->isExchanged()) ? 'true' : 'false' }});
|
||||
self.mark_paid = ko.observable({{ $expense && $expense->isPaid() ? 'true' : 'false' }});
|
||||
@endif
|
||||
|
||||
var invoiceDocuments = false;
|
||||
if (isStorageSupported()) {
|
||||
invoiceDocuments = localStorage.getItem('last:invoice_documents');
|
||||
@ -489,7 +512,7 @@
|
||||
});
|
||||
|
||||
self.enableExchangeRate = ko.computed(function() {
|
||||
if (self.convert_currency()) {
|
||||
if (self.convert_currency && self.convert_currency()) {
|
||||
return true;
|
||||
}
|
||||
var expenseCurrencyId = self.expense_currency_id() || self.account_currency_id();
|
||||
|
Loading…
Reference in New Issue
Block a user