mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-04 02:04:35 -04:00
commit
e18665d1e8
@ -1 +1 @@
|
||||
5.8.48
|
||||
5.8.49
|
@ -13,11 +13,25 @@ namespace App\DataMapper\EDoc;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
use Spatie\LaravelData\Optional;
|
||||
use App\DataMapper\EDoc\FatturaPA\DatiContratto;
|
||||
use App\DataMapper\EDoc\FatturaPA\DatiRicezione;
|
||||
use App\DataMapper\EDoc\FatturaPA\DatiOrdineAcquisto;
|
||||
use App\DataMapper\EDoc\FatturaPA\DatiAnagraficiVettore;
|
||||
|
||||
class FatturaPA extends Data
|
||||
{
|
||||
public string $RegimeFiscale = 'RF01';
|
||||
public string $TipoDocumento = 'TD01';
|
||||
public string $ModalitaPagamento = 'MP01';
|
||||
public string $CondizioniPagamento = 'TP02';
|
||||
public DatiRicezione|Optional $DatiRicezione;
|
||||
public DatiContratto|Optional $DatiContratto;
|
||||
public DatiOrdineAcquisto|Optional $DatiOrdineAcquisto;
|
||||
public DatiAnagraficiVettore|Optional $DatiAnagraficiVettore;
|
||||
|
||||
public function __construct(
|
||||
public string $RegimeFiscale = 'RF01',
|
||||
public string $TipoDocumento = 'TD01',
|
||||
public string $ModalitaPagamento = 'MP01',
|
||||
public string $CondizioniPagamento = 'TP02',
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
||||
|
28
app/DataMapper/EDoc/FatturaPA/DatiAnagraficiVettore.php
Normal file
28
app/DataMapper/EDoc/FatturaPA/DatiAnagraficiVettore.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\EDoc\FatturaPA;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Attributes\WithTransformer;
|
||||
use Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer;
|
||||
|
||||
class DatiAnagraficiVettore extends Data
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
public string $IdFiscaleIVA = '',
|
||||
public string $CodiceFiscale = '',
|
||||
public string $Anagrafica = '',
|
||||
#[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d\TH:i:s.uP')]
|
||||
public \DateTime $DataOraConsegna = new \DateTime(),
|
||||
){}
|
||||
}
|
28
app/DataMapper/EDoc/FatturaPA/DatiContratto.php
Normal file
28
app/DataMapper/EDoc/FatturaPA/DatiContratto.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\EDoc\FatturaPA;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class DatiContratto extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public string $RiferimentoNumeroLinea = '',
|
||||
public string $IdDocumento = '',
|
||||
public string $Data = '',
|
||||
public string $NumItem = '',
|
||||
public string $CodiceCommessaConvenzione = '',
|
||||
public string $CodiceCUP = '',
|
||||
public string $CodiceCIG = '',
|
||||
) {
|
||||
}
|
||||
}
|
28
app/DataMapper/EDoc/FatturaPA/DatiOrdineAcquisto.php
Normal file
28
app/DataMapper/EDoc/FatturaPA/DatiOrdineAcquisto.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\EDoc\FatturaPA;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class DatiOrdineAcquisto extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public string $RiferimentoNumeroLinea = '',
|
||||
public string $IdDocumento = '',
|
||||
public string $Data = '',
|
||||
public string $NumItem = '',
|
||||
public string $CodiceCommessaConvenzione = '',
|
||||
public string $CodiceCUP = '',
|
||||
public string $CodiceCIG = '',
|
||||
) {
|
||||
}
|
||||
}
|
28
app/DataMapper/EDoc/FatturaPA/DatiRicezione.php
Normal file
28
app/DataMapper/EDoc/FatturaPA/DatiRicezione.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\EDoc\FatturaPA;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class DatiRicezione extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public string $RiferimentoNumeroLinea = '',
|
||||
public string $IdDocumento = '',
|
||||
public string $Data = '',
|
||||
public string $NumItem = '',
|
||||
public string $CodiceCommessaConvenzione = '',
|
||||
public string $CodiceCUP = '',
|
||||
public string $CodiceCIG = '',
|
||||
) {
|
||||
}
|
||||
}
|
@ -26,48 +26,4 @@ class EDocSettings extends Data
|
||||
return $this->FatturaPA ??= new FatturaPA();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class DatiAnagraficiVettore extends Data{
|
||||
|
||||
public string $IdFiscaleIVA = '';
|
||||
public string $CodiceFiscale = '';
|
||||
public string $Anagrafica = '';
|
||||
}
|
||||
|
||||
class DatiTrasporto extends Data{
|
||||
public string $DataOraConsegna = ''; //datetime in this format 2017-01-10T16:46:12.000+02:00
|
||||
//public DatiAnagraficiVettore
|
||||
}
|
||||
|
||||
class DatiOrdineAcquisto extends Data{
|
||||
public string $RiferimentoNumeroLinea = '';
|
||||
public string $IdDocumento = '';
|
||||
public string $Data = '';
|
||||
public string $NumItem = '';
|
||||
public string $CodiceCommessaConvenzione = '';
|
||||
public string $CodiceCUP = '';
|
||||
public string $CodiceCIG = '';
|
||||
}
|
||||
|
||||
class DatiContratto extends Data{
|
||||
public string $RiferimentoNumeroLinea = '';
|
||||
public string $IdDocumento = '';
|
||||
public string $Data = '';
|
||||
public string $NumItem = '';
|
||||
public string $CodiceCommessaConvenzione = '';
|
||||
public string $CodiceCUP = '';
|
||||
public string $CodiceCIG = '';
|
||||
}
|
||||
|
||||
class DatiRicezione extends Data{
|
||||
public string $RiferimentoNumeroLinea = '';
|
||||
public string $IdDocumento = '';
|
||||
public string $Data = '';
|
||||
public string $NumItem = '';
|
||||
public string $CodiceCommessaConvenzione = '';
|
||||
public string $CodiceCUP = '';
|
||||
public string $CodiceCIG = '';
|
||||
}
|
@ -235,17 +235,17 @@ class Rule extends BaseRule implements RuleInterface
|
||||
} elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->vat_number) { //eu country / no valid vat
|
||||
if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) {
|
||||
// nlog("eu zone with sales above threshold");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate;
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate ?? 0;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate ?? 0;
|
||||
} else {
|
||||
// nlog("EU with intra-community supply ie DE to DE");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate ?? 0;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate ?? 0;
|
||||
}
|
||||
} else {
|
||||
// nlog("default tax");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate ?? 0;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate ?? 0;
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
103
app/DataProviders/EDocRules.php
Normal file
103
app/DataProviders/EDocRules.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataProviders;
|
||||
|
||||
class EDocRules
|
||||
{
|
||||
// [
|
||||
// "key" => "",
|
||||
// "label" => "",
|
||||
// "type" => "dropdown/date/string/text",
|
||||
// "resource" => "resource.json",
|
||||
// "required" => true,
|
||||
// ]
|
||||
public function rules()
|
||||
{
|
||||
|
||||
return [
|
||||
'FatturaPA' => $this->FatturaPADefaults(),
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function FatturaPADefaults()
|
||||
{
|
||||
return [
|
||||
[
|
||||
"key" => "RegimeFiscale",
|
||||
"label" => "Regime Fiscale",
|
||||
"type" => "dropdown",
|
||||
"resource" => "RegimeFiscale.json",
|
||||
"required" => true,
|
||||
],
|
||||
[
|
||||
"key" => "TipoDocumento",
|
||||
"label" => "Tipo Documento",
|
||||
"type" => "dropdown",
|
||||
"resource" => "TipoDocumento.json",
|
||||
"required" => true,
|
||||
],
|
||||
[
|
||||
"key" => "ModalitaPagamento",
|
||||
"label" => "Modalita Pagamento",
|
||||
"type" => "dropdown",
|
||||
"resource" => "ModalitaPagamento.json",
|
||||
"required" => true,
|
||||
],
|
||||
[
|
||||
"key" => "CondizioniPagamento",
|
||||
"label" => "Condizioni Pagamento",
|
||||
"type" => "dropdown",
|
||||
"resource" => "CondizioniPagamento.json",
|
||||
"required" => true,
|
||||
],
|
||||
[
|
||||
"key" => "DatiRicezione",
|
||||
"label" => "Dati Ricezione",
|
||||
"type" => "dropdown",
|
||||
"resource" => "CondizioniPagamento",
|
||||
"required" => false,
|
||||
"children" => [],
|
||||
],
|
||||
[
|
||||
"key" => "DatiContratto",
|
||||
"label" => "Dati Contratto",
|
||||
"type" => "object",
|
||||
"resource" => "DatiContratto",
|
||||
"required" => false,
|
||||
"children" => [
|
||||
[
|
||||
"key"=> "RiferimentoNumeroLinea",
|
||||
"validation" => [
|
||||
"string","min:1","max:10","required"
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
"key" => "DatiOrdineAcquisto",
|
||||
"label" => "Dati Ordine Acquisto",
|
||||
"type" => "object",
|
||||
"resource" => "DatiOrdineAcquisto",
|
||||
"required" => false,
|
||||
],
|
||||
[
|
||||
"key" => "DatiAnagraficiVettore",
|
||||
"label" => "Dati Anagrafici Vettore",
|
||||
"type" => "object",
|
||||
"resource" => "DatiAnagraficiVettore",
|
||||
"required" => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -207,7 +207,6 @@ class InvoiceController extends Controller
|
||||
|
||||
//format data
|
||||
$invoices->map(function ($invoice) {
|
||||
// $invoice->service()->removeUnpaidGatewayFees();
|
||||
$invoice->balance = $invoice->balance > 0 ? Number::formatValue($invoice->balance, $invoice->client->currency()) : 0;
|
||||
$invoice->partial = $invoice->partial > 0 ? Number::formatValue($invoice->partial, $invoice->client->currency()) : 0;
|
||||
|
||||
|
@ -144,7 +144,6 @@ class TwilioController extends BaseController
|
||||
public function generate2faResetCode(Generate2faRequest $request)
|
||||
{
|
||||
nlog($request->all());
|
||||
nlog($request->headers());
|
||||
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
|
@ -27,12 +27,18 @@ class StoreBankTransactionRuleRequest extends Request
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->user()->can('create', BankTransactionRule::class) && auth()->user()->account->hasFeature(Account::FEATURE_API);
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
return $user->can('create', BankTransactionRule::class) && $user->account->hasFeature(Account::FEATURE_API);
|
||||
;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/* Ensure we have a client name, and that all emails are unique*/
|
||||
$rules = [
|
||||
'name' => 'bail|required|string',
|
||||
@ -45,18 +51,9 @@ class StoreBankTransactionRuleRequest extends Request
|
||||
'applies_to' => 'bail|sometimes|string',
|
||||
];
|
||||
|
||||
if (isset($this->category_id)) {
|
||||
$rules['category_id'] = 'bail|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
}
|
||||
|
||||
if (isset($this->vendor_id)) {
|
||||
$rules['vendor_id'] = 'bail|sometimes|exists:vendors,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
}
|
||||
|
||||
if (isset($this->client_id)) {
|
||||
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
}
|
||||
|
||||
$rules['category_id'] = 'bail|sometimes|exists:expense_categories,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
$rules['vendor_id'] = 'bail|sometimes|exists:vendors,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
@ -94,6 +94,10 @@ class StoreCreditRequest extends Request
|
||||
$input['design_id'] = $this->decodePrimaryKey($input['design_id']);
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
|
@ -86,6 +86,10 @@ class UpdateCreditRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (isset($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
|
@ -93,8 +93,8 @@ class StoreInvoiceRequest extends Request
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0 && isset($input['partial_due_date'])) {
|
||||
$input['partial_due_date'] = '';
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
$input['amount'] = 0;
|
||||
|
@ -91,8 +91,8 @@ class UpdateInvoiceRequest extends Request
|
||||
|
||||
$input['id'] = $this->invoice->id;
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0 && isset($input['partial_due_date'])) {
|
||||
$input['partial_due_date'] = '';
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
|
@ -45,9 +45,9 @@ class UpdatePaymentRequest extends Request
|
||||
'client_id' => ['sometimes', 'bail', Rule::in([$this->payment->client_id])],
|
||||
'number' => ['sometimes', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id)],
|
||||
'invoices' => ['sometimes', 'bail', 'nullable', 'array', new PaymentAppliedValidAmount($this->all())],
|
||||
'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)],
|
||||
'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->payment->client_id)],
|
||||
'invoices.*.amount' => ['sometimes','numeric','min:0'],
|
||||
'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)],
|
||||
'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->payment->client_id)],
|
||||
'credits.*.amount' => ['required', 'bail'],
|
||||
];
|
||||
|
||||
|
@ -79,6 +79,10 @@ class StorePurchaseOrderRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
|
@ -83,6 +83,10 @@ class UpdatePurchaseOrderRequest extends Request
|
||||
|
||||
$input['id'] = $this->purchase_order->id;
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class StoreQuoteRequest extends Request
|
||||
|
||||
$rules = [];
|
||||
|
||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||
$rules['client_id'] = ['required', 'bail', Rule::exists('clients','id')->where('company_id', $user->company()->id)];
|
||||
|
||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||
$rules['documents.*'] = $this->fileValidation();
|
||||
@ -64,12 +64,17 @@ class StoreQuoteRequest extends Request
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date', 'after_or_equal:date'];
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
@ -82,6 +87,19 @@ class StoreQuoteRequest extends Request
|
||||
$input['exchange_rate'] = 1;
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if(!isset($input['date']))
|
||||
$input['date'] = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d');
|
||||
|
||||
if(isset($input['partial_due_date']) && (!isset($input['due_date']) || strlen($input['due_date']) <=1 )) {
|
||||
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
|
||||
$valid_days = ($client && strlen($client->getSetting('valid_until')) >= 1) ? $client->getSetting('valid_until') : 7;
|
||||
$input['due_date'] = \Carbon\Carbon::parse($input['date'])->addDays($valid_days)->format('Y-m-d');
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -56,16 +56,16 @@ class UpdateQuoteRequest extends Request
|
||||
$rules['file'] = $this->fileValidation();
|
||||
}
|
||||
|
||||
|
||||
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)->ignore($this->quote->id)];
|
||||
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->quote->client_id])];
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', 'after_or_equal:date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
@ -89,6 +89,9 @@ class UpdateQuoteRequest extends Request
|
||||
$input['exchange_rate'] = 1;
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
@ -31,14 +31,6 @@ class StoreSetupRequest extends Request
|
||||
/*System*/
|
||||
'url' => 'required',
|
||||
/*Mail driver*/
|
||||
'mail_driver' => 'required',
|
||||
'encryption' => 'required_unless:mail_driver,log',
|
||||
'mail_host' => 'required_unless:mail_driver,log',
|
||||
'mail_username' => 'required_unless:mail_driver,log',
|
||||
'mail_name' => 'required_unless:mail_driver,log',
|
||||
'mail_address' => 'required_unless:mail_driver,log',
|
||||
'mail_password' => 'required_unless:mail_driver,log',
|
||||
/*user registration*/
|
||||
'privacy_policy' => 'required',
|
||||
'terms_of_service' => 'required',
|
||||
'first_name' => 'required',
|
||||
|
@ -137,6 +137,9 @@ class UpdateTaskRequest extends Request
|
||||
$input['time_log'] = json_encode([]);
|
||||
}
|
||||
|
||||
if(isset($input['user']))
|
||||
unset($input['user']);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
|
@ -255,6 +255,9 @@ class BaseImport
|
||||
|
||||
unset($record['']);
|
||||
|
||||
if(!is_array($record))
|
||||
continue;
|
||||
|
||||
try {
|
||||
$entity = $this->transformer->transform($record);
|
||||
|
||||
@ -310,6 +313,11 @@ class BaseImport
|
||||
$count = 0;
|
||||
|
||||
foreach ($data as $key => $record) {
|
||||
|
||||
if(!is_array($record)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$entity = $this->transformer->transform($record);
|
||||
$validator = $this->request_name::runFormRequest($entity);
|
||||
@ -372,6 +380,11 @@ class BaseImport
|
||||
$invoices = $this->groupInvoices($invoices, $invoice_number_key);
|
||||
|
||||
foreach ($invoices as $raw_invoice) {
|
||||
|
||||
if(!is_array($raw_invoice)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$invoice_data = $invoice_transformer->transform($raw_invoice);
|
||||
|
||||
@ -459,6 +472,11 @@ class BaseImport
|
||||
|
||||
foreach ($tasks as $raw_task) {
|
||||
$task_data = [];
|
||||
|
||||
if(!is_array($raw_task)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$task_data = $task_transformer->transform($raw_task);
|
||||
$task_data['user_id'] = $this->company->owner()->id;
|
||||
@ -527,6 +545,11 @@ class BaseImport
|
||||
$invoices = $this->groupInvoices($invoices, $invoice_number_key);
|
||||
|
||||
foreach ($invoices as $raw_invoice) {
|
||||
|
||||
if(!is_array($raw_invoice)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$invoice_data = $invoice_transformer->transform($raw_invoice);
|
||||
$invoice_data['user_id'] = $this->company->owner()->id;
|
||||
@ -742,6 +765,11 @@ class BaseImport
|
||||
$quotes = $this->groupInvoices($quotes, $quote_number_key);
|
||||
|
||||
foreach ($quotes as $raw_quote) {
|
||||
|
||||
if(!is_array($raw_quote)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$quote_data = $quote_transformer->transform($raw_quote);
|
||||
$quote_data['line_items'] = $this->cleanItems(
|
||||
|
@ -232,6 +232,11 @@ class Wave extends BaseImport implements ImportInterface
|
||||
$expenses = $this->groupExpenses($data);
|
||||
|
||||
foreach ($expenses as $raw_expense) {
|
||||
|
||||
if(!is_array($raw_expense)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$expense_data = $expense_transformer->transform($raw_expense);
|
||||
|
||||
|
@ -115,7 +115,7 @@ class BaseTransformer
|
||||
return isset($data[$field]) && $data[$field] ? $data[$field] : null;
|
||||
}
|
||||
|
||||
public function getCurrencyByCode($data, $key = 'client.currency_id')
|
||||
public function getCurrencyByCode(array $data, string $key = 'client.currency_id')
|
||||
{
|
||||
$code = array_key_exists($key, $data) ? $data[$key] : false;
|
||||
|
||||
|
@ -26,6 +26,7 @@ use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class ProcessBankTransactionsYodlee implements ShouldQueue
|
||||
{
|
||||
@ -71,8 +72,8 @@ class ProcessBankTransactionsYodlee implements ShouldQueue
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
//Loop through everything until we are up to date
|
||||
$this->from_date = $this->from_date ?: '2021-01-01';
|
||||
//Loop through everything until we are up to date - improve handling of delayed accounts
|
||||
$this->from_date = $this->from_date ? Carbon::parse($this->from_date)->subWeeks(2)->format('Y-m-d') : '2021-01-01';
|
||||
|
||||
nlog("Yodlee: Processing transactions for account: {$this->bank_integration->account->key}");
|
||||
|
||||
|
@ -61,7 +61,8 @@ class ClientLedgerBalanceUpdate implements ShouldQueue
|
||||
->where('id', '<', $company_ledger->id)
|
||||
->where('client_id', $company_ledger->client_id)
|
||||
->where('company_id', $company_ledger->company_id)
|
||||
->where('balance', '!=', 0)
|
||||
->whereNotNull('balance')
|
||||
// ->where('balance', '!=', 0)
|
||||
->orderBy('id', 'DESC')
|
||||
->first();
|
||||
|
||||
|
@ -23,31 +23,6 @@ class Submit extends Component
|
||||
public function mount()
|
||||
{
|
||||
|
||||
// $request = new \Illuminate\Http\Request([
|
||||
// 'sidebar' => 'hidden',
|
||||
// 'hash' => $this->context['hash'],
|
||||
// 'action' => 'payment',
|
||||
// 'invoices' => [
|
||||
// $this->context['form']['invoice_hashed_id'],
|
||||
// ],
|
||||
// 'payable_invoices' => [
|
||||
// [
|
||||
// 'amount' => $this->context['form']['payable_amount'],
|
||||
// 'invoice_id' => $this->context['form']['invoice_hashed_id'],
|
||||
// ],
|
||||
// ],
|
||||
// 'company_gateway_id' => $this->context['form']['company_gateway_id'],
|
||||
// 'payment_method_id' => $this->context['form']['payment_method_id'],
|
||||
// 'contact_first_name' => $this->context['contact']['first_name'],
|
||||
// 'contact_last_name' => $this->context['contact']['last_name'],
|
||||
// 'contact_email' => $this->context['contact']['email'],
|
||||
// ]);
|
||||
|
||||
// return redirect((new InstantPayment($request))->run());
|
||||
// dd($this->context);
|
||||
|
||||
nlog($this->context);
|
||||
|
||||
$this->dispatch(
|
||||
'purchase.submit',
|
||||
invoice_hashed_id: $this->context['form']['invoice_hashed_id'],
|
||||
|
@ -77,7 +77,7 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property float $amount
|
||||
* @property float $balance
|
||||
* @property float|null $partial
|
||||
* @property string|null $partial_due_date
|
||||
* @property \Carbon\Carbon|null $partial_due_date
|
||||
* @property string|null $last_viewed
|
||||
* @property int|null $created_at
|
||||
* @property int|null $updated_at
|
||||
@ -195,10 +195,10 @@ class Quote extends BaseModel
|
||||
return $this->dateMutator($value);
|
||||
}
|
||||
|
||||
public function getDueDateAttribute($value)
|
||||
{
|
||||
return $value ? $this->dateMutator($value) : null;
|
||||
}
|
||||
// public function getDueDateAttribute($value)
|
||||
// {
|
||||
// return $value ? $this->dateMutator($value) : null;
|
||||
// }
|
||||
|
||||
// public function getPartialDueDateAttribute($value)
|
||||
// {
|
||||
|
@ -166,6 +166,15 @@ class Vendor extends BaseModel
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
|
||||
public function getCurrencyCode(): string
|
||||
{
|
||||
if ($this->currency()) {
|
||||
return $this->currency()->code;
|
||||
}
|
||||
|
||||
return 'USD';
|
||||
}
|
||||
|
||||
public function currency()
|
||||
{
|
||||
$currencies = Cache::get('currencies');
|
||||
|
@ -166,7 +166,10 @@ class PayPalRestPaymentDriver extends BaseDriver
|
||||
$data['gateway_type_id'] = $this->gateway_type_id;
|
||||
$data['currency'] = $this->client->currency()->code;
|
||||
|
||||
return render('gateways.paypal.pay', $data);
|
||||
|
||||
// return render('gateways.paypal.ppcp.card', $data);
|
||||
|
||||
return render('gateways.paypal.pay', $data);
|
||||
|
||||
}
|
||||
|
||||
@ -324,6 +327,65 @@ class PayPalRestPaymentDriver extends BaseDriver
|
||||
|
||||
}
|
||||
|
||||
private function getPaymentSource(): array
|
||||
{
|
||||
|
||||
if($this->gateway_type_id == 1) {
|
||||
|
||||
return [
|
||||
"card" => [
|
||||
"attributes" => [
|
||||
"verification" => [
|
||||
"method" => "SCA_WHEN_REQUIRED", //SCA_ALWAYS
|
||||
],
|
||||
],
|
||||
"name" => $this->client->present()->primary_contact_name(),
|
||||
"email_address" => $this->client->present()->email(),
|
||||
"address" => [
|
||||
"address_line_1" => $this->client->address1,
|
||||
"address_line_2" => $this->client->address2,
|
||||
"admin_area_2" => $this->client->city,
|
||||
"admin_area_1" => $this->client->state,
|
||||
"postal_code" => $this->client->postal_code,
|
||||
"country_code" => $this->client->country->iso_3166_2,
|
||||
],
|
||||
"experience_context" => [
|
||||
"user_action" => "PAY_NOW"
|
||||
],
|
||||
"stored_credential" => [
|
||||
"payment_initiator" => "MERCHANT", //"CUSTOMER" who initiated the transaction?
|
||||
"payment_type" => "UNSCHEDULED",
|
||||
"usage"=> "DERIVED",
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return [
|
||||
"paypal" => [
|
||||
"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_2" => $this->client->city,
|
||||
"admin_area_1" => $this->client->state,
|
||||
"postal_code" => $this->client->postal_code,
|
||||
"country_code" => $this->client->country->iso_3166_2,
|
||||
],
|
||||
"experience_context" => [
|
||||
"user_action" => "PAY_NOW"
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function createOrder(array $data): string
|
||||
{
|
||||
|
||||
@ -338,27 +400,7 @@ class PayPalRestPaymentDriver extends BaseDriver
|
||||
$order = [
|
||||
|
||||
"intent" => "CAPTURE",
|
||||
"payment_source" => [
|
||||
"paypal" => [
|
||||
|
||||
"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_2" => $this->client->city,
|
||||
"admin_area_1" => $this->client->state,
|
||||
"postal_code" => $this->client->postal_code,
|
||||
"country_code" => $this->client->country->iso_3166_2,
|
||||
],
|
||||
"experience_context" => [
|
||||
"user_action" => "PAY_NOW"
|
||||
],
|
||||
],
|
||||
],
|
||||
"payment_source" => $this->getPaymentSource(),
|
||||
"purchase_units" => [
|
||||
[
|
||||
"custom_id" => $this->payment_hash->hash,
|
||||
|
@ -111,7 +111,7 @@ class QuoteTransformer extends EntityTransformer
|
||||
'reminder2_sent' => $quote->reminder2_sent ?: '',
|
||||
'reminder3_sent' => $quote->reminder3_sent ?: '',
|
||||
'reminder_last_sent' => $quote->reminder_last_sent ?: '',
|
||||
'due_date' => $quote->due_date ?: '',
|
||||
'due_date' => $quote->due_date ? $quote->due_date->format('Y-m-d') : '',
|
||||
'terms' => $quote->terms ?: '',
|
||||
'public_notes' => $quote->public_notes ?: '',
|
||||
'private_notes' => $quote->private_notes ?: '',
|
||||
@ -127,7 +127,7 @@ class QuoteTransformer extends EntityTransformer
|
||||
'is_amount_discount' => (bool) ($quote->is_amount_discount ?: false),
|
||||
'footer' => $quote->footer ?: '',
|
||||
'partial' => (float) ($quote->partial ?: 0.0),
|
||||
'partial_due_date' => $quote->partial_due_date ?: '',
|
||||
'partial_due_date' => $quote->partial_due_date ? $quote->partial_due_date->format('Y-m-d') : '',
|
||||
'custom_value1' => (string) $quote->custom_value1 ?: '',
|
||||
'custom_value2' => (string) $quote->custom_value2 ?: '',
|
||||
'custom_value3' => (string) $quote->custom_value3 ?: '',
|
||||
|
@ -101,6 +101,12 @@ class Number
|
||||
if($comma === false) //no comma must be a decimal number already
|
||||
return (float) $value;
|
||||
|
||||
if(!$decimal && substr($value, -3, 1) != ","){
|
||||
$value = $value.".00";
|
||||
}
|
||||
|
||||
$decimal = strpos($value, '.');
|
||||
|
||||
if($decimal < $comma){ //decimal before a comma = euro
|
||||
$value = str_replace(['.',','], ['','.'], $value);
|
||||
return (float) $value;
|
||||
@ -113,6 +119,7 @@ class Number
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a given value based on the clients currency
|
||||
* BACK to a float.
|
||||
@ -228,9 +235,6 @@ class Number
|
||||
$code = $currency->code;
|
||||
$swapSymbol = $currency->swap_currency_symbol;
|
||||
|
||||
// App\Models\Client::country() returns instance of BelongsTo.
|
||||
// App\Models\Company::country() returns record for the country, that's why we check for the instance.
|
||||
|
||||
if ($entity instanceof Company) {
|
||||
$country = $entity->country();
|
||||
} else {
|
||||
|
@ -26,9 +26,7 @@ trait SubscriptionHooker
|
||||
'X-Requested-With' => 'XMLHttpRequest',
|
||||
];
|
||||
|
||||
$post_purchase_rest_method = &$subscription->webhook_configuration['post_purchase_rest_method'];
|
||||
|
||||
if (!isset($subscription->webhook_configuration['post_purchase_url']) && !$post_purchase_rest_method) {
|
||||
if (!isset($subscription->webhook_configuration['post_purchase_url']) && !isset($subscription->webhook_configuration['post_purchase_rest_method'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => env('APP_VERSION', '5.8.48'),
|
||||
'app_tag' => env('APP_TAG', '5.8.48'),
|
||||
'app_version' => env('APP_VERSION', '5.8.49'),
|
||||
'app_tag' => env('APP_TAG', '5.8.49'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -0,0 +1,183 @@
|
||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => ''])
|
||||
|
||||
@section('gateway_head')
|
||||
|
||||
@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_type_id" id="gateway_type_id" value="{{ $gateway_type_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>
|
||||
|
||||
<div id="checkout-form">
|
||||
<!-- Containers for Card Fields hosted by PayPal -->
|
||||
<!-- <div id="card-name-field-container"></div> -->
|
||||
<div id="card-number-field-container"></div>
|
||||
<div class="expcvv" style="display:flex;">
|
||||
<div id="card-expiry-field-container" style="width:50%"></div>
|
||||
<div id="card-cvv-field-container" style="width:50%"></div>
|
||||
</div>
|
||||
<!-- <button id="card-field-submit-button" type="button">
|
||||
{{ ctrans('texts.pay_now') }}
|
||||
</button> -->
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
<link rel="stylesheet" type="text/css" href=https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css />
|
||||
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&components=card-fields" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
|
||||
|
||||
<script>
|
||||
|
||||
const clientId = "{{ $client_id }}";
|
||||
const orderId = "{!! $order_id !!}";
|
||||
|
||||
const cardStyle = {
|
||||
'input': {
|
||||
'font-size': '16px',
|
||||
'font-family': 'courier, monospace',
|
||||
'font-weight': 'lighter',
|
||||
'color': '#ccc',
|
||||
},
|
||||
'.invalid': {
|
||||
'color': 'purple',
|
||||
},
|
||||
'.expcvv': {
|
||||
'display': 'grid',
|
||||
'grid-template-columns': 'auto'
|
||||
}
|
||||
};
|
||||
|
||||
const cardField = paypal.CardFields({
|
||||
// style: cardStyle,
|
||||
client: clientId,
|
||||
createOrder: function(data, actions) {
|
||||
return orderId;
|
||||
},
|
||||
onApprove: function(data, actions) {
|
||||
|
||||
var errorDetail = Array.isArray(data.details) && data.details[0];
|
||||
if (errorDetail && ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED'].includes(errorDetail.issue)) {
|
||||
return actions.restart();
|
||||
}
|
||||
|
||||
console.log("on approve");
|
||||
console.log(data);
|
||||
console.log(actions);
|
||||
|
||||
document.getElementById("gateway_response").value = JSON.stringify( data );
|
||||
document.getElementById("server_response").submit();
|
||||
|
||||
|
||||
},
|
||||
onCancel: function() {
|
||||
|
||||
window.location.href = "/client/invoices/";
|
||||
},
|
||||
// onError: function(error) {
|
||||
|
||||
|
||||
|
||||
// document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
|
||||
// document.getElementById('errors').hidden = false;
|
||||
|
||||
// // document.getElementById("gateway_response").value = error;
|
||||
// // document.getElementById("server_response").submit();
|
||||
// },
|
||||
onClick: function (){
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Render each field after checking for eligibility
|
||||
if (cardField.isEligible()) {
|
||||
|
||||
const numberField = cardField.NumberField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
numberField.render("#card-number-field-container");
|
||||
|
||||
const cvvField = cardField.CVVField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
cvvField.render("#card-cvv-field-container");
|
||||
|
||||
const expiryField = cardField.ExpiryField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
expiryField.render("#card-expiry-field-container");
|
||||
|
||||
document.getElementById("pay-now").addEventListener('click', (e) => {
|
||||
|
||||
document.getElementById('errors').textContent = '';
|
||||
document.getElementById('errors').hidden = true;
|
||||
|
||||
document.getElementById('pay-now').disabled = true;
|
||||
document.querySelector('#pay-now > svg').classList.remove('hidden');
|
||||
document.querySelector('#pay-now > svg').classList.add('justify-center');
|
||||
document.querySelector('#pay-now > span').classList.add('hidden');
|
||||
|
||||
cardField.submit().then((response) => {
|
||||
console.log("then");
|
||||
console.log(response);
|
||||
// lets goooo
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
console.log(error);
|
||||
|
||||
document.getElementById('pay-now').disabled = false;
|
||||
document.querySelector('#pay-now > svg').classList.add('hidden');
|
||||
document.querySelector('#pay-now > span').classList.remove('hidden');
|
||||
|
||||
if(error.message == 'INVALID_NUMBER'){
|
||||
document.getElementById('errors').textContent = "{{ ctrans('texts.invalid_card_number') }}";
|
||||
}
|
||||
else if(error.message == 'INVALID_CVV') {
|
||||
document.getElementById('errors').textContent = "{{ ctrans('texts.invalid_cvv') }}";
|
||||
}
|
||||
else if(error.message == 'INVALID_EXPIRY') {
|
||||
document.getElementById('errors').textContent = "{{ ctrans('texts.invalid_cvv') }}";
|
||||
}
|
||||
|
||||
document.getElementById('errors').hidden = false;
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@endpush
|
@ -12,16 +12,17 @@
|
||||
|
||||
namespace Tests\Feature\Bank;
|
||||
|
||||
use App\Factory\BankIntegrationFactory;
|
||||
use App\Factory\BankTransactionFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Models\BankTransaction;
|
||||
use Tests\TestCase;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Factory\BankIntegrationFactory;
|
||||
use App\Factory\BankTransactionFactory;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class BankTransactionTest extends TestCase
|
||||
{
|
||||
|
@ -54,12 +54,99 @@ class QuoteTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testQuoteDueDateInjectionValidationLayer()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'partial_due_date' => now()->format('Y-m-d'),
|
||||
'partial' => 1,
|
||||
'amount' => 20,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/quotes', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
// nlog($arr);
|
||||
|
||||
$this->assertNotEmpty($arr['data']['due_date']);
|
||||
|
||||
}
|
||||
|
||||
public function testNullDueDates()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'due_date' => '',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/quotes', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEmpty($arr['data']['due_date']);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson('/api/v1/quotes/'.$arr['data']['id'], $arr['data']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEmpty($arr['data']['due_date']);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testNonNullDueDates()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'due_date' => now()->addDays(10),
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/quotes', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertNotEmpty($arr['data']['due_date']);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson('/api/v1/quotes/'.$arr['data']['id'], $arr['data']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertNotEmpty($arr['data']['due_date']);
|
||||
|
||||
}
|
||||
|
||||
public function testPartialDueDates()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'due_date' => now()->format('Y-m-d'),
|
||||
'due_date' => now()->addDay()->format('Y-m-d'),
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
@ -73,6 +160,41 @@ class QuoteTest extends TestCase
|
||||
|
||||
$this->assertNotNull($arr['data']['due_date']);
|
||||
$this->assertEmpty($arr['data']['partial_due_date']);
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'due_date' => now()->addDay()->format('Y-m-d'),
|
||||
'partial' => 1,
|
||||
'partial_due_date' => now()->format('Y-m-d'),
|
||||
'amount' => 20,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/quotes', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals(now()->addDay()->format('Y-m-d'), $arr['data']['due_date']);
|
||||
$this->assertEquals(now()->format('Y-m-d'), $arr['data']['partial_due_date']);
|
||||
$this->assertEquals(1, $arr['data']['partial']);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson('/api/v1/quotes/'.$arr['data']['id'], $arr['data']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals(now()->addDay()->format('Y-m-d'), $arr['data']['due_date']);
|
||||
$this->assertEquals(now()->format('Y-m-d'), $arr['data']['partial_due_date']);
|
||||
$this->assertEquals(1, $arr['data']['partial']);
|
||||
|
||||
}
|
||||
|
||||
public function testQuoteToProjectConversion2()
|
||||
|
@ -28,15 +28,17 @@ class NumberTest extends TestCase
|
||||
"22000.76" =>"22 000,76",
|
||||
"22000.76" =>"22.000,76",
|
||||
"22000.76" =>"22,000.76",
|
||||
"22000" =>"22 000",
|
||||
"22000" =>"22,000",
|
||||
"2201" => "2,201",
|
||||
"22001" =>"22 001",
|
||||
"22002" =>"22,002",
|
||||
"37123" => "37,123",
|
||||
"22" =>"22.000",
|
||||
"22000" =>"22.000,",
|
||||
"22000.76" =>"22000.76",
|
||||
"22000.76" =>"22000,76",
|
||||
"1022000.76" =>"1.022.000,76",
|
||||
"1022000.76" =>"1,022,000.76",
|
||||
// "1000000" =>"1,000,000",
|
||||
"1000000" =>"1,000,000",
|
||||
// "1000000" =>"1.000.000",
|
||||
"1022000.76" =>"1022000.76",
|
||||
"1022000.76" =>"1022000,76",
|
||||
@ -48,7 +50,7 @@ class NumberTest extends TestCase
|
||||
"1" =>"1.00",
|
||||
"1" =>"1,00",
|
||||
"423545" =>"423545 €",
|
||||
// "423545" =>"423,545 €",
|
||||
"423545" =>"423,545 €",
|
||||
// "423545" =>"423.545 €",
|
||||
"1" =>"1,00 €",
|
||||
"1.02" =>"€ 1.02",
|
||||
@ -58,7 +60,8 @@ class NumberTest extends TestCase
|
||||
"1000.02" =>"1.000,02 EURO",
|
||||
"9.975" => "9.975",
|
||||
"9975" => "9.975,",
|
||||
"9975" => "9.975,00"
|
||||
"9975" => "9.975,00",
|
||||
// "0.571" => "0,571",
|
||||
];
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user