1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00

Merge pull request #9550 from turbo124/v5-develop

Update PayPal integration to support advanced cards
This commit is contained in:
David Bomba 2024-05-26 09:01:53 +10:00 committed by GitHub
commit 5123c9be6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1988 additions and 1410 deletions

View File

@ -1 +1 @@
5.8.57
5.8.58

View File

@ -1,23 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\EDoc;
use Spatie\LaravelData\Data;
class Fact1 extends Data
{
public string $sectorCode = 'SECTOR1';
public string $BankId = '';
public string $BankName = '';
public string $PaymentMeans = 'TP02';
}

View File

@ -1,29 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Optional;
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
class EDocSettings extends Data
{
public FatturaElettronica|Optional $FatturaElettronica;
public function __construct() {}
public function createFatturaPA(): FatturaElettronica
{
return $this->FatturaElettronica ??= new FatturaElettronica;
}
}

View File

@ -0,0 +1,278 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Sources;
use App\DataMapper\InvoiceItem;
class PayPalBalanceAffecting
{
private array $key_map = [
'Date' => 'date',
'Time' => 'time',
'TimeZone' => 'timezone',
'Name' => 'name',
'Type' => 'type',
'Status' => 'status',
'Currency' => 'currency',
'Gross' => 'gross',
'Fee' => 'fee',
'Net' => 'net',
'From Email Address' => 'fromEmailAddress',
'To Email Address' => 'toEmailAddress',
'Transaction ID' => 'transactionId',
'Shipping Address' => 'shippingAddress',
'Item Title' => 'itemTitle',
'Item ID' => 'itemId',
'Option 1 Name' => 'option1Name',
'Option 1 Value' => 'option1Value',
'Option 2 Name' => 'option2Name',
'Option 2 Value' => 'option2Value',
'Reference Txn ID' => 'referenceTxId',
'Invoice Number' => 'invoiceNumber',
'Custom Number' => 'customNumber',
'Quantity' => 'quantity',
'Receipt ID' => 'receiptId',
'Address Line 1' => 'addressLine1',
'Address Line 2/District/Neighborhood' => 'addressLine2DistrictNeighborhood',
'Town/City' => 'townCity',
'State/Province/Region/County/Territory/Prefecture/Republic' => 'stateProvinceRegionCountyTerritoryPrefectureRepublic',
'Zip/Postal Code' => 'zipPostalCode',
'Country' => 'country',
'Contact Phone Number' => 'contactPhoneNumber',
'Subject' => 'subject',
'Note' => 'note',
'Transaction Event Code' => 'transactionEventCode',
'Payment Tracking ID' => 'paymentTrackingId',
'Item Details' => 'itemDetails',
'Authorization Review Status' => 'authorizationReviewStatus',
'Country Code' => 'countryCode',
'Tip' => 'tip',
'Discount' => 'discount',
'Credit Transactional Fee' => 'creditTransactionalFee',
'Original Invoice ID' => 'originalInvoiceId',
];
public $date;
public $time;
public $timezone;
public $name;
public $type;
public $status;
public $currency;
public $gross;
public $fee;
public $net;
public $fromEmailAddress;
public $toEmailAddress;
public $transactionId;
public $shippingAddress;
public $itemTitle;
public $itemId;
public $option1Name;
public $option1Value;
public $option2Name;
public $option2Value;
public $referenceTxnId;
public $invoiceNumber;
public $customNumber;
public $quantity;
public $receiptId;
public $addressLine1;
public $addressLine2DistrictNeighborhood;
public $townCity;
public $stateProvinceRegionCountyTerritoryPrefectureRepublic;
public $zipPostalCode;
public $country;
public $contactPhoneNumber;
public $subject;
public $note;
public $transactionEventCode;
public $paymentTrackingId;
public $itemDetails;
public $authorizationReviewStatus;
public $countryCode;
public $tip;
public $discount;
public $creditTransactionalFee;
public $originalInvoiceId;
public function __construct(private array $import_row){}
public function run(): self
{
foreach($this->import_row as $key => $value) {
$prop = $this->key_map[$key] ?? false;
if($prop)
$this->{$prop} = $value;
}
return $this;
}
public function getClient(): array
{
$client = [
'name' => $this->name,
'contacts' => [$this->getContact()],
'email' => $this->fromEmailAddress,
];
$client = array_merge($client, $this->returnAddress());
$client = array_merge($client, $this->returnShippingAddress());
return $client;
}
public function getInvoice(): array
{
$item = new InvoiceItem;
$item->cost = $this->gross ?? 0;
$item->product_key = $this->itemId ?? '';
$item->notes = $this->subject ?? $this->itemDetails;
$item->quantity = 1;
return [
'number' => trim($this->invoiceNumber ?? $this->transactionId),
'date' => str_replace('/','-', $this->date ?? ''),
'line_items' => [$item],
'name' => $this->name ?? '',
'email' => $this->fromEmailAddress ?? '',
];
}
public function getContact(): array
{
$name_parts = explode(" ", $this->name ?? '');
if(count($name_parts) == 2)
{
$contact['first_name'] = $name_parts[0];
$contact['last_name'] = $name_parts[1];
}
else {
$contact['first_name'] = $this->name ?? '';
}
$contact['email'] = $this->fromEmailAddress ?? '';
$contact['phone'] = $this->contactPhoneNumber ?? '';
return $contact;
}
private function returnAddress(): array
{
return [
'address1' => $this->addressLine1 ?? '',
'address2' => $this->addressLine2DistrictNeighborhood ?? '',
'city' => $this->townCity ?? '',
'state' => $this->stateProvinceRegionCountyTerritoryPrefectureRepublic ?? '',
'country_id' => $this->countryCode ?? '',
'postal_code' => $this->zipPostalCode ?? '',
];
}
private function returnShippingAddress(): array
{
if(strlen($this->shippingAddress ?? '') <3)
return [];
$ship_parts = explode(",", $this->shippingAddress);
if(count($ship_parts) != 7)
return [];
return [
'shipping_address1' => $ship_parts[2],
'shipping_address2' => '',
'shipping_city' => $ship_parts[3],
'shipping_state' => $ship_parts[4],
'shipping_postal_code' => $ship_parts[5],
'shipping_country_id' => $ship_parts[6],
];
}
public function getType(): string
{
return $this->type ?? '';
}
public function isInvoiceType(): bool
{
return $this->type == 'Website Payment';
}
}
// $csv = Reader::createFromString($csvFile);
// // $csvdelimiter = self::detectDelimiter($csvfile);
// $csv->setDelimiter(",");
// $stmt = new Statement();
// $data = iterator_to_array($stmt->process($csv));
// $header = $data[0];
// $arr = [];
// foreach($data as $key => $value) {
// if($key == 0) {
// continue;
// }
// $arr[] = array_combine($header, $value);
// }
// $arr;
// $company = Company::find(3358);
// $owner = $company->owner();
// $client_repo = new ClientRepository(new ClientContactRepository());
// $invoice_repo = new InvoiceRepository();
// foreach($arr as $pp) {
// $p = new PayPalBalanceAffecting($pp);
// $p->run();
// if(!$p->isInvoiceType()) {
// continue;
// }
// $import_c = $p->getClient();
// $import_i = $p->getInvoice();
// $contact = ClientContact::where('company_id', 3358)->where('email', $import_c['email'])->first();
// if(!$contact) {
// $cc = ClientFactory::create($company->id, $owner->id);
// $client = $client_repo->save($import_c, $cc);
// } else {
// $client = $contact->client;
// }
// $i = InvoiceFactory::create($company->id, $owner->id);
// $i->client_id = $client->id;
// $invoice_repo->save($import_i, $i);
// }

View File

