mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Fixes for credit PDF
This commit is contained in:
parent
c5643bea7b
commit
28cbd75fcb
@ -364,10 +364,14 @@ class DemoMode extends Command
|
||||
|
||||
private function createProject($client, $assigned_user_id = null)
|
||||
{
|
||||
$vendor = Project::factory()->create([
|
||||
$project = Project::factory()->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company_id,
|
||||
'client_id' => $client->id,
|
||||
]);
|
||||
|
||||
$project->number = $this->getNextProjectNumber($project);
|
||||
$project->save();
|
||||
}
|
||||
|
||||
private function createInvoice($client, $assigned_user_id = null)
|
||||
|
@ -12,6 +12,10 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\Ninja\SendReminders;
|
||||
use App\Jobs\Util\WebHookHandler;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Webhook;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SendRemindersCron extends Command
|
||||
@ -48,5 +52,34 @@ class SendRemindersCron extends Command
|
||||
public function handle()
|
||||
{
|
||||
SendReminders::dispatchNow();
|
||||
|
||||
$this->webHookOverdueInvoices();
|
||||
$this->webHookExpiredQuotes();
|
||||
}
|
||||
|
||||
private function webHookOverdueInvoices()
|
||||
{
|
||||
$invoices = Invoice::where('is_deleted', 0)
|
||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||
->where('balance', '>', 0)
|
||||
->whereDate('due_date', now()->subDays(1)->startOfDay())
|
||||
->cursor();
|
||||
|
||||
$invoices->each(function ($invoice){
|
||||
WebHookHandler::dispatch(Webhook::EVENT_LATE_INVOICE, $invoice);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private function webHookExpiredQuotes()
|
||||
{
|
||||
$quotes = Quote::where('is_deleted', 0)
|
||||
->where('status_id', Quote::STATUS_SENT)
|
||||
->whereDate('due_date', now()->subDays(1)->startOfDay())
|
||||
->cursor();
|
||||
|
||||
$quotes->each(function ($quote){
|
||||
WebHookHandler::dispatch(Webhook::EVENT_EXPIRED_QUOTE, $quote);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class InvitationController extends Controller
|
||||
|
||||
$key = $entity.'_id';
|
||||
|
||||
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation'; //todo sensitive to the route parameters here
|
||||
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation';
|
||||
|
||||
$invitation = $entity_obj::whereRaw('BINARY `key`= ?', [$invitation_key])
|
||||
->with('contact.client')
|
||||
|
@ -572,10 +572,10 @@ class CreditController extends BaseController
|
||||
public function downloadPdf($invitation_key)
|
||||
{
|
||||
$invitation = $this->credit_repository->getInvitationByKey($invitation_key);
|
||||
$contact = $invitation->contact;
|
||||
// $contact = $invitation->contact;
|
||||
$credit = $invitation->credit;
|
||||
|
||||
$file_path = $credit->service()->getCreditPdf($contact);
|
||||
$file_path = $credit->service()->getCreditPdf($invitation);
|
||||
|
||||
return response()->download($file_path);
|
||||
}
|
||||
|
@ -34,8 +34,10 @@ use App\Jobs\Util\UnlinkFile;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\Quote;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Transformers\InvoiceTransformer;
|
||||
use App\Transformers\QuoteTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\TempFile;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -639,7 +641,12 @@ class InvoiceController extends BaseController
|
||||
break;
|
||||
case 'clone_to_quote':
|
||||
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
|
||||
// todo build the quote transformer and return response here
|
||||
|
||||
$this->entity_transformer = QuoteTransformer::class;
|
||||
$this->entity_type = Quote::class;
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
|
||||
break;
|
||||
case 'history':
|
||||
// code...
|
||||
|
@ -23,9 +23,11 @@ use App\Http\Requests\RecurringQuote\ShowRecurringQuoteRequest;
|
||||
use App\Http\Requests\RecurringQuote\StoreRecurringQuoteRequest;
|
||||
use App\Http\Requests\RecurringQuote\UpdateRecurringQuoteRequest;
|
||||
use App\Jobs\Entity\ActionEntity;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringQuote;
|
||||
use App\Repositories\BaseRepository;
|
||||
use App\Repositories\RecurringQuoteRepository;
|
||||
use App\Transformers\QuoteTransformer;
|
||||
use App\Transformers\RecurringQuoteTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
@ -583,8 +585,11 @@ class RecurringQuoteController extends BaseController
|
||||
// return $this->itemResponse($recurring_invoice);
|
||||
break;
|
||||
case 'clone_to_quote':
|
||||
// $quote = CloneRecurringQuoteToQuoteFactory::create($recurring_invoice, auth()->user()->id);
|
||||
// todo build the quote transformer and return response here
|
||||
$quote = CloneRecurringQuoteToQuoteFactory::create($recurring_invoice, auth()->user()->id);
|
||||
$this->entity_transformer = QuoteTransformer::class;
|
||||
$this->entity_type = Quote::class;
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
break;
|
||||
case 'history':
|
||||
// code...
|
||||
|
@ -84,4 +84,9 @@ class SelfUpdateController extends BaseController
|
||||
|
||||
return response()->json(['message' => ''], 200);
|
||||
}
|
||||
|
||||
public function checkVersion()
|
||||
{
|
||||
return trim(file_get_contents(config('ninja.version_url')));
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class ContactTokenAuth
|
||||
//stateless, don't remember the contact.
|
||||
auth()->guard('contact')->login($client_contact, false);
|
||||
|
||||
event(new ContactLoggedIn($client_contact, $client_contact->company, Ninja::eventVars())); //todo
|
||||
event(new ContactLoggedIn($client_contact, $client_contact->company, Ninja::eventVars()));
|
||||
} else {
|
||||
$error = [
|
||||
'message' => 'Invalid token',
|
||||
|
@ -75,7 +75,7 @@ class StoreClientRequest extends Request
|
||||
$input = $this->all();
|
||||
|
||||
//@todo implement feature permissions for > 100 clients
|
||||
//
|
||||
|
||||
$settings = ClientSettings::defaults();
|
||||
|
||||
if (array_key_exists('settings', $input) && ! empty($input['settings'])) {
|
||||
|
@ -77,7 +77,7 @@ class StorePaymentRequest extends Request
|
||||
}
|
||||
|
||||
if (! isset($input['amount']) || $input['amount'] == 0) {
|
||||
$input['amount'] = $invoices_total - $credits_total; //todo the payment amount is always less the credit amount applied
|
||||
$input['amount'] = $invoices_total - $credits_total;
|
||||
}
|
||||
|
||||
$input['is_manual'] = true;
|
||||
|
@ -109,22 +109,20 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
private function setAutoBillFlag($auto_bill)
|
||||
{
|
||||
if($auto_bill == 'always')
|
||||
return true;
|
||||
|
||||
if($auto_bill == 'off')
|
||||
return false;
|
||||
|
||||
//todo do we need to handle optin / optout here?
|
||||
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
private function setAutoBillFlag($auto_bill)
|
||||
{
|
||||
if($auto_bill == 'always')
|
||||
return true;
|
||||
|
||||
if($auto_bill == 'off')
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -46,16 +46,28 @@ class ValidCreditsPresentRule implements Rule
|
||||
{
|
||||
//todo need to ensure the clients credits are here not random ones!
|
||||
|
||||
if (request()->input('credits') && is_array(request()->input('credits'))) {
|
||||
foreach (request()->input('credits') as $credit) {
|
||||
$cred = Credit::find($this->decodePrimaryKey($credit['credit_id']));
|
||||
// if (request()->input('credits') && is_array(request()->input('credits'))) {
|
||||
// foreach (request()->input('credits') as $credit) {
|
||||
// $cred = Credit::find($this->decodePrimaryKey($credit['credit_id']));
|
||||
|
||||
if (! $cred || $cred->balance == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// if (! $cred || $cred->balance == 0) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return true;
|
||||
|
||||
|
||||
if (request()->input('credits') && is_array(request()->input('credits'))) {
|
||||
|
||||
$credit_collection = Credit::whereIn('id', $this->transformKeys(array_column(request()->input('credits'), 'credit_id')))
|
||||
->where('balance', '>', 0)
|
||||
->get();
|
||||
|
||||
return $credit_collection->count() == count(request()->input('credits'));
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -285,10 +285,13 @@ class SendReminders implements ShouldQueue
|
||||
* @param Invoice $invoice
|
||||
* @param float $amount The fee amount
|
||||
* @param float $percent The fee percentage amount
|
||||
*
|
||||
* @return Invoice
|
||||
*/
|
||||
private function setLateFee($invoice, $amount, $percent) :Invoice
|
||||
{
|
||||
$temp_invoice_balance = $invoice->balance;
|
||||
|
||||
if ($amount <= 0 && $percent <= 0)
|
||||
return $invoice;
|
||||
|
||||
@ -314,7 +317,9 @@ class SendReminders implements ShouldQueue
|
||||
/**Refresh Invoice values*/
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
//@todo update the ledger!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
$this->invoice->client->service()->updateBalance($this->invoice->balance - $temp_invoice_balance)->save();
|
||||
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance - $temp_invoice_balance);
|
||||
|
||||
return $invoice;
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
<?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 App\Jobs\Util;
|
||||
|
||||
use App\Models\Webhook;
|
||||
@ -40,7 +48,7 @@ class WebhookHandler implements ShouldQueue
|
||||
* @return bool
|
||||
*/
|
||||
public function handle() :bool
|
||||
{
|
||||
{//todo set multidb here
|
||||
if (! $this->entity->company || $this->entity->company->is_disabled) {
|
||||
return true;
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
return array_search($model->id, $transformed_ids);
|
||||
});
|
||||
} else {
|
||||
$gateways = $this->company->company_gateways; //todo perhaps we can remove this or keep as a catch all.
|
||||
$gateways = $this->company->company_gateways;
|
||||
}
|
||||
|
||||
foreach ($gateways as $gateway) {
|
||||
|
@ -224,8 +224,6 @@ class Credit extends BaseModel
|
||||
if ($this->balance == 0) {
|
||||
$this->status_id = self::STATUS_APPLIED;
|
||||
$this->save();
|
||||
//event(new InvoiceWasPaid($this, $this->company));//todo
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -248,10 +246,10 @@ class Credit extends BaseModel
|
||||
|
||||
if (! $invitation) {
|
||||
event(new CreditWasUpdated($this, $this->company, Ninja::eventVars()));
|
||||
CreateEntityPdf::dispatchNow($this, $this->company, $this->client->primary_contact()->first());
|
||||
CreateEntityPdf::dispatchNow($this->invitations->first());
|
||||
} else {
|
||||
event(new CreditWasUpdated($this, $this->company, Ninja::eventVars()));
|
||||
CreateEntityPdf::dispatchNow($invitation->credit, $invitation->company, $invitation->contact);
|
||||
CreateEntityPdf::dispatchNow($invitation);
|
||||
}
|
||||
|
||||
return $storage_path;
|
||||
|
@ -40,7 +40,10 @@ class Webhook extends BaseModel
|
||||
const EVENT_UPDATE_TASK = 19;
|
||||
const EVENT_DELETE_TASK = 20;
|
||||
const EVENT_APPROVE_QUOTE = 21;
|
||||
|
||||
const EVENT_LATE_INVOICE = 22;
|
||||
const EVENT_EXPIRED_QUOTE = 23;
|
||||
const EVENT_REMIND_INVOICE = 24;
|
||||
|
||||
public static $valid_events = [
|
||||
self::EVENT_CREATE_CLIENT,
|
||||
self::EVENT_CREATE_PAYMENT,
|
||||
|
@ -29,9 +29,9 @@ class CreditService
|
||||
$this->credit = $credit;
|
||||
}
|
||||
|
||||
public function getCreditPdf($contact)
|
||||
public function getCreditPdf($invitation)
|
||||
{
|
||||
return (new GetCreditPdf($this->credit, $contact))->run();
|
||||
return (new GetCreditPdf($invitation))->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,14 +19,17 @@ use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class GetCreditPdf extends AbstractService
|
||||
{
|
||||
private $credit;
|
||||
public $credit;
|
||||
|
||||
private $contact;
|
||||
public $contact;
|
||||
|
||||
public function __construct(Credit $credit, ClientContact $contact = null)
|
||||
public $invitation;
|
||||
|
||||
public function __construct($invitation)
|
||||
{
|
||||
$this->credit = $credit;
|
||||
$this->contact = $contact;
|
||||
$this->invitation = $invitation;
|
||||
$this->credit = $invitation->credit;
|
||||
$this->contact = $invitation->contact;
|
||||
}
|
||||
|
||||
public function run()
|
||||
@ -44,7 +47,7 @@ class GetCreditPdf extends AbstractService
|
||||
$file = Storage::disk($disk)->exists($file_path);
|
||||
|
||||
if (! $file) {
|
||||
$file_path = CreateEntityPdf::dispatchNow($this->credit, $this->credit->company, $this->contact);
|
||||
$file_path = CreateEntityPdf::dispatchNow($this->invitation);
|
||||
}
|
||||
|
||||
return Storage::disk($disk)->path($file_path);
|
||||
|
@ -74,7 +74,7 @@ class AccountTransformer extends EntityTransformer
|
||||
'utm_content' => (string) $account->utm_content,
|
||||
'utm_term' => (string) $account->utm_term,
|
||||
'referral_code' => (string) $account->referral_code,
|
||||
'latest_version' => (string) $account->latest_version,
|
||||
'latest_version' => (string) trim($account->latest_version),
|
||||
'current_version' => (string) config('ninja.app_version'),
|
||||
'updated_at' => (int) $account->updated_at,
|
||||
'archived_at' => (int) $account->deleted_at,
|
||||
|
@ -9,7 +9,8 @@
|
||||
"expenses",
|
||||
"CRM",
|
||||
"Credit card billing",
|
||||
"projects"
|
||||
"projects",
|
||||
"tasks"
|
||||
],
|
||||
"license": "Attribution Assurance License",
|
||||
"authors": [
|
||||
|
Loading…
Reference in New Issue
Block a user