Merge pull request #7349 from turbo124/v5-stable

v5.3.78
This commit is contained in:
David Bomba 2022-03-31 08:26:32 +11:00 committed by GitHub
commit 9d7e008fc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 713628 additions and 624331 deletions

View File

@ -1 +1 @@
5.3.77
5.3.78

View File

@ -86,8 +86,6 @@ class HostedMigrations extends Command
$path = public_path('storage/migrations/import');
nlog(public_path('storage/migrations/import'));
$directory = new DirectoryIterator($path);
foreach ($directory as $file) {

View File

@ -80,8 +80,6 @@ class ImportMigrations extends Command
$path = $this->option('path') ?? public_path('storage/migrations/import');
nlog(public_path('storage/migrations/import'));
$directory = new DirectoryIterator($path);
foreach ($directory as $file) {

View File

@ -46,7 +46,6 @@ class BaseSettings
return is_null($value) ? '' : (string) $value;
case 'bool':
case 'boolean':
nlog($value);
return boolval($value);
case 'object':
return json_decode($value);

View File

@ -124,7 +124,7 @@ class Handler extends ExceptionHandler
}
});
if ($this->validException($exception) && auth()->guard('contact')->user()->company->account->report_errors) {
if ($this->validException($exception)) {
app('sentry')->captureException($exception);
}
}

View File

@ -54,10 +54,7 @@ class ProRata
{
$days = $from_date->copy()->diffInDays($to_date);
$days_in_frequency = $this->getDaysInFrequency($frequency);
nlog($from_date->format('Y-m-d'));
nlog($days);
nlog($days_in_frequency);
nlog($amount);
return round( (($days/$days_in_frequency) * $amount),2);
}

View File

