mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Merge pull request #4629 from turbo124/v5-develop
update decimal precision
This commit is contained in:
commit
f267408029
@ -45,6 +45,8 @@ class Company extends BaseModel
|
|||||||
protected $presenter = CompanyPresenter::class;
|
protected $presenter = CompanyPresenter::class;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'hide_empty_columns_on_pdf',
|
||||||
|
'calculate_expense_tax_by_amount',
|
||||||
'invoice_expense_documents',
|
'invoice_expense_documents',
|
||||||
'invoice_task_documents',
|
'invoice_task_documents',
|
||||||
'show_tasks_table',
|
'show_tasks_table',
|
||||||
|
@ -72,6 +72,11 @@ class Expense extends BaseModel
|
|||||||
return $this->morphMany(Document::class, 'documentable');
|
return $this->morphMany(Document::class, 'documentable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
public function assigned_user()
|
public function assigned_user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class, 'assigned_user_id', 'id');
|
return $this->belongsTo(User::class, 'assigned_user_id', 'id');
|
||||||
|
@ -20,6 +20,7 @@ class ExpenseCategory extends BaseModel
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'color',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getEntityType()
|
public function getEntityType()
|
||||||
|
@ -36,6 +36,7 @@ class Project extends BaseModel
|
|||||||
'custom_value3',
|
'custom_value3',
|
||||||
'custom_value4',
|
'custom_value4',
|
||||||
'assigned_user_id',
|
'assigned_user_id',
|
||||||
|
'color',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getEntityType()
|
public function getEntityType()
|
||||||
|
@ -29,5 +29,5 @@ class TaskStatus extends BaseModel
|
|||||||
*/
|
*/
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
|
|
||||||
protected $fillable = ['name'];
|
protected $fillable = ['name','color'];
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ class AccountTransformer extends EntityTransformer
|
|||||||
'updated_at' => (int) $account->updated_at,
|
'updated_at' => (int) $account->updated_at,
|
||||||
'archived_at' => (int) $account->deleted_at,
|
'archived_at' => (int) $account->deleted_at,
|
||||||
'report_errors' => (bool) $account->report_errors,
|
'report_errors' => (bool) $account->report_errors,
|
||||||
|
'debug_enabled' => (bool) config('ninja.debug_enabled'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,8 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
'use_credits_payment' => 'always', //todo remove
|
'use_credits_payment' => 'always', //todo remove
|
||||||
'default_task_is_date_based' => (bool)$company->default_task_is_date_based,
|
'default_task_is_date_based' => (bool)$company->default_task_is_date_based,
|
||||||
'enable_product_discount' => (bool)$company->enable_product_discount,
|
'enable_product_discount' => (bool)$company->enable_product_discount,
|
||||||
|
'calculate_expense_tax_by_amount' =>(bool)$company->calculate_expense_tax_by_amount,
|
||||||
|
'hide_empty_columns_on_pdf' => (bool) $company->hide_empty_columns_on_pdf,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ class ExpenseCategoryTransformer extends EntityTransformer
|
|||||||
'id' => $this->encodePrimaryKey($expense_category->id),
|
'id' => $this->encodePrimaryKey($expense_category->id),
|
||||||
'user_id' => $this->encodePrimaryKey($expense_category->user_id),
|
'user_id' => $this->encodePrimaryKey($expense_category->user_id),
|
||||||
'name' => (string) $expense_category->name ?: '',
|
'name' => (string) $expense_category->name ?: '',
|
||||||
|
'color' => (string) $expense_category->color,
|
||||||
'is_deleted' => (bool) $expense_category->is_deleted,
|
'is_deleted' => (bool) $expense_category->is_deleted,
|
||||||
'updated_at' => (int) $expense_category->updated_at,
|
'updated_at' => (int) $expense_category->updated_at,
|
||||||
'archived_at' => (int) $expense_category->deleted_at,
|
'archived_at' => (int) $expense_category->deleted_at,
|
||||||
|
@ -62,6 +62,7 @@ class ProjectTransformer extends EntityTransformer
|
|||||||
'custom_value2' => (string) $project->custom_value2 ?: '',
|
'custom_value2' => (string) $project->custom_value2 ?: '',
|
||||||
'custom_value3' => (string) $project->custom_value3 ?: '',
|
'custom_value3' => (string) $project->custom_value3 ?: '',
|
||||||
'custom_value4' => (string) $project->custom_value4 ?: '',
|
'custom_value4' => (string) $project->custom_value4 ?: '',
|
||||||
|
'color' => (string) $project->color ?: '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ class TaskStatusTransformer extends EntityTransformer
|
|||||||
return [
|
return [
|
||||||
'id' => (string) $this->encodePrimaryKey($task_status->id),
|
'id' => (string) $this->encodePrimaryKey($task_status->id),
|
||||||
'name' => (string) $task_status->name,
|
'name' => (string) $task_status->name,
|
||||||
|
'color' => (string) $task_status->color,
|
||||||
'sort_order' => (int) $task_status->sort_order,
|
'sort_order' => (int) $task_status->sort_order,
|
||||||
'is_deleted' => (bool) $task_status->is_deleted,
|
'is_deleted' => (bool) $task_status->is_deleted,
|
||||||
'created_at' => (int) $task_status->created_at,
|
'created_at' => (int) $task_status->created_at,
|
||||||
|
@ -9,6 +9,7 @@ return [
|
|||||||
'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-stable/VERSION.txt',
|
'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-stable/VERSION.txt',
|
||||||
'app_name' => env('APP_NAME', 'Invoice Ninja'),
|
'app_name' => env('APP_NAME', 'Invoice Ninja'),
|
||||||
'app_env' => env('APP_ENV', 'selfhosted'),
|
'app_env' => env('APP_ENV', 'selfhosted'),
|
||||||
|
'debug_enabled' => env('APP_DEBUG', false),
|
||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', ''),
|
'app_domain' => env('APP_DOMAIN', ''),
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\TaskStatus;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class ImproveDecimalResolution extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table('company_ledgers', function (Blueprint $table) {
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('adjustment', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('credits', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('total_taxes', 20, 6)->change();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->change();
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('partial', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('invoices', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('total_taxes', 20, 6)->change();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->change();
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('partial', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('quotes', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('total_taxes', 20, 6)->change();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->change();
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('partial', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('expenses', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
$table->decimal('foreign_amount', 20, 6)->change();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('payments', function (Blueprint $table) {
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
$table->decimal('refunded', 20, 6)->change();
|
||||||
|
$table->decimal('applied', 20, 6)->change();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('products', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('projects', function (Blueprint $table) {
|
||||||
|
$table->decimal('task_rate', 20, 6)->change();
|
||||||
|
$table->decimal('budgeted_hours', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('recurring_invoices', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('total_taxes', 20, 6)->change();
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('recurring_quotes', function (Blueprint $table) {
|
||||||
|
$table->decimal('tax_rate1', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate2', 20, 6)->change();
|
||||||
|
$table->decimal('tax_rate3', 20, 6)->change();
|
||||||
|
$table->decimal('total_taxes', 20, 6)->change();
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('amount', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('clients', function (Blueprint $table) {
|
||||||
|
$table->decimal('balance', 20, 6)->change();
|
||||||
|
$table->decimal('paid_to_date', 20, 6)->change();
|
||||||
|
$table->decimal('credit_balance', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('tasks', function (Blueprint $table) {
|
||||||
|
$table->decimal('rate', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('tax_rates', function (Blueprint $table) {
|
||||||
|
$table->decimal('rate', 20, 6)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('companies', function (Blueprint $table) {
|
||||||
|
$table->boolean('calculate_expense_tax_by_amount')->false();
|
||||||
|
$table->boolean('hide_empty_columns_on_pdf')->false();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('task_statuses', function (Blueprint $table){
|
||||||
|
$table->string('color')->default('#fff');
|
||||||
|
$table->integer('status_sort_order')->nullable()->default(null)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('expense_categories', function (Blueprint $table){
|
||||||
|
$table->string('color')->default('#fff');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('projects', function (Blueprint $table){
|
||||||
|
$table->string('color')->default('#fff');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
TaskStatus::query()->update(['status_sort_order' => NULL]);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
64
tests/Unit/TaskSortingTest.php
Normal file
64
tests/Unit/TaskSortingTest.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class TaskSortingTest extends TestCase
|
||||||
|
{
|
||||||
|
public $collection;
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->collection = collect([
|
||||||
|
['id' => 1, 'name' =>'pizza', 'order' => 9999],
|
||||||
|
['id' => 2, 'name' =>'pineapple', 'order' => 9999],
|
||||||
|
['id' => 3, 'name' =>'ethereum', 'order' => 9999],
|
||||||
|
['id' => 4, 'name' =>'bitcoin', 'order' => 9999],
|
||||||
|
['id' => 5, 'name' =>'zulu', 'order' => 9999],
|
||||||
|
['id' => 6, 'name' =>'alpha', 'order' => 9999],
|
||||||
|
['id' => 7, 'name' =>'ninja', 'order' => 9999],
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSorting()
|
||||||
|
{
|
||||||
|
|
||||||
|
$index = 3;
|
||||||
|
$item = $this->collection->where('id', 7)->first();
|
||||||
|
|
||||||
|
$new_collection = $this->collection->reject(function ($task)use($item){
|
||||||
|
return $item['id'] == $task['id'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$sorted_tasks = $new_collection->filter(function($task, $key)use($index){
|
||||||
|
return $key < $index;
|
||||||
|
})->push($item)->merge($new_collection->filter(function($task, $key)use($index){
|
||||||
|
return $key >= $index;
|
||||||
|
}))->map(function ($item,$key){
|
||||||
|
$item['order'] = $key;
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
$index_item = $sorted_tasks->splice($index, 1)->all();
|
||||||
|
|
||||||
|
$this->assertEquals($sorted_tasks->first()['name'], 'pizza');
|
||||||
|
$this->assertEquals($sorted_tasks->last()['name'], 'alpha');
|
||||||
|
$this->assertEquals($index_item[0]['name'],'ninja');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user