@ -18,6 +18,7 @@ namespace App\DataProviders;
class Domains
{
private static array $verify_domains = [
'looksecure.net',
'0-00.usa.cc',
'0-180.com',
'0-30-24.com',

View File

@ -16,6 +16,7 @@ use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Data;
/**
* @deprecated
* [
"account": [
[

View File

@ -89,6 +89,9 @@ class EpcQrGenerator
]), "\n");
}
// substr("{$this->invoice->number} {$this->invoice->client->number}", 0,139),
private function validateFields()
{
if (Ninja::isSelfHost() && isset($this->company?->custom_fields?->company2)) {

View File

@ -301,8 +301,30 @@ class YodleeController extends BaseController
$summary = $yodlee->getAccountSummary($account_number);
$transformed_summary = AccountSummary::from($summary[0]);
//@todo remove laravel-data
// $transformed_summary = AccountSummary::from($summary[0]);
$transformed_summary = $this->transformSummary($summary[0]);
return response()->json($transformed_summary, 200);
}
private function transformSummary($summary): array
{
$dto = new \stdClass;
$dto->id = $summary['id'] ?? 0;
$dto->account_type = $summary['CONTAINER'] ?? '';
$dto->account_status = $summary['accountStatus'] ?? '';
$dto->account_number = $summary['accountNumber'] ?? '';
$dto->provider_account_id = $summary['providerAccountId'] ?? '';
$dto->provider_id = $summary['providerId'] ?? '';
$dto->provider_name = $summary['providerName'] ?? '';
$dto->nickname = $summary['nickname'] ?? '';
$dto->account_name = $summary['accountName'] ?? '';
$dto->current_balance = $summary['currentBalance']['amount'] ?? 0;
$dto->account_currency = $summary['currentBalance']['currency'] ?? 0;
return (array)$dto;
}
}

View File

@ -41,7 +41,6 @@ use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use Illuminate\Contracts\Container\BindingResolutionException;
use Invoiceninja\Einvoice\Decoder\Schema;
/**
* Class BaseController.
@ -997,8 +996,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');
}

View File

@ -13,7 +13,6 @@ namespace App\Http\Controllers;
use App\Utils\Statics;
use Illuminate\Http\Response;
use Invoiceninja\Einvoice\Decoder\Schema;
class StaticController extends BaseController
{
@ -61,8 +60,9 @@ 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');
}
return response()->json($response_data, 200, ['Content-type' => 'application/json; charset=utf-8'], JSON_PRETTY_PRINT);

View File

@ -17,7 +17,6 @@ use App\Http\ValidationRules\Company\ValidSubdomain;
use App\Http\ValidationRules\ValidSettingsRule;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
class UpdateCompanyRequest extends Request
{

View File

@ -11,6 +11,7 @@
namespace App\Import\Transformer\Invoice2Go;
use App\DataMapper\InvoiceItem;
use App\Import\ImportException;
use App\Import\Transformer\BaseTransformer;
use App\Models\Invoice;
@ -26,6 +27,8 @@ class InvoiceTransformer extends BaseTransformer
*
* @return bool|array
*/
private $is_amount_discount = false;
public function transform($invoice_data)
{
if (!isset($invoice_data['DocumentNumber'])) {
@ -39,9 +42,14 @@ class InvoiceTransformer extends BaseTransformer
$invoiceStatusMap = [
'unsent' => Invoice::STATUS_DRAFT,
'sent' => Invoice::STATUS_SENT,
'fully_paid' => Invoice::STATUS_PAID,
];
$this->is_amount_discount = $this->getFloat($invoice_data, 'Discount') > 0 ? true : false;
$transformed = [
'is_amount_discount' => $this->is_amount_discount,
'discount' => $this->getFloat($invoice_data, 'Discount'),
'company_id' => $this->company->id,
'number' => $this->getString($invoice_data, 'DocumentNumber'),
'notes' => $this->getString($invoice_data, 'Comment'),
@ -51,14 +59,7 @@ class InvoiceTransformer extends BaseTransformer
'status_id' => $invoiceStatusMap[$status =
strtolower($this->getString($invoice_data, 'DocumentStatus'))] ?? Invoice::STATUS_SENT,
// 'viewed' => $status === 'viewed',
'line_items' => [
[
'cost' => $this->getFloat($invoice_data, 'TotalAmount'),
'quantity' => 1,
'discount' => $this->getFloat($invoice_data, 'DiscountValue'),
'is_amount_discount' => false,
],
],
'line_items' => $this->harvestLineItems($invoice_data),
];
$client_id = null;
@ -88,6 +89,11 @@ class InvoiceTransformer extends BaseTransformer
],
],
];
$addresses = $this->harvestAddresses($invoice_data);
$transformed['client'] = array_merge($transformed['client'], $addresses);
}
if (! empty($invoice_data['Date Paid'])) {
$transformed['payments'] = [
@ -97,7 +103,199 @@ class InvoiceTransformer extends BaseTransformer
],
];
}
elseif(isset($invoice_data['AmountPaidAmount']) && isset($invoice_data['DatePaid'])){
$transformed['payments'] = [
[
'date' => $this->parseDate($invoice_data['DatePaid']),
'amount' => $this->getFloat($invoice_data, 'AmountPaidAmount'),
]
];
}
elseif(isset($invoice_data['DocumentStatus']) && $invoice_data['DocumentStatus'] == 'fully_paid'){
$transformed['payments'] = [
[
'date' => isset($invoice_data['DatePaid']) ? $this->parseDate($invoice_data['DatePaid']) : ($this->parseDate($invoice_data['DocumentDate']) ?? now()->format('Y-m-d')),
'amount' => $this->getFloat($invoice_data, 'TotalAmount'),
]
];
}
return $transformed;
}
private function harvestAddresses($invoice_data) {
$address = $invoice_data['DocumentRecipientAddress'];
$lines = explode("\n", $address);
$billing_address = [];
if(count($lines) == 2){
$billing_address['address1'] = $lines[0];
$parts = explode(",", $lines[1]);
if(count($parts) == 3){
$billing_address['city'] = $parts[0];
$billing_address['state'] = $parts[1];
$billing_address['postal_code'] = $parts[2];
}
}
$shipaddress = $invoice_data['ShipAddress'] ?? '';
$shipping_address = [];
$lines = explode("\n", $shipaddress);
if(count($lines) == 2) {
$shipping_address['address1'] = $lines[0];
$parts = explode(",", $lines[1]);
if(count($parts) == 3) {
$shipping_address['shipping_city'] = $parts[0];
$shipping_address['shipping_state'] = $parts[1];
$shipping_address['shipping_postal_code'] = $parts[2];
}
}
return array_merge($billing_address, $shipping_address);
}
/*
Sample invoice2go line item
"code" => "",
"description" => "",
"qty" => "1",
"unit_type" => "parts",
"withholding_tax_applies" => "false",
"applied_taxes" => "",
"unit_price" => "150",
"discount_percentage" => "50",
"discount_type" => "percentage", //amount
"discount_amount" => "0",
*/
private function harvestLineItems(array $invoice_data): array
{
$default_data =
[
[
'cost' => $this->getFloat($invoice_data, 'TotalAmount'),
'quantity' => 1,
'discount' => $this->getFloat($invoice_data, 'DiscountValue'),
'is_amount_discount' => false,
],
];
if(!isset($invoice_data['Items'])){
return $default_data;
}
// Parse the main CSV data
$processed = $this->parseCsvWithNestedCsv($invoice_data['Items']);
$line_items = [];
foreach($processed as $item)
{
$_item['cost'] = $item['unit_price'];
$_item['quantity'] = $item['qty'] ?? 1;
$_item['discount'] = $item['discount_percentage'] > $item['discount_amount'] ? $item['discount_percentage'] : $item['discount_amount'];
$_item['is_amount_discount'] = $item['discount_type'] == 'percentage' ? false : true;
$_item['product_key'] = $item['code'] ?? '';
$_item['notes'] = $item['description'] ?? '';
$_item = $this->parseTaxes($_item, $item);
$this->is_amount_discount = $_item['is_amount_discount'];
$line_items[] = $_item;
$_item = [];
}
return $line_items;
}
private function parseTaxes($ninja_item, $i2g_item): array
{
if(is_string($i2g_item['applied_taxes']))
return $ninja_item;
$ninja_item['tax_name1'] = 'Tax';
$ninja_item['tax_rate1'] = $i2g_item['applied_taxes']['rate'];
return $ninja_item;
}
function parseCsvWithNestedCsv($csvString, $delimiter = ',', $enclosure = '"', $lineEnding = ';')
{
// Regular expression to find nested CSVs
$nestedCsvPattern = '/"([^"]*(?:""[^"]*)*)"/';
preg_match_all($nestedCsvPattern, $csvString, $matches);
// Replace nested CSVs with placeholders
$placeholders = [];
foreach ($matches[0] as $index => $match) {
$placeholder = '___PLACEHOLDER_' . $index . '___';
$placeholders[$placeholder] = $match;
$csvString = str_replace($match, $placeholder, $csvString);
}
// Parse the main CSV
$rows = explode($lineEnding, $csvString);
$parsedRows = [];
foreach ($rows as $row) {
$parsedRow = str_getcsv($row, $delimiter, $enclosure);
$parsedRows[] = $parsedRow;
}
// Replace placeholders with parsed nested CSVs
foreach ($parsedRows as &$row) {
foreach ($row as &$field) {
if (isset($placeholders[$field])) {
$field = str_getcsv($placeholders[$field], $delimiter, $enclosure);
}
}
}
foreach($parsedRows as $key => &$row) {
if($key == 0) {
continue;
}
if(is_array($row[5])) {
$csv = str_getcsv($row[5][0], ";");
$row[5] = array_combine(explode(",", $csv[0]), explode(",", $csv[1]));
}
if(is_array($row[1])) {
$row[1] = $row[1][0];
}
$row = array_combine($parsedRows[0], $row);
}
unset($parsedRows[0]);
return $parsedRows;
}
}

View File

