1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 16:31:33 +02:00

Merge pull request #3927 from turbo124/v2

Fixes for base repo invitations
This commit is contained in:
David Bomba 2020-07-23 20:56:38 +10:00 committed by GitHub
commit 5349fc012c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 162 additions and 56 deletions

View File

@ -13,6 +13,8 @@ namespace App\Events\Invoice;
use App\Models\Company;
use App\Models\Invoice;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/**
@ -20,7 +22,7 @@ use Illuminate\Queue\SerializesModels;
*/
class InvoiceWasUpdated
{
use SerializesModels;
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var Invoice

View File

@ -118,7 +118,7 @@ class Handler extends ExceptionHandler
} elseif ($exception instanceof MethodNotAllowedHttpException && $request->expectsJson()) {
return response()->json(['message'=>'Method not support for this route'], 404);
} elseif ($exception instanceof ValidationException && $request->expectsJson()) {
// info(print_r($exception->validator->getMessageBag(),1));
info(print_r($exception->validator->getMessageBag(),1));
return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
} elseif ($exception instanceof RelationNotFoundException && $request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 400);

View File

@ -153,19 +153,22 @@ class BaseController extends Controller
'company.clients' =>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.tax_rates'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.groups'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.company_gateways'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.company_gateways.gateway'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.clients.contacts'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.products'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.company'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.invitations.contact'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.invitations.company'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.invoices.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.payments.paymentables'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.invitations.contact'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.invitations.company'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.quotes.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits.invitations'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.payment_terms'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.vendors'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits.documents'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits.invitations.contact'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.credits.invitations.company'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.payment_terms.company'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.vendors.contacts'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.expenses'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.tasks'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},
'company.projects'=>function ($query) use($updated_at){$query->where('updated_at', '>=', $updated_at);},

View File

@ -50,8 +50,8 @@ class QueryLogging
Log::info($request->method() . ' - ' . $request->url() . ": $count queries - " . $time);
//if($count > 10)
// Log::info($queries);
// if($count > 100)
// Log::info($queries);
}
}

View File

