mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Merge remote-tracking branch 'upstream/v5-develop' into 1314-subscriptions-v3
This commit is contained in:
commit
e9be90779a
@ -1 +1 @@
|
||||
5.8.36
|
||||
5.8.37
|
@ -159,7 +159,7 @@ class SwissQrGenerator
|
||||
// Optionally, add some human-readable information about what the bill is for.
|
||||
$qrBill->setAdditionalInformation(
|
||||
QrBill\DataGroup\Element\AdditionalInformation::create(
|
||||
$this->invoice->public_notes ? substr($this->invoice->public_notes, 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number])
|
||||
$this->invoice->public_notes ? substr(strip_tags($this->invoice->public_notes), 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number])
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -158,7 +158,6 @@ class LicenseController extends BaseController
|
||||
|
||||
/* Catch claim license requests */
|
||||
if (config('ninja.environment') == 'selfhost') {
|
||||
// $response = Http::get( "http://ninja.test:8000/claim_license", [
|
||||
$response = Http::get("https://invoicing.co/claim_license", [
|
||||
'license_key' => $license_key,
|
||||
'product_id' => 3,
|
||||
|
@ -63,7 +63,7 @@ class UpdateClientRequest extends Request
|
||||
$rules['country_id'] = 'integer|nullable|exists:countries,id';
|
||||
$rules['shipping_country_id'] = 'integer|nullable|exists:countries,id';
|
||||
$rules['classification'] = 'bail|sometimes|nullable|in:individual,business,company,partnership,trust,charity,government,other';
|
||||
$rules['id_number'] = ['sometimes', 'bail', Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id)];
|
||||
$rules['id_number'] = ['sometimes', 'bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id)];
|
||||
$rules['number'] = ['sometimes', 'bail', Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id)];
|
||||
|
||||
$rules['settings'] = new ValidClientGroupSettingsRule();
|
||||
|
@ -52,7 +52,7 @@ class ClientStatement extends Mailable
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: $this->data['company']->account->isPremium() ? 'email.template.client_premium' : 'email.template.client',
|
||||
view: 'email.template.client',
|
||||
text: 'email.template.text',
|
||||
with: [
|
||||
'text_body' => $this->data['body'],
|
||||
|
@ -75,7 +75,8 @@ class TemplateEmail extends Mailable
|
||||
$template_name = 'email.template.'.$this->build_email->getTemplate();
|
||||
|
||||
if ($this->build_email->getTemplate() == 'light' || $this->build_email->getTemplate() == 'dark') {
|
||||
$template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
|
||||
// $template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
|
||||
$template_name = 'email.template.client';
|
||||
}
|
||||
|
||||
if ($this->build_email->getTemplate() == 'custom') {
|
||||
|
@ -72,7 +72,8 @@ class VendorTemplateEmail extends Mailable
|
||||
$template_name = 'email.template.'.$this->build_email->getTemplate();
|
||||
|
||||
if ($this->build_email->getTemplate() == 'light' || $this->build_email->getTemplate() == 'dark') {
|
||||
$template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
|
||||
// $template_name = $this->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client';
|
||||
$template_name = 'email.template.client';
|
||||
}
|
||||
|
||||
if ($this->build_email->getTemplate() == 'custom') {
|
||||
|
@ -107,10 +107,10 @@ class EmailDefaults
|
||||
|
||||
match ($this->email->email_object->settings->email_style) {
|
||||
'plain' => $this->template = 'email.template.plain',
|
||||
'light' => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' : 'email.template.client',
|
||||
'dark' => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' :'email.template.client',
|
||||
'light' => $this->template = 'email.template.client',
|
||||
'dark' => $this->template = 'email.template.client',
|
||||
'custom' => $this->template = 'email.template.custom',
|
||||
default => $this->template = $this->email->email_object->company->account->isPremium() ? 'email.template.client_premium' :'email.template.client',
|
||||
default => $this->template = 'email.template.client',
|
||||
};
|
||||
|
||||
$this->email->email_object->html_template = $this->template;
|
||||
|
@ -86,6 +86,33 @@ class Number
|
||||
return rtrim(rtrim(number_format($value, $precision, $decimal, $thousand), '0'), $decimal);
|
||||
}
|
||||
|
||||
public static function parseFloat($value)
|
||||
{
|
||||
|
||||
if(!$value)
|
||||
return 0;
|
||||
|
||||
//remove everything except for numbers, decimals, commas and hyphens
|
||||
$value = preg_replace('/[^0-9.,-]+/', '', $value);
|
||||
|
||||
$decimal = strpos($value, '.');
|
||||
$comma = strpos($value, ',');
|
||||
|
||||
if($comma === false) //no comma must be a decimal number already
|
||||
return (float) $value;
|
||||
|
||||
if($decimal < $comma){ //decimal before a comma = euro
|
||||
$value = str_replace(['.',','], ['','.'], $value);
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
//comma first = traditional thousand separator
|
||||
$value = str_replace(',', '', $value);
|
||||
|
||||
return (float)$value;
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Formats a given value based on the clients currency
|
||||
* BACK to a float.
|
||||
@ -93,32 +120,9 @@ class Number
|
||||
* @param string $value The formatted number to be converted back to float
|
||||
* @return float The formatted value
|
||||
*/
|
||||
public static function parseFloat($value)
|
||||
public static function parseFloatXX($value)
|
||||
{
|
||||
// if(!$value)
|
||||
// return 0;
|
||||
|
||||
// //remove everything except for numbers, decimals, commas and hyphens
|
||||
// $value = preg_replace('/[^0-9.,-]+/', '', $value);
|
||||
|
||||
// $decimal = strpos($value, '.');
|
||||
// $comma = strpos($value, ',');
|
||||
|
||||
// if($comma === false) //no comma must be a decimal number already
|
||||
// return (float) $value;
|
||||
|
||||
// if($decimal < $comma){ //decimal before a comma = euro
|
||||
// $value = str_replace(['.',','], ['','.'], $value);
|
||||
// // $value = str_replace(',', '.', $value);
|
||||
// return (float) $value;
|
||||
// }
|
||||
|
||||
// //comma first = traditional thousan separator
|
||||
// $value = str_replace(',', '', $value);
|
||||
|
||||
// return (float)$value;
|
||||
|
||||
|
||||
if(!$value)
|
||||
return 0;
|
||||
|
||||
|
@ -17,8 +17,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => env('APP_VERSION', '5.8.36'),
|
||||
'app_tag' => env('APP_TAG', '5.8.36'),
|
||||
'app_version' => env('APP_VERSION', '5.8.37'),
|
||||
'app_tag' => env('APP_TAG', '5.8.37'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->decimal('discount', 20, 6)->default(0)->change();
|
||||
});
|
||||
|
||||
|
||||
Schema::table('credits', function (Blueprint $table) {
|
||||
$table->decimal('discount', 20, 6)->default(0)->change();
|
||||
});
|
||||
|
||||
Schema::table('quotes', function (Blueprint $table) {
|
||||
$table->decimal('discount', 20, 6)->default(0)->change();
|
||||
});
|
||||
|
||||
Schema::table('purchase_orders', function (Blueprint $table) {
|
||||
$table->decimal('discount', 20, 6)->default(0)->change();
|
||||
});
|
||||
|
||||
Schema::table('recurring_invoices', function (Blueprint $table) {
|
||||
$table->decimal('discount', 20, 6)->default(0)->change();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -5269,7 +5269,7 @@ $lang = array(
|
||||
'payment_provider' => 'Payment Provider',
|
||||
'select_email_provider' => 'Set your email as the sending user',
|
||||
'purchase_order_items' => 'Purchase Order Items',
|
||||
|
||||
'csv_rows_length' => 'No data found in this CSV file',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -20,6 +20,7 @@ use App\Models\Subscription;
|
||||
use App\Models\ClientContact;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@ -51,6 +52,116 @@ class InvoiceTest extends TestCase
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function testMaxDiscount()
|
||||
{
|
||||
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
$item->cost = 100000000;
|
||||
$item->type_id = '1';
|
||||
|
||||
$line_items[] = $item;
|
||||
|
||||
$data = [
|
||||
'status_id' => 1,
|
||||
'number' => '',
|
||||
'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,
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'line_items' => $line_items,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/invoices?mark_sent=true',$data)
|
||||
->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals(2, $arr['data']['status_id']);
|
||||
$this->assertEquals(100000000, $arr['data']['amount']);
|
||||
$this->assertEquals(100000000, $arr['data']['balance']);
|
||||
|
||||
$data = [
|
||||
'status_id' => 1,
|
||||
'number' => '',
|
||||
'discount' => 100000000,
|
||||
'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,
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'line_items' => $line_items,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/invoices?mark_sent=true', $data)
|
||||
->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals(2, $arr['data']['status_id']);
|
||||
$this->assertEquals(0, $arr['data']['amount']);
|
||||
$this->assertEquals(0, $arr['data']['balance']);
|
||||
$this->assertEquals(100000000, $arr['data']['discount']);
|
||||
|
||||
$line_items = [];
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
$item->cost = 100000000;
|
||||
$item->discount = 100000000;
|
||||
$item->type_id = '1';
|
||||
|
||||
$line_items[] = $item;
|
||||
|
||||
$data = [
|
||||
'status_id' => 1,
|
||||
'number' => '',
|
||||
'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,
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'line_items' => $line_items,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/invoices?mark_sent=true', $data)
|
||||
->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals(2, $arr['data']['status_id']);
|
||||
$this->assertEquals(0, $arr['data']['amount']);
|
||||
$this->assertEquals(0, $arr['data']['balance']);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testInvoicePaymentLinkMutation()
|
||||
{
|
||||
|
||||
|
@ -24,20 +24,20 @@ class NumberTest extends TestCase
|
||||
public function testRangeOfNumberFormats()
|
||||
{
|
||||
|
||||
|
||||
$floatvals = [
|
||||
"22000.76" =>"22 000,76",
|
||||
"22000.76" =>"22.000,76",
|
||||
"22000.76" =>"22,000.76",
|
||||
"22000" =>"22 000",
|
||||
"22000" =>"22,000",
|
||||
"22000" =>"22.000",
|
||||
"22" =>"22.000",
|
||||
"22000" =>"22.000,",
|
||||
"22000.76" =>"22000.76",
|
||||
"22000.76" =>"22000,76",
|
||||
"1022000.76" =>"1.022.000,76",
|
||||
"1022000.76" =>"1,022,000.76",
|
||||
"1000000" =>"1,000,000",
|
||||
"1000000" =>"1.000.000",
|
||||
// "1000000" =>"1,000,000",
|
||||
// "1000000" =>"1.000.000",
|
||||
"1022000.76" =>"1022000.76",
|
||||
"1022000.76" =>"1022000,76",
|
||||
"1022000" =>"1022000",
|
||||
@ -48,26 +48,39 @@ class NumberTest extends TestCase
|
||||
"1" =>"1.00",
|
||||
"1" =>"1,00",
|
||||
"423545" =>"423545 €",
|
||||
"423545" =>"423,545 €",
|
||||
"423545" =>"423.545 €",
|
||||
// "423545" =>"423,545 €",
|
||||
// "423545" =>"423.545 €",
|
||||
"1" =>"1,00 €",
|
||||
"1.02" =>"€ 1.02",
|
||||
"1000.02" =>"1'000,02 EUR",
|
||||
"1000.02" =>"1 000.02$",
|
||||
"1000.02" =>"1,000.02$",
|
||||
"1000.02" =>"1.000,02 EURO",
|
||||
"9.975" => "9.975"
|
||||
"9.975" => "9.975",
|
||||
"9975" => "9.975,",
|
||||
"9975" => "9.975,00"
|
||||
];
|
||||
|
||||
|
||||
foreach($floatvals as $key => $value) {
|
||||
|
||||
// $this->assertEquals($key, Number::parseFloat2($value));
|
||||
$this->assertEquals($key, Number::parseFloat($value));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function testThreeDecimalFloatAsTax()
|
||||
{
|
||||
|
||||
$value = '9.975';
|
||||
|
||||
$res = Number::parseFloat($value);
|
||||
|
||||
$this->assertEquals(9.975, $res);
|
||||
|
||||
}
|
||||
|
||||
public function testNegativeFloatParse()
|
||||
{
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user