From e7bf0599dbbad7e32df1cbe5c2c0d185acb5d0ab Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 23 May 2016 19:52:20 +0300 Subject: [PATCH] Separated out entity datatable classes --- app/Http/Controllers/ClientController.php | 19 +- app/Models/User.php | 34 +-- .../Datatables/AccountGatewayDatatable.php | 110 ++++++++++ app/Ninja/Datatables/ActivityDatatable.php | 52 +++++ app/Ninja/Datatables/BankAccountDatatable.php | 42 ++++ app/Ninja/Datatables/ClientDatatable.php | 136 ++++++++++++ app/Ninja/Datatables/CreditDatatable.php | 66 ++++++ app/Ninja/Datatables/EntityDatatable.php | 24 +++ app/Ninja/Datatables/ExpenseDatatable.php | 132 ++++++++++++ app/Ninja/Datatables/InvoiceDatatable.php | 193 ++++++++++++++++++ app/Ninja/Datatables/PaymentDatatable.php | 152 ++++++++++++++ app/Ninja/Datatables/ProductDatatable.php | 55 +++++ .../Datatables/RecurringInvoiceDatatable.php | 63 ++++++ app/Ninja/Datatables/TaskDatatable.php | 113 ++++++++++ app/Ninja/Datatables/TaxRateDatatable.php | 41 ++++ app/Ninja/Datatables/TokenDatatable.php | 41 ++++ app/Ninja/Datatables/UserDatatable.php | 96 +++++++++ app/Ninja/Datatables/VendorDatatable.php | 79 +++++++ app/Ninja/Repositories/ClientRepository.php | 14 +- app/Services/AccountGatewayService.php | 110 +--------- app/Services/ActivityService.php | 46 +---- app/Services/BankAccountService.php | 35 +--- app/Services/BaseService.php | 17 -- app/Services/ClientService.php | 135 +----------- app/Services/CreditService.php | 66 +----- app/Services/DatatableService.php | 43 ++-- app/Services/ExpenseService.php | 122 +---------- app/Services/InvoiceService.php | 185 +---------------- app/Services/PaymentService.php | 173 ++-------------- app/Services/PaymentTermService.php | 8 +- app/Services/ProductService.php | 50 +---- app/Services/RecurringInvoiceService.php | 59 +----- app/Services/TaskService.php | 105 +--------- app/Services/TaxRateService.php | 45 +--- app/Services/TokenService.php | 43 +--- app/Services/UserService.php | 97 +-------- app/Services/VendorService.php | 70 +------ 37 files changed, 1536 insertions(+), 1335 deletions(-) create mode 100644 app/Ninja/Datatables/AccountGatewayDatatable.php create mode 100644 app/Ninja/Datatables/ActivityDatatable.php create mode 100644 app/Ninja/Datatables/BankAccountDatatable.php create mode 100644 app/Ninja/Datatables/ClientDatatable.php create mode 100644 app/Ninja/Datatables/CreditDatatable.php create mode 100644 app/Ninja/Datatables/EntityDatatable.php create mode 100644 app/Ninja/Datatables/ExpenseDatatable.php create mode 100644 app/Ninja/Datatables/InvoiceDatatable.php create mode 100644 app/Ninja/Datatables/PaymentDatatable.php create mode 100644 app/Ninja/Datatables/ProductDatatable.php create mode 100644 app/Ninja/Datatables/RecurringInvoiceDatatable.php create mode 100644 app/Ninja/Datatables/TaskDatatable.php create mode 100644 app/Ninja/Datatables/TaxRateDatatable.php create mode 100644 app/Ninja/Datatables/TokenDatatable.php create mode 100644 app/Ninja/Datatables/UserDatatable.php create mode 100644 app/Ninja/Datatables/VendorDatatable.php diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index e5b6fd432b1a..d2a0633e5c73 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -72,7 +72,10 @@ class ClientController extends BaseController public function getDatatable() { - return $this->clientService->getDatatable(Input::get('sSearch')); + $search = Input::get('sSearch'); + $userId = Auth::user()->filterId(); + + return $this->clientService->getDatatable($search, $userId); } /** @@ -97,8 +100,8 @@ class ClientController extends BaseController */ public function show(ClientRequest $request) { - $client = $request->entity(); - + $client = $request->entity(); + $user = Auth::user(); Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT); @@ -109,19 +112,19 @@ class ClientController extends BaseController if (Utils::hasFeature(FEATURE_QUOTES) && $user->can('create', ENTITY_INVOICE)) { $actionLinks[] = ['label' => trans('texts.new_quote'), 'url' => URL::to('/quotes/create/'.$client->public_id)]; } - + if(!empty($actionLinks)){ $actionLinks[] = \DropdownButton::DIVIDER; } - + if($user->can('create', ENTITY_PAYMENT)){ $actionLinks[] = ['label' => trans('texts.enter_payment'), 'url' => URL::to('/payments/create/'.$client->public_id)]; } - + if($user->can('create', ENTITY_CREDIT)){ $actionLinks[] = ['label' => trans('texts.enter_credit'), 'url' => URL::to('/credits/create/'.$client->public_id)]; } - + if($user->can('create', ENTITY_EXPENSE)){ $actionLinks[] = ['label' => trans('texts.enter_expense'), 'url' => URL::to('/expenses/create/0/'.$client->public_id)]; } @@ -174,7 +177,7 @@ class ClientController extends BaseController public function edit(ClientRequest $request) { $client = $request->entity(); - + $data = [ 'client' => $client, 'method' => 'PUT', diff --git a/app/Models/User.php b/app/Models/User.php index 71069d25821c..9dab5e759a15 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -20,8 +20,8 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac 'create_all' => 0b0001, 'view_all' => 0b0010, 'edit_all' => 0b0100, - ); - + ); + use Authenticatable, Authorizable, CanResetPassword; /** @@ -168,7 +168,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac { return Session::get(SESSION_COUNTER, 0); } - + public function afterSave($success = true, $forced = false) { if ($this->email) { @@ -199,8 +199,8 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac return MAX_NUM_VENDORS; } - - + + public function getRememberToken() { return $this->remember_token; @@ -265,9 +265,9 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac && $this->email != $this->getOriginal('email') && $this->getOriginal('confirmed'); } - - - + + + /** * Set the permissions attribute on the model. * @@ -277,7 +277,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac protected function setPermissionsAttribute($value){ if(empty($value)) { $this->attributes['permissions'] = 0; - } else { + } else { $bitmask = 0; foreach($value as $permission){ $bitmask = $bitmask | static::$all_permissions[$permission]; @@ -285,10 +285,10 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac $this->attributes['permissions'] = $bitmask; } - + return $this; } - + /** * Expands the value of the permissions attribute * @@ -302,10 +302,10 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac $permissions[$permission] = $permission; } } - + return $permissions; } - + /** * Checks to see if the user has the required permission * @@ -325,13 +325,17 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac return count(array_intersect($permission, $this->permissions)) > 0; } } - + return false; } - + public function owns($entity) { return !empty($entity->user_id) && $entity->user_id == $this->id; } + + public function filterId() { + return $this->hasPermission('view_all') ? false : $this->id; + } } User::updating(function ($user) { diff --git a/app/Ninja/Datatables/AccountGatewayDatatable.php b/app/Ninja/Datatables/AccountGatewayDatatable.php new file mode 100644 index 000000000000..ad16fc39878a --- /dev/null +++ b/app/Ninja/Datatables/AccountGatewayDatatable.php @@ -0,0 +1,110 @@ +deleted_at) { + return $model->name; + } elseif ($model->gateway_id != GATEWAY_WEPAY) { + return link_to("gateways/{$model->public_id}/edit", $model->name)->toHtml(); + } else { + $accountGateway = AccountGateway::find($model->id); + $config = $accountGateway->getConfig(); + $endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/'; + $wepayAccountId = $config->accountId; + $wepayState = isset($config->state)?$config->state:null; + $linkText = $model->name; + $url = $endpoint.'account/'.$wepayAccountId; + $wepay = \Utils::setupWepay($accountGateway); + $html = link_to($url, $linkText, array('target'=>'_blank'))->toHtml(); + + try { + if ($wepayState == 'action_required') { + $updateUri = $wepay->request('/account/get_update_uri', array( + 'account_id' => $wepayAccountId, + 'redirect_uri' => URL::to('gateways'), + )); + + $linkText .= ' ('.trans('texts.action_required').')'; + $url = $updateUri->uri; + $html = "{$linkText}"; + $model->setupUrl = $url; + } elseif ($wepayState == 'pending') { + $linkText .= ' ('.trans('texts.resend_confirmation_email').')'; + $model->resendConfirmationUrl = $url = URL::to("gateways/{$accountGateway->public_id}/resend_confirmation"); + $html = link_to($url, $linkText)->toHtml(); + } + } catch(\WePayException $ex){} + + return $html; + } + } + ], + [ + 'payment_type', + function ($model) { + return Gateway::getPrettyPaymentType($model->gateway_id); + } + ], + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.resend_confirmation_email'), + function ($model) { + return $model->resendConfirmationUrl; + }, + function($model) { + return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY && !empty($model->resendConfirmationUrl); + } + ], [ + uctrans('texts.finish_setup'), + function ($model) { + return $model->setupUrl; + }, + function($model) { + return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY && !empty($model->setupUrl); + } + ] , [ + uctrans('texts.edit_gateway'), + function ($model) { + return URL::to("gateways/{$model->public_id}/edit"); + }, + function($model) { + return !$model->deleted_at; + } + ], [ + uctrans('texts.manage_wepay_account'), + function ($model) { + $accountGateway = AccountGateway::find($model->id); + $endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/'; + return array( + 'url' => $endpoint.'account/'.$accountGateway->getConfig()->accountId, + 'attributes' => 'target="_blank"' + ); + }, + function($model) { + return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY; + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/ActivityDatatable.php b/app/Ninja/Datatables/ActivityDatatable.php new file mode 100644 index 000000000000..5f74bbbe54fb --- /dev/null +++ b/app/Ninja/Datatables/ActivityDatatable.php @@ -0,0 +1,52 @@ +created_at)); + } + ], + [ + 'activity_type_id', + function ($model) { + $data = [ + 'client' => link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model))->toHtml(), + 'user' => $model->is_system ? '' . trans('texts.system') . '' : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email), + 'invoice' => $model->invoice ? link_to('/invoices/' . $model->invoice_public_id, $model->is_recurring ? trans('texts.recurring_invoice') : $model->invoice)->toHtml() : null, + 'quote' => $model->invoice ? link_to('/quotes/' . $model->invoice_public_id, $model->invoice)->toHtml() : null, + 'contact' => $model->contact_id ? link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model))->toHtml() : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email), + 'payment' => $model->payment ?: '', + 'credit' => $model->payment_amount ? Utils::formatMoney($model->credit, $model->currency_id, $model->country_id) : '', + 'payment_amount' => $model->payment_amount ? Utils::formatMoney($model->payment_amount, $model->currency_id, $model->country_id) : null, + 'adjustment' => $model->adjustment ? Utils::formatMoney($model->adjustment, $model->currency_id, $model->country_id) : null + ]; + + return trans("texts.activity_{$model->activity_type_id}", $data); + } + ], + [ + 'balance', + function ($model) { + return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); + } + ], + [ + 'adjustment', + function ($model) { + return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id, $model->country_id) : ''; + } + ] + ]; + } +} diff --git a/app/Ninja/Datatables/BankAccountDatatable.php b/app/Ninja/Datatables/BankAccountDatatable.php new file mode 100644 index 000000000000..48bc2672f1c9 --- /dev/null +++ b/app/Ninja/Datatables/BankAccountDatatable.php @@ -0,0 +1,42 @@ +public_id}/edit", $model->bank_name)->toHtml(); + }, + ], + [ + 'bank_library_id', + function ($model) { + return 'OFX'; + } + ], + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.edit_bank_account'), + function ($model) { + return URL::to("bank_accounts/{$model->public_id}/edit"); + }, + ] + ]; + } + + +} diff --git a/app/Ninja/Datatables/ClientDatatable.php b/app/Ninja/Datatables/ClientDatatable.php new file mode 100644 index 000000000000..4b0ca68b0544 --- /dev/null +++ b/app/Ninja/Datatables/ClientDatatable.php @@ -0,0 +1,136 @@ +public_id}", $model->name ?: '')->toHtml(); + } + ], + [ + 'first_name', + function ($model) { + return link_to("clients/{$model->public_id}", $model->first_name.' '.$model->last_name)->toHtml(); + } + ], + [ + 'email', + function ($model) { + return link_to("clients/{$model->public_id}", $model->email ?: '')->toHtml(); + } + ], + [ + 'clients.created_at', + function ($model) { + return Utils::timestampToDateString(strtotime($model->created_at)); + } + ], + [ + 'last_login', + function ($model) { + return Utils::timestampToDateString(strtotime($model->last_login)); + } + ], + [ + 'balance', + function ($model) { + return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); + } + ] + ]; + } + + public function actions() + { + return [ + [ + trans('texts.edit_client'), + function ($model) { + return URL::to("clients/{$model->public_id}/edit"); + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_CLIENT, $model->user_id]); + } + ], + [ + '--divider--', function(){return false;}, + function ($model) { + $user = Auth::user(); + return $user->can('editByOwner', [ENTITY_CLIENT, $model->user_id]) && ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE)); + } + ], + [ + trans('texts.new_task'), + function ($model) { + return URL::to("tasks/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_TASK); + } + ], + [ + trans('texts.new_invoice'), + function ($model) { + return URL::to("invoices/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_INVOICE); + } + ], + [ + trans('texts.new_quote'), + function ($model) { + return URL::to("quotes/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->hasFeature(FEATURE_QUOTES) && Auth::user()->can('create', ENTITY_INVOICE); + } + ], + [ + '--divider--', function(){return false;}, + function ($model) { + $user = Auth::user(); + return ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE)) && ($user->can('create', ENTITY_PAYMENT) || $user->can('create', ENTITY_CREDIT) || $user->can('create', ENTITY_EXPENSE)); + } + ], + [ + trans('texts.enter_payment'), + function ($model) { + return URL::to("payments/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_PAYMENT); + } + ], + [ + trans('texts.enter_credit'), + function ($model) { + return URL::to("credits/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_CREDIT); + } + ], + [ + trans('texts.enter_expense'), + function ($model) { + return URL::to("expenses/create/0/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_EXPENSE); + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/CreditDatatable.php b/app/Ninja/Datatables/CreditDatatable.php new file mode 100644 index 000000000000..7f258e377d1d --- /dev/null +++ b/app/Ninja/Datatables/CreditDatatable.php @@ -0,0 +1,66 @@ +can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ + return Utils::getClientDisplayName($model); + } + + return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; + }, + ! $this->hideClient + ], + [ + 'amount', + function ($model) { + return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id) . ''; + } + ], + [ + 'balance', + function ($model) { + return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); + } + ], + [ + 'credit_date', + function ($model) { + return Utils::fromSqlDate($model->credit_date); + } + ], + [ + 'private_notes', + function ($model) { + return $model->private_notes; + } + ] + ]; + } + + public function actions() + { + return [ + [ + trans('texts.apply_credit'), + function ($model) { + return URL::to("payments/create/{$model->client_public_id}") . '?paymentTypeId=1'; + }, + function ($model) { + return Auth::user()->can('create', ENTITY_PAYMENT); + } + ] + ]; + } +} diff --git a/app/Ninja/Datatables/EntityDatatable.php b/app/Ninja/Datatables/EntityDatatable.php new file mode 100644 index 000000000000..085645ff2069 --- /dev/null +++ b/app/Ninja/Datatables/EntityDatatable.php @@ -0,0 +1,24 @@ +isBulkEdit = $isBulkEdit; + $this->hideClient = $hideClient; + } + + public function columns() + { + return []; + } + + public function actions() + { + return []; + } +} diff --git a/app/Ninja/Datatables/ExpenseDatatable.php b/app/Ninja/Datatables/ExpenseDatatable.php new file mode 100644 index 000000000000..70cc771afe2b --- /dev/null +++ b/app/Ninja/Datatables/ExpenseDatatable.php @@ -0,0 +1,132 @@ +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 ''; + } + } + ], + [ + '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 ''; + } + } + ], + [ + 'expense_date', + function ($model) { + if(!Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id])){ + return Utils::fromSqlDate($model->expense_date); + } + + return link_to("expenses/{$model->public_id}/edit", Utils::fromSqlDate($model->expense_date))->toHtml(); + } + ], + [ + 'amount', + function ($model) { + // show both the amount and the converted amount + if ($model->exchange_rate != 1) { + $converted = round($model->amount * $model->exchange_rate, 2); + return Utils::formatMoney($model->amount, $model->expense_currency_id) . ' | ' . + Utils::formatMoney($converted, $model->invoice_currency_id); + } else { + return Utils::formatMoney($model->amount, $model->expense_currency_id); + } + } + ], + [ + 'public_notes', + function ($model) { + return $model->public_notes != null ? substr($model->public_notes, 0, 100) : ''; + } + ], + [ + 'expense_status_id', + function ($model) { + return self::getStatusLabel($model->invoice_id, $model->should_be_invoiced); + } + ], + ]; + } + + public function actions() + { + return [ + [ + trans('texts.edit_expense'), + function ($model) { + return URL::to("expenses/{$model->public_id}/edit") ; + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id]); + } + ], + [ + trans('texts.view_invoice'), + function ($model) { + return URL::to("/invoices/{$model->invoice_public_id}/edit"); + }, + function ($model) { + return $model->invoice_public_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]); + } + ], + [ + trans('texts.invoice_expense'), + function ($model) { + return "javascript:invoiceEntity({$model->public_id})"; + }, + function ($model) { + return ! $model->invoice_id && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE); + } + ], + ]; + } + + + private function getStatusLabel($invoiceId, $shouldBeInvoiced) + { + if ($invoiceId) { + $label = trans('texts.invoiced'); + $class = 'success'; + } elseif ($shouldBeInvoiced) { + $label = trans('texts.pending'); + $class = 'warning'; + } else { + $label = trans('texts.logged'); + $class = 'primary'; + } + + return "

$label

"; + } + +} diff --git a/app/Ninja/Datatables/InvoiceDatatable.php b/app/Ninja/Datatables/InvoiceDatatable.php new file mode 100644 index 000000000000..27b3343561fd --- /dev/null +++ b/app/Ninja/Datatables/InvoiceDatatable.php @@ -0,0 +1,193 @@ +entityType; + + return [ + [ + 'invoice_number', + function ($model) use ($entityType) { + if(!Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id])){ + return $model->invoice_number; + } + + return link_to("{$entityType}s/{$model->public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml(); + } + ], + [ + 'client_name', + function ($model) { + 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(); + }, + ! $this->hideClient + ], + [ + 'invoice_date', + function ($model) { + return Utils::fromSqlDate($model->invoice_date); + } + ], + [ + 'amount', + function ($model) { + return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); + } + ], + [ + 'balance', + function ($model) { + return $model->partial > 0 ? + trans('texts.partial_remaining', [ + 'partial' => Utils::formatMoney($model->partial, $model->currency_id, $model->country_id), + 'balance' => Utils::formatMoney($model->balance, $model->currency_id, $model->country_id)] + ) : + Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); + }, + $entityType == ENTITY_INVOICE + ], + [ + 'due_date', + function ($model) { + return Utils::fromSqlDate($model->due_date); + }, + ], + [ + 'invoice_status_name', + function ($model) use ($entityType) { + return $model->quote_invoice_id ? link_to("invoices/{$model->quote_invoice_id}/edit", trans('texts.converted'))->toHtml() : self::getStatusLabel($model); + } + ] + ]; + } + + public function actions() + { + $entityType = $this->entityType; + + return [ + [ + trans("texts.edit_{$entityType}"), + function ($model) use ($entityType) { + return URL::to("{$entityType}s/{$model->public_id}/edit"); + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ], + [ + trans("texts.clone_{$entityType}"), + function ($model) use ($entityType) { + return URL::to("{$entityType}s/{$model->public_id}/clone"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_INVOICE); + } + ], + [ + trans("texts.view_history"), + function ($model) use ($entityType) { + return URL::to("{$entityType}s/{$entityType}_history/{$model->public_id}"); + } + ], + [ + '--divider--', function(){return false;}, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]) || Auth::user()->can('create', ENTITY_PAYMENT); + } + ], + [ + trans("texts.mark_sent"), + function ($model) { + return "javascript:markEntity({$model->public_id})"; + }, + function ($model) { + return $model->invoice_status_id < INVOICE_STATUS_SENT && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ], + [ + trans('texts.enter_payment'), + function ($model) { + return URL::to("payments/create/{$model->client_public_id}/{$model->public_id}"); + }, + function ($model) use ($entityType) { + return $entityType == ENTITY_INVOICE && $model->balance > 0 && Auth::user()->can('create', ENTITY_PAYMENT); + } + ], + [ + trans("texts.view_quote"), + function ($model) { + return URL::to("quotes/{$model->quote_id}/edit"); + }, + function ($model) use ($entityType) { + return $entityType == ENTITY_INVOICE && $model->quote_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ], + [ + trans("texts.view_invoice"), + function ($model) { + return URL::to("invoices/{$model->quote_invoice_id}/edit"); + }, + function ($model) use ($entityType) { + return $entityType == ENTITY_QUOTE && $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ], + [ + trans("texts.convert_to_invoice"), + function ($model) { + return "javascript:convertEntity({$model->public_id})"; + }, + function ($model) use ($entityType) { + return $entityType == ENTITY_QUOTE && ! $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ] + ]; + } + + private function getStatusLabel($model) + { + $entityType = $this->entityType; + + // check if invoice is overdue + if (Utils::parseFloat($model->balance) && $model->due_date && $model->due_date != '0000-00-00') { + if (\DateTime::createFromFormat('Y-m-d', $model->due_date) < new \DateTime("now")) { + $label = $entityType == ENTITY_INVOICE ? trans('texts.overdue') : trans('texts.expired'); + return "

" . $label . "

"; + } + } + + $label = trans("texts.status_" . strtolower($model->invoice_status_name)); + $class = 'default'; + switch ($model->invoice_status_id) { + case INVOICE_STATUS_SENT: + $class = 'info'; + break; + case INVOICE_STATUS_VIEWED: + $class = 'warning'; + break; + case INVOICE_STATUS_APPROVED: + $class = 'success'; + break; + case INVOICE_STATUS_PARTIAL: + $class = 'primary'; + break; + case INVOICE_STATUS_PAID: + $class = 'success'; + break; + } + + return "

$label

"; + } + +} diff --git a/app/Ninja/Datatables/PaymentDatatable.php b/app/Ninja/Datatables/PaymentDatatable.php new file mode 100644 index 000000000000..4ca1d2839fc8 --- /dev/null +++ b/app/Ninja/Datatables/PaymentDatatable.php @@ -0,0 +1,152 @@ +can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id])){ + return $model->invoice_number; + } + + return link_to("invoices/{$model->invoice_public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml(); + } + ], + [ + 'client_name', + function ($model) { + if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ + return Utils::getClientDisplayName($model); + } + + return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; + }, + ! $this->hideClient + ], + [ + 'transaction_reference', + function ($model) { + return $model->transaction_reference ? $model->transaction_reference : 'Manual entry'; + } + ], + [ + 'payment_type', + function ($model) { + return ($model->payment_type && !$model->last4) ? $model->payment_type : ($model->account_gateway_id ? $model->gateway_name : ''); + } + ], + [ + 'source', + function ($model) { + $code = str_replace(' ', '', strtolower($model->payment_type)); + $card_type = trans("texts.card_" . $code); + if ($model->payment_type_id != PAYMENT_TYPE_ACH) { + if($model->last4) { + $expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y'))); + return '' . htmlentities($card_type) . '  •••' . $model->last4 . ' ' . $expiration; + } elseif ($model->email) { + return $model->email; + } + } elseif ($model->last4) { + $bankData = PaymentMethod::lookupBankData($model->routing_number); + if (is_object($bankData)) { + return $bankData->name.'  •••' . $model->last4; + } elseif($model->last4) { + return '' . htmlentities($card_type) . '  •••' . $model->last4; + } + } + } + ], + [ + 'amount', + function ($model) { + return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); + } + ], + [ + 'payment_date', + function ($model) { + return Utils::dateToString($model->payment_date); + } + ], + [ + 'payment_status_name', + function ($model) { + return self::getStatusLabel($model); + } + ] + ]; + } + + + public function actions() + { + return [ + [ + trans('texts.edit_payment'), + function ($model) { + return URL::to("payments/{$model->public_id}/edit"); + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_PAYMENT, $model->user_id]); + } + ], + [ + trans('texts.refund_payment'), + function ($model) { + $max_refund = number_format($model->amount - $model->refunded, 2); + $formatted = Utils::formatMoney($max_refund, $model->currency_id, $model->country_id); + $symbol = Utils::getFromCache($model->currency_id ? $model->currency_id : 1, 'currencies')->symbol ; + return "javascript:showRefundModal({$model->public_id}, '{$max_refund}', '{$formatted}', '{$symbol}')"; + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_PAYMENT, $model->user_id]) && $model->payment_status_id >= PAYMENT_STATUS_COMPLETED && + $model->refunded < $model->amount && + ( + ($model->transaction_reference && in_array($model->gateway_id , static::$refundableGateways)) + || $model->payment_type_id == PAYMENT_TYPE_CREDIT + ); + } + ] + ]; + } + + private function getStatusLabel($model) + { + $label = trans("texts.status_" . strtolower($model->payment_status_name)); + $class = 'default'; + switch ($model->payment_status_id) { + case PAYMENT_STATUS_PENDING: + $class = 'info'; + break; + case PAYMENT_STATUS_COMPLETED: + $class = 'success'; + break; + case PAYMENT_STATUS_FAILED: + $class = 'danger'; + break; + case PAYMENT_STATUS_PARTIALLY_REFUNDED: + $label = trans('texts.status_partially_refunded_amount', [ + 'amount' => Utils::formatMoney($model->refunded, $model->currency_id, $model->country_id), + ]); + $class = 'primary'; + break; + case PAYMENT_STATUS_VOIDED: + case PAYMENT_STATUS_REFUNDED: + $class = 'default'; + break; + } + return "

$label

"; + } +} diff --git a/app/Ninja/Datatables/ProductDatatable.php b/app/Ninja/Datatables/ProductDatatable.php new file mode 100644 index 000000000000..a5b3cbfc218d --- /dev/null +++ b/app/Ninja/Datatables/ProductDatatable.php @@ -0,0 +1,55 @@ +public_id.'/edit', $model->product_key)->toHtml(); + } + ], + [ + 'notes', + function ($model) { + return nl2br(Str::limit($model->notes, 100)); + } + ], + [ + 'cost', + function ($model) { + return Utils::formatMoney($model->cost); + } + ], + [ + 'tax_rate', + function ($model) { + return $model->tax_rate ? ($model->tax_name . ' ' . $model->tax_rate . '%') : ''; + }, + Auth::user()->account->invoice_item_taxes + ] + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.edit_product'), + function ($model) { + return URL::to("products/{$model->public_id}/edit"); + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/RecurringInvoiceDatatable.php b/app/Ninja/Datatables/RecurringInvoiceDatatable.php new file mode 100644 index 000000000000..7b5365814eca --- /dev/null +++ b/app/Ninja/Datatables/RecurringInvoiceDatatable.php @@ -0,0 +1,63 @@ +public_id}", $model->frequency)->toHtml(); + } + ], + [ + 'client_name', + function ($model) { + return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml(); + }, + ! $this->hideClient + ], + [ + 'start_date', + function ($model) { + return Utils::fromSqlDate($model->start_date); + } + ], + [ + 'end_date', + function ($model) { + return Utils::fromSqlDate($model->end_date); + } + ], + [ + 'amount', + function ($model) { + return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); + } + ] + ]; + } + + public function actions() + { + return [ + [ + trans('texts.edit_invoice'), + function ($model) { + return URL::to("invoices/{$model->public_id}/edit"); + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/TaskDatatable.php b/app/Ninja/Datatables/TaskDatatable.php new file mode 100644 index 000000000000..6f460b418e86 --- /dev/null +++ b/app/Ninja/Datatables/TaskDatatable.php @@ -0,0 +1,113 @@ +can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ + return Utils::getClientDisplayName($model); + } + + return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; + }, + ! $this->hideClient + ], + [ + 'created_at', + function ($model) { + return link_to("tasks/{$model->public_id}/edit", Task::calcStartTime($model))->toHtml(); + } + ], + [ + 'time_log', + function($model) { + return Utils::formatTime(Task::calcDuration($model)); + } + ], + [ + 'description', + function ($model) { + return $model->description; + } + ], + [ + 'invoice_number', + function ($model) { + return self::getStatusLabel($model); + } + ] + ]; + } + + public function actions() + { + return [ + [ + trans('texts.edit_task'), + function ($model) { + return URL::to('tasks/'.$model->public_id.'/edit'); + }, + function ($model) { + return (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]); + } + ], + [ + trans('texts.view_invoice'), + function ($model) { + return URL::to("/invoices/{$model->invoice_public_id}/edit"); + }, + function ($model) { + return $model->invoice_number && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]); + } + ], + [ + trans('texts.stop_task'), + function ($model) { + return "javascript:stopTask({$model->public_id})"; + }, + function ($model) { + return $model->is_running && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]); + } + ], + [ + trans('texts.invoice_task'), + function ($model) { + return "javascript:invoiceEntity({$model->public_id})"; + }, + function ($model) { + return ! $model->invoice_number && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE); + } + ] + ]; + } + + private function getStatusLabel($model) + { + if ($model->invoice_number) { + $class = 'success'; + $label = trans('texts.invoiced'); + } elseif ($model->is_running) { + $class = 'primary'; + $label = trans('texts.running'); + } else { + $class = 'default'; + $label = trans('texts.logged'); + } + + return "

$label

"; + } + + +} diff --git a/app/Ninja/Datatables/TaxRateDatatable.php b/app/Ninja/Datatables/TaxRateDatatable.php new file mode 100644 index 000000000000..d6cb0cb54f03 --- /dev/null +++ b/app/Ninja/Datatables/TaxRateDatatable.php @@ -0,0 +1,41 @@ +public_id}/edit", $model->name)->toHtml(); + } + ], + [ + 'rate', + function ($model) { + return $model->rate . '%'; + } + ] + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.edit_tax_rate'), + function ($model) { + return URL::to("tax_rates/{$model->public_id}/edit"); + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/TokenDatatable.php b/app/Ninja/Datatables/TokenDatatable.php new file mode 100644 index 000000000000..e0e248f15cee --- /dev/null +++ b/app/Ninja/Datatables/TokenDatatable.php @@ -0,0 +1,41 @@ +public_id}/edit", $model->name)->toHtml(); + } + ], + [ + 'token', + function ($model) { + return $model->token; + } + ] + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.edit_token'), + function ($model) { + return URL::to("tokens/{$model->public_id}/edit"); + } + ] + ]; + } + +} diff --git a/app/Ninja/Datatables/UserDatatable.php b/app/Ninja/Datatables/UserDatatable.php new file mode 100644 index 000000000000..a6f267fdbd00 --- /dev/null +++ b/app/Ninja/Datatables/UserDatatable.php @@ -0,0 +1,96 @@ +public_id ? link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name)->toHtml() : ($model->first_name.' '.$model->last_name); + } + ], + [ + 'email', + function ($model) { + return $model->email; + } + ], + [ + 'confirmed', + function ($model) { + if (!$model->public_id) { + return self::getStatusLabel(USER_STATE_OWNER); + } elseif ($model->deleted_at) { + return self::getStatusLabel(USER_STATE_DISABLED); + } elseif ($model->confirmed) { + if($model->is_admin){ + return self::getStatusLabel(USER_STATE_ADMIN); + } else { + return self::getStatusLabel(USER_STATE_ACTIVE); + } + } else { + return self::getStatusLabel(USER_STATE_PENDING); + } + } + ], + ]; + } + + public function actions() + { + return [ + [ + uctrans('texts.edit_user'), + function ($model) { + return URL::to("users/{$model->public_id}/edit"); + }, + function ($model) { + return $model->public_id; + } + ], + [ + uctrans('texts.send_invite'), + function ($model) { + return URL::to("send_confirmation/{$model->public_id}"); + }, + function ($model) { + return $model->public_id && ! $model->confirmed; + } + ] + ]; + } + + private function getStatusLabel($state) + { + $label = trans("texts.{$state}"); + $class = 'default'; + switch ($state) { + case USER_STATE_PENDING: + $class = 'default'; + break; + case USER_STATE_ACTIVE: + $class = 'info'; + break; + case USER_STATE_DISABLED: + $class = 'warning'; + break; + case USER_STATE_OWNER: + $class = 'success'; + break; + case USER_STATE_ADMIN: + $class = 'primary'; + break; + } + return "

$label

"; + } + + +} diff --git a/app/Ninja/Datatables/VendorDatatable.php b/app/Ninja/Datatables/VendorDatatable.php new file mode 100644 index 000000000000..fda61fe457d8 --- /dev/null +++ b/app/Ninja/Datatables/VendorDatatable.php @@ -0,0 +1,79 @@ +public_id}", $model->name ?: '')->toHtml(); + } + ], + [ + 'city', + function ($model) { + return $model->city; + } + ], + [ + 'work_phone', + function ($model) { + return $model->work_phone; + } + ], + [ + 'email', + function ($model) { + return link_to("vendors/{$model->public_id}", $model->email ?: '')->toHtml(); + } + ], + [ + 'vendors.created_at', + function ($model) { + return Utils::timestampToDateString(strtotime($model->created_at)); + } + ], + ]; + } + + public function actions() + { + return [ + [ + trans('texts.edit_vendor'), + function ($model) { + return URL::to("vendors/{$model->public_id}/edit"); + }, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]); + } + ], + [ + '--divider--', function(){return false;}, + function ($model) { + return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]) && Auth::user()->can('create', ENTITY_EXPENSE); + } + + ], + [ + trans('texts.enter_expense'), + function ($model) { + return URL::to("expenses/create/{$model->public_id}"); + }, + function ($model) { + return Auth::user()->can('create', ENTITY_EXPENSE); + } + ] + ]; + } + + +} diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index 83f08cd97a59..bb56d944e6fc 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -25,7 +25,7 @@ class ClientRepository extends BaseRepository ->get(); } - public function find($filter = null) + public function find($filter = null, $userId = false) { $query = DB::table('clients') ->join('accounts', 'accounts.id', '=', 'clients.account_id') @@ -63,9 +63,13 @@ class ClientRepository extends BaseRepository }); } + if ($userId) { + $query->where('clients.user_id', '=', $userId); + } + return $query; } - + public function save($data, $client = null) { $publicId = isset($data['public_id']) ? $data['public_id'] : false; @@ -78,7 +82,7 @@ class ClientRepository extends BaseRepository $client = Client::scope($publicId)->with('contacts')->firstOrFail(); \Log::warning('Entity not set in client repo save'); } - + // convert currency code to id if (isset($data['currency_code'])) { $currencyCode = strtolower($data['currency_code']); @@ -98,7 +102,7 @@ class ClientRepository extends BaseRepository return $client; } */ - + $first = true; $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts']; $contactIds = []; @@ -107,7 +111,7 @@ class ClientRepository extends BaseRepository usort($contacts, function ($left, $right) { return (isset($right['is_primary']) ? $right['is_primary'] : 1) - (isset($left['is_primary']) ? $left['is_primary'] : 0); }); - + foreach ($contacts as $contact) { $contact = $client->addContact($contact, $first); $contactIds[] = $contact->public_id; diff --git a/app/Services/AccountGatewayService.php b/app/Services/AccountGatewayService.php index 88ee177321ec..00e3f672e602 100644 --- a/app/Services/AccountGatewayService.php +++ b/app/Services/AccountGatewayService.php @@ -1,10 +1,9 @@ accountGatewayRepo; } - /* - public function save() - { - return null; - } - */ - public function getDatatable($accountId) { $query = $this->accountGatewayRepo->find($accountId); - return $this->createDatatable(ENTITY_ACCOUNT_GATEWAY, $query, false); + return $this->datatableService->createDatatable(new AccountGatewayDatatable(false), $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'name', - function ($model) { - if ($model->deleted_at) { - return $model->name; - } elseif ($model->gateway_id != GATEWAY_WEPAY) { - return link_to("gateways/{$model->public_id}/edit", $model->name)->toHtml(); - } else { - $accountGateway = AccountGateway::find($model->id); - $config = $accountGateway->getConfig(); - $endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/'; - $wepayAccountId = $config->accountId; - $wepayState = isset($config->state)?$config->state:null; - $linkText = $model->name; - $url = $endpoint.'account/'.$wepayAccountId; - $wepay = \Utils::setupWepay($accountGateway); - $html = link_to($url, $linkText, array('target'=>'_blank'))->toHtml(); - - try { - if ($wepayState == 'action_required') { - $updateUri = $wepay->request('/account/get_update_uri', array( - 'account_id' => $wepayAccountId, - 'redirect_uri' => URL::to('gateways'), - )); - - $linkText .= ' ('.trans('texts.action_required').')'; - $url = $updateUri->uri; - $html = "{$linkText}"; - $model->setupUrl = $url; - } elseif ($wepayState == 'pending') { - $linkText .= ' ('.trans('texts.resend_confirmation_email').')'; - $model->resendConfirmationUrl = $url = URL::to("gateways/{$accountGateway->public_id}/resend_confirmation"); - $html = link_to($url, $linkText)->toHtml(); - } - } catch(\WePayException $ex){} - - return $html; - } - } - ], - [ - 'payment_type', - function ($model) { - return Gateway::getPrettyPaymentType($model->gateway_id); - } - ], - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.resend_confirmation_email'), - function ($model) { - return $model->resendConfirmationUrl; - }, - function($model) { - return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY && !empty($model->resendConfirmationUrl); - } - ], [ - uctrans('texts.finish_setup'), - function ($model) { - return $model->setupUrl; - }, - function($model) { - return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY && !empty($model->setupUrl); - } - ] , [ - uctrans('texts.edit_gateway'), - function ($model) { - return URL::to("gateways/{$model->public_id}/edit"); - }, - function($model) { - return !$model->deleted_at; - } - ], [ - uctrans('texts.manage_wepay_account'), - function ($model) { - $accountGateway = AccountGateway::find($model->id); - $endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/'; - return array( - 'url' => $endpoint.'account/'.$accountGateway->getConfig()->accountId, - 'attributes' => 'target="_blank"' - ); - }, - function($model) { - return !$model->deleted_at && $model->gateway_id == GATEWAY_WEPAY; - } - ] - ]; - } - -} \ No newline at end of file +} diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php index 6f6ef4b35956..6b06fce73a8b 100644 --- a/app/Services/ActivityService.php +++ b/app/Services/ActivityService.php @@ -4,6 +4,7 @@ use Utils; use App\Models\Client; use App\Services\BaseService; use App\Ninja\Repositories\ActivityRepository; +use App\Ninja\Datatables\ActivityDatatable; class ActivityService extends BaseService { @@ -22,48 +23,7 @@ class ActivityService extends BaseService $query = $this->activityRepo->findByClientId($clientId); - return $this->createDatatable(ENTITY_ACTIVITY, $query); + return $this->datatableService->createDatatable(new ActivityDatatable(false), $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'activities.id', - function ($model) { - return Utils::timestampToDateTimeString(strtotime($model->created_at)); - } - ], - [ - 'activity_type_id', - function ($model) { - $data = [ - 'client' => link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model))->toHtml(), - 'user' => $model->is_system ? '' . trans('texts.system') . '' : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email), - 'invoice' => $model->invoice ? link_to('/invoices/' . $model->invoice_public_id, $model->is_recurring ? trans('texts.recurring_invoice') : $model->invoice)->toHtml() : null, - 'quote' => $model->invoice ? link_to('/quotes/' . $model->invoice_public_id, $model->invoice)->toHtml() : null, - 'contact' => $model->contact_id ? link_to('/clients/' . $model->client_public_id, Utils::getClientDisplayName($model))->toHtml() : Utils::getPersonDisplayName($model->user_first_name, $model->user_last_name, $model->user_email), - 'payment' => $model->payment ?: '', - 'credit' => $model->payment_amount ? Utils::formatMoney($model->credit, $model->currency_id, $model->country_id) : '', - 'payment_amount' => $model->payment_amount ? Utils::formatMoney($model->payment_amount, $model->currency_id, $model->country_id) : null, - 'adjustment' => $model->adjustment ? Utils::formatMoney($model->adjustment, $model->currency_id, $model->country_id) : null - ]; - - return trans("texts.activity_{$model->activity_type_id}", $data); - } - ], - [ - 'balance', - function ($model) { - return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); - } - ], - [ - 'adjustment', - function ($model) { - return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id, $model->country_id) : ''; - } - ] - ]; - } -} \ No newline at end of file +} diff --git a/app/Services/BankAccountService.php b/app/Services/BankAccountService.php index 688bd866d3ad..9291a36342c3 100644 --- a/app/Services/BankAccountService.php +++ b/app/Services/BankAccountService.php @@ -11,6 +11,7 @@ use App\Services\BaseService; use App\Ninja\Repositories\BankAccountRepository; use App\Ninja\Repositories\ExpenseRepository; use App\Ninja\Repositories\VendorRepository; +use App\Ninja\Datatables\BankAccountDatatable; use App\Libraries\Finance; use App\Libraries\Login; @@ -206,7 +207,7 @@ class BankAccountService extends BaseService $vendorMap[$transaction['vendor_orig']] = $vendor; $countVendors++; } - + // create the expense record $this->expenseRepo->save([ 'vendor_id' => $vendor->id, @@ -241,36 +242,6 @@ class BankAccountService extends BaseService { $query = $this->bankAccountRepo->find($accountId); - return $this->createDatatable(ENTITY_BANK_ACCOUNT, $query, false); - } - - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'bank_name', - function ($model) { - return link_to("bank_accounts/{$model->public_id}/edit", $model->bank_name)->toHtml(); - }, - ], - [ - 'bank_library_id', - function ($model) { - return 'OFX'; - } - ], - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.edit_bank_account'), - function ($model) { - return URL::to("bank_accounts/{$model->public_id}/edit"); - }, - ] - ]; + return $this->datatableService->createDatatable(new BankAccountDatatable(false), $query); } } diff --git a/app/Services/BaseService.php b/app/Services/BaseService.php index afd6ed1ea1eb..e6dad06334bd 100644 --- a/app/Services/BaseService.php +++ b/app/Services/BaseService.php @@ -30,21 +30,4 @@ class BaseService return count($entities); } - public function createDatatable($entityType, $query, $showCheckbox = true, $hideClient = false, $orderColumns = []) - { - $columns = $this->getDatatableColumns($entityType, !$showCheckbox); - $actions = $this->getDatatableActions($entityType); - - return $this->datatableService->createDatatable($entityType, $query, $columns, $actions, $showCheckbox, $orderColumns); - } - - protected function getDatatableColumns($entityType, $hideClient) - { - return []; - } - - protected function getDatatableActions($entityType) - { - return []; - } } diff --git a/app/Services/ClientService.php b/app/Services/ClientService.php index 96357991c519..065258d05abb 100644 --- a/app/Services/ClientService.php +++ b/app/Services/ClientService.php @@ -12,6 +12,7 @@ use App\Models\Payment; use App\Models\Task; use App\Ninja\Repositories\ClientRepository; use App\Ninja\Repositories\NinjaRepository; +use App\Ninja\Datatables\ClientDatatable; class ClientService extends BaseService { @@ -39,139 +40,13 @@ class ClientService extends BaseService return $this->clientRepo->save($data, $client); } - public function getDatatable($search) + public function getDatatable($search, $userId) { - $query = $this->clientRepo->find($search); + $datatable = new ClientDatatable(); - if(!Utils::hasPermission('view_all')){ - $query->where('clients.user_id', '=', Auth::user()->id); - } + $query = $this->clientRepo->find($search, $userId); - return $this->createDatatable(ENTITY_CLIENT, $query); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'name', - function ($model) { - return link_to("clients/{$model->public_id}", $model->name ?: '')->toHtml(); - } - ], - [ - 'first_name', - function ($model) { - return link_to("clients/{$model->public_id}", $model->first_name.' '.$model->last_name)->toHtml(); - } - ], - [ - 'email', - function ($model) { - return link_to("clients/{$model->public_id}", $model->email ?: '')->toHtml(); - } - ], - [ - 'clients.created_at', - function ($model) { - return Utils::timestampToDateString(strtotime($model->created_at)); - } - ], - [ - 'last_login', - function ($model) { - return Utils::timestampToDateString(strtotime($model->last_login)); - } - ], - [ - 'balance', - function ($model) { - return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_client'), - function ($model) { - return URL::to("clients/{$model->public_id}/edit"); - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_CLIENT, $model->user_id]); - } - ], - [ - '--divider--', function(){return false;}, - function ($model) { - $user = Auth::user(); - return $user->can('editByOwner', [ENTITY_CLIENT, $model->user_id]) && ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE)); - } - ], - [ - trans('texts.new_task'), - function ($model) { - return URL::to("tasks/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_TASK); - } - ], - [ - trans('texts.new_invoice'), - function ($model) { - return URL::to("invoices/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_INVOICE); - } - ], - [ - trans('texts.new_quote'), - function ($model) { - return URL::to("quotes/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->hasFeature(FEATURE_QUOTES) && Auth::user()->can('create', ENTITY_INVOICE); - } - ], - [ - '--divider--', function(){return false;}, - function ($model) { - $user = Auth::user(); - return ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE)) && ($user->can('create', ENTITY_PAYMENT) || $user->can('create', ENTITY_CREDIT) || $user->can('create', ENTITY_EXPENSE)); - } - ], - [ - trans('texts.enter_payment'), - function ($model) { - return URL::to("payments/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_PAYMENT); - } - ], - [ - trans('texts.enter_credit'), - function ($model) { - return URL::to("credits/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_CREDIT); - } - ], - [ - trans('texts.enter_expense'), - function ($model) { - return URL::to("expenses/create/0/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_EXPENSE); - } - ] - ]; - } } diff --git a/app/Services/CreditService.php b/app/Services/CreditService.php index 54ef659f05f9..a1e1a5db40ab 100644 --- a/app/Services/CreditService.php +++ b/app/Services/CreditService.php @@ -7,7 +7,7 @@ use App\Services\BaseService; use App\Models\Client; use App\Models\Payment; use App\Ninja\Repositories\CreditRepository; - +use App\Ninja\Datatables\CreditDatatable; class CreditService extends BaseService { @@ -32,68 +32,14 @@ class CreditService extends BaseService public function getDatatable($clientPublicId, $search) { + // we don't support bulk edit and hide the client on the individual client page + $datatable = new CreditDatatable( ! $clientPublicId, $clientPublicId); $query = $this->creditRepo->find($clientPublicId, $search); - + if(!Utils::hasPermission('view_all')){ $query->where('credits.user_id', '=', Auth::user()->id); } - return $this->createDatatable(ENTITY_CREDIT, $query, !$clientPublicId); + return $this->datatableService->createDatatable($datatable, $query); } - - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'client_name', - function ($model) { - if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ - return Utils::getClientDisplayName($model); - } - - return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; - }, - ! $hideClient - ], - [ - 'amount', - function ($model) { - return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id) . ''; - } - ], - [ - 'balance', - function ($model) { - return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); - } - ], - [ - 'credit_date', - function ($model) { - return Utils::fromSqlDate($model->credit_date); - } - ], - [ - 'private_notes', - function ($model) { - return $model->private_notes; - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.apply_credit'), - function ($model) { - return URL::to("payments/create/{$model->client_public_id}") . '?paymentTypeId=1'; - }, - function ($model) { - return Auth::user()->can('create', ENTITY_PAYMENT); - } - ] - ]; - } -} \ No newline at end of file +} diff --git a/app/Services/DatatableService.php b/app/Services/DatatableService.php index df4c9d93d55d..453f4d0f25b0 100644 --- a/app/Services/DatatableService.php +++ b/app/Services/DatatableService.php @@ -4,24 +4,26 @@ use HtmlString; use Utils; use Datatable; use Auth; +use App\Ninja\Datatables\EntityDatatable; class DatatableService { - public function createDatatable($entityType, $query, $columns, $actions = null, $showCheckbox = true, $orderColumns = []) + //public function createDatatable($entityType, $query, $columns, $actions = null, $showCheckbox = true, $orderColumns = []) + public function createDatatable(EntityDatatable $datatable, $query) { $table = Datatable::query($query); - $calculateOrderColumns = empty($orderColumns); - - if ($actions && $showCheckbox) { + //$calculateOrderColumns = empty($orderColumns); + + if ($datatable->isBulkEdit) { $table->addColumn('checkbox', function ($model) { $can_edit = Auth::user()->hasPermission('edit_all') || (isset($model->user_id) && Auth::user()->id == $model->user_id); - + return !$can_edit?'':''; }); } - foreach ($columns as $column) { + foreach ($datatable->columns() as $column) { // set visible to true by default if (count($column) == 2) { $column[] = true; @@ -31,27 +33,31 @@ class DatatableService if ($visible) { $table->addColumn($field, $value); + $orderColumns[] = $field; + /* if ($calculateOrderColumns) { $orderColumns[] = $field; } + */ } } - if ($actions) { - $this->createDropdown($entityType, $table, $actions); + if (count($datatable->actions())) { + $this->createDropdown($datatable, $table); } return $table->orderColumns($orderColumns)->make(); } - private function createDropdown($entityType, $table, $actions) + //private function createDropdown($entityType, $table, $actions) + private function createDropdown(EntityDatatable $datatable, $table) { - $table->addColumn('dropdown', function ($model) use ($entityType, $actions) { + $table->addColumn('dropdown', function ($model) use ($datatable) { $hasAction = false; $str = '
'; $can_edit = Auth::user()->hasPermission('edit_all') || (isset($model->user_id) && Auth::user()->id == $model->user_id); - + if (property_exists($model, 'is_deleted') && $model->is_deleted) { $str .= ''; } elseif ($model->deleted_at && $model->deleted_at !== '0000-00-00') { @@ -64,7 +70,7 @@ class DatatableService $lastIsDivider = false; if (!$model->deleted_at || $model->deleted_at == '0000-00-00') { - foreach ($actions as $action) { + foreach ($datatable->actions() as $action) { if (count($action)) { if (count($action) == 2) { $action[] = function() { @@ -104,20 +110,20 @@ class DatatableService $dropdown_contents .= "
  • "; } - if (($entityType != ENTITY_USER || $model->public_id) && $can_edit) { + if (($datatable->entityType != ENTITY_USER || $model->public_id) && $can_edit) { $dropdown_contents .= "
  • public_id})\">" - . trans("texts.archive_{$entityType}") . "
  • "; + . trans("texts.archive_{$datatable->entityType}") . ""; } } else if($can_edit) { - if ($entityType != ENTITY_ACCOUNT_GATEWAY || Auth::user()->account->canAddGateway(\App\Models\Gateway::getPaymentType($model->gateway_id))) { + if ($datatable->entityType != ENTITY_ACCOUNT_GATEWAY || Auth::user()->account->canAddGateway(\App\Models\Gateway::getPaymentType($model->gateway_id))) { $dropdown_contents .= "
  • public_id})\">" - . trans("texts.restore_{$entityType}") . "
  • "; + . trans("texts.restore_{$datatable->entityType}") . ""; } } if (property_exists($model, 'is_deleted') && !$model->is_deleted && $can_edit) { $dropdown_contents .= "
  • public_id})\">" - . trans("texts.delete_{$entityType}") . "
  • "; + . trans("texts.delete_{$datatable->entityType}") . ""; } if (!empty($dropdown_contents)) { @@ -132,5 +138,4 @@ class DatatableService return $str.'
    '; }); } - -} \ No newline at end of file +} diff --git a/app/Services/ExpenseService.php b/app/Services/ExpenseService.php index 671648ea32a5..94bfd7d8c87a 100644 --- a/app/Services/ExpenseService.php +++ b/app/Services/ExpenseService.php @@ -10,6 +10,7 @@ use App\Models\Expense; use App\Models\Invoice; use App\Models\Client; use App\Models\Vendor; +use App\Ninja\Datatables\ExpenseDatatable; class ExpenseService extends BaseService { @@ -49,7 +50,7 @@ class ExpenseService extends BaseService $query->where('expenses.user_id', '=', Auth::user()->id); } - return $this->createDatatable(ENTITY_EXPENSE, $query); + return $this->datatableService->createDatatable(new ExpenseDatatable(), $query); } public function getDatatableVendor($vendorPublicId) @@ -62,76 +63,6 @@ class ExpenseService extends BaseService false); } - protected function getDatatableColumns($entityType, $hideClient) - { - 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 ''; - } - } - ], - [ - '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 ''; - } - } - ], - [ - 'expense_date', - function ($model) { - if(!Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id])){ - return Utils::fromSqlDate($model->expense_date); - } - - return link_to("expenses/{$model->public_id}/edit", Utils::fromSqlDate($model->expense_date))->toHtml(); - } - ], - [ - 'amount', - function ($model) { - // show both the amount and the converted amount - if ($model->exchange_rate != 1) { - $converted = round($model->amount * $model->exchange_rate, 2); - return Utils::formatMoney($model->amount, $model->expense_currency_id) . ' | ' . - Utils::formatMoney($converted, $model->invoice_currency_id); - } else { - return Utils::formatMoney($model->amount, $model->expense_currency_id); - } - } - ], - [ - 'public_notes', - function ($model) { - return $model->public_notes != null ? substr($model->public_notes, 0, 100) : ''; - } - ], - [ - 'expense_status_id', - function ($model) { - return self::getStatusLabel($model->invoice_id, $model->should_be_invoiced); - } - ], - ]; - } protected function getDatatableColumnsVendor($entityType, $hideClient) { @@ -163,58 +94,9 @@ class ExpenseService extends BaseService ]; } - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_expense'), - function ($model) { - return URL::to("expenses/{$model->public_id}/edit") ; - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id]); - } - ], - [ - trans('texts.view_invoice'), - function ($model) { - return URL::to("/invoices/{$model->invoice_public_id}/edit"); - }, - function ($model) { - return $model->invoice_public_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]); - } - ], - [ - trans('texts.invoice_expense'), - function ($model) { - return "javascript:invoiceEntity({$model->public_id})"; - }, - function ($model) { - return ! $model->invoice_id && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE); - } - ], - ]; - } - protected function getDatatableActionsVendor($entityType) { return []; } - private function getStatusLabel($invoiceId, $shouldBeInvoiced) - { - if ($invoiceId) { - $label = trans('texts.invoiced'); - $class = 'success'; - } elseif ($shouldBeInvoiced) { - $label = trans('texts.pending'); - $class = 'warning'; - } else { - $label = trans('texts.logged'); - $class = 'primary'; - } - - return "

    $label

    "; - } - } diff --git a/app/Services/InvoiceService.php b/app/Services/InvoiceService.php index edbee8caf84c..950c8bb95fcb 100644 --- a/app/Services/InvoiceService.php +++ b/app/Services/InvoiceService.php @@ -11,6 +11,7 @@ use App\Models\Invitation; use App\Models\Invoice; use App\Models\Client; use App\Models\Payment; +use App\Ninja\Datatables\InvoiceDatatable; class InvoiceService extends BaseService { @@ -34,12 +35,12 @@ class InvoiceService extends BaseService { if (isset($data['client'])) { $canSaveClient = false; - $clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id'); + $clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id'); if (empty($clientPublicId) || $clientPublicId == '-1') { $canSaveClient = Auth::user()->can('create', ENTITY_CLIENT); } else { $canSaveClient = Auth::user()->can('edit', Client::scope($clientPublicId)->first()); - } + } if ($canSaveClient) { $client = $this->clientRepo->save($data['client']); $data['client_id'] = $client->id; @@ -92,7 +93,7 @@ class InvoiceService extends BaseService public function approveQuote($quote, $invitation = null) { $account = $quote->account; - + if (!$quote->is_quote || $quote->quote_invoice_id) { return null; } @@ -118,189 +119,15 @@ class InvoiceService extends BaseService public function getDatatable($accountId, $clientPublicId = null, $entityType, $search) { + $datatable = new InvoiceDatatable( ! $clientPublicId, $clientPublicId); $query = $this->invoiceRepo->getInvoices($accountId, $clientPublicId, $entityType, $search) ->where('invoices.is_quote', '=', $entityType == ENTITY_QUOTE ? true : false); if(!Utils::hasPermission('view_all')){ $query->where('invoices.user_id', '=', Auth::user()->id); } - - return $this->createDatatable($entityType, $query, !$clientPublicId); - } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'invoice_number', - function ($model) use ($entityType) { - if(!Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id])){ - return $model->invoice_number; - } - - return link_to("{$entityType}s/{$model->public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml(); - } - ], - [ - 'client_name', - function ($model) { - 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(); - }, - ! $hideClient - ], - [ - 'invoice_date', - function ($model) { - return Utils::fromSqlDate($model->invoice_date); - } - ], - [ - 'amount', - function ($model) { - return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); - } - ], - [ - 'balance', - function ($model) { - return $model->partial > 0 ? - trans('texts.partial_remaining', [ - 'partial' => Utils::formatMoney($model->partial, $model->currency_id, $model->country_id), - 'balance' => Utils::formatMoney($model->balance, $model->currency_id, $model->country_id)] - ) : - Utils::formatMoney($model->balance, $model->currency_id, $model->country_id); - }, - $entityType == ENTITY_INVOICE - ], - [ - 'due_date', - function ($model) { - return Utils::fromSqlDate($model->due_date); - }, - ], - [ - 'invoice_status_name', - function ($model) use ($entityType) { - return $model->quote_invoice_id ? link_to("invoices/{$model->quote_invoice_id}/edit", trans('texts.converted'))->toHtml() : self::getStatusLabel($entityType, $model); - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans("texts.edit_{$entityType}"), - function ($model) use ($entityType) { - return URL::to("{$entityType}s/{$model->public_id}/edit"); - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ], - [ - trans("texts.clone_{$entityType}"), - function ($model) use ($entityType) { - return URL::to("{$entityType}s/{$model->public_id}/clone"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_INVOICE); - } - ], - [ - trans("texts.view_history"), - function ($model) use ($entityType) { - return URL::to("{$entityType}s/{$entityType}_history/{$model->public_id}"); - } - ], - [ - '--divider--', function(){return false;}, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]) || Auth::user()->can('create', ENTITY_PAYMENT); - } - ], - [ - trans("texts.mark_sent"), - function ($model) { - return "javascript:markEntity({$model->public_id})"; - }, - function ($model) { - return $model->invoice_status_id < INVOICE_STATUS_SENT && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ], - [ - trans('texts.enter_payment'), - function ($model) { - return URL::to("payments/create/{$model->client_public_id}/{$model->public_id}"); - }, - function ($model) use ($entityType) { - return $entityType == ENTITY_INVOICE && $model->balance > 0 && Auth::user()->can('create', ENTITY_PAYMENT); - } - ], - [ - trans("texts.view_quote"), - function ($model) { - return URL::to("quotes/{$model->quote_id}/edit"); - }, - function ($model) use ($entityType) { - return $entityType == ENTITY_INVOICE && $model->quote_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ], - [ - trans("texts.view_invoice"), - function ($model) { - return URL::to("invoices/{$model->quote_invoice_id}/edit"); - }, - function ($model) use ($entityType) { - return $entityType == ENTITY_QUOTE && $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ], - [ - trans("texts.convert_to_invoice"), - function ($model) { - return "javascript:convertEntity({$model->public_id})"; - }, - function ($model) use ($entityType) { - return $entityType == ENTITY_QUOTE && ! $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ] - ]; - } - - private function getStatusLabel($entityType, $model) - { - // check if invoice is overdue - if (Utils::parseFloat($model->balance) && $model->due_date && $model->due_date != '0000-00-00') { - if (\DateTime::createFromFormat('Y-m-d', $model->due_date) < new \DateTime("now")) { - $label = $entityType == ENTITY_INVOICE ? trans('texts.overdue') : trans('texts.expired'); - return "

    " . $label . "

    "; - } - } - - $label = trans("texts.status_" . strtolower($model->invoice_status_name)); - $class = 'default'; - switch ($model->invoice_status_id) { - case INVOICE_STATUS_SENT: - $class = 'info'; - break; - case INVOICE_STATUS_VIEWED: - $class = 'warning'; - break; - case INVOICE_STATUS_APPROVED: - $class = 'success'; - break; - case INVOICE_STATUS_PARTIAL: - $class = 'primary'; - break; - case INVOICE_STATUS_PAID: - $class = 'success'; - break; - } - return "

    $label

    "; + return $this->datatableService->createDatatable($datatable, $query); } } diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php index 51cbccc57177..c4dabe5b9a2c 100644 --- a/app/Services/PaymentService.php +++ b/app/Services/PaymentService.php @@ -23,6 +23,7 @@ use App\Ninja\Repositories\PaymentRepository; use App\Ninja\Repositories\AccountRepository; use App\Services\BaseService; use App\Events\PaymentWasCreated; +use App\Ninja\Datatables\PaymentDatatable; class PaymentService extends BaseService { @@ -524,7 +525,7 @@ class PaymentService extends BaseService return $paymentMethod; } - + public function convertPaymentMethodFromGatewayResponse($gatewayResponse, $accountGateway, $accountGatewayToken = null, $contactId = null, $existingPaymentMethod = null) { if ($accountGateway->gateway_id == GATEWAY_STRIPE) { $data = $gatewayResponse->getData(); @@ -642,7 +643,7 @@ class PaymentService extends BaseService $payment->contact_id = $invitation->contact_id; $payment->transaction_reference = $ref; $payment->payment_date = date_create()->format('Y-m-d'); - + if (!empty($paymentDetails['card'])) { $card = $paymentDetails['card']; $payment->last4 = $card->getNumberLastFour(); @@ -707,10 +708,10 @@ class PaymentService extends BaseService $pending_monthly = true; } } - - if (!empty($plan)) { + + if (!empty($plan)) { $account = Account::with('users')->find($invoice->client->public_id); - + if( $account->company->plan != $plan || DateTime::createFromFormat('Y-m-d', $account->company->plan_expires) >= date_create('-7 days') @@ -719,10 +720,10 @@ class PaymentService extends BaseService // Reset any grandfathering $account->company->plan_started = date_create()->format('Y-m-d'); } - + if ( $account->company->plan == $plan - && $account->company->plan_term == $term + && $account->company->plan_term == $term && DateTime::createFromFormat('Y-m-d', $account->company->plan_expires) >= date_create() ) { // This is a renewal; mark it paid as of when this term expires @@ -730,13 +731,13 @@ class PaymentService extends BaseService } else { $account->company->plan_paid = date_create()->format('Y-m-d'); } - + $account->company->payment_id = $payment->id; $account->company->plan = $plan; $account->company->plan_term = $term; $account->company->plan_expires = DateTime::createFromFormat('Y-m-d', $account->company->plan_paid) ->modify($term == PLAN_TERM_MONTHLY ? '+1 month' : '+1 year')->format('Y-m-d'); - + if (!empty($pending_monthly)) { $account->company->pending_plan = $plan; $account->company->pending_term = PLAN_TERM_MONTHLY; @@ -744,7 +745,7 @@ class PaymentService extends BaseService $account->company->pending_plan = null; $account->company->pending_term = null; } - + $account->company->save(); } } @@ -783,7 +784,7 @@ class PaymentService extends BaseService return PAYMENT_TYPE_CREDIT_CARD_OTHER; } } - + private function detectCardType($number) { if (preg_match('/^3[47][0-9]{13}$/',$number)) { @@ -856,127 +857,17 @@ class PaymentService extends BaseService public function getDatatable($clientPublicId, $search) { + $datatable = new PaymentDatatable( ! $clientPublicId, $clientPublicId); $query = $this->paymentRepo->find($clientPublicId, $search); if(!Utils::hasPermission('view_all')){ $query->where('payments.user_id', '=', Auth::user()->id); } - return $this->createDatatable(ENTITY_PAYMENT, $query, !$clientPublicId, false, - ['invoice_number', 'transaction_reference', 'payment_type', 'amount', 'payment_date']); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'invoice_number', - function ($model) { - if(!Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id])){ - return $model->invoice_number; - } - - return link_to("invoices/{$model->invoice_public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml(); - } - ], - [ - 'client_name', - function ($model) { - if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ - return Utils::getClientDisplayName($model); - } - - return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; - }, - ! $hideClient - ], - [ - 'transaction_reference', - function ($model) { - return $model->transaction_reference ? $model->transaction_reference : 'Manual entry'; - } - ], - [ - 'payment_type', - function ($model) { - return ($model->payment_type && !$model->last4) ? $model->payment_type : ($model->account_gateway_id ? $model->gateway_name : ''); - } - ], - [ - 'source', - function ($model) { - $code = str_replace(' ', '', strtolower($model->payment_type)); - $card_type = trans("texts.card_" . $code); - if ($model->payment_type_id != PAYMENT_TYPE_ACH) { - if($model->last4) { - $expiration = trans('texts.card_expiration', array('expires' => Utils::fromSqlDate($model->expiration, false)->format('m/y'))); - return '' . htmlentities($card_type) . '  •••' . $model->last4 . ' ' . $expiration; - } elseif ($model->email) { - return $model->email; - } - } elseif ($model->last4) { - $bankData = PaymentMethod::lookupBankData($model->routing_number); - if (is_object($bankData)) { - return $bankData->name.'  •••' . $model->last4; - } elseif($model->last4) { - return '' . htmlentities($card_type) . '  •••' . $model->last4; - } - } - } - ], - [ - 'amount', - function ($model) { - return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); - } - ], - [ - 'payment_date', - function ($model) { - return Utils::dateToString($model->payment_date); - } - ], - [ - 'payment_status_name', - function ($model) use ($entityType) { - return self::getStatusLabel($entityType, $model); - } - ] - ]; - } - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_payment'), - function ($model) { - return URL::to("payments/{$model->public_id}/edit"); - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_PAYMENT, $model->user_id]); - } - ], - [ - trans('texts.refund_payment'), - function ($model) { - $max_refund = number_format($model->amount - $model->refunded, 2); - $formatted = Utils::formatMoney($max_refund, $model->currency_id, $model->country_id); - $symbol = Utils::getFromCache($model->currency_id ? $model->currency_id : 1, 'currencies')->symbol ; - return "javascript:showRefundModal({$model->public_id}, '{$max_refund}', '{$formatted}', '{$symbol}')"; - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_PAYMENT, $model->user_id]) && $model->payment_status_id >= PAYMENT_STATUS_COMPLETED && - $model->refunded < $model->amount && - ( - ($model->transaction_reference && in_array($model->gateway_id , static::$refundableGateways)) - || $model->payment_type_id == PAYMENT_TYPE_CREDIT - ); - } - ] - ]; - } - public function bulk($ids, $action, $params = array()) { if ($action == 'refund') { @@ -1001,50 +892,22 @@ class PaymentService extends BaseService return parent::bulk($ids, $action); } } - - private function getStatusLabel($entityType, $model) - { - $label = trans("texts.status_" . strtolower($model->payment_status_name)); - $class = 'default'; - switch ($model->payment_status_id) { - case PAYMENT_STATUS_PENDING: - $class = 'info'; - break; - case PAYMENT_STATUS_COMPLETED: - $class = 'success'; - break; - case PAYMENT_STATUS_FAILED: - $class = 'danger'; - break; - case PAYMENT_STATUS_PARTIALLY_REFUNDED: - $label = trans('texts.status_partially_refunded_amount', [ - 'amount' => Utils::formatMoney($model->refunded, $model->currency_id, $model->country_id), - ]); - $class = 'primary'; - break; - case PAYMENT_STATUS_VOIDED: - case PAYMENT_STATUS_REFUNDED: - $class = 'default'; - break; - } - return "

    $label

    "; - } - + public function refund($payment, $amount = null) { if ($amount) { $amount = min($amount, $payment->amount - $payment->refunded); } $accountGateway = $payment->account_gateway; - + if (!$accountGateway) { $accountGateway = AccountGateway::withTrashed()->find($payment->account_gateway_id); } - + if (!$amount || !$accountGateway) { return; } - + if ($payment->payment_type_id != PAYMENT_TYPE_CREDIT) { $gateway = $this->createGateway($accountGateway); diff --git a/app/Services/PaymentTermService.php b/app/Services/PaymentTermService.php index 1371d20c2c43..08e2a84caf4b 100644 --- a/app/Services/PaymentTermService.php +++ b/app/Services/PaymentTermService.php @@ -25,10 +25,10 @@ class PaymentTermService extends BaseService { $query = $this->paymentTermRepo->find(); - return $this->createDatatable(ENTITY_PAYMENT_TERM, $query, false); + return $this->datatableService->createDatatable(ENTITY_PAYMENT_TERM, $query, false); } - protected function getDatatableColumns($entityType, $hideClient) + public function columns($entityType, $hideClient) { return [ [ @@ -46,7 +46,7 @@ class PaymentTermService extends BaseService ]; } - protected function getDatatableActions($entityType) + public function actions($entityType) { return [ [ @@ -57,4 +57,4 @@ class PaymentTermService extends BaseService ] ]; } -} \ No newline at end of file +} diff --git a/app/Services/ProductService.php b/app/Services/ProductService.php index f8ec6e1131d5..fc7fc6cceed4 100644 --- a/app/Services/ProductService.php +++ b/app/Services/ProductService.php @@ -1,12 +1,12 @@ productRepo->find($accountId); - return $this->createDatatable(ENTITY_PRODUCT, $query, false); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'product_key', - function ($model) { - return link_to('products/'.$model->public_id.'/edit', $model->product_key)->toHtml(); - } - ], - [ - 'notes', - function ($model) { - return nl2br(Str::limit($model->notes, 100)); - } - ], - [ - 'cost', - function ($model) { - return Utils::formatMoney($model->cost); - } - ], - [ - 'tax_rate', - function ($model) { - return $model->tax_rate ? ($model->tax_name . ' ' . $model->tax_rate . '%') : ''; - }, - Auth::user()->account->invoice_item_taxes - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.edit_product'), - function ($model) { - return URL::to("products/{$model->public_id}/edit"); - } - ] - ]; - } - -} \ No newline at end of file +} diff --git a/app/Services/RecurringInvoiceService.php b/app/Services/RecurringInvoiceService.php index b003455abd6a..bc6daa1f0178 100644 --- a/app/Services/RecurringInvoiceService.php +++ b/app/Services/RecurringInvoiceService.php @@ -5,6 +5,7 @@ use Auth; use Utils; use App\Models\Invoice; use App\Ninja\Repositories\InvoiceRepository; +use App\Ninja\Datatables\RecurringInvoiceDatatable; class RecurringInvoiceService extends BaseService { @@ -19,64 +20,14 @@ class RecurringInvoiceService extends BaseService public function getDatatable($accountId, $clientPublicId = null, $entityType, $search) { + $datatable = new RecurringInvoiceDatatable( ! $clientPublicId, $clientPublicId); $query = $this->invoiceRepo->getRecurringInvoices($accountId, $clientPublicId, $search); if(!Utils::hasPermission('view_all')){ $query->where('invoices.user_id', '=', Auth::user()->id); } - - return $this->createDatatable(ENTITY_RECURRING_INVOICE, $query, !$clientPublicId); + + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'frequency', - function ($model) { - return link_to("invoices/{$model->public_id}", $model->frequency)->toHtml(); - } - ], - [ - 'client_name', - function ($model) { - return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml(); - }, - ! $hideClient - ], - [ - 'start_date', - function ($model) { - return Utils::fromSqlDate($model->start_date); - } - ], - [ - 'end_date', - function ($model) { - return Utils::fromSqlDate($model->end_date); - } - ], - [ - 'amount', - function ($model) { - return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id); - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_invoice'), - function ($model) { - return URL::to("invoices/{$model->public_id}/edit"); - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); - } - ] - ]; - } -} \ No newline at end of file +} diff --git a/app/Services/TaskService.php b/app/Services/TaskService.php index e07793b2f85c..bfb25708d0d5 100644 --- a/app/Services/TaskService.php +++ b/app/Services/TaskService.php @@ -8,6 +8,7 @@ use App\Models\Invoice; use App\Models\Client; use App\Ninja\Repositories\TaskRepository; use App\Services\BaseService; +use App\Ninja\Datatables\TaskDatatable; class TaskService extends BaseService { @@ -34,112 +35,14 @@ class TaskService extends BaseService public function getDatatable($clientPublicId, $search) { + $datatable = new TaskDatatable( ! $clientPublicId, $clientPublicId); $query = $this->taskRepo->find($clientPublicId, $search); if(!Utils::hasPermission('view_all')){ $query->where('tasks.user_id', '=', Auth::user()->id); } - return $this->createDatatable(ENTITY_TASK, $query, !$clientPublicId); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'client_name', - function ($model) { - if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){ - return Utils::getClientDisplayName($model); - } - - return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : ''; - }, - ! $hideClient - ], - [ - 'created_at', - function ($model) { - return link_to("tasks/{$model->public_id}/edit", Task::calcStartTime($model))->toHtml(); - } - ], - [ - 'time_log', - function($model) { - return Utils::formatTime(Task::calcDuration($model)); - } - ], - [ - 'description', - function ($model) { - return $model->description; - } - ], - [ - 'invoice_number', - function ($model) { - return self::getStatusLabel($model); - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_task'), - function ($model) { - return URL::to('tasks/'.$model->public_id.'/edit'); - }, - function ($model) { - return (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]); - } - ], - [ - trans('texts.view_invoice'), - function ($model) { - return URL::to("/invoices/{$model->invoice_public_id}/edit"); - }, - function ($model) { - return $model->invoice_number && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]); - } - ], - [ - trans('texts.stop_task'), - function ($model) { - return "javascript:stopTask({$model->public_id})"; - }, - function ($model) { - return $model->is_running && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]); - } - ], - [ - trans('texts.invoice_task'), - function ($model) { - return "javascript:invoiceEntity({$model->public_id})"; - }, - function ($model) { - return ! $model->invoice_number && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE); - } - ] - ]; - } - - private function getStatusLabel($model) - { - if ($model->invoice_number) { - $class = 'success'; - $label = trans('texts.invoiced'); - } elseif ($model->is_running) { - $class = 'primary'; - $label = trans('texts.running'); - } else { - $class = 'default'; - $label = trans('texts.logged'); - } - - return "

    $label

    "; - } - -} \ No newline at end of file +} diff --git a/app/Services/TaxRateService.php b/app/Services/TaxRateService.php index db5b041395f0..330477149462 100644 --- a/app/Services/TaxRateService.php +++ b/app/Services/TaxRateService.php @@ -4,6 +4,7 @@ use URL; use Auth; use App\Services\BaseService; use App\Ninja\Repositories\TaxRateRepository; +use App\Ninja\Datatables\TaxRateDatatable; class TaxRateService extends BaseService { @@ -21,48 +22,12 @@ class TaxRateService extends BaseService return $this->taxRateRepo; } - /* - public function save() - { - return null; - } - */ - public function getDatatable($accountId) { + $datatable = new TaxRateDatatable(false); $query = $this->taxRateRepo->find($accountId); - return $this->createDatatable(ENTITY_TAX_RATE, $query, false); + return $this->datatableService->createDatatable($datatable, $query); } - - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'name', - function ($model) { - return link_to("tax_rates/{$model->public_id}/edit", $model->name)->toHtml(); - } - ], - [ - 'rate', - function ($model) { - return $model->rate . '%'; - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.edit_tax_rate'), - function ($model) { - return URL::to("tax_rates/{$model->public_id}/edit"); - } - ] - ]; - } - -} \ No newline at end of file + +} diff --git a/app/Services/TokenService.php b/app/Services/TokenService.php index 092f3995d3d7..5d5b29e3de6c 100644 --- a/app/Services/TokenService.php +++ b/app/Services/TokenService.php @@ -3,6 +3,7 @@ use URL; use App\Services\BaseService; use App\Ninja\Repositories\TokenRepository; +use App\Ninja\Datatables\TokenDatatable; class TokenService extends BaseService { @@ -20,48 +21,12 @@ class TokenService extends BaseService return $this->tokenRepo; } - /* - public function save() - { - return null; - } - */ - public function getDatatable($userId) { + $datatable = new TokenDatatable(false); $query = $this->tokenRepo->find($userId); - return $this->createDatatable(ENTITY_TOKEN, $query, false); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'name', - function ($model) { - return link_to("tokens/{$model->public_id}/edit", $model->name)->toHtml(); - } - ], - [ - 'token', - function ($model) { - return $model->token; - } - ] - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.edit_token'), - function ($model) { - return URL::to("tokens/{$model->public_id}/edit"); - } - ] - ]; - } - -} \ No newline at end of file +} diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 8e31b4c30d2d..3aa7a60c8851 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -3,6 +3,7 @@ use URL; use App\Services\BaseService; use App\Ninja\Repositories\UserRepository; +use App\Ninja\Datatables\UserDatatable; class UserService extends BaseService { @@ -20,102 +21,12 @@ class UserService extends BaseService return $this->userRepo; } - /* - public function save() - { - return null; - } - */ - public function getDatatable($accountId) { + $datatable = new UserDatatable(false); $query = $this->userRepo->find($accountId); - return $this->createDatatable(ENTITY_USER, $query, false); + return $this->datatableService->createDatatable($datatable, $query); } - protected function getDatatableColumns($entityType, $hideClient) - { - return [ - [ - 'first_name', - function ($model) { - return $model->public_id ? link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name)->toHtml() : ($model->first_name.' '.$model->last_name); - } - ], - [ - 'email', - function ($model) { - return $model->email; - } - ], - [ - 'confirmed', - function ($model) { - if (!$model->public_id) { - return self::getStatusLabel(USER_STATE_OWNER); - } elseif ($model->deleted_at) { - return self::getStatusLabel(USER_STATE_DISABLED); - } elseif ($model->confirmed) { - if($model->is_admin){ - return self::getStatusLabel(USER_STATE_ADMIN); - } else { - return self::getStatusLabel(USER_STATE_ACTIVE); - } - } else { - return self::getStatusLabel(USER_STATE_PENDING); - } - } - ], - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - uctrans('texts.edit_user'), - function ($model) { - return URL::to("users/{$model->public_id}/edit"); - }, - function ($model) { - return $model->public_id; - } - ], - [ - uctrans('texts.send_invite'), - function ($model) { - return URL::to("send_confirmation/{$model->public_id}"); - }, - function ($model) { - return $model->public_id && ! $model->confirmed; - } - ] - ]; - } - - private function getStatusLabel($state) - { - $label = trans("texts.{$state}"); - $class = 'default'; - switch ($state) { - case USER_STATE_PENDING: - $class = 'default'; - break; - case USER_STATE_ACTIVE: - $class = 'info'; - break; - case USER_STATE_DISABLED: - $class = 'warning'; - break; - case USER_STATE_OWNER: - $class = 'success'; - break; - case USER_STATE_ADMIN: - $class = 'primary'; - break; - } - return "

    $label

    "; - } - -} \ No newline at end of file +} diff --git a/app/Services/VendorService.php b/app/Services/VendorService.php index 41f5fd4664bb..7477300036d7 100644 --- a/app/Services/VendorService.php +++ b/app/Services/VendorService.php @@ -38,78 +38,12 @@ class VendorService extends BaseService public function getDatatable($search) { $query = $this->vendorRepo->find($search); - + if(!Utils::hasPermission('view_all')){ $query->where('vendors.user_id', '=', Auth::user()->id); } - return $this->createDatatable(ENTITY_VENDOR, $query); + return $this->datatableService->createDatatable(ENTITY_VENDOR, $query); } - protected function getDatatableColumns($entityType, $hideVendor) - { - return [ - [ - 'name', - function ($model) { - return link_to("vendors/{$model->public_id}", $model->name ?: '')->toHtml(); - } - ], - [ - 'city', - function ($model) { - return $model->city; - } - ], - [ - 'work_phone', - function ($model) { - return $model->work_phone; - } - ], - [ - 'email', - function ($model) { - return link_to("vendors/{$model->public_id}", $model->email ?: '')->toHtml(); - } - ], - [ - 'vendors.created_at', - function ($model) { - return Utils::timestampToDateString(strtotime($model->created_at)); - } - ], - ]; - } - - protected function getDatatableActions($entityType) - { - return [ - [ - trans('texts.edit_vendor'), - function ($model) { - return URL::to("vendors/{$model->public_id}/edit"); - }, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]); - } - ], - [ - '--divider--', function(){return false;}, - function ($model) { - return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]) && Auth::user()->can('create', ENTITY_EXPENSE); - } - - ], - [ - trans('texts.enter_expense'), - function ($model) { - return URL::to("expenses/create/{$model->public_id}"); - }, - function ($model) { - return Auth::user()->can('create', ENTITY_EXPENSE); - } - ] - ]; - } }