@ -39,7 +39,7 @@ class UpdateInvoiceRequest extends Request
public function rules()
{
$rules = [];
if ($this->input('documents') && is_array($this->input('documents'))) {
@ -60,7 +60,7 @@ class UpdateInvoiceRequest extends Request
protected function prepareForValidation()
{
$input = $this->all();
if (array_key_exists('design_id', $input) && is_string($input['design_id'])) {
$input['design_id'] = $this->decodePrimaryKey($input['design_id']);
}
@ -75,9 +75,8 @@ class UpdateInvoiceRequest extends Request
if (isset($input['invitations'])) {
foreach ($input['invitations'] as $key => $value) {
if (is_numeric($input['invitations'][$key]['id'])) {
if (array_key_exists('id', $input['invitations'][$key]) && is_numeric($input['invitations'][$key]['id'])) {
unset($input['invitations'][$key]['id']);
}
if (array_key_exists('id', $input['invitations'][$key]) && is_string($input['invitations'][$key]['id'])) {

View File

@ -77,7 +77,8 @@ class StorePaymentRequest extends Request
}
if (!isset($input['amount']) || $input['amount'] == 0) {
$input['amount'] = $invoices_total - $credits_total;
//$input['amount'] = $invoices_total - $credits_total;
$input['amount'] = $invoices_total;
}
$input['is_manual'] = true;

View File

@ -85,18 +85,18 @@ class ValidCreditsRules implements Rule
if(count($this->input['credits']) >=1){
$total_payments = $this->input['amount'] + array_sum(array_column($this->input['credits'], 'amount'));
// $total_payments = $this->input['amount'] + array_sum(array_column($this->input['credits'], 'amount'));
info(print_r($this->input,1));
info("total payments = {$total_payments}");
info("total credits available = " . array_sum(array_column($this->input['credits'], 'amount')));
info("total invoices payable = " . array_sum(array_column($this->input['invoices'], 'amount')));
// info(print_r($this->input,1));
// info("total payments = {$total_payments}");
// info("total credits available = " . array_sum(array_column($this->input['credits'], 'amount')));
// info("total invoices payable = " . array_sum(array_column($this->input['invoices'], 'amount')));
if($total_payments > array_sum(array_column($this->input['invoices'], 'amount'))){
// if($total_payments > array_sum(array_column($this->input['invoices'], 'amount'))){
$this->error_msg = "Sum of total payments and credits is greater than the total of invoices";
return false;
}
// $this->error_msg = "Sum of total payments and credits is greater than the total of invoices";
// return false;
// }
}

View File

@ -116,7 +116,7 @@ class Client extends BaseModel implements HasLocalePreference
'deleted_at' => 'timestamp',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -58,7 +58,7 @@ class CompanyGateway extends BaseModel
// return json_decode($this->attributes['fees_and_limits']);
// }
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -27,7 +27,7 @@ class CompanyLedger extends Model
'deleted_at' => 'timestamp',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -27,7 +27,7 @@ class CompanyToken extends BaseModel
protected $with = [
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()

View File

@ -48,7 +48,7 @@ class CompanyUser extends Pivot
'slack_webhook_url',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -78,7 +78,7 @@ class Credit extends BaseModel
'deleted_at' => 'timestamp',
];
protected $touches = ['company'];
protected $touches = [];
const STATUS_DRAFT = 1;
const STATUS_SENT = 2;

View File

@ -60,7 +60,7 @@ class Expense extends BaseModel
'deleted_at' => 'timestamp',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -40,7 +40,7 @@ class GroupSetting extends StaticModel
'settings'
];
protected $touches = ['company'];
protected $touches = [];
public function company()
{

View File

@ -56,7 +56,7 @@ class Invoice extends BaseModel
protected $presenter = 'App\Models\Presenters\InvoicePresenter';
protected $touches = ['company'];
protected $touches = [];
protected $hidden = [
'id',

View File

@ -29,7 +29,7 @@ class InvoiceInvitation extends BaseModel
protected $fillable = [
//'key',
//'client_contact_id',
'client_contact_id',
];
protected $with = [

View File

@ -82,7 +82,7 @@ class Payment extends BaseModel
'paymentables',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -40,7 +40,7 @@ class Product extends BaseModel
'tax_rate3',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -42,7 +42,7 @@ class Project extends BaseModel
return Project::class;
}
protected $touches = ['company'];
protected $touches = [];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@ -22,7 +22,7 @@ class Proposal extends BaseModel
'id',
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -42,7 +42,7 @@ class Quote extends BaseModel
protected $presenter = 'App\Models\Presenters\QuotePresenter';
protected $touches = ['company'];
protected $touches = [];
protected $fillable = [
'assigned_user_id',

View File

@ -18,6 +18,7 @@ use App\Utils\Ninja;
use App\Utils\Traits\Inviteable;
use App\Utils\Traits\MakesDates;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;
@ -25,7 +26,8 @@ class QuoteInvitation extends BaseModel
{
use MakesDates;
use Inviteable;
use SoftDeletes;
protected $fillable = [
'id',
'client_contact_id',

View File

@ -112,7 +112,7 @@ class RecurringInvoice extends BaseModel
'status'
];
protected $touches = ['company'];
protected $touches = [];
public function getEntityType()
{

View File

@ -18,6 +18,8 @@ class RecurringInvoiceInvitation extends BaseModel
{
use MakesDates;
protected $fillable = ['client_contact_id'];
protected $touches = ['recurring_invoice'];
public function getEntityType()

View File

@ -81,7 +81,7 @@ class RecurringQuote extends BaseModel
'start_date',
];
protected $touches = ['company'];
protected $touches = [];
protected $casts = [
'line_items' => 'object',

View File

@ -30,7 +30,7 @@ class Task extends BaseModel
'time_log',
];
protected $touches = ['company'];
protected $touches = [];
protected $casts = [
'updated_at' => 'timestamp',

View File

@ -53,7 +53,7 @@ class Vendor extends BaseModel
'deleted_at' => 'timestamp',
];
protected $touches = ['company'];
protected $touches = [];
protected $with = [
// 'contacts',

View File

@ -256,7 +256,6 @@ class BaseRepository
// $this->getInvitation($invitation, $resource)->delete();
$invitation_class = sprintf("App\\Models\\%sInvitation", $resource);
$invitation = $invitation_class::whereRaw("BINARY `key`= ?", [$invitation])->first();
if($invitation)
@ -277,10 +276,28 @@ class BaseRepository
if ($contact && $model->client_id == $contact->client_id);
{
$new_invitation = $invitation_factory_class::create($model->company_id, $model->user_id);
$new_invitation->{$lcfirst_resource_id} = $model->id;
$new_invitation->client_contact_id = $contact->id;
$new_invitation->save();
$invitation_class = sprintf("App\\Models\\%sInvitation", $resource);
$new_invitation = $invitation_class::withTrashed()
->where('client_contact_id', $contact->id)
->where($lcfirst_resource_id, $model->id)
->first();
if($new_invitation && $new_invitation->trashed()){
$new_invitation->restore();
}
else {
$new_invitation = $invitation_factory_class::create($model->company_id, $model->user_id);
$new_invitation->{$lcfirst_resource_id} = $model->id;
$new_invitation->client_contact_id = $contact->id;
$new_invitation->save();
}
}
}
}
@ -322,7 +339,6 @@ class BaseRepository
if(!$model->design_id)
$model->design_id = $this->decodePrimaryKey($client->getSetting('credit_design_id'));
}
if ($class->name == Quote::class) {
@ -331,13 +347,12 @@ class BaseRepository
if(!$model->design_id)
$model->design_id = $this->decodePrimaryKey($client->getSetting('quote_design_id'));
}
$model->save();
return $model->fresh();
}
}

View File

@ -12,17 +12,18 @@
namespace App\Services\Invoice;
use App\Events\Invoice\InvoiceWasMarkedSent;
use App\Models\Client;
use App\Models\Invoice;
use App\Services\AbstractService;
use App\Utils\Ninja;
class MarkSent extends AbstractService
{
private $client;
public $client;
private $invoice;
public $invoice;
public function __construct($client, $invoice)
public function __construct(Client $client, Invoice $invoice)
{
$this->client = $client;
$this->invoice = $invoice;

View File

@ -0,0 +1,81 @@
<?php
namespace Tests\Unit;
use App\Factory\InvoiceInvitationFactory;
use App\Jobs\Util\UploadFile;
use App\Models\Document;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Storage;
use Tests\MockAccountData;
use Tests\TestCase;
class InvitationTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public function setUp() :void
{
parent::setUp();
$this->makeTestData();
$this->withoutMiddleware(
ThrottleRequests::class
);
}
public function testInvitationSanity()
{
$this->assertEquals($this->invoice->invitations->count(), 2);
$invitations = $this->invoice->invitations()->get();
$invites = $invitations->reject(function ($invitation){
return $invitation->contact->is_primary == false;
})->toArray();
$this->invoice->invitations = $invites;
$this->invoice->line_items = [];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $this->invoice->toArray())
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(1, count($arr['data']['invitations']));
//test pushing a contact invitation back on
$contact = $this->invoice->client->contacts->where('is_primary', false)->first();
$new_invite = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id);
$new_invite->client_contact_id = $contact->hashed_id;
$invitations = $this->invoice->invitations()->get();
$invitations->push($new_invite);
$this->invoice->invitations = $invitations->toArray();
$this->invoice->line_items = [];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $this->invoice->toArray())
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(2, count($arr['data']['invitations']));
}
}