@ -113,7 +113,7 @@ class CreateRawPdf
} catch (\Exception) {
throw new FilePermissionsFailure('Unable to generate the raw PDF');
}
if ($this->entity_string == "invoice" && $this->entity->getSetting("merge_e_invoice_to_pdf")){
if ($this->entity_string == "invoice" && $this->entity->client->getSetting("merge_e_invoice_to_pdf")){
$pdf = (new MergeEDocument($this->entity, $pdf))->handle();
}
return $pdf;

View File

@ -1739,6 +1739,7 @@ class Import implements ShouldQueue
$modified['company_id'] = $this->company->id;
$modified['user_id'] = $this->processUserId($resource);
$modified['is_deleted'] = isset($modified['is_deleted']) ? (bool)$modified['is_deleted'] : false;
/** @var \App\Models\ExpenseCategory $expense_category **/
$expense_category = ExpenseCategory::create($modified);

View File

@ -344,10 +344,15 @@ class PayPalBasePaymentDriver extends BaseDriver
->withHeaders($this->getHeaders($headers))
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
if($r->successful()) {
if($r->status() <= 422){
// if($r->successful()) {
return $r;
}
nlog($r->body());
nlog($r->json());
nlog($r);
SystemLogger::dispatch(
['response' => $r->body()],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
@ -357,8 +362,21 @@ class PayPalBasePaymentDriver extends BaseDriver
$this->client->company ?? $this->company_gateway->company,
);
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
return response()->json(['message' => "Gateway failure - {$r->body()}"], 401);
// throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
}
public function handleRetry($response, $request) {
// $response = $r->json();
// nlog($response['details']);
// if(in_array($response['details'][0]['issue'], ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED']))
return response()->json($response->json());
}
/**
@ -369,6 +387,7 @@ class PayPalBasePaymentDriver extends BaseDriver
*/
public function getHeaders(array $headers = []): array
{
return array_merge([
'Accept' => 'application/json',
'Content-type' => 'application/json',

View File

@ -146,6 +146,12 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
try {
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
if($r->status() == 422) {
//handle conditions where the client may need to try again.
return $this->handleRetry($r, $request);
}
} catch(\Exception $e) {
//Rescue for duplicate invoice_id
@ -193,7 +199,9 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
$this->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
return response()->json(['redirect' => route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)], false)]);
// return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
} else {
@ -212,7 +220,9 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
$message = $response['body']['details'][0]['description'] ?? 'Payment failed. Please try again.';
throw new PaymentFailed($message, 400);
return response()->json(['message' => $message], 400);
// throw new PaymentFailed($message, 400);
}
}

View File

@ -66,6 +66,8 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
$response = json_decode($request['gateway_response'], true);
nlog($response);
if($request->has('token') && strlen($request->input('token')) > 2)
return $this->processTokenPayment($request, $response);
@ -93,7 +95,14 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
}
try{
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
if($r->status() == 422){
//handle conditions where the client may need to try again.
return $this->handleRetry($r, $request);
}
}
catch(\Exception $e) {
@ -146,7 +155,9 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
$message = $response['body']['details'][0]['description'] ?? 'Payment failed. Please try again.';
throw new PaymentFailed($message, 400);
return response()->json(['message' => $message], 400);
//throw new PaymentFailed($message, 400);
}
}
@ -202,7 +213,9 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
$this->client->company,
);
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
return response()->json(['redirect' => route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)], false)]);
// return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
}
@ -257,10 +270,9 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
if(isset($data['payment_source']))
$order['payment_source'] = $data['payment_source'];
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
nlog($r->json());
return $r->json()['id'];
}

View File

