mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-09-27 03:37:11 +02:00
commit
d114445ab2
@ -1 +1 @@
|
|||||||
5.3.8
|
5.3.9
|
@ -24,12 +24,14 @@ use App\Models\Invoice;
|
|||||||
use App\Models\InvoiceInvitation;
|
use App\Models\InvoiceInvitation;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\Paymentable;
|
use App\Models\Paymentable;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use DB;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Mail;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -103,6 +105,7 @@ class CheckData extends Command
|
|||||||
// $this->checkPaidToCompanyDates();
|
// $this->checkPaidToCompanyDates();
|
||||||
$this->checkClientBalances();
|
$this->checkClientBalances();
|
||||||
$this->checkContacts();
|
$this->checkContacts();
|
||||||
|
$this->checkEntityInvitations();
|
||||||
$this->checkCompanyData();
|
$this->checkCompanyData();
|
||||||
|
|
||||||
|
|
||||||
@ -197,7 +200,7 @@ class CheckData extends Command
|
|||||||
->where('id', '=', $contact->id)
|
->where('id', '=', $contact->id)
|
||||||
->whereNull('contact_key')
|
->whereNull('contact_key')
|
||||||
->update([
|
->update([
|
||||||
'contact_key' => str_random(config('ninja.key_length')),
|
'contact_key' => Str::random(config('ninja.key_length')),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,13 +310,73 @@ class CheckData extends Command
|
|||||||
$invitation->company_id = $invoice->company_id;
|
$invitation->company_id = $invoice->company_id;
|
||||||
$invitation->user_id = $invoice->user_id;
|
$invitation->user_id = $invoice->user_id;
|
||||||
$invitation->invoice_id = $invoice->id;
|
$invitation->invoice_id = $invoice->id;
|
||||||
$invitation->contact_id = ClientContact::whereClientId($invoice->client_id)->whereIsPrimary(true)->first()->id;
|
$invitation->contact_id = ClientContact::whereClientId($invoice->client_id)->first()->id;
|
||||||
$invitation->invitation_key = str_random(config('ninja.key_length'));
|
$invitation->invitation_key = Str::random(config('ninja.key_length'));
|
||||||
$invitation->save();
|
$invitation->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function checkEntityInvitations()
|
||||||
|
{
|
||||||
|
|
||||||
|
RecurringInvoiceInvitation::where('deleted_at',"0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||||
|
InvoiceInvitation::where('deleted_at',"0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||||
|
QuoteInvitation::where('deleted_at',"0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||||
|
|
||||||
|
$entities = ['invoice', 'quote', 'credit', 'recurring_invoice'];
|
||||||
|
|
||||||
|
foreach($entities as $entity)
|
||||||
|
{
|
||||||
|
$table = "{$entity}s";
|
||||||
|
$invitation_table = "{$entity}_invitations";
|
||||||
|
|
||||||
|
$entities = DB::table($table)
|
||||||
|
->leftJoin($invitation_table, function ($join) use($invitation_table, $table, $entity){
|
||||||
|
$join->on("{$invitation_table}.{$entity}_id", '=', "{$table}.id");
|
||||||
|
// ->whereNull("{$invitation_table}.deleted_at");
|
||||||
|
})
|
||||||
|
->groupBy("{$table}.id", "{$table}.user_id", "{$table}.company_id", "{$table}.client_id")
|
||||||
|
->havingRaw("count({$invitation_table}.id) = 0")
|
||||||
|
->get(["{$table}.id", "{$table}.user_id", "{$table}.company_id", "{$table}.client_id"]);
|
||||||
|
|
||||||
|
|
||||||
|
$this->logMessage($entities->count()." {$table} without any invitations");
|
||||||
|
|
||||||
|
if ($this->option('fix') == 'true')
|
||||||
|
$this->fixInvitations($entities, $entity);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fixInvitations($entities, $entity)
|
||||||
|
{
|
||||||
|
$entity_key = "{$entity}_id";
|
||||||
|
|
||||||
|
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($entity)).'Invitation';
|
||||||
|
|
||||||
|
foreach($entities as $entity)
|
||||||
|
{
|
||||||
|
$invitation = new $entity_obj();
|
||||||
|
$invitation->company_id = $entity->company_id;
|
||||||
|
$invitation->user_id = $entity->user_id;
|
||||||
|
$invitation->{$entity_key} = $entity->id;
|
||||||
|
$invitation->client_contact_id = ClientContact::whereClientId($entity->client_id)->first()->id;
|
||||||
|
$invitation->key = Str::random(config('ninja.key_length'));
|
||||||
|
|
||||||
|
try{
|
||||||
|
$invitation->save();
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
$invitation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// private function checkPaidToCompanyDates()
|
// private function checkPaidToCompanyDates()
|
||||||
// {
|
// {
|
||||||
// Company::cursor()->each(function ($company){
|
// Company::cursor()->each(function ($company){
|
||||||
|
@ -15,12 +15,14 @@ class S3Cleanup extends Command
|
|||||||
*/
|
*/
|
||||||
protected $signature = 'ninja:s3-cleanup';
|
protected $signature = 'ninja:s3-cleanup';
|
||||||
|
|
||||||
|
protected $log = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Remove orphan folders';
|
protected $description = 'Remove orphan folders/files';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
@ -54,7 +56,11 @@ class S3Cleanup extends Command
|
|||||||
if(!in_array($dir, $merged))
|
if(!in_array($dir, $merged))
|
||||||
{
|
{
|
||||||
$this->logMessage("Deleting $dir");
|
$this->logMessage("Deleting $dir");
|
||||||
Storage::disk(config('filesystems.default'))->deleteDirectory($dir);
|
|
||||||
|
/* Ensure we are not deleting the root folder */
|
||||||
|
if(strlen($dir) > 1)
|
||||||
|
Storage::disk(config('filesystems.default'))->deleteDirectory($dir);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ class Kernel extends ConsoleKernel
|
|||||||
|
|
||||||
$schedule->job(new AdjustEmailQuota)->dailyAt('23:00')->withoutOverlapping();
|
$schedule->job(new AdjustEmailQuota)->dailyAt('23:00')->withoutOverlapping();
|
||||||
$schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
|
$schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
|
||||||
$schedule->command('ninja:check-data --database=db-ninja-02')->daily()->withoutOverlapping();
|
$schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('00:15')->withoutOverlapping();
|
||||||
|
$schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class DocumentController extends Controller
|
|||||||
$zip = new ZipStream(now() . '-documents.zip', $options);
|
$zip = new ZipStream(now() . '-documents.zip', $options);
|
||||||
|
|
||||||
foreach ($documents as $document) {
|
foreach ($documents as $document) {
|
||||||
$zip->addFileFromPath(basename($document->diskPath()), TempFile::path($document->diskPath()));
|
$zip->addFileFromPath(basename($document->diskPath()), TempFile::path($document->filePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$zip->finish();
|
$zip->finish();
|
||||||
|
@ -18,10 +18,10 @@ use App\Libraries\MultiDB;
|
|||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Auth;
|
|
||||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class NinjaPlanController extends Controller
|
class NinjaPlanController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests\Gateways\Checkout3ds;
|
namespace App\Http\Requests\Gateways\Checkout3ds;
|
||||||
|
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
@ -37,6 +38,7 @@ class Checkout3dsRequest extends FormRequest
|
|||||||
|
|
||||||
public function getCompany()
|
public function getCompany()
|
||||||
{
|
{
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($this->company_key);
|
||||||
return Company::where('company_key', $this->company_key)->first();
|
return Company::where('company_key', $this->company_key)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class InvoiceTransformer extends BaseTransformer {
|
|||||||
|
|
||||||
if ( $transformed['balance'] < $transformed['amount'] ) {
|
if ( $transformed['balance'] < $transformed['amount'] ) {
|
||||||
$transformed['payments'] = [[
|
$transformed['payments'] = [[
|
||||||
'date' => date( 'Y-m-d' ),
|
'date' => isset( $invoice_data['Last Payment Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Invoice Date'] ) ) : date( 'Y-m-d' ),
|
||||||
'amount' => $transformed['amount'] - $transformed['balance'],
|
'amount' => $transformed['amount'] - $transformed['balance'],
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
@ -75,3 +75,4 @@ class InvoiceTransformer extends BaseTransformer {
|
|||||||
return $transformed;
|
return $transformed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,18 +121,29 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post mark buries the proper message in a a guzzle response
|
||||||
|
* this merges a text string with a json object
|
||||||
|
* need to harvest the ->Message property using the following
|
||||||
|
*/
|
||||||
if($e instanceof ClientException) { //postmark specific failure
|
if($e instanceof ClientException) { //postmark specific failure
|
||||||
|
|
||||||
$response = $e->getResponse();
|
$response = $e->getResponse();
|
||||||
|
$message_body = json_decode($response->getBody()->getContents());
|
||||||
|
|
||||||
|
if(property_exists($message_body, 'Message')){
|
||||||
|
$message = $message_body->Message;
|
||||||
|
nlog($message);
|
||||||
|
}
|
||||||
|
|
||||||
nlog($response);
|
|
||||||
// $message = $response->Message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the is an entity attached to the message send a failure mailer */
|
||||||
if($this->nmo->entity)
|
if($this->nmo->entity)
|
||||||
$this->entityEmailFailed($message);
|
$this->entityEmailFailed($message);
|
||||||
|
|
||||||
if(Ninja::isHosted() && (!$e instanceof ClientException)) // Don't send postmark failures to Sentry
|
/* Don't send postmark failures to Sentry */
|
||||||
|
if(Ninja::isHosted() && (!$e instanceof ClientException))
|
||||||
app('sentry')->captureException($e);
|
app('sentry')->captureException($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,6 +640,7 @@ class Import implements ShouldQueue
|
|||||||
$client->updated_at = Carbon::parse($modified['updated_at']);
|
$client->updated_at = Carbon::parse($modified['updated_at']);
|
||||||
|
|
||||||
$client->save(['timestamps' => false]);
|
$client->save(['timestamps' => false]);
|
||||||
|
$client->fresh();
|
||||||
|
|
||||||
$client->contacts()->forceDelete();
|
$client->contacts()->forceDelete();
|
||||||
|
|
||||||
@ -650,7 +651,7 @@ class Import implements ShouldQueue
|
|||||||
$modified_contacts[$key]['company_id'] = $this->company->id;
|
$modified_contacts[$key]['company_id'] = $this->company->id;
|
||||||
$modified_contacts[$key]['user_id'] = $this->processUserId($resource);
|
$modified_contacts[$key]['user_id'] = $this->processUserId($resource);
|
||||||
$modified_contacts[$key]['client_id'] = $client->id;
|
$modified_contacts[$key]['client_id'] = $client->id;
|
||||||
$modified_contacts[$key]['password'] = 'mysuperpassword'; // @todo, and clean up the code..
|
$modified_contacts[$key]['password'] = Str::random(8);
|
||||||
unset($modified_contacts[$key]['id']);
|
unset($modified_contacts[$key]['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,6 +686,8 @@ class Import implements ShouldQueue
|
|||||||
'old' => $resource['id'],
|
'old' => $resource['id'],
|
||||||
'new' => $client->id,
|
'new' => $client->id,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$client = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::reguard();
|
Client::reguard();
|
||||||
|
@ -88,7 +88,7 @@ class PaymentNotification implements ShouldQueue
|
|||||||
$client = $payment->client;
|
$client = $payment->client;
|
||||||
$amount = $payment->amount;
|
$amount = $payment->amount;
|
||||||
|
|
||||||
if ($invoice) {
|
if ($invoice && $invoice->line_items) {
|
||||||
$items = $invoice->line_items;
|
$items = $invoice->line_items;
|
||||||
$item = end($items)->product_key;
|
$item = end($items)->product_key;
|
||||||
$entity_number = $invoice->number;
|
$entity_number = $invoice->number;
|
||||||
|
@ -62,9 +62,10 @@ class SupportMessageSent extends Mailable
|
|||||||
$company = auth()->user()->company();
|
$company = auth()->user()->company();
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$db = str_replace("db-ninja-", "", $company->db);
|
$db = str_replace("db-ninja-", "", $company->db);
|
||||||
|
$is_large = $company->is_large ? "L" : "";
|
||||||
|
|
||||||
if(Ninja::isHosted())
|
if(Ninja::isHosted())
|
||||||
$subject = "{$priority}Hosted-{$db}-[{$company->is_large}] :: {$plan} :: ".date('M jS, g:ia');
|
$subject = "{$priority}Hosted-{$db}{$is_large} :: {$plan} :: ".date('M jS, g:ia');
|
||||||
else
|
else
|
||||||
$subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia');
|
$subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia');
|
||||||
|
|
||||||
|
@ -126,7 +126,11 @@ class TemplateEmail extends Mailable
|
|||||||
if($this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_DOCUMENTS)){
|
if($this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_DOCUMENTS)){
|
||||||
|
|
||||||
$ubl_string = CreateUbl::dispatchNow($this->invitation->invoice);
|
$ubl_string = CreateUbl::dispatchNow($this->invitation->invoice);
|
||||||
$this->attachData($ubl_string, $this->invitation->invoice->getFileName('xml'));
|
|
||||||
|
nlog($ubl_string);
|
||||||
|
|
||||||
|
if($ubl_string)
|
||||||
|
$this->attachData($ubl_string, $this->invitation->invoice->getFileName('xml'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
'contacts.company',
|
'contacts.company',
|
||||||
// 'currency',
|
// 'currency',
|
||||||
// 'primary_contact',
|
// 'primary_contact',
|
||||||
// 'country',
|
'country',
|
||||||
// 'contacts',
|
// 'contacts',
|
||||||
// 'shipping_country',
|
// 'shipping_country',
|
||||||
// 'company',
|
// 'company',
|
||||||
@ -218,7 +218,7 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
|
|
||||||
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')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function country()
|
public function country()
|
||||||
|
@ -92,7 +92,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
|
|||||||
'custom_value4',
|
'custom_value4',
|
||||||
'email',
|
'email',
|
||||||
'is_primary',
|
'is_primary',
|
||||||
'client_id',
|
// 'client_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,10 +13,12 @@ namespace App\Models;
|
|||||||
|
|
||||||
use App\Utils\Traits\MakesDates;
|
use App\Utils\Traits\MakesDates;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class ClientGatewayToken extends BaseModel
|
class ClientGatewayToken extends BaseModel
|
||||||
{
|
{
|
||||||
use MakesDates;
|
use MakesDates;
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'meta' => 'object',
|
'meta' => 'object',
|
||||||
|
@ -36,7 +36,7 @@ class CompanyLedger extends Model
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
|
@ -23,6 +23,8 @@ class CompanyToken extends BaseModel
|
|||||||
];
|
];
|
||||||
|
|
||||||
protected $with = [
|
protected $with = [
|
||||||
|
'company',
|
||||||
|
'user'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $touches = [];
|
protected $touches = [];
|
||||||
|
@ -78,7 +78,7 @@ class CompanyUser extends Pivot
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
|
@ -120,7 +120,7 @@ class Credit extends BaseModel
|
|||||||
|
|
||||||
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')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function history()
|
public function history()
|
||||||
|
@ -84,7 +84,7 @@ class Expense extends BaseModel
|
|||||||
|
|
||||||
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')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
|
@ -52,7 +52,7 @@ class GroupSetting extends StaticModel
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clients()
|
public function clients()
|
||||||
|
@ -45,6 +45,11 @@ class Proposal 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');
|
||||||
|
@ -76,7 +76,7 @@ class Subscription extends BaseModel
|
|||||||
|
|
||||||
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function nextDateByInterval($date, $frequency_id)
|
public function nextDateByInterval($date, $frequency_id)
|
||||||
|
@ -66,7 +66,7 @@ class Task extends BaseModel
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function client()
|
public function client()
|
||||||
|
@ -82,7 +82,7 @@ class Vendor extends BaseModel
|
|||||||
|
|
||||||
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')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function contacts()
|
public function contacts()
|
||||||
|
@ -87,7 +87,7 @@ class Webhook extends BaseModel
|
|||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Jobs\Invoice\CreateUbl;
|
||||||
|
use App\Models\Invoice;
|
||||||
use App\Utils\TempFile;
|
use App\Utils\TempFile;
|
||||||
use App\Utils\Traits\MakesInvoiceHtml;
|
use App\Utils\Traits\MakesInvoiceHtml;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
@ -46,7 +46,7 @@ class InvoiceObserver
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function updated(Invoice $invoice)
|
public function updated(Invoice $invoice)
|
||||||
{nlog("updated");
|
{
|
||||||
$subscriptions = Webhook::where('company_id', $invoice->company->id)
|
$subscriptions = Webhook::where('company_id', $invoice->company->id)
|
||||||
->where('event_id', Webhook::EVENT_UPDATE_INVOICE)
|
->where('event_id', Webhook::EVENT_UPDATE_INVOICE)
|
||||||
->exists();
|
->exists();
|
||||||
|
@ -205,7 +205,6 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
|
|
||||||
$invoices->each(function ($invoice) use ($payment) {
|
$invoices->each(function ($invoice) use ($payment) {
|
||||||
event(new InvoiceWasPaid($invoice, $payment, $payment->company, Ninja::eventVars()));
|
event(new InvoiceWasPaid($invoice, $payment, $payment->company, Ninja::eventVars()));
|
||||||
$invoice->service()->workFlow();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return $payment->service()->applyNumber()->save();
|
return $payment->service()->applyNumber()->save();
|
||||||
|
@ -362,9 +362,14 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
$response = null;
|
$response = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $this->stripe
|
// $response = $this->stripe
|
||||||
->refunds
|
// ->refunds
|
||||||
->create(['charge' => $payment->transaction_reference, 'amount' => $this->convertToStripeAmount($amount, $this->client->currency()->precision, $this->client->currency())], $meta);
|
// ->create(['charge' => $payment->transaction_reference, 'amount' => $this->convertToStripeAmount($amount, $this->client->currency()->precision, $this->client->currency())], $meta);
|
||||||
|
|
||||||
|
$response = \Stripe\Refund::create([
|
||||||
|
'charge' => $payment->transaction_reference,
|
||||||
|
'amount' => $this->convertToStripeAmount($amount, $this->client->currency()->precision, $this->client->currency())
|
||||||
|
], $meta);
|
||||||
|
|
||||||
if ($response->status == $response::STATUS_SUCCEEDED) {
|
if ($response->status == $response::STATUS_SUCCEEDED) {
|
||||||
SystemLogger::dispatch(['server_response' => $response, 'data' => request()->all(),], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->client, $this->client->company);
|
SystemLogger::dispatch(['server_response' => $response, 'data' => request()->all(),], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->client, $this->client->company);
|
||||||
|
@ -60,12 +60,18 @@ use WePayCommon;
|
|||||||
'method' => '1',
|
'method' => '1',
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
|
try {
|
||||||
'client_id' => config('ninja.wepay.client_id'),
|
|
||||||
'client_secret' => config('ninja.wepay.client_secret'),
|
|
||||||
'credit_card_id' => (int)$data['credit_card_id'],
|
|
||||||
));
|
|
||||||
|
|
||||||
|
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
|
||||||
|
'client_id' => config('ninja.wepay.client_id'),
|
||||||
|
'client_secret' => config('ninja.wepay.client_secret'),
|
||||||
|
'credit_card_id' => (int)$data['credit_card_id'],
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
return $this->wepay_payment_driver->processInternallyFailedPayment($this->wepay_payment_driver, $e);
|
||||||
|
}
|
||||||
// display the response
|
// display the response
|
||||||
// nlog($response);
|
// nlog($response);
|
||||||
|
|
||||||
@ -116,11 +122,16 @@ use WePayCommon;
|
|||||||
{
|
{
|
||||||
nlog("authorize the card first!");
|
nlog("authorize the card first!");
|
||||||
|
|
||||||
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
|
try {
|
||||||
'client_id' => config('ninja.wepay.client_id'),
|
$response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', array(
|
||||||
'client_secret' => config('ninja.wepay.client_secret'),
|
'client_id' => config('ninja.wepay.client_id'),
|
||||||
'credit_card_id' => (int)$request->input('credit_card_id'),
|
'client_secret' => config('ninja.wepay.client_secret'),
|
||||||
));
|
'credit_card_id' => (int)$request->input('credit_card_id'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
return $this->wepay_payment_driver->processInternallyFailedPayment($this->wepay_payment_driver, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$credit_card_id = (int)$response->credit_card_id;
|
$credit_card_id = (int)$response->credit_card_id;
|
||||||
|
|
||||||
|
@ -56,9 +56,11 @@ class ClientContactRepository extends BaseRepository
|
|||||||
|
|
||||||
if (! $update_contact) {
|
if (! $update_contact) {
|
||||||
$update_contact = ClientContactFactory::create($client->company_id, $client->user_id);
|
$update_contact = ClientContactFactory::create($client->company_id, $client->user_id);
|
||||||
$update_contact->client_id = $client->id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//10-09-2021 - enforce the client->id and remove client_id from fillables
|
||||||
|
$update_contact->client_id = $client->id;
|
||||||
|
|
||||||
/* We need to set NULL email addresses to blank strings to pass authentication*/
|
/* We need to set NULL email addresses to blank strings to pass authentication*/
|
||||||
if(array_key_exists('email', $contact) && is_null($contact['email']))
|
if(array_key_exists('email', $contact) && is_null($contact['email']))
|
||||||
$contact['email'] = '';
|
$contact['email'] = '';
|
||||||
@ -88,5 +90,7 @@ class ClientContactRepository extends BaseRepository
|
|||||||
$new_contact->email = ' ';
|
$new_contact->email = ' ';
|
||||||
$new_contact->save();
|
$new_contact->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$client = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,8 @@ class TriggeredActions extends AbstractService
|
|||||||
private function sendEmail()
|
private function sendEmail()
|
||||||
{
|
{
|
||||||
|
|
||||||
//$reminder_template = $this->invoice->calculateTemplate('invoice');
|
$reminder_template = $this->invoice->calculateTemplate('invoice');
|
||||||
$reminder_template = 'payment';
|
//$reminder_template = 'payment';
|
||||||
|
|
||||||
$this->invoice->invitations->load('contact.client.country', 'invoice.client.country', 'invoice.company')->each(function ($invitation) use ($reminder_template) {
|
$this->invoice->invitations->load('contact.client.country', 'invoice.client.country', 'invoice.company')->each(function ($invitation) use ($reminder_template) {
|
||||||
EmailEntity::dispatch($invitation, $this->invoice->company, $reminder_template);
|
EmailEntity::dispatch($invitation, $this->invoice->company, $reminder_template);
|
||||||
|
@ -83,6 +83,7 @@ class UpdateInvoicePayment
|
|||||||
->updatePaidToDate($paid_amount)
|
->updatePaidToDate($paid_amount)
|
||||||
->updateStatus()
|
->updateStatus()
|
||||||
->deletePdf()
|
->deletePdf()
|
||||||
|
->workFlow()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
@ -38,6 +38,7 @@ use App\Utils\Traits\MakesHash;
|
|||||||
use App\Utils\Traits\SubscriptionHooker;
|
use App\Utils\Traits\SubscriptionHooker;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
|
|
||||||
class SubscriptionService
|
class SubscriptionService
|
||||||
{
|
{
|
||||||
@ -950,7 +951,12 @@ class SubscriptionService
|
|||||||
return redirect($default_redirect);
|
return redirect($default_redirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function planPaid($invoice)
|
/**
|
||||||
|
* @param Invoice $invoice
|
||||||
|
* @return true
|
||||||
|
* @throws BindingResolutionException
|
||||||
|
*/
|
||||||
|
public function planPaid(Invoice $invoice)
|
||||||
{
|
{
|
||||||
$recurring_invoice_hashed_id = $invoice->recurring_invoice()->exists() ? $invoice->recurring_invoice->hashed_id : null;
|
$recurring_invoice_hashed_id = $invoice->recurring_invoice()->exists() ? $invoice->recurring_invoice->hashed_id : null;
|
||||||
|
|
||||||
@ -959,12 +965,14 @@ class SubscriptionService
|
|||||||
'subscription' => $this->subscription->hashed_id,
|
'subscription' => $this->subscription->hashed_id,
|
||||||
'recurring_invoice' => $recurring_invoice_hashed_id,
|
'recurring_invoice' => $recurring_invoice_hashed_id,
|
||||||
'client' => $invoice->client->hashed_id,
|
'client' => $invoice->client->hashed_id,
|
||||||
'contact' => $invoice->client->primary_contact()->first() ? $invoice->client->contacts->first() : false,
|
'contact' => $invoice->client->primary_contact()->first() ? $invoice->client->primary_contact()->first(): $invoice->client->contacts->first(),
|
||||||
'invoice' => $invoice->hashed_id,
|
'invoice' => $invoice->hashed_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->triggerWebhook($context);
|
$response = $this->triggerWebhook($context);
|
||||||
|
|
||||||
|
nlog($response);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,8 @@ 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', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => '5.3.8',
|
'app_version' => '5.3.9',
|
||||||
'app_tag' => '5.3.8',
|
'app_tag' => '5.3.9',
|
||||||
'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', ''),
|
||||||
|
6
public/flutter_service_worker.js
vendored
6
public/flutter_service_worker.js
vendored
@ -3,12 +3,12 @@ const MANIFEST = 'flutter-app-manifest';
|
|||||||
const TEMP = 'flutter-temp-cache';
|
const TEMP = 'flutter-temp-cache';
|
||||||
const CACHE_NAME = 'flutter-app-cache';
|
const CACHE_NAME = 'flutter-app-cache';
|
||||||
const RESOURCES = {
|
const RESOURCES = {
|
||||||
"main.dart.js": "a4ce90340b3e610ee073d2f40c0377c1",
|
"main.dart.js": "0124649b1dd42c7fd93b9489eaf99b1e",
|
||||||
"version.json": "46d4015fc9abcefe5371cafcf2084173",
|
"version.json": "9ec5e3813adc4bfd8713556c5059e97d",
|
||||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||||
"/": "7fb4e233bcd97d5af44e8e4ed2d9784b",
|
"/": "debe3f3301b29dcbdc324fb3f330965a",
|
||||||
"assets/NOTICES": "9eb7e2eb2888ea5bae5f536720db37cd",
|
"assets/NOTICES": "9eb7e2eb2888ea5bae5f536720db37cd",
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
||||||
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
||||||
|
172461
public/main.dart.js
vendored
172461
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
171966
public/main.foss.dart.js
vendored
171966
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4102
public/main.profile.dart.js
vendored
4102
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
175855
public/main.wasm.dart.js
vendored
175855
public/main.wasm.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"app_name":"invoiceninja_flutter","version":"5.0.58","build_number":"58"}
|
{"app_name":"invoiceninja_flutter","version":"5.0.59","build_number":"59"}
|
@ -36,7 +36,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.company-logo {
|
.company-logo {
|
||||||
max-width: 55%;
|
height: 100%;
|
||||||
|
padding-right: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#company-details,
|
#company-details,
|
||||||
@ -252,6 +253,10 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
max-height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
/** Useful snippets, uncomment to enable. **/
|
/** Useful snippets, uncomment to enable. **/
|
||||||
|
|
||||||
/** Hide company logo **/
|
/** Hide company logo **/
|
||||||
@ -288,7 +293,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="header-wrapper" id="header">
|
<div class="header-wrapper" id="header">
|
||||||
<img class="company-logo" src="$company.logo" alt="$company.name logo"/>
|
<div class="logo-container">
|
||||||
|
<img class="company-logo" src="$company.logo" alt="$company.name logo"/>
|
||||||
|
</div>
|
||||||
<div id="company-details"></div>
|
<div id="company-details"></div>
|
||||||
<div id="company-address"></div>
|
<div id="company-address"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -208,6 +208,7 @@ trait MockAccountData
|
|||||||
$this->cu = CompanyUserFactory::create($user->id, $this->company->id, $this->account->id);
|
$this->cu = CompanyUserFactory::create($user->id, $this->company->id, $this->account->id);
|
||||||
$this->cu->is_owner = true;
|
$this->cu->is_owner = true;
|
||||||
$this->cu->is_admin = true;
|
$this->cu->is_admin = true;
|
||||||
|
$this->cu->is_locked = false;
|
||||||
$this->cu->save();
|
$this->cu->save();
|
||||||
|
|
||||||
$this->token = \Illuminate\Support\Str::random(64);
|
$this->token = \Illuminate\Support\Str::random(64);
|
||||||
|
Loading…
Reference in New Issue
Block a user