@ -276,6 +276,7 @@ class RecurringExpenseController extends BaseController
}
$recurring_expense = $this->recurring_expense_repo->save($request->all(), $recurring_expense);
$recurring_expense->service()->triggeredActions($request)->save();
$this->uploadLogo($request->file('company_logo'), $recurring_expense->company, $recurring_expense);
@ -372,6 +373,7 @@ class RecurringExpenseController extends BaseController
public function store(StoreRecurringExpenseRequest $request)
{
$recurring_expense = $this->recurring_expense_repo->save($request->all(), RecurringExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id));
$recurring_expense->service()->triggeredActions($request)->save();
event(new RecurringExpenseWasCreated($recurring_expense, $recurring_expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -388,7 +388,10 @@ class RecurringInvoiceController extends BaseController
$recurring_invoice = $this->recurring_invoice_repo->save($request->all(), $recurring_invoice);
$recurring_invoice->service()->deletePdf()->save();
$recurring_invoice->service()
->triggeredActions($request)
->deletePdf()
->save();
event(new RecurringInvoiceWasUpdated($recurring_invoice, $recurring_invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -280,6 +280,7 @@ class TaskController extends BaseController
$old_task = json_decode(json_encode($task));
$task = $this->task_repo->save($request->all(), $task);
$task = $this->task_repo->triggeredActions($request, $task);
if($task->status_order != $old_task->status_order)
$this->task_repo->sortStatuses($old_task, $task);
@ -377,6 +378,7 @@ class TaskController extends BaseController
public function store(StoreTaskRequest $request)
{
$task = $this->task_repo->save($request->all(), TaskFactory::create(auth()->user()->company()->id, auth()->user()->id));
$task = $this->task_repo->triggeredActions($request, $task);
event(new TaskWasCreated($task, $task->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -238,6 +238,7 @@ class BillingPortalPurchase extends Component
{
$company = $this->subscription->company;
$user = $this->subscription->user;
$user->setCompany($company);
$client_repo = new ClientRepository(new ClientContactRepository());

View File

@ -75,12 +75,6 @@ class PaymentAmountsBalanceRule implements Rule
return true;
}
// nlog(request()->input('invoices'));
// nlog($payment_amounts);
// nlog($invoice_amounts);
// nlog(request()->all());
nlog($payment_amounts ." >= " . $invoice_amounts);
return round($payment_amounts,2) >= round($invoice_amounts,2);
}

View File

@ -74,7 +74,6 @@ class BaseTransformer
->where('id_number', $client_name);
if ($client_id_search->count() >= 1) {
// nlog("found via id number => {$client_id_search->first()->id}");
return $client_id_search->first()->id;
}
@ -83,7 +82,6 @@ class BaseTransformer
->where('name', $client_name);
if ($client_name_search->count() >= 1) {
// nlog("found via name {$client_name_search->first()->id}");
return $client_name_search->first()->id;
}
}
@ -94,13 +92,10 @@ class BaseTransformer
)->where('email', $client_email);
if ($contacts->count() >= 1) {
// nlog("found via contact {$contacts->first()->client_id}");
return $contacts->first()->client_id;
}
}
// nlog("did not find client");
return null;
}

View File

@ -66,14 +66,12 @@ class BaseTransformer
if ( $client_id_search->count() >= 1 ) {
return $client_id_search->first()->id;
nlog("found via id number");
}
$client_name_search = $clients->where( 'name', $client_name );
if ( $client_name_search->count() >= 1 ) {
return $client_name_search->first()->id;
nlog("found via name");
}
if ( ! empty( $client_email ) ) {
@ -82,10 +80,8 @@ class BaseTransformer
if ( $contacts->count() >= 1 ) {
return $contacts->first()->client_id;
nlog("found via contact");
}
}
// nlog("did not find client");
return null;
}

View File

@ -483,8 +483,6 @@ class CompanyImport implements ShouldQueue
$tmp_company->db = config('database.default');
$tmp_company->account_id = $this->account->id;
nlog($tmp_company);
if(Ninja::isHosted())
$tmp_company->subdomain = MultiDB::randomSubdomainGenerator();
else

View File

@ -46,7 +46,7 @@ class SupportMessageSent extends Mailable
$log_file->seek(PHP_INT_MAX);
$last_line = $log_file->key();
$lines = new LimitIterator($log_file, $last_line - 100, $last_line);
$lines = new LimitIterator($log_file, max(0,$last_line - 100), $last_line);
$log_lines = iterator_to_array($lines);
}
@ -76,7 +76,7 @@ class SupportMessageSent extends Mailable
->replyTo($user->email, $user->present()->name())
->subject($subject)
->view('email.support.message', [
'support_message' => $this->data['message'],
'support_message' => nl2br($this->data['message']),
'system_info' => $system_info,
'laravel_log' => $log_lines,
'logo' => $company->present()->logo(),

View File

@ -529,17 +529,17 @@ class Client extends BaseModel implements HasLocalePreference
}
if ($this->currency()->code == 'EUR' && in_array(GatewayType::SEPA, array_column($pms, 'gateway_type_id'))) {
foreach ($pms as $pm) {
if ($pm['gateway_type_id'] == GatewayType::SEPA) {
$cg = CompanyGateway::find($pm['company_gateway_id']);
// if ($this->currency()->code == 'EUR' && in_array(GatewayType::SEPA, array_column($pms, 'gateway_type_id'))) {
// foreach ($pms as $pm) {
// if ($pm['gateway_type_id'] == GatewayType::SEPA) {
// $cg = CompanyGateway::find($pm['company_gateway_id']);
if ($cg && $cg->fees_and_limits->{GatewayType::SEPA}->is_enabled) {
return $cg;
}
}
}
}
// if ($cg && $cg->fees_and_limits->{GatewayType::SEPA}->is_enabled) {
// return $cg;
// }
// }
// }
// }
if ($this->country && $this->country->iso_3166_3 == 'GBR' && in_array(GatewayType::DIRECT_DEBIT, array_column($pms, 'gateway_type_id'))) {
foreach ($pms as $pm) {

View File

@ -99,6 +99,7 @@ class Company extends BaseModel
'report_include_drafts',
'client_registration_fields',
'convert_rate_to_client',
'markdown_email_enabled',
];
protected $hidden = [

View File

@ -255,9 +255,6 @@ class CreditCard
$response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction);
nlog('eway');
nlog($response);
$response_status = ErrorCode::getStatus($response->ResponseMessage);
if(!$response_status['success']){

View File

@ -151,8 +151,6 @@ class PayFastPaymentDriver extends BaseDriver
if($this->company_gateway->getConfigField('passphrase'))
$fields['passphrase'] = $this->company_gateway->getConfigField('passphrase');
nlog(http_build_query($fields));
return md5(http_build_query($fields));
}

View File

@ -34,6 +34,12 @@ class SEPA
public function authorizeView($data)
{
$data['gateway'] = $this->stripe;
$data['payment_method_id'] = GatewayType::SEPA;
$data['client'] = $this->stripe->client;
$data['country'] = $this->stripe->client->country->iso_3166_2;
$data['currency'] = $this->stripe->client->currency();
return render('gateways.stripe.sepa.authorize', $data);
}

View File

@ -13,6 +13,7 @@ namespace App\Repositories;
use App\Factory\ClientFactory;
use App\Models\Client;
use App\Models\Company;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\SavesDocuments;
@ -60,9 +61,9 @@ class ClientRepository extends BaseRepository
$client->fill($data);
if(auth()->user() && !$client->country_id){
$client->country_id = auth()->user()->company()->settings->country_id;
if(!$client->country_id){
$company = Company::find($client->company_id);
$client->country_id = $company->settings->country_id;
}

View File

@ -203,7 +203,7 @@ class TaskRepository extends BaseRepository
$last = end($log);
if($last[1] !== 0){
if(is_array($last) && $last[1] !== 0){
$new = [time(), 0];
$log = array_merge($log, [$new]);
@ -212,6 +212,7 @@ class TaskRepository extends BaseRepository
}
return $task;
}
public function stop(Task $task)
@ -220,7 +221,7 @@ class TaskRepository extends BaseRepository
$last = end($log);
if($last[1] === 0){
if(is_array($last) && $last[1] === 0){
$last[1] = time();
@ -231,5 +232,21 @@ class TaskRepository extends BaseRepository
$task->save();
}
return $task;
}
public function triggeredActions($request, $task)
{
if ($request->has('start') && $request->input('start') == 'true') {
$task = $this->start($task);
}
if ($request->has('stop') && $request->input('stop') == 'true') {
$task = $this->stop($task);
}
return $task;
}
}

View File

@ -41,70 +41,15 @@ class HandleRestore extends AbstractService
foreach ($this->invoice->payments as $payment) {
//restore the payment record
// $payment->restore();
$this->invoice->restore();
// //determine the paymentable amount before paymentable restoration
// $pre_restore_amount = $payment->paymentables()
// ->where('paymentable_type', '=', 'invoices')
// ->sum(\DB::raw('amount'));
// nlog("first pre restore amount = {$pre_restore_amount}");
// $pre_restore_amount -= $payment->paymentables()
// ->where('paymentable_type', '=', 'invoices')
// ->sum(\DB::raw('refunded'));
// nlog("second pre restore amount = {$pre_restore_amount}");
//restore the paymentables
// $payment->paymentables()
// ->where('paymentable_type', '=', 'invoices')
// ->where('paymentable_id', $this->invoice->id)
// ->restore();
//determine the post restore paymentable amount (we need to increment the payment amount by the difference between pre and post)
// $payment_amount = $payment->paymentables()
// ->where('paymentable_type', '=', 'invoices')
// ->sum(\DB::raw('amount'));
// nlog("first payment_amount = {$payment_amount}");
// $payment_amount -= $payment->paymentables()
// ->where('paymentable_type', '=', 'invoices')
// ->sum(\DB::raw('refunded'));
// nlog("second payment_amount = {$payment_amount}");
// nlog($payment->amount . " == " . $payment_amount);
// if ($payment->amount == $payment_amount) {
// $payment->is_deleted = false;
// $payment->save();
// $this->payment_total += $payment_amount;
// } else {
// $payment->is_deleted = false;
// $payment->amount += ($payment_amount - $pre_restore_amount);
// $payment->applied += ($payment_amount - $pre_restore_amount);
// $payment->save();
// $this->payment_total += ($payment_amount - $pre_restore_amount);
// }
}
//adjust ledger balance
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance, "Restored invoice {$this->invoice->number}")->save();
//adjust paid to dates
// $this->invoice->client->service()->updatePaidToDate($this->payment_total)->save();
$this->invoice->client->service()->updateBalance($this->invoice->balance)->save();
// you only need to touch the ledger ONCE per transaction.
// $this->invoice->ledger()->updatePaymentBalance($this->payment_total*-1, "Restored payment for invoice {$this->invoice->number}")->save();
$this->windBackInvoiceNumber();
$this->invoice->is_deleted = false;

View File

@ -362,6 +362,8 @@ class InvoiceService
if(!collect($this->invoice->line_items)->contains('type_id', 3))
return $this;
$pre_count = count($this->invoice->line_items);
$this->invoice->line_items = collect($this->invoice->line_items)
->reject(function ($item) {
return $item->type_id == '3';
@ -372,7 +374,7 @@ class InvoiceService
/* 24-03-2022 */
$new_balance = $this->invoice->balance;
if(floatval($balance) - floatval($new_balance) != 0)
if($pre_count != count($this->invoice->line_items))
{
$adjustment = $balance - $new_balance;

View File

@ -96,17 +96,10 @@ class MarkPaid extends AbstractService
$payment->ledger()
->updatePaymentBalance($payment->amount * -1);
// $client = $this->invoice->client->fresh();
// $client->paid_to_date += $payment->amount;
// $client->balance += $payment->amount * -1;
// $client->save();
$this->invoice
->client
->service()
->updateBalance($payment->amount * -1)
->updatePaidToDate($payment->amount)
->save();
$this->invoice->client->fresh();
$this->invoice->client->paid_to_date += $payment->amount;
$this->invoice->client->balance += $payment->amount * -1;
$this->invoice->client->push();
$this->invoice = $this->invoice
->service()

View File

@ -47,12 +47,6 @@ class MarkSent extends AbstractService
->updateBalance($adjustment, true)
->save();
/*Adjust client balance*/
$this->client
->service()
->updateBalance($adjustment)
->save();
/*Update ledger*/
$this->invoice
->ledger()
@ -68,6 +62,12 @@ class MarkSent extends AbstractService
->setReminder()
->save();
/*Adjust client balance*/
$this->client->fresh();
$this->client->balance += $adjustment;
$this->client->save();
$this->invoice->markInvitationsSent();
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -57,6 +57,9 @@ class TriggeredActions extends AbstractService
$this->invoice = $this->invoice->service()->markSent()->save();
}
if ($this->request->has('cancel') && $this->request->input('cancel') == 'true') {
$this->invoice = $this->invoice->service()->handleCancellation()->save();
}
return $this->invoice;
}

View File

@ -678,7 +678,7 @@ class Design extends BaseDesign
$elements = [
['element' => 'div', 'properties' => ['style' => 'display: flex; flex-direction: column;'], 'elements' => [
['element' => 'p', 'content' => strtr(str_replace("labels", "", $_variables['values']['$entity.public_notes']), $_variables), 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;']],
['element' => 'p', 'content' => strtr(str_replace(["labels","values"], ["",""], $_variables['values']['$entity.public_notes']), $_variables), 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;']],
['element' => 'p', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column; page-break-inside: auto;'], 'elements' => [
['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['hidden' => $this->entityVariableCheck('$entity.terms'), 'data-ref' => 'total_table-terms-label', 'style' => 'font-weight: bold; text-align: left; margin-top: 1rem;']],
['element' => 'span', 'content' => strtr(str_replace("labels", "", $_variables['values']['$entity.terms']), $_variables['labels']), 'properties' => ['data-ref' => 'total_table-terms', 'style' => 'text-align: left;']],

View File

@ -50,6 +50,10 @@ class TriggeredActions extends AbstractService
$this->quote = $this->quote->service()->convert()->save();
}
if ($this->request->has('approve') && $this->request->input('approve') == 'true' && in_array($this->quote->status_id, [Quote::STATUS_SENT, Quote::STATUS_DRAFT])) {
$this->quote = $this->quote->service()->convert()->save();
}
return $this->quote;
}

View File

@ -167,6 +167,7 @@ class CompanyTransformer extends EntityTransformer
'report_include_drafts' => (bool) $company->report_include_drafts,
'client_registration_fields' => (array) $company->client_registration_fields,
'convert_rate_to_client' => (bool) $company->convert_rate_to_client,
'markdown_email_enabled' => (bool) $company->markdown_email_enabled,
];
}

View File

@ -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.3.77',
'app_tag' => '5.3.77',
'app_version' => '5.3.78',
'app_tag' => '5.3.78',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -0,0 +1,46 @@
<?php
use App\Models\Company;
use App\Models\Gateway;
use App\Utils\Ninja;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ReverseAppleDomainForHosted extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if(Ninja::isHosted())
{
$stripe_connect = Gateway::find(56);
if($stripe_connect){
$stripe_connect->fields = '{"account_id":""}';
$stripe_connect->save();
}
}
Company::cursor()->each(function ($company){
$company->update(['markdown_email_enabled' => true]);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -2293,6 +2293,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--------------------------------------------------------------------------------
args
csslib
logging
Copyright 2013, the Dart project authors.
@ -11856,6 +11857,62 @@ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
--------------------------------------------------------------------------------
html
Copyright (c) 2006-2012 The Authors
Contributors:
James Graham - jg307@cam.ac.uk
Anne van Kesteren - annevankesteren@gmail.com
Lachlan Hunt - lachlan.hunt@lachy.id.au
Matt McDonald - kanashii@kanashii.ca
Sam Ruby - rubys@intertwingly.net
Ian Hickson (Google) - ian@hixie.ch
Thomas Broyer - t.broyer@ltgt.net
Jacques Distler - distler@golem.ph.utexas.edu
Henri Sivonen - hsivonen@iki.fi
Adam Barth - abarth@webkit.org
Eric Seidel - eric@webkit.org
The Mozilla Foundation (contributions from Henri Sivonen since 2008)
David Flanagan (Mozilla) - dflanagan@mozilla.com
Google Inc. (contributed the Dart port) - misc@dartlang.org
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
html2md
BSD 2-Clause License
Copyright (c) 2018, Jaron Tai
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
http_multi_server

View File

@ -25,14 +25,14 @@ const RESOURCES = {
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "015400679694f1f51047e46da0e1dc98",
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
"assets/NOTICES": "6820525c3248a35b97051cac66bfeed4",
"assets/NOTICES": "77252e3089798e3055aba40bd2362d84",
"assets/fonts/MaterialIcons-Regular.otf": "7e7a6cccddf6d7b20012a548461d5d81",
"favicon.ico": "51636d3a390451561744c42188ccd628",
"/": "ceb3b368aacf6f0124e5e6d7c76b5b89",
"/": "2aaa2367b17c44e0c497272dedb15e37",
"version.json": "443986d36b3df952ad780139ecccd516",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"main.dart.js": "6043add2238de74021ea2fb01f9aec7b",
"main.dart.js": "b4fed37271543049124ee6a37767a56d",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
"canvaskit/profiling/canvaskit.js": "ae2949af4efc61d28a4a80fffa1db900",

323707
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

321974
public/main.foss.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

323140
public/main.html.dart.js vendored

File diff suppressed because one or more lines are too long

322511
public/main.next.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,8 @@
@component('email.template.admin', ['settings' => $settings, 'logo' => $logo ?? 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
{{-- Body --}}
{{ $support_message }}
{!! $support_message !!}
<hr>
{!! str_replace('\n', '<br>', $system_info) !!}

View File

@ -31,7 +31,7 @@
@endif
<!-- Title -->
@if(isset($account) && !$account->isPaid())
@if(isset($company->account) && !$company->account->isPaid())
<title>@yield('meta_title', '') Invoice Ninja</title>
@elseif(isset($company) && !is_null($company))
<title>@yield('meta_title', '') {{ $company->present()->name() }}</title>
@ -74,7 +74,7 @@
{{-- Feel free to push anything to header using @push('header') --}}
@stack('head')
@if((isset($account) && $account->isPaid()) || ((bool) \App\Utils\Ninja::isSelfHost() && !empty($client->getSetting('portal_custom_head'))))
@if((isset($company) && $company->account->isPaid() && !empty($client->getSetting('portal_custom_head'))) || ((bool) \App\Utils\Ninja::isSelfHost() && !empty($client->getSetting('portal_custom_head'))))
<div class="py-1 text-sm text-center text-white bg-primary">
{!! $client->getSetting('portal_custom_head') !!}
</div>

View File

@ -211,5 +211,76 @@ class RecurringExpenseApiTest extends TestCase
$this->assertEquals(RecurringInvoice::STATUS_PAUSED, $arr['data'][0]['status_id']);
}
public function testRecurringExpenseStartedWithTriggeredAction()
{
$data = [
'ids' => [$this->encodePrimaryKey($this->recurring_expense->id)],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/recurring_expenses/'.$this->recurring_expense->hashed_id.'?start=true', []);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_ACTIVE, $arr['data']['status_id']);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/recurring_expenses/'.$this->recurring_expense->hashed_id.'?stop=true', []);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_PAUSED, $arr['data']['status_id']);
}
public function testRecurringExpensePostWithStartAction()
{
$data = [
'amount' => 10,
'client_id' => $this->client->hashed_id,
'number' => '123321',
'frequency_id' => 5,
'remaining_cycles' =>5
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/recurring_expenses?start=true', $data);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_ACTIVE, $arr['data']['status_id']);
}
public function testRecurringExpensePostWithStopAction()
{
$data = [
'amount' => 10,
'client_id' => $this->client->hashed_id,
'number' => '1233x21',
'frequency_id' => 5,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/recurring_expenses?stop=true', $data);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_PAUSED, $arr['data']['status_id']);
}
}

View File

@ -50,6 +50,79 @@ class RecurringInvoiceTest extends TestCase
$this->makeTestData();
}
public function testPostRecurringInvoice()
{
$data = [
'frequency_id' => 1,
'status_id' => 1,
'discount' => 0,
'is_amount_discount' => 1,
'po_number' => '3434343',
'public_notes' => 'notes',
'is_deleted' => 0,
'custom_value1' => 0,
'custom_value2' => 0,
'custom_value3' => 0,
'custom_value4' => 0,
'status' => 1,
'client_id' => $this->encodePrimaryKey($this->client->id),
'line_items' => $this->buildLineItems(),
'remaining_cycles' => -1,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/recurring_invoices/', $data)
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_DRAFT, $arr['data']['status_id']);
}
public function testPostRecurringInvoiceWithStartAndStop()
{
$data = [
'frequency_id' => 1,
'status_id' => 1,
'discount' => 0,
'is_amount_discount' => 1,
'po_number' => '3434343',
'public_notes' => 'notes',
'is_deleted' => 0,
'custom_value1' => 0,
'custom_value2' => 0,
'custom_value3' => 0,
'custom_value4' => 0,
'status' => 1,
'client_id' => $this->encodePrimaryKey($this->client->id),
'line_items' => $this->buildLineItems(),
'remaining_cycles' => -1,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/recurring_invoices?start=true', $data)
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_ACTIVE, $arr['data']['status_id']);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/recurring_invoices/'.$arr['data']['id'].'?stop=true', $data)
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(RecurringInvoice::STATUS_PAUSED, $arr['data']['status_id']);
}
public function testRecurringInvoiceList()
{
Client::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id])->each(function ($c) {

View File

@ -90,7 +90,7 @@ class TaskApiTest extends TestCase
$response->assertStatus(200);
$this->assertEquals('taskynumber', $arr['data']['number']);
$this->assertLessThan(5, strlen($arr['data']['time_log']));
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
@ -113,6 +113,23 @@ class TaskApiTest extends TestCase
$this->assertNotEmpty($arr['data']['number']);
}
public function testTaskPostNoDefinedTaskNumber()
{
$data = [
'description' => $this->faker->firstName,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/tasks', $data);
$arr = $response->json();
$response->assertStatus(200);
$this->assertNotEmpty($arr['data']['number']);
}
public function testTaskPostWithActionStart()
{
$data = [
@ -224,4 +241,46 @@ class TaskApiTest extends TestCase
$this->assertTrue($arr['data'][0]['is_deleted']);
}
public function testTaskPostWithStartAction()
{
$data = [
'description' => $this->faker->firstName,
'number' => 'taskynumber2'
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/tasks?start=true', $data);
$arr = $response->json();
$response->assertStatus(200);
$this->assertEquals('taskynumber2', $arr['data']['number']);
$this->assertGreaterThan(5, strlen($arr['data']['time_log']));
}
public function testTaskPostWithStopAction()
{
$data = [
'description' => $this->faker->firstName,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/tasks?stop=true', $data);
$arr = $response->json();
$response->assertStatus(200);
$this->assertLessThan(5, strlen($arr['data']['time_log']));
}
}

View File

@ -182,7 +182,8 @@ class CompanyLedgerTest extends TestCase
//client->balance should = 10
$invoice->service()->markSent()->save();
$this->assertEquals($invoice->client->balance, 10);
$this->client = Client::find($this->client->id);
$this->assertEquals($this->client->balance, 10);
$invoice_ledger = $invoice->company_ledger->sortByDesc('id')->first();