@ -57,7 +57,7 @@ class ProcessBankRules extends AbstractService
->get();
$invoice = $this->invoices->first(function ($value, $key) {
return str_contains($this->bank_transaction->description, $value->number);
return str_contains($this->bank_transaction->description, $value->number) || str_contains(str_replace("\n", "", $this->bank_transaction->description), $value->number);
});
if ($invoice) {

View File

@ -39,6 +39,9 @@ use CleverIt\UBL\Invoice\FatturaPA\common\CessionarioCommittente;
use CleverIt\UBL\Invoice\FatturaPA\common\FatturaElettronicaBody;
use CleverIt\UBL\Invoice\FatturaPA\common\FatturaElettronicaHeader;
/**
* @deprecated not needed anylonger as we have invoiceninja/einvoice
*/
class FatturaPA extends AbstractService
{
private $xml;

View File

@ -105,8 +105,7 @@
"webpatser/laravel-countries": "dev-master#75992ad",
"wepay/php-sdk": "^0.3",
"wildbit/postmark-php": "^4.0",
"hyvor/php-json-exporter": "^0.0.3",
"invoiceninja/einvoice": "dev-main"
"hyvor/php-json-exporter": "^0.0.3"
},
"require-dev": {
"php": "^8.1|^8.2",

300
composer.lock generated
View File

@ -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": "1356155e46e797b140685c105df97b8e",
"content-hash": "6904626bbe465492796c27cd86ad4d2c",
"packages": [
{
"name": "adrienrn/php-mimetyper",
@ -1385,16 +1385,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.307.1",
"version": "3.308.3",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "cc79f16e1a1bd3feee421401ba2f21915abfdf91"
"reference": "7fa0625056fa1fcf6732f89ba37b3f630d78de59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cc79f16e1a1bd3feee421401ba2f21915abfdf91",
"reference": "cc79f16e1a1bd3feee421401ba2f21915abfdf91",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7fa0625056fa1fcf6732f89ba37b3f630d78de59",
"reference": "7fa0625056fa1fcf6732f89ba37b3f630d78de59",
"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.307.1"
"source": "https://github.com/aws/aws-sdk-php/tree/3.308.3"
},
"time": "2024-05-17T18:07:44+00:00"
"time": "2024-05-24T18:29:40+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -2509,16 +2509,16 @@
},
{
"name": "doctrine/event-manager",
"version": "2.0.0",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/event-manager.git",
"reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32"
"reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32",
"reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32",
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e",
"reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e",
"shasum": ""
},
"require": {
@ -2528,10 +2528,10 @@
"doctrine/common": "<2.9"
},
"require-dev": {
"doctrine/coding-standard": "^10",
"doctrine/coding-standard": "^12",
"phpstan/phpstan": "^1.8.8",
"phpunit/phpunit": "^9.5",
"vimeo/psalm": "^4.28"
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^5.24"
},
"type": "library",
"autoload": {
@ -2580,7 +2580,7 @@
],
"support": {
"issues": "https://github.com/doctrine/event-manager/issues",
"source": "https://github.com/doctrine/event-manager/tree/2.0.0"
"source": "https://github.com/doctrine/event-manager/tree/2.0.1"
},
"funding": [
{
@ -2596,7 +2596,7 @@
"type": "tidelift"
}
],
"time": "2022-10-12T20:59:15+00:00"
"time": "2024-05-22T20:47:39+00:00"
},
{
"name": "doctrine/inflector",
@ -4588,16 +4588,16 @@
},
{
"name": "horstoeko/zugferd",
"version": "v1.0.44",
"version": "v1.0.47",
"source": {
"type": "git",
"url": "https://github.com/horstoeko/zugferd.git",
"reference": "18de152080610d6d77eda97e375bfb8ec03ef4f8"
"reference": "7a5a8b7bb44f7aebfd66af112662c30383f31dd9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/18de152080610d6d77eda97e375bfb8ec03ef4f8",
"reference": "18de152080610d6d77eda97e375bfb8ec03ef4f8",
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/7a5a8b7bb44f7aebfd66af112662c30383f31dd9",
"reference": "7a5a8b7bb44f7aebfd66af112662c30383f31dd9",
"shasum": ""
},
"require": {
@ -4657,9 +4657,9 @@
],
"support": {
"issues": "https://github.com/horstoeko/zugferd/issues",
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.44"
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.47"
},
"time": "2024-05-16T16:19:57+00:00"
"time": "2024-05-23T03:12:53+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
@ -4869,16 +4869,16 @@
},
{
"name": "imdhemy/laravel-purchases",
"version": "1.11.0",
"version": "1.12.0",
"source": {
"type": "git",
"url": "https://github.com/imdhemy/laravel-in-app-purchases.git",
"reference": "3c0031880dc0bbd39ec89eac61fc3d0f32580dec"
"reference": "bd7303d23a950aa8f4573d98498ce1e4c8b6664a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/imdhemy/laravel-in-app-purchases/zipball/3c0031880dc0bbd39ec89eac61fc3d0f32580dec",
"reference": "3c0031880dc0bbd39ec89eac61fc3d0f32580dec",
"url": "https://api.github.com/repos/imdhemy/laravel-in-app-purchases/zipball/bd7303d23a950aa8f4573d98498ce1e4c8b6664a",
"reference": "bd7303d23a950aa8f4573d98498ce1e4c8b6664a",
"shasum": ""
},
"require": {
@ -4934,7 +4934,7 @@
],
"support": {
"issues": "https://github.com/imdhemy/laravel-in-app-purchases/issues",
"source": "https://github.com/imdhemy/laravel-in-app-purchases/tree/1.11.0"
"source": "https://github.com/imdhemy/laravel-in-app-purchases/tree/1.12.0"
},
"funding": [
{
@ -4942,7 +4942,7 @@
"type": "github"
}
],
"time": "2024-05-12T19:06:24+00:00"
"time": "2024-05-25T12:18:29+00:00"
},
{
"name": "intervention/image",
@ -5028,55 +5028,6 @@
],
"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": "39aec367c528ba66d923dc1d9e5c96f673bb46c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/39aec367c528ba66d923dc1d9e5c96f673bb46c7",
"reference": "39aec367c528ba66d923dc1d9e5c96f673bb46c7",
"shasum": ""
},
"require": {
"illuminate/collections": "^10.48",
"sabre/xml": "^4.0",
"spatie/laravel-data": "^3.6"
},
"require-dev": {
"nesbot/carbon": "^2",
"nette/php-generator": "^4.1",
"phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^10.5",
"symfony/console": "^6.4"
},
"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-20T11:42:32+00:00"
},
{
"name": "invoiceninja/inspector",
"version": "v2.0",
@ -5638,16 +5589,16 @@
},
{
"name": "laravel/framework",
"version": "v10.48.10",
"version": "v10.48.11",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "91e2b9e218afa4e5c377510faa11957042831ba3"
"reference": "afdc2b03bd8d126446583da5414d659491aa4f54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/91e2b9e218afa4e5c377510faa11957042831ba3",
"reference": "91e2b9e218afa4e5c377510faa11957042831ba3",
"url": "https://api.github.com/repos/laravel/framework/zipball/afdc2b03bd8d126446583da5414d659491aa4f54",
"reference": "afdc2b03bd8d126446583da5414d659491aa4f54",
"shasum": ""
},
"require": {
@ -5841,20 +5792,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2024-04-30T12:52:59+00:00"
"time": "2024-05-21T17:53:51+00:00"
},
{
"name": "laravel/prompts",
"version": "v0.1.21",
"version": "v0.1.22",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
"reference": "23ea808e8a145653e0ab29e30d4385e49f40a920"
"reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/23ea808e8a145653e0ab29e30d4385e49f40a920",
"reference": "23ea808e8a145653e0ab29e30d4385e49f40a920",
"url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
"reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
"shasum": ""
},
"require": {
@ -5897,9 +5848,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.21"
"source": "https://github.com/laravel/prompts/tree/v0.1.22"
},
"time": "2024-04-30T12:46:16+00:00"
"time": "2024-05-10T19:22:18+00:00"
},
{
"name": "laravel/serializable-closure",
@ -6162,16 +6113,16 @@
},
{
"name": "laravel/ui",
"version": "v4.5.1",
"version": "v4.5.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/ui.git",
"reference": "a3562953123946996a503159199d6742d5534e61"
"reference": "c75396f63268c95b053c8e4814eb70e0875e9628"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/ui/zipball/a3562953123946996a503159199d6742d5534e61",
"reference": "a3562953123946996a503159199d6742d5534e61",
"url": "https://api.github.com/repos/laravel/ui/zipball/c75396f63268c95b053c8e4814eb70e0875e9628",
"reference": "c75396f63268c95b053c8e4814eb70e0875e9628",
"shasum": ""
},
"require": {
@ -6219,9 +6170,9 @@
"ui"
],
"support": {
"source": "https://github.com/laravel/ui/tree/v4.5.1"
"source": "https://github.com/laravel/ui/tree/v4.5.2"
},
"time": "2024-03-21T18:12:29+00:00"
"time": "2024-05-08T18:07:10+00:00"
},
{
"name": "lcobucci/clock",
@ -6551,40 +6502,39 @@
},
{
"name": "league/csv",
"version": "9.15.0",
"version": "9.16.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "fa7e2441c0bc9b2360f4314fd6c954f7ff40d435"
"reference": "998280c6c34bd67d8125fdc8b45bae28d761b440"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/fa7e2441c0bc9b2360f4314fd6c954f7ff40d435",
"reference": "fa7e2441c0bc9b2360f4314fd6c954f7ff40d435",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/998280c6c34bd67d8125fdc8b45bae28d761b440",
"reference": "998280c6c34bd67d8125fdc8b45bae28d761b440",
"shasum": ""
},
"require": {
"ext-filter": "*",
"ext-json": "*",
"ext-mbstring": "*",
"php": "^8.1.2"
},
"require-dev": {
"doctrine/collections": "^2.1.4",
"doctrine/collections": "^2.2.2",
"ext-dom": "*",
"ext-xdebug": "*",
"friendsofphp/php-cs-fixer": "^v3.22.0",
"friendsofphp/php-cs-fixer": "^3.57.1",
"phpbench/phpbench": "^1.2.15",
"phpstan/phpstan": "^1.10.57",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
"phpstan/phpstan-phpunit": "^1.3.15",
"phpstan/phpstan-strict-rules": "^1.5.2",
"phpunit/phpunit": "^10.5.9",
"symfony/var-dumper": "^6.4.2"
"phpstan/phpstan": "^1.11.1",
"phpstan/phpstan-deprecation-rules": "^1.2.0",
"phpstan/phpstan-phpunit": "^1.4.0",
"phpstan/phpstan-strict-rules": "^1.6.0",
"phpunit/phpunit": "^10.5.16 || ^11.1.3",
"symfony/var-dumper": "^6.4.6 || ^7.0.7"
},
"suggest": {
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters"
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters",
"ext-mbstring": "Needed to ease transcoding CSV using mb stream filters"
},
"type": "library",
"extra": {
@ -6636,20 +6586,20 @@
"type": "github"
}
],
"time": "2024-02-20T20:00:00+00:00"
"time": "2024-05-24T11:04:54+00:00"
},
{
"name": "league/flysystem",
"version": "3.27.0",
"version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "4729745b1ab737908c7d055148c9a6b3e959832f"
"reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f",
"reference": "4729745b1ab737908c7d055148c9a6b3e959832f",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c",
"reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c",
"shasum": ""
},
"require": {
@ -6673,10 +6623,13 @@
"composer/semver": "^3.0",
"ext-fileinfo": "*",
"ext-ftp": "*",
"ext-mongodb": "^1.3",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.5",
"google/cloud-storage": "^1.23",
"guzzlehttp/psr7": "^2.6",
"microsoft/azure-storage-blob": "^1.1",
"mongodb/mongodb": "^1.2",
"phpseclib/phpseclib": "^3.0.36",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5.11|^10.0",
@ -6714,32 +6667,22 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.27.0"
"source": "https://github.com/thephpleague/flysystem/tree/3.28.0"
},
"funding": [
{
"url": "https://ecologi.com/frankdejonge",
"type": "custom"
},
{
"url": "https://github.com/frankdejonge",
"type": "github"
}
],
"time": "2024-04-07T19:17:50+00:00"
"time": "2024-05-22T10:09:12+00:00"
},
{
"name": "league/flysystem-aws-s3-v3",
"version": "3.27.0",
"version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
"reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837"
"reference": "22071ef1604bc776f5ff2468ac27a752514665c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/3e6ce2f972f1470db779f04d29c289dcd2c32837",
"reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/22071ef1604bc776f5ff2468ac27a752514665c8",
"reference": "22071ef1604bc776f5ff2468ac27a752514665c8",
"shasum": ""
},
"require": {
@ -6779,32 +6722,22 @@
"storage"
],
"support": {
"source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.27.0"
"source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.28.0"
},
"funding": [
{
"url": "https://ecologi.com/frankdejonge",
"type": "custom"
},
{
"url": "https://github.com/frankdejonge",
"type": "github"
}
],
"time": "2024-04-07T19:16:54+00:00"
"time": "2024-05-06T20:05:52+00:00"
},
{
"name": "league/flysystem-local",
"version": "3.25.1",
"version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git",
"reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92"
"reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/61a6a90d6e999e4ddd9ce5adb356de0939060b92",
"reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92",
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/13f22ea8be526ea58c2ddff9e158ef7c296e4f40",
"reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40",
"shasum": ""
},
"require": {
@ -6838,19 +6771,9 @@
"local"
],
"support": {
"source": "https://github.com/thephpleague/flysystem-local/tree/3.25.1"
"source": "https://github.com/thephpleague/flysystem-local/tree/3.28.0"
},
"funding": [
{
"url": "https://ecologi.com/frankdejonge",
"type": "custom"
},
{
"url": "https://github.com/frankdejonge",
"type": "github"
}
],
"time": "2024-03-15T19:58:44+00:00"
"time": "2024-05-06T20:05:52+00:00"
},
{
"name": "league/fractal",
@ -7293,16 +7216,16 @@
},
{
"name": "livewire/livewire",
"version": "v3.4.12",
"version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
"reference": "54dd265c17f7b5200627eb9690590e7cbbad1027"
"reference": "72e900825c560f0e4e620185b26c5441a8914435"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/54dd265c17f7b5200627eb9690590e7cbbad1027",
"reference": "54dd265c17f7b5200627eb9690590e7cbbad1027",
"url": "https://api.github.com/repos/livewire/livewire/zipball/72e900825c560f0e4e620185b26c5441a8914435",
"reference": "72e900825c560f0e4e620185b26c5441a8914435",
"shasum": ""
},
"require": {
@ -7357,7 +7280,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
"source": "https://github.com/livewire/livewire/tree/v3.4.12"
"source": "https://github.com/livewire/livewire/tree/v3.5.0"
},
"funding": [
{
@ -7365,7 +7288,7 @@
"type": "github"
}
],
"time": "2024-05-02T17:10:37+00:00"
"time": "2024-05-21T13:39:04+00:00"
},
{
"name": "maennchen/zipstream-php",
@ -17106,16 +17029,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.57.1",
"version": "v3.57.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "3f7efe667a8c9818aacceee478add7c0fc24cb21"
"reference": "22f7f3145606df92b02fb1bd22c30abfce956d3c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/3f7efe667a8c9818aacceee478add7c0fc24cb21",
"reference": "3f7efe667a8c9818aacceee478add7c0fc24cb21",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/22f7f3145606df92b02fb1bd22c30abfce956d3c",
"reference": "22f7f3145606df92b02fb1bd22c30abfce956d3c",
"shasum": ""
},
"require": {
@ -17194,7 +17117,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.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.57.2"
},
"funding": [
{
@ -17202,7 +17125,7 @@
"type": "github"
}
],
"time": "2024-05-15T22:01:07+00:00"
"time": "2024-05-20T20:41:57+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@ -17930,16 +17853,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.11.1",
"version": "1.11.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b"
"reference": "0d5d4294a70deb7547db655c47685d680e39cfec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b",
"reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d5d4294a70deb7547db655c47685d680e39cfec",
"reference": "0d5d4294a70deb7547db655c47685d680e39cfec",
"shasum": ""
},
"require": {
@ -17984,7 +17907,7 @@
"type": "github"
}
],
"time": "2024-05-15T08:00:59+00:00"
"time": "2024-05-24T13:23:04+00:00"
},
{
"name": "phpunit/php-code-coverage",
@ -18709,16 +18632,16 @@
},
{
"name": "react/promise",
"version": "v3.1.0",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c"
"reference": "8a164643313c71354582dc850b42b33fa12a4b63"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
"reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
"url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63",
"reference": "8a164643313c71354582dc850b42b33fa12a4b63",
"shasum": ""
},
"require": {
@ -18770,7 +18693,7 @@
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
"source": "https://github.com/reactphp/promise/tree/v3.1.0"
"source": "https://github.com/reactphp/promise/tree/v3.2.0"
},
"funding": [
{
@ -18778,7 +18701,7 @@
"type": "open_collective"
}
],
"time": "2023-11-16T16:21:57+00:00"
"time": "2024-05-24T10:39:05+00:00"
},
{
"name": "react/socket",
@ -19919,16 +19842,16 @@
},
{
"name": "spatie/flare-client-php",
"version": "1.5.1",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/flare-client-php.git",
"reference": "e27977d534eefe04c154c6fd8460217024054c05"
"reference": "220a7c8745e9fa427d54099f47147c4b97fe6462"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/e27977d534eefe04c154c6fd8460217024054c05",
"reference": "e27977d534eefe04c154c6fd8460217024054c05",
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/220a7c8745e9fa427d54099f47147c4b97fe6462",
"reference": "220a7c8745e9fa427d54099f47147c4b97fe6462",
"shasum": ""
},
"require": {
@ -19976,7 +19899,7 @@
],
"support": {
"issues": "https://github.com/spatie/flare-client-php/issues",
"source": "https://github.com/spatie/flare-client-php/tree/1.5.1"
"source": "https://github.com/spatie/flare-client-php/tree/1.6.0"
},
"funding": [
{
@ -19984,7 +19907,7 @@
"type": "github"
}
],
"time": "2024-05-03T15:43:14+00:00"
"time": "2024-05-22T09:45:39+00:00"
},
{
"name": "spatie/ignition",
@ -20416,8 +20339,7 @@
"minimum-stability": "dev",
"stability-flags": {
"socialiteproviders/apple": 20,
"webpatser/laravel-countries": 20,
"invoiceninja/einvoice": 20
"webpatser/laravel-countries": 20
},
"prefer-stable": true,
"prefer-lowest": false,

View File

@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION', '5.8.57'),
'app_tag' => env('APP_TAG', '5.8.57'),
'app_version' => env('APP_VERSION', '5.8.58'),
'app_tag' => env('APP_TAG', '5.8.58'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),

View File

@ -242,7 +242,7 @@ $lang = array(
'invoice_subject' => 'Nová faktura :number od :account',
'invoice_message' => 'Pro zobrazení faktury za :amount, klikněte na odkaz níže.',
'payment_subject' => 'Platba obdržena',
'payment_message' => 'Děkujeme za Vaši platbu vy výši :amount.',
'payment_message' => 'Děkujeme za Vaši platbu ve výši :amount.',
'email_salutation' => 'Vážený(á) :name,',
'email_signature' => 'S pozdravem,',
'email_from' => 'Tým Invoice Ninja',
@ -435,7 +435,7 @@ $lang = array(
'token_billing_4' => 'Vždy',
'token_billing_checkbox' => 'Ukládat detaily platební karty',
'view_in_gateway' => 'Zobrazit v :gateway',
'use_card_on_file' => 'Use Card on File',
'use_card_on_file' => 'Použít uloženou kartu',
'edit_payment_details' => 'Editovat platební údaje',
'token_billing' => 'Ukládat platební údaje',
'token_billing_secure' => 'Data jsou bezpečně uložena u :stripe_link',
@ -460,9 +460,9 @@ $lang = array(
'edit_token' => 'Editovat token',
'delete_token' => 'Smazat Token',
'token' => 'Token',
'add_gateway' => 'Add Payment Gateway',
'delete_gateway' => 'Delete Payment Gateway',
'edit_gateway' => 'Edit Payment Gateway',
'add_gateway' => 'Přidat platební bránu',
'delete_gateway' => 'Odstranit platební bránu',
'edit_gateway' => 'Upravit platební bránu',
'updated_gateway' => 'Brána úspěšně změněna',
'created_gateway' => 'Brána úspěšně vytvořena',
'deleted_gateway' => 'Brána úspěšně smazána',
@ -3081,7 +3081,7 @@ $lang = array(
'please_enter_a_last_name' => 'Please enter a last name',
'please_agree_to_terms_and_privacy' => 'Please agree to the terms of service and privacy policy to create an account.',
'i_agree_to_the' => 'I agree to the',
'terms_of_service_link' => 'terms of service',
'terms_of_service_link' => 'smluvní podmínky',
'privacy_policy_link' => 'privacy policy',
'view_website' => 'Navštívit web',
'create_account' => 'Create Account',
@ -4030,7 +4030,7 @@ $lang = array(
'user_detached' => 'User detached from company',
'create_webhook_failure' => 'Failed to create Webhook',
'payment_message_extended' => 'Thank you for your payment of :amount for :invoice',
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is bigger than $1 or currency equivalent.',
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
'payment_token_not_found' => 'Payment token not found, please try again. If an issue still persist, try with another payment method',
'vendor_address1' => 'Vendor Street',
'vendor_address2' => 'Dodavatelské číslo patra/bytu',
@ -5013,7 +5013,7 @@ $lang = array(
'tax_category' => 'Tax Category',
'physical_goods' => 'Physical Goods',
'digital_products' => 'Digitální produkty',
'services' => 'Services',
'services' => 'Služby',
'shipping' => 'Shipping',
'tax_exempt' => 'Osvobozen od daní',
'late_fee_added_locked_invoice' => 'Late fee for invoice :invoice added on :date',
@ -5298,6 +5298,34 @@ $lang = array(
'rappen_rounding_help' => 'Round amount to 5 cents',
'assign_group' => 'Assign group',
'paypal_advanced_cards' => 'Advanced Card Payments',
'local_domain_help' => 'EHLO domain (optional)',
'port_help' => 'ie. 25,587,465',
'host_help' => 'ie. smtp.gmail.com',
'always_show_required_fields' => 'Allows show required fields form',
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
'advanced_cards' => 'Advanced Cards',
'activity_140' => 'Statement sent to :client',
'invoice_net_amount' => 'Invoice Net Amount',
'round_to_minutes' => 'Round To Minutes',
'1_minute' => '1 Minute',
'5_minutes' => '5 Minutes',
'15_minutes' => '15 Minutes',
'30_minutes' => '30 Minutes',
'1_hour' => '1 Hour',
'1_day' => '1 Day',
'round_tasks' => 'Round Tasks',
'round_tasks_help' => 'Round time intervals when saving tasks',
'direction' => 'Direction',
'round_up' => 'Round Up',
'round_down' => 'Round Down',
'task_round_to_nearest' => 'Round To Nearest',
'bulk_updated' => 'Successfully updated data',
'bulk_update' => 'Bulk Update',
'calculate' => 'Calculate',
'sum' => 'Sum',
'money' => 'Money',
'web_app' => 'Web App',
'desktop_app' => 'Desktop App',
);
return $lang;

View File

@ -739,7 +739,7 @@ $lang = array(
'activity_7' => ':contact hat Rechnung :invoice für :client angesehen',
'activity_8' => ':user archivierte Rechnung :invoice',
'activity_9' => ':user löschte Rechnung :invoice',
'activity_10' => ':user hat die Zahlung :payment für :payment _amount der Rechnung :invoice für Kunde :client eingegeben',
'activity_10' => ':user hat die Zahlung :payment über :payment_amount der Rechnung :invoice für Kunde :client eingegeben.',
'activity_11' => ':user aktualisierte Zahlung :payment',
'activity_12' => ':user archivierte Zahlung :payment',
'activity_13' => ':user löschte Zahlung :payment',
@ -2198,7 +2198,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese
'mailgun_private_key' => 'Mailgun privater Schlüssel',
'brevo_domain' => 'Brevo-Domäne',
'brevo_private_key' => 'Privater Brevo-Schlüssel',
'send_test_email' => 'Send Test Email',
'send_test_email' => 'Test-E-Mail verschicken',
'select_label' => 'Bezeichnung wählen',
'label' => 'Label',
'service' => 'Leistung',
@ -5302,8 +5302,33 @@ Leistungsempfängers',
'assign_group' => 'Gruppe zuweisen',
'paypal_advanced_cards' => 'Advanced Card Payments',
'local_domain_help' => 'EHLO domain (optional)',
'port_help' => 'ie. 25,587,465',
'host_help' => 'ie. smtp.gmail.com',
'port_help' => 'z.B. 25, 587, 465',
'host_help' => 'z.B. smtp.gmail.com',
'always_show_required_fields' => 'Allows show required fields form',
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
'advanced_cards' => 'Advanced Cards',
'activity_140' => 'Statement sent to :client',
'invoice_net_amount' => 'Rechnungsnettobetrag',
'round_to_minutes' => 'Auf Minuten runden',
'1_minute' => '1 Minute',
'5_minutes' => '5 Minuten',
'15_minutes' => '15 Minuten',
'30_minutes' => '30 Minuten',
'1_hour' => '1 Stunde',
'1_day' => '1 Tag',
'round_tasks' => 'Round Tasks',
'round_tasks_help' => 'Zeitintervalle beim speichern runden',
'direction' => 'Richtung',
'round_up' => 'Aufrunden',
'round_down' => 'Abrunden',
'task_round_to_nearest' => 'Round To Nearest',
'bulk_updated' => 'Daten erfolgreich aktualisiert',
'bulk_update' => 'Bulk Update',
'calculate' => 'Berechnen',
'sum' => 'Summe',
'money' => 'Money',
'web_app' => 'Webanwendung',
'desktop_app' => 'Desktopanwendung',
);
return $lang;

View File

@ -5325,6 +5325,9 @@ $lang = array(
'money' => 'Money',
'web_app' => 'Web App',
'desktop_app' => 'Desktop App',
'disconnected' => 'Disconnected',
'reconnect' => 'Reconnect',
'e_invoice_settings' => 'E-Invoice Settings',
);
return $lang;

File diff suppressed because it is too large Load Diff

View File

@ -5317,6 +5317,11 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'task_round_to_nearest' => 'Arrondir au plus près',
'bulk_updated' => 'Les données ont été mises à jour',
'bulk_update' => 'Mise à jour groupée',
'calculate' => 'Calculer',
'sum' => 'Somme',
'money' => 'Argent',
'web_app' => 'App web',
'desktop_app' => 'App de bureau',
);
return $lang;

View File

@ -26,7 +26,7 @@
@push('footer')
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&currency={!! $currency !!}&components=buttons,funding-eligibility&intent=capture&enable-funding={!! $funding_source !!}" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
<div id="paypal-button-container"></div>
<script>
//&buyer-country=US&currency=USD&enable-funding=venmo
@ -44,19 +44,60 @@
},
onApprove: function(data, actions) {
console.log(data);
document.getElementById("gateway_response").value =JSON.stringify( data );
formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server_response")))),
fetch('{{ route('client.payments.response') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
},
body: formData,
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json(); // or response.json() if the response is JSON
})
.then(data => {
var errorDetail = Array.isArray(data.details) && data.details[0];
if (errorDetail && ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED'].includes(errorDetail.issue)) {
return actions.restart();
}
if(data.redirect){
window.location.href = data.redirect;
return;
}
document.getElementById("gateway_response").value =JSON.stringify( data );
document.getElementById("server_response").submit();
})
.catch(error => {
console.error('Error:', error);
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
document.getElementById('errors').hidden = false;
});
},
onCancel: function() {
window.location.href = "/client/invoices/";
},
onError: function(error) {
console.log("on error");
console.log(error);
document.getElementById("gateway_response").value = error;
document.getElementById("server_response").submit();
},
@ -64,6 +105,12 @@
if(fundingSource != 'card')
document.getElementById('paypal-button-container').hidden = true;
document.querySelector('div[data-ref="required-fields-container').classList.add('hidden');
},
onInit: function (){
console.log("init");
}
}).render('#paypal-button-container').catch(function(err) {

View File

@ -125,10 +125,6 @@
}
var errorDetail = Array.isArray(data.details) && data.details[0];
if (errorDetail && ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED'].includes(errorDetail.issue)) {
return actions.restart();
}
let storeCard = document.querySelector('input[name=token-billing-checkbox]:checked');
@ -136,9 +132,44 @@
document.getElementById("store_card").value = storeCard.value;
}
document.getElementById("gateway_response").value = JSON.stringify( data );
document.getElementById("server_response").submit();
document.getElementById("gateway_response").value =JSON.stringify( data );
formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server_response")))),
fetch('{{ route('client.payments.response') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
},
body: formData,
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
var errorDetail = Array.isArray(data.details) && data.details[0];
if (errorDetail && ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED'].includes(errorDetail.issue)) {
return actions.restart();
}
if(data.redirect){
window.location.href = data.redirect;
return;
}
document.getElementById("gateway_response").value =JSON.stringify( data );
document.getElementById("server_response").submit();
})
.catch(error => {
console.error('Error:', error);
});
},
onCancel: function() {
@ -160,8 +191,8 @@
// Render each field after checking for eligibility
if (cardField.isEligible()) {
const nameField = cardField.NameField();
nameField.render("#card-name-field-container");
// const nameField = cardField.NameField();
// nameField.render("#card-name-field-container");
const numberField = cardField.NumberField({
inputEvents: {

View File

@ -26,7 +26,6 @@
@push('footer')
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&currency={!! $currency !!}&merchant-id={!! $merchantId !!}&components=buttons,funding-eligibility&intent=capture&enable-funding={!! $funding_source !!}" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
<div id="paypal-button-container"></div>
<script>
//&buyer-country=US&currency=USD&enable-funding=venmo
@ -43,13 +42,48 @@
},
onApprove: function(data, actions) {
document.getElementById("gateway_response").value =JSON.stringify( data );
formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server_response")))),
fetch('{{ route('client.payments.response') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
},
body: formData,
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
var errorDetail = Array.isArray(data.details) && data.details[0];
if (errorDetail && ['INSTRUMENT_DECLINED', 'PAYER_ACTION_REQUIRED'].includes(errorDetail.issue)) {
return actions.restart();
}
if(data.redirect){
window.location.href = data.redirect;
return;
}
document.getElementById("gateway_response").value =JSON.stringify( data );
document.getElementById("server_response").submit();
})
.catch(error => {
console.error('Error:', error);
document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`;
document.getElementById('errors').hidden = false;
});
},
onCancel: function() {

View File

@ -35,14 +35,14 @@ class LoginTest extends TestCase
Session::start();
}
public function testLoginFormDisplayed()
{
$response = $this->get('/login', [
'_token' => csrf_token(),
]);
// public function testLoginFormDisplayed()
// {
// $response = $this->get('/login', [
// '_token' => csrf_token(),
// ]);
$response->assertStatus(404);
}
// $response->assertStatus(404);
// }
/**
* A valid user can be logged in.

View File

@ -11,23 +11,24 @@
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Account;
use App\Models\Company;
use App\Models\Invoice;
use Tests\MockAccountData;
use App\Models\CompanyToken;
use App\Models\ClientContact;
use App\Jobs\Util\ReminderJob;
use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash;
use App\DataMapper\CompanySettings;
use App\Factory\CompanyUserFactory;
use App\Jobs\Util\ReminderJob;
use App\Models\Account;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Company;
use App\Models\CompanyToken;
use App\Models\Invoice;
use App\Models\User;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Carbon;
use Tests\MockAccountData;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* @test
@ -138,7 +139,8 @@ class ReminderTest extends TestCase
'is_primary' => 1,
'first_name' => 'john',
'last_name' => 'doe',
'email' => 'john@doe.com'
'email' => 'john@doe.com',
'send_email' => true,
]);
$this->invoice = Invoice::factory()->create([
@ -157,6 +159,147 @@ class ReminderTest extends TestCase
}
public function testDKRemindersNotSending()
{
//Schedule
// Settings:
// Payment terms: 14 days
// 1st reminder: after 5 days
// 2st reminder: after 10 days
// 3rd reminder: after 15 days
// Endless reminder: all 2 weeks
// Email settings: 9:00
// Timezone: UTC+1
$settings = CompanySettings::defaults();
$settings->timezone_id = '40';
$settings->entity_send_time = 9;
$settings->payment_terms = '14';
$settings->send_reminders = true;
$settings->enable_reminder1 = true;
$settings->enable_reminder2 = true;
$settings->enable_reminder3 = true;
$settings->enable_reminder_endless = true;
$settings->schedule_reminder1 = 'after_invoice_date';
$settings->schedule_reminder2 = 'after_invoice_date';
$settings->schedule_reminder3 = 'after_invoice_date';
$settings->num_days_reminder1 = 5;
$settings->num_days_reminder2 = 10;
$settings->num_days_reminder3 = 15;
$settings->endless_reminder_frequency_id = '3';
$this->buildData($settings);
$this->travelTo(Carbon::parse('2024-03-01')->startOfDay());
$invoice = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'amount' => 10,
'balance' => 10,
'date' => '2024-03-01',
'number' => 'X-11-2024',
'due_date' => null,
'status_id' => 1,
'last_sent_date' => '2024-03-01',
]);
//baseline checks pass
$invoice->service()->createInvitations()->markSent()->save();
$this->assertGreaterThan(0, $invoice->balance);
$this->assertEquals(5, $this->invoice->company->settings->num_days_reminder1);
$this->assertEquals('2024-03-01', now()->format('Y-m-d'));
$this->assertEquals('2024-03-15', $invoice->due_date);
$this->assertEquals('2024-03-06', $invoice->next_send_date->format('Y-m-d'));
// //day five: schedule send time 7am UTC
$this->travelTo(now()->addDays(5)->startOfDay());
$this->assertEquals('2024-03-06', now()->format('Y-m-d'));
$x = false;
do {
$this->travelTo(now()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$x = (bool)$invoice->reminder1_sent;
}
while($x === false);
$this->assertNotNull($invoice->reminder_last_sent);
//check next send date is on day "10"
$this->assertEquals(now()->addDays(5), $invoice->next_send_date);
$this->travelTo(now()->copy()->addDays(5)->startOfDay()->addHours(5));
$this->assertEquals('2024-03-11', now()->format('Y-m-d'));
$this->travelTo(now()->copy()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$this->assertGreaterThan(0, $invoice->balance);
$this->assertNull($invoice->reminder2_sent);
$this->travelTo(now()->copy()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$this->assertNotNull($invoice->reminder2_sent);
$this->assertEquals($invoice->reminder2_sent, $invoice->reminder_last_sent);
$this->assertEquals(now()->addDays(5), $invoice->next_send_date);
//check next send date is on day "15"
$this->assertEquals(now()->addDays(5), $invoice->next_send_date);
$this->travelTo(now()->copy()->addDays(5)->startOfDay()->addHours(5));
$this->assertEquals('2024-03-16', now()->format('Y-m-d'));
$this->travelTo(now()->copy()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$this->assertGreaterThan(0, $invoice->balance);
$this->assertNull($invoice->reminder3_sent);
$this->travelTo(now()->copy()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$this->assertNotNull($invoice->reminder3_sent);
$this->assertEquals($invoice->reminder3_sent, $invoice->reminder_last_sent);
//endless reminders
$this->assertEquals(now()->addDays(14), $invoice->next_send_date);
$this->travelTo(now()->addDays(14)->startOfDay());
$this->assertEquals('2024-03-30', now()->format('Y-m-d'));
$x = false;
do {
$this->travelTo(now()->addHour());
(new ReminderJob())->handle();
$invoice = $invoice->fresh();
$x = (bool)Carbon::parse($invoice->next_send_date)->gt(now()->addDays(2));
} while($x === false);
nlog($invoice->toArray());
$this->assertEquals(now()->addDays(14), $invoice->next_send_date);
}
public function testForUtcEdgeCaseOnTheFirstOfMonth()
{

View File

@ -141,4 +141,55 @@ class AccountSummaryTest extends TestCase
$this->assertEquals($dto->id, 19315);
}
public function testTransformRefactor()
{
$dto = $this->transformSummary($this->data[0]);
$this->assertEquals($dto->id, 19315);
$this->assertEquals($dto->provider_account_id, 330);
$this->assertEquals($dto->account_type, $this->data[0]['CONTAINER'] ?? '');
$this->assertEquals($dto->account_status, $this->data[0]['accountStatus'] ?? '');
$this->assertEquals($dto->account_number, $this->data[0]['accountNumber'] ?? '');
$this->assertEquals($dto->provider_account_id, $this->data[0]['providerAccountId'] ?? '');
$this->assertEquals($dto->provider_id, $this->data[0]['providerId'] ?? '');
$this->assertEquals($dto->provider_name, $this->data[0]['providerName'] ?? '');
$this->assertEquals($dto->nickname, $this->data[0]['nickname'] ?? '');
$this->assertEquals($dto->account_name, $this->data[0]['accountName'] ?? '');
$this->assertEquals($dto->current_balance, $this->data[0]['currentBalance']['amount'] ?? 0);
$this->assertEquals($dto->account_currency, $this->data[0]['currentBalance']['currency'] ?? 0);
$dto_array = (array)$dto;
$this->assertEquals($dto_array['id'], 19315);
$this->assertEquals($dto_array['provider_account_id'], 330);
$this->assertEquals($dto_array['account_type'], $this->data[0]['CONTAINER'] ?? '');
$this->assertEquals($dto_array['account_status'], $this->data[0]['accountStatus'] ?? '');
$this->assertEquals($dto_array['account_number'], $this->data[0]['accountNumber'] ?? '');
$this->assertEquals($dto_array['provider_account_id'], $this->data[0]['providerAccountId'] ?? '');
$this->assertEquals($dto_array['provider_id'], $this->data[0]['providerId'] ?? '');
$this->assertEquals($dto_array['provider_name'], $this->data[0]['providerName'] ?? '');
$this->assertEquals($dto_array['nickname'], $this->data[0]['nickname'] ?? '');
$this->assertEquals($dto_array['account_name'], $this->data[0]['accountName'] ?? '');
$this->assertEquals($dto_array['current_balance'], $this->data[0]['currentBalance']['amount'] ?? 0);
$this->assertEquals($dto_array['account_currency'], $this->data[0]['currentBalance']['currency'] ?? 0);
}
private function transformSummary($summary)
{
$dto = new \stdClass;
$dto->id = $summary['id'] ?? 0;
$dto->account_type = $summary['CONTAINER'] ?? '';
$dto->account_status = $summary['accountStatus'] ?? '';
$dto->account_number = $summary['accountNumber'] ?? '';
$dto->provider_account_id = $summary['providerAccountId'] ?? '';
$dto->provider_id = $summary['providerId'] ?? '';
$dto->provider_name = $summary['providerName'] ?? '';
$dto->nickname = $summary['nickname'] ?? '';
$dto->account_name = $summary['accountName'] ?? '';
$dto->current_balance = $summary['currentBalance']['amount'] ?? 0;
$dto->account_currency = $summary['currentBalance']['currency'] ?? 0;
return $dto;
}
}

View File

@ -1,203 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Integration\Einvoice;
use Tests\TestCase;
use Sabre\Xml\Reader;
use Sabre\Xml\Service;
use Invoiceninja\Einvoice\Models\FACT1\Invoice;
/**
* @test
*/
class FACT1Test extends TestCase
{
public array $set = [];
protected function setUp(): void
{
parent::setUp();
}
public function testValidationFact1()
{
$files = [
'tests/Integration/Einvoice/samples/fact1_no_prefixes.xml',
];
foreach($files as $f) {
$xml = file_get_contents($f);
$xml = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json, true);
$i = Invoice::from($array);
$rules = Invoice::getValidationRules($array);
$this->assertIsArray($rules);
$validation_array = Invoice::validate($array);
$this->assertIsArray($validation_array);
}
}
public function removeNamespacesFromArray($data)
{
if (is_array($data)) {
foreach ($data as &$item) {
if (isset($item['name'])) {
// Remove the namespace from the name
$item['name'] = preg_replace('/^\{\}(.+)/', '$1', $item['name']);
}
if (isset($item['value']) && is_array($item['value'])) {
// Recursively process child elements
$item['value'] = $this->removeNamespacesFromArray($item['value']);
}
if (isset($item['attributes'])) {
unset($item['attributes']);
}
}
}
return $data;
}
// function convertToKeyValue($data)
// {
// $result = [];
// foreach ($data as $item) {
// // Remove namespace prefix if present
// $name = preg_replace('/^\{\}(.+)/', '$1', $item['name']);
// $result[$name] = $item['value'];
// }
// return $result;
// }
// public function keyValueDeserializer(Reader $reader)
// {
// $values = [];
// $reader->read();
// $reader->next();
// foreach ($reader->parseGetElements() as $element) {
// // Strip the namespace prefix
// echo "merp".PHP_EOL;
// $name = preg_replace('/^\{\}.*/', '', $element['name']);
// $values[$name] = $element['value'];
// }
// return $values;
// }
// public function testFactToArray()
// {
// $xml = file_get_contents('tests/Integration/Einvoice/samples/fact1_no_prefixes.xml');
// $service = new Service();
// // $service->elementMap = [
// // '{}' => 'Sabre\Xml\Deserializer\keyValue',
// // ];
// // $service->elementMap = [
// // '{}*' => function (Reader $reader) use ($service) {
// // return $this->keyValueDeserializer($reader);
// // }
// // ];
// $result = $this->removeNamespacesFromArray($service->parse($xml));
// // Convert parsed XML to key-value array
// if (isset($result['value']) && is_array($result['value'])) {
// $keyValueArray = $this->convertToKeyValue($result['value']);
// } else {
// $keyValueArray = [];
// }
// // Output the result
// nlog($keyValueArray);
// // nlog($cleanedArray);
// nlog($service->parse($xml));
// }
// Output the result
// ($xmlWithoutNamespaces);
// $reader = new Reader();
// $service = new Service();
// $service->elementMap = [
// '*' => 'Sabre\Xml\Deserializer\keyValue',
// ];
// nlog($service->parse($xmlstring));
// $payload ='';
// // $reader->xml($xmlstring);
// // $payload = $reader->parse();
// // nlog($payload);
// $validation_array = false;
// try {
// $rules = Invoice::getValidationRules($payload);
// nlog($rules);
// $this->assertIsArray($rules);
// $payload = Invoice::from($payload)->toArray();
// nlog($payload);
// $this->assertIsArray($payload);
// $validation_array = Invoice::validate($payload);
// $this->assertIsArray($validation_array);
// } catch(\Illuminate\Validation\ValidationException $e) {
// nlog($e->errors());
// }
// $this->assertIsArray($validation_array);
// }
// private function extractName($name): string
// {
// $pattern = '/\{[^{}]*\}([^{}]*)/';
// if (preg_match($pattern, $name, $matches)) {
// $extracted = $matches[1];
// return $extracted;
// }
// return $name;
// }
}

File diff suppressed because one or more lines are too long

View File

@ -92,15 +92,14 @@
</LegalMonetaryTotal>
<InvoiceLine>
<ID>1</ID>
<InvoicedQuantity unitCode="H87">1</InvoicedQuantity> // unitcode is a speciffic
identifier for the type of product <LineExtensionAmount currencyID="RON">
335.00</LineExtensionAmount>
<InvoicedQuantity unitCode="H87">1</InvoicedQuantity> // unitcode is a speciffic identifier for the type of product
<LineExtensionAmount currencyID="RON">335.00</LineExtensionAmount>
<Item>
<Description>Some Description</Description>
<Name>Some product</Name>
<ClassifiedTaxCategory>
<ID>S</ID> // this is a speciffic identifier for the VAT type <Percent>
19</Percent>
<ID>S</ID> // this is a speciffic identifier for the VAT type
<Percent>19</Percent>
<TaxScheme>
<ID>VAT</ID>
</TaxScheme>

View File

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<p:FatturaElettronica versione="FPR12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>00001</ProgressivoInvio>
<FormatoTrasmissione>FPR12</FormatoTrasmissione>
<CodiceDestinatario>ABC1234</CodiceDestinatario>
<ContattiTrasmittente />
</DatiTrasmissione>
<CedentePrestatore>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdFiscaleIVA>
<Anagrafica>
<Denominazione>SOCIETA' ALPHA SRL</Denominazione>
</Anagrafica>
<RegimeFiscale>RF01</RegimeFiscale>
</DatiAnagrafici>
<Sede>
<Indirizzo>VIALE ROMA 543</Indirizzo>
<CAP>07100</CAP>
<Comune>SASSARI</Comune>
<Provincia>SS</Provincia>
<Nazione>IT</Nazione>
</Sede>
</CedentePrestatore>
<CessionarioCommittente>
<DatiAnagrafici>
<CodiceFiscale>09876543210</CodiceFiscale>
<Anagrafica>
<Denominazione>BETA GAMMA</Denominazione>
</Anagrafica>
</DatiAnagrafici>
<Sede>
<Indirizzo>VIA TORINO 38-B</Indirizzo>
<CAP>00145</CAP>
<Comune>ROMA</Comune>
<Provincia>RM</Provincia>
<Nazione>IT</Nazione>
</Sede>
</CessionarioCommittente>
</FatturaElettronicaHeader>
<FatturaElettronicaBody>
<DatiGenerali>
<DatiGeneraliDocumento>
<TipoDocumento>TD01</TipoDocumento>
<Divisa>EUR</Divisa>
<Data>2014-12-18</Data>
<Numero>123</Numero>
<Causale>LA FATTURA FA RIFERIMENTO AD UNA OPERAZIONE AAAA BBBBBBBBBBBBBBBBBB CCC
DDDDDDDDDDDDDDD E FFFFFFFFFFFFFFFFFFFF GGGGGGGGGG HHHHHHH II LLLLLLLLLLLLLLLLL
MMM NNNNN OO PPPPPPPPPPP QQQQ RRRR SSSSSSSSSSSSSS</Causale>
<Causale>SEGUE DESCRIZIONE CAUSALE NEL CASO IN CUI NON SIANO STATI SUFFICIENTI 200
CARATTERI AAAAAAAAAAA BBBBBBBBBBBBBBBBB</Causale>
</DatiGeneraliDocumento>
<DatiOrdineAcquisto>
<RiferimentoNumeroLinea>1</RiferimentoNumeroLinea>
<IdDocumento>66685</IdDocumento>
<NumItem>1</NumItem>
</DatiOrdineAcquisto>
<DatiTrasporto>
<DatiAnagraficiVettore>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>24681012141</IdCodice>
</IdFiscaleIVA>
<Anagrafica>
<Denominazione>Trasporto spa</Denominazione>
</Anagrafica>
</DatiAnagraficiVettore>
<DataOraConsegna>2012-10-22T16:46:12.000+02:00</DataOraConsegna>
</DatiTrasporto>
</DatiGenerali>
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
<Descrizione>LA DESCRIZIONE DELLA FORNITURA PUO' SUPERARE I CENTO CARATTERI CHE
RAPPRESENTAVANO IL PRECEDENTE LIMITE DIMENSIONALE. TALE LIMITE NELLA NUOVA
VERSIONE E' STATO PORTATO A MILLE CARATTERI</Descrizione>
<Quantita>5.00</Quantita>
<PrezzoUnitario>1.00</PrezzoUnitario>
<PrezzoTotale>5.00</PrezzoTotale>
<AliquotaIVA>22.00</AliquotaIVA>
</DettaglioLinee>
<DettaglioLinee>
<NumeroLinea>2</NumeroLinea>
<Descrizione>FORNITURE VARIE PER UFFICIO</Descrizione>
<Quantita>10.00</Quantita>
<PrezzoUnitario>2.00</PrezzoUnitario>
<PrezzoTotale>20.00</PrezzoTotale>
<AliquotaIVA>22.00</AliquotaIVA>
</DettaglioLinee>
<DatiRiepilogo>
<AliquotaIVA>22.00</AliquotaIVA>
<ImponibileImporto>27.00</ImponibileImporto>
<Imposta>5.95</Imposta>
<EsigibilitaIVA>I</EsigibilitaIVA>
</DatiRiepilogo>
</DatiBeniServizi>
<DatiPagamento>
<CondizioniPagamento>TP01</CondizioniPagamento>
<DettaglioPagamento>
<ModalitaPagamento>MP01</ModalitaPagamento>
<DataScadenzaPagamento>2015-01-30</DataScadenzaPagamento>
<ImportoPagamento>32.95</ImportoPagamento>
</DettaglioPagamento>
</DatiPagamento>
</FatturaElettronicaBody>
<FatturaElettronicaBody>
<DatiGenerali>
<DatiGeneraliDocumento>
<TipoDocumento>TD01</TipoDocumento>
<Divisa>EUR</Divisa>
<Data>2014-12-20</Data>
<Numero>456</Numero>
<Causale>LA FATTURA FA RIFERIMENTO AD UNA OPERAZIONE AAAA BBBBBBBBBBBBBBBBBB CCC
DDDDDDDDDDDDDDD E FFFFFFFFFFFFFFFFFFFF GGGGGGGGGG HHHHHHH II LLLLLLLLLLLLLLLLL
MMM NNNNN OO PPPPPPPPPPP QQQQ RRRR SSSSSSSSSSSSSS</Causale>
<Causale>SEGUE DESCRIZIONE CAUSALE NEL CASO IN CUI NON SIANO STATI SUFFICIENTI 200
CARATTERI AAAAAAAAAAA BBBBBBBBBBBBBBBBB</Causale>
</DatiGeneraliDocumento>
<DatiOrdineAcquisto>
<RiferimentoNumeroLinea>1</RiferimentoNumeroLinea>
<IdDocumento>66685</IdDocumento>
<NumItem>1</NumItem>
</DatiOrdineAcquisto>
</DatiGenerali>
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
<Descrizione>PRESTAZIONE DEL SEGUENTE SERVIZIO PROFESSIONALE: LA DESCRIZIONE DELLA
PRESTAZIONE PUO' SUPERARE I CENTO CARATTERI CHE RAPPRESENTAVANO IL PRECEDENTE
LIMITE DIMENSIONALE. TALE LIMITE NELLA NUOVA VERSIONE E' STATO PORTATO A MILLE
CARATTERI</Descrizione>
<PrezzoUnitario>2000.00</PrezzoUnitario>
<PrezzoTotale>2000.00</PrezzoTotale>
<AliquotaIVA>22.00</AliquotaIVA>
</DettaglioLinee>
<DatiRiepilogo>
<AliquotaIVA>22.00</AliquotaIVA>
<ImponibileImporto>2000.00</ImponibileImporto>
<Imposta>440.00</Imposta>
<EsigibilitaIVA>I</EsigibilitaIVA>
</DatiRiepilogo>
</DatiBeniServizi>
<DatiPagamento>
<CondizioniPagamento>TP01</CondizioniPagamento>
<DettaglioPagamento>
<ModalitaPagamento>MP19</ModalitaPagamento>
<DataScadenzaPagamento>2015-01-28</DataScadenzaPagamento>
<ImportoPagamento>2440.00</ImportoPagamento>
</DettaglioPagamento>
</DatiPagamento>
</FatturaElettronicaBody>
</p:FatturaElettronica>