mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 22:34:31 -04:00
Merge branch 'v5-develop' of https://github.com/invoiceninja/invoiceninja into feature-inbound-email-expenses
This commit is contained in:
commit
0aaaf27314
@ -13,5 +13,10 @@ namespace Illuminate\Contracts\Mail
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function brevo_config(string $key)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,53 +11,54 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\DataMapper\ClientRegistrationFields;
|
use stdClass;
|
||||||
use App\DataMapper\CompanySettings;
|
use Carbon\Carbon;
|
||||||
use App\DataMapper\FeesAndLimits;
|
use Faker\Factory;
|
||||||
use App\Events\Invoice\InvoiceWasCreated;
|
use App\Models\Task;
|
||||||
use App\Events\RecurringInvoice\RecurringInvoiceWasCreated;
|
use App\Models\User;
|
||||||
use App\Factory\GroupSettingFactory;
|
use App\Utils\Ninja;
|
||||||
use App\Factory\InvoiceFactory;
|
use App\Models\Quote;
|
||||||
use App\Factory\InvoiceItemFactory;
|
|
||||||
use App\Factory\RecurringInvoiceFactory;
|
|
||||||
use App\Factory\SubscriptionFactory;
|
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
|
||||||
use App\Jobs\Company\CreateCompanyTaskStatuses;
|
|
||||||
use App\Libraries\MultiDB;
|
|
||||||
use App\Models\Account;
|
|
||||||
use App\Models\BankIntegration;
|
|
||||||
use App\Models\BankTransaction;
|
|
||||||
use App\Models\BankTransactionRule;
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\Company;
|
|
||||||
use App\Models\CompanyGateway;
|
|
||||||
use App\Models\CompanyToken;
|
|
||||||
use App\Models\Country;
|
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
use App\Models\Vendor;
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Country;
|
||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Quote;
|
|
||||||
use App\Models\RecurringInvoice;
|
|
||||||
use App\Models\Task;
|
|
||||||
use App\Models\TaskStatus;
|
|
||||||
use App\Models\TaxRate;
|
use App\Models\TaxRate;
|
||||||
use App\Models\User;
|
use App\Libraries\MultiDB;
|
||||||
use App\Models\Vendor;
|
use App\Models\TaskStatus;
|
||||||
|
use App\Models\CompanyToken;
|
||||||
|
use App\Models\ClientContact;
|
||||||
use App\Models\VendorContact;
|
use App\Models\VendorContact;
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Models\CompanyGateway;
|
||||||
use App\Utils\Ninja;
|
use App\Factory\InvoiceFactory;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Models\BankIntegration;
|
||||||
|
use App\Models\BankTransaction;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Carbon\Carbon;
|
|
||||||
use Faker\Factory;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\DataMapper\FeesAndLimits;
|
||||||
|
use App\DataMapper\ClientSettings;
|
||||||
|
use App\DataMapper\CompanySettings;
|
||||||
|
use App\Factory\InvoiceItemFactory;
|
||||||
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Models\BankTransactionRule;
|
||||||
|
use App\Factory\GroupSettingFactory;
|
||||||
|
use App\Factory\SubscriptionFactory;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
use stdClass;
|
use App\Repositories\InvoiceRepository;
|
||||||
|
use App\Factory\RecurringInvoiceFactory;
|
||||||
|
use App\Events\Invoice\InvoiceWasCreated;
|
||||||
|
use App\DataMapper\ClientRegistrationFields;
|
||||||
|
use App\Jobs\Company\CreateCompanyTaskStatuses;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasCreated;
|
||||||
|
|
||||||
class CreateSingleAccount extends Command
|
class CreateSingleAccount extends Command
|
||||||
{
|
{
|
||||||
@ -951,7 +952,7 @@ class CreateSingleAccount extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config('ninja.testvars.paytrace.decrypted') && ($this->gateway == 'all' || $this->gateway == 'paytrace')) {
|
if (config('ninja.testvars.paytrace') && ($this->gateway == 'all' || $this->gateway == 'paytrace')) {
|
||||||
$cg = new CompanyGateway();
|
$cg = new CompanyGateway();
|
||||||
$cg->company_id = $company->id;
|
$cg->company_id = $company->id;
|
||||||
$cg->user_id = $user->id;
|
$cg->user_id = $user->id;
|
||||||
@ -960,7 +961,7 @@ class CreateSingleAccount extends Command
|
|||||||
$cg->require_billing_address = true;
|
$cg->require_billing_address = true;
|
||||||
$cg->require_shipping_address = true;
|
$cg->require_shipping_address = true;
|
||||||
$cg->update_details = true;
|
$cg->update_details = true;
|
||||||
$cg->config = encrypt(config('ninja.testvars.paytrace.decrypted'));
|
$cg->config = encrypt(config('ninja.testvars.paytrace'));
|
||||||
|
|
||||||
$cg->save();
|
$cg->save();
|
||||||
|
|
||||||
@ -1015,6 +1016,85 @@ class CreateSingleAccount extends Command
|
|||||||
$cg->fees_and_limits = $fees_and_limits;
|
$cg->fees_and_limits = $fees_and_limits;
|
||||||
$cg->save();
|
$cg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config('ninja.testvars.eway') && ($this->gateway == 'all' || $this->gateway == 'eway')) {
|
||||||
|
$cg = new CompanyGateway();
|
||||||
|
$cg->company_id = $company->id;
|
||||||
|
$cg->user_id = $user->id;
|
||||||
|
$cg->gateway_key = '944c20175bbe6b9972c05bcfe294c2c7';
|
||||||
|
$cg->require_cvv = true;
|
||||||
|
$cg->require_billing_address = true;
|
||||||
|
$cg->require_shipping_address = true;
|
||||||
|
$cg->update_details = true;
|
||||||
|
$cg->config = encrypt(config('ninja.testvars.eway'));
|
||||||
|
$cg->save();
|
||||||
|
|
||||||
|
$gateway_types = $cg->driver()->gatewayTypes();
|
||||||
|
|
||||||
|
$fees_and_limits = new stdClass();
|
||||||
|
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits();
|
||||||
|
|
||||||
|
$cg->fees_and_limits = $fees_and_limits;
|
||||||
|
$cg->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (config('ninja.testvars.gocardless') && ($this->gateway == 'all' || $this->gateway == 'gocardless')) {
|
||||||
|
|
||||||
|
$c_settings = ClientSettings::defaults();
|
||||||
|
$c_settings->currency_id = '2';
|
||||||
|
|
||||||
|
$client = Client::factory()->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'name' => 'cypress',
|
||||||
|
'country_id' => 826,
|
||||||
|
'settings' => $c_settings
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cg = new CompanyGateway();
|
||||||
|
$cg->company_id = $company->id;
|
||||||
|
$cg->user_id = $user->id;
|
||||||
|
$cg->gateway_key = 'b9886f9257f0c6ee7c302f1c74475f6c';
|
||||||
|
$cg->require_cvv = true;
|
||||||
|
$cg->require_billing_address = true;
|
||||||
|
$cg->require_shipping_address = true;
|
||||||
|
$cg->update_details = true;
|
||||||
|
$cg->config = encrypt(config('ninja.testvars.gocardless'));
|
||||||
|
$cg->save();
|
||||||
|
|
||||||
|
$gateway_types = $cg->driver($client)->gatewayTypes();
|
||||||
|
|
||||||
|
$fees_and_limits = new stdClass();
|
||||||
|
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits();
|
||||||
|
|
||||||
|
$cg->fees_and_limits = $fees_and_limits;
|
||||||
|
$cg->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config('ninja.testvars.forte') && ($this->gateway == 'all' || $this->gateway == 'forte')) {
|
||||||
|
$cg = new CompanyGateway();
|
||||||
|
$cg->company_id = $company->id;
|
||||||
|
$cg->user_id = $user->id;
|
||||||
|
$cg->gateway_key = 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs';
|
||||||
|
$cg->require_cvv = true;
|
||||||
|
$cg->require_billing_address = true;
|
||||||
|
$cg->require_shipping_address = true;
|
||||||
|
$cg->update_details = true;
|
||||||
|
$cg->config = encrypt(config('ninja.testvars.forte'));
|
||||||
|
$cg->save();
|
||||||
|
|
||||||
|
$gateway_types = $cg->driver()->gatewayTypes();
|
||||||
|
|
||||||
|
$fees_and_limits = new stdClass();
|
||||||
|
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits();
|
||||||
|
|
||||||
|
$cg->fees_and_limits = $fees_and_limits;
|
||||||
|
$cg->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createRecurringInvoice(Client $client)
|
private function createRecurringInvoice(Client $client)
|
||||||
|
@ -229,7 +229,7 @@ class CompanySettings extends BaseSettings
|
|||||||
public $require_quote_signature = false; //@TODO ben to confirm
|
public $require_quote_signature = false; //@TODO ben to confirm
|
||||||
|
|
||||||
//email settings
|
//email settings
|
||||||
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun', 'mailgun' //@implemented
|
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun', 'mailgun', 'client_brevo' //@implemented
|
||||||
|
|
||||||
public $gmail_sending_user_id = '0'; //@implemented
|
public $gmail_sending_user_id = '0'; //@implemented
|
||||||
|
|
||||||
@ -451,6 +451,8 @@ class CompanySettings extends BaseSettings
|
|||||||
|
|
||||||
public $mailgun_endpoint = 'api.mailgun.net'; //api.eu.mailgun.net
|
public $mailgun_endpoint = 'api.mailgun.net'; //api.eu.mailgun.net
|
||||||
|
|
||||||
|
public $brevo_secret = '';
|
||||||
|
|
||||||
public $auto_bill_standard_invoices = false;
|
public $auto_bill_standard_invoices = false;
|
||||||
|
|
||||||
public $email_alignment = 'center'; // center , left, right
|
public $email_alignment = 'center'; // center , left, right
|
||||||
@ -497,7 +499,10 @@ class CompanySettings extends BaseSettings
|
|||||||
|
|
||||||
public $use_unapplied_payment = 'off'; //always, option, off //@implemented
|
public $use_unapplied_payment = 'off'; //always, option, off //@implemented
|
||||||
|
|
||||||
|
public $enable_rappen_rounding = false;
|
||||||
|
|
||||||
public static $casts = [
|
public static $casts = [
|
||||||
|
'enable_rappen_rounding' => 'bool',
|
||||||
'use_unapplied_payment' => 'string',
|
'use_unapplied_payment' => 'string',
|
||||||
'show_pdfhtml_on_mobile' => 'bool',
|
'show_pdfhtml_on_mobile' => 'bool',
|
||||||
'payment_email_all_contacts' => 'bool',
|
'payment_email_all_contacts' => 'bool',
|
||||||
@ -527,6 +532,7 @@ class CompanySettings extends BaseSettings
|
|||||||
'postmark_secret' => 'string',
|
'postmark_secret' => 'string',
|
||||||
'mailgun_secret' => 'string',
|
'mailgun_secret' => 'string',
|
||||||
'mailgun_domain' => 'string',
|
'mailgun_domain' => 'string',
|
||||||
|
'brevo_secret' => 'string',
|
||||||
'send_email_on_mark_paid' => 'bool',
|
'send_email_on_mark_paid' => 'bool',
|
||||||
'vendor_portal_enable_uploads' => 'bool',
|
'vendor_portal_enable_uploads' => 'bool',
|
||||||
'besr_id' => 'string',
|
'besr_id' => 'string',
|
||||||
@ -848,7 +854,7 @@ class CompanySettings extends BaseSettings
|
|||||||
$company_settings = (object) get_class_vars(self::class);
|
$company_settings = (object) get_class_vars(self::class);
|
||||||
|
|
||||||
foreach ($company_settings as $key => $value) {
|
foreach ($company_settings as $key => $value) {
|
||||||
if (! property_exists($settings, $key)) {
|
if (!property_exists($settings, $key)) {
|
||||||
$settings->{$key} = self::castAttribute($key, $company_settings->{$key});
|
$settings->{$key} = self::castAttribute($key, $company_settings->{$key});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,7 +887,7 @@ class CompanySettings extends BaseSettings
|
|||||||
{
|
{
|
||||||
$notification = new stdClass();
|
$notification = new stdClass();
|
||||||
$notification->email = [];
|
$notification->email = [];
|
||||||
$notification->email = ['invoice_sent_all','payment_success_all','payment_manual_all'];
|
$notification->email = ['invoice_sent_all', 'payment_success_all', 'payment_manual_all'];
|
||||||
|
|
||||||
return $notification;
|
return $notification;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ class SettingsData
|
|||||||
|
|
||||||
public bool $show_accept_quote_terms = false; //@TODO ben to confirm
|
public bool $show_accept_quote_terms = false; //@TODO ben to confirm
|
||||||
|
|
||||||
public string $email_sending_method = 'default'; // enum 'default', 'gmail', 'office365', 'client_postmark', 'client_mailgun' //@implemented
|
public string $email_sending_method = 'default'; // enum 'default', 'gmail', 'office365', 'client_postmark', 'client_mailgun' , 'client_brevo' //@implemented
|
||||||
|
|
||||||
public string $gmail_sending_user_id = '0'; //@implemented
|
public string $gmail_sending_user_id = '0'; //@implemented
|
||||||
|
|
||||||
@ -433,6 +433,8 @@ class SettingsData
|
|||||||
|
|
||||||
public string $mailgun_endpoint = 'api.mailgun.net'; // api.eu.mailgun.net
|
public string $mailgun_endpoint = 'api.mailgun.net'; // api.eu.mailgun.net
|
||||||
|
|
||||||
|
public string $brevo_secret = '';
|
||||||
|
|
||||||
public bool $auto_bill_standard_invoices = false;
|
public bool $auto_bill_standard_invoices = false;
|
||||||
|
|
||||||
public string $email_alignment = 'center'; // center, left, right
|
public string $email_alignment = 'center'; // center, left, right
|
||||||
@ -469,8 +471,8 @@ class SettingsData
|
|||||||
|
|
||||||
public function cast(mixed $object)
|
public function cast(mixed $object)
|
||||||
{
|
{
|
||||||
if(is_array($object)) {
|
if (is_array($object)) {
|
||||||
$object = (object)$object;
|
$object = (object) $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_object($object)) {
|
if (is_object($object)) {
|
||||||
@ -478,9 +480,9 @@ class SettingsData
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
settype($object->{$key}, gettype($this->{$key}));
|
settype($object->{$key}, gettype($this->{$key}));
|
||||||
} catch(\Exception | \Error | \Throwable $e) {
|
} catch (\Exception | \Error | \Throwable $e) {
|
||||||
|
|
||||||
if(property_exists($this, $key)) {
|
if (property_exists($this, $key)) {
|
||||||
$object->{$key} = $this->{$key};
|
$object->{$key} = $this->{$key};
|
||||||
} else {
|
} else {
|
||||||
unset($object->{$key});
|
unset($object->{$key});
|
||||||
@ -506,11 +508,11 @@ class SettingsData
|
|||||||
|
|
||||||
public function toObject(): object
|
public function toObject(): object
|
||||||
{
|
{
|
||||||
return (object)$this->object;
|
return (object) $this->object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return (array)$this->object;
|
return (array) $this->object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
88398
app/DataProviders/SMSNumbers.php
Normal file
88398
app/DataProviders/SMSNumbers.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -294,6 +294,7 @@ class BaseExport
|
|||||||
'line_total' => 'item.line_total',
|
'line_total' => 'item.line_total',
|
||||||
'gross_line_total' => 'item.gross_line_total',
|
'gross_line_total' => 'item.gross_line_total',
|
||||||
'tax_amount' => 'item.tax_amount',
|
'tax_amount' => 'item.tax_amount',
|
||||||
|
'product_cost' => 'item.product_cost'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected array $quote_report_keys = [
|
protected array $quote_report_keys = [
|
||||||
|
@ -59,6 +59,9 @@ class DesignFilters extends QueryFilters
|
|||||||
public function entities(string $entities = ''): Builder
|
public function entities(string $entities = ''): Builder
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(stripos($entities, 'statement') !== false)
|
||||||
|
$entities = 'client';
|
||||||
|
|
||||||
if (strlen($entities) == 0 || str_contains($entities, ',')) {
|
if (strlen($entities) == 0 || str_contains($entities, ',')) {
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,9 @@ class InvoiceFilters extends QueryFilters
|
|||||||
|
|
||||||
if($sort_col[0] == 'number') {
|
if($sort_col[0] == 'number') {
|
||||||
// return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
|
// return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
|
||||||
return $this->builder->orderByRaw('ABS(number) ' . $dir);
|
// return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number");
|
||||||
|
// return $this->builder->orderByRaw('ABS(number) ' . $dir);
|
||||||
|
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $dir);
|
return $this->builder->orderBy($sort_col[0], $dir);
|
||||||
|
@ -52,6 +52,7 @@ class InvoiceSum
|
|||||||
|
|
||||||
public InvoiceItemSum $invoice_items;
|
public InvoiceItemSum $invoice_items;
|
||||||
|
|
||||||
|
private $rappen_rounding = false;
|
||||||
/**
|
/**
|
||||||
* Constructs the object with Invoice and Settings object.
|
* Constructs the object with Invoice and Settings object.
|
||||||
*
|
*
|
||||||
@ -63,8 +64,11 @@ class InvoiceSum
|
|||||||
|
|
||||||
if ($this->invoice->client) {
|
if ($this->invoice->client) {
|
||||||
$this->precision = $this->invoice->client->currency()->precision;
|
$this->precision = $this->invoice->client->currency()->precision;
|
||||||
|
$this->rappen_rounding = $this->invoice->client->getSetting('enable_rappen_rounding');
|
||||||
} else {
|
} else {
|
||||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
$this->precision = $this->invoice->vendor->currency()->precision;
|
||||||
|
$this->rappen_rounding = $this->invoice->vendor->getSetting('enable_rappen_rounding');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tax_map = new Collection();
|
$this->tax_map = new Collection();
|
||||||
@ -252,11 +256,20 @@ class InvoiceSum
|
|||||||
/* Set new calculated total */
|
/* Set new calculated total */
|
||||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||||
|
|
||||||
|
if($this->rappen_rounding)
|
||||||
|
$this->invoice->amount = $this->roundRappen($this->invoice->amount);
|
||||||
|
|
||||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function roundRappen($value): float
|
||||||
|
{
|
||||||
|
return round($value / .05, 0) * .05;
|
||||||
|
}
|
||||||
|
|
||||||
public function getSubTotal()
|
public function getSubTotal()
|
||||||
{
|
{
|
||||||
return $this->sub_total;
|
return $this->sub_total;
|
||||||
|
@ -47,6 +47,8 @@ class InvoiceSumInclusive
|
|||||||
|
|
||||||
private $precision;
|
private $precision;
|
||||||
|
|
||||||
|
private $rappen_rounding = false;
|
||||||
|
|
||||||
public InvoiceItemSumInclusive $invoice_items;
|
public InvoiceItemSumInclusive $invoice_items;
|
||||||
/**
|
/**
|
||||||
* Constructs the object with Invoice and Settings object.
|
* Constructs the object with Invoice and Settings object.
|
||||||
@ -59,8 +61,10 @@ class InvoiceSumInclusive
|
|||||||
|
|
||||||
if ($this->invoice->client) {
|
if ($this->invoice->client) {
|
||||||
$this->precision = $this->invoice->client->currency()->precision;
|
$this->precision = $this->invoice->client->currency()->precision;
|
||||||
|
$this->rappen_rounding = $this->invoice->client->getSetting('enable_rappen_rounding');
|
||||||
} else {
|
} else {
|
||||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
$this->precision = $this->invoice->vendor->currency()->precision;
|
||||||
|
$this->rappen_rounding = $this->invoice->vendor->getSetting('enable_rappen_rounding');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tax_map = new Collection();
|
$this->tax_map = new Collection();
|
||||||
@ -268,13 +272,23 @@ class InvoiceSumInclusive
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set new calculated total */
|
/* Set new calculated total */
|
||||||
|
/** @todo - rappen rounding here */
|
||||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||||
|
|
||||||
|
if($this->rappen_rounding) {
|
||||||
|
$this->invoice->amount = $this->roundRappen($this->invoice->amount);
|
||||||
|
}
|
||||||
|
|
||||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function roundRappen($value): float
|
||||||
|
{
|
||||||
|
return round($value / .05, 0) * .05;
|
||||||
|
}
|
||||||
|
|
||||||
public function getSubTotal()
|
public function getSubTotal()
|
||||||
{
|
{
|
||||||
return $this->sub_total;
|
return $this->sub_total;
|
||||||
|
72
app/Http/Controllers/BrevoController.php
Normal file
72
app/Http/Controllers/BrevoController.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Jobs\Brevo\ProcessBrevoWebhook;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PostMarkController.
|
||||||
|
*/
|
||||||
|
class BrevoController extends BaseController
|
||||||
|
{
|
||||||
|
private $invitation;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process Postmark Webhook.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/v1/postmark_webhook",
|
||||||
|
* operationId="postmarkWebhook",
|
||||||
|
* tags={"postmark"},
|
||||||
|
* summary="Processing webhooks from PostMark",
|
||||||
|
* description="Adds an credit to the system",
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||||
|
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Returns the saved credit object",
|
||||||
|
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||||
|
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Credit"),
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=422,
|
||||||
|
* description="Validation error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||||
|
*
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response="default",
|
||||||
|
* description="Unexpected Error",
|
||||||
|
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function webhook(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->has('token') && $request->get('token') == config('services.brevo.key')) {
|
||||||
|
ProcessBrevoWebhook::dispatch($request->all())->delay(10);
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Success'], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Unauthorized'], 403);
|
||||||
|
}
|
||||||
|
}
|
@ -11,26 +11,29 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use App\Models\CompanyGateway;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
use App\DataMapper\FeesAndLimits;
|
use App\DataMapper\FeesAndLimits;
|
||||||
|
use App\Jobs\Util\ApplePayDomain;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
use App\Factory\CompanyGatewayFactory;
|
use App\Factory\CompanyGatewayFactory;
|
||||||
use App\Filters\CompanyGatewayFilters;
|
use App\Filters\CompanyGatewayFilters;
|
||||||
|
use App\Repositories\CompanyRepository;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use App\Transformers\CompanyGatewayTransformer;
|
||||||
|
use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
|
||||||
|
use App\PaymentDrivers\CheckoutCom\CheckoutSetupWebhook;
|
||||||
use App\Http\Requests\CompanyGateway\BulkCompanyGatewayRequest;
|
use App\Http\Requests\CompanyGateway\BulkCompanyGatewayRequest;
|
||||||
use App\Http\Requests\CompanyGateway\CreateCompanyGatewayRequest;
|
|
||||||
use App\Http\Requests\CompanyGateway\DestroyCompanyGatewayRequest;
|
|
||||||
use App\Http\Requests\CompanyGateway\EditCompanyGatewayRequest;
|
use App\Http\Requests\CompanyGateway\EditCompanyGatewayRequest;
|
||||||
use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest;
|
use App\Http\Requests\CompanyGateway\ShowCompanyGatewayRequest;
|
||||||
|
use App\Http\Requests\CompanyGateway\TestCompanyGatewayRequest;
|
||||||
use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest;
|
use App\Http\Requests\CompanyGateway\StoreCompanyGatewayRequest;
|
||||||
|
use App\Http\Requests\CompanyGateway\CreateCompanyGatewayRequest;
|
||||||
use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
|
use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
|
||||||
use App\Jobs\Util\ApplePayDomain;
|
use App\Http\Requests\CompanyGateway\DestroyCompanyGatewayRequest;
|
||||||
use App\Models\Client;
|
|
||||||
use App\Models\CompanyGateway;
|
|
||||||
use App\PaymentDrivers\CheckoutCom\CheckoutSetupWebhook;
|
|
||||||
use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
|
|
||||||
use App\Repositories\CompanyRepository;
|
|
||||||
use App\Transformers\CompanyGatewayTransformer;
|
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
|
||||||
use Illuminate\Http\Response;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CompanyGatewayController.
|
* Class CompanyGatewayController.
|
||||||
@ -52,6 +55,9 @@ class CompanyGatewayController extends BaseController
|
|||||||
|
|
||||||
private string $checkout_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
|
private string $checkout_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
|
||||||
|
|
||||||
|
private string $forte_key = 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompanyGatewayController constructor.
|
* CompanyGatewayController constructor.
|
||||||
* @param CompanyRepository $company_repo
|
* @param CompanyRepository $company_repo
|
||||||
@ -225,6 +231,13 @@ class CompanyGatewayController extends BaseController
|
|||||||
StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
|
StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
|
||||||
} elseif($company_gateway->gateway_key == $this->checkout_key) {
|
} elseif($company_gateway->gateway_key == $this->checkout_key) {
|
||||||
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
|
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
|
||||||
|
} elseif($company_gateway->gateway_key == $this->forte_key) {
|
||||||
|
|
||||||
|
dispatch(function () use ($company_gateway) {
|
||||||
|
MultiDB::setDb($company_gateway->company->db);
|
||||||
|
$company_gateway->driver()->updateFees();
|
||||||
|
})->afterResponse();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->itemResponse($company_gateway);
|
return $this->itemResponse($company_gateway);
|
||||||
@ -407,6 +420,13 @@ class CompanyGatewayController extends BaseController
|
|||||||
|
|
||||||
if($company_gateway->gateway_key == $this->checkout_key) {
|
if($company_gateway->gateway_key == $this->checkout_key) {
|
||||||
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id);
|
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id);
|
||||||
|
}elseif($company_gateway->gateway_key == $this->forte_key){
|
||||||
|
|
||||||
|
dispatch(function () use ($company_gateway) {
|
||||||
|
MultiDB::setDb($company_gateway->company->db);
|
||||||
|
$company_gateway->driver()->updateFees();
|
||||||
|
})->afterResponse();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->itemResponse($company_gateway);
|
return $this->itemResponse($company_gateway);
|
||||||
@ -535,4 +555,28 @@ class CompanyGatewayController extends BaseController
|
|||||||
|
|
||||||
return $this->listResponse(CompanyGateway::withTrashed()->company()->whereIn('id', $request->ids));
|
return $this->listResponse(CompanyGateway::withTrashed()->company()->whereIn('id', $request->ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test(TestCompanyGatewayRequest $request, CompanyGateway $company_gateway)
|
||||||
|
{
|
||||||
|
|
||||||
|
return response()->json(['message' => $company_gateway->driver()->auth() ? 'true' : 'false'], 200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers(TestCompanyGatewayRequest $request, CompanyGateway $company_gateway)
|
||||||
|
{
|
||||||
|
//Throttle here
|
||||||
|
// if (Cache::get("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}"))
|
||||||
|
// return response()->json(['message' => ctrans('texts.import_started')], 200);
|
||||||
|
|
||||||
|
dispatch(function () use($company_gateway) {
|
||||||
|
MultiDB::setDb($company_gateway->company->db);
|
||||||
|
$company_gateway->driver()->importCustomers();
|
||||||
|
})->afterResponse();
|
||||||
|
|
||||||
|
Cache::put("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}", true, 300);
|
||||||
|
|
||||||
|
return response()->json(['message' => ctrans('texts.import_started')], 200);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,11 @@ class LogoutController extends BaseController
|
|||||||
$ct->company
|
$ct->company
|
||||||
->tokens()
|
->tokens()
|
||||||
->where('is_system', true)
|
->where('is_system', true)
|
||||||
->forceDelete();
|
->cursor()
|
||||||
|
->each(function ($ct){
|
||||||
|
$ct->token = \Illuminate\Support\Str::random(64);
|
||||||
|
$ct->save();
|
||||||
|
});
|
||||||
|
|
||||||
return response()->json(['message' => 'All tokens deleted'], 200);
|
return response()->json(['message' => 'All tokens deleted'], 200);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,17 @@ class SmtpController extends BaseController
|
|||||||
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
|
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mail::mailer('smtp')->to($user->email, $user->present()->name())->send(new TestMailServer('Email Server Works!', strlen($company->settings->custom_sending_email) > 1 ? $company->settings->custom_sending_email : $user->email));
|
|
||||||
|
$sending_email = (isset($company->settings->custom_sending_email) && stripos($company->settings->custom_sending_email, "@")) ? $company->settings->custom_sending_email : $user->email;
|
||||||
|
$sending_user = (isset($company->settings->email_from_name) && strlen($company->settings->email_from_name) > 2) ? $company->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
|
$mailable = new TestMailServer('Email Server Works!', $sending_email);
|
||||||
|
$mailable->from($sending_email,$sending_user);
|
||||||
|
|
||||||
|
Mail::mailer('smtp')
|
||||||
|
->to($user->email, $user->present()->name())
|
||||||
|
->send($mailable);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
app('mail.manager')->forgetMailers();
|
app('mail.manager')->forgetMailers();
|
||||||
return response()->json(['message' => $e->getMessage()], 400);
|
return response()->json(['message' => $e->getMessage()], 400);
|
||||||
|
@ -33,15 +33,15 @@ class UploadBankIntegrationRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -33,15 +33,15 @@ class UploadBankTransactionRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -45,18 +45,18 @@ class StoreClientRequest extends Request
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure we have a client name, and that all emails are unique*/
|
/* Ensure we have a client name, and that all emails are unique*/
|
||||||
|
@ -44,15 +44,15 @@ class UpdateClientRequest extends Request
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
} else {
|
} else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,15 @@ class UploadClientRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -30,15 +30,15 @@ class UploadCompanyRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Requests\CompanyGateway;
|
||||||
|
|
||||||
|
use App\Http\Requests\Request;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class TestCompanyGatewayRequest extends Request
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
return $user->isAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForValidation()
|
||||||
|
{
|
||||||
|
$input = $this->all();
|
||||||
|
|
||||||
|
$this->replace($input);
|
||||||
|
}
|
||||||
|
}
|
@ -47,17 +47,17 @@ class StoreCreditRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User $user */
|
||||||
|
@ -49,17 +49,17 @@ class UpdateCreditRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)];
|
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)];
|
||||||
|
@ -33,15 +33,15 @@ class UploadCreditRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -33,15 +33,15 @@ class UploadExpenseRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -30,15 +30,15 @@ class UploadGroupSettingRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -44,17 +44,17 @@ class StoreInvoiceRequest extends Request
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0';
|
$rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||||
|
@ -46,17 +46,17 @@ class UpdateInvoiceRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// $rules['id'] = new LockedInvoiceRule($this->invoice);
|
// $rules['id'] = new LockedInvoiceRule($this->invoice);
|
||||||
|
@ -33,15 +33,15 @@ class UploadInvoiceRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -123,17 +123,17 @@ class StorePaymentRequest extends Request
|
|||||||
];
|
];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -52,17 +52,17 @@ class UpdatePaymentRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -33,15 +33,15 @@ class UploadPaymentRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -32,17 +32,17 @@ class StoreProductRequest extends Request
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['cost'] = 'sometimes|numeric';
|
$rules['cost'] = 'sometimes|numeric';
|
||||||
|
@ -35,17 +35,17 @@ class UpdateProductRequest extends Request
|
|||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['cost'] = 'numeric';
|
$rules['cost'] = 'numeric';
|
||||||
|
@ -32,15 +32,15 @@ class UploadProductRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [];
|
$rules = [];
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -51,17 +51,17 @@ class StoreProjectRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -48,17 +48,17 @@ class UpdateProjectRequest extends Request
|
|||||||
$rules['budgeted_hours'] = 'sometimes|numeric';
|
$rules['budgeted_hours'] = 'sometimes|numeric';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -33,15 +33,15 @@ class UploadProjectRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -54,17 +54,17 @@ class StorePurchaseOrderRequest extends Request
|
|||||||
$rules['line_items'] = 'array';
|
$rules['line_items'] = 'array';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
} else {
|
} else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['status_id'] = 'nullable|integer|in:1,2,3,4,5';
|
$rules['status_id'] = 'nullable|integer|in:1,2,3,4,5';
|
||||||
|
@ -56,17 +56,17 @@ class UpdatePurchaseOrderRequest extends Request
|
|||||||
$rules['is_amount_discount'] = ['boolean'];
|
$rules['is_amount_discount'] = ['boolean'];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['status_id'] = 'sometimes|integer|in:1,2,3,4,5';
|
$rules['status_id'] = 'sometimes|integer|in:1,2,3,4,5';
|
||||||
|
@ -33,15 +33,15 @@ class UploadPurchaseOrderRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -46,17 +46,17 @@ class StoreQuoteRequest extends Request
|
|||||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['number'] = ['nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
|
$rules['number'] = ['nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
|
||||||
|
@ -43,17 +43,17 @@ class UpdateQuoteRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,15 +33,15 @@ class UploadQuoteRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -57,15 +57,15 @@ class StoreRecurringExpenseRequest extends Request
|
|||||||
$rules['currency_id'] = 'bail|required|integer|exists:currencies,id';
|
$rules['currency_id'] = 'bail|required|integer|exists:currencies,id';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -49,15 +49,15 @@ class UpdateRecurringExpenseRequest extends Request
|
|||||||
$rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
$rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -30,15 +30,15 @@ class UploadRecurringExpenseRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -46,17 +46,17 @@ class StoreRecurringInvoiceRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||||
|
@ -45,17 +45,17 @@ class UpdateRecurringInvoiceRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['number'] = ['bail', 'sometimes', Rule::unique('recurring_invoices')->where('company_id', $user->company()->id)->ignore($this->recurring_invoice->id)];
|
$rules['number'] = ['bail', 'sometimes', Rule::unique('recurring_invoices')->where('company_id', $user->company()->id)->ignore($this->recurring_invoice->id)];
|
||||||
|
@ -33,15 +33,15 @@ class UploadRecurringInvoiceRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -46,15 +46,15 @@ class StoreRecurringQuoteRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||||
|
@ -38,15 +38,15 @@ class UpdateRecurringQuoteRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->number) {
|
if ($this->number) {
|
||||||
|
@ -30,15 +30,15 @@ class UploadRecurringQuoteRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
@ -20,7 +20,7 @@ class Request extends FormRequest
|
|||||||
use MakesHash;
|
use MakesHash;
|
||||||
use RuntimeFormRequest;
|
use RuntimeFormRequest;
|
||||||
|
|
||||||
protected $file_validation = 'sometimes|file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp,xml,zip,csv,ods,odt,odp|max:100000';
|
protected $file_validation = 'sometimes|file|max:100000|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp,xml,zip,csv,ods,odt,odp';
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
@ -31,6 +31,15 @@ class Request extends FormRequest
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function fileValidation()
|
||||||
|
{
|
||||||
|
if(config('ninja.upload_extensions'))
|
||||||
|
return $this->file_validation. ",".config('ninja.upload_extensions');
|
||||||
|
|
||||||
|
return $this->file_validation;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function globalRules($rules)
|
public function globalRules($rules)
|
||||||
{
|
{
|
||||||
$merge_rules = [];
|
$merge_rules = [];
|
||||||
|
@ -79,17 +79,17 @@ class StoreTaskRequest extends Request
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,17 +85,17 @@ class UpdateTaskRequest extends Request
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
|
@ -33,15 +33,15 @@ class UploadTaskRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -61,17 +61,17 @@ class StoreVendorRequest extends Request
|
|||||||
$rules['currency_id'] = 'bail|required|exists:currencies,id';
|
$rules['currency_id'] = 'bail|required|exists:currencies,id';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
||||||
|
@ -62,17 +62,17 @@ class UpdateVendorRequest extends Request
|
|||||||
$rules['currency_id'] = 'bail|sometimes|exists:currencies,id';
|
$rules['currency_id'] = 'bail|sometimes|exists:currencies,id';
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}else {
|
}else {
|
||||||
$rules['documents'] = 'bail|sometimes|array';
|
$rules['documents'] = 'bail|sometimes|array';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
||||||
|
@ -30,15 +30,15 @@ class UploadVendorRequest extends Request
|
|||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||||
$rules['documents.*'] = $this->file_validation;
|
$rules['documents.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('documents')) {
|
} elseif ($this->file('documents')) {
|
||||||
$rules['documents'] = $this->file_validation;
|
$rules['documents'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->file('file') && is_array($this->file('file'))) {
|
if ($this->file('file') && is_array($this->file('file'))) {
|
||||||
$rules['file.*'] = $this->file_validation;
|
$rules['file.*'] = $this->fileValidation();
|
||||||
} elseif ($this->file('file')) {
|
} elseif ($this->file('file')) {
|
||||||
$rules['file'] = $this->file_validation;
|
$rules['file'] = $this->fileValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules['is_public'] = 'sometimes|boolean';
|
$rules['is_public'] = 'sometimes|boolean';
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
*
|
*1`
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ class BlackListRule implements ValidationRule
|
|||||||
{
|
{
|
||||||
/** Bad domains +/- dispoable email domains */
|
/** Bad domains +/- dispoable email domains */
|
||||||
private array $blacklist = [
|
private array $blacklist = [
|
||||||
|
'wireconnected.com',
|
||||||
'secure-coinspot.com',
|
'secure-coinspot.com',
|
||||||
'casasotombo.com',
|
'casasotombo.com',
|
||||||
'otpku.com',
|
'otpku.com',
|
||||||
|
@ -85,6 +85,8 @@ class ProcessBankTransactionsNordigen implements ShouldQueue
|
|||||||
|
|
||||||
$this->bank_integration->company->notification(new GenericNinjaAdminNotification($content))->ninja();
|
$this->bank_integration->company->notification(new GenericNinjaAdminNotification($content))->ninja();
|
||||||
|
|
||||||
|
sleep(5);
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
if (!$this->nordigen_account) {
|
if (!$this->nordigen_account) {
|
||||||
|
492
app/Jobs/Brevo/ProcessBrevoWebhook.php
Normal file
492
app/Jobs/Brevo/ProcessBrevoWebhook.php
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs\Brevo;
|
||||||
|
|
||||||
|
use App\DataMapper\Analytics\Mail\EmailBounce;
|
||||||
|
use App\DataMapper\Analytics\Mail\EmailSpam;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\CreditInvitation;
|
||||||
|
use App\Models\InvoiceInvitation;
|
||||||
|
use App\Models\PurchaseOrderInvitation;
|
||||||
|
use App\Models\QuoteInvitation;
|
||||||
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Notifications\Ninja\EmailBounceNotification;
|
||||||
|
use App\Notifications\Ninja\EmailSpamNotification;
|
||||||
|
use Brevo\Client\Configuration;
|
||||||
|
use Brevo\Client\Model\GetTransacEmailContentEvents;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Brevo\Client\Api\TransactionalEmailsApi;
|
||||||
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
|
|
||||||
|
class ProcessBrevoWebhook implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $tries = 1;
|
||||||
|
|
||||||
|
public $invitation;
|
||||||
|
|
||||||
|
private $entity;
|
||||||
|
|
||||||
|
private array $default_response = [
|
||||||
|
'recipients' => '',
|
||||||
|
'subject' => 'Message not found.',
|
||||||
|
'entity' => '',
|
||||||
|
'entity_id' => '',
|
||||||
|
'events' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
private ?Company $company = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct(private array $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSystemLog(string $message_id): ?SystemLog
|
||||||
|
{
|
||||||
|
return SystemLog::query()
|
||||||
|
->where('company_id', $this->invitation->company_id)
|
||||||
|
->where('type_id', SystemLog::TYPE_WEBHOOK_RESPONSE)
|
||||||
|
->whereJsonContains('log', ['message-id' => $message_id])
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateSystemLog(SystemLog $system_log, array $data): void
|
||||||
|
{
|
||||||
|
$system_log->log = $data;
|
||||||
|
$system_log->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($this->request['tags'][0]);
|
||||||
|
$this->company = Company::where('company_key', $this->request['tags'][0])->first();
|
||||||
|
|
||||||
|
$this->invitation = $this->discoverInvitation($this->request['message-id']);
|
||||||
|
|
||||||
|
if ($this->company && $this->request['event'] == 'spam' && config('ninja.notification.slack')) {
|
||||||
|
$this->company->notification(new EmailSpamNotification($this->company))->ninja();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->invitation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('reason', $this->request)) {
|
||||||
|
$this->invitation->email_error = $this->request['reason'];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->request['event']) {
|
||||||
|
case 'delivered':
|
||||||
|
return $this->processDelivery();
|
||||||
|
case 'soft_bounce':
|
||||||
|
case 'hard_bounce':
|
||||||
|
case 'invalid_email':
|
||||||
|
case 'blocked':
|
||||||
|
|
||||||
|
if ($this->request['subject'] == ctrans('texts.confirmation_subject')) {
|
||||||
|
$this->company->notification(new EmailBounceNotification($this->request['email']))->ninja();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->processBounce();
|
||||||
|
case 'spam':
|
||||||
|
return $this->processSpamComplaint();
|
||||||
|
case 'unique_opened':
|
||||||
|
case 'opened':
|
||||||
|
case 'click':
|
||||||
|
return $this->processOpen();
|
||||||
|
default:
|
||||||
|
# code...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "test@example.com",
|
||||||
|
// "message-id": "<202312211546.94160606300@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:34:42",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "unique_opened",
|
||||||
|
// "subject": "Reminder: Invoice 0002 from Untitled Company",
|
||||||
|
// "sending_ip": "74.125.208.8",
|
||||||
|
// "ts": 1703180082,
|
||||||
|
// "ts_epoch": 1703180082286,
|
||||||
|
// "ts_event": 1703180082,
|
||||||
|
// "link": "",
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "test@example.com",
|
||||||
|
// "message-id": "<202312211555.14720890391@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:34:53",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "opened",
|
||||||
|
// "subject": "Reminder: Invoice 0002 from Untitled Company",
|
||||||
|
// "sending_ip": "74.125.208.8",
|
||||||
|
// "ts": 1703180093,
|
||||||
|
// "ts_epoch": 1703180093075,
|
||||||
|
// "ts_event": 1703180093,
|
||||||
|
// "link": "",
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "paul@wer-ner.de",
|
||||||
|
// "message-id": "<202312280812.10968711117@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-28 09:20:18",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "click",
|
||||||
|
// "subject": "Reminder: Invoice 0002 from Untitled Company",
|
||||||
|
// "sending_ip": "79.235.133.157",
|
||||||
|
// "ts": 1703751618,
|
||||||
|
// "ts_epoch": 1703751618831,
|
||||||
|
// "ts_event": 1703751618,
|
||||||
|
// "link": "http://localhost/client/invoice/CssCvqOcKsenMCgYJ7EUNRZwxSDGUkau",
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
|
||||||
|
private function processOpen()
|
||||||
|
{
|
||||||
|
$this->invitation->opened_date = now();
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['message-id']);
|
||||||
|
|
||||||
|
if ($sl) {
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
new SystemLogger(
|
||||||
|
$data,
|
||||||
|
SystemLog::CATEGORY_MAIL,
|
||||||
|
SystemLog::EVENT_MAIL_OPENED,
|
||||||
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
|
$this->invitation->contact->client,
|
||||||
|
$this->invitation->company
|
||||||
|
)
|
||||||
|
)->handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "test@example",
|
||||||
|
// "message-id": "<202312211742.12697514322@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:42:31",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "delivered",
|
||||||
|
// "subject": "Reminder: Invoice 0002 from Untitled Company",
|
||||||
|
// "sending_ip": "77.32.148.26",
|
||||||
|
// "ts_event": 1703180551,
|
||||||
|
// "ts": 1703180551,
|
||||||
|
// "reason": "sent",
|
||||||
|
// "ts_epoch": 1703180551324,
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
private function processDelivery()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'delivered';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['message-id']);
|
||||||
|
|
||||||
|
if ($sl) {
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
new SystemLogger(
|
||||||
|
$data,
|
||||||
|
SystemLog::CATEGORY_MAIL,
|
||||||
|
SystemLog::EVENT_MAIL_DELIVERY,
|
||||||
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
|
$this->invitation->contact->client,
|
||||||
|
$this->invitation->company
|
||||||
|
)
|
||||||
|
)->handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "ryder36@example.net",
|
||||||
|
// "message-id": "<202312211744.55168080257@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:44:52",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "soft_bounce",
|
||||||
|
// "subject": "Reminder: Invoice 0001 from Untitled Company",
|
||||||
|
// "sending_ip": "77.32.148.26",
|
||||||
|
// "ts_event": 1703180692,
|
||||||
|
// "ts": 1703180692,
|
||||||
|
// "reason": "Unable to find MX of domain example.net",
|
||||||
|
// "ts_epoch": 1703180692382,
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "gloria46@example.com",
|
||||||
|
// "message-id": "<202312211744.57456703957@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:44:54",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "hard_bounce",
|
||||||
|
// "subject": "Reminder: Invoice 0001 from Untitled Company",
|
||||||
|
// "sending_ip": "77.32.148.25",
|
||||||
|
// "ts_event": 1703180694,
|
||||||
|
// "ts": 1703180694,
|
||||||
|
// "reason": "blocked by Admin",
|
||||||
|
// "ts_epoch": 1703180694175,
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// "event" : "invalid_email",
|
||||||
|
// "email" : "example@example.com",
|
||||||
|
// "id" : 1,
|
||||||
|
// "date" : "yyyy-mm-dd hh:i:s",
|
||||||
|
// "message-id" : "<xxx@msgid.domain>",
|
||||||
|
// "subject" : "Test subject",
|
||||||
|
// "tag" : "<defined-tag>",//json of array
|
||||||
|
// "tags": [
|
||||||
|
// "company_key"
|
||||||
|
// ],
|
||||||
|
// "sending_ip" : "xxx.xx.xxx.xx",
|
||||||
|
// "ts_epoch" : 1534486682000,
|
||||||
|
// "template_id" : 1,
|
||||||
|
// "sender_email": "user@example.com",
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// "id": 948562,
|
||||||
|
// "email": "neoma.langosh@example.com",
|
||||||
|
// "message-id": "<202312211745.65538701430@smtp-relay.mailin.fr>",
|
||||||
|
// "date": "2023-12-21 18:45:48",
|
||||||
|
// "tags": [
|
||||||
|
// "gMtwiTIJtJxklXCj1OUFANgY6YYynQxV"
|
||||||
|
// ],
|
||||||
|
// "tag": "[\"gMtwiTIJtJxklXCj1OUFANgY6YYynQxV\"]",
|
||||||
|
// "event": "blocked",
|
||||||
|
// "subject": "Reminder: Invoice 0001 from Untitled Company",
|
||||||
|
// "ts_event": 1703180748,
|
||||||
|
// "ts": 1703180748,
|
||||||
|
// "reason": "blocked : due to blacklist user",
|
||||||
|
// "ts_epoch": 1703180748987,
|
||||||
|
// "sender_email": "user@example.com"
|
||||||
|
// }
|
||||||
|
|
||||||
|
private function processBounce()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'bounced';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$bounce = new EmailBounce(
|
||||||
|
$this->request['tags'][0],
|
||||||
|
$this->request['sender_email'], // TODO: @turbo124 is this the recipent?
|
||||||
|
$this->request['message-id']
|
||||||
|
);
|
||||||
|
|
||||||
|
LightLogs::create($bounce)->send();
|
||||||
|
|
||||||
|
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['message-id']);
|
||||||
|
|
||||||
|
if ($sl) {
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
|
||||||
|
|
||||||
|
// if(config('ninja.notification.slack'))
|
||||||
|
// $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja();
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "event" : "spam",
|
||||||
|
// "email" : "example@example.com",
|
||||||
|
// "id" : 1,
|
||||||
|
// "date" : "yyyy-mm-dd hh:i:s",
|
||||||
|
// "message-id" : "<xxx@msgid.domain>",
|
||||||
|
// "tag" : "<defined-tag>",//json of array
|
||||||
|
// "tags": [
|
||||||
|
// "company_key"
|
||||||
|
// ],
|
||||||
|
// "sending_ip" : "xxx.xx.xxx.xx",
|
||||||
|
// "sender_email": "user@example.com",
|
||||||
|
// }
|
||||||
|
private function processSpamComplaint()
|
||||||
|
{
|
||||||
|
$this->invitation->email_status = 'spam';
|
||||||
|
$this->invitation->save();
|
||||||
|
|
||||||
|
$spam = new EmailSpam(
|
||||||
|
$this->request['tags'][0],
|
||||||
|
$this->request['sender_email'],
|
||||||
|
$this->request['message-id']
|
||||||
|
);
|
||||||
|
|
||||||
|
LightLogs::create($spam)->send();
|
||||||
|
|
||||||
|
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
|
||||||
|
|
||||||
|
$sl = $this->getSystemLog($this->request['message-id']);
|
||||||
|
|
||||||
|
if ($sl) {
|
||||||
|
$this->updateSystemLog($sl, $data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
|
||||||
|
|
||||||
|
if (config('ninja.notification.slack')) {
|
||||||
|
$this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function discoverInvitation(string $message_id)
|
||||||
|
{
|
||||||
|
$invitation = false;
|
||||||
|
|
||||||
|
if ($invitation = InvoiceInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'invoice';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = QuoteInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'quote';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = RecurringInvoiceInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'recurring_invoice';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = CreditInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'credit';
|
||||||
|
return $invitation;
|
||||||
|
} elseif ($invitation = PurchaseOrderInvitation::where('message_id', $message_id)->first()) {
|
||||||
|
$this->entity = 'purchase_order';
|
||||||
|
return $invitation;
|
||||||
|
} else {
|
||||||
|
return $invitation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRawMessage(string $message_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
$brevo_secret = !empty($this->company->settings->brevo_secret) ? $this->company->settings->brevo_secret : config('services.brevo.key');
|
||||||
|
|
||||||
|
$brevo = new TransactionalEmailsApi(null, Configuration::getDefaultConfiguration()->setApiKey('api-key', $brevo_secret));
|
||||||
|
$messageDetail = $brevo->getTransacEmailContent($message_id);
|
||||||
|
return $messageDetail;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getBounceId(string $message_id): ?int
|
||||||
|
{
|
||||||
|
|
||||||
|
$messageDetail = $this->getRawMessage($message_id);
|
||||||
|
|
||||||
|
$event = collect($messageDetail->getEvents())->first(function ($event) {
|
||||||
|
|
||||||
|
return $event?->Details?->BounceID ?? false;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return $event?->Details?->BounceID ?? null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
private function fetchMessage(): array
|
||||||
|
{
|
||||||
|
if (strlen($this->request['message-id']) < 1) {
|
||||||
|
return $this->default_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$messageDetail = $this->getRawMessage($this->request['message-id']);
|
||||||
|
|
||||||
|
$recipient = array_key_exists("email", $this->request) ? $this->request["email"] : '';
|
||||||
|
$server_ip = array_key_exists("sending_ip", $this->request) ? $this->request["sending_ip"] : '';
|
||||||
|
$delivery_message = array_key_exists("reason", $this->request) ? $this->request["reason"] : '';
|
||||||
|
$subject = $messageDetail->getSubject() ?? '';
|
||||||
|
|
||||||
|
$events = collect($messageDetail->getEvents())->map(function (GetTransacEmailContentEvents $event) use ($recipient, $server_ip, $delivery_message) { // @turbo124 event does only contain name & time property, how to handle transformation?!
|
||||||
|
|
||||||
|
return [
|
||||||
|
'bounce_id' => '',
|
||||||
|
'recipient' => $recipient,
|
||||||
|
'status' => $event->name ?? '',
|
||||||
|
'delivery_message' => $delivery_message, // TODO: @turbo124 this results in all cases for the history in the string, which may be incorrect
|
||||||
|
'server' => '',
|
||||||
|
'server_ip' => $server_ip,
|
||||||
|
'date' => \Carbon\Carbon::parse($event->getTime())->format('Y-m-d H:i:s') ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'recipients' => $recipient,
|
||||||
|
'subject' => $subject,
|
||||||
|
'entity' => $this->entity ?? '',
|
||||||
|
'entity_id' => $this->invitation->{$this->entity}->hashed_id ?? '',
|
||||||
|
'events' => $events,
|
||||||
|
];
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
return $this->default_response;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
protected $client_mailgun_domain = false;
|
protected $client_mailgun_domain = false;
|
||||||
|
|
||||||
|
protected $client_brevo_secret = false;
|
||||||
|
|
||||||
public function __construct(public ?NinjaMailerObject $nmo, public bool $override = false)
|
public function __construct(public ?NinjaMailerObject $nmo, public bool $override = false)
|
||||||
{
|
{
|
||||||
@ -99,7 +100,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->nmo->mailable->replyTo($this->nmo->settings->reply_to_email, $reply_to_name);
|
$this->nmo->mailable->replyTo($this->nmo->settings->reply_to_email, $reply_to_name);
|
||||||
} elseif(isset($this->nmo->invitation->user)) {
|
} elseif (isset ($this->nmo->invitation->user)) {
|
||||||
$this->nmo->mailable->replyTo($this->nmo->invitation->user->email, $this->nmo->invitation->user->present()->name());
|
$this->nmo->mailable->replyTo($this->nmo->invitation->user->email, $this->nmo->invitation->user->present()->name());
|
||||||
} else {
|
} else {
|
||||||
$this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name());
|
$this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name());
|
||||||
@ -120,8 +121,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
//send email
|
//send email
|
||||||
try {
|
try {
|
||||||
nlog("Trying to send to {$this->nmo->to_user->email} ". now()->toDateTimeString());
|
nlog("Trying to send to {$this->nmo->to_user->email} " . now()->toDateTimeString());
|
||||||
nlog("Using mailer => ". $this->mailer);
|
nlog("Using mailer => " . $this->mailer);
|
||||||
|
|
||||||
$mailer = Mail::mailer($this->mailer);
|
$mailer = Mail::mailer($this->mailer);
|
||||||
|
|
||||||
@ -133,10 +134,14 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->nmo->settings->mailgun_endpoint);
|
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->nmo->settings->mailgun_endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->client_brevo_secret) {
|
||||||
|
$mailer->brevo_config($this->client_brevo_secret);
|
||||||
|
}
|
||||||
|
|
||||||
$mailable = $this->nmo->mailable;
|
$mailable = $this->nmo->mailable;
|
||||||
|
|
||||||
/** May need to re-build it here */
|
/** May need to re-build it here */
|
||||||
if(Ninja::isHosted() && method_exists($mailable, 'build')) {
|
if (Ninja::isHosted() && method_exists($mailable, 'build')) {
|
||||||
$mailable->build();
|
$mailable->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,13 +156,13 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
LightLogs::create(new EmailSuccess($this->nmo->company->company_key, $this->nmo->mailable->subject))
|
LightLogs::create(new EmailSuccess($this->nmo->company->company_key, $this->nmo->mailable->subject))
|
||||||
->send();
|
->send();
|
||||||
|
|
||||||
} catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
} catch (\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
||||||
return;
|
return;
|
||||||
} catch(\Symfony\Component\Mime\Exception\LogicException $e) {
|
} catch (\Symfony\Component\Mime\Exception\LogicException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
@ -224,7 +229,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
private function incrementEmailCounter(): void
|
private function incrementEmailCounter(): void
|
||||||
{
|
{
|
||||||
if(in_array($this->mailer, ['default','mailgun']))
|
if(in_array($this->mailer, ['default','mailgun','postmark']))
|
||||||
Cache::increment("email_quota".$this->company->account->key);
|
Cache::increment("email_quota".$this->company->account->key);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -273,7 +278,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
// return $this;
|
// return $this;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if(Ninja::isHosted() && $this->company->account->isPaid() && $this->nmo->settings->email_sending_method == 'default') {
|
if (Ninja::isHosted() && $this->company->account->isPaid() && $this->nmo->settings->email_sending_method == 'default') {
|
||||||
//check if outlook.
|
//check if outlook.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -281,7 +286,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
$domain = explode("@", $email)[1] ?? "";
|
$domain = explode("@", $email)[1] ?? "";
|
||||||
$dns = dns_get_record($domain, DNS_MX);
|
$dns = dns_get_record($domain, DNS_MX);
|
||||||
$server = $dns[0]["target"];
|
$server = $dns[0]["target"];
|
||||||
if(stripos($server, "outlook.com") !== false) {
|
if (stripos($server, "outlook.com") !== false) {
|
||||||
|
|
||||||
$this->mailer = 'postmark';
|
$this->mailer = 'postmark';
|
||||||
$this->client_postmark_secret = config('services.postmark-outlook.token');
|
$this->client_postmark_secret = config('services.postmark-outlook.token');
|
||||||
@ -298,7 +303,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
nlog("problem switching outlook driver - hosted");
|
nlog("problem switching outlook driver - hosted");
|
||||||
nlog($e->getMessage());
|
nlog($e->getMessage());
|
||||||
@ -331,6 +336,10 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
$this->mailer = 'mailgun';
|
$this->mailer = 'mailgun';
|
||||||
$this->setMailgunMailer();
|
$this->setMailgunMailer();
|
||||||
return $this;
|
return $this;
|
||||||
|
case 'client_brevo':
|
||||||
|
$this->mailer = 'brevo';
|
||||||
|
$this->setBrevoMailer();
|
||||||
|
return $this;
|
||||||
case 'smtp':
|
case 'smtp':
|
||||||
$this->mailer = 'smtp';
|
$this->mailer = 'smtp';
|
||||||
$this->configureSmtpMailer();
|
$this->configureSmtpMailer();
|
||||||
@ -380,7 +389,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
||||||
|
|
||||||
$this->nmo
|
$this->nmo
|
||||||
->mailable
|
->mailable
|
||||||
@ -426,6 +435,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
$this->client_mailgun_domain = false;
|
$this->client_mailgun_domain = false;
|
||||||
|
|
||||||
|
$this->client_brevo_secret = false;
|
||||||
|
|
||||||
//always dump the drivers to prevent reuse
|
//always dump the drivers to prevent reuse
|
||||||
app('mail.manager')->forgetMailers();
|
app('mail.manager')->forgetMailers();
|
||||||
}
|
}
|
||||||
@ -496,8 +507,31 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
||||||
$sending_user = (isset($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
|
$sending_user = (isset ($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
|
$this->nmo
|
||||||
|
->mailable
|
||||||
|
->from($sending_email, $sending_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Brevo using client supplied secret
|
||||||
|
* as the Mailer
|
||||||
|
*/
|
||||||
|
private function setBrevoMailer()
|
||||||
|
{
|
||||||
|
if (strlen($this->nmo->settings->brevo_secret) > 2) {
|
||||||
|
$this->client_brevo_secret = $this->nmo->settings->brevo_secret;
|
||||||
|
} else {
|
||||||
|
$this->nmo->settings->email_sending_method = 'default';
|
||||||
|
return $this->setMailDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
|
$sending_email = (isset ($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
||||||
|
$sending_user = (isset ($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
$this->nmo
|
$this->nmo
|
||||||
->mailable
|
->mailable
|
||||||
@ -519,8 +553,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
|
||||||
$sending_user = (isset($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
|
$sending_user = (isset ($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
$this->nmo
|
$this->nmo
|
||||||
->mailable
|
->mailable
|
||||||
@ -578,7 +612,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
||||||
$this->nmo->settings->email_sending_method = 'default';
|
$this->nmo->settings->email_sending_method = 'default';
|
||||||
return $this->setMailDriver();
|
return $this->setMailDriver();
|
||||||
@ -626,7 +660,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
private function preFlightChecksFail(): bool
|
private function preFlightChecksFail(): bool
|
||||||
{
|
{
|
||||||
/* Always send regardless */
|
/* Always send regardless */
|
||||||
if($this->override) {
|
if ($this->override) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,7 +680,7 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* GMail users are uncapped */
|
/* GMail users are uncapped */
|
||||||
if (Ninja::isHosted() && (in_array($this->nmo->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun']))) {
|
if (Ninja::isHosted() && (in_array($this->nmo->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun', 'client_brevo']))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,14 +724,16 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
private function logMailError($errors, $recipient_object): void
|
private function logMailError($errors, $recipient_object): void
|
||||||
{
|
{
|
||||||
(new SystemLogger(
|
(
|
||||||
|
new SystemLogger(
|
||||||
$errors,
|
$errors,
|
||||||
SystemLog::CATEGORY_MAIL,
|
SystemLog::CATEGORY_MAIL,
|
||||||
SystemLog::EVENT_MAIL_SEND,
|
SystemLog::EVENT_MAIL_SEND,
|
||||||
SystemLog::TYPE_FAILURE,
|
SystemLog::TYPE_FAILURE,
|
||||||
$recipient_object,
|
$recipient_object,
|
||||||
$this->nmo->company
|
$this->nmo->company
|
||||||
))->handle();
|
)
|
||||||
|
)->handle();
|
||||||
|
|
||||||
$job_failure = new EmailFailure($this->nmo->company->company_key);
|
$job_failure = new EmailFailure($this->nmo->company->company_key);
|
||||||
$job_failure->string_metric5 = 'failed_email';
|
$job_failure->string_metric5 = 'failed_email';
|
||||||
@ -729,8 +765,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
|
|
||||||
$token = json_decode($guzzle->post($url, [
|
$token = json_decode($guzzle->post($url, [
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'client_id' => config('ninja.o365.client_id') ,
|
'client_id' => config('ninja.o365.client_id'),
|
||||||
'client_secret' => config('ninja.o365.client_secret') ,
|
'client_secret' => config('ninja.o365.client_secret'),
|
||||||
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
||||||
'grant_type' => 'refresh_token',
|
'grant_type' => 'refresh_token',
|
||||||
'refresh_token' => $user->oauth_user_refresh_token
|
'refresh_token' => $user->oauth_user_refresh_token
|
||||||
|
@ -74,7 +74,7 @@ class BankTransactionSync implements ShouldQueue
|
|||||||
|
|
||||||
if ($account->isEnterprisePaidClient()) {
|
if ($account->isEnterprisePaidClient()) {
|
||||||
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->where('disabled_upstream', 0)->cursor()->each(function ($bank_integration) use ($account) {
|
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->where('disabled_upstream', 0)->cursor()->each(function ($bank_integration) use ($account) {
|
||||||
(new ProcessBankTransactionsYodlee($account->id, $bank_integration))->handle();
|
(new ProcessBankTransactionsYodlee($account->bank_integration_account_id, $bank_integration))->handle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,14 @@ class BankTransactionSync implements ShouldQueue
|
|||||||
|
|
||||||
if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isEnterprisePaidClient()))) {
|
if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isEnterprisePaidClient()))) {
|
||||||
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->where('disabled_upstream', 0)->cursor()->each(function ($bank_integration) {
|
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->where('disabled_upstream', 0)->cursor()->each(function ($bank_integration) {
|
||||||
|
try {
|
||||||
(new ProcessBankTransactionsNordigen($bank_integration))->handle();
|
(new ProcessBankTransactionsNordigen($bank_integration))->handle();
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
sleep(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(5);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
'events' => [],
|
'events' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private ?Company $company = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
@ -87,12 +89,12 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
MultiDB::findAndSetDbByCompanyKey($this->request['Tag']);
|
MultiDB::findAndSetDbByCompanyKey($this->request['Tag']);
|
||||||
$company = Company::where('company_key', $this->request['Tag'])->first();
|
$this->company = Company::where('company_key', $this->request['Tag'])->first();
|
||||||
|
|
||||||
$this->invitation = $this->discoverInvitation($this->request['MessageID']);
|
$this->invitation = $this->discoverInvitation($this->request['MessageID']);
|
||||||
|
|
||||||
if ($company && $this->request['RecordType'] == 'SpamComplaint' && config('ninja.notification.slack')) {
|
if ($this->company && $this->request['RecordType'] == 'SpamComplaint' && config('ninja.notification.slack')) {
|
||||||
$company->notification(new EmailSpamNotification($company))->ninja();
|
$this->company->notification(new EmailSpamNotification($this->company))->ninja();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->invitation) {
|
if (!$this->invitation) {
|
||||||
@ -108,8 +110,8 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
return $this->processDelivery();
|
return $this->processDelivery();
|
||||||
case 'Bounce':
|
case 'Bounce':
|
||||||
|
|
||||||
if($this->request['Subject'] == ctrans('texts.confirmation_subject')) {
|
if ($this->request['Subject'] == ctrans('texts.confirmation_subject')) {
|
||||||
$company->notification(new EmailBounceNotification($this->request['Email']))->ninja();
|
$this->company->notification(new EmailBounceNotification($this->request['Email']))->ninja();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->processBounce();
|
return $this->processBounce();
|
||||||
@ -169,19 +171,21 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$sl = $this->getSystemLog($this->request['MessageID']);
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
if($sl) {
|
if ($sl) {
|
||||||
$this->updateSystemLog($sl, $data);
|
$this->updateSystemLog($sl, $data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(new SystemLogger(
|
(
|
||||||
|
new SystemLogger(
|
||||||
$data,
|
$data,
|
||||||
SystemLog::CATEGORY_MAIL,
|
SystemLog::CATEGORY_MAIL,
|
||||||
SystemLog::EVENT_MAIL_OPENED,
|
SystemLog::EVENT_MAIL_OPENED,
|
||||||
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
$this->invitation->contact->client,
|
$this->invitation->contact->client,
|
||||||
$this->invitation->company
|
$this->invitation->company
|
||||||
))->handle();
|
)
|
||||||
|
)->handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
// {
|
||||||
@ -207,19 +211,21 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$sl = $this->getSystemLog($this->request['MessageID']);
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
if($sl) {
|
if ($sl) {
|
||||||
$this->updateSystemLog($sl, $data);
|
$this->updateSystemLog($sl, $data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(new SystemLogger(
|
(
|
||||||
|
new SystemLogger(
|
||||||
$data,
|
$data,
|
||||||
SystemLog::CATEGORY_MAIL,
|
SystemLog::CATEGORY_MAIL,
|
||||||
SystemLog::EVENT_MAIL_DELIVERY,
|
SystemLog::EVENT_MAIL_DELIVERY,
|
||||||
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
$this->invitation->contact->client,
|
$this->invitation->contact->client,
|
||||||
$this->invitation->company
|
$this->invitation->company
|
||||||
))->handle();
|
)
|
||||||
|
)->handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
// {
|
||||||
@ -265,7 +271,7 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$sl = $this->getSystemLog($this->request['MessageID']);
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
if($sl) {
|
if ($sl) {
|
||||||
$this->updateSystemLog($sl, $data);
|
$this->updateSystemLog($sl, $data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -316,7 +322,7 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
$sl = $this->getSystemLog($this->request['MessageID']);
|
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||||
|
|
||||||
if($sl) {
|
if ($sl) {
|
||||||
$this->updateSystemLog($sl, $data);
|
$this->updateSystemLog($sl, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +355,9 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
public function getRawMessage(string $message_id)
|
public function getRawMessage(string $message_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
$postmark = new PostmarkClient(config('services.postmark.token'));
|
$postmark_secret = !empty($this->company->settings->postmark_secret) ? $this->company->settings->postmark_secret : config('services.postmark.token');
|
||||||
|
|
||||||
|
$postmark = new PostmarkClient($postmark_secret);
|
||||||
$messageDetail = $postmark->getOutboundMessageDetails($message_id);
|
$messageDetail = $postmark->getOutboundMessageDetails($message_id);
|
||||||
return $messageDetail;
|
return $messageDetail;
|
||||||
|
|
||||||
@ -374,13 +382,15 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
|||||||
|
|
||||||
private function fetchMessage(): array
|
private function fetchMessage(): array
|
||||||
{
|
{
|
||||||
if(strlen($this->request['MessageID']) < 1) {
|
if (strlen($this->request['MessageID']) < 1) {
|
||||||
return $this->default_response;
|
return $this->default_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$postmark = new PostmarkClient(config('services.postmark.token'));
|
$postmark_secret = !empty($this->company->settings->postmark_secret) ? $this->company->settings->postmark_secret : config('services.postmark.token');
|
||||||
|
|
||||||
|
$postmark = new PostmarkClient($postmark_secret);
|
||||||
$messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']);
|
$messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']);
|
||||||
|
|
||||||
$recipients = collect($messageDetail['recipients'])->flatten()->implode(',');
|
$recipients = collect($messageDetail['recipients'])->flatten()->implode(',');
|
||||||
|
@ -76,12 +76,12 @@ class SendRecurring implements ShouldQueue
|
|||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->markSent()
|
->markSent()
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->fillDefaults()
|
->fillDefaults(true)
|
||||||
->adjustInventory()
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
} else {
|
} else {
|
||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->fillDefaults()
|
->fillDefaults(true)
|
||||||
->save();
|
->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ use Illuminate\Support\Str;
|
|||||||
use App\Models\CompanyToken;
|
use App\Models\CompanyToken;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\VendorContact;
|
use App\Models\VendorContact;
|
||||||
|
use App\DataProviders\SMSNumbers;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -586,6 +587,10 @@ class MultiDB
|
|||||||
|
|
||||||
$current_db = config('database.default');
|
$current_db = config('database.default');
|
||||||
|
|
||||||
|
if(SMSNumbers::hasNumber($phone)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (self::$dbs as $db) {
|
foreach (self::$dbs as $db) {
|
||||||
self::setDB($db);
|
self::setDB($db);
|
||||||
if ($exists = Account::where('account_sms_verification_number', $phone)->where('account_sms_verified', true)->exists()) {
|
if ($exists = Account::where('account_sms_verification_number', $phone)->where('account_sms_verified', true)->exists()) {
|
||||||
|
@ -222,8 +222,9 @@ class RequiredClientInfo extends Component
|
|||||||
$this->show_form = true;
|
$this->show_form = true;
|
||||||
|
|
||||||
$hash = Cache::get(request()->input('hash'));
|
$hash = Cache::get(request()->input('hash'));
|
||||||
|
$invoice = Invoice::find($this->decodePrimaryKey($hash['invoice_id']));
|
||||||
|
|
||||||
$this->invoice_terms = Invoice::find($this->decodePrimaryKey($hash['invoice_id']))->terms;
|
$this->invoice_terms = $invoice->terms;
|
||||||
}
|
}
|
||||||
|
|
||||||
count($this->fields) > 0 || $this->show_terms
|
count($this->fields) > 0 || $this->show_terms
|
||||||
|
@ -102,7 +102,7 @@ class Account extends BaseModel
|
|||||||
|
|
||||||
private $free_plan_email_quota = 20;
|
private $free_plan_email_quota = 20;
|
||||||
|
|
||||||
private $paid_plan_email_quota = 400;
|
private $paid_plan_email_quota = 300;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
@ -494,7 +494,7 @@ class Account extends BaseModel
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Carbon::createFromTimestamp($this->created_at)->diffInWeeks() == 0) {
|
if (Carbon::createFromTimestamp($this->created_at)->diffInWeeks() <= 1) {
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,11 +503,13 @@ class Account extends BaseModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isPaid()) {
|
if ($this->isPaid()) {
|
||||||
|
$multiplier = $this->plan == 'enterprise' ? 2 : 1.2;
|
||||||
|
|
||||||
$limit = $this->paid_plan_email_quota;
|
$limit = $this->paid_plan_email_quota;
|
||||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 50;
|
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * (20 * $multiplier);
|
||||||
} else {
|
} else {
|
||||||
$limit = $this->free_plan_email_quota;
|
$limit = $this->free_plan_email_quota;
|
||||||
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 2;
|
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return min($limit, 1000);
|
return min($limit, 1000);
|
||||||
|
@ -485,7 +485,7 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*Company Settings*/
|
/*Company Settings*/
|
||||||
elseif ((property_exists($this->company->settings, $setting) != false) && (isset($this->company->settings->{$setting}) !== false)) {
|
elseif ((property_exists($this->company->settings, $setting) !== false) && (isset($this->company->settings->{$setting}) !== false)) {
|
||||||
return $this->company->settings->{$setting};
|
return $this->company->settings->{$setting};
|
||||||
} elseif (property_exists(CompanySettings::defaults(), $setting)) {
|
} elseif (property_exists(CompanySettings::defaults(), $setting)) {
|
||||||
return CompanySettings::defaults()->{$setting};
|
return CompanySettings::defaults()->{$setting};
|
||||||
|
@ -132,6 +132,7 @@ class CompanyGateway extends BaseModel
|
|||||||
// const TYPE_EWAY = 313;
|
// const TYPE_EWAY = 313;
|
||||||
// const TYPE_FORTE = 314;
|
// const TYPE_FORTE = 314;
|
||||||
// const PAYPAL_PPCP = 323;
|
// const PAYPAL_PPCP = 323;
|
||||||
|
// const SQUARE = 320;
|
||||||
|
|
||||||
public $gateway_consts = [
|
public $gateway_consts = [
|
||||||
'38f2c48af60c7dd69e04248cbb24c36e' => 300,
|
'38f2c48af60c7dd69e04248cbb24c36e' => 300,
|
||||||
@ -144,7 +145,7 @@ class CompanyGateway extends BaseModel
|
|||||||
'8fdeed552015b3c7b44ed6c8ebd9e992' => 309,
|
'8fdeed552015b3c7b44ed6c8ebd9e992' => 309,
|
||||||
'd6814fc83f45d2935e7777071e629ef9' => 310,
|
'd6814fc83f45d2935e7777071e629ef9' => 310,
|
||||||
'bbd736b3254b0aabed6ad7fda1298c88' => 311,
|
'bbd736b3254b0aabed6ad7fda1298c88' => 311,
|
||||||
'1bd651fb213ca0c9d66ae3c336dc77e7' => 312,
|
'1bd651fb213ca0c9d66ae3c336dc77e8' => 312,
|
||||||
'944c20175bbe6b9972c05bcfe294c2c7' => 313,
|
'944c20175bbe6b9972c05bcfe294c2c7' => 313,
|
||||||
'kivcvjexxvdiyqtj3mju5d6yhpeht2xs' => 314,
|
'kivcvjexxvdiyqtj3mju5d6yhpeht2xs' => 314,
|
||||||
'65faab2ab6e3223dbe848b1686490baz' => 320,
|
'65faab2ab6e3223dbe848b1686490baz' => 320,
|
||||||
|
@ -193,6 +193,18 @@ class AuthorizePaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
public function import()
|
public function import()
|
||||||
{
|
{
|
||||||
|
$this->init();
|
||||||
|
|
||||||
return (new AuthorizeCustomer($this))->importCustomers();
|
return (new AuthorizeCustomer($this))->importCustomers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
return $this->import();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
return $this->init()->getPublicClientKey() ?? false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -806,4 +806,14 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,29 +12,40 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
use Exception;
|
||||||
use App\Models\ClientGatewayToken;
|
use App\Models\Client;
|
||||||
use App\Models\GatewayType;
|
use Braintree\Gateway;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use App\Models\PaymentHash;
|
use App\Models\PaymentHash;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\SystemLog;
|
use App\Models\ClientContact;
|
||||||
|
use App\Factory\ClientFactory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Models\ClientGatewayToken;
|
||||||
|
use App\Factory\ClientContactFactory;
|
||||||
use App\PaymentDrivers\Braintree\ACH;
|
use App\PaymentDrivers\Braintree\ACH;
|
||||||
use App\PaymentDrivers\Braintree\CreditCard;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
use App\PaymentDrivers\Braintree\PayPal;
|
use App\PaymentDrivers\Braintree\PayPal;
|
||||||
use Braintree\Gateway;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use App\PaymentDrivers\Braintree\CreditCard;
|
||||||
|
|
||||||
class BraintreePaymentDriver extends BaseDriver
|
class BraintreePaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
|
use GeneratesCounter;
|
||||||
|
|
||||||
public $refundable = true;
|
public $refundable = true;
|
||||||
|
|
||||||
public $token_billing = true;
|
public $token_billing = true;
|
||||||
|
|
||||||
public $can_authorise_credit_card = true;
|
public $can_authorise_credit_card = true;
|
||||||
|
|
||||||
|
private bool $completed = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Gateway;
|
* @var Gateway;
|
||||||
*/
|
*/
|
||||||
@ -157,34 +168,6 @@ class BraintreePaymentDriver extends BaseDriver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function updateCustomer()
|
|
||||||
// {
|
|
||||||
// $customer = $this->findOrCreateCustomer();
|
|
||||||
|
|
||||||
// $result = $this->gateway->customer()->update(
|
|
||||||
// $customer->id,
|
|
||||||
// [
|
|
||||||
// 'firstName' => $this->client->present()->name(),
|
|
||||||
// 'email' => $this->client->present()->email(),
|
|
||||||
// 'phone' => $this->client->present()->phone(),
|
|
||||||
// 'creditCard' => [
|
|
||||||
// 'billingAddress' => [
|
|
||||||
// 'options' => [
|
|
||||||
// 'updateExisting' => true
|
|
||||||
// ],
|
|
||||||
// 'firstName' => $this->client->present()->first_name() ?: $this->client->present()->name(),
|
|
||||||
// 'lastName' => $this->client->present()->last_name() ?: '',
|
|
||||||
// 'streetAddress' => $this->client->address1 ?: '',
|
|
||||||
// 'extendedAddress' =>$this->client->address2 ?: '',
|
|
||||||
// 'locality' => $this->client->city ?: '',
|
|
||||||
// 'postalCode' => $this->client->postal_code ?: '',
|
|
||||||
// 'countryCodeAlpha2' => $this->client->country ? $this->client->country->iso_3166_2 : 'US',
|
|
||||||
// ],
|
|
||||||
// ],
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function refund(Payment $payment, $amount, $return_client_response = false)
|
public function refund(Payment $payment, $amount, $return_client_response = false)
|
||||||
{
|
{
|
||||||
$this->init();
|
$this->init();
|
||||||
@ -324,13 +307,198 @@ class BraintreePaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
nlog('braintree webhook');
|
nlog('braintree webhook');
|
||||||
|
|
||||||
// if($webhookNotification)
|
|
||||||
// nlog($webhookNotification->kind);
|
|
||||||
|
|
||||||
// // Example values for webhook notification properties
|
|
||||||
// $message = $webhookNotification->kind; // "subscription_went_past_due"
|
|
||||||
// $message = $webhookNotification->timestamp->format('D M j G:i:s T Y'); // "Sun Jan 1 00:00:00 UTC 2012"
|
|
||||||
|
|
||||||
return response()->json([], 200);
|
return response()->json([], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ct =$this->init()->gateway->clientToken()->generate();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function find(string $customer_id = '') {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return $this->init()->gateway->customer()->find($customer_id);
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findTokens(string $gateway_customer_reference)
|
||||||
|
{
|
||||||
|
return ClientGatewayToken::where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('gateway_customer_reference', $gateway_customer_reference)
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToken(string $token, string $gateway_customer_reference)
|
||||||
|
{
|
||||||
|
|
||||||
|
return ClientGatewayToken::where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('gateway_customer_reference', $gateway_customer_reference)
|
||||||
|
->where('token', $token)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findClient(string $email) {
|
||||||
|
return ClientContact::where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('email', $email)
|
||||||
|
->first()->client ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addClientCards(Client $client, array $cards)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->client = $client;
|
||||||
|
|
||||||
|
foreach($cards as $card) {
|
||||||
|
|
||||||
|
if($this->getToken($card->token, $card->customerId) || Carbon::createFromDate($card->expirationYear, $card->expirationMonth, '1')->lt(now()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$payment_meta = new \stdClass();
|
||||||
|
$payment_meta->exp_month = (string) $card->expirationMonth;
|
||||||
|
$payment_meta->exp_year = (string) $card->expirationYear;
|
||||||
|
$payment_meta->brand = (string) $card->cardType;
|
||||||
|
$payment_meta->last4 = (string) $card->last4;
|
||||||
|
$payment_meta->type = GatewayType::CREDIT_CARD;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'payment_meta' => $payment_meta,
|
||||||
|
'token' => $card->token,
|
||||||
|
'payment_method_id' => GatewayType::CREDIT_CARD,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->storeGatewayToken($data, ['gateway_customer_reference' => $card->customerId]);
|
||||||
|
|
||||||
|
nlog("adding card to customer payment profile");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createNinjaClient(mixed $customer): Client
|
||||||
|
{
|
||||||
|
|
||||||
|
$client = ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id);
|
||||||
|
|
||||||
|
$b_business_address = count($customer->addresses) >= 1 ? $customer->addresses[0] : false;
|
||||||
|
$b_shipping_address = count($customer->addresses) > 1 ? $customer->addresses[1] : false;
|
||||||
|
$import_client_data = [];
|
||||||
|
|
||||||
|
if($b_business_address) {
|
||||||
|
|
||||||
|
$braintree_address =
|
||||||
|
[
|
||||||
|
'address1' => $b_business_address->extendedAddress ?? '',
|
||||||
|
'address2' => $b_business_address->streetAddress ?? '',
|
||||||
|
'city' => $b_business_address->locality ?? '',
|
||||||
|
'postal_code' => $b_business_address->postalCode ?? '',
|
||||||
|
'state' => $b_business_address->region ?? '',
|
||||||
|
'country_id' => $b_business_address->countryCodeNumeric ?? '840',
|
||||||
|
];
|
||||||
|
|
||||||
|
$import_client_data = array_merge($import_client_data, $braintree_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($b_shipping_address) {
|
||||||
|
|
||||||
|
$braintree_shipping_address =
|
||||||
|
[
|
||||||
|
'shipping_address1' => $b_shipping_address->extendedAddress ?? '',
|
||||||
|
'shipping_address2' => $b_shipping_address->streetAddress ?? '',
|
||||||
|
'shipping_city' => $b_shipping_address->locality ?? '',
|
||||||
|
'shipping_postal_code' => $b_shipping_address->postalCode ?? '',
|
||||||
|
'shipping_state' => $b_shipping_address->region ?? '',
|
||||||
|
'shipping_country_id' => $b_shipping_address->countryCodeNumeric ?? '840',
|
||||||
|
];
|
||||||
|
|
||||||
|
$import_client_data = array_merge($import_client_data, $braintree_shipping_address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$client->fill($import_client_data);
|
||||||
|
|
||||||
|
$client->phone = $customer->phone ?? '';
|
||||||
|
$client->name = $customer->company ?? $customer->firstName;
|
||||||
|
|
||||||
|
$settings = $client->settings;
|
||||||
|
$settings->currency_id = (string) $this->company_gateway->company->settings->currency_id;
|
||||||
|
$client->settings = $settings;
|
||||||
|
$client->save();
|
||||||
|
|
||||||
|
$contact = ClientContactFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id);
|
||||||
|
$contact->first_name = $customer->firstName ?? '';
|
||||||
|
$contact->last_name = $customer->lastName ?? '';
|
||||||
|
$contact->email = $customer->email ?? '';
|
||||||
|
$contact->phone = $customer->phone ?? '';
|
||||||
|
$contact->client_id = $client->id;
|
||||||
|
$contact->saveQuietly();
|
||||||
|
|
||||||
|
if (! isset($client->number) || empty($client->number)) {
|
||||||
|
$x = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
$client->number = $this->getNextClientNumber($client);
|
||||||
|
$client->saveQuietly();
|
||||||
|
|
||||||
|
$this->completed = false;
|
||||||
|
} catch (QueryException $e) {
|
||||||
|
$x++;
|
||||||
|
|
||||||
|
if ($x > 10) {
|
||||||
|
$this->completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ($this->completed);
|
||||||
|
} else {
|
||||||
|
$client->saveQuietly();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $client;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
$customers = $this->init()->gateway->customer()->all();
|
||||||
|
|
||||||
|
foreach($customers as $c){
|
||||||
|
|
||||||
|
$customer = $this->find($c->id);
|
||||||
|
|
||||||
|
// nlog(count($customer->creditCards). " Exists for {$c->id}");
|
||||||
|
|
||||||
|
if(!$customer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$client = $this->findClient($customer->email);
|
||||||
|
|
||||||
|
if(!$this->findTokens($c->id) && !$client) {
|
||||||
|
//customer is not referenced in the system - create client
|
||||||
|
$client = $this->createNinjaClient($customer);
|
||||||
|
// nlog("Creating new Client");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addClientCards($client, $customer->creditCards);
|
||||||
|
|
||||||
|
// nlog("Adding Braintree Client: {$c->id} => {$client->id}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,37 +12,38 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Exceptions\PaymentFailed;
|
use Exception;
|
||||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
|
||||||
use App\Http\Requests\Gateways\Checkout3ds\Checkout3dsRequest;
|
|
||||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Models\ClientGatewayToken;
|
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\GatewayType;
|
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use Checkout\CheckoutSdk;
|
||||||
|
use Checkout\Environment;
|
||||||
|
use Checkout\Common\Phone;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use App\Models\PaymentHash;
|
use App\Models\PaymentHash;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\SystemLog;
|
use Illuminate\Support\Carbon;
|
||||||
use App\PaymentDrivers\CheckoutCom\CheckoutWebhook;
|
use App\Jobs\Util\SystemLogger;
|
||||||
use App\PaymentDrivers\CheckoutCom\CreditCard;
|
use App\Exceptions\PaymentFailed;
|
||||||
use App\PaymentDrivers\CheckoutCom\Utilities;
|
use App\Models\ClientGatewayToken;
|
||||||
use App\Utils\Traits\SystemLogTrait;
|
|
||||||
use Checkout\CheckoutApiException;
|
use Checkout\CheckoutApiException;
|
||||||
|
use App\Utils\Traits\SystemLogTrait;
|
||||||
|
use Checkout\Payments\RefundRequest;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Checkout\CheckoutArgumentException;
|
use Checkout\CheckoutArgumentException;
|
||||||
use Checkout\CheckoutAuthorizationException;
|
|
||||||
use Checkout\CheckoutSdk;
|
|
||||||
use Checkout\Common\Phone;
|
|
||||||
use Checkout\Customers\CustomerRequest;
|
use Checkout\Customers\CustomerRequest;
|
||||||
use Checkout\Environment;
|
use Checkout\CheckoutAuthorizationException;
|
||||||
|
use App\PaymentDrivers\CheckoutCom\Utilities;
|
||||||
|
use Checkout\Payments\Request\PaymentRequest;
|
||||||
|
use App\PaymentDrivers\CheckoutCom\CreditCard;
|
||||||
|
use App\PaymentDrivers\CheckoutCom\CheckoutWebhook;
|
||||||
|
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||||
|
use Checkout\Payments\Request\Source\RequestIdSource;
|
||||||
|
use App\Http\Requests\Gateways\Checkout3ds\Checkout3dsRequest;
|
||||||
|
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||||
use Checkout\Payments\Previous\PaymentRequest as PreviousPaymentRequest;
|
use Checkout\Payments\Previous\PaymentRequest as PreviousPaymentRequest;
|
||||||
use Checkout\Payments\Previous\Source\RequestIdSource as SourceRequestIdSource;
|
use Checkout\Payments\Previous\Source\RequestIdSource as SourceRequestIdSource;
|
||||||
use Checkout\Payments\RefundRequest;
|
|
||||||
use Checkout\Payments\Request\PaymentRequest;
|
|
||||||
use Checkout\Payments\Request\Source\RequestIdSource;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class CheckoutComPaymentDriver extends BaseDriver
|
class CheckoutComPaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
@ -534,4 +535,87 @@ class CheckoutComPaymentDriver extends BaseDriver
|
|||||||
{
|
{
|
||||||
// Gateway doesn't support this feature.
|
// Gateway doesn't support this feature.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$this->init()->gateway->getCustomersClient('x');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToken(string $token, $gateway_customer_reference)
|
||||||
|
{
|
||||||
|
return ClientGatewayToken::query()
|
||||||
|
->where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('gateway_customer_reference', $gateway_customer_reference)
|
||||||
|
->where('token', $token)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImportCustomers
|
||||||
|
*
|
||||||
|
* Only their methods because checkout.com
|
||||||
|
* does not have a list route for customers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
$this->company_gateway
|
||||||
|
->company
|
||||||
|
->clients()
|
||||||
|
->cursor()
|
||||||
|
->each(function ($client){
|
||||||
|
|
||||||
|
if(!str_contains($client->present()->email(), "@"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try{
|
||||||
|
$customer = $this->gateway->getCustomersClient()->get($client->present()->email());
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
nlog("Checkout: Customer not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->client = $client;
|
||||||
|
|
||||||
|
nlog($customer['instruments']);
|
||||||
|
|
||||||
|
foreach($customer['instruments'] as $card)
|
||||||
|
{
|
||||||
|
if(
|
||||||
|
$card['type'] != 'card' ||
|
||||||
|
Carbon::createFromDate($card['expiry_year'], $card['expiry_month'], '1')->lt(now()) ||
|
||||||
|
$this->getToken($card['id'], $customer['id'])
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$payment_meta = new \stdClass();
|
||||||
|
$payment_meta->exp_month = (string) $card['expiry_month'];
|
||||||
|
$payment_meta->exp_year = (string) $card['expiry_year'];
|
||||||
|
$payment_meta->brand = (string) $card['scheme'];
|
||||||
|
$payment_meta->last4 = (string) $card['last4'];
|
||||||
|
$payment_meta->type = (int) GatewayType::CREDIT_CARD;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'payment_meta' => $payment_meta,
|
||||||
|
'token' => $card['id'],
|
||||||
|
'payment_method_id' => GatewayType::CREDIT_CARD,
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->storeGatewayToken($data, ['gateway_customer_reference' => $customer['id']]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,4 +211,24 @@ class EwayPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
$response =$this->init()->eway->queryTransaction('xx');
|
||||||
|
|
||||||
|
return (bool) count($response->getErrors()) == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* importCustomers
|
||||||
|
*
|
||||||
|
* No support
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
137
app/PaymentDrivers/Factory/ForteCustomerFactory.php
Normal file
137
app/PaymentDrivers/Factory/ForteCustomerFactory.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?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://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers\Factory;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\Company;
|
||||||
|
|
||||||
|
class ForteCustomerFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
public function convertToNinja(array $customer, Company $company): array
|
||||||
|
{
|
||||||
|
return
|
||||||
|
collect([
|
||||||
|
'name' => $customer['company_name'] ?? $customer['first_name'],
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'first_name' => $customer['first_name'],
|
||||||
|
'last_name' => $customer['last_name'],
|
||||||
|
'email' => $this->getBillingAddress($customer)['email'],
|
||||||
|
'phone' => $this->getBillingAddress($customer)['phone'],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'settings' => [
|
||||||
|
'currency_id' => $company->settings->currency_id,
|
||||||
|
],
|
||||||
|
])->merge($this->getShippingAddress($customer))
|
||||||
|
->merge($this->getBillingAddress($customer))
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// public function convertToGateway(Client $client): array
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
private function getBillingAddress(array $customer): array
|
||||||
|
{
|
||||||
|
if(isset($customer['default_billing_address_token'])) {
|
||||||
|
|
||||||
|
foreach($customer['addresses'] as $address) {
|
||||||
|
|
||||||
|
if($address['address_token'] != $customer['default_billing_address_token'])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'address1' => $address['physical_address']['street_line1'],
|
||||||
|
'address2' => $address['physical_address']['street_line2'],
|
||||||
|
'city' => $address['physical_address']['locality'],
|
||||||
|
'state' => $address['physical_address']['region'],
|
||||||
|
'postal_code' => $address['physical_address']['postal_code'],
|
||||||
|
'country_id' => '840',
|
||||||
|
'email' => $address['email'],
|
||||||
|
'phone' => $address['phone'],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($customer['addresses'][0])) {
|
||||||
|
|
||||||
|
$address = $customer['addresses'][0];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'address1' => $address['physical_address']['street_line1'],
|
||||||
|
'address2' => $address['physical_address']['street_line2'],
|
||||||
|
'city' => $address['physical_address']['locality'],
|
||||||
|
'state' => $address['physical_address']['region'],
|
||||||
|
'postal_code' => $address['physical_address']['postal_code'],
|
||||||
|
'email' => $address['email'],
|
||||||
|
'phone' => $address['phone'],
|
||||||
|
'country_id' => '840',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['email' => '', 'phone' => ''];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShippingAddress(array $customer): array
|
||||||
|
{
|
||||||
|
|
||||||
|
if(isset($customer['default_shipping_address_token'])) {
|
||||||
|
|
||||||
|
foreach($customer['addresses'] as $address) {
|
||||||
|
|
||||||
|
if($address['address_token'] != $customer['default_shipping_address_token']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'shipping_address1' => $address['physical_address']['street_line1'],
|
||||||
|
'shipping_address2' => $address['physical_address']['street_line2'],
|
||||||
|
'shipping_city' => $address['physical_address']['locality'],
|
||||||
|
'shipping_state' => $address['physical_address']['region'],
|
||||||
|
'shipping_postal_code' => $address['physical_address']['postal_code'],
|
||||||
|
'shipping_country_id' => '840',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($customer['addresses'][1])){
|
||||||
|
|
||||||
|
$address = $customer['addresses'][1];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'shipping_address1' => $address['physical_address']['street_line1'],
|
||||||
|
'shipping_address2' => $address['physical_address']['street_line2'],
|
||||||
|
'shipping_city' => $address['physical_address']['locality'],
|
||||||
|
'shipping_state' => $address['physical_address']['region'],
|
||||||
|
'shipping_postal_code' => $address['physical_address']['postal_code'],
|
||||||
|
'shipping_country_id' => '840',
|
||||||
|
'email' => $address['email'],
|
||||||
|
'phone' => $address['phone'],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['email' => '', 'phone' => ''];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
59
app/PaymentDrivers/Factory/PaytraceCustomerFactory.php
Normal file
59
app/PaymentDrivers/Factory/PaytraceCustomerFactory.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?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://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers\Factory;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
|
||||||
|
class PaytraceCustomerFactory
|
||||||
|
{
|
||||||
|
public function convertToNinja($customer, Company $company): array
|
||||||
|
{
|
||||||
|
return
|
||||||
|
collect([
|
||||||
|
'name' => $customer->billing_address->name ?? $customer->shipping_address->name,
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'first_name' => $customer->billing_address->name ?? $customer->shipping_address->name,
|
||||||
|
'last_name' => '',
|
||||||
|
'email' => $customer->email,
|
||||||
|
'phone' => $customer->phone,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'currency_id' => $company->settings->currency_id,
|
||||||
|
'address1' => $customer->billing_address->street_address,
|
||||||
|
'address2' => $customer->billing_address->street_address2,
|
||||||
|
'city' => $customer->billing_address->city,
|
||||||
|
'state' => $customer->billing_address->state,
|
||||||
|
'postal_code' => $customer->billing_address->zip,
|
||||||
|
'country_id' => '840',
|
||||||
|
'shipping_address1' => $customer->shipping_address->street_address,
|
||||||
|
'shipping_address2' => $customer->shipping_address->street_address2,
|
||||||
|
'shipping_city' => $customer->shipping_address->city,
|
||||||
|
'shipping_state' => $customer->shipping_address->state,
|
||||||
|
'shipping_postal_code' => $customer->shipping_address->zip,
|
||||||
|
'shipping_country_id' => '840',
|
||||||
|
'settings' => [
|
||||||
|
'currency_id' => $company->settings->currency_id,
|
||||||
|
],
|
||||||
|
'card' => [
|
||||||
|
'token' => $customer->customer_id,
|
||||||
|
'last4' => $customer->credit_card->masked_number,
|
||||||
|
'expiry_month' => $customer->credit_card->expiration_month,
|
||||||
|
'expiry_year' => $customer->credit_card->expiration_year,
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
132
app/PaymentDrivers/Factory/SquareCustomerFactory.php
Normal file
132
app/PaymentDrivers/Factory/SquareCustomerFactory.php
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<?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://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers\Factory;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
|
||||||
|
class SquareCustomerFactory
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"id": "A537H7KAQWSAF8M8EM1Y23E16M",
|
||||||
|
"created_at": "2021-10-28T20:19:07.692Z",
|
||||||
|
"updated_at": "2024-01-09T20:14:21Z",
|
||||||
|
"cards": [
|
||||||
|
{
|
||||||
|
"id": "ccof:oG9wEmGAvoAnrBGt3GB",
|
||||||
|
"card_brand": "VISA",
|
||||||
|
"last_4": "5858",
|
||||||
|
"exp_month": 10,
|
||||||
|
"exp_year": 2023,
|
||||||
|
"cardholder_name": "Amelia Earhart",
|
||||||
|
"billing_address": {
|
||||||
|
"address_line_1": "500 Electric Ave",
|
||||||
|
"locality": "New York",
|
||||||
|
"administrative_district_level_1": "NY",
|
||||||
|
"postal_code": "94103",
|
||||||
|
"country": "US"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gftc:06c30c2b9772458a9e87b2880ee2ce1a",
|
||||||
|
"card_brand": "SQUARE_GIFT_CARD",
|
||||||
|
"last_4": "0895",
|
||||||
|
"exp_month": 12,
|
||||||
|
"exp_year": 2050,
|
||||||
|
"billing_address": {
|
||||||
|
"postal_code": "94103"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"given_name": "Amelia",
|
||||||
|
"family_name": "Earhart",
|
||||||
|
"email_address": "Amelia.Earhart@example.com",
|
||||||
|
"address": {
|
||||||
|
"address_line_1": "123 Main St",
|
||||||
|
"locality": "Seattle",
|
||||||
|
"administrative_district_level_1": "WA",
|
||||||
|
"postal_code": "98121",
|
||||||
|
"country": "US"
|
||||||
|
},
|
||||||
|
"phone_number": "1-212-555-4240",
|
||||||
|
"note": "a customer on seller account",
|
||||||
|
"reference_id": "YOUR_REFERENCE_ID",
|
||||||
|
"company_name": "ACME",
|
||||||
|
"preferences": {
|
||||||
|
"email_unsubscribed": false
|
||||||
|
},
|
||||||
|
"creation_source": "THIRD_PARTY",
|
||||||
|
"segment_ids": [
|
||||||
|
"8QJTJCE6AZSN6.REACHABLE",
|
||||||
|
"8QJTJCE6AZSN6.CARDS_ON_FILE",
|
||||||
|
"gv2:8H24YRM74H2030XWJWP9F0MAEW",
|
||||||
|
"gv2:4TR2NFVP8N63D9K1FZ5E62VD78"
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function convertToNinja($customer, Company $company): array
|
||||||
|
{
|
||||||
|
$cards = [];
|
||||||
|
|
||||||
|
|
||||||
|
foreach($customer->getCards() ?? [] as $card){
|
||||||
|
|
||||||
|
$meta = new \stdClass;
|
||||||
|
$meta->exp_month = $card->getExpMonth();
|
||||||
|
$meta->exp_year = $card->getExpYear();
|
||||||
|
$meta->last4 = $card->getLast4();
|
||||||
|
$meta->brand = $card->getCardBrand();
|
||||||
|
$meta->type = GatewayType::CREDIT_CARD;
|
||||||
|
|
||||||
|
$cards[] = [
|
||||||
|
'token' => $card->getId(),
|
||||||
|
'payment_meta' => $meta,
|
||||||
|
'payment_method_id' => GatewayType::CREDIT_CARD,
|
||||||
|
'gateway_customer_reference' => $customer->getId(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$address = $customer->getAddress();
|
||||||
|
|
||||||
|
return
|
||||||
|
collect([
|
||||||
|
'name' => $customer->getCompanyName() ?? ($customer->getGivenName() ?? '' ." " . $customer->getFamilyName() ?? ''),
|
||||||
|
'contacts' => [
|
||||||
|
[
|
||||||
|
'first_name' => $customer->getGivenName(),
|
||||||
|
'last_name' => $customer->getFamilyName(),
|
||||||
|
'email' => $customer->getEmailAddress(),
|
||||||
|
'phone' => $customer->getPhoneNumber(),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'currency_id' => $company->settings->currency_id,
|
||||||
|
'address1' => $address->getAddressLine1(),
|
||||||
|
'address2' => $address->getAddressLine2(),
|
||||||
|
'city' => $address->getLocality(),
|
||||||
|
'state' => $address->getAdministrativeDistrictLevel1(),
|
||||||
|
'postal_code' => $address->getPostalCode(),
|
||||||
|
'country_id' => '840',
|
||||||
|
'settings' => [
|
||||||
|
'currency_id' => $company->settings->currency_id,
|
||||||
|
],
|
||||||
|
'cards' => $cards,
|
||||||
|
])
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,13 +11,19 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Models\GatewayType;
|
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\SystemLog;
|
use App\Models\SystemLog;
|
||||||
use App\PaymentDrivers\Forte\ACH;
|
use App\Models\GatewayType;
|
||||||
use App\PaymentDrivers\Forte\CreditCard;
|
use App\Models\ClientContact;
|
||||||
|
use App\Factory\ClientFactory;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\PaymentDrivers\Forte\ACH;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
|
use App\PaymentDrivers\Forte\CreditCard;
|
||||||
|
use App\Repositories\ClientContactRepository;
|
||||||
|
use App\PaymentDrivers\Factory\ForteCustomerFactory;
|
||||||
|
|
||||||
class FortePaymentDriver extends BaseDriver
|
class FortePaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
@ -183,8 +189,140 @@ class FortePaymentDriver extends BaseDriver
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
////////////////////////////////////////////
|
||||||
// {
|
// DB
|
||||||
// return $this->payment_method->yourTokenBillingImplmentation();
|
///////////////////////////////////////////
|
||||||
// }
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
$forte_base_uri = "https://sandbox.forte.net/api/v3/";
|
||||||
|
if ($this->company_gateway->getConfigField('testMode') == false) {
|
||||||
|
$forte_base_uri = "https://api.forte.net/v3/";
|
||||||
|
}
|
||||||
|
$forte_api_access_id = $this->company_gateway->getConfigField('apiAccessId');
|
||||||
|
$forte_secure_key = $this->company_gateway->getConfigField('secureKey');
|
||||||
|
$forte_auth_organization_id = $this->company_gateway->getConfigField('authOrganizationId');
|
||||||
|
$forte_organization_id = $this->company_gateway->getConfigField('organizationId');
|
||||||
|
$forte_location_id = $this->company_gateway->getConfigField('locationId');
|
||||||
|
|
||||||
|
$response = Http::withBasicAuth($forte_api_access_id, $forte_secure_key)
|
||||||
|
->withHeaders(['X-Forte-Auth-Organization-Id' => $forte_organization_id])
|
||||||
|
->get("{$forte_base_uri}/organizations/{$forte_organization_id}/locations/{$forte_location_id}/customers/");
|
||||||
|
|
||||||
|
return $response->successful();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function baseUri(): string
|
||||||
|
{
|
||||||
|
|
||||||
|
$forte_base_uri = "https://sandbox.forte.net/api/v3/";
|
||||||
|
if ($this->company_gateway->getConfigField('testMode') == false) {
|
||||||
|
$forte_base_uri = "https://api.forte.net/v3/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $forte_base_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getOrganisationId(): string
|
||||||
|
{
|
||||||
|
return $this->company_gateway->getConfigField('organizationId');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLocationId(): string
|
||||||
|
{
|
||||||
|
return $this->company_gateway->getConfigField('locationId');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stubRequest()
|
||||||
|
{
|
||||||
|
|
||||||
|
$forte_api_access_id = $this->company_gateway->getConfigField('apiAccessId');
|
||||||
|
$forte_secure_key = $this->company_gateway->getConfigField('secureKey');
|
||||||
|
$forte_auth_organization_id = $this->company_gateway->getConfigField('authOrganizationId');
|
||||||
|
|
||||||
|
return Http::withBasicAuth($forte_api_access_id, $forte_secure_key)
|
||||||
|
->withHeaders(['X-Forte-Auth-Organization-Id' => $this->getOrganisationId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getClient(?string $email)
|
||||||
|
{
|
||||||
|
return ClientContact::query()
|
||||||
|
->where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('email', $email)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLocation()
|
||||||
|
{
|
||||||
|
|
||||||
|
$response = $this->stubRequest()
|
||||||
|
->withQueryParameters(['page_size' => 10000])
|
||||||
|
->get("{$this->baseUri()}/organizations/{$this->getOrganisationId()}/locations/{$this->getLocationId()}");
|
||||||
|
|
||||||
|
if($response->successful())
|
||||||
|
return $response->json();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateFees()
|
||||||
|
{
|
||||||
|
$response = $this->getLocation();
|
||||||
|
|
||||||
|
if($response)
|
||||||
|
{
|
||||||
|
$body = $response['services'];
|
||||||
|
|
||||||
|
$fees_and_limits = $this->company_gateway->fees_and_limits;
|
||||||
|
|
||||||
|
if($body['card']['service_fee_percentage'] > 0 || $body['card']['service_fee_additional_amount'] > 0){
|
||||||
|
|
||||||
|
$fees_and_limits->{1}->fee_amount = $body['card']['service_fee_additional_amount'];
|
||||||
|
$fees_and_limits->{1}->fee_percent = $body['card']['service_fee_percentage'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if($body['debit']['service_fee_percentage'] > 0 || $body['debit']['service_fee_additional_amount'] > 0) {
|
||||||
|
|
||||||
|
$fees_and_limits->{2}->fee_amount = $body['debit']['service_fee_additional_amount'];
|
||||||
|
$fees_and_limits->{2}->fee_percent = $body['debit']['service_fee_percentage'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->company_gateway->fees_and_limits = $fees_and_limits;
|
||||||
|
$this->company_gateway->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
|
||||||
|
$response = $this->stubRequest()
|
||||||
|
->withQueryParameters(['page_size' => 10000])
|
||||||
|
->get("{$this->baseUri()}/organizations/{$this->getOrganisationId()}/locations/{$this->getLocationId()}/customers");
|
||||||
|
|
||||||
|
if($response->successful()){
|
||||||
|
|
||||||
|
foreach($response->json()['results'] as $customer)
|
||||||
|
{
|
||||||
|
|
||||||
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||||
|
$factory = new ForteCustomerFactory();
|
||||||
|
|
||||||
|
$data = $factory->convertToNinja($customer, $this->company_gateway->company);
|
||||||
|
|
||||||
|
if(strlen($data['email']) == 0 || $this->getClient($data['email']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
|
||||||
|
|
||||||
|
//persist any payment methods here!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,11 +84,11 @@ class GoCardlessPaymentDriver extends BaseDriver
|
|||||||
$types[] = GatewayType::DIRECT_DEBIT;
|
$types[] = GatewayType::DIRECT_DEBIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($this->client->currency()->code, ['EUR', 'GBP'])) {
|
if ($this->client && in_array($this->client->currency()->code, ['EUR', 'GBP'])) {
|
||||||
$types[] = GatewayType::SEPA;
|
$types[] = GatewayType::SEPA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->client->currency()->code === 'GBP') {
|
if ($this->client && $this->client->currency()->code === 'GBP') {
|
||||||
$types[] = GatewayType::INSTANT_BANK_PAY;
|
$types[] = GatewayType::INSTANT_BANK_PAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,4 +558,17 @@ class GoCardlessPaymentDriver extends BaseDriver
|
|||||||
{
|
{
|
||||||
return render('gateways.gocardless.verification');
|
return render('gateways.gocardless.verification');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$customers = $this->init()->gateway->customers()->list();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,4 +420,20 @@ class MolliePaymentDriver extends BaseDriver
|
|||||||
{
|
{
|
||||||
return \number_format((float) $amount, 2, '.', '');
|
return \number_format((float) $amount, 2, '.', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$p = $this->gateway->payments->page();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,4 +561,27 @@ class PayPalPPCPPaymentDriver extends BaseDriver
|
|||||||
PayPalWebhook::dispatch($request->all(), $request->headers->all(), $this->access_token);
|
PayPalWebhook::dispatch($request->all(), $request->headers->all(), $this->access_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->init()->getClientToken();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
|
||||||
|
// $response = $this->gatewayRequest('/v1/reporting/transactions', 'get', ['fields' => 'all','page_size' => 500,'start_date' => '2024-02-01T00:00:00-0000', 'end_date' => '2024-03-01T00:00:00-0000']);
|
||||||
|
|
||||||
|
// nlog($response->json());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,11 +81,7 @@ class PayPalRestPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
// $this->omnipay_gateway = Omnipay::create(
|
|
||||||
// $this->company_gateway->gateway->provider
|
|
||||||
// );
|
|
||||||
|
|
||||||
// $this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
|
|
||||||
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
|
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
|
||||||
|
|
||||||
$secret = $this->company_gateway->getConfigField('secret');
|
$secret = $this->company_gateway->getConfigField('secret');
|
||||||
@ -380,61 +376,6 @@ class PayPalRestPaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
return $r->json()['id'];
|
return $r->json()['id'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// $_invoice = collect($this->payment_hash->data->invoices)->first();
|
|
||||||
|
|
||||||
// $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
|
||||||
|
|
||||||
// $order = [
|
|
||||||
// "intent" => "CAPTURE",
|
|
||||||
// "payer" => [
|
|
||||||
// "name" => [
|
|
||||||
// "given_name" => $this->client->present()->first_name(),
|
|
||||||
// "surname" => $this->client->present()->last_name(),
|
|
||||||
// ],
|
|
||||||
// "email_address" => $this->client->present()->email(),
|
|
||||||
// "address" => [
|
|
||||||
// "address_line_1" => $this->client->address1,
|
|
||||||
// "address_line_2" => $this->client->address2,
|
|
||||||
// "admin_area_1" => $this->client->city,
|
|
||||||
// "admin_area_2" => $this->client->state,
|
|
||||||
// "postal_code" => $this->client->postal_code,
|
|
||||||
// "country_code" => $this->client->country->iso_3166_2,
|
|
||||||
// ]
|
|
||||||
// ],
|
|
||||||
// "purchase_units" => [
|
|
||||||
// [
|
|
||||||
// "description" => ctrans('texts.invoice_number').'# '.$invoice->number,
|
|
||||||
// "invoice_id" => $invoice->number,
|
|
||||||
// "amount" => [
|
|
||||||
// "value" => (string)$data['amount_with_fee'],
|
|
||||||
// "currency_code" => $this->client->currency()->code,
|
|
||||||
// "breakdown" => [
|
|
||||||
// "item_total" => [
|
|
||||||
// "currency_code" => $this->client->currency()->code,
|
|
||||||
// "value" => (string)$data['amount_with_fee']
|
|
||||||
// ]
|
|
||||||
// ]
|
|
||||||
// ],
|
|
||||||
// "items" => [
|
|
||||||
// [
|
|
||||||
// "name" => ctrans('texts.invoice_number').'# '.$invoice->number,
|
|
||||||
// "quantity" => "1",
|
|
||||||
// "unit_amount" => [
|
|
||||||
// "currency_code" => $this->client->currency()->code,
|
|
||||||
// "value" => (string)$data['amount_with_fee']
|
|
||||||
// ],
|
|
||||||
// ],
|
|
||||||
// ],
|
|
||||||
// ]
|
|
||||||
// ]
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
|
||||||
|
|
||||||
// return $r->json()['id'];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getShippingAddress(): ?array
|
private function getShippingAddress(): ?array
|
||||||
@ -483,7 +424,7 @@ class PayPalRestPaymentDriver extends BaseDriver
|
|||||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||||
SystemLog::TYPE_PAYPAL,
|
SystemLog::TYPE_PAYPAL,
|
||||||
$this->client,
|
$this->client,
|
||||||
$this->client->company,
|
$this->client->company ?? $this->company_gateway->company,
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
|
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
|
||||||
@ -520,5 +461,23 @@ class PayPalRestPaymentDriver extends BaseDriver
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->init()->getClientToken();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,9 @@ class CreditCard
|
|||||||
'enc_key' => $data['enc_key'],
|
'enc_key' => $data['enc_key'],
|
||||||
'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'),
|
'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'),
|
||||||
'billing_address' => $this->buildBillingAddress(),
|
'billing_address' => $this->buildBillingAddress(),
|
||||||
|
'email' => $this->paytrace->client->present()->email(),
|
||||||
|
'phone' => $this->paytrace->client->present()->phone(),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->paytrace->gatewayRequest('/v1/customer/pt_protect_create', $post_data);
|
$response = $this->paytrace->gatewayRequest('/v1/customer/pt_protect_create', $post_data);
|
||||||
|
@ -11,19 +11,24 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Exceptions\SystemError;
|
|
||||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Models\ClientGatewayToken;
|
|
||||||
use App\Models\GatewayType;
|
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Utils\CurlUtils;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use App\Models\PaymentHash;
|
use App\Models\PaymentHash;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\SystemLog;
|
use App\Factory\ClientFactory;
|
||||||
use App\PaymentDrivers\PayTrace\CreditCard;
|
use App\Exceptions\SystemError;
|
||||||
use App\Utils\CurlUtils;
|
use App\Jobs\Util\SystemLogger;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Models\ClientGatewayToken;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
|
use App\PaymentDrivers\PayTrace\CreditCard;
|
||||||
|
use App\Repositories\ClientContactRepository;
|
||||||
|
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||||
|
use App\Models\ClientContact;
|
||||||
|
use App\PaymentDrivers\Factory\PaytraceCustomerFactory;
|
||||||
|
|
||||||
class PaytracePaymentDriver extends BaseDriver
|
class PaytracePaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
@ -246,4 +251,76 @@ class PaytracePaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->init()->generateAuthHeaders() && strlen($this->company_gateway->getConfigField('integratorId')) > 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'integrator_id' => $this->company_gateway->getConfigField('integratorId'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->gatewayRequest('/v1/customer/export', $data);
|
||||||
|
|
||||||
|
nlog($response);
|
||||||
|
|
||||||
|
if ($response && $response->success) {
|
||||||
|
|
||||||
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||||
|
$factory = new PaytraceCustomerFactory();
|
||||||
|
|
||||||
|
foreach($response->customers as $customer)
|
||||||
|
{
|
||||||
|
$data = $factory->convertToNinja($customer, $this->company_gateway->company);
|
||||||
|
|
||||||
|
$client = false;
|
||||||
|
|
||||||
|
if(str_contains($data['contacts'][0]['email'], "@"))
|
||||||
|
{
|
||||||
|
$client = ClientContact::query()
|
||||||
|
->where('company_id', $this->company_gateway->company_id)
|
||||||
|
->where('email', $data['contacts'][0]['email'])
|
||||||
|
->first()->client ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$client)
|
||||||
|
$client = $client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
|
||||||
|
|
||||||
|
$this->client = $client;
|
||||||
|
|
||||||
|
if(ClientGatewayToken::query()->where('client_id', $client->id)->where('token',$data['card']['token'])->exists())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$cgt = [];
|
||||||
|
$cgt['token'] = $data['card']['token'];
|
||||||
|
$cgt['payment_method_id'] = GatewayType::CREDIT_CARD;
|
||||||
|
|
||||||
|
$payment_meta = new \stdClass();
|
||||||
|
$payment_meta->exp_month = $data['card']['expiry_month'];
|
||||||
|
$payment_meta->exp_year = $data['card']['expiry_year'];
|
||||||
|
$payment_meta->brand = 'CC';
|
||||||
|
$payment_meta->last4 = $data['card']['last4'];
|
||||||
|
$payment_meta->type = GatewayType::CREDIT_CARD;
|
||||||
|
|
||||||
|
$cgt['payment_meta'] = $payment_meta;
|
||||||
|
|
||||||
|
$token = $this->storeGatewayToken($cgt, []);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ class CreditCard implements MethodInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
$square_card = new \Square\Models\Card();
|
$square_card = new \Square\Models\Card();
|
||||||
$square_card->setCustomerId($this->findOrCreateClient());
|
$square_card->setCustomerId($this->square_driver->findOrCreateClient());
|
||||||
|
|
||||||
$body = new \Square\Models\CreateCardRequest(uniqid("st", true), $source_id, $square_card);
|
$body = new \Square\Models\CreateCardRequest(uniqid("st", true), $source_id, $square_card);
|
||||||
|
|
||||||
@ -238,82 +238,5 @@ class CreditCard implements MethodInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function findOrCreateClient()
|
|
||||||
{
|
|
||||||
$email_address = new \Square\Models\CustomerTextFilter();
|
|
||||||
$email_address->setExact($this->square_driver->client->present()->email());
|
|
||||||
|
|
||||||
$filter = new \Square\Models\CustomerFilter();
|
|
||||||
$filter->setEmailAddress($email_address);
|
|
||||||
|
|
||||||
$query = new \Square\Models\CustomerQuery();
|
|
||||||
$query->setFilter($filter);
|
|
||||||
|
|
||||||
$body = new \Square\Models\SearchCustomersRequest();
|
|
||||||
$body->setQuery($query);
|
|
||||||
|
|
||||||
$api_response = $this->square_driver
|
|
||||||
->init()
|
|
||||||
->square
|
|
||||||
->getCustomersApi()
|
|
||||||
->searchCustomers($body);
|
|
||||||
|
|
||||||
$customers = false;
|
|
||||||
|
|
||||||
if ($api_response->isSuccess()) {
|
|
||||||
$customers = $api_response->getBody();
|
|
||||||
$customers = json_decode($customers);
|
|
||||||
|
|
||||||
if (count([$api_response->getBody(), 1]) == 0) {
|
|
||||||
$customers = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$errors = $api_response->getErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($customers && property_exists($customers, 'customers')) {
|
|
||||||
return $customers->customers[0]->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->createClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createClient()
|
|
||||||
{
|
|
||||||
$country = $this->square_driver->client->country ? $this->square_driver->client->country->iso_3166_2 : $this->square_driver->client->company->country()->iso_3166_2;
|
|
||||||
|
|
||||||
/* Step two - create the customer */
|
|
||||||
$billing_address = new \Square\Models\Address();
|
|
||||||
$billing_address->setAddressLine1($this->square_driver->client->address1);
|
|
||||||
$billing_address->setAddressLine2($this->square_driver->client->address2);
|
|
||||||
$billing_address->setLocality($this->square_driver->client->city);
|
|
||||||
$billing_address->setAdministrativeDistrictLevel1($this->square_driver->client->state);
|
|
||||||
$billing_address->setPostalCode($this->square_driver->client->postal_code);
|
|
||||||
$billing_address->setCountry($country);
|
|
||||||
|
|
||||||
$body = new \Square\Models\CreateCustomerRequest();
|
|
||||||
$body->setGivenName($this->square_driver->client->present()->name());
|
|
||||||
$body->setFamilyName('');
|
|
||||||
$body->setEmailAddress($this->square_driver->client->present()->email());
|
|
||||||
$body->setAddress($billing_address);
|
|
||||||
// $body->setPhoneNumber($this->square_driver->client->phone);
|
|
||||||
$body->setReferenceId($this->square_driver->client->number);
|
|
||||||
$body->setNote('Created by Invoice Ninja.');
|
|
||||||
|
|
||||||
$api_response = $this->square_driver
|
|
||||||
->init()
|
|
||||||
->square
|
|
||||||
->getCustomersApi()
|
|
||||||
->createCustomer($body);
|
|
||||||
|
|
||||||
if ($api_response->isSuccess()) {
|
|
||||||
$result = $api_response->getResult();
|
|
||||||
|
|
||||||
return $result->getCustomer()->getId();
|
|
||||||
} else {
|
|
||||||
$errors = $api_response->getErrors();
|
|
||||||
nlog($errors);
|
|
||||||
return $this->processUnsuccessfulPayment($api_response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,22 +11,27 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Models\ClientGatewayToken;
|
|
||||||
use App\Models\GatewayType;
|
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Models\GatewayType;
|
||||||
use App\Models\PaymentHash;
|
use App\Models\PaymentHash;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\SystemLog;
|
use App\Models\ClientContact;
|
||||||
|
use App\Factory\ClientFactory;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Square\Utils\WebhooksHelper;
|
||||||
|
use App\Models\ClientGatewayToken;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
|
use Square\Models\WebhookSubscription;
|
||||||
use App\PaymentDrivers\Square\CreditCard;
|
use App\PaymentDrivers\Square\CreditCard;
|
||||||
use App\PaymentDrivers\Square\SquareWebhook;
|
use App\PaymentDrivers\Square\SquareWebhook;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Repositories\ClientContactRepository;
|
||||||
use Square\Models\Builders\RefundPaymentRequestBuilder;
|
|
||||||
use Square\Models\CreateWebhookSubscriptionRequest;
|
use Square\Models\CreateWebhookSubscriptionRequest;
|
||||||
use Square\Models\WebhookSubscription;
|
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||||
use Square\Utils\WebhooksHelper;
|
use App\PaymentDrivers\Factory\SquareCustomerFactory;
|
||||||
|
use Square\Models\Builders\RefundPaymentRequestBuilder;
|
||||||
|
|
||||||
class SquarePaymentDriver extends BaseDriver
|
class SquarePaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
@ -429,4 +434,205 @@ class SquarePaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
return $amount;
|
return $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
$api_response = $this->init()
|
||||||
|
->square
|
||||||
|
->getCustomersApi()
|
||||||
|
->listCustomers();
|
||||||
|
|
||||||
|
|
||||||
|
return (bool) count($api_response->getErrors()) == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCustomers()
|
||||||
|
{
|
||||||
|
|
||||||
|
$limit = 100;
|
||||||
|
|
||||||
|
$api_response = $this->init()
|
||||||
|
->square
|
||||||
|
->getCustomersApi()
|
||||||
|
->listCustomers(null,
|
||||||
|
$limit,
|
||||||
|
'DEFAULT',
|
||||||
|
'DESC'
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($api_response->isSuccess()) {
|
||||||
|
|
||||||
|
while ($api_response->getResult()->getCustomers()) {
|
||||||
|
|
||||||
|
$customers = $api_response->getResult()->getCustomers();
|
||||||
|
|
||||||
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||||
|
|
||||||
|
foreach($customers as $customer)
|
||||||
|
{
|
||||||
|
|
||||||
|
$data = (new SquareCustomerFactory())->convertToNinja($customer, $this->company_gateway->company);
|
||||||
|
$client = ClientContact::where('company_id', $this->company_gateway->company_id)->where('email', $customer->getEmailAddress())->first()->client ?? false;
|
||||||
|
|
||||||
|
if(!$client)
|
||||||
|
$client = $client_repo->save($data, ClientFactory::create($this->company_gateway->company_id, $this->company_gateway->user_id));
|
||||||
|
|
||||||
|
$this->client = $client;
|
||||||
|
|
||||||
|
foreach($data['cards'] as $card) {
|
||||||
|
|
||||||
|
if(ClientGatewayToken::where('company_id', $this->company_gateway->company_id)->where('token', $card['token'])->exists())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$this->storeGatewayToken($card);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = $api_response->getCursor();
|
||||||
|
if ($c) {
|
||||||
|
|
||||||
|
$api_response = $this->init()
|
||||||
|
->square
|
||||||
|
->getCustomersApi()
|
||||||
|
->listCustomers(
|
||||||
|
$c,
|
||||||
|
$limit,
|
||||||
|
'DEFAULT',
|
||||||
|
'DESC'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findClient($email = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
$email_address_string = $email ?? $this->client->present()->email();
|
||||||
|
|
||||||
|
$email_address = new \Square\Models\CustomerTextFilter();
|
||||||
|
$email_address->setExact($email_address_string);
|
||||||
|
|
||||||
|
$filter = new \Square\Models\CustomerFilter();
|
||||||
|
$filter->setEmailAddress($email_address);
|
||||||
|
|
||||||
|
$query = new \Square\Models\CustomerQuery();
|
||||||
|
$query->setFilter($filter);
|
||||||
|
|
||||||
|
$body = new \Square\Models\SearchCustomersRequest();
|
||||||
|
$body->setQuery($query);
|
||||||
|
|
||||||
|
$api_response = $this->init()
|
||||||
|
->square
|
||||||
|
->getCustomersApi()
|
||||||
|
->searchCustomers($body);
|
||||||
|
|
||||||
|
$customers = false;
|
||||||
|
|
||||||
|
if ($api_response->isSuccess()) {
|
||||||
|
$customers = $api_response->getBody();
|
||||||
|
$customers = json_decode($customers);
|
||||||
|
|
||||||
|
if (count([$api_response->getBody(), 1]) == 0) {
|
||||||
|
$customers = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errors = $api_response->getErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($customers && property_exists($customers, 'customers')) {
|
||||||
|
return $customers->customers[0]->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findOrCreateClient()
|
||||||
|
{
|
||||||
|
if($customer_id = $this->findClient())
|
||||||
|
return $customer_id;
|
||||||
|
|
||||||
|
return $this->createClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createClient()
|
||||||
|
{
|
||||||
|
$country = $this->client->country ? $this->client->country->iso_3166_2 : $this->client->company->country()->iso_3166_2;
|
||||||
|
|
||||||
|
/* Step two - create the customer */
|
||||||
|
$billing_address = new \Square\Models\Address();
|
||||||
|
$billing_address->setAddressLine1($this->client->address1);
|
||||||
|
$billing_address->setAddressLine2($this->client->address2);
|
||||||
|
$billing_address->setLocality($this->client->city);
|
||||||
|
$billing_address->setAdministrativeDistrictLevel1($this->client->state);
|
||||||
|
$billing_address->setPostalCode($this->client->postal_code);
|
||||||
|
$billing_address->setCountry($country);
|
||||||
|
|
||||||
|
$body = new \Square\Models\CreateCustomerRequest();
|
||||||
|
$body->setGivenName($this->client->present()->name());
|
||||||
|
$body->setFamilyName('');
|
||||||
|
$body->setEmailAddress($this->client->present()->email());
|
||||||
|
$body->setAddress($billing_address);
|
||||||
|
$body->setReferenceId($this->client->number);
|
||||||
|
$body->setNote('Created by Invoice Ninja.');
|
||||||
|
|
||||||
|
$api_response = $this->init()
|
||||||
|
->square
|
||||||
|
->getCustomersApi()
|
||||||
|
->createCustomer($body);
|
||||||
|
|
||||||
|
if ($api_response->isSuccess()) {
|
||||||
|
$result = $api_response->getResult();
|
||||||
|
|
||||||
|
return $result->getCustomer()->getId();
|
||||||
|
} else {
|
||||||
|
$errors = $api_response->getErrors();
|
||||||
|
nlog($errors);
|
||||||
|
|
||||||
|
$error = end($errors);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'response' => $error->getDetail(),
|
||||||
|
'error' => $error->getDetail(),
|
||||||
|
'error_code' => $error->getCode(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->processUnsuccessfulTransaction($data);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,12 +62,6 @@ class ImportCustomers
|
|||||||
$this->addCustomer($customer);
|
$this->addCustomer($customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle
|
|
||||||
// if(is_array($customers->data) && end($customers->data) && array_key_exists('id', end($customers->data)))
|
|
||||||
// $starting_after = end($customers->data)['id'];
|
|
||||||
// else
|
|
||||||
// break;
|
|
||||||
|
|
||||||
$starting_after = isset(end($customers->data)['id']) ? end($customers->data)['id'] : false;
|
$starting_after = isset(end($customers->data)['id']) ? end($customers->data)['id'] : false;
|
||||||
|
|
||||||
if (!$starting_after) {
|
if (!$starting_after) {
|
||||||
|
@ -990,4 +990,20 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
|
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
|
||||||
}, $string);
|
}, $string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function auth(): bool
|
||||||
|
{
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->verifyConnect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ use App\Http\Middleware\SetDomainNameDb;
|
|||||||
use Illuminate\Queue\Events\JobProcessing;
|
use Illuminate\Queue\Events\JobProcessing;
|
||||||
use App\Helpers\Mail\Office365MailTransport;
|
use App\Helpers\Mail\Office365MailTransport;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
|
use Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory;
|
||||||
|
use Symfony\Component\Mailer\Transport\Dsn;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -119,6 +121,30 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
return $this;
|
return $this;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Mail::extend('brevo', function () {
|
||||||
|
return (new BrevoTransportFactory)->create(
|
||||||
|
new Dsn(
|
||||||
|
'brevo+api',
|
||||||
|
'default',
|
||||||
|
config('services.brevo.key')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Mailer::macro('brevo_config', function (string $brevo_key) {
|
||||||
|
// @phpstan-ignore /** @phpstan-ignore-next-line **/
|
||||||
|
Mailer::setSymfonyTransport(
|
||||||
|
(new BrevoTransportFactory)->create(
|
||||||
|
new Dsn(
|
||||||
|
'brevo+api',
|
||||||
|
'default',
|
||||||
|
$brevo_key
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function register(): void
|
public function register(): void
|
||||||
|
@ -162,6 +162,7 @@ class Statement
|
|||||||
$ts->addGlobal(['show_credits' => $this->options['show_credits_table']]);
|
$ts->addGlobal(['show_credits' => $this->options['show_credits_table']]);
|
||||||
$ts->addGlobal(['show_aging' => $this->options['show_aging_table']]);
|
$ts->addGlobal(['show_aging' => $this->options['show_aging_table']]);
|
||||||
$ts->addGlobal(['show_payments' => $this->options['show_payments_table']]);
|
$ts->addGlobal(['show_payments' => $this->options['show_payments_table']]);
|
||||||
|
$ts->addGlobal(['currency_code' => $this->client->company->currency()->code]);
|
||||||
|
|
||||||
$ts->build([
|
$ts->build([
|
||||||
'variables' => collect([$variables]),
|
'variables' => collect([$variables]),
|
||||||
|
@ -59,6 +59,8 @@ class AdminEmail implements ShouldQueue
|
|||||||
|
|
||||||
protected ?string $client_mailgun_endpoint = null;
|
protected ?string $client_mailgun_endpoint = null;
|
||||||
|
|
||||||
|
protected ?string $client_brevo_secret = null;
|
||||||
|
|
||||||
private string $mailer = 'default';
|
private string $mailer = 'default';
|
||||||
|
|
||||||
public Mailable $mailable;
|
public Mailable $mailable;
|
||||||
@ -137,24 +139,28 @@ class AdminEmail implements ShouldQueue
|
|||||||
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint);
|
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->client_brevo_secret) {
|
||||||
|
$mailer->brevo_config($this->client_brevo_secret);
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt the send! */
|
/* Attempt the send! */
|
||||||
try {
|
try {
|
||||||
nlog("Using mailer => ". $this->mailer. " ". now()->toDateTimeString());
|
nlog("Using mailer => " . $this->mailer . " " . now()->toDateTimeString());
|
||||||
|
|
||||||
$mailer->send($this->mailable);
|
$mailer->send($this->mailable);
|
||||||
|
|
||||||
Cache::increment("email_quota".$this->company->account->key);
|
Cache::increment("email_quota" . $this->company->account->key);
|
||||||
|
|
||||||
LightLogs::create(new EmailSuccess($this->company->company_key, $this->mailable->subject))
|
LightLogs::create(new EmailSuccess($this->company->company_key, $this->mailable->subject))
|
||||||
->send();
|
->send();
|
||||||
|
|
||||||
} catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
} catch (\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
||||||
return;
|
return;
|
||||||
} catch(\Symfony\Component\Mime\Exception\LogicException $e) {
|
} catch (\Symfony\Component\Mime\Exception\LogicException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
@ -224,7 +230,7 @@ class AdminEmail implements ShouldQueue
|
|||||||
public function preFlightChecksFail(): bool
|
public function preFlightChecksFail(): bool
|
||||||
{
|
{
|
||||||
/* Always send if disabled */
|
/* Always send if disabled */
|
||||||
if($this->override) {
|
if ($this->override) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +254,7 @@ class AdminEmail implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* GMail users are uncapped */
|
/* GMail users are uncapped */
|
||||||
if (in_array($this->email_object->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun'])) {
|
if (in_array($this->email_object->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun', 'client_brevo'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +343,10 @@ class AdminEmail implements ShouldQueue
|
|||||||
$this->mailer = 'mailgun';
|
$this->mailer = 'mailgun';
|
||||||
$this->setMailgunMailer();
|
$this->setMailgunMailer();
|
||||||
return $this;
|
return $this;
|
||||||
|
case 'client_brevo':
|
||||||
|
$this->mailer = 'brevo';
|
||||||
|
$this->setBrevoMailer();
|
||||||
|
return $this;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->mailer = config('mail.default');
|
$this->mailer = config('mail.default');
|
||||||
@ -390,6 +400,8 @@ class AdminEmail implements ShouldQueue
|
|||||||
|
|
||||||
$this->client_mailgun_endpoint = null;
|
$this->client_mailgun_endpoint = null;
|
||||||
|
|
||||||
|
$this->client_brevo_secret = null;
|
||||||
|
|
||||||
//always dump the drivers to prevent reuse
|
//always dump the drivers to prevent reuse
|
||||||
app('mail.manager')->forgetMailers();
|
app('mail.manager')->forgetMailers();
|
||||||
}
|
}
|
||||||
@ -454,6 +466,28 @@ class AdminEmail implements ShouldQueue
|
|||||||
$this->mailable
|
$this->mailable
|
||||||
->from($sending_email, $sending_user);
|
->from($sending_email, $sending_user);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Configures Brevo using client supplied secret
|
||||||
|
* as the Mailer
|
||||||
|
*/
|
||||||
|
private function setBrevoMailer()
|
||||||
|
{
|
||||||
|
if (strlen($this->email_object->settings->brevo_secret) > 2) {
|
||||||
|
$this->client_brevo_secret = $this->email_object->settings->brevo_secret;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$this->email_object->settings->email_sending_method = 'default';
|
||||||
|
return $this->setMailDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
|
$sending_email = (isset($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
||||||
|
$sending_user = (isset($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
|
$this->mailable
|
||||||
|
->from($sending_email, $sending_user);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures Postmark using client supplied secret
|
* Configures Postmark using client supplied secret
|
||||||
@ -527,7 +561,7 @@ class AdminEmail implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
||||||
$this->email_object->settings->email_sending_method = 'default';
|
$this->email_object->settings->email_sending_method = 'default';
|
||||||
return $this->setMailDriver();
|
return $this->setMailDriver();
|
||||||
@ -573,14 +607,16 @@ class AdminEmail implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
private function logMailError($errors, $recipient_object): void
|
private function logMailError($errors, $recipient_object): void
|
||||||
{
|
{
|
||||||
(new SystemLogger(
|
(
|
||||||
|
new SystemLogger(
|
||||||
$errors,
|
$errors,
|
||||||
SystemLog::CATEGORY_MAIL,
|
SystemLog::CATEGORY_MAIL,
|
||||||
SystemLog::EVENT_MAIL_SEND,
|
SystemLog::EVENT_MAIL_SEND,
|
||||||
SystemLog::TYPE_FAILURE,
|
SystemLog::TYPE_FAILURE,
|
||||||
$recipient_object,
|
$recipient_object,
|
||||||
$this->company
|
$this->company
|
||||||
))->handle();
|
)
|
||||||
|
)->handle();
|
||||||
|
|
||||||
$job_failure = new EmailFailure($this->company->company_key);
|
$job_failure = new EmailFailure($this->company->company_key);
|
||||||
$job_failure->string_metric5 = 'failed_email';
|
$job_failure->string_metric5 = 'failed_email';
|
||||||
@ -608,8 +644,8 @@ class AdminEmail implements ShouldQueue
|
|||||||
|
|
||||||
$token = json_decode($guzzle->post($url, [
|
$token = json_decode($guzzle->post($url, [
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'client_id' => config('ninja.o365.client_id') ,
|
'client_id' => config('ninja.o365.client_id'),
|
||||||
'client_secret' => config('ninja.o365.client_secret') ,
|
'client_secret' => config('ninja.o365.client_secret'),
|
||||||
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
||||||
'grant_type' => 'refresh_token',
|
'grant_type' => 'refresh_token',
|
||||||
'refresh_token' => $user->oauth_user_refresh_token
|
'refresh_token' => $user->oauth_user_refresh_token
|
||||||
|
@ -41,6 +41,7 @@ use Illuminate\Queue\InteractsWithQueue;
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Log;
|
||||||
use Turbo124\Beacon\Facades\LightLogs;
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
|
|
||||||
class Email implements ShouldQueue
|
class Email implements ShouldQueue
|
||||||
@ -72,6 +73,9 @@ class Email implements ShouldQueue
|
|||||||
/** MailGun endpoint */
|
/** MailGun endpoint */
|
||||||
protected ?string $client_mailgun_endpoint = null;
|
protected ?string $client_mailgun_endpoint = null;
|
||||||
|
|
||||||
|
/** Brevo endpoint */
|
||||||
|
protected ?string $client_brevo_secret = null;
|
||||||
|
|
||||||
/** Default mailer */
|
/** Default mailer */
|
||||||
private string $mailer = 'default';
|
private string $mailer = 'default';
|
||||||
|
|
||||||
@ -246,7 +250,7 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
private function incrementEmailCounter(): void
|
private function incrementEmailCounter(): void
|
||||||
{
|
{
|
||||||
if(in_array($this->mailer, ['default','mailgun']))
|
if(in_array($this->mailer, ['default','mailgun','postmark']))
|
||||||
Cache::increment("email_quota".$this->company->account->key);
|
Cache::increment("email_quota".$this->company->account->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +265,7 @@ class Email implements ShouldQueue
|
|||||||
/* Init the mailer*/
|
/* Init the mailer*/
|
||||||
$mailer = Mail::mailer($this->mailer);
|
$mailer = Mail::mailer($this->mailer);
|
||||||
|
|
||||||
|
|
||||||
/* Additional configuration if using a client third party mailer */
|
/* Additional configuration if using a client third party mailer */
|
||||||
if ($this->client_postmark_secret) {
|
if ($this->client_postmark_secret) {
|
||||||
$mailer->postmark_config($this->client_postmark_secret);
|
$mailer->postmark_config($this->client_postmark_secret);
|
||||||
@ -270,9 +275,13 @@ class Email implements ShouldQueue
|
|||||||
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint);
|
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->client_brevo_secret) {
|
||||||
|
$mailer->brevo_config($this->client_brevo_secret);
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt the send! */
|
/* Attempt the send! */
|
||||||
try {
|
try {
|
||||||
nlog("Using mailer => ". $this->mailer. " ". now()->toDateTimeString());
|
nlog("Using mailer => " . $this->mailer . " " . now()->toDateTimeString());
|
||||||
|
|
||||||
$mailer->send($this->mailable);
|
$mailer->send($this->mailable);
|
||||||
|
|
||||||
@ -281,13 +290,13 @@ class Email implements ShouldQueue
|
|||||||
LightLogs::create(new EmailSuccess($this->company->company_key, $this->mailable->subject))
|
LightLogs::create(new EmailSuccess($this->company->company_key, $this->mailable->subject))
|
||||||
->send();
|
->send();
|
||||||
|
|
||||||
} catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
} catch (\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
||||||
return;
|
return;
|
||||||
} catch(\Symfony\Component\Mime\Exception\LogicException $e) {
|
} catch (\Symfony\Component\Mime\Exception\LogicException $e) {
|
||||||
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
|
||||||
$this->fail();
|
$this->fail();
|
||||||
$this->cleanUpMailers();
|
$this->cleanUpMailers();
|
||||||
@ -376,7 +385,7 @@ class Email implements ShouldQueue
|
|||||||
public function preFlightChecksFail(): bool
|
public function preFlightChecksFail(): bool
|
||||||
{
|
{
|
||||||
/* Always send if disabled */
|
/* Always send if disabled */
|
||||||
if($this->override) {
|
if ($this->override) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +409,7 @@ class Email implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* GMail users are uncapped */
|
/* GMail users are uncapped */
|
||||||
if (in_array($this->email_object->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun'])) {
|
if (in_array($this->email_object->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun', 'client_brevo'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +470,7 @@ class Email implements ShouldQueue
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($address_object->name == " " || $address_object->name == "") {
|
if ($address_object->name == " " || $address_object->name == "") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,7 +507,7 @@ class Email implements ShouldQueue
|
|||||||
// return $this;
|
// return $this;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if(Ninja::isHosted() && $this->company->account->isPaid() && $this->email_object->settings->email_sending_method == 'default') {
|
if (Ninja::isHosted() && $this->company->account->isPaid() && $this->email_object->settings->email_sending_method == 'default') {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@ -507,7 +516,7 @@ class Email implements ShouldQueue
|
|||||||
$domain = explode("@", $email)[1] ?? "";
|
$domain = explode("@", $email)[1] ?? "";
|
||||||
$dns = dns_get_record($domain, DNS_MX);
|
$dns = dns_get_record($domain, DNS_MX);
|
||||||
$server = $dns[0]["target"];
|
$server = $dns[0]["target"];
|
||||||
if(stripos($server, "outlook.com") !== false) {
|
if (stripos($server, "outlook.com") !== false) {
|
||||||
|
|
||||||
if (property_exists($this->email_object->settings, 'email_from_name') && strlen($this->email_object->settings->email_from_name) > 1) {
|
if (property_exists($this->email_object->settings, 'email_from_name') && strlen($this->email_object->settings->email_from_name) > 1) {
|
||||||
$email_from_name = $this->email_object->settings->email_from_name;
|
$email_from_name = $this->email_object->settings->email_from_name;
|
||||||
@ -523,7 +532,7 @@ class Email implements ShouldQueue
|
|||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
nlog("problem switching outlook driver - hosted");
|
nlog("problem switching outlook driver - hosted");
|
||||||
nlog($e->getMessage());
|
nlog($e->getMessage());
|
||||||
}
|
}
|
||||||
@ -555,6 +564,10 @@ class Email implements ShouldQueue
|
|||||||
$this->mailer = 'mailgun';
|
$this->mailer = 'mailgun';
|
||||||
$this->setMailgunMailer();
|
$this->setMailgunMailer();
|
||||||
return $this;
|
return $this;
|
||||||
|
case 'client_brevo':
|
||||||
|
$this->mailer = 'brevo';
|
||||||
|
$this->setBrevoMailer();
|
||||||
|
return $this;
|
||||||
case 'smtp':
|
case 'smtp':
|
||||||
$this->mailer = 'smtp';
|
$this->mailer = 'smtp';
|
||||||
$this->configureSmtpMailer();
|
$this->configureSmtpMailer();
|
||||||
@ -600,8 +613,8 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
$sending_email = (isset($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
||||||
$sending_user = (isset($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
$sending_user = (isset ($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
$this->mailable
|
$this->mailable
|
||||||
->from($sending_email, $sending_user);
|
->from($sending_email, $sending_user);
|
||||||
@ -648,6 +661,8 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
$this->client_mailgun_endpoint = null;
|
$this->client_mailgun_endpoint = null;
|
||||||
|
|
||||||
|
$this->client_brevo_secret = null;
|
||||||
|
|
||||||
//always dump the drivers to prevent reuse
|
//always dump the drivers to prevent reuse
|
||||||
app('mail.manager')->forgetMailers();
|
app('mail.manager')->forgetMailers();
|
||||||
}
|
}
|
||||||
@ -706,8 +721,30 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
$sending_email = (isset($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
||||||
$sending_user = (isset($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
$sending_user = (isset ($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
|
$this->mailable
|
||||||
|
->from($sending_email, $sending_user);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Configures Brevo using client supplied secret
|
||||||
|
* as the Mailer
|
||||||
|
*/
|
||||||
|
private function setBrevoMailer()
|
||||||
|
{
|
||||||
|
if (strlen($this->email_object->settings->brevo_secret) > 2) {
|
||||||
|
$this->client_brevo_secret = $this->email_object->settings->brevo_secret;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$this->email_object->settings->email_sending_method = 'default';
|
||||||
|
return $this->setMailDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
|
$sending_email = (isset ($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
||||||
|
$sending_user = (isset ($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
$this->mailable
|
$this->mailable
|
||||||
->from($sending_email, $sending_user);
|
->from($sending_email, $sending_user);
|
||||||
@ -728,8 +765,8 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
$user = $this->resolveSendingUser();
|
$user = $this->resolveSendingUser();
|
||||||
|
|
||||||
$sending_email = (isset($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
$sending_email = (isset ($this->email_object->settings->custom_sending_email) && stripos($this->email_object->settings->custom_sending_email, "@")) ? $this->email_object->settings->custom_sending_email : $user->email;
|
||||||
$sending_user = (isset($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
$sending_user = (isset ($this->email_object->settings->email_from_name) && strlen($this->email_object->settings->email_from_name) > 2) ? $this->email_object->settings->email_from_name : $user->name();
|
||||||
|
|
||||||
$this->mailable
|
$this->mailable
|
||||||
->from($sending_email, $sending_user);
|
->from($sending_email, $sending_user);
|
||||||
@ -785,7 +822,7 @@ class Email implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
|
||||||
$this->email_object->settings->email_sending_method = 'default';
|
$this->email_object->settings->email_sending_method = 'default';
|
||||||
return $this->setMailDriver();
|
return $this->setMailDriver();
|
||||||
@ -831,14 +868,16 @@ class Email implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
private function logMailError($errors, $recipient_object): void
|
private function logMailError($errors, $recipient_object): void
|
||||||
{
|
{
|
||||||
(new SystemLogger(
|
(
|
||||||
|
new SystemLogger(
|
||||||
$errors,
|
$errors,
|
||||||
SystemLog::CATEGORY_MAIL,
|
SystemLog::CATEGORY_MAIL,
|
||||||
SystemLog::EVENT_MAIL_SEND,
|
SystemLog::EVENT_MAIL_SEND,
|
||||||
SystemLog::TYPE_FAILURE,
|
SystemLog::TYPE_FAILURE,
|
||||||
$recipient_object,
|
$recipient_object,
|
||||||
$this->company
|
$this->company
|
||||||
))->handle();
|
)
|
||||||
|
)->handle();
|
||||||
|
|
||||||
$job_failure = new EmailFailure($this->company->company_key);
|
$job_failure = new EmailFailure($this->company->company_key);
|
||||||
$job_failure->string_metric5 = 'failed_email';
|
$job_failure->string_metric5 = 'failed_email';
|
||||||
@ -866,8 +905,8 @@ class Email implements ShouldQueue
|
|||||||
|
|
||||||
$token = json_decode($guzzle->post($url, [
|
$token = json_decode($guzzle->post($url, [
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'client_id' => config('ninja.o365.client_id') ,
|
'client_id' => config('ninja.o365.client_id'),
|
||||||
'client_secret' => config('ninja.o365.client_secret') ,
|
'client_secret' => config('ninja.o365.client_secret'),
|
||||||
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
'scope' => 'email Mail.Send offline_access profile User.Read openid',
|
||||||
'grant_type' => 'refresh_token',
|
'grant_type' => 'refresh_token',
|
||||||
'refresh_token' => $user->oauth_user_refresh_token
|
'refresh_token' => $user->oauth_user_refresh_token
|
||||||
|
@ -544,7 +544,7 @@ class InvoiceService
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fillDefaults()
|
public function fillDefaults(bool $is_recurring = false)
|
||||||
{
|
{
|
||||||
$this->invoice->load('client.company');
|
$this->invoice->load('client.company');
|
||||||
|
|
||||||
@ -571,7 +571,7 @@ class InvoiceService
|
|||||||
$this->invoice->exchange_rate = $this->invoice->client->setExchangeRate();
|
$this->invoice->exchange_rate = $this->invoice->client->setExchangeRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->invoice->client->getSetting('auto_bill_standard_invoices')) {
|
if ($is_recurring && $this->invoice->client->getSetting('auto_bill_standard_invoices')) {
|
||||||
$this->invoice->auto_bill_enabled = true;
|
$this->invoice->auto_bill_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,24 +113,30 @@ class PdfMock
|
|||||||
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
||||||
$entity = Invoice::factory()->make();
|
$entity = Invoice::factory()->make();
|
||||||
$entity->client = Client::factory()->make(['settings' => $settings]);
|
$entity->client = Client::factory()->make(['settings' => $settings]);
|
||||||
|
$entity->client->setRelation('company', $this->company);
|
||||||
$entity->invitation = InvoiceInvitation::factory()->make();
|
$entity->invitation = InvoiceInvitation::factory()->make();
|
||||||
break;
|
break;
|
||||||
case 'quote':
|
case 'quote':
|
||||||
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
||||||
$entity = Quote::factory()->make();
|
$entity = Quote::factory()->make();
|
||||||
$entity->client = Client::factory()->make(['settings' => $settings]);
|
$entity->client = Client::factory()->make(['settings' => $settings]);
|
||||||
|
$entity->client->setRelation('company', $this->company);
|
||||||
$entity->invitation = QuoteInvitation::factory()->make();
|
$entity->invitation = QuoteInvitation::factory()->make();
|
||||||
break;
|
break;
|
||||||
case 'credit':
|
case 'credit':
|
||||||
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
||||||
$entity = Credit::factory()->make();
|
$entity = Credit::factory()->make();
|
||||||
$entity->client = Client::factory()->make(['settings' => $settings]);
|
$entity->client = Client::factory()->make(['settings' => $settings]);
|
||||||
|
$entity->client->setRelation('company', $this->company);
|
||||||
$entity->invitation = CreditInvitation::factory()->make();
|
$entity->invitation = CreditInvitation::factory()->make();
|
||||||
break;
|
break;
|
||||||
case 'purchase_order':
|
case 'purchase_order':
|
||||||
/** @var \App\Models\Invoice | \App\Models\Credit | \App\Models\Quote $entity */
|
|
||||||
|
/** @var \App\Models\PurchaseOrder $entity */
|
||||||
$entity = PurchaseOrder::factory()->make();
|
$entity = PurchaseOrder::factory()->make();
|
||||||
$entity->client = Client::factory()->make(['settings' => $settings]);
|
// $entity->client = Client::factory()->make(['settings' => $settings]);
|
||||||
|
$entity->vendor = Vendor::factory()->make();
|
||||||
|
$entity->vendor->setRelation('company', $this->company);
|
||||||
$entity->invitation = PurchaseOrderInvitation::factory()->make();
|
$entity->invitation = PurchaseOrderInvitation::factory()->make();
|
||||||
break;
|
break;
|
||||||
case PurchaseOrder::class:
|
case PurchaseOrder::class:
|
||||||
@ -138,13 +144,13 @@ class PdfMock
|
|||||||
$entity = PurchaseOrder::factory()->make();
|
$entity = PurchaseOrder::factory()->make();
|
||||||
$entity->invitation = PurchaseOrderInvitation::factory()->make();
|
$entity->invitation = PurchaseOrderInvitation::factory()->make();
|
||||||
$entity->vendor = Vendor::factory()->make();
|
$entity->vendor = Vendor::factory()->make();
|
||||||
|
$entity->invitation->setRelation('company', $this->company);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$entity = false;
|
$entity = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$entity->tax_map = $this->getTaxMap();
|
$entity->tax_map = $this->getTaxMap();
|
||||||
$entity->total_tax_map = $this->getTotalTaxMap();
|
$entity->total_tax_map = $this->getTotalTaxMap();
|
||||||
$entity->invitation->company = $this->company;
|
$entity->invitation->company = $this->company;
|
||||||
|
@ -613,8 +613,6 @@ class TemplateService
|
|||||||
|
|
||||||
$this->payment = $payment;
|
$this->payment = $payment;
|
||||||
|
|
||||||
$this->addGlobal(['currency_code' => $payment->currency->code ?? $this->company->currency()->code]);
|
|
||||||
|
|
||||||
$credits = $payment->credits->map(function ($credit) use ($payment) {
|
$credits = $payment->credits->map(function ($credit) use ($payment) {
|
||||||
return [
|
return [
|
||||||
'credit' => $credit->number,
|
'credit' => $credit->number,
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
"doctrine/dbal": "^3.0",
|
"doctrine/dbal": "^3.0",
|
||||||
"eway/eway-rapid-php": "^1.3",
|
"eway/eway-rapid-php": "^1.3",
|
||||||
"fakerphp/faker": "^1.14",
|
"fakerphp/faker": "^1.14",
|
||||||
|
"getbrevo/brevo-php": "^1.0",
|
||||||
"gocardless/gocardless-pro": "^4.12",
|
"gocardless/gocardless-pro": "^4.12",
|
||||||
"google/apiclient": "^2.7",
|
"google/apiclient": "^2.7",
|
||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
@ -95,7 +96,8 @@
|
|||||||
"sprain/swiss-qr-bill": "^4.3",
|
"sprain/swiss-qr-bill": "^4.3",
|
||||||
"square/square": "30.0.0.*",
|
"square/square": "30.0.0.*",
|
||||||
"stripe/stripe-php": "^12",
|
"stripe/stripe-php": "^12",
|
||||||
"symfony/http-client": "^7.0",
|
"symfony/brevo-mailer": "6.4",
|
||||||
|
"symfony/http-client": "^6.0",
|
||||||
"symfony/mailgun-mailer": "^6.1",
|
"symfony/mailgun-mailer": "^6.1",
|
||||||
"symfony/postmark-mailer": "^6.1",
|
"symfony/postmark-mailer": "^6.1",
|
||||||
"turbo124/beacon": "^1.5",
|
"turbo124/beacon": "^1.5",
|
||||||
|
207
composer.lock
generated
207
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "63d177f80df79731528c8669d192ded6",
|
"content-hash": "fdea921aefca562c17db327acd8df062",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "afosto/yaac",
|
"name": "afosto/yaac",
|
||||||
@ -1343,16 +1343,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
"version": "3.301.1",
|
"version": "3.301.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
"reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba"
|
"reference": "7f8180275e624cb566d8af77d2f1c958bf5be35b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0a910d2b35e7087337cdf3569dc9b6ce232aafba",
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7f8180275e624cb566d8af77d2f1c958bf5be35b",
|
||||||
"reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba",
|
"reference": "7f8180275e624cb566d8af77d2f1c958bf5be35b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1432,9 +1432,9 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.301.1"
|
"source": "https://github.com/aws/aws-sdk-php/tree/3.301.2"
|
||||||
},
|
},
|
||||||
"time": "2024-03-15T18:14:42+00:00"
|
"time": "2024-03-18T18:06:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@ -3269,6 +3269,69 @@
|
|||||||
],
|
],
|
||||||
"time": "2023-10-12T05:21:21+00:00"
|
"time": "2023-10-12T05:21:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "getbrevo/brevo-php",
|
||||||
|
"version": "v1.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/getbrevo/brevo-php.git",
|
||||||
|
"reference": "6c3286e62327277fd8445cddb057d44e850722c0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/getbrevo/brevo-php/zipball/6c3286e62327277fd8445cddb057d44e850722c0",
|
||||||
|
"reference": "6c3286e62327277fd8445cddb057d44e850722c0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"guzzlehttp/guzzle": "^7.4.0",
|
||||||
|
"php": ">=5.6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "~1.12",
|
||||||
|
"phpunit/phpunit": "^4.8",
|
||||||
|
"squizlabs/php_codesniffer": "~2.6"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Brevo\\Client\\": "lib/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Brevo Developers",
|
||||||
|
"email": "contact@brevo.com",
|
||||||
|
"homepage": "https://www.brevo.com/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Official Brevo provided RESTFul API V3 php library",
|
||||||
|
"homepage": "https://github.com/getbrevo/brevo-php",
|
||||||
|
"keywords": [
|
||||||
|
"api",
|
||||||
|
"brevo",
|
||||||
|
"php",
|
||||||
|
"sdk",
|
||||||
|
"swagger"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/getbrevo/brevo-php/issues",
|
||||||
|
"source": "https://github.com/getbrevo/brevo-php/tree/v1.0.2"
|
||||||
|
},
|
||||||
|
"time": "2023-07-14T10:00:50+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "gocardless/gocardless-pro",
|
"name": "gocardless/gocardless-pro",
|
||||||
"version": "4.28.0",
|
"version": "4.28.0",
|
||||||
@ -3455,16 +3518,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "google/apiclient-services",
|
"name": "google/apiclient-services",
|
||||||
"version": "v0.339.0",
|
"version": "v0.340.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/googleapis/google-api-php-client-services.git",
|
"url": "https://github.com/googleapis/google-api-php-client-services.git",
|
||||||
"reference": "5662d2ab3da41ac0e0e99db221a8c22c511c8f9c"
|
"reference": "c89999ea477da2b0803b2b4f14c9e7fc23b6344a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/5662d2ab3da41ac0e0e99db221a8c22c511c8f9c",
|
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/c89999ea477da2b0803b2b4f14c9e7fc23b6344a",
|
||||||
"reference": "5662d2ab3da41ac0e0e99db221a8c22c511c8f9c",
|
"reference": "c89999ea477da2b0803b2b4f14c9e7fc23b6344a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3493,9 +3556,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
|
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
|
||||||
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.339.0"
|
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.340.0"
|
||||||
},
|
},
|
||||||
"time": "2024-03-10T01:06:17+00:00"
|
"time": "2024-03-17T00:56:17+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "google/auth",
|
"name": "google/auth",
|
||||||
@ -12228,6 +12291,75 @@
|
|||||||
},
|
},
|
||||||
"time": "2023-10-16T18:04:12+00:00"
|
"time": "2023-10-16T18:04:12+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/brevo-mailer",
|
||||||
|
"version": "v6.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/brevo-mailer.git",
|
||||||
|
"reference": "83db87e0f44653cd40aeef54a2f57ab6bfccadfe"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/brevo-mailer/zipball/83db87e0f44653cd40aeef54a2f57ab6bfccadfe",
|
||||||
|
"reference": "83db87e0f44653cd40aeef54a2f57ab6bfccadfe",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"symfony/mailer": "^5.4.21|^6.2.7|^7.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/mime": "<6.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/http-client": "^6.3|^7.0",
|
||||||
|
"symfony/webhook": "^6.3|^7.0"
|
||||||
|
},
|
||||||
|
"type": "symfony-mailer-bridge",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Mailer\\Bridge\\Brevo\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Pierre Tanguy",
|
||||||
|
"homepage": "https://github.com/petanguy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony Brevo Mailer Bridge",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/brevo-mailer/tree/v7.0.0-RC1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-11-06T17:20:05+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.4.4",
|
"version": "v6.4.4",
|
||||||
@ -12814,27 +12946,28 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-client",
|
"name": "symfony/http-client",
|
||||||
"version": "v7.0.5",
|
"version": "v6.4.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-client.git",
|
"url": "https://github.com/symfony/http-client.git",
|
||||||
"reference": "425f462a59d8030703ee04a9e1c666575ed5db3b"
|
"reference": "f3c86a60a3615f466333a11fd42010d4382a82c7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/425f462a59d8030703ee04a9e1c666575ed5db3b",
|
"url": "https://api.github.com/repos/symfony/http-client/zipball/f3c86a60a3615f466333a11fd42010d4382a82c7",
|
||||||
"reference": "425f462a59d8030703ee04a9e1c666575ed5db3b",
|
"reference": "f3c86a60a3615f466333a11fd42010d4382a82c7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.1",
|
||||||
"psr/log": "^1|^2|^3",
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/http-client-contracts": "^3",
|
"symfony/http-client-contracts": "^3",
|
||||||
"symfony/service-contracts": "^2.5|^3"
|
"symfony/service-contracts": "^2.5|^3"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"php-http/discovery": "<1.15",
|
"php-http/discovery": "<1.15",
|
||||||
"symfony/http-foundation": "<6.4"
|
"symfony/http-foundation": "<6.3"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
"php-http/async-client-implementation": "*",
|
"php-http/async-client-implementation": "*",
|
||||||
@ -12851,11 +12984,11 @@
|
|||||||
"nyholm/psr7": "^1.0",
|
"nyholm/psr7": "^1.0",
|
||||||
"php-http/httplug": "^1.0|^2.0",
|
"php-http/httplug": "^1.0|^2.0",
|
||||||
"psr/http-client": "^1.0",
|
"psr/http-client": "^1.0",
|
||||||
"symfony/dependency-injection": "^6.4|^7.0",
|
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||||
"symfony/http-kernel": "^6.4|^7.0",
|
"symfony/http-kernel": "^5.4|^6.0|^7.0",
|
||||||
"symfony/messenger": "^6.4|^7.0",
|
"symfony/messenger": "^5.4|^6.0|^7.0",
|
||||||
"symfony/process": "^6.4|^7.0",
|
"symfony/process": "^5.4|^6.0|^7.0",
|
||||||
"symfony/stopwatch": "^6.4|^7.0"
|
"symfony/stopwatch": "^5.4|^6.0|^7.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -12886,7 +13019,7 @@
|
|||||||
"http"
|
"http"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/http-client/tree/v7.0.5"
|
"source": "https://github.com/symfony/http-client/tree/v6.4.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -12902,7 +13035,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-02T12:46:12+00:00"
|
"time": "2024-03-02T12:45:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-client-contracts",
|
"name": "symfony/http-client-contracts",
|
||||||
@ -16807,16 +16940,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v3.51.0",
|
"version": "v3.52.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||||
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd"
|
"reference": "a3564bd66f4bce9bc871ef18b690e2dc67a7f969"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/127fa74f010da99053e3f5b62672615b72dd6efd",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a3564bd66f4bce9bc871ef18b690e2dc67a7f969",
|
||||||
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd",
|
"reference": "a3564bd66f4bce9bc871ef18b690e2dc67a7f969",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -16887,7 +17020,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.51.0"
|
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.52.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -16895,7 +17028,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-02-28T19:50:06+00:00"
|
"time": "2024-03-18T18:40:11+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hamcrest/hamcrest-php",
|
"name": "hamcrest/hamcrest-php",
|
||||||
@ -17621,16 +17754,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.10.62",
|
"version": "1.10.63",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9"
|
"reference": "ad12836d9ca227301f5fb9960979574ed8628339"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ad12836d9ca227301f5fb9960979574ed8628339",
|
||||||
"reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9",
|
"reference": "ad12836d9ca227301f5fb9960979574ed8628339",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -17679,7 +17812,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-13T12:27:20+00:00"
|
"time": "2024-03-18T16:53:53+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user