diff --git a/VERSION.txt b/VERSION.txt index 8fa0157a0207..8a55abf0b000 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.5.40 \ No newline at end of file +5.5.41 \ No newline at end of file diff --git a/app/Filters/BankTransactionFilters.php b/app/Filters/BankTransactionFilters.php index f76cc81cfdb7..e7cff05feee9 100644 --- a/app/Filters/BankTransactionFilters.php +++ b/app/Filters/BankTransactionFilters.php @@ -55,6 +55,55 @@ class BankTransactionFilters extends QueryFilters } + +/** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - unmatched + * - matched + * - converted + * - deposits + * - withdrawals + * + * @return Builder + */ + public function client_status(string $value = '') :Builder + { + if (strlen($value) == 0) { + return $this->builder; + } + + $status_parameters = explode(',', $value); + + if (in_array('all', $status_parameters)) { + return $this->builder; + } + + if (in_array('unmatched', $status_parameters)) { + $this->builder->where('status_id', BankTransaction::STATUS_UNMATCHED); + } + + if (in_array('matched', $status_parameters)) { + $this->builder->where('status_id', BankTransaction::STATUS_MATCHED); + } + + if (in_array('converted', $status_parameters)) { + $this->builder->where('status_id', BankTransaction::STATUS_CONVERTED); + } + + if (in_array('deposits', $status_parameters)) { + $this->builder->where('base_type', 'CREDIT'); + } + + if (in_array('withdrawals', $status_parameters)) { + $this->builder->where('base_type', 'DEBIT'); + } + + return $this->builder; + } + /** * Filters the list based on the status * archived, active, deleted. diff --git a/app/Filters/ExpenseFilters.php b/app/Filters/ExpenseFilters.php index 174acff790af..d7e10ac0f4f1 100644 --- a/app/Filters/ExpenseFilters.php +++ b/app/Filters/ExpenseFilters.php @@ -44,6 +44,55 @@ class ExpenseFilters extends QueryFilters }); } + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - logged + * - pending + * - invoiced + * - paid + * - unpaid + * + * @return Builder + */ + public function client_status(string $value = '') :Builder + { + if (strlen($value) == 0) { + return $this->builder; + } + + $status_parameters = explode(',', $value); + + if (in_array('all', $status_parameters)) { + return $this->builder; + } + + if (in_array('logged', $status_parameters)) { + $this->builder->where('amount', '>', 0); + } + + if (in_array('pending', $status_parameters)) { + $this->builder->whereNull('invoice_id')->whereNotNull('payment_date'); + } + + if (in_array('invoiced', $status_parameters)) { + $this->builder->whereNotNull('invoice_id'); + } + + if (in_array('paid', $status_parameters)) { + $this->builder->whereNotNull('payment_date'); + } + + if (in_array('unpaid', $status_parameters)) { + $this->builder->whereNull('payment_date'); + } + + return $this->builder; + } + + /** * Filters the list based on the status * archived, active, deleted. diff --git a/app/Filters/PurchaseOrderFilters.php b/app/Filters/PurchaseOrderFilters.php index 3aa91958ef36..2d9f957d75f6 100644 --- a/app/Filters/PurchaseOrderFilters.php +++ b/app/Filters/PurchaseOrderFilters.php @@ -17,19 +17,20 @@ use Illuminate\Database\Eloquent\Builder; class PurchaseOrderFilters extends QueryFilters { + /** * Filter based on client status. * * Statuses we need to handle * - all - * - paid - * - unpaid - * - overdue - * - reversed + * - draft + * - sent + * - accepted + * - cancelled * * @return Builder */ - public function credit_status(string $value = '') :Builder + public function client_status(string $value = '') :Builder { if (strlen($value) == 0) { return $this->builder; @@ -45,16 +46,17 @@ class PurchaseOrderFilters extends QueryFilters $this->builder->where('status_id', PurchaseOrder::STATUS_DRAFT); } - if (in_array('partial', $status_parameters)) { - $this->builder->where('status_id', PurchaseOrder::STATUS_PARTIAL); + if (in_array('sent', $status_parameters)) { + $this->builder->where('status_id', PurchaseOrder::STATUS_SENT); } - if (in_array('applied', $status_parameters)) { - $this->builder->where('status_id', PurchaseOrder::STATUS_APPLIED); + if (in_array('accepted', $status_parameters)) { + $this->builder->where('status_id', PurchaseOrder::STATUS_ACCEPTED); } - //->where('due_date', '>', Carbon::now()) - //->orWhere('partial_due_date', '>', Carbon::now()); + if (in_array('cancelled', $status_parameters)) { + $this->builder->where('status_id', PurchaseOrder::STATUS_CANCELLED); + } return $this->builder; } diff --git a/app/Filters/QuoteFilters.php b/app/Filters/QuoteFilters.php index f619559b621c..9942ee909c29 100644 --- a/app/Filters/QuoteFilters.php +++ b/app/Filters/QuoteFilters.php @@ -11,6 +11,7 @@ namespace App\Filters; +use App\Models\Quote; use App\Models\User; use Illuminate\Database\Eloquent\Builder; @@ -41,6 +42,51 @@ class QuoteFilters extends QueryFilters }); } + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - active + * - paused + * - completed + * + * @param string client_status The invoice status as seen by the client + * @return Builder + */ + public function client_status(string $value = '') :Builder + { + if (strlen($value) == 0) { + return $this->builder; + } + + $status_parameters = explode(',', $value); + + if (in_array('all', $status_parameters)) { + return $this->builder; + } + + if (in_array('draft', $status_parameters)) { + $this->builder->where('status_id', Quote::STATUS_DRAFT); + } + + if (in_array('sent', $status_parameters)) { + $this->builder->where('status_id', Quote::STATUS_SENT); + } + + if (in_array('approved', $status_parameters)) { + $this->builder->where('status_id', Quote::STATUS_APPROVED); + } + + if (in_array('expired', $status_parameters)) { + $this->builder->where('status_id', Quote::STATUS_SENT) + ->where('due_date', '<=', now()->toDateString()); + } + + return $this->builder; + } + + /** * Filters the list based on the status * archived, active, deleted. diff --git a/app/Filters/RecurringInvoiceFilters.php b/app/Filters/RecurringInvoiceFilters.php index 39f0bcaa0de7..541f24c03617 100644 --- a/app/Filters/RecurringInvoiceFilters.php +++ b/app/Filters/RecurringInvoiceFilters.php @@ -11,6 +11,7 @@ namespace App\Filters; +use App\Models\RecurringInvoice; use App\Models\User; use Illuminate\Database\Eloquent\Builder; @@ -40,6 +41,46 @@ class RecurringInvoiceFilters extends QueryFilters }); } + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - active + * - paused + * - completed + * + * @param string client_status The invoice status as seen by the client + * @return Builder + */ + public function client_status(string $value = '') :Builder + { + if (strlen($value) == 0) { + return $this->builder; + } + + $status_parameters = explode(',', $value); + + if (in_array('all', $status_parameters)) { + return $this->builder; + } + + if (in_array('active', $status_parameters)) { + $this->builder->where('status_id', RecurringInvoice::STATUS_ACTIVE); + } + + if (in_array('paused', $status_parameters)) { + $this->builder->where('status_id', RecurringInvoice::STATUS_PAUSED); + } + + if (in_array('completed', $status_parameters)) { + $this->builder->where('status_id', RecurringInvoice::STATUS_COMPLETED); + } + + return $this->builder; + } + + /** * Filters the list based on the status * archived, active, deleted. diff --git a/app/Filters/TaskFilters.php b/app/Filters/TaskFilters.php index d0f7f2419c05..f8278f506043 100644 --- a/app/Filters/TaskFilters.php +++ b/app/Filters/TaskFilters.php @@ -41,6 +41,37 @@ class TaskFilters extends QueryFilters }); } + + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - invoiced + * + * @param string client_status The invoice status as seen by the client + * @return Builder + */ + public function client_status(string $value = '') :Builder + { + if (strlen($value) == 0) { + return $this->builder; + } + + $status_parameters = explode(',', $value); + + if (in_array('all', $status_parameters)) { + return $this->builder; + } + + if (in_array('invoiced', $status_parameters)) { + $this->builder->whereNotNull('invoice_id'); + } + + return $this->builder; + } + + /** * Filters the list based on the status * archived, active, deleted. diff --git a/app/Http/Requests/Company/UpdateCompanyRequest.php b/app/Http/Requests/Company/UpdateCompanyRequest.php index 37cf05e5400e..94797598d43c 100644 --- a/app/Http/Requests/Company/UpdateCompanyRequest.php +++ b/app/Http/Requests/Company/UpdateCompanyRequest.php @@ -22,6 +22,14 @@ class UpdateCompanyRequest extends Request { use MakesHash; + private array $protected_input = [ + 'client_portal_privacy_policy', + 'client_portal_terms', + 'portal_custom_footer', + 'portal_custom_css', + 'portal_custom_head' + ]; + /** * Determine if the user is authorized to make this request. * @@ -32,6 +40,8 @@ class UpdateCompanyRequest extends Request return auth()->user()->can('edit', $this->company); } + + public function rules() { $input = $this->all(); @@ -90,6 +100,14 @@ class UpdateCompanyRequest extends Request { $account = $this->company->account; + if(Ninja::isHosted()) + { + foreach($this->protected_input as $protected_var) + { + $settings[$protected_var] = str_replace("script", "", $settings[$protected_var]); + } + } + if (! $account->isFreeHostedClient()) { return $settings; } diff --git a/app/Listeners/Invoice/InvoiceEmailFailedActivity.php b/app/Listeners/Invoice/InvoiceEmailFailedActivity.php index 122bdc972379..b46493528fb8 100644 --- a/app/Listeners/Invoice/InvoiceEmailFailedActivity.php +++ b/app/Listeners/Invoice/InvoiceEmailFailedActivity.php @@ -21,8 +21,6 @@ class InvoiceEmailFailedActivity implements ShouldQueue { protected $activity_repo; - public $delay = 5; - /** * Create the event listener. * diff --git a/app/PaymentDrivers/Forte/CreditCard.php b/app/PaymentDrivers/Forte/CreditCard.php index 336ef7b525b1..2b851a88b7fb 100644 --- a/app/PaymentDrivers/Forte/CreditCard.php +++ b/app/PaymentDrivers/Forte/CreditCard.php @@ -92,12 +92,14 @@ class CreditCard $payment_hash = PaymentHash::where('hash', $request->input('payment_hash'))->firstOrFail(); $amount_with_fee = $payment_hash->data->total->amount_with_fee; $invoice_totals = $payment_hash->data->total->invoice_totals; - $fee_total = 0; + $fee_total = null; $fees_and_limits = $this->forte->company_gateway->getFeesAndLimits(GatewayType::CREDIT_CARD); if(property_exists($fees_and_limits, 'fee_percent') && $fees_and_limits->fee_percent > 0) { + $fee_total = 0; + for ($i = ($invoice_totals * 100) ; $i < ($amount_with_fee * 100); $i++) { $calculated_fee = ( 3 * $i) / 100; $calculated_amount_with_fee = round(($i + $calculated_fee) / 100,2); diff --git a/app/Utils/Helpers.php b/app/Utils/Helpers.php index 25a36e55d09e..e512ee3cb73b 100644 --- a/app/Utils/Helpers.php +++ b/app/Utils/Helpers.php @@ -144,9 +144,9 @@ class Helpers ':QUARTER' => 'Q'.now()->quarter, ':WEEK_BEFORE' => \sprintf( '%s %s %s', - Carbon::now()->subDays(6)->translatedFormat($entity->date_format()), + Carbon::now()->subDays(7)->translatedFormat($entity->date_format()), ctrans('texts.to'), - Carbon::now()->translatedFormat($entity->date_format()) + Carbon::now()->subDays(1)->translatedFormat($entity->date_format()) ), ':WEEK_AHEAD' => \sprintf( '%s %s %s', @@ -156,9 +156,9 @@ class Helpers ), ':WEEK' => \sprintf( '%s %s %s', - Carbon::now()->translatedFormat($entity->date_format()), + Carbon::now()->subDays(7)->translatedFormat($entity->date_format()), ctrans('texts.to'), - Carbon::now()->addDays(6)->translatedFormat($entity->date_format()) + Carbon::now()->addDays(13)->translatedFormat($entity->date_format()) ), ], 'raw' => [ diff --git a/config/ninja.php b/config/ninja.php index a3bb71301c2d..edfc4c68b0f2 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.5.40', - 'app_tag' => '5.5.40', + 'app_version' => '5.5.41', + 'app_tag' => '5.5.41', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), diff --git a/lang/en/texts.php b/lang/en/texts.php index fe2e75ac1590..3817b0d65129 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -4839,6 +4839,10 @@ $LANG = array( 'show_tasks_in_client_portal' => 'Show Tasks in Client Portal', 'notification_quote_expired_subject' => 'Quote :invoice has expired for :client', 'notification_quote_expired' => 'The following Quote :invoice for client :client and :amount has now expired.', + 'auto_sync' => 'Auto Sync', + 'refresh_accounts' => 'Refresh Accounts', + 'upgrade_to_connect_bank_account' => 'Upgrade to Enterprise to connect your bank account', + 'click_here_to_connect_bank_account' => 'Click here to connect your bank account', ); return $LANG; diff --git a/resources/views/portal/ninja2020/layout/app.blade.php b/resources/views/portal/ninja2020/layout/app.blade.php index e2aed0225bbb..a68a47b90b41 100644 --- a/resources/views/portal/ninja2020/layout/app.blade.php +++ b/resources/views/portal/ninja2020/layout/app.blade.php @@ -163,7 +163,7 @@ @yield('footer') @stack('footer') - @if((bool) \App\Utils\Ninja::isSelfHost() && !empty($client->getSetting('portal_custom_footer'))) + @if($company && $company->account->isPaid() && !empty($client->getSetting('portal_custom_footer')))