mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 21:22:58 +01:00
commit
7758bcaafe
@ -711,6 +711,29 @@ class CreateSingleAccount extends Command
|
||||
$cg->save();
|
||||
}
|
||||
|
||||
if (config('ninja.testvars.paypal_rest') && ($this->gateway == 'all' || $this->gateway == 'paypal_rest')) {
|
||||
$cg = new CompanyGateway;
|
||||
$cg->company_id = $company->id;
|
||||
$cg->user_id = $user->id;
|
||||
$cg->gateway_key = '80af24a6a691230bbec33e930ab40665';
|
||||
$cg->require_cvv = true;
|
||||
$cg->require_billing_address = true;
|
||||
$cg->require_shipping_address = true;
|
||||
$cg->update_details = true;
|
||||
$cg->config = encrypt(config('ninja.testvars.paypal_rest'));
|
||||
$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.checkout') && ($this->gateway == 'all' || $this->gateway == 'checkout')) {
|
||||
$cg = new CompanyGateway;
|
||||
$cg->company_id = $company->id;
|
||||
|
@ -37,7 +37,6 @@ class AccountCreated extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class AccountDeleted extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class AccountPlatform extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class AccountSignup extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
@ -61,7 +60,7 @@ class AccountSignup extends GenericMixedMetric
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
* @var int
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class BankAccountsCreated extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class DbQuery extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
@ -57,7 +56,7 @@ class DbQuery extends GenericMixedMetric
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
* @var int
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class EmailCount extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class EmailFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
@ -61,7 +60,6 @@ class EmailFailure extends GenericMixedMetric
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class EmailInvoiceFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class EmailSuccess extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
@ -61,7 +60,6 @@ class EmailSuccess extends GenericMixedMetric
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class LivePreview extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class LoginFailure extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class LoginSuccess extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,6 @@ class EmailBounce extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
@ -67,7 +66,6 @@ class EmailBounce extends GenericMixedMetric
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
|
@ -16,13 +16,13 @@ namespace App\DataMapper;
|
||||
*/
|
||||
class BaseSettings
|
||||
{
|
||||
//@deprecated
|
||||
public function __construct($obj)
|
||||
{
|
||||
// foreach ($obj as $key => $value) {
|
||||
// $obj->{$key} = $value;
|
||||
// }
|
||||
}
|
||||
// //@deprecated
|
||||
// public function __construct($obj)
|
||||
// {
|
||||
// // foreach ($obj as $key => $value) {
|
||||
// // $obj->{$key} = $value;
|
||||
// // }
|
||||
// }
|
||||
|
||||
public static function setCasts($obj, $casts)
|
||||
{
|
||||
|
@ -47,17 +47,17 @@ class ClientSettings extends BaseSettings
|
||||
'send_reminders' => 'bool',
|
||||
];
|
||||
|
||||
/**
|
||||
* Cast object values and return entire class
|
||||
* prevents missing properties from not being returned
|
||||
* and always ensure an up to date class is returned.
|
||||
*
|
||||
* @param $obj
|
||||
*/
|
||||
public function __construct($obj)
|
||||
{
|
||||
parent::__construct($obj);
|
||||
}
|
||||
// /**
|
||||
// * Cast object values and return entire class
|
||||
// * prevents missing properties from not being returned
|
||||
// * and always ensure an up to date class is returned.
|
||||
// *
|
||||
// * @param $obj
|
||||
// */
|
||||
// public function __construct($obj)
|
||||
// {
|
||||
// // parent::__construct($obj);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Default Client Settings scaffold.
|
||||
@ -78,8 +78,8 @@ class ClientSettings extends BaseSettings
|
||||
/**
|
||||
* Merges settings from Company to Client.
|
||||
*
|
||||
* @param stdClass $company_settings
|
||||
* @param stdClass $client_settings
|
||||
* @param $company_settings
|
||||
* @param $client_settings
|
||||
* @return stdClass of merged settings
|
||||
*/
|
||||
public static function buildClientSettings($company_settings, $client_settings)
|
||||
|
@ -767,18 +767,18 @@ class CompanySettings extends BaseSettings
|
||||
'purchase_order_design_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Cast object values and return entire class
|
||||
* prevents missing properties from not being returned
|
||||
* and always ensure an up to date class is returned.
|
||||
*
|
||||
* @param $obj
|
||||
* @deprecated
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// parent::__construct($obj);
|
||||
}
|
||||
// /**
|
||||
// * Cast object values and return entire class
|
||||
// * prevents missing properties from not being returned
|
||||
// * and always ensure an up to date class is returned.
|
||||
// *
|
||||
// * @param $obj
|
||||
// * @deprecated
|
||||
// */
|
||||
// public function __construct()
|
||||
// {
|
||||
// // parent::__construct($obj);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Provides class defaults on init.
|
||||
|
@ -34,13 +34,4 @@ class DefaultSettings extends BaseSettings
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return stdClass
|
||||
*/
|
||||
private static function userSettingsObject() : stdClass
|
||||
{
|
||||
return (object) [
|
||||
// 'per_page' => self::$per_page,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
@ -24,92 +24,78 @@ class EmailTemplateDefaults
|
||||
|
||||
case 'email_template_invoice':
|
||||
return self::emailInvoiceTemplate();
|
||||
break;
|
||||
case 'email_template_quote':
|
||||
return self::emailQuoteTemplate();
|
||||
break;
|
||||
case 'email_template_credit':
|
||||
return self::emailCreditTemplate();
|
||||
break;
|
||||
case 'email_template_payment':
|
||||
return self::emailPaymentTemplate();
|
||||
break;
|
||||
case 'email_template_payment_partial':
|
||||
return self::emailPaymentPartialTemplate();
|
||||
break;
|
||||
case 'email_template_statement':
|
||||
return self::emailStatementTemplate();
|
||||
break;
|
||||
case 'email_template_reminder1':
|
||||
return self::emailReminder1Template();
|
||||
break;
|
||||
case 'email_template_reminder2':
|
||||
return self::emailReminder2Template();
|
||||
break;
|
||||
case 'email_template_reminder3':
|
||||
return self::emailReminder3Template();
|
||||
break;
|
||||
case 'email_template_reminder_endless':
|
||||
return self::emailReminderEndlessTemplate();
|
||||
break;
|
||||
case 'email_template_custom1':
|
||||
return self::emailInvoiceTemplate();
|
||||
break;
|
||||
case 'email_template_custom2':
|
||||
return self::emailInvoiceTemplate();
|
||||
break;
|
||||
case 'email_template_custom3':
|
||||
return self::emailInvoiceTemplate();
|
||||
case 'email_template_purchase_order':
|
||||
return self::emailPurchaseOrderTemplate();
|
||||
break;
|
||||
|
||||
/* Subject */
|
||||
case 'email_subject_purchase_order':
|
||||
return self::emailPurchaseOrderSubject();
|
||||
case 'email_subject_invoice':
|
||||
return self::emailInvoiceSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_quote':
|
||||
return self::emailQuoteSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_credit':
|
||||
return self::emailCreditSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_payment':
|
||||
return self::emailPaymentSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_payment_partial':
|
||||
return self::emailPaymentPartialSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_statement':
|
||||
return self::emailStatementSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_reminder1':
|
||||
return self::emailReminder1Subject();
|
||||
break;
|
||||
|
||||
case 'email_subject_reminder2':
|
||||
return self::emailReminder2Subject();
|
||||
break;
|
||||
|
||||
case 'email_subject_reminder3':
|
||||
return self::emailReminder3Subject();
|
||||
break;
|
||||
|
||||
case 'email_subject_reminder_endless':
|
||||
return self::emailReminderEndlessSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_custom1':
|
||||
return self::emailInvoiceSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_custom2':
|
||||
return self::emailInvoiceSubject();
|
||||
break;
|
||||
|
||||
case 'email_subject_custom3':
|
||||
return self::emailInvoiceSubject();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return self::emailInvoiceTemplate();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,6 @@ class FreeCompanySettings extends BaseSettings
|
||||
|
||||
public static $casts = [
|
||||
'portal_design_id' => 'string',
|
||||
'currency_id' => 'string',
|
||||
'task_number_pattern' => 'string',
|
||||
'task_number_counter' => 'int',
|
||||
'expense_number_pattern' => 'string',
|
||||
@ -191,16 +190,16 @@ class FreeCompanySettings extends BaseSettings
|
||||
'website' => 'string',
|
||||
];
|
||||
|
||||
/**
|
||||
* Cast object values and return entire class
|
||||
* prevents missing properties from not being returned
|
||||
* and always ensure an up to date class is returned.
|
||||
*
|
||||
* @param $obj
|
||||
*/
|
||||
public function __construct($obj)
|
||||
{
|
||||
}
|
||||
// /**
|
||||
// * Cast object values and return entire class
|
||||
// * prevents missing properties from not being returned
|
||||
// * and always ensure an up to date class is returned.
|
||||
// *
|
||||
// * @param $obj
|
||||
// */
|
||||
// public function __construct($obj)
|
||||
// {
|
||||
// }
|
||||
|
||||
/**
|
||||
* Provides class defaults on init.
|
||||
@ -223,7 +222,7 @@ class FreeCompanySettings extends BaseSettings
|
||||
$data->date_format_id = (string) config('ninja.i18n.date_format_id');
|
||||
$data->country_id = (string) config('ninja.i18n.country_id');
|
||||
$data->translations = (object) [];
|
||||
$data->pdf_variables = (object) self::getEntityVariableDefaults();
|
||||
// $data->pdf_variables = (object) self::getEntityVariableDefaults();
|
||||
|
||||
return self::setCasts($data, self::$casts);
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ class Rule extends BaseRule implements RuleInterface
|
||||
// }
|
||||
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
|
||||
return $this;
|
||||
|
||||
|
@ -197,7 +197,7 @@ class BaseRule implements RuleInterface
|
||||
}
|
||||
|
||||
/** If we are in a Origin based state, force the company tax here */
|
||||
if($company->origin_tax_data?->originDestination == 'O' && ($company->tax_data?->seller_subregion == $this->client_subregion)) {
|
||||
if($company->origin_tax_data->originDestination == 'O' && ($company->tax_data?->seller_subregion == $this->client_subregion)) {
|
||||
|
||||
$tax_data = $company->origin_tax_data;
|
||||
|
||||
|
@ -33859,8 +33859,6 @@ class USStates
|
||||
'99926' => 'AK',
|
||||
'99927' => 'AK',
|
||||
'99929' => 'AK',
|
||||
'13021' => 'NY',
|
||||
'13024' => 'NY',
|
||||
];
|
||||
|
||||
public static function get(): array
|
||||
|
@ -30,7 +30,7 @@ class DesignWasCreated
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return PrivateChannel
|
||||
* @return PrivateChannel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ class DesignWasDeleted
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return PrivateChannel
|
||||
* @return PrivateChannel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ class DesignWasRestored
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return PrivateChannel
|
||||
* @return PrivateChannel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ class DesignWasUpdated
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return PrivateChannel
|
||||
* @return PrivateChannel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
|
@ -17,8 +17,10 @@ use App\Utils\Ninja;
|
||||
use Sentry\State\Scope;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Http\Request;
|
||||
use InvalidArgumentException;
|
||||
use Sentry\Laravel\Integration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Aws\Exception\CredentialsException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use League\Flysystem\UnableToCreateDirectory;
|
||||
@ -34,7 +36,6 @@ use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
@ -64,7 +65,7 @@ class Handler extends ExceptionHandler
|
||||
ConnectException::class,
|
||||
RuntimeException::class,
|
||||
InvalidArgumentException::class,
|
||||
Aws\Exception\CredentialsException::class,
|
||||
CredentialsException::class,
|
||||
];
|
||||
|
||||
protected $hostedDontReport = [
|
||||
|
@ -14,7 +14,7 @@ namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class PaymentRefundFailed extends Exception
|
||||
{
|
||||
@ -32,14 +32,14 @@ class PaymentRefundFailed extends Exception
|
||||
* Render the exception into an HTTP response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function render($request)
|
||||
{
|
||||
// $msg = 'Unable to refund the transaction';
|
||||
$msg = ctrans('texts.warning_local_refund');
|
||||
|
||||
if ($this->getMessage() && strlen($this->getMessage()) >= 1) {
|
||||
if ($this->getMessage() && strlen($this->getMessage()) > 1) {
|
||||
$msg = $this->getMessage();
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class QuoteConversion extends Exception
|
||||
{
|
||||
@ -32,7 +32,7 @@ class QuoteConversion extends Exception
|
||||
* Render the exception into an HTTP response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function render($request)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class YodleeApiException extends Exception
|
||||
{
|
||||
@ -32,14 +32,14 @@ class YodleeApiException extends Exception
|
||||
* Render the exception into an HTTP response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function render($request)
|
||||
{
|
||||
// $msg = 'Unable to refund the transaction';
|
||||
$msg = ctrans('texts.error');
|
||||
|
||||
if ($this->getMessage() && strlen($this->getMessage()) >= 1) {
|
||||
if ($this->getMessage() && strlen($this->getMessage()) > 1) {
|
||||
$msg = $this->getMessage();
|
||||
}
|
||||
|
||||
|
@ -373,6 +373,8 @@ class BaseExport
|
||||
if(!is_array($parts) || count($parts) < 2)
|
||||
return '';
|
||||
|
||||
$value = '';
|
||||
|
||||
match($parts[0]) {
|
||||
'contact' => $value = $this->resolveClientContactKey($parts[1], $entity, $transformer),
|
||||
'client' => $value = $this->resolveClientKey($parts[1], $entity, $transformer),
|
||||
@ -385,7 +387,7 @@ class BaseExport
|
||||
'purchase_order' => $value = $this->resolvePurchaseOrderKey($parts[1], $entity, $transformer),
|
||||
'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
|
||||
'task' => $value = $this->resolveTaskKey($parts[1], $entity, $transformer),
|
||||
default => $value = ''
|
||||
default => $value = '',
|
||||
};
|
||||
|
||||
return $value;
|
||||
@ -580,6 +582,7 @@ class BaseExport
|
||||
private function resolveInvoiceKey($column, $entity, $transformer)
|
||||
{
|
||||
nlog("searching for {$column}");
|
||||
$transformed_invoice = false;
|
||||
|
||||
if($transformer instanceof PaymentTransformer) {
|
||||
$transformed_invoices = $transformer->includeInvoices($entity);
|
||||
@ -615,14 +618,14 @@ class BaseExport
|
||||
|
||||
}
|
||||
|
||||
if(array_key_exists($column, $transformed_invoice)) {
|
||||
if($transformed_invoice && array_key_exists($column, $transformed_invoice)) {
|
||||
return $transformed_invoice[$column];
|
||||
} elseif (array_key_exists(str_replace("invoice.", "", $column), $transformed_invoice)) {
|
||||
} elseif ($transformed_invoice && array_key_exists(str_replace("invoice.", "", $column), $transformed_invoice)) {
|
||||
return $transformed_invoice[$column];
|
||||
}
|
||||
|
||||
if($column == 'status')
|
||||
return $entity->stringStatus($entity->status_id);
|
||||
// if($column == 'status')
|
||||
// return $entity->stringStatus($entity->status_id);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class BankTransactionFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -118,7 +118,7 @@ class BankTransactionFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -36,7 +36,7 @@ class BankTransactionRuleFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -54,7 +54,7 @@ class BankTransactionRuleFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class PaymentTermFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -39,7 +39,7 @@ class PaymentTermFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -22,7 +22,7 @@ class QuoteFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -124,7 +124,7 @@ class QuoteFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class RecurringExpenseFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -52,7 +52,7 @@ class RecurringExpenseFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class SubscriptionFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -39,7 +39,7 @@ class SubscriptionFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -48,7 +48,7 @@ class SystemLogFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -64,7 +64,7 @@ class SystemLogFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -24,7 +24,7 @@ class TaskFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -99,7 +99,7 @@ class TaskFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
@ -131,8 +131,8 @@ class TaskFilters extends QueryFilters
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if(count($status_parameters) > 0)
|
||||
return $this->builder->whereIn('status_id', $this->transformKeys($status_parameters));
|
||||
if(count($status_parameters) >= 1)
|
||||
$this->builder->whereIn('status_id', $this->transformKeys($status_parameters));
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class TaskStatusFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -39,7 +39,7 @@ class TaskStatusFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class TaxRateFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -39,7 +39,7 @@ class TaxRateFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class TokenFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -45,7 +45,7 @@ class TokenFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class UserFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -43,7 +43,7 @@ class UserFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
@ -69,6 +69,19 @@ class UserFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters users that have been removed from the
|
||||
* company, but not deleted from the system.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hideRemovedUsers()
|
||||
{
|
||||
return $this->builder->whereHas('company_users', function ($q) {
|
||||
$q->where('company_id', '=', auth()->user()->company()->id)->whereNull('deleted_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the base with() function as no company ID
|
||||
* exists on the user table
|
||||
|
@ -21,7 +21,7 @@ class VendorFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -58,7 +58,7 @@ class VendorFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -21,7 +21,7 @@ class WebhookFilters extends QueryFilters
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @param string $filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
@ -39,7 +39,7 @@ class WebhookFilters extends QueryFilters
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @param string $sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort = ''): Builder
|
||||
|
@ -19,7 +19,7 @@ use Illuminate\View\View;
|
||||
*
|
||||
* @param $page
|
||||
* @param bool $boolean
|
||||
* @return bool
|
||||
* @return bool | string
|
||||
*/
|
||||
function isActive($page, bool $boolean = false)
|
||||
{
|
||||
@ -40,8 +40,6 @@ function isActive($page, bool $boolean = false)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,8 @@ class EpcQrGenerator
|
||||
$qr = $writer->writeString($this->encodeMessage(), 'utf-8');
|
||||
} catch(\Throwable $e) {
|
||||
return '';
|
||||
} catch(\Exception $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@ -50,7 +51,7 @@ class BankIntegrationController extends BaseController
|
||||
|
||||
/**
|
||||
* @param BankIntegrationFilters $filters
|
||||
* @return Responsec
|
||||
* @return Response
|
||||
*/
|
||||
public function index(BankIntegrationFilters $filters)
|
||||
{
|
||||
@ -250,7 +251,7 @@ class BankIntegrationController extends BaseController
|
||||
* Return the remote list of accounts stored on the third party provider
|
||||
* and update our local cache.
|
||||
*
|
||||
* @return Response
|
||||
* @return Response | JsonResponse
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -71,7 +71,7 @@ class BankTransactionController extends BaseController
|
||||
|
||||
public function create(CreateBankTransactionRequest $request)
|
||||
{
|
||||
$bank_transaction = BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id);
|
||||
$bank_transaction = BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
@ -79,7 +79,7 @@ class BankTransactionController extends BaseController
|
||||
public function store(StoreBankTransactionRequest $request)
|
||||
{
|
||||
//stub to store the model
|
||||
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id));
|
||||
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class QuoteController extends Controller
|
||||
$quote->service()->approve(auth()->user())->save();
|
||||
|
||||
if (request()->has('signature') && ! is_null(request()->signature) && ! empty(request()->signature)) {
|
||||
InjectSignature::dispatch($quote, request()->signature);
|
||||
InjectSignature::dispatch($quote, auth()->guard('contact')->user()->id, request()->signature, request()->getClientIp());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,8 +186,7 @@ class PurchaseOrderController extends Controller
|
||||
->save();
|
||||
|
||||
if (request()->has('signature') && ! is_null(request()->signature) && ! empty(request()->signature)) {
|
||||
(new InjectSignature($purchase_order, request()->signature))->handle();
|
||||
// InjectSignature::dispatch($purchase_order, request()->signature);
|
||||
(new InjectSignature($purchase_order, auth()->guard('vendor')->user()->id, request()->signature, request()->getClientIp()))->handle();
|
||||
}
|
||||
|
||||
event(new PurchaseOrderWasAccepted($purchase_order, auth()->guard('vendor')->user(), $purchase_order->company, Ninja::eventVars()));
|
||||
|
@ -53,6 +53,8 @@ class PdfSlot extends Component
|
||||
|
||||
public $route_entity = 'client';
|
||||
|
||||
public $is_quote = false;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
MultiDB::setDb($this->db);
|
||||
@ -111,9 +113,9 @@ class PdfSlot extends Component
|
||||
$this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_quote_columns);
|
||||
}
|
||||
|
||||
$this->html_variables = $this->entity->client ?
|
||||
(new HtmlEngine($this->invitation))->generateLabelsAndValues() :
|
||||
(new VendorHtmlEngine($this->invitation))->generateLabelsAndValues();
|
||||
$this->html_variables = $this->entity_type == 'purchase_order' ?
|
||||
(new VendorHtmlEngine($this->invitation))->generateLabelsAndValues() :
|
||||
(new HtmlEngine($this->invitation))->generateLabelsAndValues();
|
||||
|
||||
return render('components.livewire.pdf-slot', [
|
||||
'invitation' => $this->invitation,
|
||||
@ -230,15 +232,16 @@ class PdfSlot extends Component
|
||||
private function getProducts()
|
||||
{
|
||||
|
||||
|
||||
|
||||
$product_items = collect($this->entity->line_items)->filter(function ($item) {
|
||||
return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5;
|
||||
})->map(function ($item){
|
||||
|
||||
$notes = strlen($item->notes) > 4 ? $item->notes : $item->product_key;
|
||||
|
||||
return [
|
||||
'quantity' => $item->quantity,
|
||||
'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor),
|
||||
'notes' => $this->invitation->company->markdown_enabled ? DesignHelpers::parseMarkdownToHtml($item->notes) : $item->notes,
|
||||
'notes' => $this->invitation->company->markdown_enabled ? DesignHelpers::parseMarkdownToHtml($notes) : $notes,
|
||||
'line_total' => Number::formatMoney($item->line_total, $this->entity->client ?: $this->entity->vendor),
|
||||
];
|
||||
});
|
||||
@ -268,6 +271,7 @@ class PdfSlot extends Component
|
||||
if ($this->invitation instanceof InvoiceInvitation) {
|
||||
return 'invoice';
|
||||
} elseif ($this->invitation instanceof QuoteInvitation) {
|
||||
$this->is_quote = true;
|
||||
return 'quote';
|
||||
} elseif ($this->invitation instanceof CreditInvitation) {
|
||||
return 'credit';
|
||||
|
@ -47,11 +47,11 @@ class MatchBankTransactions implements ShouldQueue
|
||||
|
||||
private array $input;
|
||||
|
||||
protected Company $company;
|
||||
protected ?Company $company;
|
||||
|
||||
public Invoice $invoice;
|
||||
|
||||
private BankTransaction $bt;
|
||||
private ?BankTransaction $bt;
|
||||
|
||||
private $categories;
|
||||
|
||||
@ -78,8 +78,6 @@ class MatchBankTransactions implements ShouldQueue
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
@ -108,10 +108,12 @@ class ProcessBankTransactions implements ShouldQueue
|
||||
$at = new AccountTransformer();
|
||||
$account = $at->transform($account_summary);
|
||||
|
||||
$this->bank_integration->balance = $account['current_balance'];
|
||||
$this->bank_integration->currency = $account['account_currency'];
|
||||
$this->bank_integration->save();
|
||||
|
||||
if($account[0]['current_balance']) {
|
||||
$this->bank_integration->balance = $account['current_balance'];
|
||||
$this->bank_integration->currency = $account['account_currency'];
|
||||
$this->bank_integration->save();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
|
@ -52,7 +52,7 @@ class CompanyTaxRate implements ShouldQueue
|
||||
|
||||
/** State must be calculated else default to the company state for taxes */
|
||||
if(array_key_exists($this->company->settings->state, USStates::get())) {
|
||||
$calculated_state = $this->company->setting->state;
|
||||
$calculated_state = $this->company->settings->state;
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -2,21 +2,19 @@
|
||||
|
||||
namespace App\Jobs\Invoice;
|
||||
|
||||
use App\Jobs\Entity\CreateEntityPdf;
|
||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InjectSignature implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var App\Models\Invoice|App\Models\Quote
|
||||
* @var \App\Models\Invoice | \App\Models\Quote | \App\Models\Credit | \App\Models\PurchaseOrder
|
||||
*/
|
||||
public $entity;
|
||||
|
||||
@ -25,17 +23,26 @@ class InjectSignature implements ShouldQueue
|
||||
*/
|
||||
public $signature;
|
||||
|
||||
public $contact_id;
|
||||
|
||||
public $ip;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param $entity
|
||||
* @param string $signature
|
||||
*/
|
||||
public function __construct($entity, string $signature)
|
||||
public function __construct($entity, $contact_id, string $signature, ?string $ip)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
$this->contact_id = $contact_id;
|
||||
|
||||
$this->signature = $signature;
|
||||
|
||||
$this->ip = $ip;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,20 +52,31 @@ class InjectSignature implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$invitation = $this->entity->invitations->whereNotNull('signature_base64')->first();
|
||||
$invitation = false;
|
||||
|
||||
if($this->entity instanceof PurchaseOrder){
|
||||
$invitation = $this->entity->invitations()->where('vendor_contact_id', $this->contact_id)->first();
|
||||
|
||||
if(!$invitation)
|
||||
$invitation = $this->entity->invitations->first();
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$invitation = $this->entity->invitations()->where('client_contact_id', $this->contact_id)->first();
|
||||
|
||||
if(!$invitation)
|
||||
$invitation = $this->entity->invitations->first();
|
||||
}
|
||||
|
||||
if (! $invitation) {
|
||||
return;
|
||||
}
|
||||
|
||||
$invitation->signature_base64 = $this->signature;
|
||||
$invitation->signature_date = now();
|
||||
$invitation->signature_ip = $this->ip;
|
||||
$invitation->save();
|
||||
|
||||
$this->entity->refresh()->service()->touchPdf(true);
|
||||
|
||||
// if($this->entity instanceof PurchaseOrder)
|
||||
// (new CreatePurchaseOrderPdf($invitation))->handle();
|
||||
// else
|
||||
// (new CreateEntityPdf($invitation))->handle();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace App\Models;
|
||||
|
||||
use App\Utils\Number;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\Activity
|
||||
@ -302,161 +303,120 @@ class Activity extends StaticModel
|
||||
'backup',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function getHashedIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return self::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function backup()
|
||||
{
|
||||
return $this->hasOne(Backup::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function history()
|
||||
{
|
||||
return $this->hasOne(Backup::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function user()
|
||||
public function user() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function contact()
|
||||
{
|
||||
return $this->belongsTo(ClientContact::class, 'client_contact_id', 'id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(Client::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function invoice()
|
||||
{
|
||||
return $this->belongsTo(Invoice::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function recurring_invoice()
|
||||
{
|
||||
return $this->belongsTo(RecurringInvoice::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function credit()
|
||||
{
|
||||
return $this->belongsTo(Credit::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function quote()
|
||||
{
|
||||
return $this->belongsTo(Quote::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function subscription()
|
||||
{
|
||||
return $this->belongsTo(Subscription::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function payment()
|
||||
{
|
||||
return $this->belongsTo(Payment::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function expense()
|
||||
{
|
||||
return $this->belongsTo(Expense::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function recurring_expense()
|
||||
{
|
||||
return $this->belongsTo(RecurringExpense::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function purchase_order()
|
||||
{
|
||||
return $this->belongsTo(PurchaseOrder::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function vendor_contact()
|
||||
{
|
||||
return $this->belongsTo(VendorContact::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function task()
|
||||
{
|
||||
return $this->belongsTo(Task::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
|
@ -50,12 +50,6 @@ class BankAccount extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'bank_id',
|
||||
'app_version',
|
||||
|
@ -31,30 +31,35 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio
|
||||
* @property-read mixed $hashed_id
|
||||
* @property string $number
|
||||
* @property int $company_id
|
||||
* @property int $id
|
||||
* @property \App\Models\Company $company
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel|Illuminate\Database\Eloquent\Relations\BelongsTo|\Awobaz\Compoships\Database\Eloquent\Relations\BelongsTo|\App\Models\Company company()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel|Illuminate\Database\Eloquent\Relations\HasMany|BaseModel orderBy()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel with()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel with($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel newModelQuery($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel newQuery($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude(array $excludeable)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scopeExclude()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel find()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereIn()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel where()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scopeExclude($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel find($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereIn($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel where($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel count()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel create()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel insert()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel create($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel insert($query)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel service()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereHas()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel orderBy($column, $direction)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel invitations()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel createInvitations()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereHas($query)
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation | \App\Models\CreditInvitation | \App\Models\QuoteInvitation | \App\Models\RecurringInvoiceInvitation> $invitations
|
||||
* @property-read int|null $invitations_count
|
||||
*
|
||||
* @method \App\Models\Company company()
|
||||
* @method int companyId()
|
||||
* @method createInvitations()
|
||||
* @method Builder|static exclude($columns)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder exclude(array $columns)
|
||||
* @mixin \Eloquent
|
||||
|
@ -11,21 +11,26 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\GatewayType;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\DataMapper\FeesAndLimits;
|
||||
use App\Models\Traits\Excludable;
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\DataMapper\FeesAndLimits;
|
||||
use App\Models\Presenters\ClientPresenter;
|
||||
use App\Models\Traits\Excludable;
|
||||
use App\Services\Client\ClientService;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\Translation\HasLocalePreference;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Services\Client\ClientService;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use App\Models\Presenters\ClientPresenter;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||
use App\Libraries\Currency\Conversion\CurrencyApi;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Contracts\Translation\HasLocalePreference;
|
||||
|
||||
/**
|
||||
* App\Models\Client
|
||||
@ -65,6 +70,7 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property string|null $shipping_postal_code
|
||||
* @property int|null $shipping_country_id
|
||||
* @property object|null $settings
|
||||
* @property object|null $group_settings
|
||||
* @property bool $is_deleted
|
||||
* @property int|null $group_settings_id
|
||||
* @property string|null $vat_number
|
||||
@ -114,68 +120,12 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
|
||||
* @property-read int|null $tasks_count
|
||||
* @property-read \App\Models\User $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel company()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client exclude($columns)
|
||||
* @method static \Database\Factories\ClientFactory factory($count = null, $state = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client filter(\App\Filters\QueryFilters $filters)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereAddress1($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereAddress2($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereAssignedUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereBalance($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereClientHash($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCompanyId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCountryId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCreditBalance($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCustomValue1($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCustomValue2($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCustomValue3($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereCustomValue4($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereGroupSettingsId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIdNumber($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIndustryId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIsDeleted($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereLastLogin($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereLogo($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereNumber($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePaidToDate($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePhone($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePostalCode($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePrivateNotes($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePublicNotes($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereSettings($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingAddress1($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingAddress2($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingCity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingCountryId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingPostalCode($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereShippingState($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereSizeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereState($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereVatNumber($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereWebsite($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client withoutTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client with()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client where()
|
||||
* @property string $payment_balance
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client wherePaymentBalance($value)
|
||||
* @property mixed $tax_data
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereTaxData($value)
|
||||
* @property int $is_tax_exempt
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIsTaxExempt($value)
|
||||
|
||||
* @property int $has_valid_vat_number
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
@ -357,62 +307,62 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
return $this->hasMany(Activity::class)->take(50)->orderBy('id', 'desc');
|
||||
}
|
||||
|
||||
public function contacts()
|
||||
public function contacts() :HasMany
|
||||
{
|
||||
return $this->hasMany(ClientContact::class)->orderBy('is_primary', 'desc');
|
||||
}
|
||||
|
||||
public function primary_contact()
|
||||
public function primary_contact():HasMany
|
||||
{
|
||||
return $this->hasMany(ClientContact::class)->where('is_primary', true);
|
||||
}
|
||||
|
||||
public function company()
|
||||
public function company() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function user()
|
||||
public function user() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function assigned_user()
|
||||
public function assigned_user() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_user_id', 'id')->withTrashed();
|
||||
}
|
||||
|
||||
public function country()
|
||||
public function country() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Country::class);
|
||||
}
|
||||
|
||||
public function invoices()
|
||||
public function invoices() :HasMany
|
||||
{
|
||||
return $this->hasMany(Invoice::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function quotes()
|
||||
public function quotes() :HasMany
|
||||
{
|
||||
return $this->hasMany(Quote::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function tasks()
|
||||
public function tasks() :HasMany
|
||||
{
|
||||
return $this->hasMany(Task::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function payments()
|
||||
public function payments() :HasMany
|
||||
{
|
||||
return $this->hasMany(Payment::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function recurring_invoices()
|
||||
public function recurring_invoices() :HasMany
|
||||
{
|
||||
return $this->hasMany(RecurringInvoice::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function recurring_expenses()
|
||||
public function recurring_expenses() :HasMany
|
||||
{
|
||||
return $this->hasMany(RecurringExpense::class)->withTrashed();
|
||||
}
|
||||
@ -422,12 +372,12 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
return $this->belongsTo(Country::class, 'shipping_country_id', 'id');
|
||||
}
|
||||
|
||||
public function system_logs()
|
||||
public function system_logs() :HasMany
|
||||
{
|
||||
return $this->hasMany(SystemLog::class)->take(50)->orderBy('id', 'desc');
|
||||
}
|
||||
|
||||
public function timezone()
|
||||
public function timezone() :Timezone
|
||||
{
|
||||
return Timezone::find($this->getSetting('timezone_id'));
|
||||
}
|
||||
@ -445,17 +395,17 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
})->first();
|
||||
}
|
||||
|
||||
public function industry()
|
||||
public function industry() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Industry::class);
|
||||
}
|
||||
|
||||
public function size()
|
||||
public function size() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Size::class);
|
||||
}
|
||||
|
||||
public function locale()
|
||||
public function locale() :string
|
||||
{
|
||||
if (! $this->language()) {
|
||||
return 'en';
|
||||
@ -526,7 +476,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
* @param string $setting The Setting parameter
|
||||
* @return mixed The setting requested
|
||||
*/
|
||||
public function getSetting($setting)
|
||||
public function getSetting($setting) :mixed
|
||||
{
|
||||
/*Client Settings*/
|
||||
if ($this->settings && property_exists($this->settings, $setting) && isset($this->settings->{$setting})) {
|
||||
@ -556,7 +506,6 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
|
||||
return '';
|
||||
|
||||
// throw new \Exception("Settings corrupted", 1);
|
||||
}
|
||||
|
||||
public function getSettingEntity($setting)
|
||||
@ -582,12 +531,12 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
throw new \Exception('Could not find a settings object', 1);
|
||||
}
|
||||
|
||||
public function documents()
|
||||
public function documents() :MorphMany
|
||||
{
|
||||
return $this->morphMany(Document::class, 'documentable');
|
||||
}
|
||||
|
||||
public function group_settings()
|
||||
public function group_settings() :BelongsTo
|
||||
{
|
||||
return $this->belongsTo(GroupSetting::class);
|
||||
}
|
||||
@ -710,7 +659,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
}
|
||||
}
|
||||
|
||||
public function getCurrencyCode()
|
||||
public function getCurrencyCode(): string
|
||||
{
|
||||
if ($this->currency()) {
|
||||
return $this->currency()->code;
|
||||
@ -751,51 +700,51 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
})->first()->locale;
|
||||
}
|
||||
|
||||
public function backup_path()
|
||||
public function backup_path() :string
|
||||
{
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/backups';
|
||||
}
|
||||
|
||||
public function invoice_filepath($invitation)
|
||||
public function invoice_filepath($invitation) :string
|
||||
{
|
||||
$contact_key = $invitation->contact->contact_key;
|
||||
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/invoices/';
|
||||
}
|
||||
public function e_invoice_filepath($invitation)
|
||||
public function e_invoice_filepath($invitation) :string
|
||||
{
|
||||
$contact_key = $invitation->contact->contact_key;
|
||||
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/e_invoice/';
|
||||
}
|
||||
|
||||
public function quote_filepath($invitation)
|
||||
public function quote_filepath($invitation) :string
|
||||
{
|
||||
$contact_key = $invitation->contact->contact_key;
|
||||
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/quotes/';
|
||||
}
|
||||
|
||||
public function credit_filepath($invitation)
|
||||
public function credit_filepath($invitation) :string
|
||||
{
|
||||
$contact_key = $invitation->contact->contact_key;
|
||||
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/credits/';
|
||||
}
|
||||
|
||||
public function recurring_invoice_filepath($invitation)
|
||||
public function recurring_invoice_filepath($invitation) :string
|
||||
{
|
||||
$contact_key = $invitation->contact->contact_key;
|
||||
|
||||
return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/recurring_invoices/';
|
||||
}
|
||||
|
||||
public function company_filepath()
|
||||
public function company_filepath() :string
|
||||
{
|
||||
return $this->company->company_key.'/';
|
||||
}
|
||||
|
||||
public function document_filepath()
|
||||
public function document_filepath() :string
|
||||
{
|
||||
return $this->company->company_key.'/documents/';
|
||||
}
|
||||
@ -820,10 +769,13 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
$defaults['public_notes'] = $this->public_notes;
|
||||
}
|
||||
|
||||
$exchange_rate = new CurrencyApi();
|
||||
$defaults['exchange_rate'] = 1/$exchange_rate->exchangeRate($this->getSetting('currency_id'), $this->company->settings->currency_id);
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
public function timezone_offset()
|
||||
public function timezone_offset() :int
|
||||
{
|
||||
$offset = 0;
|
||||
|
||||
@ -853,7 +805,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
];
|
||||
}
|
||||
|
||||
public function translate_entity()
|
||||
public function translate_entity() :string
|
||||
{
|
||||
return ctrans('texts.client');
|
||||
}
|
||||
|
@ -130,59 +130,8 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Client> $client
|
||||
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ClientContact extends Authenticatable implements HasLocalePreference
|
||||
|
@ -37,29 +37,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property-read \App\Models\GatewayType|null $gateway_type
|
||||
* @property-read mixed $hashed_id
|
||||
* @property-read \App\Models\User $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel company()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel exclude($columns)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereClientId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereCompanyGatewayId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereCompanyId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereGatewayCustomerReference($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereGatewayTypeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereIsDefault($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereIsDeleted($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereMeta($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereRoutingNumber($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ClientGatewayToken withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ClientGatewayToken extends BaseModel
|
||||
|
@ -393,17 +393,17 @@ class Company extends BaseModel
|
||||
return $this->morphMany(Document::class, 'documentable');
|
||||
}
|
||||
|
||||
public function schedulers()
|
||||
public function schedulers() :HasMany
|
||||
{
|
||||
return $this->hasMany(Scheduler::class);
|
||||
}
|
||||
|
||||
public function task_schedulers() //alias for schedulers
|
||||
public function task_schedulers() :HasMany
|
||||
{
|
||||
return $this->hasMany(Scheduler::class);
|
||||
}
|
||||
|
||||
public function all_documents()
|
||||
public function all_documents() :HasMany
|
||||
{
|
||||
return $this->hasMany(Document::class);
|
||||
}
|
||||
@ -413,22 +413,22 @@ class Company extends BaseModel
|
||||
return self::class;
|
||||
}
|
||||
|
||||
public function ledger()
|
||||
public function ledger() :HasMany
|
||||
{
|
||||
return $this->hasMany(CompanyLedger::class);
|
||||
}
|
||||
|
||||
public function bank_integrations()
|
||||
public function bank_integrations() :HasMany
|
||||
{
|
||||
return $this->hasMany(BankIntegration::class);
|
||||
}
|
||||
|
||||
public function bank_transactions()
|
||||
public function bank_transactions() :HasMany
|
||||
{
|
||||
return $this->hasMany(BankTransaction::class);
|
||||
}
|
||||
|
||||
public function bank_transaction_rules()
|
||||
public function bank_transaction_rules() :HasMany
|
||||
{
|
||||
return $this->hasMany(BankTransactionRule::class);
|
||||
}
|
||||
@ -443,7 +443,7 @@ class Company extends BaseModel
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
public function client_contacts()
|
||||
public function client_contacts() :HasMany
|
||||
{
|
||||
return $this->hasMany(ClientContact::class)->withTrashed();
|
||||
}
|
||||
@ -453,27 +453,27 @@ class Company extends BaseModel
|
||||
return $this->hasManyThrough(User::class, CompanyUser::class, 'company_id', 'id', 'id', 'user_id')->withTrashed();
|
||||
}
|
||||
|
||||
public function expense_categories()
|
||||
public function expense_categories() :HasMany
|
||||
{
|
||||
return $this->hasMany(ExpenseCategory::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function subscriptions()
|
||||
public function subscriptions() :HasMany
|
||||
{
|
||||
return $this->hasMany(Subscription::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function purchase_orders()
|
||||
public function purchase_orders() :HasMany
|
||||
{
|
||||
return $this->hasMany(PurchaseOrder::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function task_statuses()
|
||||
public function task_statuses() :HasMany
|
||||
{
|
||||
return $this->hasMany(TaskStatus::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function clients()
|
||||
public function clients() :HasMany
|
||||
{
|
||||
return $this->hasMany(Client::class)->withTrashed();
|
||||
}
|
||||
@ -481,12 +481,12 @@ class Company extends BaseModel
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function tasks()
|
||||
public function tasks() :HasMany
|
||||
{
|
||||
return $this->hasMany(Task::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function webhooks()
|
||||
public function webhooks() :HasMany
|
||||
{
|
||||
return $this->hasMany(Webhook::class);
|
||||
}
|
||||
@ -494,7 +494,7 @@ class Company extends BaseModel
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function projects()
|
||||
public function projects() :HasMany
|
||||
{
|
||||
return $this->hasMany(Project::class)->withTrashed();
|
||||
}
|
||||
@ -502,17 +502,17 @@ class Company extends BaseModel
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function vendors()
|
||||
public function vendors() :HasMany
|
||||
{
|
||||
return $this->hasMany(Vendor::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function all_activities()
|
||||
public function all_activities() :HasMany
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
|
||||
public function activities()
|
||||
public function activities() :HasMany
|
||||
{
|
||||
return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(50);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property int|null $update_details
|
||||
* @property int $is_deleted
|
||||
* @property string $config
|
||||
* @property object $fees_and_limits
|
||||
* @property mixed $fees_and_limits
|
||||
* @property string|null $custom_value1
|
||||
* @property string|null $custom_value2
|
||||
* @property string|null $custom_value3
|
||||
@ -232,7 +232,8 @@ class CompanyGateway extends BaseModel
|
||||
/* This is the public entry point into the payment superclass */
|
||||
public function driver(Client $client = null)
|
||||
{
|
||||
$class = static::driver_class();
|
||||
// $class = static::driver_class();
|
||||
$class = self::driver_class();
|
||||
|
||||
if (!$class) {
|
||||
return false;
|
||||
@ -343,10 +344,10 @@ class CompanyGateway extends BaseModel
|
||||
return ! empty($this->getConfigField('enable_pay_pal'));
|
||||
}
|
||||
|
||||
public function feesEnabled()
|
||||
{
|
||||
return floatval($this->fee_amount) || floatval($this->fee_percent);
|
||||
}
|
||||
// public function feesEnabled()
|
||||
// {
|
||||
// return floatval($this->fee_amount) || floatval($this->fee_percent);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns the current test mode of the gateway.
|
||||
|
@ -53,7 +53,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|CompanyToken whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|CompanyToken withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|CompanyToken withoutTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|CompanyToken with()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class CompanyToken extends BaseModel
|
||||
|
@ -180,7 +180,6 @@ class Gateway extends StaticModel
|
||||
GatewayType::SEPA => ['refund' => false, 'token_billing' => true, 'webhooks' => [' ']],
|
||||
GatewayType::INSTANT_BANK_PAY => ['refund' => false, 'token_billing' => true, 'webhooks' => [' ']],
|
||||
];
|
||||
break;
|
||||
case 58:
|
||||
return [
|
||||
GatewayType::HOSTED_PAGE => ['refund' => false, 'token_billing' => false, 'webhooks' => [' ']], // Razorpay
|
||||
@ -190,6 +189,20 @@ class Gateway extends StaticModel
|
||||
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], // Forte
|
||||
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => [' ']],
|
||||
];
|
||||
case 60:
|
||||
return [
|
||||
GatewayType::PAYPAL => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::VENMO => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::SEPA => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::BANCONTACT => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::EPS => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::MYBANK => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::PAYLATER => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false],
|
||||
// GatewayType::SOFORT => ['refund' => false, 'token_billing' => false],
|
||||
]; //Paypal
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
@ -29,17 +29,6 @@ namespace App\Models;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|GatewayType whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|GatewayType whereName($value)
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class GatewayType extends StaticModel
|
||||
@ -94,6 +83,14 @@ class GatewayType extends StaticModel
|
||||
|
||||
const BACS = 24;
|
||||
|
||||
const VENMO = 25;
|
||||
|
||||
const MERCADOPAGO = 26;
|
||||
|
||||
const MYBANK = 27;
|
||||
|
||||
const PAYLATER = 28;
|
||||
|
||||
public function gateway()
|
||||
{
|
||||
return $this->belongsTo(Gateway::class);
|
||||
@ -153,9 +150,17 @@ class GatewayType extends StaticModel
|
||||
return ctrans('texts.fpx');
|
||||
case self::KLARNA:
|
||||
return ctrans('texts.klarna');
|
||||
case self::VENMO:
|
||||
return ctrans('texts.payment_type_Venmo');
|
||||
case self::MERCADOPAGO:
|
||||
return ctrans('texts.mercado_pago');
|
||||
case self::MYBANK:
|
||||
return ctrans('texts.mybank');
|
||||
case self::PAYLATER:
|
||||
return ctrans('texts.paypal_paylater');
|
||||
default:
|
||||
return ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,6 @@ class PaymentTerm extends BaseModel
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['num_days'];
|
||||
|
||||
public function getNumDays()
|
||||
|
@ -25,8 +25,6 @@ class CompanyPresenter extends EntityPresenter
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
$settings = $this->entity->settings;
|
||||
|
||||
return $this->settings->name ?: ctrans('texts.untitled_account');
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ class InvoicePresenter extends EntityPresenter
|
||||
$properties->itemized_receipt[] = $this->itemRbits($item);
|
||||
}
|
||||
|
||||
$data = new stdClass();
|
||||
$data = new \stdClass();
|
||||
$data->receive_time = time();
|
||||
$data->type = 'transaction_details';
|
||||
$data->source = 'user';
|
||||
@ -64,7 +64,7 @@ class InvoicePresenter extends EntityPresenter
|
||||
|
||||
public function itemRbits($item)
|
||||
{
|
||||
$data = new stdClass();
|
||||
$data = new \stdClass();
|
||||
$data->description = $item->notes;
|
||||
$data->item_price = floatval($item->cost);
|
||||
$data->quantity = floatval($item->quantity);
|
||||
|
@ -106,12 +106,6 @@ class Project extends BaseModel
|
||||
use PresentableTrait;
|
||||
use Filterable;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'client_id',
|
||||
|
@ -22,13 +22,13 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio
|
||||
* @property-read mixed $id
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel company()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel exclude($columns)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel find()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel with()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel withTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel findOrFail()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newModelQuery($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newQuery($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel query($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel find($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel with($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel withTrashed($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel findOrFail($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class StaticModel extends Model
|
||||
|
@ -98,6 +98,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User where($column, $value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAcceptedTermsVersion($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAccountId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAvatar($value)
|
||||
@ -336,13 +337,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
return $this->getCompany();
|
||||
}
|
||||
|
||||
// private function setCompanyByGuard()
|
||||
// {
|
||||
// if (Auth::guard('contact')->check()) {
|
||||
// $this->setCompany(auth()->user()->client->company);
|
||||
// }
|
||||
// }
|
||||
|
||||
public function company_users()
|
||||
{
|
||||
return $this->hasMany(CompanyUser::class)->withTrashed();
|
||||
|
@ -88,7 +88,7 @@ class ClientObserver
|
||||
{
|
||||
|
||||
/** Monitor postal code changes for US based clients for tax calculations */
|
||||
if($client->getOriginal('postal_code') != $client->postal_code && $client->country_id == 840 && $client->company->calculate_taxes && !$client->company->account->isFreeHostedClient()) {
|
||||
if(($client->getOriginal('shipping_postal_code') != $client->shipping_postal_code || $client->getOriginal('postal_code') != $client->postal_code) && $client->country_id == 840 && $client->company->calculate_taxes && !$client->company->account->isFreeHostedClient()) {
|
||||
UpdateTaxData::dispatch($client, $client->company);
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,9 @@ use App\Models\Subscription;
|
||||
class SubscriptionObserver
|
||||
{
|
||||
/**
|
||||
* Handle the billing_subscription "created" event.
|
||||
* Handle the subscription "created" event.
|
||||
*
|
||||
* @param Subscription $billing_subscription
|
||||
* @param Subscription $subscription
|
||||
* @return void
|
||||
*/
|
||||
public function created(Subscription $subscription)
|
||||
@ -27,9 +27,9 @@ class SubscriptionObserver
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the billing_subscription "updated" event.
|
||||
* Handle the subscription "updated" event.
|
||||
*
|
||||
* @param Subscription $billing_subscription
|
||||
* @param Subscription $subscription
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Subscription $subscription)
|
||||
@ -38,9 +38,9 @@ class SubscriptionObserver
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the billing_subscription "deleted" event.
|
||||
* Handle the subscription "deleted" event.
|
||||
*
|
||||
* @param Subscription $billing_subscription
|
||||
* @param Subscription $subscription
|
||||
* @return void
|
||||
*/
|
||||
public function deleted(Subscription $subscription)
|
||||
@ -49,9 +49,9 @@ class SubscriptionObserver
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the billing_subscription "restored" event.
|
||||
* Handle the subscription "restored" event.
|
||||
*
|
||||
* @param Subscription $billing_subscription
|
||||
* @param Subscription $subscription
|
||||
* @return void
|
||||
*/
|
||||
public function restored(Subscription $subscription)
|
||||
@ -60,9 +60,9 @@ class SubscriptionObserver
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the billing_subscription "force deleted" event.
|
||||
* Handle the subscription "force deleted" event.
|
||||
*
|
||||
* @param Subscription $billing_subscription
|
||||
* @param Subscription $subscription
|
||||
* @return void
|
||||
*/
|
||||
public function forceDeleted(Subscription $subscription)
|
||||
|
432
app/PaymentDrivers/PayPalRestPaymentDriver.php
Normal file
432
app/PaymentDrivers/PayPalRestPaymentDriver.php
Normal file
@ -0,0 +1,432 @@
|
||||
<?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\PaymentDrivers;
|
||||
|
||||
use Omnipay\Omnipay;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\SystemLog;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\PaymentType;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PayPalRestPaymentDriver extends BaseDriver
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
public $token_billing = false;
|
||||
|
||||
public $can_authorise_credit_card = false;
|
||||
|
||||
private $omnipay_gateway;
|
||||
|
||||
private float $fee = 0;
|
||||
|
||||
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL;
|
||||
|
||||
private string $api_endpoint_url = '';
|
||||
|
||||
private string $paypal_payment_method = '';
|
||||
|
||||
private array $funding_options = [
|
||||
3 => 'paypal',
|
||||
1 => 'card',
|
||||
25 => 'venmo',
|
||||
9 => 'sepa',
|
||||
12 => 'bancontact',
|
||||
17 => 'eps',
|
||||
15 => 'giropay',
|
||||
13 => 'ideal',
|
||||
26 => 'mercadopago',
|
||||
27 => 'mybank',
|
||||
28 => 'paylater',
|
||||
16 => 'p24',
|
||||
7 => 'sofort'
|
||||
];
|
||||
|
||||
|
||||
public function gatewayTypes()
|
||||
{
|
||||
|
||||
$funding_options = [];
|
||||
|
||||
foreach ($this->company_gateway->fees_and_limits as $key => $value) {
|
||||
if ($value->is_enabled) {
|
||||
$funding_options[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $funding_options;
|
||||
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPaymentMethod($payment_method_id)
|
||||
{
|
||||
if(!$payment_method_id)
|
||||
return $this;
|
||||
|
||||
$this->paypal_payment_method = $this->funding_options[$payment_method_id];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function authorizeView($payment_method)
|
||||
{
|
||||
// PayPal doesn't support direct authorization.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function authorizeResponse($request)
|
||||
{
|
||||
// PayPal doesn't support direct authorization.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function processPaymentView($data)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
$data['gateway'] = $this;
|
||||
|
||||
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
||||
$this->payment_hash->save();
|
||||
|
||||
$data['client_id'] = $this->company_gateway->getConfigField('clientId');
|
||||
$data['token'] = $this->getClientToken();
|
||||
$data['order_id'] = $this->createOrder($data);
|
||||
$data['funding_options'] = $this->paypal_payment_method;
|
||||
|
||||
return render('gateways.paypal.pay', $data);
|
||||
|
||||
}
|
||||
|
||||
private function getFundingOptions():string
|
||||
{
|
||||
|
||||
$enums = [
|
||||
3 => 'paypal',
|
||||
1 => 'card',
|
||||
25 => 'venmo',
|
||||
// 9 => 'sepa',
|
||||
// 12 => 'bancontact',
|
||||
// 17 => 'eps',
|
||||
// 15 => 'giropay',
|
||||
// 13 => 'ideal',
|
||||
// 26 => 'mercadopago',
|
||||
// 27 => 'mybank',
|
||||
// 28 => 'paylater',
|
||||
// 16 => 'p24',
|
||||
// 7 => 'sofort'
|
||||
];
|
||||
|
||||
$funding_options = '';
|
||||
|
||||
foreach($this->company_gateway->fees_and_limits as $key => $value) {
|
||||
|
||||
if($value->is_enabled) {
|
||||
|
||||
$funding_options .=$enums[$key].',';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rtrim($funding_options, ',');
|
||||
|
||||
}
|
||||
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
|
||||
$response = json_decode($request['gateway_response'], true);
|
||||
|
||||
if($response['status'] == 'COMPLETED' && isset($response['purchase_units'])){
|
||||
|
||||
$data = [
|
||||
'payment_type' => PaymentType::PAYPAL,
|
||||
'amount' => $response['purchase_units'][0]['amount']['value'],
|
||||
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
|
||||
'gateway_type_id' => GatewayType::PAYPAL,
|
||||
];
|
||||
|
||||
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $response, 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $response],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
|
||||
throw new PaymentFailed('Payment failed. Please try again.', 401);
|
||||
}
|
||||
}
|
||||
|
||||
private function getClientToken(): string
|
||||
{
|
||||
|
||||
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
|
||||
|
||||
if($r->successful())
|
||||
return $r->json()['client_token'];
|
||||
|
||||
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
|
||||
|
||||
}
|
||||
|
||||
private function createOrder(array $data): string
|
||||
{
|
||||
|
||||
$_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'];
|
||||
|
||||
}
|
||||
|
||||
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = [])
|
||||
{
|
||||
$r = Http::withToken($this->omnipay_gateway->getToken())
|
||||
->withHeaders($this->getHeaders($headers))
|
||||
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
|
||||
|
||||
if($r->successful())
|
||||
return $r;
|
||||
|
||||
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
|
||||
|
||||
}
|
||||
|
||||
private function getHeaders(array $headers = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'Accept' => 'application/json',
|
||||
'Content-type' => 'application/json',
|
||||
'Accept-Language' => 'en_US',
|
||||
], $headers);
|
||||
}
|
||||
|
||||
/*
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
$this->initializeOmnipayGateway();
|
||||
|
||||
$response = $this->omnipay_gateway
|
||||
->completePurchase(['amount' => $this->payment_hash->data->amount, 'currency' => $this->client->getCurrencyCode()])
|
||||
->send();
|
||||
|
||||
if ($response->isCancelled() && $this->client->getSetting('enable_client_portal')) {
|
||||
return redirect()->route('client.invoices.index')->with('warning', ctrans('texts.status_cancelled'));
|
||||
} elseif ($response->isCancelled() && !$this->client->getSetting('enable_client_portal')) {
|
||||
redirect()->route('client.invoices.show', ['invoice' => $this->payment_hash->fee_invoice])->with('warning', ctrans('texts.status_cancelled'));
|
||||
}
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
$data = [
|
||||
'payment_method' => $response->getData()['TOKEN'],
|
||||
'payment_type' => PaymentType::PAYPAL,
|
||||
'amount' => $this->payment_hash->data->amount,
|
||||
'transaction_reference' => $response->getTransactionReference(),
|
||||
'gateway_type_id' => GatewayType::PAYPAL,
|
||||
];
|
||||
|
||||
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => (array) $response->getData(), 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
||||
}
|
||||
|
||||
if (! $response->isSuccessful()) {
|
||||
$data = $response->getData();
|
||||
|
||||
$this->sendFailureMail($response->getMessage() ?: '');
|
||||
|
||||
$message = [
|
||||
'server_response' => $data['L_LONGMESSAGE0'],
|
||||
'data' => $this->payment_hash->data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
||||
throw new PaymentFailed($response->getMessage(), $response->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function generatePaymentDetails(array $data)
|
||||
{
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
|
||||
// $this->fee = $this->feeCalc($invoice, $data['total']['amount_with_fee']);
|
||||
|
||||
return [
|
||||
'currency' => $this->client->getCurrencyCode(),
|
||||
'transactionType' => 'Purchase',
|
||||
'clientIp' => request()->getClientIp(),
|
||||
// 'amount' => round(($data['total']['amount_with_fee'] + $this->fee),2),
|
||||
'amount' => round($data['total']['amount_with_fee'], 2),
|
||||
'returnUrl' => route('client.payments.response', [
|
||||
'company_gateway_id' => $this->company_gateway->id,
|
||||
'payment_hash' => $this->payment_hash->hash,
|
||||
'payment_method_id' => GatewayType::PAYPAL,
|
||||
]),
|
||||
'cancelUrl' => $this->client->company->domain()."/client/invoices/{$invoice->hashed_id}",
|
||||
'description' => implode(',', collect($this->payment_hash->data->invoices)
|
||||
->map(function ($invoice) {
|
||||
return sprintf('%s: %s', ctrans('texts.invoice_number'), $invoice->invoice_number);
|
||||
})->toArray()),
|
||||
'transactionId' => $this->payment_hash->hash.'-'.time(),
|
||||
'ButtonSource' => 'InvoiceNinja_SP',
|
||||
'solutionType' => 'Sole',
|
||||
];
|
||||
}
|
||||
|
||||
public function generatePaymentItems(array $data)
|
||||
{
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
|
||||
$items = [];
|
||||
|
||||
$items[] = new Item([
|
||||
'name' => ' ',
|
||||
'description' => ctrans('texts.invoice_number').'# '.$invoice->number,
|
||||
'price' => $data['total']['amount_with_fee'],
|
||||
'quantity' => 1,
|
||||
]);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
private function feeCalc($invoice, $invoice_total)
|
||||
{
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
$invoice = $invoice->fresh();
|
||||
|
||||
$balance = floatval($invoice->balance);
|
||||
|
||||
$_updated_invoice = $invoice->service()->addGatewayFee($this->company_gateway, GatewayType::PAYPAL, $invoice_total)->save();
|
||||
|
||||
if (floatval($_updated_invoice->balance) > $balance) {
|
||||
$fee = floatval($_updated_invoice->balance) - $balance;
|
||||
|
||||
$this->payment_hash->fee_total = $fee;
|
||||
$this->payment_hash->save();
|
||||
|
||||
return $fee;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -165,6 +165,7 @@ class BaseRepository
|
||||
|
||||
if (! $model->id) {
|
||||
$company_defaults = $client->setCompanyDefaults($data, lcfirst($resource));
|
||||
$data['exchange_rate'] = $company_defaults['exchange_rate'];
|
||||
$model->uses_inclusive_taxes = $client->getSetting('inclusive_taxes');
|
||||
$data = array_merge($company_defaults, $data);
|
||||
}
|
||||
|
@ -175,8 +175,11 @@ class InstantPayment
|
||||
}
|
||||
|
||||
if ($this->request->has('signature') && ! is_null($this->request->signature) && ! empty($this->request->signature)) {
|
||||
$invoices->each(function ($invoice) {
|
||||
InjectSignature::dispatch($invoice, $this->request->signature);
|
||||
|
||||
$contact_id = auth()->guard('contact')->user() ? auth()->guard('contact')->user()->id : null;
|
||||
|
||||
$invoices->each(function ($invoice) use($contact_id) {
|
||||
InjectSignature::dispatch($invoice, $contact_id, $this->request->signature, request()->getClientIp());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,9 @@ class InvoiceService
|
||||
* Sets the exchange rate on the invoice if the client currency
|
||||
* is different to the company currency.
|
||||
*/
|
||||
public function setExchangeRate()
|
||||
public function setExchangeRate($force = false)
|
||||
{
|
||||
if ($this->invoice->exchange_rate != 1) {
|
||||
if ($this->invoice->exchange_rate != 1 || $force) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -11,22 +11,17 @@
|
||||
|
||||
namespace App\Services\Quote;
|
||||
|
||||
use App\Events\Quote\QuoteWasMarkedSent;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Webhook;
|
||||
use App\Utils\Ninja;
|
||||
use Carbon\Carbon;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Client;
|
||||
use App\Models\Webhook;
|
||||
use App\Events\Quote\QuoteWasMarkedSent;
|
||||
|
||||
class MarkSent
|
||||
{
|
||||
private $client;
|
||||
|
||||
private $quote;
|
||||
|
||||
public function __construct($client, $quote)
|
||||
public function __construct(private Client $client, private Quote $quote)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->quote = $quote;
|
||||
}
|
||||
|
||||
public function run()
|
||||
@ -38,9 +33,9 @@ class MarkSent
|
||||
|
||||
$this->quote->markInvitationsSent();
|
||||
|
||||
if ($this->quote->due_date != '' || $this->quote->client->getSetting('valid_until') == '') {
|
||||
if ($this->quote->due_date != '' || $this->client->getSetting('valid_until') == '') {
|
||||
} else {
|
||||
$this->quote->due_date = Carbon::parse($this->quote->date)->addDays($this->quote->client->getSetting('valid_until'));
|
||||
$this->quote->due_date = Carbon::parse($this->quote->date)->addDays($this->client->getSetting('valid_until'));
|
||||
}
|
||||
|
||||
$this->quote
|
||||
|
@ -19,7 +19,6 @@ use App\Models\Invoice;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use League\Csv\Writer;
|
||||
|
||||
@ -33,6 +32,8 @@ class ARSummaryReport extends BaseExport
|
||||
|
||||
public Client $client;
|
||||
|
||||
private float $total = 0;
|
||||
|
||||
public array $report_keys = [
|
||||
'client_name',
|
||||
'client_number',
|
||||
@ -101,7 +102,7 @@ class ARSummaryReport extends BaseExport
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return [
|
||||
$row = [
|
||||
$this->client->present()->name(),
|
||||
$this->client->number,
|
||||
$this->client->id_number,
|
||||
@ -111,7 +112,12 @@ class ARSummaryReport extends BaseExport
|
||||
$this->getAgingAmount('90'),
|
||||
$this->getAgingAmount('120'),
|
||||
$this->getAgingAmount('120+'),
|
||||
Number::formatMoney($this->total, $this->client),
|
||||
];
|
||||
|
||||
$this->total = 0;
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
private function getCurrent(): string
|
||||
@ -128,6 +134,8 @@ class ARSummaryReport extends BaseExport
|
||||
})
|
||||
->sum('balance');
|
||||
|
||||
$this->total += $amount;
|
||||
|
||||
return Number::formatMoney($amount, $this->client);
|
||||
|
||||
}
|
||||
@ -153,6 +161,8 @@ class ARSummaryReport extends BaseExport
|
||||
->whereBetween('due_date', [$to, $from])
|
||||
->sum('balance');
|
||||
|
||||
$this->total += $amount;
|
||||
|
||||
return Number::formatMoney($amount, $this->client);
|
||||
}
|
||||
|
||||
|
@ -366,7 +366,7 @@ class ProfitLoss
|
||||
|
||||
$csv->insertOne(['--------------------']);
|
||||
|
||||
$csv->insertOne([ctrans('texts.total_revenue'), Number::formatMoney($this->income, $this->company)]);
|
||||
$csv->insertOne([ctrans('texts.total_revenue'), Number::formatMoney($this->income - $this->income_taxes, $this->company)]);
|
||||
|
||||
//total taxes
|
||||
|
||||
@ -386,7 +386,7 @@ class ProfitLoss
|
||||
$csv->insertOne([ctrans('texts.total_taxes'), Number::formatMoney(array_sum(array_column($this->expense_break_down, 'tax')), $this->company)]);
|
||||
|
||||
$csv->insertOne(['--------------------']);
|
||||
$csv->insertOne([ctrans('texts.total_profit'), Number::formatMoney($this->income - array_sum(array_column($this->expense_break_down, 'total')), $this->company)]);
|
||||
$csv->insertOne([ctrans('texts.total_profit'), Number::formatMoney($this->income - $this->income_taxes - array_sum(array_column($this->expense_break_down, 'total'))- array_sum(array_column($this->expense_break_down, 'tax')), $this->company)]);
|
||||
|
||||
//net profit
|
||||
|
||||
|
@ -68,6 +68,8 @@ trait Inviteable
|
||||
|
||||
$qr = $writer->writeString($this->getPaymentLink(), 'utf-8');
|
||||
|
||||
return "<div>$qr</div>";
|
||||
|
||||
return "<svg class='pqrcode' viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
||||
<rect x='0' y='0' width='100%' height='100%' />{$qr}</svg>";
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ trait MakesHash
|
||||
return $hashids->encode($value);
|
||||
}
|
||||
|
||||
public function decodePrimaryKey($value) : string
|
||||
public function decodePrimaryKey($value)
|
||||
{
|
||||
try {
|
||||
$hashids = new Hashids(config('ninja.hash_salt'), 10);
|
||||
@ -71,7 +71,6 @@ trait MakesHash
|
||||
|
||||
if (! is_array($decoded_array)) {
|
||||
throw new \Exception('Invalid Primary Key');
|
||||
//response()->json(['error'=>'Invalid primary key'], 400);
|
||||
}
|
||||
|
||||
return $decoded_array[0];
|
||||
|
@ -84,6 +84,7 @@ return [
|
||||
'password' => 'password',
|
||||
'stripe' => env('STRIPE_KEYS', ''),
|
||||
'paypal' => env('PAYPAL_KEYS', ''),
|
||||
'paypal_rest' => env('PAYPAL_REST_KEYS', ''),
|
||||
'authorize' => env('AUTHORIZE_KEYS', ''),
|
||||
'checkout' => env('CHECKOUT_KEYS', ''),
|
||||
'travis' => env('TRAVIS', false),
|
||||
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Gateway;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
if(!Gateway::find(60))
|
||||
{
|
||||
|
||||
$fields = new \stdClass;
|
||||
$fields->clientId = "";
|
||||
$fields->secret = "";
|
||||
$fields->testMode = false;
|
||||
|
||||
$paypal = new Gateway;
|
||||
$paypal->id = 60;
|
||||
$paypal->name = 'PayPal REST';
|
||||
$paypal->key = '80af24a6a691230bbec33e930ab40665';
|
||||
$paypal->provider = 'PayPal_Rest';
|
||||
$paypal->is_offsite = false;
|
||||
$paypal->fields = \json_encode($fields);
|
||||
$paypal->visible = 1;
|
||||
$paypal->site_url = 'https://www.paypal.com/';
|
||||
$paypal->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -83,6 +83,7 @@ class PaymentLibrariesSeeder extends Seeder
|
||||
['id' => 57, 'name' => 'Square', 'provider' => 'Square', 'is_offsite' => false, 'sort_order' => 21, 'key' => '65faab2ab6e3223dbe848b1686490baz', 'fields' => '{"accessToken":"","applicationId":"","locationId":"","testMode":false}'],
|
||||
['id' => 58, 'name' => 'Razorpay', 'provider' => 'Razorpay', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9', 'fields' => '{"apiKey":"","apiSecret":""}'],
|
||||
['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'],
|
||||
['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'],
|
||||
];
|
||||
|
||||
foreach ($gateways as $gateway) {
|
||||
@ -99,7 +100,7 @@ class PaymentLibrariesSeeder extends Seeder
|
||||
|
||||
Gateway::query()->update(['visible' => 0]);
|
||||
|
||||
Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59])->update(['visible' => 1]);
|
||||
Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60])->update(['visible' => 1]);
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
Gateway::whereIn('id', [20])->update(['visible' => 0]);
|
||||
|
@ -882,7 +882,7 @@ $LANG = array(
|
||||
'custom_invoice_charges_helps' => 'Add a text input to the invoice create/edit page and include the charge in the invoice subtotals.',
|
||||
'token_expired' => 'Validation token was expired. Please try again.',
|
||||
'invoice_link' => 'Invoice Link',
|
||||
'button_confirmation_message' => 'Confirm your email.',
|
||||
'button_confirmation_message' => 'Klik for at bekræfte din e-mail.',
|
||||
'confirm' => 'Confirm',
|
||||
'email_preferences' => 'Email Preferences',
|
||||
'created_invoices' => 'Successfully created :count invoice(s)',
|
||||
@ -1179,7 +1179,7 @@ $LANG = array(
|
||||
'plan_started' => 'Plan Started',
|
||||
'plan_expires' => 'Plan Expires',
|
||||
|
||||
'white_label_button' => 'Purchase White Label',
|
||||
'white_label_button' => 'Køb whitelabel licens',
|
||||
|
||||
'pro_plan_year_description' => 'One year enrollment in the Invoice Ninja Pro Plan.',
|
||||
'pro_plan_month_description' => 'One month enrollment in the Invoice Ninja Pro Plan.',
|
||||
@ -1853,7 +1853,7 @@ $LANG = array(
|
||||
'task' => 'Opgave',
|
||||
'contact_name' => 'Kontakt navn',
|
||||
'city_state_postal' => 'By/Postnummer',
|
||||
'postal_city' => 'Postal/City',
|
||||
'postal_city' => 'Postnr og by',
|
||||
'custom_field' => 'Brugerdefineret felt',
|
||||
'account_fields' => 'Virksomheds felter',
|
||||
'facebook_and_twitter' => 'Facebook og Twitter',
|
||||
@ -2060,8 +2060,8 @@ $LANG = array(
|
||||
'group_when_sorted' => 'Group Sort',
|
||||
'group_dates_by' => 'Gruppér datoer efter',
|
||||
'year' => 'År',
|
||||
'view_statement' => 'View Statement',
|
||||
'statement' => 'Statement',
|
||||
'view_statement' => 'Se kontoudskrift',
|
||||
'statement' => 'Kontoudtog',
|
||||
'statement_date' => 'Statement Date',
|
||||
'mark_active' => 'Markér som aktiv',
|
||||
'send_automatically' => 'Send automatisk',
|
||||
@ -4972,7 +4972,7 @@ $LANG = array(
|
||||
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
|
||||
'xinvoice_no_buyers_reference' => "No buyer's reference given",
|
||||
'xinvoice_online_payment' => 'The invoice needs to be paid online via the provided link',
|
||||
'pre_payment' => 'Pre Payment',
|
||||
'pre_payment' => 'Forudbetaling',
|
||||
'number_of_payments' => 'Number of payments',
|
||||
'number_of_payments_helper' => 'The number of times this payment will be made',
|
||||
'pre_payment_indefinitely' => 'Continue until cancelled',
|
||||
@ -5113,6 +5113,16 @@ $LANG = array(
|
||||
'item_tax_rate2' => 'Item Tax Rate 2',
|
||||
'item_tax_rate3' => 'Item Tax Rate 3',
|
||||
'buy_price' => 'Buy Price',
|
||||
'country_Macedonia' => 'Macedonia',
|
||||
'admin_initiated_payments' => 'Admin Initiated Payments',
|
||||
'admin_initiated_payments_help' => 'Support entering a payment in the admin portal without an invoice',
|
||||
'paid_date' => 'Paid Date',
|
||||
'downloaded_entities' => 'An email will be sent with the PDFs',
|
||||
'lang_French - Swiss' => 'French - Swiss',
|
||||
'currency_swazi_lilangeni' => 'Swazi Lilangeni',
|
||||
'income' => 'Income',
|
||||
'amount_received_help' => 'Enter a value here if the total amount received was MORE than the invoice amount, or when recording a payment with no invoices. Otherwise this field should be left blank.',
|
||||
'vendor_phone' => 'Vendor Phone',
|
||||
);
|
||||
|
||||
|
||||
|
@ -5124,6 +5124,17 @@ $LANG = array(
|
||||
'income' => 'Income',
|
||||
'amount_received_help' => 'Enter a value here if the total amount received was MORE than the invoice amount, or when recording a payment with no invoices. Otherwise this field should be left blank.',
|
||||
'vendor_phone' => 'Vendor Phone',
|
||||
'mercado_pago' => 'Mercado Pago',
|
||||
'mybank' => 'MyBank',
|
||||
'paypal_paylater' => 'Pay in 4',
|
||||
'paid_date' => 'Paid Date',
|
||||
'district' => 'District',
|
||||
'region' => 'Region',
|
||||
'county' => 'County',
|
||||
'tax_details' => 'Tax Details',
|
||||
'activity_10_online' => ':contact entered payment :payment for invoice :invoice for :client',
|
||||
'activity_10_manual' => ':user entered payment :payment for invoice :invoice for :client',
|
||||
'default_payment_type' => 'Default Payment Type',
|
||||
);
|
||||
|
||||
|
||||
|
@ -4947,8 +4947,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'click_to_variables' => 'Cliquez ici pour voir toutes les variables',
|
||||
'ship_to' => 'Livrer à',
|
||||
'stripe_direct_debit_details' => 'Veuillez transférer dans le compte bancaire indiqué ci-dessus.',
|
||||
'branch_name' => 'Nom de branche',
|
||||
'branch_code' => 'Code de branche',
|
||||
'branch_name' => 'Nom de succursale',
|
||||
'branch_code' => 'Code de succursale',
|
||||
'bank_name' => 'Nom de l\'institution bancaire',
|
||||
'bank_code' => 'Code de l\'institution bancaire',
|
||||
'bic' => 'BIC',
|
||||
@ -5114,7 +5114,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'lang_French - Swiss' => 'Français - Suisse',
|
||||
'currency_swazi_lilangeni' => 'Lilangeni Eswatinien',
|
||||
'income' => 'Revenu',
|
||||
|
||||
'amount_received_help' => 'Saisissez une valeur si le montant total reçu été PLUS élevé que le montant de la facture, ou lors de l\'enregistrement d\'un paiement sans factures. Sinon, ce champ devrait rester vide.',
|
||||
'vendor_phone' => 'Téléphone du fournisseur',
|
||||
);
|
||||
|
||||
|
||||
|
@ -4569,7 +4569,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'activity_134' => ':user restored purchase order :purchase_order',
|
||||
'activity_135' => ':user emailed purchase order :purchase_order',
|
||||
'activity_136' => ':contact viewed purchase order :purchase_order',
|
||||
'purchase_order_subject' => 'New Purchase Order :number from :account',
|
||||
'purchase_order_subject' => 'Novo pedido de compra',
|
||||
'purchase_order_message' => 'To view your purchase order for :amount, click the link below.',
|
||||
'view_purchase_order' => 'View Purchase Order',
|
||||
'purchase_orders_backup_subject' => 'Your purchase orders are ready for download',
|
||||
@ -4639,7 +4639,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'purchase_order_footer' => 'Purchase Order Footer',
|
||||
'require_purchase_order_signature' => 'Purchase Order Signature',
|
||||
'require_purchase_order_signature_help' => 'Require vendor to provide their signature.',
|
||||
'new_purchase_order' => 'New Purchase Order',
|
||||
'new_purchase_order' => 'Novo pedido de compra',
|
||||
'edit_purchase_order' => 'Edit Purchase Order',
|
||||
'created_purchase_order' => 'Successfully created purchase order',
|
||||
'updated_purchase_order' => 'Successfully updated purchase order',
|
||||
@ -5108,6 +5108,16 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'item_tax_rate2' => 'Item Tax Rate 2',
|
||||
'item_tax_rate3' => 'Item Tax Rate 3',
|
||||
'buy_price' => 'Buy Price',
|
||||
'country_Macedonia' => 'Macedonia',
|
||||
'admin_initiated_payments' => 'Admin Initiated Payments',
|
||||
'admin_initiated_payments_help' => 'Support entering a payment in the admin portal without an invoice',
|
||||
'paid_date' => 'Paid Date',
|
||||
'downloaded_entities' => 'An email will be sent with the PDFs',
|
||||
'lang_French - Swiss' => 'French - Swiss',
|
||||
'currency_swazi_lilangeni' => 'Swazi Lilangeni',
|
||||
'income' => 'Income',
|
||||
'amount_received_help' => 'Enter a value here if the total amount received was MORE than the invoice amount, or when recording a payment with no invoices. Otherwise this field should be left blank.',
|
||||
'vendor_phone' => 'Vendor Phone',
|
||||
);
|
||||
|
||||
|
||||
|
12
phpstan.neon
12
phpstan.neon
@ -1,19 +1,13 @@
|
||||
includes:
|
||||
- ./vendor/nunomaduro/larastan/extension.neon
|
||||
- phpstan-baseline.neon
|
||||
parameters:
|
||||
treatPhpDocTypesAsCertain: false
|
||||
parallel:
|
||||
jobSize: 10
|
||||
maximumNumberOfProcesses: 1
|
||||
processTimeout: 60.0
|
||||
ignoreErrors:
|
||||
- '#Call to an undefined method .*badMethod\(\)#'
|
||||
- '#Call to an undefined method Illuminate\Database\Eloquent\Builder::exclude#'
|
||||
level: 4
|
||||
paths:
|
||||
- 'app/'
|
||||
excludePaths:
|
||||
- 'vendor/'
|
||||
- 'app/Jobs/Ninja/*'
|
||||
- 'app/Console/Commands/*'
|
||||
- 'app/DataMapper/Analytics/*'
|
||||
universalObjectCratesClasses:
|
||||
- App\DataMapper\Tax\RuleInterface
|
@ -136,10 +136,12 @@ span {
|
||||
<td style="text-align:left; padding-right:10px;" class="text-lg">{{ ctrans('texts.total') }}</td>
|
||||
<td style="text-align:right; padding-right:10px;" class="text-lg">{{ $amount }}</td>
|
||||
</tr>
|
||||
@if(!$is_quote)
|
||||
<tr>
|
||||
<td style="text-align:left; padding-right:10px;" class="text-lg">{{ ctrans('texts.balance') }}</td>
|
||||
<td style="text-align:right; padding-right:10px;" class="text-lg">{{ $balance }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal'])
|
||||
|
||||
@section('gateway_head')
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"
|
||||
/>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_content')
|
||||
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
|
||||
@csrf
|
||||
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
|
||||
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
|
||||
<input type="hidden" name="gateway_response" id="gateway_response">
|
||||
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
|
||||
</form>
|
||||
|
||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||
|
||||
<div id="paypal-button-container" class="paypal-button-container"></div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
<script src="https://www.paypal.com/sdk/js?enable-funding={!! $funding_options !!}&disable-funding=credit&components=buttons,hosted-fields,funding-eligibility&intent=capture&client-id={!! $client_id !!}" data-client-token="{!! $token !!}">
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
paypal.Buttons({
|
||||
|
||||
env: "{{ $gateway->company_gateway->getConfigField('testMode') ? 'sandbox' : 'production' }}",
|
||||
client: {
|
||||
@if($gateway->company_gateway->getConfigField('testMode'))
|
||||
sandbox: "{{ $gateway->company_gateway->getConfigField('clientId') }}"
|
||||
@else
|
||||
production: "{{ $gateway->company_gateway->getConfigField('clientId') }}"
|
||||
@endif
|
||||
},
|
||||
createOrder: function(data, actions) {
|
||||
return "{!! $order_id !!}"
|
||||
},
|
||||
onApprove: function(data, actions) {
|
||||
|
||||
return actions.order.capture().then(function(details) {
|
||||
|
||||
document.getElementById("gateway_response").value =JSON.stringify( details );
|
||||
document.getElementById("server_response").submit();
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
onError: function(err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
}).render('#paypal-button-container');
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
@endpush
|
@ -120,6 +120,108 @@ class ProfitAndLossReportTest extends TestCase
|
||||
$this->account->delete();
|
||||
}
|
||||
|
||||
public function testExpenseResolution()
|
||||
{
|
||||
$this->buildData();
|
||||
|
||||
Expense::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'amount' => 121,
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'uses_inclusive_taxes' => true,
|
||||
'tax_rate1' => 21,
|
||||
'tax_name1' => 'VAT',
|
||||
'calculate_tax_by_amount' => false,
|
||||
'exchange_rate' => 1,
|
||||
]);
|
||||
|
||||
$pl = new ProfitLoss($this->company, $this->payload);
|
||||
$pl->build();
|
||||
|
||||
$expense_breakdown = $pl->getExpenseBreakDown();
|
||||
|
||||
$this->assertEquals(100, array_sum(array_column($expense_breakdown, 'total')));
|
||||
$this->assertEquals(21, array_sum(array_column($expense_breakdown, 'tax')));
|
||||
|
||||
$this->account->delete();
|
||||
|
||||
}
|
||||
|
||||
public function testMultiCurrencyInvoiceIncome()
|
||||
{
|
||||
$this->buildData();
|
||||
|
||||
$settings = ClientSettings::defaults();
|
||||
$settings->currency_id = 2;
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_deleted' => 0,
|
||||
'settings' => $settings
|
||||
]);
|
||||
|
||||
|
||||
$client2 = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_deleted' => 0,
|
||||
]);
|
||||
|
||||
Invoice::factory()->create([
|
||||
'client_id' => $client->id,
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'amount' => 10,
|
||||
'balance' => 10,
|
||||
'status_id' => 2,
|
||||
'total_taxes' => 1,
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'terms' => 'nada',
|
||||
'discount' => 0,
|
||||
'tax_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'uses_inclusive_taxes' => false,
|
||||
'exchange_rate' => 2
|
||||
]);
|
||||
|
||||
Invoice::factory()->create([
|
||||
'client_id' => $client2->id,
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'amount' => 10,
|
||||
'balance' => 10,
|
||||
'status_id' => 2,
|
||||
'total_taxes' => 1,
|
||||
'date' => now()->format('Y-m-d'),
|
||||
'terms' => 'nada',
|
||||
'discount' => 0,
|
||||
'tax_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'uses_inclusive_taxes' => false,
|
||||
'exchange_rate' => 1
|
||||
]);
|
||||
|
||||
|
||||
$pl = new ProfitLoss($this->company, $this->payload);
|
||||
$pl->build();
|
||||
|
||||
$this->assertEquals(13.5, $pl->getIncome());
|
||||
$this->assertEquals(1.5, $pl->getIncomeTaxes());
|
||||
|
||||
$this->account->delete();
|
||||
|
||||
}
|
||||
|
||||
public function testSimpleInvoiceIncome()
|
||||
{
|
||||
$this->buildData();
|
||||
|
@ -70,6 +70,60 @@ class ReportCsvGenerationTest extends TestCase
|
||||
|
||||
public $cu;
|
||||
|
||||
private $all_client_report_keys = ["client.name","client.user","client.assigned_user","client.balance","client.paid_to_date","client.currency_id","client.website","client.private_notes","client.industry_id","client.size_id","client.address1","client.address2","client.city","client.state","client.postal_code","client.country_id","contact.custom_value4","client.shipping_address1","client.shipping_address2","client.shipping_city","client.shipping_state","client.shipping_postal_code","client.shipping_country_id","client.payment_terms","client.vat_number","client.id_number","client.public_notes","client.phone","contact.first_name","contact.last_name","contact.email","contact.phone"];
|
||||
|
||||
private $all_payment_report_keys = [
|
||||
'payment.date',
|
||||
'payment.amount',
|
||||
'payment.refunded',
|
||||
'payment.applied',
|
||||
'payment.transaction_reference',
|
||||
'payment.currency',
|
||||
'payment.exchange_rate',
|
||||
'payment.number',
|
||||
'payment.method',
|
||||
'payment.status',
|
||||
'payment.private_notes',
|
||||
'payment.custom_value1',
|
||||
'payment.custom_value2',
|
||||
'payment.custom_value3',
|
||||
'payment.custom_value4',
|
||||
'payment.user_id',
|
||||
'payment.assigned_user_id'
|
||||
];
|
||||
|
||||
private $all_invoice_report_keys = [
|
||||
'invoice.number',
|
||||
'invoice.amount',
|
||||
'invoice.balance',
|
||||
'invoice.paid_to_date',
|
||||
'invoice.discount',
|
||||
'invoice.po_number',
|
||||
'invoice.date',
|
||||
'invoice.due_date',
|
||||
'invoice.terms',
|
||||
'invoice.footer',
|
||||
'invoice.status',
|
||||
'invoice.public_notes',
|
||||
'invoice.private_notes',
|
||||
'invoice.uses_inclusive_taxes',
|
||||
'invoice.is_amount_discount',
|
||||
'invoice.partial',
|
||||
'invoice.partial_due_date',
|
||||
'invoice.custom_value1',
|
||||
'invoice.custom_value2',
|
||||
'invoice.custom_value3',
|
||||
'invoice.custom_value4',
|
||||
'invoice.custom_surcharge1',
|
||||
'invoice.custom_surcharge2',
|
||||
'invoice.custom_surcharge3',
|
||||
'invoice.custom_surcharge4',
|
||||
'invoice.exchange_rate',
|
||||
'invoice.total_taxes',
|
||||
'invoice.assigned_user_id',
|
||||
'invoice.user_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* start_date - Y-m-d
|
||||
end_date - Y-m-d
|
||||
@ -329,6 +383,32 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('123456', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number'));
|
||||
$this->assertEquals(1000, $this->getFirstValueByColumn($csv, 'Invoice Amount'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/tasks', $data)->assertStatus(200);
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => array_merge(["task.date","task.number"], $this->all_invoice_report_keys),
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/tasks', $data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -474,6 +554,33 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Client Balance'));
|
||||
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Client Paid to Date'));
|
||||
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/payments', $data)->assertStatus(200);
|
||||
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => array_merge(["payment.amount","payment.date"],$this->all_invoice_report_keys),
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/payments', $data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -603,6 +710,17 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount'));
|
||||
$this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date'));
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_payment_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/credits', $data)->assertStatus(200);
|
||||
|
||||
}
|
||||
|
||||
public function testInvoiceCustomColumnsCsvGeneration()
|
||||
@ -625,7 +743,7 @@ class ReportCsvGenerationTest extends TestCase
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount"],
|
||||
'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount","invoice.user"],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
@ -641,6 +759,33 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount'));
|
||||
$this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/invoices', $data)->assertStatus(200);
|
||||
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_payment_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/invoices', $data)->assertStatus(200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testRecurringInvoiceCustomColumnsCsvGeneration()
|
||||
@ -679,6 +824,20 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice Invoice Number'));
|
||||
$this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/recurring_invoices', $data)->assertStatus(200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -745,6 +904,33 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1'));
|
||||
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/invoice_items', $data)->assertStatus(200);
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_payment_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/invoice_items', $data)->assertStatus(200);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -810,6 +996,20 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1'));
|
||||
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/quote_items', $data)->assertStatus(200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -973,6 +1173,20 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number'));
|
||||
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Quote Amount'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/quotes', $data)->assertStatus(200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1104,6 +1318,33 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes'));
|
||||
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
|
||||
$this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/credits', $data)->assertStatus(200);
|
||||
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_payment_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/credits', $data)->assertStatus(200);
|
||||
|
||||
}
|
||||
|
||||
public function testInvoiceCsvGeneration()
|
||||
@ -1364,6 +1605,21 @@ class ReportCsvGenerationTest extends TestCase
|
||||
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
|
||||
$this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'User'));
|
||||
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => $this->all_client_report_keys,
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/expenses', $data)->assertStatus(200);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testExpenseCustomColumnsCsvGeneration()
|
||||
|
Loading…
Reference in New Issue
Block a user