diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index dd850c742042..04bb33545951 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -13,8 +13,8 @@ jobs:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
- operating-system: ['ubuntu-20.04', 'ubuntu-22.04']
- php-versions: ['8.1','8.2']
+ operating-system: ['ubuntu-22.04','ubuntu-24.04']
+ php-versions: ['8.2']
phpunit-versions: ['latest']
ci_node_total: [ 8 ]
ci_node_index: [ 0, 1, 2, 3, 4, 5, 6, 7]
@@ -95,14 +95,15 @@ jobs:
- name: Get Composer Cache Directory
id: composer-cache
run: |
- echo "::set-output name=dir::$(composer config cache-files-dir)"
- - uses: actions/cache@v3
+ echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+ - uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.php }}-composer-
+
- name: Install composer dependencies
run: |
composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }}
diff --git a/VERSION.txt b/VERSION.txt
index 5a2fcfc24009..01959b109939 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.8.57
+5.8.57
\ No newline at end of file
diff --git a/app/Console/Commands/EDocLint.php b/app/Console/Commands/EDocLint.php
deleted file mode 100644
index 8604dd2edaa8..000000000000
--- a/app/Console/Commands/EDocLint.php
+++ /dev/null
@@ -1,69 +0,0 @@
-classes as $class)
- {
-
- $provider = new $class();
-
- foreach($provider as $key => $value) {
-
- $json = json_encode($provider->{$key}, JSON_PRETTY_PRINT);
- Storage::disk('local')->put($key.'.json', $json);
-
- }
-
- }
-
- }
-}
diff --git a/app/DataProviders/FACT1.php b/app/DataProviders/FACT1.php
new file mode 100644
index 000000000000..3572e15253bb
--- /dev/null
+++ b/app/DataProviders/FACT1.php
@@ -0,0 +1,24 @@
+ "Regime ordinario",
- "RF02" => "Regime dei contribuenti minimi (art. 1,c.96-117, L. 244/2007)",
- "RF04" => "Agricoltura e attività connesse e pesca (artt. 34 e 34-bis, D.P.R. 633/1972)",
- "RF05" => "Vendita sali e tabacchi (art. 74, c.1, D.P.R. 633/1972)",
- "RF06" => "Commercio dei fiammiferi (art. 74, c.1, D.P.R. 633/1972)",
- "RF07" => "Editoria (art. 74, c.1, D.P.R. 633/1972)",
- "RF08" => "Gestione di servizi di telefonia pubblica (art. 74, c.1, D.P.R. 633/1972)" ,
- "RF09" => "Rivendita di documenti di trasporto pubblico e di sosta (art. 74, c.1, D.P.R. 633/1972)" ,
- "RF10" => "Intrattenimenti, giochi e altre attività di cui alla tariffa allegata al D.P.R. 640/72 (art. 74, c.6, D.P.R. 633/1972)" ,
- "RF11" => "Agenzie di viaggi e turismo (art. 74-ter, D.P.R. 633/1972)" ,
- "RF12" => "Agriturismo (art. 5, c.2, L. 413/1991)" ,
- "RF13" => "Vendite a domicilio (art. 25-bis, c.6, D.P.R. 600/1973)" ,
- "RF14" => "Rivendita di beni usati, di oggetti d’arte, d’antiquariato o da collezione (art. 36, D.L. 41/1995)" ,
- "RF15" => "Agenzie di vendite all’asta di oggetti d’arte, antiquariato o da collezione (art. 40-bis, D.L. 41/1995)" ,
- "RF16" => "IVA per cassa P.A. (art. 6, c.5, D.P.R. 633/1972)" ,
- "RF17" => "IVA per cassa (art. 32-bis, D.L. 83/2012)" ,
- "RF19" => "Regime forfettario" ,
- "RF18" => "Altro"
- ];
-
- public array $tipo_documento = [
- 'TD01' => 'Fattura',
- 'TD02' => 'Acconto/Anticipo su fattura',
- 'TD03' => 'Acconto/Anticipo su parcella',
- 'TD04' => 'Nota di Credito',
- 'TD05' => 'Nota di Debito',
- 'TD06' => 'Parcella',
- 'TD16' => 'Integrazione fattura reverse charge interno',
- 'TD17' => 'Integrazione/autofattura per acquisto servizi dall’estero',
- 'TD18' => 'Integrazione per acquisto di beni intracomunitari',
- 'TD19' => 'Integrazione/autofattura per acquisto di beni ex art.17 c.2 DPR 633/72',
- 'TD20' => 'Autofattura per regolarizzazione e integrazione delle fatture',
- 'TD21' => 'Autofattura per splafonamento',
- 'TD22' => 'Estrazione beni da Deposito IVA',
- 'TD23' => 'Estrazione beni da Deposito IVA con versamento dell’IVA',
- 'TD24' => 'Fattura differita di cui all’art.21, comma 4, lett. a)',
- 'TD25' => 'Fattura differita di cui all’art.21, comma 4, terzo periodo lett. b)',
- 'TD26' => 'Cessione di beni ammortizzabili e per passaggi interni ',
- 'TD27' => 'Fattura per autoconsumo o per cessioni gratuite senza rivalsa',
- ];
-
- public array $esigibilita_iva = [
- 'I' => 'IVA ad esigibilità immediata',
- 'D' => 'IVA ad esigibilità differita',
- 'S' => 'Scissione dei pagamenti',
- ];
-
- public array $modalita_pagamento = [
- 'MP01' => 'contanti', //cash
- 'MP02' => 'assegno', //check
- 'MP03' => 'assegno circolare', //cashier's check
- 'MP04' => 'contanti presso Tesoreria', //cash at treasury
- 'MP05' => 'bonifico', //bank transfer
- 'MP06' => 'vaglia cambiario', //bill of exchange
- 'MP07' => 'bollettino bancario', //bank bulletin
- 'MP08' => 'carta di pagamento', //payment card
- 'MP09' => 'RID', //RID
- 'MP10' => 'RID utenze', //RID utilities
- 'MP11' => 'RID veloce', //fast RID
- 'MP12' => 'Riba', //Riba
- 'MP13' => 'MAV //MAV',
- 'MP14' => 'quietanza erario stato', //state treasury receipt
- 'MP15' => 'giroconto su conti di contabilità speciale', //transfer to special accounting accounts
- 'MP16' => 'domiciliazione bancaria', //bank domiciliation
- 'MP17' => 'domiciliazione postale', //postal domiciliation
- 'MP18' => 'bollettino di c/c postale', //postal giro account
- 'MP19' => 'SEPA Direct Debit', //SEPA Direct Debit
- 'MP20' => 'SEPA Direct Debit CORE', //SEPA Direct Debit CORE
- 'MP21' => 'SEPA Direct Debit B2B', //SEPA Direct Debit B2B
- 'MP22' => 'Trattenuta su somme già riscosse', //Withholding on sums already collected
- 'MP23' => 'PagoPA', //PagoPA
- ];
-
- public array $esigibilita_pagamento = [
- 'TP01' => 'Pagamento a rate',
- 'TP02' => 'Pagamento completo',
- 'TP03' => 'Anticipo',
- ];
-
- public function __construct()
- {
- }
-
- public function getRegimeFiscale(): array
- {
- return $this->regime_fiscale;
- }
- public function getTipoDocumento(): array
- {
- return $this->tipo_documento;
- }
-
- public function getEsigibilitaIva(): array
- {
- return $this->esigibilita_iva;
- }
-
- public function getModalitaPagamento(): array
- {
- return $this->modalita_pagamento;
- }
-
- public function getEsigibilitaPagamento(): array
- {
- return $this->esigibilita_pagamento;
- }
-
-}
\ No newline at end of file
diff --git a/app/Export/CSV/ClientExport.php b/app/Export/CSV/ClientExport.php
index 736b2285c098..de3ee42c0650 100644
--- a/app/Export/CSV/ClientExport.php
+++ b/app/Export/CSV/ClientExport.php
@@ -125,8 +125,10 @@ class ClientExport extends BaseExport
$query = Client::query()->with('contacts')
->withTrashed()
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false)
+ $query->where('is_deleted', 0);
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php
index fe1db16d1b2b..67ba75c1695e 100644
--- a/app/Export/CSV/ExpenseExport.php
+++ b/app/Export/CSV/ExpenseExport.php
@@ -82,8 +82,12 @@ class ExpenseExport extends BaseExport
$query = Expense::query()
->with('client')
->withTrashed()
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php
index 5d9fd4442253..b0435e3859fd 100644
--- a/app/Export/CSV/InvoiceExport.php
+++ b/app/Export/CSV/InvoiceExport.php
@@ -60,8 +60,12 @@ class InvoiceExport extends BaseExport
->whereHas('client', function ($q){
$q->where('is_deleted', false);
})
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php
index fcc0470400da..20308854f2ac 100644
--- a/app/Export/CSV/InvoiceItemExport.php
+++ b/app/Export/CSV/InvoiceItemExport.php
@@ -73,8 +73,11 @@ class InvoiceItemExport extends BaseExport
->whereHas('client', function ($q){
$q->where('is_deleted', false);
})
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/ProductExport.php b/app/Export/CSV/ProductExport.php
index b1ef871c2522..cd874d16eb92 100644
--- a/app/Export/CSV/ProductExport.php
+++ b/app/Export/CSV/ProductExport.php
@@ -73,8 +73,12 @@ class ProductExport extends BaseExport
$query = Product::query()
->withTrashed()
- ->where('company_id', $this->company->id)
- ->where('is_deleted', 0);
+ ->where('company_id', $this->company->id);
+
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php
index ff092f3fbd3e..cbe54e51b2c9 100644
--- a/app/Export/CSV/PurchaseOrderExport.php
+++ b/app/Export/CSV/PurchaseOrderExport.php
@@ -61,8 +61,11 @@ class PurchaseOrderExport extends BaseExport
->whereHas('vendor', function ($q){
$q->where('is_deleted', false);
})
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php
index d7839448bcec..96c4c03aff28 100644
--- a/app/Export/CSV/PurchaseOrderItemExport.php
+++ b/app/Export/CSV/PurchaseOrderItemExport.php
@@ -65,8 +65,11 @@ class PurchaseOrderItemExport extends BaseExport
->whereHas('vendor', function ($q){
$q->where('is_deleted', false);
})
- ->with('vendor')->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->with('vendor')->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/QuoteExport.php b/app/Export/CSV/QuoteExport.php
index ceaafeffce6f..13c53cb0dc3a 100644
--- a/app/Export/CSV/QuoteExport.php
+++ b/app/Export/CSV/QuoteExport.php
@@ -67,8 +67,11 @@ class QuoteExport extends BaseExport
->whereHas('client', function ($q){
$q->where('is_deleted', false);
})
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/QuoteItemExport.php b/app/Export/CSV/QuoteItemExport.php
index d3c004c1c201..d3f8be4b91f8 100644
--- a/app/Export/CSV/QuoteItemExport.php
+++ b/app/Export/CSV/QuoteItemExport.php
@@ -68,8 +68,11 @@ class QuoteItemExport extends BaseExport
->whereHas('client', function ($q){
$q->where('is_deleted', false);
})
- ->with('client')->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->with('client')->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/RecurringInvoiceExport.php b/app/Export/CSV/RecurringInvoiceExport.php
index df80d2d2a92b..9c88f33f7ab9 100644
--- a/app/Export/CSV/RecurringInvoiceExport.php
+++ b/app/Export/CSV/RecurringInvoiceExport.php
@@ -59,8 +59,11 @@ class RecurringInvoiceExport extends BaseExport
->whereHas('client', function ($q){
$q->where('is_deleted', false);
})
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/TaskExport.php b/app/Export/CSV/TaskExport.php
index 7830114f260a..5b1985ce4782 100644
--- a/app/Export/CSV/TaskExport.php
+++ b/app/Export/CSV/TaskExport.php
@@ -68,8 +68,11 @@ class TaskExport extends BaseExport
$query = Task::query()
->withTrashed()
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Export/CSV/VendorExport.php b/app/Export/CSV/VendorExport.php
index 5037e4d43b7f..187487a14765 100644
--- a/app/Export/CSV/VendorExport.php
+++ b/app/Export/CSV/VendorExport.php
@@ -62,8 +62,11 @@ class VendorExport extends BaseExport
$query = Vendor::query()->with('contacts')
->withTrashed()
- ->where('company_id', $this->company->id)
- ->where('is_deleted', $this->input['include_deleted'] ?? false);
+ ->where('company_id', $this->company->id);
+
+ if(!$this->input['include_deleted'] ?? false){
+ $query->where('is_deleted', 0);
+ }
$query = $this->addDateRange($query);
diff --git a/app/Factory/UserFactory.php b/app/Factory/UserFactory.php
index 960584cceead..e0c46bbcda2a 100644
--- a/app/Factory/UserFactory.php
+++ b/app/Factory/UserFactory.php
@@ -12,6 +12,7 @@
namespace App\Factory;
use App\Models\User;
+use Illuminate\Support\Str;
class UserFactory
{
@@ -29,6 +30,7 @@ class UserFactory
$user->signature = '';
$user->theme_id = 0;
$user->user_logged_in_notification = true;
+ $user->referral_code = Str::lower(Str::random(32));
return $user;
}
diff --git a/app/Helpers/Mail/GmailTransport.php b/app/Helpers/Mail/GmailTransport.php
index e13c6f07923c..0655c710cad8 100644
--- a/app/Helpers/Mail/GmailTransport.php
+++ b/app/Helpers/Mail/GmailTransport.php
@@ -64,23 +64,23 @@ class GmailTransport extends AbstractTransport
$body->setRaw($this->base64_encode($bcc_list.$message->toString()));
- try {
+ // try {
$service->users_messages->send('me', $body, []);
- } catch(\Google\Service\Exception $e) {
- /* Need to slow down */
- if ($e->getCode() == '429') {
- nlog("429 google - retrying ");
+ // } catch(\Google\Service\Exception $e) {
+ // /* Need to slow down */
+ // if ($e->getCode() == '429') {
+ // nlog("429 google - retrying ");
- sleep(rand(3,8));
+ // sleep(rand(3,8));
- try {
- $service->users_messages->send('me', $body, []);
- } catch(\Google\Service\Exception $e) {
+ // try {
+ // $service->users_messages->send('me', $body, []);
+ // } catch(\Google\Service\Exception $e) {
- }
+ // }
- }
- }
+ // }
+ // }
}
private function base64_encode($data)
diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php
index 8e2c8de91f25..f573fa72e00f 100644
--- a/app/Http/Controllers/BaseController.php
+++ b/app/Http/Controllers/BaseController.php
@@ -38,6 +38,7 @@ use App\Transformers\ArraySerializer;
use App\Transformers\EntityTransformer;
use League\Fractal\Resource\Collection;
use Illuminate\Database\Eloquent\Builder;
+use Invoiceninja\Einvoice\Decoder\Schema;
use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use Illuminate\Contracts\Container\BindingResolutionException;
@@ -996,8 +997,8 @@ class BaseController extends Controller
if(request()->has('einvoice')){
- // $ro = new Schema();
- // $response_data['einvoice_schema'] = $ro('FACT1');
+ $ro = new Schema();
+ $response_data['einvoice_schema'] = $ro('FACT1');
}
diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php
index 4af43a2a1224..de5808b0f120 100644
--- a/app/Http/Controllers/SelfUpdateController.php
+++ b/app/Http/Controllers/SelfUpdateController.php
@@ -26,8 +26,6 @@ class SelfUpdateController extends BaseController
use ClientGroupSettingsSaver;
use AppSetup;
- // private bool $use_zip = false;
-
private string $filename = 'invoiceninja.tar';
private array $purge_file_list = [
diff --git a/app/Http/Controllers/StaticController.php b/app/Http/Controllers/StaticController.php
index 135384fb9697..71403d055d1b 100644
--- a/app/Http/Controllers/StaticController.php
+++ b/app/Http/Controllers/StaticController.php
@@ -13,6 +13,7 @@ namespace App\Http\Controllers;
use App\Utils\Statics;
use Illuminate\Http\Response;
+use Invoiceninja\Einvoice\Decoder\Schema;
class StaticController extends BaseController
{
@@ -60,8 +61,8 @@ class StaticController extends BaseController
if(request()->has('einvoice')){
- // $schema = new Schema();
- // $response_data['einvoice_schema'] = $schema('FACT1');
+ $schema = new Schema();
+ $response_data['einvoice_schema'] = $schema('FACT1');
}
diff --git a/app/Http/Controllers/WePayController.php b/app/Http/Controllers/WePayController.php
deleted file mode 100644
index b8669efd8540..000000000000
--- a/app/Http/Controllers/WePayController.php
+++ /dev/null
@@ -1,56 +0,0 @@
-firstOrFail();
-
- $data['user_id'] = $user->id;
- $data['user_company'] = $company;
-
- // $data['company_key'] = $company->company_key;
- // $data['db'] = $company->db;
-
- $wepay_driver = new WePayPaymentDriver(new CompanyGateway(), null, null);
-
- return $wepay_driver->setup($data);
- }
-
- public function finished()
- {
- return render('gateways.wepay.signup.finished');
- }
-}
diff --git a/app/Http/Requests/CompanyUser/UpdateCompanyUserRequest.php b/app/Http/Requests/CompanyUser/UpdateCompanyUserRequest.php
index f0927348ab24..5c17f5ccd52a 100644
--- a/app/Http/Requests/CompanyUser/UpdateCompanyUserRequest.php
+++ b/app/Http/Requests/CompanyUser/UpdateCompanyUserRequest.php
@@ -35,4 +35,14 @@ class UpdateCompanyUserRequest extends Request
{
return [];
}
+
+ public function prepareForValidation()
+ {
+ $input = $this->all();
+
+ if(isset($input['company_user']['user']))
+ unset($input['company_user']['user']);
+
+ $this->replace($input);
+ }
}
diff --git a/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php
index 1796d30fa785..9852d8e60316 100644
--- a/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php
+++ b/app/Http/Requests/Nordigen/ConnectNordigenBankIntegrationRequest.php
@@ -45,6 +45,9 @@ class ConnectNordigenBankIntegrationRequest extends Request
$context = $this->getTokenContent();
+ if(isset($context['institution_id']))
+ $input['institution_id'] = $context['institution_id'];
+
$input["redirect"] = isset($context["is_react"]) && $context['is_react'] ? config('ninja.react_url') . "/#/settings/bank_accounts" : config('ninja.app_url');
$this->replace($input);
diff --git a/app/Http/Requests/Report/GenericReportRequest.php b/app/Http/Requests/Report/GenericReportRequest.php
index 7c8521a19305..1ebd60dc4321 100644
--- a/app/Http/Requests/Report/GenericReportRequest.php
+++ b/app/Http/Requests/Report/GenericReportRequest.php
@@ -26,7 +26,7 @@ class GenericReportRequest extends Request
*/
public function authorize(): bool
{
- return $this->checkAuthority();
+ return true;
}
public function rules()
@@ -68,27 +68,25 @@ class GenericReportRequest extends Request
$input['user_id'] = auth()->user()->id;
+ if(!$this->checkAuthority()){
+ $input['date_range'] = '';
+ $input['start_date'] = '';
+ $input['end_date'] = '';
+ $input['send_email'] = true;
+ $input['report_keys'] = [];
+ $input['document_email_attachment'] = false;
+ }
+
$this->replace($input);
}
private function checkAuthority()
{
- $this->error_message = ctrans('texts.authorization_failure');
/** @var \App\Models\User $user */
$user = auth()->user();
-
- if(Ninja::isHosted() && $user->account->isFreeHostedClient()){
- $this->error_message = ctrans('texts.upgrade_to_view_reports');
- return false;
- }
-
+
return $user->isAdmin() || $user->hasPermission('view_reports');
}
-
- protected function failedAuthorization()
- {
- throw new AuthorizationException($this->error_message);
- }
}
diff --git a/app/Jobs/Bank/MatchBankTransactions.php b/app/Jobs/Bank/MatchBankTransactions.php
index 5748dcecc052..2dabff1e05c7 100644
--- a/app/Jobs/Bank/MatchBankTransactions.php
+++ b/app/Jobs/Bank/MatchBankTransactions.php
@@ -289,6 +289,8 @@ class MatchBankTransactions implements ShouldQueue
private function createPayment($invoices, float $amount): void
{
+
+ $this->attachable_invoices = [];
$this->available_balance = $amount;
\DB::connection(config('database.default'))->transaction(function () use ($invoices) {
diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php
index b1b1c94690eb..04edfe884073 100644
--- a/app/Jobs/Mail/NinjaMailerJob.php
+++ b/app/Jobs/Mail/NinjaMailerJob.php
@@ -152,19 +152,39 @@ class NinjaMailerJob implements ShouldQueue
LightLogs::create(new EmailSuccess($this->nmo->company->company_key, $this->nmo->mailable->subject))
->send();
- } catch (\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
+ }
+ catch (\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
$this->fail();
$this->cleanUpMailers();
$this->logMailError($e->getMessage(), $this->company->clients()->first());
return;
- } catch (\Symfony\Component\Mime\Exception\LogicException $e) {
+ }
+ catch (\Symfony\Component\Mime\Exception\LogicException $e) {
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
$this->fail();
$this->cleanUpMailers();
$this->logMailError($e->getMessage(), $this->company->clients()->first());
return;
- } catch (\Exception | \Google\Service\Exception $e) {
+ }
+ catch(\Symfony\Component\Mailer\Transport\Dsn $e){
+ nlog("Incorrectly configured mail server - setting to default mail driver.");
+ $this->nmo->settings->email_sending_method = 'default';
+ return $this->setMailDriver();
+ }
+ catch(\Google\Service\Exception $e){
+
+ if ($e->getCode() == '429') {
+
+ $message = "Google rate limiting triggered, we are queueing based on Gmail requirements.";
+ $this->logMailError($message, $this->company->clients()->first());
+ sleep(rand(1, 2));
+ $this->release(900);
+
+ }
+
+ }
+ catch (\Exception $e) {
nlog("Mailer failed with {$e->getMessage()}");
$message = $e->getMessage();
@@ -221,8 +241,7 @@ class NinjaMailerJob implements ShouldQueue
}
/* Releasing immediately does not add in the backoff */
- sleep(rand(5, 10));
-
+ sleep(rand(2, 3));
$this->release($this->backoff()[$this->attempts() - 1]);
}
@@ -779,15 +798,20 @@ class NinjaMailerJob implements ShouldQueue
return false;
}
- $token = json_decode($guzzle->post($url, [
- 'form_params' => [
- 'client_id' => config('ninja.o365.client_id'),
- 'client_secret' => config('ninja.o365.client_secret'),
- 'scope' => 'email Mail.Send offline_access profile User.Read openid',
- 'grant_type' => 'refresh_token',
- 'refresh_token' => $user->oauth_user_refresh_token
- ],
- ])->getBody()->getContents());
+ try {
+ $token = json_decode($guzzle->post($url, [
+ 'form_params' => [
+ 'client_id' => config('ninja.o365.client_id'),
+ 'client_secret' => config('ninja.o365.client_secret'),
+ 'scope' => 'email Mail.Send offline_access profile User.Read openid',
+ 'grant_type' => 'refresh_token',
+ 'refresh_token' => $user->oauth_user_refresh_token
+ ],
+ ])->getBody()->getContents());
+ }
+ catch(\Exception $e){
+ nlog("Problem getting new Microsoft token for User: {$user->email}");
+ }
if ($token) {
$user->oauth_user_refresh_token = property_exists($token, 'refresh_token') ? $token->refresh_token : $user->oauth_user_refresh_token;
diff --git a/app/Jobs/User/CreateUser.php b/app/Jobs/User/CreateUser.php
index 504a27b80a1c..73f5e968f325 100644
--- a/app/Jobs/User/CreateUser.php
+++ b/app/Jobs/User/CreateUser.php
@@ -17,6 +17,7 @@ use App\Models\User;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Support\Str;
class CreateUser
{
@@ -62,6 +63,7 @@ class CreateUser
$user->fill($this->request);
$user->email = $this->request['email']; //todo need to remove this in production
$user->last_login = now();
+ $user->referral_code = Str::lower(Str::random(32));
$user->ip = request()->ip();
if (Ninja::isSelfHost()) {
diff --git a/app/Livewire/WepaySignup.php b/app/Livewire/WepaySignup.php
deleted file mode 100644
index 7ed96676e2dd..000000000000
--- a/app/Livewire/WepaySignup.php
+++ /dev/null
@@ -1,215 +0,0 @@
- ['required'],
- 'last_name' => ['required'],
- 'email' => ['required', 'email'],
- 'company_name' => ['required'],
- 'country' => ['required'],
- 'ach' => ['sometimes'],
- 'wepay_payment_tos_agree' => ['accepted'],
- 'debit_cards' => ['sometimes'],
- ];
-
- public function mount()
- {
- MultiDB::setDb($this->company->db);
-
- $user = User::find($this->user_id);
- $this->company = Company::query()->where('company_key', $this->company->company_key)->first();
-
- $this->fill([
- 'wepay_payment_tos_agree' => '',
- 'ach' => '',
- 'country' => 'US',
- 'user' => $user,
- 'first_name' => $user->first_name,
- 'last_name' => $user->last_name,
- 'email' => $user->email,
- 'company_name' => $this->company->present()->name(),
- 'saved' => ctrans('texts.confirm'),
- 'terms' => ''.ctrans('texts.terms_of_service').'',
- 'privacy_policy' => ''.ctrans('texts.privacy_policy').'',
- ]);
- }
-
- public function render()
- {
- return render('gateways.wepay.signup.wepay-signup');
- }
-
- public function submit()
- {
- MultiDB::setDb($this->company->db);
-
- $data = $this->validate($this->rules);
-
- //need to create or get a new WePay CompanyGateway
- $cg = CompanyGateway::query()->where('gateway_key', '8fdeed552015b3c7b44ed6c8ebd9e992')
- ->where('company_id', $this->company->id)
- ->firstOrNew();
-
- if (! $cg->id) {
- $fees_and_limits = new \stdClass();
- $fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits();
- $fees_and_limits->{GatewayType::BANK_TRANSFER} = new FeesAndLimits();
-
- $cg = CompanyGatewayFactory::create($this->company->id, $this->user->id);
- $cg->gateway_key = '8fdeed552015b3c7b44ed6c8ebd9e992';
- $cg->require_cvv = false;
- $cg->require_billing_address = false;
- $cg->require_shipping_address = false;
- $cg->update_details = false;
- $cg->config = encrypt(config('ninja.testvars.checkout'));
- $cg->fees_and_limits = $fees_and_limits;
- $cg->token_billing = 'always';
- $cg->save();
- }
-
- $this->saved = ctrans('texts.processing');
-
- $wepay_driver = new WePayPaymentDriver($cg, null, null);
-
- $wepay = $wepay_driver->init()->wepay;
-
- $user_details = [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'email' => $data['email'],
- 'first_name' => $data['first_name'],
- 'last_name' => $data['last_name'],
- 'original_ip' => request()->ip(),
- 'original_device' => request()->server('HTTP_USER_AGENT'),
- 'tos_acceptance_time' => time(),
- 'redirect_uri' => route('wepay.finished'),
- 'scope' => 'manage_accounts,collect_payments,view_user,preapprove_payments,send_money',
- ];
-
- $wepay_user = $wepay->request('user/register/', $user_details);
-
- $access_token = $wepay_user->access_token;
-
- $access_token_expires = $wepay_user->expires_in ? (time() + $wepay_user->expires_in) : null;
-
- $wepay = new WePay($access_token);
-
- $account_details = [
- 'name' => $data['company_name'],
- 'description' => ctrans('texts.wepay_account_description'),
- 'theme_object' => json_decode('{"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}'),
- 'callback_uri' => route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $cg->hashed_id]),
- 'rbits' => $this->company->rBits(),
- 'country' => $data['country'],
- ];
-
- if ($data['country'] == 'CA') {
- $account_details['currencies'] = ['CAD'];
- $account_details['country_options'] = ['debit_opt_in' => boolval($data['debit_cards'])];
- } elseif ($data['country'] == 'GB') {
- $account_details['currencies'] = ['GBP'];
- }
-
- $wepay_account = $wepay->request('account/create/', $account_details);
- $confirmation_required = false;
-
- try {
- $wepay->request('user/send_confirmation/', []);
- $confirmation_required = true;
- } catch (\WePayException $ex) {
- if ($ex->getMessage() == 'This access_token is already approved.') {
- $confirmation_required = false;
- } else {
-
- /** @phpstan-ignore-next-line */
- request()->session()->flash('message', $ex->getMessage());
- }
-
- nlog('failed in try catch ');
- nlog($ex->getMessage());
- }
-
- $config = [
- 'userId' => $wepay_user->user_id,
- 'accessToken' => $access_token,
- 'tokenType' => $wepay_user->token_type,
- 'tokenExpires' => $access_token_expires,
- 'accountId' => $wepay_account->account_id,
- 'state' => $wepay_account->state,
- 'testMode' => config('ninja.wepay.environment') == 'staging',
- 'country' => $data['country'],
- ];
-
- $cg->setConfig($config);
- $cg->save();
-
- if ($confirmation_required) {
-
- /** @phpstan-ignore-next-line **/
- request()->session()->flash('message', trans('texts.created_wepay_confirmation_required'));
- } else {
- $update_uri = $wepay->request('/account/get_update_uri', [
- 'account_id' => $wepay_account->account_id,
- 'redirect_uri' => config('ninja.app_url'),
- ]);
-
- return redirect($update_uri->uri);
- }
-
- return redirect()->to('/wepay/finished');
- }
-}
diff --git a/app/Models/Presenters/ClientContactPresenter.php b/app/Models/Presenters/ClientContactPresenter.php
index c42d7c0f6097..3fc2e9aed3fa 100644
--- a/app/Models/Presenters/ClientContactPresenter.php
+++ b/app/Models/Presenters/ClientContactPresenter.php
@@ -44,4 +44,15 @@ class ClientContactPresenter extends EntityPresenter
{
return $this->name().' <'.$this->entity->email.'>' ?? '';
}
+
+ public function phone()
+ {
+ return strlen($this->phone ?? '') > 1 ? $this->phone : '';
+ }
+
+ public function email()
+ {
+ return strlen($this->email ?? '') > 1 ? $this->email : '';
+ }
+
}
diff --git a/app/Notifications/Ninja/WePayFailureNotification.php b/app/Notifications/Ninja/WePayFailureNotification.php
deleted file mode 100644
index 74199a4eb1d2..000000000000
--- a/app/Notifications/Ninja/WePayFailureNotification.php
+++ /dev/null
@@ -1,79 +0,0 @@
-company_id = $company_id;
- }
-
- /**
- * Get the notification's delivery channels.
- *
- * @param mixed $notifiable
- * @return array
- */
- public function via($notifiable)
- {
- return ['slack'];
- }
-
- /**
- * Get the mail representation of the notification.
- *
- * @param mixed $notifiable
- *
- */
- public function toMail($notifiable)
- {
- }
-
- /**
- * Get the array representation of the notification.
- *
- * @param mixed $notifiable
- * @return array
- */
- public function toArray($notifiable)
- {
- return [
- //
- ];
- }
-
- public function toSlack($notifiable)
- {
- $ip = '';
-
- if (request()) {
- $ip = request()->getClientIp();
- }
-
- return (new SlackMessage())
- ->success()
- ->from(ctrans('texts.notification_bot'))
- ->image('https://app.invoiceninja.com/favicon.png')
- ->content("New WePay ACH Failure from Company ID: {$this->company_id} IP: {$ip}");
- }
-}
diff --git a/app/PaymentDrivers/Sample/resources/pay.blade.php b/app/PaymentDrivers/Sample/resources/pay.blade.php
index ea05015e1c90..1734c9f328a9 100644
--- a/app/PaymentDrivers/Sample/resources/pay.blade.php
+++ b/app/PaymentDrivers/Sample/resources/pay.blade.php
@@ -45,7 +45,7 @@
@include('portal.ninja2020.gateways.includes.save_card')
- @include('portal.ninja2020.gateways.wepay.includes.credit_card')
+ @include('portal.ninja2020.gateways.stripe.includes.credit_card')
@include('portal.ninja2020.gateways.includes.pay_now')
diff --git a/app/PaymentDrivers/WePay/ACH.php b/app/PaymentDrivers/WePay/ACH.php
deleted file mode 100644
index d6dea4e464c7..000000000000
--- a/app/PaymentDrivers/WePay/ACH.php
+++ /dev/null
@@ -1,354 +0,0 @@
-wepay_payment_driver = $wepay_payment_driver;
- }
-
- public function authorizeView($data)
- {
- $data['gateway'] = $this->wepay_payment_driver;
- $data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company->country()->iso_3166_2;
-
- return render('gateways.wepay.authorize.bank_transfer', $data);
- }
-
- public function authorizeResponse($request)
- {
- //https://developer.wepay.com/api/api-calls/credit_card#authorize
- $data = $request->all();
- // authorize the credit card
-
- //nlog($data);
- /*
- '_token' => '1Fk5CRj34up5ntKPvrFyMIAJhDdUNF3boqT3iIN3',
- 'company_gateway_id' => '39',
- 'payment_method_id' => '1',
- 'gateway_response' => NULL,
- 'is_default' => NULL,
- 'credit_card_id' => '180642154638',
- 'q' => '/client/payment_methods',
- 'method' => '1',
- */
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('payment_bank/persist', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'payment_bank_id' => (int) $data['bank_account_id'],
- ]);
- } catch (\Exception $e) {
- $this->wepay_payment_driver->sendFailureMail($e->getMessage());
-
- $message = [
- 'server_response' => $e->getMessage(),
- ];
-
- SystemLogger::dispatch(
- $e->getMessage(),
- SystemLog::CATEGORY_GATEWAY_RESPONSE,
- SystemLog::EVENT_GATEWAY_FAILURE,
- SystemLog::TYPE_WEPAY,
- $this->wepay_payment_driver->client,
- $this->wepay_payment_driver->client->company,
- );
-
- if (config('ninja.notification.slack')) {
- $this->wepay_payment_driver->company_gateway->company->notification(new WePayFailureNotification($this->wepay_payment_driver->company_gateway->company))->ninja();
- }
-
- throw new PaymentFailed($e->getMessage(), 400);
- }
- // display the response
- // nlog($response);
-
- if (in_array($response->state, ['new', 'pending', 'authorized'])) {
- $this->storePaymentMethod($response, GatewayType::BANK_TRANSFER);
-
- return redirect()->route('client.payment_methods.index');
- }
-
- throw new PaymentFailed('There was a problem adding this payment method.', 400);
- /*
- {
- "payment_bank_id": 12345,
- "bank_name": "Wells Fargo",
- "account_last_four": "6789",
- "state": "authorized"
- }
-
- state options: new, pending, authorized, disabled.
- */
- }
-
- /* If the bank transfer token is PENDING - we need to verify!! */
- //
-
- public function verificationView(ClientGatewayToken $token)
- {
- $this->wepay_payment_driver->init();
-
- $data = [
- 'token' => $token,
- 'gateway' => $this->wepay_payment_driver,
- ];
-
- return render('gateways.wepay.authorize.verify', $data);
- }
-
- /**
- {
- "client_id": 1234,
- "client_secret": "b1fc2f68-4d1f-4a",
- "payment_bank_id": 12345,
- "type": "microdeposits",
- "microdeposits": [
- 8,
- 12
- ]
- }
- */
- public function processVerification(Request $request, ClientGatewayToken $token)
- {
- $transactions = $request->input('transactions');
-
- $transformed_transactions = [];
-
- foreach ($transactions as $transaction) {
- $transformed_transactions[] = (int) $transaction;
- }
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('payment_bank/verify', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'payment_bank_id' => $token->token,
- 'type' => 'microdeposits',
- 'microdeposits' => $transformed_transactions,
- ]);
- } catch (\Exception $e) {
- nlog('we pay exception');
- nlog($e->getMessage());
-
- return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER])
- ->with('error', $e->getMessage());
- }
- /*
- {
- "payment_bank_id": 12345,
- "bank_name": "Wells Fargo",
- "account_last_four": "6789",
- "state": "authorized"
- }
- */
- nlog($response);
-
- //$meta = $token->meta;
- if ($response->state == 'authorized') {
- $meta = $token->meta;
- $meta->state = $response->state;
- $token->meta = $meta;
- $token->save();
-
- return redirect()->route('client.payment_methods.index');
- } else {
- return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER])
- ->with('error', ctrans('texts.verification_failed'));
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////
- public function paymentView(array $data)
- {
- $data['gateway'] = $this->wepay_payment_driver;
- $data['currency'] = $this->wepay_payment_driver->client->getCurrencyCode();
- $data['payment_method_id'] = GatewayType::BANK_TRANSFER;
- $data['amount'] = $data['total']['amount_with_fee'];
-
- return render('gateways.wepay.bank_transfer', $data);
- }
-
- public function paymentResponse($request)
- {
- $token = ClientGatewayToken::query()->find($this->decodePrimaryKey($request->input('source')));
- $token_meta = $token->meta;
-
- if (! property_exists($token_meta, 'state') || $token_meta->state != 'authorized') {
- $response = $this->wepay_payment_driver->wepay->request('/payment_bank', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'payment_bank_id' => $token->token,
- ]);
-
- if ($response->state == 'authorized') {
- $meta = $token->meta;
- $meta->state = $response->state;
- $token->meta = $meta;
- $token->save();
- } else {
- return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
- }
- }
-
- $app_fee = (config('ninja.wepay.fee_ach_multiplier') * $this->wepay_payment_driver->payment_hash->data->amount_with_fee) + config('ninja.wepay.fee_fixed');
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('checkout/create', [
- // 'callback_uri' => route('payment_webhook', ['company_key' => $this->wepay_payment_driver->company_gateway->company->company_key, 'company_gateway_id' => $this->wepay_payment_driver->company_gateway->hashed_id]),
- 'unique_id' => Str::random(40),
- 'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
- 'amount' => $this->wepay_payment_driver->payment_hash->data->amount_with_fee,
- 'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
- 'short_description' => 'Goods and Services',
- 'type' => 'goods',
- 'fee' => [
- 'fee_payer' => config('ninja.wepay.fee_payer'),
- 'app_fee' => $app_fee,
- ],
- 'payment_method' => [
- 'type' => 'payment_bank',
- 'payment_bank' => [
- 'id' => $token->token,
- ],
- ],
- ]);
- } catch (\Exception $e) {
- throw new PaymentFailed($e->getMessage(), 500);
- }
-
- /* Merge all data and store in the payment hash*/
- $state = [
- 'server_response' => $response,
- 'payment_hash' => $request->payment_hash,
- ];
-
- $state = array_merge($state, $request->all());
- $this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
- $this->wepay_payment_driver->payment_hash->save();
-
- if (in_array($response->state, ['authorized', 'captured'])) {
- //success
- nlog('success');
- $payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
-
- return $this->processSuccessfulPayment($response, $payment_status, GatewayType::BANK_TRANSFER);
- }
-
- if (in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])) {
- //some type of failure
- nlog('failure');
-
- $payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
-
- $this->processUnSuccessfulPayment($response, $payment_status);
- }
- }
-
- private function storePaymentMethod($response, $payment_method_id)
- {
- $payment_meta = new \stdClass();
- $payment_meta->exp_month = (string) '';
- $payment_meta->exp_year = (string) '';
- $payment_meta->brand = (string) $response->bank_name;
- $payment_meta->last4 = (string) $response->account_last_four;
- $payment_meta->type = GatewayType::BANK_TRANSFER;
- $payment_meta->state = $response->state;
-
- $data = [
- 'payment_meta' => $payment_meta,
- 'token' => $response->payment_bank_id,
- 'payment_method_id' => $payment_method_id,
- ];
-
- $this->wepay_payment_driver->storeGatewayToken($data);
- }
-
- public function tokenBilling($token, $payment_hash)
- {
- $token_meta = $token->meta;
-
- if (! property_exists($token_meta, 'state') || $token_meta->state != 'authorized') {
- return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
- }
-
- $amount = array_sum(array_column($this->wepay_payment_driver->payment_hash->invoices(), 'amount')) + $this->wepay_payment_driver->payment_hash->fee_total;
-
- $app_fee = (config('ninja.wepay.fee_cc_multiplier') * $amount) + config('ninja.wepay.fee_fixed');
-
- $response = $this->wepay_payment_driver->wepay->request('checkout/create', [
- 'unique_id' => Str::random(40),
- 'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
- 'amount' => $amount,
- 'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
- 'short_description' => 'Goods and Services',
- 'type' => 'goods',
- 'fee' => [
- 'fee_payer' => config('ninja.wepay.fee_payer'),
- 'app_fee' => $app_fee,
- ],
- 'payment_method' => [
- 'type' => 'payment_bank',
- 'payment_bank' => [
- 'id' => $token->token,
- ],
- ],
- ]);
-
- /* Merge all data and store in the payment hash*/
- $state = [
- 'server_response' => $response,
- 'payment_hash' => $this->wepay_payment_driver->payment_hash,
- ];
-
- $this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
- $this->wepay_payment_driver->payment_hash->save();
-
- if (in_array($response->state, ['authorized', 'captured'])) {
- //success
- nlog('success');
- $payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
-
- return $this->processSuccessfulPayment($response, $payment_status, GatewayType::BANK_TRANSFER, true);
- }
-
- if (in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])) {
- //some type of failure
- nlog('failure');
-
- $payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
-
- $this->processUnSuccessfulPayment($response, $payment_status);
- }
- }
-}
diff --git a/app/PaymentDrivers/WePay/CreditCard.php b/app/PaymentDrivers/WePay/CreditCard.php
deleted file mode 100644
index 2e15012d7c1f..000000000000
--- a/app/PaymentDrivers/WePay/CreditCard.php
+++ /dev/null
@@ -1,346 +0,0 @@
-wepay_payment_driver = $wepay_payment_driver;
- }
-
- public function authorizeView($data)
- {
- $data['gateway'] = $this->wepay_payment_driver;
- $data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company->country()->iso_3166_2;
-
- return render('gateways.wepay.authorize.authorize', $data);
- }
-
- public function authorizeResponse($request)
- {
- //https://developer.wepay.com/api/api-calls/credit_card#authorize
- $data = $request->all();
- // authorize the credit card
-
- // nlog($data);
- /*
- '_token' => '1Fk5CRj34up5ntKPvrFyMIAJhDdUNF3boqT3iIN3',
- 'company_gateway_id' => '39',
- 'payment_method_id' => '1',
- 'gateway_response' => NULL,
- 'is_default' => NULL,
- 'credit_card_id' => '180642154638',
- 'q' => '/client/payment_methods',
- 'method' => '1',
- */
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'credit_card_id' => (int) $data['credit_card_id'],
- ]);
- } catch (\Exception $e) {
- return $this->wepay_payment_driver->processInternallyFailedPayment($this->wepay_payment_driver, $e);
- }
- // display the response
- // nlog($response);
-
- if (in_array($response->state, ['new', 'authorized'])) {
- $this->storePaymentMethod($response, GatewayType::CREDIT_CARD);
-
- return redirect()->route('client.payment_methods.index');
- }
-
- throw new PaymentFailed('There was a problem adding this payment method.', 400);
- /*
- [credit_card_id] => 348084962473
- [credit_card_name] => Visa xxxxxx4018
- [state] => authorized
- [user_name] => Joey Diaz
- [email] => user@example.com
- [create_time] => 1623798172
- [expiration_month] => 10
- [expiration_year] => 2023
- [last_four] => 4018
- [input_source] => card_keyed
- [virtual_terminal_mode] => none
- [card_on_file] =>
- [recurring] =>
- [cvv_provided] => 1
- [auto_update] =>
- */
- }
-
- public function paymentView(array $data)
- {
- $data['gateway'] = $this->wepay_payment_driver;
- $data['description'] = ctrans('texts.invoices').': '.collect($data['invoices'])->pluck('invoice_number');
- $data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
-
- return render('gateways.wepay.credit_card.pay', $data);
- }
-
- public function paymentResponse(PaymentResponseRequest $request)
- {
- nlog('payment response');
-
- //it could be an existing token or a new credit_card_id that needs to be converted into a wepay token
- if ($request->has('credit_card_id') && $request->input('credit_card_id')) {
- nlog('authorize the card first!');
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('credit_card/authorize', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'credit_card_id' => (int) $request->input('credit_card_id'),
- ]);
- } catch (\Exception $e) {
- return $this->wepay_payment_driver->processInternallyFailedPayment($this->wepay_payment_driver, $e);
- }
-
- $credit_card_id = (int) $response->credit_card_id;
-
- if (in_array($response->state, ['new', 'authorized']) && boolval($request->input('store_card'))) {
- $this->storePaymentMethod($response, GatewayType::CREDIT_CARD);
- }
- } else {
- $credit_card_id = (int) $request->input('token');
- }
-
- // USD, CAD, and GBP.
- // nlog($request->all());
-
- $app_fee = (config('ninja.wepay.fee_cc_multiplier') * $this->wepay_payment_driver->payment_hash->data->amount_with_fee) + config('ninja.wepay.fee_fixed');
- // charge the credit card
-
- try {
- $response = $this->wepay_payment_driver->wepay->request('checkout/create', [
- 'unique_id' => Str::random(40),
- 'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
- 'amount' => $this->wepay_payment_driver->payment_hash->data->amount_with_fee,
- 'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
- 'short_description' => 'Goods and services',
- 'type' => 'goods',
- 'fee' => [
- 'fee_payer' => config('ninja.wepay.fee_payer'),
- 'app_fee' => $app_fee,
- ],
- 'payment_method' => [
- 'type' => 'credit_card',
- 'credit_card' => [
- 'id' => $credit_card_id,
- ],
- ],
- ]);
- } catch (\Exception $e) {
- $this->wepay_payment_driver->sendFailureMail($e->getMessage());
-
- $message = [
- 'server_response' => $e->getMessage(),
- 'data' => $this->wepay_payment_driver->payment_hash->data,
- ];
-
- SystemLogger::dispatch(
- $e->getMessage(),
- SystemLog::CATEGORY_GATEWAY_RESPONSE,
- SystemLog::EVENT_GATEWAY_FAILURE,
- SystemLog::TYPE_WEPAY,
- $this->wepay_payment_driver->client,
- $this->wepay_payment_driver->client->company,
- );
-
- throw new PaymentFailed($e->getMessage(), 500);
- }
-
- /* Merge all data and store in the payment hash*/
- $state = [
- 'server_response' => $response,
- 'payment_hash' => $request->payment_hash,
- ];
-
- $state = array_merge($state, $request->all());
- $this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
- $this->wepay_payment_driver->payment_hash->save();
-
- if (in_array($response->state, ['authorized', 'captured'])) {
- //success
- nlog('success');
- $payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
-
- return $this->processSuccessfulPayment($response, $payment_status, GatewayType::CREDIT_CARD);
- }
-
- if (in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])) {
- //some type of failure
- nlog('failure');
-
- $payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
-
- $this->processUnSuccessfulPayment($response, $payment_status);
- }
- }
-
- /*
- new The checkout was created by the application. This state typically indicates that checkouts created in WePay's hosted checkout flow are waiting for the payer to submit their information.
- authorized The payer entered their payment info and confirmed the payment on WePay. WePay has successfully charged the card.
- captured The payment has been reserved from the payer.
- released The payment has been credited to the payee account. Note that the released state may be active although there are active partial refunds or partial chargebacks.
- cancelled The payment has been cancelled by the payer, payee, or application.
- refunded The payment was captured and then refunded by the payer, payee, or application. The payment has been debited from the payee account.
- charged back The payment has been charged back by the payer and the payment has been debited from the payee account.
- failed The payment has failed.
- expired Checkouts expire if they remain in the new state for more than 30 minutes (e.g., they have been abandoned).
- */
-
- /*
- https://developer.wepay.com/api/api-calls/checkout
- {
- "checkout_id": 649945633,
- "account_id": 1548718026,
- "type": "donation",
- "short_description": "test checkout",
- "currency": "USD",
- "amount": 20,
- "state": "authorized",
- "soft_descriptor": "WPY*Wolverine",
- "auto_release": true,
- "create_time": 1463589958,
- "gross": 20.88,
- "reference_id": null,
- "callback_uri": null,
- "long_description": null,
- "delivery_type": null,
- "initiated_by": "merchant",
- "in_review": false,
- "fee": {
- "app_fee": 0,
- "processing_fee": 0.88,
- "fee_payer": "payer"
- },
- "chargeback": {
- "amount_charged_back": 0,
- "dispute_uri": null
- },
- "refund": {
- "amount_refunded": 0,
- "refund_reason": null
- },
- "payment_method": {
- "type": "credit_card",
- "credit_card": {
- "id": 1684847614,
- "data": {
- "emv_receipt": null,
- "signature_url": null
- },
- "auto_release": false
- }
- },
- "hosted_checkout": null,
- "payer": {
- "email": "test@example.com",
- "name": "Mr Smith",
- "home_address": null
- },
- "npo_information": null,
- "payment_error": null
- }
- */
-
- private function storePaymentMethod($response, $payment_method_id)
- {
- nlog('storing card');
-
- $payment_meta = new \stdClass();
- $payment_meta->exp_month = (string) $response->expiration_month;
- $payment_meta->exp_year = (string) $response->expiration_year;
- $payment_meta->brand = (string) $response->credit_card_name;
- $payment_meta->last4 = (string) $response->last_four;
- $payment_meta->type = GatewayType::CREDIT_CARD;
-
- $data = [
- 'payment_meta' => $payment_meta,
- 'token' => $response->credit_card_id,
- 'payment_method_id' => $payment_method_id,
- ];
-
- $this->wepay_payment_driver->storeGatewayToken($data);
- }
-
- public function tokenBilling($cgt, $payment_hash)
- {
- $amount = array_sum(array_column($this->wepay_payment_driver->payment_hash->invoices(), 'amount')) + $this->wepay_payment_driver->payment_hash->fee_total;
-
- $app_fee = (config('ninja.wepay.fee_cc_multiplier') * $amount) + config('ninja.wepay.fee_fixed');
- // charge the credit card
- $response = $this->wepay_payment_driver->wepay->request('checkout/create', [
- 'unique_id' => Str::random(40),
- 'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
- 'amount' => $amount,
- 'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
- 'short_description' => 'Goods and services',
- 'type' => 'goods',
- 'fee' => [
- 'fee_payer' => config('ninja.wepay.fee_payer'),
- 'app_fee' => $app_fee,
- ],
- 'payment_method' => [
- 'type' => 'credit_card',
- 'credit_card' => [
- 'id' => $cgt->token,
- ],
- ],
- ]);
-
- /* Merge all data and store in the payment hash*/
- $state = [
- 'server_response' => $response,
- 'payment_hash' => $payment_hash,
- ];
-
- $this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
- $this->wepay_payment_driver->payment_hash->save();
-
- if (in_array($response->state, ['authorized', 'captured'])) {
- //success
- nlog('success');
- $payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
-
- return $this->processSuccessfulPayment($response, $payment_status, GatewayType::CREDIT_CARD, true);
- }
-
- if (in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])) {
- //some type of failure
- nlog('failure');
-
- $payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
-
- $this->processUnSuccessfulPayment($response, $payment_status);
- }
- }
-}
diff --git a/app/PaymentDrivers/WePay/Setup.php b/app/PaymentDrivers/WePay/Setup.php
deleted file mode 100644
index 19b04e95c27a..000000000000
--- a/app/PaymentDrivers/WePay/Setup.php
+++ /dev/null
@@ -1,34 +0,0 @@
-wepay = $wepay;
- }
-
- public function boot($data)
- {
- /*
- 'user_id',
- 'user_company',
- */
-
- return render('gateways.wepay.signup.index', $data);
- }
-}
diff --git a/app/PaymentDrivers/WePay/WePayCommon.php b/app/PaymentDrivers/WePay/WePayCommon.php
deleted file mode 100644
index ab3365f41655..000000000000
--- a/app/PaymentDrivers/WePay/WePayCommon.php
+++ /dev/null
@@ -1,75 +0,0 @@
- $payment_type,
- 'amount' => $response->amount,
- 'transaction_reference' => $response->checkout_id,
- 'gateway_type_id' => $gateway_type,
- ];
-
- $payment = $this->wepay_payment_driver->createPayment($data, $payment_status);
-
- SystemLogger::dispatch(
- ['response' => $this->wepay_payment_driver->payment_hash->data->server_response, 'data' => $data],
- SystemLog::CATEGORY_GATEWAY_RESPONSE,
- SystemLog::EVENT_GATEWAY_SUCCESS,
- SystemLog::TYPE_WEPAY,
- $this->wepay_payment_driver->client,
- $this->wepay_payment_driver->client->company,
- );
-
- if ($return_payment) {
- return $payment;
- }
-
- return redirect()->route('client.payments.show', ['payment' => $this->wepay_payment_driver->encodePrimaryKey($payment->id)]);
- }
-
- private function processUnSuccessfulPayment($response, $payment_status)
- {
- $this->wepay_payment_driver->sendFailureMail($response->state);
-
- $message = [
- 'server_response' => $response,
- 'data' => $this->wepay_payment_driver->payment_hash->data,
- ];
-
- SystemLogger::dispatch(
- $message,
- SystemLog::CATEGORY_GATEWAY_RESPONSE,
- SystemLog::EVENT_GATEWAY_FAILURE,
- SystemLog::TYPE_WEPAY,
- $this->wepay_payment_driver->client,
- $this->wepay_payment_driver->client->company,
- );
-
- throw new PaymentFailed('Failed to process the payment.', 500);
- }
-}
diff --git a/app/PaymentDrivers/WePayPaymentDriver.php b/app/PaymentDrivers/WePayPaymentDriver.php
index 4b7254344e80..2cd93f7905de 100644
--- a/app/PaymentDrivers/WePayPaymentDriver.php
+++ b/app/PaymentDrivers/WePayPaymentDriver.php
@@ -17,13 +17,12 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
-use App\PaymentDrivers\WePay\ACH;
-use App\PaymentDrivers\WePay\CreditCard;
-use App\PaymentDrivers\WePay\Setup;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
-use WePay;
+/**
+ * @deprecated 5.9
+ */
class WePayPaymentDriver extends BaseDriver
{
use MakesHash;
@@ -45,27 +44,14 @@ class WePayPaymentDriver extends BaseDriver
/* Maps the Payment Gateway Type - to its implementation */
public static $methods = [
- GatewayType::CREDIT_CARD => CreditCard::class,
- GatewayType::BANK_TRANSFER => ACH::class,
];
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_WEPAY;
public function init()
{
- if (WePay::getEnvironment() == 'none') {
- if (config('ninja.wepay.environment') == 'staging') {
- WePay::useStaging(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret'));
- } else {
- WePay::useProduction(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret'));
- }
- }
+ throw new \Exception("Gateway no longer supported", 500);
- if ($this->company_gateway) {
- $this->wepay = new WePay($this->company_gateway->getConfigField('accessToken'));
- } else {
- $this->wepay = new WePay(null);
- }
return $this;
}
@@ -93,7 +79,6 @@ class WePayPaymentDriver extends BaseDriver
*/
public function setup(array $data)
{
- return (new Setup($this))->boot($data);
}
/**
@@ -168,140 +153,17 @@ class WePayPaymentDriver extends BaseDriver
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
{
$this->init();
-
- $input = $request->all();
-
- $config = $this->company_gateway->getConfig();
-
- $accountId = $this->company_gateway->getConfigField('accountId');
- $objectId = false;
- $objectType = '';
-
- foreach (array_keys($input) as $key) {
- if ('_id' == substr($key, -3)) {
- $objectType = substr($key, 0, -3);
- $objectId = $input[$key];
- break;
- }
- }
-
- if (! $objectId) {
- throw new \Exception('Could not find object id parameter');
- }
-
- if ($objectType == 'credit_card') {
- $payment_method = ClientGatewayToken::where('token', $objectId)->first();
-
- if (! $payment_method) {
- throw new \Exception('Unknown payment method');
- }
-
- $source = $this->wepay->request('credit_card', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'credit_card_id' => (int) $objectId,
- ]);
-
- if ($source->state == 'deleted') {
- $payment_method->delete();
- } else {
- //$this->paymentService->convertPaymentMethodFromWePay($source, null, $paymentMethod)->save();
- }
-
- return 'Processed successfully';
- } elseif ($objectType == 'account') {
- if ($accountId != $objectId) {
- throw new \Exception('Unknown account '.$accountId.' does not equal '.$objectId);
- }
-
- $wepayAccount = $this->wepay->request('account', [
- 'account_id' => (int) $objectId,
- ]);
-
- if ($wepayAccount->state == 'deleted') {
- $this->company_gateway->delete();
- } else {
- $config->state = $wepayAccount->state;
- $this->company_gateway->setConfig($config);
- $this->company_gateway->save();
- }
-
- return ['message' => 'Processed successfully'];
- } elseif ($objectType == 'checkout') {
- /** @var \App\Models\Payment $payment */
- $payment = Payment::where('company_id', $this->company_gateway->company_id)
- ->where('transaction_reference', '=', $objectId)
- ->first();
-
- if (! $payment) {
- throw new \Exception('Unknown payment');
- }
-
- if ($payment->is_deleted) {
- throw new \Exception('Payment is deleted');
- }
-
- $checkout = $this->wepay->request('checkout', [
- 'checkout_id' => intval($objectId),
- ]);
-
- if ($checkout->state == 'captured') {
- $payment->status_id = Payment::STATUS_COMPLETED;
- $payment->save();
- } elseif ($checkout->state == 'cancelled') {
- $payment->service()->deletePayment()->save();
- } elseif ($checkout->state == 'failed') {
- $payment->status_id = Payment::STATUS_FAILED;
- $payment->save();
- }
-
- return 'Processed successfully';
- } else {
- return 'Ignoring event';
- }
-
- return true;
}
public function refund(Payment $payment, $amount, $return_client_response = false)
{
$this->init();
- $response = $this->wepay->request('checkout/refund', [
- 'checkout_id' => $payment->transaction_reference,
- 'refund_reason' => 'Refund by merchant',
- 'amount' => $amount,
- ]);
-
- return [
- 'transaction_reference' => $response->checkout_id,
- 'transaction_response' => json_encode($response),
- 'success' => $response->state == 'refunded' ? true : false,
- 'description' => 'refund',
- 'code' => 0,
- ];
}
public function detach(ClientGatewayToken $token)
{
- /*Bank accounts cannot be deleted - only CC*/
- if ($token->gateway_type_id == 2) {
- return true;
- }
-
- $this->init();
-
- $response = $this->wepay->request('/credit_card/delete', [
- 'client_id' => config('ninja.wepay.client_id'),
- 'client_secret' => config('ninja.wepay.client_secret'),
- 'credit_card_id' => intval($token->token),
- ]);
-
- if ($response->state == 'deleted') {
- return true;
- } else {
- throw new \Exception(trans('texts.failed_remove_payment_method'));
- }
+
}
public function getClientRequiredFields(): array
diff --git a/app/Providers/ClientPortalServiceProvider.php b/app/Providers/ClientPortalServiceProvider.php
index 46abc838b0cc..5c134bdb8e90 100644
--- a/app/Providers/ClientPortalServiceProvider.php
+++ b/app/Providers/ClientPortalServiceProvider.php
@@ -1,4 +1,13 @@
bank_integration_id = $data['bank_integration_id'];
}
-
$bank_transaction->fill($data);
$bank_transaction->save();
@@ -43,7 +42,7 @@ class BankTransactionRepository extends BaseRepository
$data['transactions'] = $bank_transactions->map(function ($bt) {
return ['id' => $bt->id, 'invoice_ids' => $bt->invoice_ids, 'ninja_category_id' => $bt->ninja_category_id];
})->toArray();
-
+
$bts = (new MatchBankTransactions($user->company()->id, $user->company()->db, $data))->handle();
}
diff --git a/app/Services/EDocument/Standards/FatturaPANew.php b/app/Services/EDocument/Standards/FatturaPANew.php
new file mode 100644
index 000000000000..870021d08ddd
--- /dev/null
+++ b/app/Services/EDocument/Standards/FatturaPANew.php
@@ -0,0 +1,288 @@
+init()
+ ->setIdTrasmittente() //order of execution matters.
+ ->setDatiTrasmissione()
+ ->setIdFiscaleIVA()
+ ->setAnagrafica()
+ ->setDatiAnagrafici()
+ ->setCedentePrestatore()
+ ->setClientDetails()
+ ->setDatiGeneraliDocumento()
+ ->setDatiGenerali()
+ ->setLineItems()
+ ->setDettaglioPagamento()
+ ->setFatturaElettronica();
+ }
+
+ public function getFatturaElettronica(): FatturaElettronica
+ {
+ return $this->FatturaElettronica;
+ }
+
+ private function setDatiTrasmissione(): self
+ {
+
+ $this->DatiTrasmissione->FormatoTrasmissione = "FPR12";
+ $this->DatiTrasmissione->CodiceDestinatario = $this->invoice->client->routing_id;
+ $this->DatiTrasmissione->ProgressivoInvio = $this->invoice->number;
+
+ $this->DatiTrasmissione->IdTrasmittente = $this->IdTrasmittente;
+
+ $this->FatturaElettronicaHeader->DatiTrasmissione = $this->DatiTrasmissione;
+
+ return $this;
+ }
+
+
+ private function setIdTrasmittente():self
+ {
+ $this->IdTrasmittente->IdPaese = $this->invoice->company->country()->iso_3166_2;
+ $this->IdTrasmittente->IdCodice = $this->invoice->company->settings->vat_number;
+
+ return $this;
+ }
+
+ private function setCedentePrestatore():self
+ {
+ $this->CedentePrestatore->DatiAnagrafici = $this->DatiAnagrafici;
+
+ $sede = new Sede;
+ $sede->Indirizzo = $this->invoice->company->settings->address1;
+ $sede->CAP = (int)$this->invoice->company->settings->postal_code;
+ $sede->Comune = $this->invoice->company->settings->city;
+ $sede->Provincia = $this->invoice->company->settings->state;
+ $sede->Nazione = $this->invoice->company->country()->iso_3166_2;
+ $this->CedentePrestatore->Sede = $sede;
+
+ $this->FatturaElettronicaHeader->CedentePrestatore = $this->CedentePrestatore;
+
+ return $this;
+ }
+
+ private function setDatiAnagrafici():self
+ {
+ $this->DatiAnagrafici->RegimeFiscale = "RF01";
+ $this->DatiAnagrafici->Anagrafica = $this->Anagrafica;
+ $this->DatiAnagrafici->IdFiscaleIVA = $this->IdFiscaleIVA;
+
+ return $this;
+ }
+
+ private function setClientDetails():self
+ {
+
+ $datiAnagrafici = new DatiAnagrafici();
+ $anagrafica = new Anagrafica();
+ $anagrafica->Denominazione = $this->invoice->client->present()->name();
+ $datiAnagrafici->Anagrafica = $anagrafica;
+
+ $idFiscale = new IdFiscaleIVA;
+ $idFiscale->IdCodice= $this->invoice->client->vat_number;
+ $idFiscale->IdPaese = $this->invoice->client->country->iso_3166_2;
+
+ $datiAnagrafici->IdFiscaleIVA = $idFiscale;
+
+ $sede = new Sede;
+ $sede->Indirizzo = $this->invoice->client->address1;
+ $sede->CAP = (int)$this->invoice->client->postal_code;
+ $sede->Comune = $this->invoice->client->city;
+ $sede->Provincia = $this->invoice->client->state;
+ $sede->Nazione = $this->invoice->client->country->iso_3166_2;
+
+ $cessionarioCommittente = new CessionarioCommittente;
+ $cessionarioCommittente->DatiAnagrafici = $datiAnagrafici;
+ $cessionarioCommittente->Sede = $sede;
+
+ $this->FatturaElettronicaHeader->CessionarioCommittente = $cessionarioCommittente;
+
+ return $this;
+ }
+
+ private function setIdFiscaleIVA():self
+ {
+
+ $this->IdFiscaleIVA->IdPaese = $this->invoice->company->country()->iso_3166_2;
+ $this->IdFiscaleIVA->IdCodice = $this->invoice->company->settings->vat_number;
+
+ return $this;
+ }
+
+ //this is a choice, need to switch based on values here.
+ private function setAnagrafica():self
+ {
+ $this->Anagrafica->Denominazione = $this->invoice->company->present()->name();
+
+ return $this;
+ }
+
+ private function setDatiGeneraliDocumento():self
+ {
+
+ $this->DatiGeneraliDocumento->TipoDocumento = "TD01";
+ $this->DatiGeneraliDocumento->Divisa = $this->invoice->client->currency()->code;
+ $this->DatiGeneraliDocumento->Data = new \DateTime($this->invoice->date);
+ $this->DatiGeneraliDocumento->Numero = $this->invoice->number;
+ $this->DatiGeneraliDocumento->Causale[] = substr($this->invoice->public_notes ?? '',0, 200); //unsure..
+
+ return $this;
+ }
+
+ private function setDatiGenerali():self
+ {
+ $this->DatiGenerali->DatiGeneraliDocumento = $this->DatiGeneraliDocumento;
+
+ $this->FatturaElettronicaBody->DatiGenerali = $this->DatiGenerali;
+
+ return $this;
+ }
+
+ private function setDettaglioPagamento():self
+ {
+
+ $this->DettaglioPagamento->ModalitaPagamento = "MP01"; //String
+ $this->DettaglioPagamento->DataScadenzaPagamento = new \DateTime($this->invoice->due_date ?? $this->invoice->date);
+ $this->DettaglioPagamento->ImportoPagamento = (string) sprintf('%0.2f', $this->invoice->balance);
+
+ $DatiPagamento = new DatiPagamento;
+ $DatiPagamento->CondizioniPagamento = "TP02";
+ $DatiPagamento->DettaglioPagamento[] = $this->DettaglioPagamento;
+
+ $this->FatturaElettronicaBody->DatiPagamento[] = $DatiPagamento;
+
+ return $this;
+ }
+
+ private function setLineItems(): self
+ {
+
+ $calc = $this->invoice->calc();
+
+ $datiBeniServizi = new DatiBeniServizi();
+ $tax_rate_level = 0;
+ //line items
+ foreach ($this->invoice->line_items as $key => $item) {
+
+ $numero = $key + 1;
+ $dettaglioLinee = new DettaglioLinee;
+ $dettaglioLinee->NumeroLinea = "{$numero}";
+ $dettaglioLinee->Descrizione = $item->notes ?? 'Descrizione';
+ $dettaglioLinee->Quantita = sprintf('%0.2f', $item->quantity);
+ $dettaglioLinee->PrezzoUnitario = sprintf('%0.2f', $item->cost);
+ $dettaglioLinee->PrezzoTotale = sprintf('%0.2f', $item->line_total);
+ $dettaglioLinee->AliquotaIVA = sprintf('%0.2f', $item->tax_rate1);
+
+
+ $datiBeniServizi->DettaglioLinee[] = $dettaglioLinee;
+
+ if ($item->tax_rate1 > $tax_rate_level) {
+ $tax_rate_level = sprintf('%0.2f', $item->tax_rate1);
+ }
+
+ }
+
+ //totals
+ if($this->invoice->tax_rate1 > $tax_rate_level) {
+ $tax_rate_level = sprintf('%0.2f', $this->invoice->tax_rate1);
+ }
+
+ $subtotal = sprintf('%0.2f', $calc->getSubTotal());
+ $taxes = sprintf('%0.2f', $calc->getTotalTaxes());
+
+ $datiRiepilogo = new DatiRiepilogo;
+ $datiRiepilogo->AliquotaIVA = "{$tax_rate_level}";
+ $datiRiepilogo->ImponibileImporto = "{$subtotal}";
+ $datiRiepilogo->Imposta = "{$taxes}";
+ $datiRiepilogo->EsigibilitaIVA = "I";
+
+ $datiBeniServizi->DatiRiepilogo[] = $datiRiepilogo;
+
+ $this->FatturaElettronicaBody->DatiBeniServizi = $datiBeniServizi;
+
+ return $this;
+ }
+
+ private function setFatturaElettronica(): self
+ {
+
+ $this->FatturaElettronica->FatturaElettronicaBody[] = $this->FatturaElettronicaBody;
+ $this->FatturaElettronica->FatturaElettronicaHeader = $this->FatturaElettronicaHeader;
+
+ return $this;
+ }
+
+ private function init(): self
+ {
+
+ $this->FatturaElettronica = new FatturaElettronica;
+ $this->FatturaElettronicaBody = new FatturaElettronicaBody;
+ $this->FatturaElettronicaHeader = new FatturaElettronicaHeader;
+ $this->DatiTrasmissione = new DatiTrasmissione;
+ $this->IdTrasmittente = new IdTrasmittente;
+ $this->CedentePrestatore = new CedentePrestatore;
+ $this->DatiAnagrafici = new DatiAnagrafici;
+ $this->IdFiscaleIVA = new IdFiscaleIVA;
+ $this->Anagrafica = new Anagrafica;
+ $this->DatiGeneraliDocumento = new DatiGeneraliDocumento;
+ $this->DatiGenerali = new DatiGenerali;
+ $this->DettaglioPagamento = new DettaglioPagamento;
+
+ return $this;
+
+ }
+}
\ No newline at end of file
diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php
index e56091c909d5..f1bd7ee01d11 100644
--- a/app/Services/Email/Email.php
+++ b/app/Services/Email/Email.php
@@ -302,7 +302,26 @@ class Email implements ShouldQueue
$this->cleanUpMailers();
$this->logMailError($e->getMessage(), $this->company->clients()->first());
return;
- } catch (\Exception | \RuntimeException | \Google\Service\Exception $e) {
+ }
+ catch(\Symfony\Component\Mailer\Transport\Dsn $e){
+ nlog("Incorrectly configured mail server - setting to default mail driver.");
+ $this->email_object->settings->email_sending_method = 'default';
+ return $this->setMailDriver();
+ }
+ catch(\Google\Service\Exception $e){
+
+ if ($e->getCode() == '429') {
+
+ $message = "Google rate limiting triggered, we are queueing based on Gmail requirements.";
+ $this->logMailError($message, $this->company->clients()->first());
+ sleep(rand(1, 2));
+ $this->release(900);
+ $message = null;
+ }
+
+ }
+
+ catch (\Exception | \RuntimeException $e) {
nlog("Mailer failed with {$e->getMessage()}");
$message = $e->getMessage();
@@ -916,15 +935,20 @@ class Email implements ShouldQueue
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
- $token = json_decode($guzzle->post($url, [
- 'form_params' => [
- 'client_id' => config('ninja.o365.client_id'),
- 'client_secret' => config('ninja.o365.client_secret'),
- 'scope' => 'email Mail.Send offline_access profile User.Read openid',
- 'grant_type' => 'refresh_token',
- 'refresh_token' => $user->oauth_user_refresh_token
- ],
- ])->getBody()->getContents());
+ try {
+ $token = json_decode($guzzle->post($url, [
+ 'form_params' => [
+ 'client_id' => config('ninja.o365.client_id'),
+ 'client_secret' => config('ninja.o365.client_secret'),
+ 'scope' => 'email Mail.Send offline_access profile User.Read openid',
+ 'grant_type' => 'refresh_token',
+ 'refresh_token' => $user->oauth_user_refresh_token
+ ],
+ ])->getBody()->getContents());
+ }
+ catch(\Exception $e){
+ nlog("Problem getting new Microsoft token for User: {$user->email}");
+ }
if ($token) {
$user->oauth_user_refresh_token = property_exists($token, 'refresh_token') ? $token->refresh_token : $user->oauth_user_refresh_token;
diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php
index efcc85660683..718ac515dc6b 100644
--- a/app/Services/Email/EmailDefaults.php
+++ b/app/Services/Email/EmailDefaults.php
@@ -166,9 +166,9 @@ class EmailDefaults
private function setBody(): self
{
- if (strlen($this->email->email_object->body) > 3) {
+ if (strlen($this->email->email_object->body ?? '') > 3) {
// A Custom Message has been set in the email screen.
- } elseif (strlen($this->email->email_object->settings?->{$this->email->email_object->email_template_body}) > 3) {
+ } elseif (strlen($this->email->email_object->settings?->{$this->email->email_object->email_template_body} ?? '') > 3) {
// A body has been saved in the settings.
$this->email->email_object->body = $this->email->email_object->settings?->{$this->email->email_object->email_template_body};
} else {
diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php
index c7d0a63270c6..74973c0f8a46 100644
--- a/app/Services/Payment/DeletePayment.php
+++ b/app/Services/Payment/DeletePayment.php
@@ -59,6 +59,7 @@ class DeletePayment
$this->payment->delete();
BankTransaction::query()->where('payment_id', $this->payment->id)->cursor()->each(function ($bt) {
+ $bt->invoice_ids = null;
$bt->payment_id = null;
$bt->status_id = 1;
$bt->save();
diff --git a/composer.json b/composer.json
index 06738df83297..801f0decb20a 100644
--- a/composer.json
+++ b/composer.json
@@ -31,7 +31,7 @@
],
"type": "project",
"require": {
- "php": "^8.1|^8.2",
+ "php": "^8.2",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
@@ -56,7 +56,6 @@
"hashids/hashids": "^4.0",
"hedii/laravel-gelf-logger": "^8",
"horstoeko/zugferd": "^1",
- "horstoeko/orderx": "^1",
"imdhemy/laravel-purchases": "^1.7",
"intervention/image": "^2.5",
"invoiceninja/inspector": "^2.0",
@@ -87,7 +86,6 @@
"sentry/sentry-laravel": "^3",
"setasign/fpdf": "^1.8",
"setasign/fpdi": "^2.3",
- "shopify/shopify-api": "^4.3",
"socialiteproviders/apple": "dev-master",
"socialiteproviders/microsoft": "^4.1",
"spatie/laravel-data": "^3.5",
@@ -103,12 +101,13 @@
"twig/twig": "^3",
"twilio/sdk": "^6.40",
"webpatser/laravel-countries": "dev-master#75992ad",
- "wepay/php-sdk": "^0.3",
"wildbit/postmark-php": "^4.0",
- "hyvor/php-json-exporter": "^0.0.3"
+ "hyvor/php-json-exporter": "^0.0.3",
+ "invoiceninja/einvoice": "dev-main",
+ "horstoeko/orderx": "dev-master"
},
"require-dev": {
- "php": "^8.1|^8.2",
+ "php": "^8.2",
"barryvdh/laravel-debugbar": "^3.6",
"barryvdh/laravel-ide-helper": "^2.13",
"beyondcode/laravel-query-detector": "^1.8",
@@ -120,7 +119,7 @@
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^7.0",
"phpstan/phpstan": "^1.9",
- "phpunit/phpunit": "^10.0",
+ "phpunit/phpunit": "^10",
"spatie/laravel-ignition": "^2.0",
"spaze/phpstan-stripe": "^3.0"
},
@@ -184,6 +183,10 @@
{
"type":"vcs",
"url": "https://github.com/invoiceninja/einvoice"
+ },
+ {
+ "type": "vcs",
+ "url": "https://github.com/turbo124/orderx"
}
],
"minimum-stability": "dev",
diff --git a/composer.lock b/composer.lock
index ab4aa4eec903..08e04f668141 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "6904626bbe465492796c27cd86ad4d2c",
+ "content-hash": "4a46c646e01374b4a5aaff1875fa9975",
"packages": [
{
"name": "adrienrn/php-mimetyper",
@@ -1226,16 +1226,16 @@
},
{
"name": "authorizenet/authorizenet",
- "version": "2.0.2",
+ "version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/AuthorizeNet/sdk-php.git",
- "reference": "a3e76f96f674d16e892f87c58bedb99dada4b067"
+ "reference": "e1acf55c9cb22bef1852b1e494502973ade11cce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/AuthorizeNet/sdk-php/zipball/a3e76f96f674d16e892f87c58bedb99dada4b067",
- "reference": "a3e76f96f674d16e892f87c58bedb99dada4b067",
+ "url": "https://api.github.com/repos/AuthorizeNet/sdk-php/zipball/e1acf55c9cb22bef1852b1e494502973ade11cce",
+ "reference": "e1acf55c9cb22bef1852b1e494502973ade11cce",
"shasum": ""
},
"require": {
@@ -1263,9 +1263,9 @@
],
"support": {
"issues": "https://github.com/AuthorizeNet/sdk-php/issues",
- "source": "https://github.com/AuthorizeNet/sdk-php/tree/2.0.2"
+ "source": "https://github.com/AuthorizeNet/sdk-php/tree/2.0.3"
},
- "time": "2021-03-31T18:22:14+00:00"
+ "time": "2024-05-29T17:33:13+00:00"
},
{
"name": "awobaz/compoships",
@@ -1385,16 +1385,16 @@
},
{
"name": "aws/aws-sdk-php",
- "version": "3.308.3",
+ "version": "3.308.5",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "7fa0625056fa1fcf6732f89ba37b3f630d78de59"
+ "reference": "81386b0d0fd18ae8015f279247f714c5d5acb696"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7fa0625056fa1fcf6732f89ba37b3f630d78de59",
- "reference": "7fa0625056fa1fcf6732f89ba37b3f630d78de59",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/81386b0d0fd18ae8015f279247f714c5d5acb696",
+ "reference": "81386b0d0fd18ae8015f279247f714c5d5acb696",
"shasum": ""
},
"require": {
@@ -1474,9 +1474,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.308.3"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.308.5"
},
- "time": "2024-05-24T18:29:40+00:00"
+ "time": "2024-05-29T18:08:33+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -3602,16 +3602,16 @@
},
{
"name": "google/apiclient-services",
- "version": "v0.356.0",
+ "version": "v0.357.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git",
- "reference": "8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7"
+ "reference": "c84b0ac2191d56d40d43bc18e62b37a2781040a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7",
- "reference": "8e22b0a6f661f2db3f99abb6ee5a1dcf28d370e7",
+ "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/c84b0ac2191d56d40d43bc18e62b37a2781040a9",
+ "reference": "c84b0ac2191d56d40d43bc18e62b37a2781040a9",
"shasum": ""
},
"require": {
@@ -3640,9 +3640,9 @@
],
"support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
- "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.356.0"
+ "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.357.0"
},
- "time": "2024-05-18T01:10:18+00:00"
+ "time": "2024-05-27T01:02:20+00:00"
},
{
"name": "google/auth",
@@ -4466,16 +4466,16 @@
},
{
"name": "horstoeko/orderx",
- "version": "v1.0.21",
+ "version": "dev-master",
"source": {
"type": "git",
- "url": "https://github.com/horstoeko/orderx.git",
- "reference": "eaa2bd74b03c6845a38ef4611501cc4e70adbef7"
+ "url": "https://github.com/turbo124/orderx.git",
+ "reference": "92b5f713ae3d07ba409f38218e1f0b131ad5fb05"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/horstoeko/orderx/zipball/eaa2bd74b03c6845a38ef4611501cc4e70adbef7",
- "reference": "eaa2bd74b03c6845a38ef4611501cc4e70adbef7",
+ "url": "https://api.github.com/repos/turbo124/orderx/zipball/92b5f713ae3d07ba409f38218e1f0b131ad5fb05",
+ "reference": "92b5f713ae3d07ba409f38218e1f0b131ad5fb05",
"shasum": ""
},
"require": {
@@ -4488,7 +4488,7 @@
"setasign/fpdf": "^1",
"setasign/fpdi": "^2",
"smalot/pdfparser": "^0",
- "symfony/validator": "^5|^6",
+ "symfony/validator": "^5|^6|^7",
"symfony/yaml": "^5|^6"
},
"require-dev": {
@@ -4501,13 +4501,56 @@
"sebastian/phpcpd": "^6",
"squizlabs/php_codesniffer": "^3"
},
+ "default-branch": true,
"type": "package",
"autoload": {
"psr-4": {
"horstoeko\\orderx\\": "src"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "autoload-dev": {
+ "psr-4": {
+ "horstoeko\\orderx\\tests\\": "tests"
+ }
+ },
+ "scripts": {
+ "tests": [
+ "./vendor/bin/phpunit ./tests/"
+ ],
+ "testsreal": [
+ "./vendor/bin/phpunit --configuration ./build/phpunit.xml"
+ ],
+ "phpcs": [
+ "./vendor/bin/phpcs --standard=./build/phpcsrules.xml --extensions=php --ignore=autoload.php ./src ./tests"
+ ],
+ "phpcs12": [
+ "./vendor/bin/phpcs --standard=./build/phpcsrules_psr12.xml --extensions=php --ignore=autoload.php ./src ./tests"
+ ],
+ "phpcbf": [
+ "./vendor/bin/phpcbf -q ./src ./tests"
+ ],
+ "phpcbf1": [
+ "./vendor/bin/phpcbf --standard=./build/phpcsrules_psr1.xml -q ./src ./tests"
+ ],
+ "phpcbf2": [
+ "./vendor/bin/phpcbf --standard=./build/phpcsrules_psr2.xml -q ./src ./tests"
+ ],
+ "phpcbf12": [
+ "./vendor/bin/phpcbf --standard=./build/phpcsrules_psr12.xml -q ./src ./tests"
+ ],
+ "phpcbfsq": [
+ "./vendor/bin/phpcbf --standard=./build/phpcsrules_squiz.xml -q ./src ./tests"
+ ],
+ "phpstan": [
+ "./vendor/bin/phpstan analyze -c ./build/phpstan.neon --autoload-file=vendor/autoload.php --no-interaction --no-progress --xdebug"
+ ],
+ "phpstan_cs": [
+ "./vendor/bin/phpstan analyze -c ./build/phpstan.neon --autoload-file=vendor/autoload.php --no-interaction --no-progress --error-format=checkstyle --xdebug"
+ ],
+ "makedoc": [
+ "phing -f ./build.xml projectdoc"
+ ]
+ },
"license": [
"MIT"
],
@@ -4527,10 +4570,9 @@
"orderx"
],
"support": {
- "issues": "https://github.com/horstoeko/orderx/issues",
- "source": "https://github.com/horstoeko/orderx/tree/v1.0.21"
+ "source": "https://github.com/turbo124/orderx/tree/master"
},
- "time": "2024-04-18T04:14:03+00:00"
+ "time": "2024-05-26T21:58:53+00:00"
},
{
"name": "horstoeko/stringmanagement",
@@ -4588,16 +4630,16 @@
},
{
"name": "horstoeko/zugferd",
- "version": "v1.0.47",
+ "version": "v1.0.48",
"source": {
"type": "git",
"url": "https://github.com/horstoeko/zugferd.git",
- "reference": "7a5a8b7bb44f7aebfd66af112662c30383f31dd9"
+ "reference": "32233f85860a71494716c077eb28bf9f3df5d673"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/7a5a8b7bb44f7aebfd66af112662c30383f31dd9",
- "reference": "7a5a8b7bb44f7aebfd66af112662c30383f31dd9",
+ "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/32233f85860a71494716c077eb28bf9f3df5d673",
+ "reference": "32233f85860a71494716c077eb28bf9f3df5d673",
"shasum": ""
},
"require": {
@@ -4657,9 +4699,9 @@
],
"support": {
"issues": "https://github.com/horstoeko/zugferd/issues",
- "source": "https://github.com/horstoeko/zugferd/tree/v1.0.47"
+ "source": "https://github.com/horstoeko/zugferd/tree/v1.0.48"
},
- "time": "2024-05-23T03:12:53+00:00"
+ "time": "2024-05-29T15:12:06+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
@@ -5028,6 +5070,59 @@
],
"time": "2022-05-21T17:30:32+00:00"
},
+ {
+ "name": "invoiceninja/einvoice",
+ "version": "dev-main",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/invoiceninja/einvoice.git",
+ "reference": "9b400960f1d885ef98667494f46dc1fbd3a2fbbc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/9b400960f1d885ef98667494f46dc1fbd3a2fbbc",
+ "reference": "9b400960f1d885ef98667494f46dc1fbd3a2fbbc",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/collections": "^10.48",
+ "phpdocumentor/reflection-docblock": "^5.4",
+ "sabre/xml": "^4.0",
+ "symfony/property-access": "^7",
+ "symfony/property-info": "^7.0",
+ "symfony/serializer": "^7",
+ "symfony/validator": "^7"
+ },
+ "require-dev": {
+ "milo/schematron": "^1.0",
+ "nette/php-generator": "^4.1",
+ "phpstan/phpstan": "^1.11",
+ "phpunit/phpunit": "^10.5",
+ "symfony/console": "^7"
+ },
+ "default-branch": true,
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Invoiceninja\\Einvoice\\": "src/"
+ }
+ },
+ "license": [
+ "Elastic-2.0"
+ ],
+ "authors": [
+ {
+ "name": "David Bomba",
+ "email": "turbo124@gmail.com"
+ }
+ ],
+ "description": "Schema for einvoicing standards",
+ "support": {
+ "source": "https://github.com/invoiceninja/einvoice/tree/main",
+ "issues": "https://github.com/invoiceninja/einvoice/issues"
+ },
+ "time": "2024-05-29T21:03:48+00:00"
+ },
{
"name": "invoiceninja/inspector",
"version": "v2.0",
@@ -5589,16 +5684,16 @@
},
{
"name": "laravel/framework",
- "version": "v10.48.11",
+ "version": "v10.48.12",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "afdc2b03bd8d126446583da5414d659491aa4f54"
+ "reference": "590afea38e708022662629fbf5184351fa82cf08"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/afdc2b03bd8d126446583da5414d659491aa4f54",
- "reference": "afdc2b03bd8d126446583da5414d659491aa4f54",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/590afea38e708022662629fbf5184351fa82cf08",
+ "reference": "590afea38e708022662629fbf5184351fa82cf08",
"shasum": ""
},
"require": {
@@ -5792,20 +5887,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2024-05-21T17:53:51+00:00"
+ "time": "2024-05-28T15:46:19+00:00"
},
{
"name": "laravel/prompts",
- "version": "v0.1.22",
+ "version": "v0.1.23",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5"
+ "reference": "9bc4df7c699b0452c6b815e64a2d84b6d7f99400"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
- "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/9bc4df7c699b0452c6b815e64a2d84b6d7f99400",
+ "reference": "9bc4df7c699b0452c6b815e64a2d84b6d7f99400",
"shasum": ""
},
"require": {
@@ -5848,9 +5943,9 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
- "source": "https://github.com/laravel/prompts/tree/v0.1.22"
+ "source": "https://github.com/laravel/prompts/tree/v0.1.23"
},
- "time": "2024-05-10T19:22:18+00:00"
+ "time": "2024-05-27T13:53:20+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -6176,34 +6271,34 @@
},
{
"name": "lcobucci/clock",
- "version": "3.0.0",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/clock.git",
- "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc"
+ "reference": "6f28b826ea01306b07980cb8320ab30b966cd715"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc",
- "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc",
+ "url": "https://api.github.com/repos/lcobucci/clock/zipball/6f28b826ea01306b07980cb8320ab30b966cd715",
+ "reference": "6f28b826ea01306b07980cb8320ab30b966cd715",
"shasum": ""
},
"require": {
- "php": "~8.1.0 || ~8.2.0",
+ "php": "~8.2.0 || ~8.3.0",
"psr/clock": "^1.0"
},
"provide": {
"psr/clock-implementation": "1.0"
},
"require-dev": {
- "infection/infection": "^0.26",
- "lcobucci/coding-standard": "^9.0",
- "phpstan/extension-installer": "^1.2",
- "phpstan/phpstan": "^1.9.4",
- "phpstan/phpstan-deprecation-rules": "^1.1.1",
- "phpstan/phpstan-phpunit": "^1.3.2",
- "phpstan/phpstan-strict-rules": "^1.4.4",
- "phpunit/phpunit": "^9.5.27"
+ "infection/infection": "^0.27",
+ "lcobucci/coding-standard": "^11.0.0",
+ "phpstan/extension-installer": "^1.3.1",
+ "phpstan/phpstan": "^1.10.25",
+ "phpstan/phpstan-deprecation-rules": "^1.1.3",
+ "phpstan/phpstan-phpunit": "^1.3.13",
+ "phpstan/phpstan-strict-rules": "^1.5.1",
+ "phpunit/phpunit": "^10.2.3"
},
"type": "library",
"autoload": {
@@ -6224,7 +6319,7 @@
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/clock/issues",
- "source": "https://github.com/lcobucci/clock/tree/3.0.0"
+ "source": "https://github.com/lcobucci/clock/tree/3.2.0"
},
"funding": [
{
@@ -6236,7 +6331,7 @@
"type": "patreon"
}
],
- "time": "2022-12-19T15:00:24+00:00"
+ "time": "2023-11-17T17:00:27+00:00"
},
{
"name": "lcobucci/jwt",
@@ -9480,6 +9575,70 @@
},
"time": "2020-06-27T09:03:43+00:00"
},
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "5.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c",
+ "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.1",
+ "ext-filter": "*",
+ "php": "^7.4 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.2",
+ "phpdocumentor/type-resolver": "^1.7",
+ "phpstan/phpdoc-parser": "^1.7",
+ "webmozart/assert": "^1.9.1"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.3.5",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-mockery": "^1.1",
+ "phpstan/phpstan-webmozart-assert": "^1.2",
+ "phpunit/phpunit": "^9.5",
+ "vimeo/psalm": "^5.13"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ },
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "opensource@ijaap.nl"
+ }
+ ],
+ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+ "support": {
+ "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
+ "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1"
+ },
+ "time": "2024-05-21T05:55:05+00:00"
+ },
{
"name": "phpdocumentor/type-resolver",
"version": "1.8.2",
@@ -11534,69 +11693,6 @@
],
"time": "2023-12-11T16:03:32+00:00"
},
- {
- "name": "shopify/shopify-api",
- "version": "v4.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/Shopify/shopify-api-php.git",
- "reference": "80cde593a69acb9b9095235fa8f7748e9389294c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Shopify/shopify-api-php/zipball/80cde593a69acb9b9095235fa8f7748e9389294c",
- "reference": "80cde593a69acb9b9095235fa8f7748e9389294c",
- "shasum": ""
- },
- "require": {
- "doctrine/inflector": "^2.0",
- "ext-json": "*",
- "firebase/php-jwt": "^5.2 || ^6.2",
- "guzzlehttp/guzzle": "^7.0",
- "php": "^7.4 || ^8.0 || ^8.1",
- "psr/http-client": "^1.0",
- "psr/log": "^1.1 || ^2.0 || ^3.0",
- "ramsey/uuid": "^4.1"
- },
- "require-dev": {
- "mikey179/vfsstream": "^1.6",
- "phpunit/phpunit": "^9",
- "squizlabs/php_codesniffer": "^3.6"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Shopify\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Shopify Inc.",
- "email": "dev-tools-education@shopify.com"
- }
- ],
- "description": "Shopify API Library for PHP",
- "keywords": [
- "Storefront API",
- "admin api",
- "app",
- "graphql",
- "jwt",
- "node",
- "rest",
- "shopify",
- "webhook"
- ],
- "support": {
- "issues": "https://github.com/Shopify/shopify-api-php/issues",
- "source": "https://github.com/Shopify/shopify-api-php/tree/v4.3.0"
- },
- "time": "2023-04-12T15:42:26+00:00"
- },
{
"name": "smalot/pdfparser",
"version": "v0.19.0",
@@ -12421,20 +12517,20 @@
},
{
"name": "symfony/css-selector",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b"
+ "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/1c5d5c2103c3762aff27a27e1e2409e30a79083b",
- "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
+ "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.2"
},
"type": "library",
"autoload": {
@@ -12466,7 +12562,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v6.4.7"
+ "source": "https://github.com/symfony/css-selector/tree/v7.0.7"
},
"funding": [
{
@@ -12482,7 +12578,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -12628,24 +12724,24 @@
},
{
"name": "symfony/event-dispatcher",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f"
+ "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d84384f3f67de3cb650db64d685d70395dacfc3f",
- "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db2a7fab994d67d92356bb39c367db115d9d30f9",
+ "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/dependency-injection": "<5.4",
+ "symfony/dependency-injection": "<6.4",
"symfony/service-contracts": "<2.5"
},
"provide": {
@@ -12654,13 +12750,13 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0|^7.0",
- "symfony/dependency-injection": "^5.4|^6.0|^7.0",
- "symfony/error-handler": "^5.4|^6.0|^7.0",
- "symfony/expression-language": "^5.4|^6.0|^7.0",
- "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^5.4|^6.0|^7.0"
+ "symfony/stopwatch": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -12688,7 +12784,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.7"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.7"
},
"funding": [
{
@@ -12704,7 +12800,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -13274,25 +13370,25 @@
},
{
"name": "symfony/intl",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/intl.git",
- "reference": "9ed7dfeeba5759b61798358100bb63230509b337"
+ "reference": "dd12042707110995e2e7d80103f8d9928bea8621"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/intl/zipball/9ed7dfeeba5759b61798358100bb63230509b337",
- "reference": "9ed7dfeeba5759b61798358100bb63230509b337",
+ "url": "https://api.github.com/repos/symfony/intl/zipball/dd12042707110995e2e7d80103f8d9928bea8621",
+ "reference": "dd12042707110995e2e7d80103f8d9928bea8621",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.2"
},
"require-dev": {
- "symfony/filesystem": "^5.4|^6.0|^7.0",
- "symfony/finder": "^5.4|^6.0|^7.0",
- "symfony/var-exporter": "^5.4|^6.0|^7.0"
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/var-exporter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -13337,7 +13433,7 @@
"localization"
],
"support": {
- "source": "https://github.com/symfony/intl/tree/v6.4.7"
+ "source": "https://github.com/symfony/intl/tree/v7.0.7"
},
"funding": [
{
@@ -13353,7 +13449,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/mailer",
@@ -13591,20 +13687,20 @@
},
{
"name": "symfony/options-resolver",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed"
+ "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9a3c92b490716ba6771f5beced13c6eda7183eed",
- "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/23cc173858776ad451e31f053b1c9f47840b2cfa",
+ "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
@@ -13638,7 +13734,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v6.4.7"
+ "source": "https://github.com/symfony/options-resolver/tree/v7.0.7"
},
"funding": [
{
@@ -13654,7 +13750,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -14582,6 +14678,165 @@
],
"time": "2024-04-18T09:22:46+00:00"
},
+ {
+ "name": "symfony/property-access",
+ "version": "v7.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-access.git",
+ "reference": "8661b861480d2807eb2789ff99d034c0c71ab955"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-access/zipball/8661b861480d2807eb2789ff99d034c0c71ab955",
+ "reference": "8661b861480d2807eb2789ff99d034c0c71ab955",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/property-info": "^6.4|^7.0"
+ },
+ "require-dev": {
+ "symfony/cache": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyAccess\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides functions to read and write from/to an object or array using a simple string notation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "access",
+ "array",
+ "extraction",
+ "index",
+ "injection",
+ "object",
+ "property",
+ "property-path",
+ "reflection"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-access/tree/v7.0.7"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-18T09:29:19+00:00"
+ },
+ {
+ "name": "symfony/property-info",
+ "version": "v7.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-info.git",
+ "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-info/zipball/f0bdb46e19ab308527b324b7ec36161f6880a532",
+ "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/string": "^6.4|^7.0"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<5.2",
+ "phpdocumentor/type-resolver": "<1.5.1",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/serializer": "<6.4"
+ },
+ "require-dev": {
+ "phpdocumentor/reflection-docblock": "^5.2",
+ "phpstan/phpdoc-parser": "^1.0",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyInfo\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kévin Dunglas",
+ "email": "dunglas@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Extracts information about PHP class' properties using metadata of popular sources",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "doctrine",
+ "phpdoc",
+ "property",
+ "symfony",
+ "type",
+ "validator"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-info/tree/v7.0.7"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-28T11:44:19+00:00"
+ },
{
"name": "symfony/psr-http-message-bridge",
"version": "v2.3.1",
@@ -14754,6 +15009,101 @@
],
"time": "2024-04-18T09:22:46+00:00"
},
+ {
+ "name": "symfony/serializer",
+ "version": "v7.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/serializer.git",
+ "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/serializer/zipball/08f0c517acf4b12dfc0d3963cd12f7b8023aea31",
+ "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/property-access": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/uid": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
+ "require-dev": {
+ "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
+ "seld/jsonlint": "^1.10",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0",
+ "symfony/var-exporter": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Serializer\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/serializer/tree/v7.0.7"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-28T11:44:19+00:00"
+ },
{
"name": "symfony/service-contracts",
"version": "v3.5.0",
@@ -14839,20 +15189,20 @@
},
{
"name": "symfony/string",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69"
+ "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69",
- "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69",
+ "url": "https://api.github.com/repos/symfony/string/zipball/e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
+ "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
@@ -14862,11 +15212,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/error-handler": "^5.4|^6.0|^7.0",
- "symfony/http-client": "^5.4|^6.0|^7.0",
- "symfony/intl": "^6.2|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^5.4|^6.0|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -14905,7 +15255,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.4.7"
+ "source": "https://github.com/symfony/string/tree/v7.0.7"
},
"funding": [
{
@@ -14921,7 +15271,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/translation",
@@ -15172,55 +15522,53 @@
},
{
"name": "symfony/validator",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/validator.git",
- "reference": "4761a08d161d823ec281151ade0905547e0502a7"
+ "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/validator/zipball/4761a08d161d823ec281151ade0905547e0502a7",
- "reference": "4761a08d161d823ec281151ade0905547e0502a7",
+ "url": "https://api.github.com/repos/symfony/validator/zipball/ab4e75b9d23ba70e78480aecbe4d8da15adf10eb",
+ "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/deprecation-contracts": "^2.5|^3",
+ "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php83": "^1.27",
"symfony/translation-contracts": "^2.5|^3"
},
"conflict": {
- "doctrine/annotations": "<1.13",
"doctrine/lexer": "<1.1",
- "symfony/dependency-injection": "<5.4",
- "symfony/expression-language": "<5.4",
- "symfony/http-kernel": "<5.4",
- "symfony/intl": "<5.4",
- "symfony/property-info": "<5.4",
- "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3",
- "symfony/yaml": "<5.4"
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<7.0",
+ "symfony/expression-language": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/intl": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
+ "symfony/yaml": "<6.4"
},
"require-dev": {
- "doctrine/annotations": "^1.13|^2",
"egulias/email-validator": "^2.1.10|^3|^4",
- "symfony/cache": "^5.4|^6.0|^7.0",
- "symfony/config": "^5.4|^6.0|^7.0",
- "symfony/console": "^5.4|^6.0|^7.0",
- "symfony/dependency-injection": "^5.4|^6.0|^7.0",
- "symfony/expression-language": "^5.4|^6.0|^7.0",
- "symfony/finder": "^5.4|^6.0|^7.0",
- "symfony/http-client": "^5.4|^6.0|^7.0",
- "symfony/http-foundation": "^5.4|^6.0|^7.0",
- "symfony/http-kernel": "^5.4|^6.0|^7.0",
- "symfony/intl": "^5.4|^6.0|^7.0",
- "symfony/mime": "^5.4|^6.0|^7.0",
- "symfony/property-access": "^5.4|^6.0|^7.0",
- "symfony/property-info": "^5.4|^6.0|^7.0",
- "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3",
- "symfony/yaml": "^5.4|^6.0|^7.0"
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/translation": "^6.4.3|^7.0.3",
+ "symfony/yaml": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -15248,7 +15596,7 @@
"description": "Provides tools to validate values",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/validator/tree/v6.4.7"
+ "source": "https://github.com/symfony/validator/tree/v7.0.7"
},
"funding": [
{
@@ -15264,7 +15612,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-28T10:38:38+00:00"
+ "time": "2024-04-28T11:44:19+00:00"
},
{
"name": "symfony/var-dumper",
@@ -16017,57 +16365,6 @@
},
"time": "2023-02-08T11:09:34+00:00"
},
- {
- "name": "wepay/php-sdk",
- "version": "0.3.1",
- "source": {
- "type": "git",
- "url": "https://github.com/wepay/PHP-SDK.git",
- "reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wepay/PHP-SDK/zipball/2a89ceb2954d117d082f869d3bfcb7864e6c2a7d",
- "reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "php": ">=5.3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "0.2.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "wepay.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "Apache-2.0"
- ],
- "authors": [
- {
- "name": "WePay",
- "email": "api@wepay.com"
- }
- ],
- "description": "WePay APIv2 SDK for PHP",
- "keywords": [
- "payment",
- "sdk",
- "wepay"
- ],
- "support": {
- "issues": "https://github.com/wepay/PHP-SDK/issues",
- "source": "https://github.com/wepay/PHP-SDK/tree/master"
- },
- "time": "2017-01-21T07:03:26+00:00"
- },
{
"name": "wildbit/postmark-php",
"version": "v4.0.5",
@@ -16400,16 +16697,16 @@
},
{
"name": "brianium/paratest",
- "version": "v7.3.1",
+ "version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/paratestphp/paratest.git",
- "reference": "551f46f52a93177d873f3be08a1649ae886b4a30"
+ "reference": "bfe354e71aca261cf37bf70bf47791081100000d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paratestphp/paratest/zipball/551f46f52a93177d873f3be08a1649ae886b4a30",
- "reference": "551f46f52a93177d873f3be08a1649ae886b4a30",
+ "url": "https://api.github.com/repos/paratestphp/paratest/zipball/bfe354e71aca261cf37bf70bf47791081100000d",
+ "reference": "bfe354e71aca261cf37bf70bf47791081100000d",
"shasum": ""
},
"require": {
@@ -16417,28 +16714,27 @@
"ext-pcre": "*",
"ext-reflection": "*",
"ext-simplexml": "*",
- "fidry/cpu-core-counter": "^0.5.1 || ^1.0.0",
- "jean85/pretty-package-versions": "^2.0.5",
- "php": "~8.1.0 || ~8.2.0 || ~8.3.0",
- "phpunit/php-code-coverage": "^10.1.7",
- "phpunit/php-file-iterator": "^4.1.0",
- "phpunit/php-timer": "^6.0",
- "phpunit/phpunit": "^10.4.2",
- "sebastian/environment": "^6.0.1",
- "symfony/console": "^6.3.4 || ^7.0.0",
- "symfony/process": "^6.3.4 || ^7.0.0"
+ "fidry/cpu-core-counter": "^1.1.0",
+ "jean85/pretty-package-versions": "^2.0.6",
+ "php": "~8.2.0 || ~8.3.0",
+ "phpunit/php-code-coverage": "^10.1.14 || ^11.0.3",
+ "phpunit/php-file-iterator": "^4.1.0 || ^5.0.0",
+ "phpunit/php-timer": "^6.0.0 || ^7.0.0",
+ "phpunit/phpunit": "^10.5.20 || ^11.1.3",
+ "sebastian/environment": "^6.1.0 || ^7.1.0",
+ "symfony/console": "^6.4.7 || ^7.0.7",
+ "symfony/process": "^6.4.7 || ^7.0.7"
},
"require-dev": {
"doctrine/coding-standard": "^12.0.0",
"ext-pcov": "*",
"ext-posix": "*",
- "infection/infection": "^0.27.6",
- "phpstan/phpstan": "^1.10.40",
+ "phpstan/phpstan": "^1.10.67",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
- "phpstan/phpstan-phpunit": "^1.3.15",
- "phpstan/phpstan-strict-rules": "^1.5.2",
- "squizlabs/php_codesniffer": "^3.7.2",
- "symfony/filesystem": "^6.3.1 || ^7.0.0"
+ "phpstan/phpstan-phpunit": "^1.3.16",
+ "phpstan/phpstan-strict-rules": "^1.5.5",
+ "squizlabs/php_codesniffer": "^3.9.2",
+ "symfony/filesystem": "^6.4.3 || ^7.0.7"
},
"bin": [
"bin/paratest",
@@ -16479,7 +16775,7 @@
],
"support": {
"issues": "https://github.com/paratestphp/paratest/issues",
- "source": "https://github.com/paratestphp/paratest/tree/v7.3.1"
+ "source": "https://github.com/paratestphp/paratest/tree/v7.4.4"
},
"funding": [
{
@@ -16491,7 +16787,7 @@
"type": "paypal"
}
],
- "time": "2023-10-31T09:24:17+00:00"
+ "time": "2024-05-03T13:01:49+00:00"
},
{
"name": "clue/ndjson-react",
@@ -16632,16 +16928,16 @@
},
{
"name": "composer/pcre",
- "version": "3.1.3",
+ "version": "3.1.4",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
+ "reference": "04229f163664973f68f38f6f73d917799168ef24"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
- "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24",
+ "reference": "04229f163664973f68f38f6f73d917799168ef24",
"shasum": ""
},
"require": {
@@ -16683,7 +16979,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.1.3"
+ "source": "https://github.com/composer/pcre/tree/3.1.4"
},
"funding": [
{
@@ -16699,7 +16995,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T10:26:25+00:00"
+ "time": "2024-05-27T13:40:54+00:00"
},
{
"name": "composer/semver",
@@ -17029,16 +17325,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.57.2",
+ "version": "v3.58.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "22f7f3145606df92b02fb1bd22c30abfce956d3c"
+ "reference": "04e9424025677a86914b9a4944dbbf4060bb0aff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/22f7f3145606df92b02fb1bd22c30abfce956d3c",
- "reference": "22f7f3145606df92b02fb1bd22c30abfce956d3c",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/04e9424025677a86914b9a4944dbbf4060bb0aff",
+ "reference": "04e9424025677a86914b9a4944dbbf4060bb0aff",
"shasum": ""
},
"require": {
@@ -17117,7 +17413,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.57.2"
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.58.1"
},
"funding": [
{
@@ -17125,7 +17421,7 @@
"type": "github"
}
],
- "time": "2024-05-20T20:41:57+00:00"
+ "time": "2024-05-29T16:39:07+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -17239,16 +17535,16 @@
},
{
"name": "larastan/larastan",
- "version": "v2.9.6",
+ "version": "v2.9.7",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
- "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f"
+ "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/larastan/larastan/zipball/93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f",
- "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f",
+ "url": "https://api.github.com/repos/larastan/larastan/zipball/5c805f636095cc2e0b659e3954775cf8f1dad1bb",
+ "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb",
"shasum": ""
},
"require": {
@@ -17262,7 +17558,7 @@
"illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0",
"php": "^8.0.2",
"phpmyadmin/sql-parser": "^5.9.0",
- "phpstan/phpstan": "^1.10.66"
+ "phpstan/phpstan": "^1.11.1"
},
"require-dev": {
"doctrine/coding-standard": "^12.0",
@@ -17317,7 +17613,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
- "source": "https://github.com/larastan/larastan/tree/v2.9.6"
+ "source": "https://github.com/larastan/larastan/tree/v2.9.7"
},
"funding": [
{
@@ -17337,7 +17633,7 @@
"type": "patreon"
}
],
- "time": "2024-05-09T11:53:26+00:00"
+ "time": "2024-05-27T18:33:26+00:00"
},
{
"name": "maximebf/debugbar",
@@ -19911,16 +20207,16 @@
},
{
"name": "spatie/ignition",
- "version": "1.14.1",
+ "version": "1.14.2",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
- "reference": "c23cc018c5f423d2f413b99f84655fceb6549811"
+ "reference": "5e11c11f675bb5251f061491a493e04a1a571532"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/ignition/zipball/c23cc018c5f423d2f413b99f84655fceb6549811",
- "reference": "c23cc018c5f423d2f413b99f84655fceb6549811",
+ "url": "https://api.github.com/repos/spatie/ignition/zipball/5e11c11f675bb5251f061491a493e04a1a571532",
+ "reference": "5e11c11f675bb5251f061491a493e04a1a571532",
"shasum": ""
},
"require": {
@@ -19990,7 +20286,7 @@
"type": "github"
}
],
- "time": "2024-05-03T15:56:16+00:00"
+ "time": "2024-05-29T08:10:20+00:00"
},
{
"name": "spatie/laravel-ignition",
@@ -20224,20 +20520,20 @@
},
{
"name": "symfony/stopwatch",
- "version": "v6.4.7",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "ffec95ba269e541eb2232126c0c20f83086b5c68"
+ "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ffec95ba269e541eb2232126c0c20f83086b5c68",
- "reference": "ffec95ba269e541eb2232126c0c20f83086b5c68",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/41a7a24aa1dc82adf46a06bc292d1923acfe6b84",
+ "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/service-contracts": "^2.5|^3"
},
"type": "library",
@@ -20266,7 +20562,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/stopwatch/tree/v6.4.7"
+ "source": "https://github.com/symfony/stopwatch/tree/v7.0.7"
},
"funding": [
{
@@ -20282,7 +20578,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:22:46+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "theseer/tokenizer",
@@ -20339,18 +20635,20 @@
"minimum-stability": "dev",
"stability-flags": {
"socialiteproviders/apple": 20,
- "webpatser/laravel-countries": 20
+ "webpatser/laravel-countries": 20,
+ "invoiceninja/einvoice": 20,
+ "horstoeko/orderx": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": "^8.1|^8.2",
+ "php": "^8.2",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*"
},
"platform-dev": {
- "php": "^8.1|^8.2"
+ "php": "^8.2"
},
"plugin-api-version": "2.3.0"
}
diff --git a/config/ninja.php b/config/ninja.php
index 1543dfb44c9f..0d4f30250d7c 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -54,17 +54,14 @@ return [
'hosted' => env('TERMS_OF_SERVICE_URL', 'https://www.invoiceninja.com/terms/'),
'selfhost' => env('TERMS_OF_SERVICE_URL', 'https://www.invoiceninja.com/self-hosting-terms-service/'),
],
-
'privacy_policy_url' => [
'hosted' => env('PRIVACY_POLICY_URL', 'https://www.invoiceninja.com/privacy-policy/'),
'selfhost' => env('PRIVACY_POLICY_URL', 'https://www.invoiceninja.com/self-hosting-privacy-data-control/'),
],
-
'db' => [
'multi_db_enabled' => env('MULTI_DB_ENABLED', false),
'default' => env('DB_CONNECTION', 'mysql'),
],
-
'i18n' => [
'timezone_id' => env('DEFAULT_TIMEZONE', 1),
'country_id' => env('DEFAULT_COUNTRY', 840), // United Stated
@@ -79,7 +76,6 @@ return [
'first_day_of_week' => env('FIRST_DATE_OF_WEEK', 0),
'first_month_of_year' => env('FIRST_MONTH_OF_YEAR', '2000-01-01'),
],
-
'testvars' => [
'username' => 'user@example.com',
'clientname' => 'client@example.com',
diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php
index 3b0463502f76..f979c8d7d30e 100644
--- a/database/factories/ClientFactory.php
+++ b/database/factories/ClientFactory.php
@@ -13,6 +13,7 @@ namespace Database\Factories;
use App\DataMapper\ClientSettings;
use Illuminate\Database\Eloquent\Factories\Factory;
+use Str;
class ClientFactory extends Factory
{
@@ -49,6 +50,7 @@ class ClientFactory extends Factory
'shipping_country_id' => 4,
'settings' => ClientSettings::defaults(),
'client_hash' => \Illuminate\Support\Str::random(40),
+ 'routing_id' => rand(100000,200000),
];
}
}
diff --git a/database/migrations/2024_05_26_210407_2024_05_28_kwd_precision.php b/database/migrations/2024_05_26_210407_2024_05_28_kwd_precision.php
new file mode 100644
index 000000000000..779abac80f41
--- /dev/null
+++ b/database/migrations/2024_05_26_210407_2024_05_28_kwd_precision.php
@@ -0,0 +1,28 @@
+precision = 3;
+ $currency->save();
+ }
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ //
+ }
+};
diff --git a/database/seeders/CurrenciesSeeder.php b/database/seeders/CurrenciesSeeder.php
index 1c69e5771e7b..90c900835bdc 100644
--- a/database/seeders/CurrenciesSeeder.php
+++ b/database/seeders/CurrenciesSeeder.php
@@ -111,7 +111,7 @@ class CurrenciesSeeder extends Seeder
['id' => 86, 'name' => 'CFP Franc', 'code' => 'XPF', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], // precision should be zero
['id' => 87, 'name' => 'Mauritian Rupee', 'code' => 'MUR', 'symbol' => 'Rs', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['id' => 88, 'name' => 'Cape Verdean Escudo', 'code' => 'CVE', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => '$'],
- ['id' => 89, 'name' => 'Kuwaiti Dinar', 'code' => 'KWD', 'symbol' => 'KD', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
+ ['id' => 89, 'name' => 'Kuwaiti Dinar', 'code' => 'KWD', 'symbol' => 'KD', 'precision' => '3', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['id' => 90, 'name' => 'Algerian Dinar', 'code' => 'DZD', 'symbol' => 'DA', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['id' => 91, 'name' => 'Macedonian Denar', 'code' => 'MKD', 'symbol' => 'ден', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['id' => 92, 'name' => 'Fijian Dollar', 'code' => 'FJD', 'symbol' => 'FJ$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
diff --git a/lang/en/texts.php b/lang/en/texts.php
index 3f0bfe40cfed..719c858c6334 100644
--- a/lang/en/texts.php
+++ b/lang/en/texts.php
@@ -5328,6 +5328,9 @@ $lang = array(
'disconnected' => 'Disconnected',
'reconnect' => 'Reconnect',
'e_invoice_settings' => 'E-Invoice Settings',
+ 'currency_mauritanian_ouguiya' => 'Mauritanian Ouguiya',
+ 'currency_bhutan_ngultrum' => 'Bhutan Ngultrum',
+
);
return $lang;
diff --git a/phpunit.xml b/phpunit.xml
index 113938ad5e36..1c27f29b2b43 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -25,7 +25,7 @@
-
+
diff --git a/routes/web.php b/routes/web.php
index 68878ac6869e..1d56f5d88390 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -13,7 +13,6 @@ use App\Http\Controllers\Gateways\Mollie3dsController;
use App\Http\Controllers\SetupController;
use App\Http\Controllers\StripeConnectController;
use App\Http\Controllers\UserController;
-use App\Http\Controllers\WePayController;
use Illuminate\Support\Facades\Route;
Route::get('/', [BaseController::class, 'flutterRoute'])->middleware('guest');
@@ -31,9 +30,6 @@ Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEm
Route::get('password/reset/{token}', [ResetPasswordController::class, 'showResetForm'])->middleware(['domain_db', 'email_db'])->name('password.reset');
Route::post('password/reset', [ResetPasswordController::class, 'reset'])->middleware('email_db')->name('password.update');
-Route::get('wepay/signup/{token}', [WePayController::class, 'signup'])->name('wepay.signup');
-Route::get('wepay/finished', [WePayController::class, 'finished'])->name('wepay.finished');
-
Route::get('auth/{provider}', [LoginController::class, 'redirectToProvider']);
Route::middleware('url_db')->group(function () {
diff --git a/tests/Feature/ClientGatewayTokenApiTest.php b/tests/Feature/ClientGatewayTokenApiTest.php
index 9a7849de06f6..11b089b10d37 100644
--- a/tests/Feature/ClientGatewayTokenApiTest.php
+++ b/tests/Feature/ClientGatewayTokenApiTest.php
@@ -11,13 +11,14 @@
namespace Tests\Feature;
-use App\Models\CompanyGateway;
+use Tests\TestCase;
+use Tests\MockAccountData;
use App\Models\GatewayType;
+use App\Models\CompanyGateway;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
-use Tests\MockAccountData;
-use Tests\TestCase;
/**
* @test
@@ -29,6 +30,9 @@ class ClientGatewayTokenApiTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
+ protected $faker;
+ protected CompanyGateway $cg;
+
protected function setUp() :void
{
parent::setUp();
diff --git a/tests/Feature/EInvoice/FatturaPATest.php b/tests/Feature/EInvoice/FatturaPATest.php
index bb683e10acb0..1d70d00d73fc 100644
--- a/tests/Feature/EInvoice/FatturaPATest.php
+++ b/tests/Feature/EInvoice/FatturaPATest.php
@@ -11,11 +11,21 @@
namespace Tests\Feature\EInvoice;
-use App\Services\EDocument\Standards\FatturaPA;
-use Illuminate\Foundation\Testing\DatabaseTransactions;
-use Illuminate\Routing\Middleware\ThrottleRequests;
-use Tests\MockAccountData;
use Tests\TestCase;
+use App\Models\Client;
+use App\Models\Company;
+use Tests\MockAccountData;
+use App\DataMapper\ClientSettings;
+use App\DataMapper\CompanySettings;
+use App\DataMapper\InvoiceItem;
+use App\Models\Invoice;
+use Invoiceninja\Einvoice\Symfony\Encode;
+use App\Services\EDocument\Standards\FatturaPANew;
+use Illuminate\Routing\Middleware\ThrottleRequests;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
+use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
+use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
/**
* @test
@@ -31,6 +41,9 @@ class FatturaPATest extends TestCase
$this->makeTestData();
+
+ $this->markTestSkipped('prevent running in CI');
+
$this->withoutMiddleware(
ThrottleRequests::class
);
@@ -38,9 +51,86 @@ class FatturaPATest extends TestCase
public function testInvoiceBoot()
{
- $fat = new FatturaPA($this->invoice);
- $xml = $fat->run();
- $this->assertnotNull($xml);
+ $settings = CompanySettings::defaults();
+ $settings->address1 = 'Via Silvio Spaventa 108';
+ $settings->city = 'Calcinelli';
+
+$settings->state = 'PA';
+
+// $settings->state = 'Perugia';
+ $settings->postal_code = '61030';
+ $settings->country_id = '380';
+ $settings->currency_id = '3';
+ $settings->vat_number = '01234567890';
+ $settings->id_number = '';
+
+ $company = Company::factory()->create([
+ 'account_id' => $this->account->id,
+ 'settings' => $settings,
+ ]);
+
+ $client_settings = ClientSettings::defaults();
+ $client_settings->currency_id = '3';
+
+ $client = Client::factory()->create([
+ 'company_id' => $company->id,
+ 'user_id' => $this->user->id,
+ 'name' => 'Italian Client Name',
+ 'address1' => 'Via Antonio da Legnago 68',
+ 'city' => 'Monasterace',
+ 'state' => 'CR',
+ // 'state' => 'Reggio Calabria',
+ 'postal_code' => '89040',
+ 'country_id' => 380,
+ 'routing_id' => 'ABC1234',
+ 'settings' => $client_settings,
+ ]);
+
+ $item = new InvoiceItem;
+ $item->product_key = "Product Key";
+ $item->notes = "Product Description";
+ $item->cost = 10;
+ $item->quantity = 10;
+ $item->tax_rate1 = 22;
+ $item->tax_name1 = 'IVA';
+
+ $invoice = Invoice::factory()->create([
+ 'company_id' => $company->id,
+ 'user_id' => $this->user->id,
+ 'client_id' => $client->id,
+ 'discount' => 0,
+ 'uses_inclusive_taxes' => false,
+ 'status_id' => 1,
+ 'tax_rate1' => 0,
+ 'tax_name1' => '',
+ 'tax_rate2' => 0,
+ 'tax_rate3' => 0,
+ 'tax_name2' => '',
+ 'tax_name3' => '',
+ 'line_items' => [$item],
+ 'number' => 'ITA-'.rand(1000,100000)
+ ]);
+
+ $invoice->service()->markSent()->save();
+
+ $fat = new FatturaPANew($invoice);
+ $fat->run();
+
+ $fe = $fat->getFatturaElettronica();
+
+ $this->assertNotNull($fe);
+
+ $this->assertInstanceOf(FatturaElettronica::class, $fe);
+ $this->assertInstanceOf(FatturaElettronicaBody::class, $fe->FatturaElettronicaBody[0]);
+ $this->assertInstanceOf(FatturaElettronicaHeader::class, $fe->FatturaElettronicaHeader);
+
+
+ $encoder = new Encode($fe);
+ $xml = $encoder->toXml();
+
+ $this->assertNotNull($xml);
+
+
}
}
diff --git a/tests/Integration/Einvoice/Fact1Test.php b/tests/Integration/Einvoice/Fact1Test.php
new file mode 100644
index 000000000000..0cc647941476
--- /dev/null
+++ b/tests/Integration/Einvoice/Fact1Test.php
@@ -0,0 +1,452 @@
+markTestSkipped('prevent running in CI');
+
+ $this->makeTestData();
+ }
+
+ public function testRoBuild()
+ {
+ $settings = $this->company->settings;
+ $settings->currency_id = '42';
+ $this->company->saveSettings($settings, $this->company);
+ $this->company->save();
+
+ $settings = ClientSettings::defaults();
+ $settings->currency_id = '42';
+
+//VAT
+//19%
+ $client = Client::factory()
+ ->create([
+ 'user_id' => $this->user->id,
+ 'company_id' => $this->company->id,
+ 'id_number' => '646546549',
+ 'address1' => '40D, Șoseaua București-Ploiești',
+ 'city' => 'SECTOR3',
+ 'state' => 'RO-B',
+ 'country_id' => 642,
+ 'vat_number' => 646546549,
+ 'name' => 'Client Company Name',
+ 'settings' => $settings,
+ ]);
+
+ ClientContact::factory()->create([
+ 'user_id' => $this->user->id,
+ 'company_id' => $this->company->id,
+ 'client_id' => $client->id,
+ 'first_name' => 'Bob',
+ 'last_name' => 'Jane',
+ 'email' => 'bob@gmail.com',
+ ]);
+
+ $items = [];
+
+ $item = new InvoiceItem;
+ $item->cost = 10;
+ $item->quantity = 10;
+ $item->tax_name1 = 'VAT';
+ $item->tax_rate1 = '19';
+ $item->product_key = "Product Name";
+ $item->notes = "A great product description";
+
+ $_invoice = Invoice::factory()->create([
+ 'user_id' => $this->user->id,
+ 'company_id' => $this->company->id,
+ 'client_id' => $client->id,
+ 'number' => 'INV-'.rand(1000,1000000),
+ 'line_items' => [$item],
+ 'due_date' => now()->addDays(20)->format('Y-m-d'),
+ 'status_id' => 1,
+ 'discount' => 0,
+ ]);
+
+ $_invoice->service()->markSent()->save();
+ $calc = $_invoice->calc();
+
+ $invoice = new \Invoiceninja\Einvoice\Models\FACT1\Invoice();
+ $invoice->UBLVersionID = '2.1';
+ $invoice->CustomizationID = 'urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1';
+ $invoice->ID = $_invoice->number;
+ $invoice->InvoiceTypeCode = 380;
+ $invoice->IssueDate = new DateTime($_invoice->date);
+ $invoice->DueDate = new DateTime($_invoice->due_date);
+ $invoice->DocumentCurrencyCode = 'RON';
+ $invoice->TaxCurrencyCode = 'RON';
+
+ $asp = new AccountingSupplierParty();
+ $party = new Party();
+
+ $party_identification = new PartyIdentification();
+ $party_identification->ID = 'company_id_number';
+ $party->PartyIdentification[] = $party_identification;
+
+ $sp_address = new PostalAddress();
+ $sp_address->StreetName = $this->company->settings->address1;
+ $sp_address->CityName = 'SECTOR2';
+ $sp_address->CountrySubentity = 'RO-B';
+
+ $country = new Country();
+ $country->IdentificationCode='RO';
+ $sp_address->Country = $country;
+
+ $party->PostalAddress = $sp_address;
+
+ $pts = new PartyTaxScheme();
+ $tax_scheme = new TaxScheme();
+ $tax_scheme->ID = 'VAT';
+
+ $pts->CompanyID = 'RO234234234';
+ $pts->TaxScheme = $tax_scheme;
+
+ $party->PartyTaxScheme[] = $pts;
+
+ $ple = new PartyLegalEntity();
+ $ple->RegistrationName = $this->company->settings->name;
+ $ple->CompanyID = 'J40/2222/2009';
+
+ $party->PartyLegalEntity[] = $ple;
+
+ $p_contact = new Contact();
+ $p_contact->Name = $this->company->owner()->present()->name();
+ $p_contact->Telephone = $this->company->settings->phone;
+ $p_contact->ElectronicMail = $this->company->owner()->email;
+ $party->Contact = $p_contact;
+ $asp->Party = $party;
+
+ $invoice->AccountingSupplierParty = $asp;
+
+ $acp = new AccountingCustomerParty();
+
+ $party = new Party();
+
+ $party_identification = new PartyIdentification();
+ $party_identification->ID = 'client_id_number';
+ $party->PartyIdentification[] = $party_identification;
+
+ $sp_address = new PostalAddress();
+ $sp_address->StreetName = $client->address1;
+ $sp_address->CityName = 'SECTOR2';
+ $sp_address->CountrySubentity = 'RO-B';
+
+ $country = new Country();
+ $country->IdentificationCode = 'RO';
+ $sp_address->Country = $country;
+
+ $party->PostalAddress = $sp_address;
+
+ $ple = new PartyLegalEntity();
+ $ple->RegistrationName = $client->name;
+ $ple->CompanyID = '646546549';
+
+ $party->PartyLegalEntity[] = $ple;
+
+ $p_contact = new Contact();
+ $p_contact->Name = $client->contacts->first()->present()->name();
+ $p_contact->Telephone = $client->contacts->first()->present()->phone();
+ $p_contact->ElectronicMail = $client->contacts->first()->present()->email();
+
+ $party->Contact = $p_contact;
+
+ $acp->Party = $party;
+ $invoice->AccountingCustomerParty = $acp;
+
+ $taxtotal = new TaxTotal();
+ $tax_amount = new TaxAmount();
+
+ $tax_amount->amount = $calc->getItemTotalTaxes();
+ $tax_amount->currencyID = $_invoice->client->currency()->code;
+
+ $tc = new TaxCategory();
+ $tc->ID = "S";
+
+ $taxable = $this->getTaxable($_invoice);
+
+ $taxable_amount = new TaxableAmount();
+ $taxable_amount->amount = $taxable;
+ $taxable_amount->currencyID = $_invoice->client->currency()->code;
+
+ $tax_sub_total = new TaxSubtotal();
+ $tax_sub_total->TaxAmount = $tax_amount;
+ $tax_sub_total->TaxCategory = $tc;
+ $tax_sub_total->TaxableAmount = $taxable_amount;
+ $taxtotal->TaxSubtotal[] = $tax_sub_total;
+
+ $invoice->TaxTotal[] = $taxtotal;
+
+ $lmt = new LegalMonetaryTotal();
+
+ $lea = new LineExtensionAmount();
+ $lea->amount = $taxable;
+ $lea->currencyID = $_invoice->client->currency()->code;
+
+ $lmt->LineExtensionAmount = $lea;
+
+ $tea = new TaxExclusiveAmount;
+ $tea->amount = $taxable;
+ $tea->currencyID = $_invoice->client->currency()->code;
+
+ $lmt->TaxExclusiveAmount = $tea;
+
+ $tia = new TaxInclusiveAmount;
+ $tia->amount = $_invoice->amount;
+ $tia->currencyID = $_invoice->client->currency()->code;
+
+ $lmt->TaxInclusiveAmount = $tia;
+
+ $pa = new PayableAmount;
+ $pa->amount = $_invoice->amount;
+ $pa->currencyID = $_invoice->client->currency()->code;
+
+ $lmt->PayableAmount = $pa;
+ $invoice->LegalMonetaryTotal = $lmt;
+
+ foreach($_invoice->line_items as $key => $item)
+ {
+
+ $invoice_line = new InvoiceLine;
+ $invoice_line->ID = $key++;
+
+ $iq = new InvoicedQuantity();
+ $iq->amount = $item->cost;
+ $iq->unitCode = 'H87';
+
+ $invoice_line->InvoicedQuantity = $iq;
+
+ $invoice_line->Note = substr($item->notes, 0, 200);
+
+ $ctc = new ClassifiedTaxCategory();
+ $ctc->ID = 'S';
+
+ $i = new Item;
+ $i->Description = $item->notes;
+ $i->Name = $item->product_key;
+
+ $tax_scheme = new FACT1TaxScheme();
+ $tax_scheme->ID = $item->tax_name1;
+ $tax_scheme->Name = $item->tax_rate1;
+
+ $ctc = new ClassifiedTaxCategory();
+ $ctc->TaxScheme = $tax_scheme;
+ $ctc->ID = 'S';
+
+ $i->ClassifiedTaxCategory[] = $ctc;
+
+ $invoice_line->Item = $i;
+
+
+ $lea = new LineExtensionAmount;
+ $lea->amount = $item->line_total;
+ $lea->currencyID = $_invoice->client->currency()->code;
+
+ $invoice_line->LineExtensionAmount = $lea;
+
+ $price = new Price();
+ $pa = new PriceAmount();
+ $pa->amount = $item->line_total;
+ $pa->currencyID = $_invoice->client->currency()->code;
+
+ $price->PriceAmount = $pa;
+
+ $lea = new LineExtensionAmount();
+ $lea->amount = $item->line_total;
+ $lea->currencyID = $_invoice->client->currency()->code;
+
+ $invoice_line->LineExtensionAmount = $lea;
+
+ $invoice->InvoiceLine[] = $invoice_line;
+ }
+
+ $validator = Validation::createValidatorBuilder()
+ ->enableAttributeMapping()
+ ->getValidator();
+
+ $errors = $validator->validate($invoice);
+
+ foreach($errors as $error) {
+ // echo $error->getPropertyPath() . ': ' . $error->getMessage() . "\n";
+ }
+
+ $this->assertCount(0, $errors);
+
+ $phpDocExtractor = new PhpDocExtractor();
+ $reflectionExtractor = new ReflectionExtractor();
+ // list of PropertyListExtractorInterface (any iterable)
+ $listExtractors = [$reflectionExtractor];
+ // list of PropertyTypeExtractorInterface (any iterable)
+ $typeExtractors = [$reflectionExtractor,$phpDocExtractor];
+ // list of PropertyDescriptionExtractorInterface (any iterable)
+ $descriptionExtractors = [$phpDocExtractor];
+ // list of PropertyAccessExtractorInterface (any iterable)
+ $accessExtractors = [$reflectionExtractor];
+ // list of PropertyInitializableExtractorInterface (any iterable)
+ $propertyInitializableExtractors = [$reflectionExtractor];
+ $propertyInfo = new PropertyInfoExtractor(
+ // $listExtractors,
+ $propertyInitializableExtractors,
+ $descriptionExtractors,
+ $typeExtractors,
+ // $accessExtractors,
+ );
+ $context = [
+ 'xml_format_output' => true,
+ 'remove_empty_tags' => true,
+ ];
+
+ $encoder = new XmlEncoder($context);
+ $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
+ $metadataAwareNameConverter = new MetadataAwareNameConverter($classMetadataFactory);
+ $discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
+
+ $normalizer = new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter, null, $propertyInfo);
+
+ $normalizers = [ new DateTimeNormalizer(), $normalizer, new ArrayDenormalizer() , ];
+ $encoders = [$encoder, new JsonEncoder()];
+ $serializer = new Serializer($normalizers, $encoders);
+
+ $n_context = [
+ AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
+ // AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true,
+ ];
+
+
+ // $invoice = $normalizer->normalize($invoice, 'json', $n_context);
+ // echo print_r($invoice);
+ // $invoice = $serializer->serialize($invoice, 'xml', $n_context);
+ $dataxml = $serializer->encode($invoice, 'xml', $context);
+
+ // echo $dataxml;
+
+ //set default standard props
+ }
+
+
+
+
+ /**
+ * @return float|int|mixed
+ */
+ private function getTaxable(Invoice $invoice): float
+ {
+ $total = 0;
+
+ foreach ($invoice->line_items as $item) {
+ $line_total = $item->quantity * $item->cost;
+
+ if ($item->discount != 0) {
+ if ($invoice->is_amount_discount) {
+ $line_total -= $item->discount;
+ } else {
+ $line_total -= $line_total * $item->discount / 100;
+ }
+ }
+
+ $total += $line_total;
+ }
+
+ if ($invoice->discount > 0) {
+ if ($invoice->is_amount_discount) {
+ $total -= $invoice->discount;
+ } else {
+ $total *= (100 - $invoice->discount) / 100;
+ $total = round($total, 2);
+ }
+ }
+
+ if ($invoice->custom_surcharge1 && $invoice->custom_surcharge_tax1) {
+ $total += $invoice->custom_surcharge1;
+ }
+
+ if ($invoice->custom_surcharge2 && $invoice->custom_surcharge_tax2) {
+ $total += $invoice->custom_surcharge2;
+ }
+
+ if ($invoice->custom_surcharge3 && $invoice->custom_surcharge_tax3) {
+ $total += $invoice->custom_surcharge3;
+ }
+
+ if ($invoice->custom_surcharge4 && $invoice->custom_surcharge_tax4) {
+ $total += $invoice->custom_surcharge4;
+ }
+
+ return $total;
+ }
+
+
+}