mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-01 10:04:34 -04:00
Version bump + linking tasks expenses with invoices
This commit is contained in:
parent
685b7e25c2
commit
ae44b9c032
@ -1 +1 @@
|
|||||||
5.0.22
|
5.0.23
|
||||||
|
@ -38,8 +38,8 @@ class StoreTaskRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
$rules['number'] = Rule::unique('tasks')
|
if(isset($this->number))
|
||||||
->where('company_id', auth()->user()->company()->id);
|
$rules['number'] = Rule::unique('tasks')->where('company_id', auth()->user()->company()->id);
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,8 @@ class UpdateTaskRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
$rules['number'] = Rule::unique('tasks')
|
if(isset($this->number))
|
||||||
->where('company_id', auth()->user()->company()->id)
|
$rules['number'] = Rule::unique('tasks')->where('company_id', auth()->user()->company()->id)->ignore($this->task->id);
|
||||||
->ignore($this->task->id);
|
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,15 @@ class Invoice extends BaseModel
|
|||||||
return $this->hasMany(Credit::class);
|
return $this->hasMany(Credit::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function tasks()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Task::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expenses()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Expense::class);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Service entry points.
|
* Service entry points.
|
||||||
*/
|
*/
|
||||||
|
@ -314,6 +314,7 @@ class BaseRepository
|
|||||||
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
|
if (($state['finished_amount'] != $state['starting_amount']) && ($model->status_id != Invoice::STATUS_DRAFT)) {
|
||||||
$model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']));
|
$model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']));
|
||||||
$model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();
|
$model->client->service()->updateBalance(($state['finished_amount'] - $state['starting_amount']))->save();
|
||||||
|
$model->service()->linkEntities()->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $model->design_id) {
|
if (! $model->design_id) {
|
||||||
|
@ -14,8 +14,10 @@ namespace App\Services\Invoice;
|
|||||||
use App\Jobs\Entity\CreateEntityPdf;
|
use App\Jobs\Entity\CreateEntityPdf;
|
||||||
use App\Jobs\Util\UnlinkFile;
|
use App\Jobs\Util\UnlinkFile;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
|
use App\Models\Expense;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Models\Task;
|
||||||
use App\Services\Client\ClientService;
|
use App\Services\Client\ClientService;
|
||||||
use App\Services\Invoice\ApplyNumber;
|
use App\Services\Invoice\ApplyNumber;
|
||||||
use App\Services\Invoice\ApplyPayment;
|
use App\Services\Invoice\ApplyPayment;
|
||||||
@ -30,10 +32,13 @@ use App\Services\Invoice\MarkInvoicePaid;
|
|||||||
use App\Services\Invoice\MarkSent;
|
use App\Services\Invoice\MarkSent;
|
||||||
use App\Services\Invoice\TriggeredActions;
|
use App\Services\Invoice\TriggeredActions;
|
||||||
use App\Services\Invoice\UpdateBalance;
|
use App\Services\Invoice\UpdateBalance;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
class InvoiceService
|
class InvoiceService
|
||||||
{
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
private $invoice;
|
private $invoice;
|
||||||
|
|
||||||
protected $client_service;
|
protected $client_service;
|
||||||
@ -328,6 +333,30 @@ class InvoiceService
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function linkEntities()
|
||||||
|
{
|
||||||
|
//set all task.invoice_ids = 0
|
||||||
|
$this->invoice->tasks()->update(['invoice_id' => null]);
|
||||||
|
|
||||||
|
//set all tasks.invoice_ids = x with the current line_items
|
||||||
|
$tasks = collect($this->invoice->line_items)->map(function ($item){
|
||||||
|
|
||||||
|
if(isset($item->task_id))
|
||||||
|
$item->task_id = $this->decodePrimaryKey($item->task_id);
|
||||||
|
|
||||||
|
if(isset($item->expense_id))
|
||||||
|
$item->expense_id = $this->decodePrimaryKey($item->expense_id);
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Task::whereIn('id',$tasks->pluck('task_id'))->update(['invoice_id' => $this->invoice->id]);
|
||||||
|
Expense::whereIn('id',$tasks->pluck('expense_id'))->update(['invoice_id' => $this->invoice->id]);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the invoice.
|
* Saves the invoice.
|
||||||
* @return Invoice object
|
* @return Invoice object
|
||||||
|
@ -53,6 +53,10 @@ class MarkInvoiceDeleted extends AbstractService
|
|||||||
|
|
||||||
$this->invoice->number = $number;
|
$this->invoice->number = $number;
|
||||||
|
|
||||||
|
//wipe references to invoices from related entities.
|
||||||
|
$this->invoice->tasks()->update(['invoice_id' => null]);
|
||||||
|
$this->invoice->expenses()->update(['invoice_id' => null]);
|
||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ trait UserNotifies
|
|||||||
|
|
||||||
public function findUserEntityNotificationType($entity, $company_user, $required_permissions) :array
|
public function findUserEntityNotificationType($entity, $company_user, $required_permissions) :array
|
||||||
{
|
{
|
||||||
if ($this->migrationRunning($company_user)) {
|
if ($company_user->company->is_disabled) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ trait UserNotifies
|
|||||||
|
|
||||||
public function findCompanyUserNotificationType($company_user, $required_permissions) :array
|
public function findCompanyUserNotificationType($company_user, $required_permissions) :array
|
||||||
{
|
{
|
||||||
if ($this->migrationRunning($company_user)) {
|
if ($company_user->company->is_disabled) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ return [
|
|||||||
'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', ''),
|
||||||
'app_version' => '5.0.22',
|
'app_version' => '5.0.23',
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
|
@ -42,6 +42,7 @@ class ExpenseFactory extends Factory
|
|||||||
'public_notes' => $this->faker->text(50),
|
'public_notes' => $this->faker->text(50),
|
||||||
'private_notes' => $this->faker->text(50),
|
'private_notes' => $this->faker->text(50),
|
||||||
'transaction_reference' => $this->faker->text(5),
|
'transaction_reference' => $this->faker->text(5),
|
||||||
|
'invoice_id' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ class TaskFactory extends Factory
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'description' => $this->faker->text(50),
|
'description' => $this->faker->text(50),
|
||||||
|
'invoice_id' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
77
tests/Feature/InvoiceLinkTasksTest.php
Normal file
77
tests/Feature/InvoiceLinkTasksTest.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\DataMapper\ClientSettings;
|
||||||
|
use App\DataMapper\CompanySettings;
|
||||||
|
use App\Factory\InvoiceFactory;
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\ClientContact;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Task;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Foundation\Testing\WithFaker;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class InvoiceLinkTasksTest extends TestCase
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
use MockAccountData;
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
Session::start();
|
||||||
|
|
||||||
|
$this->faker = \Faker\Factory::create();
|
||||||
|
|
||||||
|
Model::reguard();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapCreation()
|
||||||
|
{
|
||||||
|
$temp_invoice_id = $this->invoice->id;
|
||||||
|
|
||||||
|
$tasks = collect($this->invoice->line_items)->map(function ($item){
|
||||||
|
|
||||||
|
if(isset($item->task_id))
|
||||||
|
$item->task_id = $this->decodePrimaryKey($item->task_id);
|
||||||
|
|
||||||
|
if(isset($item->expense_id))
|
||||||
|
$item->expense_id = $this->decodePrimaryKey($item->expense_id);
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertEquals($tasks->first()->task_id, $this->task->id);
|
||||||
|
$this->assertEquals($tasks->first()->expense_id, $this->expense->id);
|
||||||
|
|
||||||
|
$this->invoice = $this->invoice->service()->linkEntities()->save();
|
||||||
|
|
||||||
|
$this->assertEquals($this->task->fresh()->invoice_id, $temp_invoice_id);
|
||||||
|
$this->assertEquals($this->expense->fresh()->invoice_id, $temp_invoice_id);
|
||||||
|
}
|
||||||
|
}
|
@ -570,6 +570,8 @@ trait MockAccountData
|
|||||||
$item = InvoiceItemFactory::create();
|
$item = InvoiceItemFactory::create();
|
||||||
$item->quantity = 1;
|
$item->quantity = 1;
|
||||||
$item->cost = 10;
|
$item->cost = 10;
|
||||||
|
$item->task_id = $this->encodePrimaryKey($this->task->id);
|
||||||
|
$item->expense_id = $this->encodePrimaryKey($this->expense->id);
|
||||||
|
|
||||||
$line_items[] = $item;
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user