mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
e1b2afd871
@ -36,6 +36,10 @@ class ExpenseMap
|
||||
17 => 'expense.tax_rate3',
|
||||
18 => 'expense.uses_inclusive_taxes',
|
||||
19 => 'expense.payment_date',
|
||||
20 => 'expense.custom_value1',
|
||||
21 => 'expense.custom_value2',
|
||||
22 => 'expense.custom_value3',
|
||||
23 => 'expense.custom_value4',
|
||||
|
||||
];
|
||||
}
|
||||
@ -63,6 +67,10 @@ class ExpenseMap
|
||||
17 => 'texts.tax_rate3',
|
||||
18 => 'texts.uses_inclusive_taxes',
|
||||
19 => 'texts.payment_date',
|
||||
20 => 'texts.custom_value1',
|
||||
21 => 'texts.custom_value2',
|
||||
22 => 'texts.custom_value3',
|
||||
23 => 'texts.custom_value4',
|
||||
|
||||
];
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class CreateAccount
|
||||
$sp794f3f->hosted_company_count = config('ninja.quotas.free.max_companies');
|
||||
$sp794f3f->account_sms_verified = true;
|
||||
|
||||
if(in_array($this->getDomain($this->request['email']), ['gmail.com', 'hotmail.com', 'outlook.com', 'yahoo.com', 'aol.com', 'mail.ru'])){
|
||||
if(in_array($this->getDomain($this->request['email']), ['yopmail.com','gmail.com', 'hotmail.com', 'outlook.com', 'yahoo.com', 'aol.com', 'mail.ru'])){
|
||||
$sp794f3f->account_sms_verified = false;
|
||||
}
|
||||
|
||||
|
@ -515,8 +515,8 @@ class CompanyExport implements ShouldQueue
|
||||
|
||||
$path = 'backups';
|
||||
|
||||
if(!Storage::disk(config('filesystems.default'))->exists($path))
|
||||
Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
|
||||
// if(!Storage::disk(config('filesystems.default'))->exists($path))
|
||||
// Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
|
||||
|
||||
$zip_path = public_path('storage/backups/'.$file_name);
|
||||
$zip = new \ZipArchive();
|
||||
|
@ -213,11 +213,13 @@ class CreateEntityPdf implements ShouldQueue
|
||||
|
||||
if ($pdf) {
|
||||
try {
|
||||
if (! Storage::disk($this->disk)->exists($path)) {
|
||||
Storage::disk($this->disk)->makeDirectory($path, 0775);
|
||||
}
|
||||
// if (! Storage::disk($this->disk)->exists($path)) {
|
||||
// Storage::disk($this->disk)->makeDirectory($path, 0775);
|
||||
// }
|
||||
|
||||
Storage::disk($this->disk)->put($file_path, $pdf, 'public');
|
||||
|
||||
//r2 Storage::disk($this->disk)->put($file_path, $pdf);
|
||||
} catch (\Exception $e) {
|
||||
throw new FilePermissionsFailure($e->getMessage());
|
||||
}
|
||||
|
@ -83,9 +83,23 @@ class UpdateOrCreateProduct implements ShouldQueue
|
||||
|
||||
$product = Product::withTrashed()->firstOrNew(['product_key' => $item->product_key, 'company_id' => $this->invoice->company->id]);
|
||||
|
||||
/* If a user is using placeholders in their descriptions, do not update the products */
|
||||
$string_hit = false;
|
||||
|
||||
foreach ( [':MONTH',':YEAR',':QUARTER',':WEEK'] as $string )
|
||||
{
|
||||
|
||||
if(stripos($product->notes, $string) !== FALSE) {
|
||||
$string_hit = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($string_hit)
|
||||
continue;
|
||||
|
||||
$product->product_key = $item->product_key;
|
||||
$product->notes = isset($item->notes) ? $item->notes : '';
|
||||
//$product->cost = isset($item->cost) ? $item->cost : 0; //this value shouldn't be updated.
|
||||
$product->price = isset($item->cost) ? $item->cost : 0;
|
||||
|
||||
if (! $product->id) {
|
||||
|
6
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
6
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
@ -100,11 +100,13 @@ class CreatePurchaseOrderPdf implements ShouldQueue
|
||||
|
||||
try{
|
||||
|
||||
if(!Storage::disk($this->disk)->exists($this->path))
|
||||
Storage::disk($this->disk)->makeDirectory($this->path, 0775);
|
||||
// if(!Storage::disk($this->disk)->exists($this->path))
|
||||
// Storage::disk($this->disk)->makeDirectory($this->path, 0775);
|
||||
|
||||
Storage::disk($this->disk)->put($this->file_path, $pdf, 'public');
|
||||
|
||||
//r2 Storage::disk($this->disk)->put($this->file_path, $pdf);
|
||||
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
|
@ -146,10 +146,17 @@ class TemplateEmail extends Mailable
|
||||
|
||||
}
|
||||
|
||||
//22-10-2022 - Performance - To improve the performance/reliability of sending emails, attaching as Data is much better, stubs in place
|
||||
foreach ($this->build_email->getAttachments() as $file) {
|
||||
if (is_string($file)) {
|
||||
// nlog($file);
|
||||
// $file_data = file_get_contents($file);
|
||||
// $this->attachData($file_data, basename($file));
|
||||
$this->attach($file);
|
||||
} elseif (is_array($file)) {
|
||||
// nlog($file['path']);
|
||||
// $file_data = file_get_contents($file['path']);
|
||||
// $this->attachData($file_data, $file['name']);
|
||||
$this->attach($file['path'], ['as' => $file['name'], 'mime' => null]);
|
||||
}
|
||||
}
|
||||
|
@ -36,15 +36,15 @@ class Backup extends BaseModel
|
||||
$filename = now()->format('Y_m_d').'_'.md5(time()).'.html';
|
||||
$file_path = $path.$filename;
|
||||
|
||||
Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
|
||||
// Storage::disk(config('filesystems.default'))->makeDirectory($path, 0775);
|
||||
|
||||
Storage::disk(config('filesystems.default'))->put($file_path, $html);
|
||||
|
||||
if (Storage::disk(config('filesystems.default'))->exists($file_path)) {
|
||||
// if (Storage::disk(config('filesystems.default'))->exists($file_path)) {
|
||||
$this->html_backup = '';
|
||||
$this->filename = $file_path;
|
||||
$this->save();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
public function deleteFile()
|
||||
|
@ -602,11 +602,11 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->company_gateway->require_contact_email) {
|
||||
if ($this->checkRequiredResource($this->email)) {
|
||||
$this->required_fields[] = 'contact_email';
|
||||
}
|
||||
}
|
||||
// if ($this->company_gateway->require_contact_email) {
|
||||
// if ($this->checkRequiredResource($this->email)) {
|
||||
// $this->required_fields[] = 'contact_email';
|
||||
// }
|
||||
// }
|
||||
|
||||
// if ($this->company_gateway->require_contact_name) {
|
||||
// if ($this->checkRequiredResource($this->first_name)) {
|
||||
|
@ -14,9 +14,11 @@ namespace App\PaymentDrivers\CheckoutCom;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Payment;
|
||||
use App\Models\SystemLog;
|
||||
use App\PaymentDrivers\CheckoutComPaymentDriver;
|
||||
use App\PaymentDrivers\Common\MethodInterface;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -242,6 +244,16 @@ class CreditCard implements MethodInterface
|
||||
if ($response['status'] == 'Declined') {
|
||||
$this->checkout->unWindGatewayFees($this->checkout->payment_hash);
|
||||
|
||||
//18-10-2022
|
||||
SystemLogger::dispatch(
|
||||
$response,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_ERROR,
|
||||
SystemLog::TYPE_CHECKOUT,
|
||||
$this->checkout->client,
|
||||
$this->checkout->client->company,
|
||||
);
|
||||
|
||||
return $this->processUnsuccessfulPayment($response);
|
||||
}
|
||||
} catch (CheckoutApiException $e) {
|
||||
|
@ -49,8 +49,8 @@ class EntityPolicy
|
||||
return ($user->isAdmin() && $entity->company_id == $user->companyId())
|
||||
|| ($user->hasPermission('edit_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId())
|
||||
|| ($user->hasPermission('edit_all') && $entity->company_id == $user->companyId())
|
||||
|| $user->owns($entity)
|
||||
|| $user->assigned($entity);
|
||||
|| ($user->owns($entity) && $entity->company_id == $user->companyId())
|
||||
|| ($user->assigned($entity) && $entity->company_id == $user->companyId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +66,7 @@ class EntityPolicy
|
||||
return ($user->isAdmin() && $entity->company_id == $user->companyId())
|
||||
|| ($user->hasPermission('view_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId())
|
||||
|| ($user->hasPermission('view_all') && $entity->company_id == $user->companyId())
|
||||
|| $user->owns($entity)
|
||||
|| $user->assigned($entity);
|
||||
|| ($user->owns($entity) && $entity->company_id == $user->companyId())
|
||||
|| ($user->assigned($entity) && $entity->company_id == $user->companyId());
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ class ActivityRepository extends BaseRepository
|
||||
|
||||
$activity->save();
|
||||
|
||||
$this->createBackup($entity, $activity);
|
||||
//rate limiter
|
||||
// $this->createBackup($entity, $activity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +83,8 @@ class ActivityRepository extends BaseRepository
|
||||
$backup = new Backup();
|
||||
$entity->load('client');
|
||||
$contact = $entity->client->primary_contact()->first();
|
||||
$backup->html_backup = $this->generateHtml($entity);
|
||||
$backup->html_backup = '';
|
||||
// $backup->html_backup = $this->generateHtml($entity);
|
||||
$backup->amount = $entity->amount;
|
||||
$backup->activity_id = $activity->id;
|
||||
$backup->json_backup = '';
|
||||
|
@ -19,9 +19,11 @@ use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Utils\Helpers;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use Google\Service\Vision\Property;
|
||||
use ReflectionClass;
|
||||
|
||||
class BaseRepository
|
||||
@ -108,32 +110,6 @@ class BaseRepository
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $ids
|
||||
* @param $action
|
||||
*
|
||||
* @return int
|
||||
* @deprecated - this doesn't appear to be used anywhere?
|
||||
*/
|
||||
// public function bulk($ids, $action)
|
||||
// {
|
||||
// if (! $ids) {
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// $ids = $this->transformKeys($ids);
|
||||
|
||||
// $entities = $this->findByPublicIdsWithTrashed($ids);
|
||||
|
||||
// foreach ($entities as $entity) {
|
||||
// if (auth()->user()->can('edit', $entity)) {
|
||||
// $this->$action($entity);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return count($entities);
|
||||
// }
|
||||
|
||||
/* Returns an invoice if defined as a key in the $resource array*/
|
||||
public function getInvitation($invitation, $resource)
|
||||
{
|
||||
@ -171,7 +147,7 @@ class BaseRepository
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function alternativeSave($data, $model)
|
||||
{
|
||||
{ //$start = microtime(true);
|
||||
//forces the client_id if it doesn't exist
|
||||
if(array_key_exists('client_id', $data))
|
||||
$model->client_id = $data['client_id'];
|
||||
@ -208,9 +184,21 @@ class BaseRepository
|
||||
$model->custom_surcharge_tax3 = $client->company->custom_surcharge_taxes3;
|
||||
$model->custom_surcharge_tax4 = $client->company->custom_surcharge_taxes4;
|
||||
|
||||
if(!$model->id)
|
||||
if(!$model->id){
|
||||
$this->new_model = true;
|
||||
|
||||
|
||||
if(is_array($model->line_items))
|
||||
{
|
||||
$model->line_items = (collect($model->line_items))->map(function ($item) use($model,$client) {
|
||||
|
||||
$item->notes = Helpers::processReservedKeywords($item->notes, $client);
|
||||
|
||||
return $item;
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$model->saveQuietly();
|
||||
|
||||
/* Model now persisted, now lets do some child tasks */
|
||||
@ -378,6 +366,8 @@ class BaseRepository
|
||||
|
||||
$model->save();
|
||||
|
||||
// nlog("save time = ". microtime(true) - $start);
|
||||
|
||||
return $model->fresh();
|
||||
}
|
||||
}
|
||||
|
@ -105,11 +105,14 @@ class GenerateDeliveryNote
|
||||
info($maker->getCompiledHTML());
|
||||
}
|
||||
|
||||
if (! Storage::disk($this->disk)->exists($this->invoice->client->invoice_filepath($invitation))) {
|
||||
Storage::disk($this->disk)->makeDirectory($this->invoice->client->invoice_filepath($invitation), 0775);
|
||||
}
|
||||
// if (! Storage::disk($this->disk)->exists($this->invoice->client->invoice_filepath($invitation))) {
|
||||
// Storage::disk($this->disk)->makeDirectory($this->invoice->client->invoice_filepath($invitation), 0775);
|
||||
// }
|
||||
|
||||
Storage::disk($this->disk)->put($file_path, $pdf, 'public');
|
||||
|
||||
//r2 Storage::disk($this->disk)->put($file_path, $pdf);
|
||||
|
||||
return $file_path;
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +218,7 @@ class InvoiceService
|
||||
public function markDeleted()
|
||||
{
|
||||
$this->removeUnpaidGatewayFees();
|
||||
$this->deletePdf();
|
||||
|
||||
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
||||
|
||||
@ -298,6 +299,9 @@ class InvoiceService
|
||||
} elseif ($this->invoice->balance > 0 && $this->invoice->balance < $this->invoice->amount) {
|
||||
$this->setStatus(Invoice::STATUS_PARTIAL);
|
||||
}
|
||||
elseif($this->invoice->balance < 0) {
|
||||
$this->setStatus(Invoice::STATUS_PARTIAL);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -71,10 +71,6 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
|
||||
private function adjustPaidToDateAndBalance()
|
||||
{
|
||||
// $client = $this->invoice->client->fresh();
|
||||
// $client->paid_to_date += $this->adjustment_amount * -1;
|
||||
// $client->balance += $this->balance_adjustment * -1;
|
||||
// $client->save();
|
||||
|
||||
// 06-09-2022
|
||||
$this->invoice
|
||||
|
@ -128,7 +128,7 @@ class Helpers
|
||||
|
||||
if(!$string_hit)
|
||||
return $value;
|
||||
// 04-10-2022 Return Early if no reserved keywords are present, this is a very expenseive process
|
||||
// 04-10-2022 Return Early if no reserved keywords are present, this is a very expensive process
|
||||
|
||||
Carbon::setLocale($entity->locale());
|
||||
|
||||
@ -296,8 +296,7 @@ class Helpers
|
||||
}
|
||||
|
||||
return $value;
|
||||
// $x = str_replace(["\n", "<br>"], ["\r", "<br>"], $value);
|
||||
// return $x;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,17 +54,33 @@ class Number
|
||||
* Formats a given value based on the clients currency.
|
||||
*
|
||||
* @param float $value The number to be formatted
|
||||
* @param object $currency The client currency object
|
||||
*
|
||||
* @return string The formatted value
|
||||
*/
|
||||
public static function formatValueNoTrailingZeroes($value, $currency) :string
|
||||
public static function formatValueNoTrailingZeroes($value, $entity) :string
|
||||
{
|
||||
$value = floatval($value);
|
||||
|
||||
$currency = $entity->currency();
|
||||
|
||||
$thousand = $currency->thousand_separator;
|
||||
$decimal = $currency->decimal_separator;
|
||||
$precision = $currency->precision;
|
||||
// $precision = $currency->precision;
|
||||
|
||||
if ($entity instanceof Company) {
|
||||
$country = $entity->country();
|
||||
} else {
|
||||
$country = $entity->country;
|
||||
}
|
||||
|
||||
/* Country settings override client settings */
|
||||
if (isset($country->thousand_separator) && strlen($country->thousand_separator) >= 1) {
|
||||
$thousand = $country->thousand_separator;
|
||||
}
|
||||
|
||||
if (isset($country->decimal_separator) && strlen($country->decimal_separator) >= 1) {
|
||||
$decimal = $country->decimal_separator;
|
||||
}
|
||||
|
||||
$precision = 10;
|
||||
|
||||
|
@ -65,7 +65,17 @@ trait ClientGroupSettingsSaver
|
||||
}
|
||||
|
||||
$entity->settings = $entity_settings;
|
||||
$entity->save();
|
||||
|
||||
try{
|
||||
$entity->save();
|
||||
}
|
||||
catch(\Exception $e){
|
||||
|
||||
nlog("client settings failure");
|
||||
nlog($entity_settings);
|
||||
nlog($e->getMessage());
|
||||
|
||||
}
|
||||
|
||||
return $entity_settings;
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ trait MakesInvoiceValues
|
||||
$data[$key][$table_type.".{$_table_type}4"] = strlen($item->custom_value4) >= 1 ? $helpers->formatCustomFieldValue($this->company->custom_fields, "{$_table_type}4", $item->custom_value4, $entity) : '';
|
||||
|
||||
if ($item->quantity > 0 || $item->cost > 0) {
|
||||
$data[$key][$table_type.'.quantity'] = Number::formatValueNoTrailingZeroes($item->quantity, $entity_currency);
|
||||
$data[$key][$table_type.'.quantity'] = Number::formatValueNoTrailingZeroes($item->quantity, $entity);
|
||||
|
||||
$data[$key][$table_type.'.unit_cost'] = Number::formatMoneyNoRounding($item->cost, $entity);
|
||||
|
||||
|
@ -79,6 +79,19 @@ return [
|
||||
'throw' => false,
|
||||
],
|
||||
|
||||
'r2' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'url' => env('AWS_URL'),
|
||||
'visibility' => 'private',
|
||||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||
'throw' => false,
|
||||
],
|
||||
|
||||
'gcs' => [
|
||||
'driver' => 'gcs',
|
||||
'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'your-project-id'),
|
||||
|
6
public/flutter_service_worker.js
vendored
6
public/flutter_service_worker.js
vendored
@ -4,9 +4,9 @@ const TEMP = 'flutter-temp-cache';
|
||||
const CACHE_NAME = 'flutter-app-cache';
|
||||
const RESOURCES = {
|
||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||
"main.dart.js": "221c5c0123d1312d9dd4625143c4e890",
|
||||
"main.dart.js": "da1ca4eca714583ff82c65cd3792029b",
|
||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||
"/": "3bb8121d93d3f214ecd76dd2a5db3bad",
|
||||
"/": "384495013e69b7963a1f0883fc10f045",
|
||||
"flutter.js": "f85e6fb278b0fd20c349186fb46ae36d",
|
||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||
"canvaskit/canvaskit.js": "2bc454a691c631b07a9307ac4ca47797",
|
||||
@ -299,7 +299,7 @@ const RESOURCES = {
|
||||
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
|
||||
"assets/fonts/MaterialIcons-Regular.otf": "95db9098c58fd6db106f1116bae85a0b",
|
||||
"assets/NOTICES": "1a34e70168d56fad075adfb4bdbb20eb",
|
||||
"version.json": "5e61b05ca3d51910bc4464df86bcda1a",
|
||||
"version.json": "ecddd9a09423be80c670ca3af19cf971",
|
||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed"
|
||||
};
|
||||
|
13841
public/main.dart.js
vendored
13841
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
6445
public/main.foss.dart.js
vendored
6445
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
81
public/main.profile.dart.js
vendored
81
public/main.profile.dart.js
vendored
@ -61440,7 +61440,7 @@
|
||||
if (B.JSString_methods.startsWith$1(url, "https://invoicing.co"))
|
||||
secret = "";
|
||||
t1 = type$.legacy_String;
|
||||
headers = A.LinkedHashMap_LinkedHashMap$_literal(["X-CLIENT-VERSION", "5.0.98", "X-API-SECRET", secret, "X-Requested-With", "XMLHttpRequest", "Content-Type", "application/json; charset=utf-8"], t1, t1);
|
||||
headers = A.LinkedHashMap_LinkedHashMap$_literal(["X-CLIENT-VERSION", "5.0.99", "X-API-SECRET", secret, "X-Requested-With", "XMLHttpRequest", "Content-Type", "application/json; charset=utf-8"], t1, t1);
|
||||
if (token.length !== 0)
|
||||
headers.$indexSet(0, "X-API-Token", token);
|
||||
if ((idToken == null ? "" : idToken).length !== 0)
|
||||
@ -61463,9 +61463,9 @@
|
||||
else if (serverVersion == null)
|
||||
throw A.wrapException("Error: please check that Invoice Ninja v5 is installed on the server");
|
||||
else {
|
||||
t2 = A.Version__compare(A.Version_parse("5.0.98"), A.Version_parse(minClientVersion));
|
||||
t2 = A.Version__compare(A.Version_parse("5.0.99"), A.Version_parse(minClientVersion));
|
||||
if (t2 < 0)
|
||||
throw A.wrapException("Error: client not supported, please update to the latest version [Current v5.0.98 < Minimum v" + A.S(minClientVersion) + "]");
|
||||
throw A.wrapException("Error: client not supported, please update to the latest version [Current v5.0.99 < Minimum v" + A.S(minClientVersion) + "]");
|
||||
else {
|
||||
t2 = A.Version__compare(A.Version_parse(serverVersion), A.Version_parse("5.0.4"));
|
||||
if (t2 < 0)
|
||||
@ -92148,16 +92148,17 @@
|
||||
UpgradeDialog: function UpgradeDialog(t0) {
|
||||
this.key = t0;
|
||||
},
|
||||
_UpgradeDialogState: function _UpgradeDialogState(t0, t1, t2, t3) {
|
||||
_UpgradeDialogState: function _UpgradeDialogState(t0, t1, t2, t3, t4) {
|
||||
var _ = this;
|
||||
_._inAppPurchase = t0;
|
||||
_._upgrade_dialog$_scrollController = t0;
|
||||
_._inAppPurchase = t1;
|
||||
_._upgrade_dialog$_subscription = null;
|
||||
_._upgrade_dialog$_products = t1;
|
||||
_._purchases = t2;
|
||||
_._upgrade_dialog$_products = t2;
|
||||
_._purchases = t3;
|
||||
_._purchasePending = _._isAvailable = false;
|
||||
_._loading = true;
|
||||
_._widget = _._queryProductError = null;
|
||||
_._debugLifecycleState = t3;
|
||||
_._debugLifecycleState = t4;
|
||||
_._framework$_element = null;
|
||||
},
|
||||
_UpgradeDialogState_initState_closure: function _UpgradeDialogState_initState_closure(t0) {
|
||||
@ -328474,6 +328475,7 @@
|
||||
t1 = A.convertDateTimeToSqlDate(null);
|
||||
b.get$_invoice_model$_$this()._date = t1;
|
||||
b.get$_invoice_model$_$this()._dueDate = "";
|
||||
b.get$_invoice_model$_$this()._partialDueDate = "";
|
||||
B.JSArray_methods.clear$0(b.get$documents().get$_safeList());
|
||||
t1 = b.get$lineItems();
|
||||
t2 = this.$this;
|
||||
@ -359702,7 +359704,7 @@
|
||||
version = "v" + (t1 == null ? "" : t1);
|
||||
if (version.length !== 0)
|
||||
version += "-";
|
||||
return B.JSString_methods.$add(version + A.getPlatformLetter(), B.JSArray_methods.get$last("5.0.98".split(".")));
|
||||
return B.JSString_methods.$add(version + A.getPlatformLetter(), B.JSArray_methods.get$last("5.0.99".split(".")));
|
||||
},
|
||||
get$historyList() {
|
||||
var _this = this,
|
||||
@ -417336,8 +417338,9 @@
|
||||
else
|
||||
isEnabled = false;
|
||||
t6 = t2[t4].userCompany;
|
||||
if (t6.isOwner)
|
||||
if (t6.account.trialStarted.length === 0) {
|
||||
if (t6.isOwner) {
|
||||
t6 = t6.account;
|
||||
if (t6.trialStarted.length === 0 && t6.plan === "" && !A.isIOS()) {
|
||||
t5.toString;
|
||||
t6 = $.$get$LocalizationsProvider__localizedValues();
|
||||
t7 = t5.localeCode;
|
||||
@ -417354,7 +417357,7 @@
|
||||
t8 = "";
|
||||
upgradeMessage = t8;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
t5.toString;
|
||||
t6 = $.$get$LocalizationsProvider__localizedValues();
|
||||
t7 = t5.localeCode;
|
||||
@ -423766,7 +423769,8 @@
|
||||
t1 = A.StoreProvider_of(context, t1).__Store__state_A;
|
||||
t1 === $ && A.throwUnnamedLateFieldNI();
|
||||
if (!t1.get$isPaidAccount())
|
||||
A.isApple();
|
||||
if (A.isApple())
|
||||
A.isIOS();
|
||||
}
|
||||
t9.push(A.DrawerTile$(company, _null, A.getEntityIcon(B.EntityType_dashboard), _null, new A._MenuDrawerState_build_closure8(store), new A._MenuDrawerState_build_closure9(), t4.get$dashboard()));
|
||||
t1 = A.getEntityIcon(B.EntityType_client);
|
||||
@ -427203,7 +427207,7 @@
|
||||
};
|
||||
A.UpgradeDialog.prototype = {
|
||||
createState$0() {
|
||||
return new A._UpgradeDialogState(A.InAppPurchase__getOrCreateInstance(), A._setArrayType([], type$.JSArray_legacy_ProductDetails), A._setArrayType([], type$.JSArray_legacy_PurchaseDetails), B._StateLifecycle_0);
|
||||
return new A._UpgradeDialogState(A.ScrollController$(0, true), A.InAppPurchase__getOrCreateInstance(), A._setArrayType([], type$.JSArray_legacy_ProductDetails), A._setArrayType([], type$.JSArray_legacy_PurchaseDetails), B._StateLifecycle_0);
|
||||
}
|
||||
};
|
||||
A._UpgradeDialogState.prototype = {
|
||||
@ -427274,13 +427278,15 @@
|
||||
return A._asyncStartSync($async$initStoreInfo$0, $async$completer);
|
||||
},
|
||||
dispose$0() {
|
||||
var _this = this;
|
||||
if ($.$get$Platform_isIOS()) {
|
||||
this._inAppPurchase.toString;
|
||||
_this._inAppPurchase.toString;
|
||||
type$.legacy_InAppPurchaseStoreKitPlatformAddition._as($.InAppPurchasePlatformAddition__instance).toString;
|
||||
$.$get$SKPaymentQueueWrapper__singleton().setDelegate$1(null);
|
||||
}
|
||||
this._upgrade_dialog$_subscription.cancel$0(0);
|
||||
this.super$State$dispose();
|
||||
_this._upgrade_dialog$_subscription.cancel$0(0);
|
||||
_this._upgrade_dialog$_scrollController.dispose$0();
|
||||
_this.super$State$dispose();
|
||||
},
|
||||
build$1(context) {
|
||||
var t4, t5, t6, _this = this, _null = null,
|
||||
@ -427290,11 +427296,12 @@
|
||||
stack = A._setArrayType([], t2),
|
||||
t3 = _this._queryProductError;
|
||||
if (t3 == null) {
|
||||
t3 = A._setArrayType([], t2);
|
||||
t3 = _this._upgrade_dialog$_scrollController;
|
||||
t4 = A._setArrayType([], t2);
|
||||
if ($.$get$Platform_isIOS())
|
||||
t3.push(new A.Padding(B.EdgeInsets_0_0_0_16, A.Text$("Payment will be charged to iTunes Account at confirmation of purchase. Subscription automatically renews unless auto-renew is turned off at least 24-hours before the end of the current period. Account will be charged for renewal within 24-hours prior to the end of the current period, and identify the cost of the renewal. Subscriptions may be managed by the user and auto-renewal may be turned off by going to the user's Account Settings after purchase.", _null, _null, _null, _null, _null, A.TextStyle$(_null, _null, B.MaterialColor_Map_HFpTk_4288585374, _null, _null, _null, _null, _null, _null, _null, _null, 12, _null, _null, _null, _null, _null, true, _null, _null, _null, _null, _null, _null, _null, _null), _null, _null, _null), _null));
|
||||
t3.push(_this._buildProductList$0());
|
||||
stack.push(A.ListView$(t3, _null, _null, _null, B.Axis_1, false));
|
||||
t4.push(new A.Padding(B.EdgeInsets_0_0_0_16, A.Text$("Payment will be charged to iTunes Account at confirmation of purchase. Subscription automatically renews unless auto-renew is turned off at least 24-hours before the end of the current period. Account will be charged for renewal within 24-hours prior to the end of the current period, and identify the cost of the renewal. Subscriptions may be managed by the user and auto-renewal may be turned off by going to the user's Account Settings after purchase.", _null, _null, _null, _null, _null, A.TextStyle$(_null, _null, B.MaterialColor_Map_HFpTk_4288585374, _null, _null, _null, _null, _null, _null, _null, _null, 12, _null, _null, _null, _null, _null, true, _null, _null, _null, _null, _null, _null, _null, _null), _null, _null, _null), _null));
|
||||
t4.push(_this._buildProductList$0());
|
||||
stack.push(A.Scrollbar$(A.ListView$(t4, t3, _null, _null, B.Axis_1, false), t3, true));
|
||||
} else
|
||||
stack.push(A.Center$(A.Text$(t3, _null, _null, _null, _null, _null, _null, _null, _null, _null), _null, _null));
|
||||
if (_this._purchasePending)
|
||||
@ -427601,26 +427608,24 @@
|
||||
};
|
||||
A._UpgradeDialogState__buildProductList_closure1.prototype = {
|
||||
call$1(productDetails) {
|
||||
var t5, _null = null,
|
||||
var t4, t5, _null = null,
|
||||
_s8_ = "activate",
|
||||
t1 = productDetails.id,
|
||||
previousPurchase = this.purchases.$index(0, t1),
|
||||
description = productDetails.description,
|
||||
t2 = A.Text$(description.length === 0 && t1 === "enterprise_plan_10" ? "One month of the Enterprise Plan (10 users)" : description, _null, _null, _null, _null, _null, _null, _null, _null, _null),
|
||||
t3 = A.TextButton_styleFrom(_null, _null, B.Color_4281236786, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, B.Color_4294967295, _null, _null, _null, _null, _null, _null),
|
||||
t4 = this.$this;
|
||||
previousPurchase = this.purchases.$index(0, productDetails.id),
|
||||
t1 = A.Text$(productDetails.description, _null, _null, _null, _null, _null, _null, _null, _null, _null),
|
||||
t2 = A.TextButton_styleFrom(_null, _null, B.Color_4281236786, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, B.Color_4294967295, _null, _null, _null, _null, _null, _null),
|
||||
t3 = this.$this;
|
||||
if (previousPurchase != null) {
|
||||
t1 = t4._framework$_element;
|
||||
t1.toString;
|
||||
t1 = A.Localizations_of(t1, B.Type_AppLocalization_KyD, type$.legacy_AppLocalization);
|
||||
t1.toString;
|
||||
t4 = t3._framework$_element;
|
||||
t4.toString;
|
||||
t4 = A.Localizations_of(t4, B.Type_AppLocalization_KyD, type$.legacy_AppLocalization);
|
||||
t4.toString;
|
||||
t5 = $.$get$LocalizationsProvider__localizedValues();
|
||||
t1 = J.$index$asx(t5.$index(0, t1.localeCode), _s8_);
|
||||
if (t1 == null)
|
||||
t1 = J.$index$asx(t5.$index(0, "en"), _s8_);
|
||||
t4 = J.$index$asx(t5.$index(0, t4.localeCode), _s8_);
|
||||
if (t4 == null)
|
||||
t4 = J.$index$asx(t5.$index(0, "en"), _s8_);
|
||||
} else
|
||||
t1 = productDetails.price;
|
||||
return A.ListTile$(false, _null, _null, _null, true, _null, _null, false, _null, _null, _null, _null, false, _null, _null, A.Column$(A._setArrayType([A.TextButton$(false, A.Text$(t1, _null, _null, _null, _null, _null, _null, _null, _null, _null), _null, _null, new A._UpgradeDialogState__buildProductList__closure(t4, previousPurchase, productDetails, this.account), t3), new A.SizedBox(_null, 20, _null, _null)], type$.JSArray_legacy_Widget), B.CrossAxisAlignment_0, _null, B.MainAxisAlignment_0, B.MainAxisSize_1, B.VerticalDirection_1), _null, t2, _null, _null);
|
||||
t4 = productDetails.price;
|
||||
return A.ListTile$(false, _null, _null, _null, true, _null, _null, false, _null, _null, _null, _null, false, _null, _null, A.Column$(A._setArrayType([A.TextButton$(false, A.Text$(t4, _null, _null, _null, _null, _null, _null, _null, _null, _null), _null, _null, new A._UpgradeDialogState__buildProductList__closure(t3, previousPurchase, productDetails, this.account), t2), new A.SizedBox(_null, 20, _null, _null)], type$.JSArray_legacy_Widget), B.CrossAxisAlignment_0, _null, B.MainAxisAlignment_0, B.MainAxisSize_1, B.VerticalDirection_1), _null, t1, _null, _null);
|
||||
},
|
||||
$signature: 2377
|
||||
};
|
||||
@ -465226,7 +465231,7 @@
|
||||
else
|
||||
t7 = false;
|
||||
if (t7) {
|
||||
if (account.trialStarted.length === 0 && account.plan === "") {
|
||||
if (account.trialStarted.length === 0 && account.plan === "" && !A.isIOS()) {
|
||||
t7 = J.$index$asx(t5.$index(0, t6), _s16_);
|
||||
if (t7 == null)
|
||||
t7 = J.$index$asx(t5.$index(0, _s2_), _s16_);
|
||||
|
@ -1 +1 @@
|
||||
{"app_name":"invoiceninja_flutter","version":"5.0.98","build_number":"98","package_name":"invoiceninja_flutter"}
|
||||
{"app_name":"invoiceninja_flutter","version":"5.0.99","build_number":"99","package_name":"invoiceninja_flutter"}
|
@ -12,6 +12,7 @@
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Utils\Number;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
@ -401,4 +402,89 @@ class ClientApiTest extends TestCase
|
||||
|
||||
$response->assertStatus(302);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsTwo()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.05, $currency);
|
||||
|
||||
$this->assertEquals(0.05, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsThree()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.005, $currency);
|
||||
|
||||
$this->assertEquals(0.005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsFour()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.0005, $currency);
|
||||
|
||||
$this->assertEquals(0.0005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsFive()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.00005, $currency);
|
||||
|
||||
$this->assertEquals(0.00005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsSix()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.000005, $currency);
|
||||
|
||||
$this->assertEquals(0.000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsSeven()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.0000005, $currency);
|
||||
|
||||
$this->assertEquals(0.0000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsEight()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.00000005, $currency);
|
||||
|
||||
$this->assertEquals(0.00000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingPositive()
|
||||
{
|
||||
$currency = $this->company;
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.5, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.500, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50005, $currency);
|
||||
$this->assertEquals(1.50005, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50000005, $currency);
|
||||
$this->assertEquals(1.50000005, $x);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -166,11 +166,12 @@ class RecurringInvoiceTest extends TestCase
|
||||
'company_id' => $this->company->id,
|
||||
]);
|
||||
});
|
||||
$client = Client::all()->first();
|
||||
|
||||
$client = Client::query()->orderBy('id', 'DESC')->first();
|
||||
|
||||
RecurringInvoice::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]);
|
||||
|
||||
$RecurringInvoice = RecurringInvoice::where('user_id', $this->user->id)->first();
|
||||
$RecurringInvoice = RecurringInvoice::query()->where('user_id', $this->user->id)->orderBy('id', 'DESC')->first();
|
||||
$RecurringInvoice->save();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
|
@ -63,7 +63,7 @@ class RecurringQuoteTest extends TestCase
|
||||
{
|
||||
RecurringQuote::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]);
|
||||
|
||||
$RecurringQuote = RecurringQuote::where('user_id', $this->user->id)->first();
|
||||
$RecurringQuote = RecurringQuote::query()->where('user_id', $this->user->id)->orderBy('id','DESC')->first();
|
||||
$RecurringQuote->save();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
|
@ -58,37 +58,5 @@ class DownloadHistoricalInvoiceTest extends TestCase
|
||||
$this->assertNotNull($this->invoice->activities);
|
||||
}
|
||||
|
||||
public function testBackupExists()
|
||||
{
|
||||
$this->mockActivity();
|
||||
|
||||
$this->assertNotNull($this->invoice->activities->first()->backup->html_backup);
|
||||
}
|
||||
|
||||
public function testBackupDownload()
|
||||
{
|
||||
$this->mockActivity();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->get('/api/v1/activities/download_entity/'.$this->encodePrimaryKey($this->invoice->activities->first()->id));
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testBackupCheckPriorToDownloadWorks()
|
||||
{
|
||||
$this->mockActivity();
|
||||
|
||||
$backup = $this->invoice->activities->first()->backup;
|
||||
$backup->forceDelete();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->get('/api/v1/activities/download_entity/'.$this->encodePrimaryKey($this->invoice->activities->first()->id));
|
||||
|
||||
$response->assertStatus(404);
|
||||
}
|
||||
}
|
||||
|
@ -89,18 +89,6 @@ class NumberTest extends TestCase
|
||||
$this->assertEquals(2.15, $rounded);
|
||||
}
|
||||
|
||||
//this method proved an error! removing this method from production
|
||||
// public function testImportFloatConversion()
|
||||
// {
|
||||
|
||||
// $amount = '€7,99';
|
||||
|
||||
// $converted_amount = Number::parseStringFloat($amount);
|
||||
|
||||
// $this->assertEquals(799, $converted_amount);
|
||||
|
||||
// }
|
||||
|
||||
public function testParsingStringCurrency()
|
||||
{
|
||||
$amount = '€7,99';
|
||||
@ -110,86 +98,4 @@ class NumberTest extends TestCase
|
||||
$this->assertEquals(7.99, $converted_amount);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsTwo()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.05, $currency);
|
||||
|
||||
$this->assertEquals(0.05, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsThree()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.005, $currency);
|
||||
|
||||
$this->assertEquals(0.005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsFour()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.0005, $currency);
|
||||
|
||||
$this->assertEquals(0.0005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsFive()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.00005, $currency);
|
||||
|
||||
$this->assertEquals(0.00005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsSix()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.000005, $currency);
|
||||
|
||||
$this->assertEquals(0.000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsSeven()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.0000005, $currency);
|
||||
|
||||
$this->assertEquals(0.0000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingDecimalsEight()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(0.00000005, $currency);
|
||||
|
||||
$this->assertEquals(0.00000005, $x);
|
||||
}
|
||||
|
||||
public function testRoundingPositive()
|
||||
{
|
||||
$currency = Currency::find(1);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.5, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.500, $currency);
|
||||
$this->assertEquals(1.5, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50005, $currency);
|
||||
$this->assertEquals(1.50005, $x);
|
||||
|
||||
$x = Number::formatValueNoTrailingZeroes(1.50000005, $currency);
|
||||
$this->assertEquals(1.50000005, $x);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user