1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-08 20:22:42 +01:00

Merge remote-tracking branch 'upstream/v5-develop' into laravel11

This commit is contained in:
Benjamin Beganović 2024-06-04 17:48:15 +02:00
commit 39a0ffc52d
58 changed files with 1833 additions and 1085 deletions

View File

@ -12,7 +12,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.2
extensions: mysql, mysqlnd, sqlite3, bcmath, gd, curl, zip, openssl, mbstring, xml
- name: Checkout code

View File

@ -12,7 +12,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.2
extensions: mysql, mysqlnd, sqlite3, bcmath, gd, curl, zip, openssl, mbstring, xml
- name: Checkout code

View File

@ -1 +1 @@
5.8.57
5.9.2

View File

@ -105,17 +105,34 @@ class PayPalBalanceAffecting
public $discount;
public $creditTransactionalFee;
public $originalInvoiceId;
public function __construct(private array $import_row){}
public function run(): self
{
$this->cleanUp();
foreach($this->import_row as $key => $value) {
$prop = $this->key_map[$key] ?? false;
if($prop)
if($prop){
echo "Setting {$prop} to {$value}".PHP_EOL;
$this->{$prop} = $value;
}
}
return $this;
}
private function cleanUp(): self
{
foreach($this->key_map as $value){
echo "Setting {$value} to null".PHP_EOL;
$this->{$value} = null;
}
return $this;
@ -149,6 +166,7 @@ class PayPalBalanceAffecting
'line_items' => [$item],
'name' => $this->name ?? '',
'email' => $this->fromEmailAddress ?? '',
'transaction_reference' => $this->transactionId ?? '',
];
}

View File

@ -44,6 +44,9 @@ class ExpenseFilters extends QueryFilters
})
->orWhereHas('vendor', function ($q) use ($filter) {
$q->where('name', 'like', '%'.$filter.'%');
})
->orWhereHas('client', function ($q) use ($filter) {
$q->where('name', 'like', '%'.$filter.'%');
});
});
}

View File

@ -26,7 +26,6 @@ class TaskFilters extends QueryFilters
*
* @param string $filter
* @return Builder
* @deprecated
*/
public function filter(string $filter = ''): Builder
{

View File

@ -35,7 +35,7 @@ class NordigenController extends BaseController
/** @var array $context */
$context = $request->getTokenContent();
$company = $request->getCompany();
$lang = $company->locale();
$lang = substr($company->locale(), 0, 2);
$context["lang"] = $lang;
if (!$context) {
@ -143,7 +143,7 @@ class NordigenController extends BaseController
$data = $request->all();
$company = $request->getCompany();
$account = $company->account;
$lang = $company->locale();
$lang = substr($company->locale(), 0, 2);
/** @var array $context */
$context = $request->getTokenContent();

View File

@ -11,33 +11,35 @@
namespace App\Http\Controllers;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Invoice;
use App\Utils\HtmlEngine;
use Illuminate\Support\Str;
use Twig\Error\SyntaxError;
use App\Jobs\Util\PreviewPdf;
use App\Models\ClientContact;
use App\Services\Pdf\PdfMock;
use App\Utils\Traits\MakesHash;
use App\Services\Pdf\PdfService;
use App\Utils\PhantomJS\Phantom;
use App\Models\InvoiceInvitation;
use App\Services\PdfMaker\Design;
use App\Utils\HostedPDF\NinjaPdf;
use Illuminate\Support\Facades\DB;
use App\Services\PdfMaker\PdfMaker;
use Illuminate\Support\Facades\App;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesInvoiceHtml;
use Turbo124\Beacon\Facades\LightLogs;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\Response;
use App\DataMapper\Analytics\LivePreview;
use App\Services\Template\TemplateService;
use App\Http\Requests\Preview\ShowPreviewRequest;
use App\Http\Requests\Preview\DesignPreviewRequest;
use App\Http\Requests\Preview\PreviewInvoiceRequest;
use App\Http\Requests\Preview\ShowPreviewRequest;
use App\Jobs\Util\PreviewPdf;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Services\Pdf\PdfMock;
use App\Services\Pdf\PdfService;
use App\Services\PdfMaker\Design;
use App\Services\PdfMaker\PdfMaker;
use App\Services\Template\TemplateService;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesInvoiceHtml;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Response;
use Turbo124\Beacon\Facades\LightLogs;
use Twig\Error\SyntaxError;
use App\Utils\VendorHtmlEngine;
class PreviewController extends BaseController
{
@ -136,6 +138,7 @@ class PreviewController extends BaseController
*/
public function show(ShowPreviewRequest $request)
{
if($request->input('design.is_template')) {
return $this->template();
}
@ -143,8 +146,8 @@ class PreviewController extends BaseController
if (request()->has('entity') &&
request()->has('entity_id') &&
! empty(request()->input('entity')) &&
! empty(request()->input('entity_id')) &&
request()->has('body')) {
! empty(request()->input('entity_id')))
{
$design_object = json_decode(json_encode(request()->input('design')));
@ -152,7 +155,8 @@ class PreviewController extends BaseController
return response()->json(['message' => ctrans('texts.invalid_design_object')], 400);
}
$entity = ucfirst(request()->input('entity'));
// $entity = ucfirst(request()->input('entity'));
$entity = Str::camel(request()->input('entity'));
$class = "App\Models\\$entity";
@ -166,17 +170,20 @@ class PreviewController extends BaseController
App::forgetInstance('translator');
$t = app('translator');
App::setLocale($entity_obj->client->primary_contact()->preferredLocale());
App::setLocale($entity_obj->client->preferredLocale());
$t->replace(Ninja::transformTranslations($entity_obj->client->getMergedSettings()));
$html = new HtmlEngine($entity_obj->invitations()->first());
if($entity_obj->client){
$html = new HtmlEngine($entity_obj->invitations()->first());
}
else {
$html = new VendorHtmlEngine($entity_obj->invitations()->first());
}
$design_namespace = 'App\Services\PdfMaker\Designs\\'.request()->design['name'];
$design_class = new $design_namespace();
$design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]);
$state = [
'template' => $design_class->elements([
'template' => $design->elements([
'client' => $entity_obj->client,
'entity' => $entity_obj,
'pdf_variables' => (array) $entity_obj->company->settings->pdf_variables,
@ -191,7 +198,6 @@ class PreviewController extends BaseController
]
];
$design = new Design(request()->design['name']);
$maker = new PdfMaker($state);
$maker

View File

@ -70,12 +70,10 @@ class StartupCheck
private function buildTemplates($name = 'templates')
{
$data = [
'invoice' => [
'subject' => EmailTemplateDefaults::emailInvoiceSubject(),
'body' => EmailTemplateDefaults::emailInvoiceTemplate(),
],
'quote' => [
'subject' => EmailTemplateDefaults::emailQuoteSubject(),
'body' => EmailTemplateDefaults::emailQuoteTemplate(),

View File

@ -38,7 +38,7 @@ class StoreVendorRequest extends Request
$user = auth()->user();
$rules = [];
$rules['name'] = 'bail|required|string';
$rules['contacts'] = 'bail|array';
$rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email';
$rules['contacts.*.password'] = [

View File

@ -81,7 +81,7 @@ class SubscriptionCron
$company = Company::find($company_id);
$timezone_now = now()->setTimezone($company->timezone()->name);
$timezone_now = now()->setTimezone($company->timezone()->name ?? 'Pacific/Midway');
//Capture companies within the window of 00:00 and 00:30
if($timezone_now->gt($timezone_now->copy()->startOfDay()) && $timezone_now->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {

View File

@ -112,6 +112,7 @@ class NinjaMailerJob implements ShouldQueue
->mailable
->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('x-invitation', $this->nmo->invitation->key);
// $message->getHeaders()->addTextHeader('List-Unsubscribe', $this->nmo->mailable->viewData->email_preferences);
});
}

View File

@ -51,6 +51,7 @@ use Laracasts\Presenter\PresentableTrait;
* @property int|null $last_login
* @property int|null $industry_id
* @property int|null $size_id
* @property object|null $e_invoice
* @property string|null $address1
* @property string|null $address2
* @property string|null $city
@ -185,6 +186,7 @@ class Client extends BaseModel implements HasLocalePreference
'deleted_at' => 'timestamp',
'last_login' => 'timestamp',
'tax_data' => 'object',
'e_invoice' => 'object',
];
protected $touches = [];
@ -376,15 +378,16 @@ class Client extends BaseModel implements HasLocalePreference
public function language()
{
$languages = Cache::get('languages');
$languages = app('languages');
// $languages = Cache::get('languages');
if (! $languages) {
$this->buildCache(true);
}
// if (! $languages) {
// $this->buildCache(true);
// }
return $languages->filter(function ($item) {
return $languages->first(function ($item) {
return $item->id == $this->getSetting('language_id');
})->first();
});
}
public function industry(): BelongsTo
@ -408,28 +411,30 @@ class Client extends BaseModel implements HasLocalePreference
public function date_format()
{
$date_formats = Cache::get('date_formats');
$date_formats = app('date_formats');
// $date_formats = Cache::get('date_formats');
if (! $date_formats) {
$this->buildCache(true);
}
// if (! $date_formats) {
// $this->buildCache(true);
// }
return $date_formats->filter(function ($item) {
return $date_formats->first(function ($item) {
return $item->id == $this->getSetting('date_format_id');
})->first()->format;
})->format;
}
public function currency()
{
$currencies = Cache::get('currencies');
$currencies = app('currencies');
// $currencies = Cache::get('currencies');
if (! $currencies) {
$this->buildCache(true);
}
// if (! $currencies) {
// $this->buildCache(true);
// }
return $currencies->filter(function ($item) {
return $currencies->first(function ($item) {
return $item->id == $this->getSetting('currency_id');
})->first();
});
}
public function service(): ClientService
@ -737,15 +742,17 @@ class Client extends BaseModel implements HasLocalePreference
public function preferredLocale()
{
$languages = Cache::get('languages');
$this->language()->locale ?? 'en';
// $languages = app('languages');
// $languages = Cache::get('languages');
if (! $languages) {
$this->buildCache(true);
}
// if (! $languages) {
// $this->buildCache(true);
// }
return $languages->filter(function ($item) {
return $item->id == $this->getSetting('language_id');
})->first()->locale;
// return $languages->first(function ($item) {
// return $item->id == $this->getSetting('language_id');
// })->locale;
}
public function backup_path(): string

View File

@ -20,6 +20,10 @@ use App\Utils\Traits\MakesHash;
use App\PaymentDrivers\Common\MethodInterface;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Exceptions\PaymentFailed;
use Illuminate\Mail\Mailables\Address;
use App\Services\Email\EmailObject;
use App\Services\Email\Email;
use Illuminate\Support\Facades\App;
class BTCPay implements MethodInterface
{
@ -128,18 +132,55 @@ class BTCPay implements MethodInterface
public function refund(Payment $payment, $amount)
{
try {
$invoice = $payment->invoices()->first();
$isPartialRefund = ($amount < $payment->amount);
if ($amount == $payment->amount) {
$refundVariant = "Fiat";
$refundPaymentMethod = "BTC";
$refundDescription = "Full refund";
$refundCustomCurrency = null;
$refundCustomAmount = null;
} else {
$refundVariant = "Custom";
$refundPaymentMethod = "";
$refundDescription = "Partial refund";
$refundCustomCurrency = $payment->currency;
$refundCustomAmount = $amount;
}
$client = new \BTCPayServer\Client\Invoice($this->driver_class->btcpay_url, $this->driver_class->api_key);
$refund = $client->refundInvoice($this->driver_class->store_id, $payment->transaction_reference);
$refund = $client->refundInvoice(
$this->driver_class->store_id,
$payment->transaction_reference,
$refundVariant,
$refundPaymentMethod,
null,
$refundDescription,
0,
$refundCustomAmount,
$refundCustomCurrency
);
App::setLocale($payment->company->getLocale());
/* $data = [];
$data['InvoiceNumber'] = $invoice->number;
$data['isPartialRefund'] = $isPartialRefund;
$data['BTCPayLink'] = $refund->getViewLink();*/
$mo = new EmailObject();
$mo->subject = ctrans('texts.btcpay_refund_subject');
$mo->body = ctrans('texts.btcpay_refund_body') . '<br>' . $refund->getViewLink();
$mo->text_body = ctrans('texts.btcpay_refund_body') . '\n' . $refund->getViewLink();
$mo->company_key = $payment->company->company_key;
$mo->html_template = 'email.template.generic';
$mo->to = [new Address($payment->client->present()->email(), $payment->client->present()->name())];
$mo->email_template_body = 'btcpay_refund_subject';
$mo->email_template_subject = 'btcpay_refund_body';
return $refund->getViewLink();
Email::dispatch($mo, $payment->company);
$data = [
'transaction_reference' => $refund->getId(),
'transaction_response' => json_encode($refund),
'success' => true,
'description' => "Please follow this link to claim your refund: " . $refund->getViewLink(),
'code' => 202,
];
return $data;
} catch (\Throwable $e) {
throw new PaymentFailed('Error during BTCPay refund : ' . $e->getMessage());
}

View File

@ -79,10 +79,14 @@ class BTCPayPaymentDriver extends BaseDriver
return $this->payment_method->paymentView($data); //this is your custom implementation from here
}
public function processPaymentResponse($request)
{
return $this->payment_method->paymentResponse($request);
}
public function processWebhookRequest()
{
$webhook_payload = file_get_contents('php://input');
//file_put_contents("/home/claude/invoiceninja/storage/my.log", $webhook_payload);
$btcpayRep = json_decode($webhook_payload);
if ($btcpayRep == null) {

View File

@ -0,0 +1,131 @@
<?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\Providers;
use App\Models\Bank;
use App\Models\Size;
use App\Models\Country;
use App\Models\Gateway;
use App\Models\Currency;
use App\Models\Industry;
use App\Models\Language;
use App\Models\Timezone;
use App\Models\DateFormat;
use App\Models\PaymentTerm;
use Illuminate\Support\ServiceProvider;
use App\DataMapper\EmailTemplateDefaults;
class StaticServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
app()->singleton('currencies', function ($app) {
return Currency::query()->orderBy('name')->get();
});
app()->singleton('languages', function ($app) {
return Language::query()->orderBy('name')->get();
});
app()->singleton('countries', function ($app) {
return Country::query()->orderBy('name')->get();
});
app()->singleton('payment_types', function ($app) {
return PaymentTerm::query()->orderBy('num_days')->get();
});
app()->singleton('industries', function ($app) {
return Industry::query()->orderBy('name')->get();
});
app()->singleton('banks', function ($app) {
return Bank::query()->orderBy('name')->get();
});
app()->singleton('date_formats', function ($app) {
return DateFormat::query()->orderBy('id')->get();
});
app()->singleton('timezones', function ($app) {
return Timezone::query()->orderBy('id')->get();
});
app()->singleton('gateways', function ($app) {
return Gateway::query()->orderBy('id')->get();
});
app()->singleton('industries', function ($app) {
return Industry::query()->orderBy('id')->get();
});
app()->singleton('sizes', function ($app) {
return Size::query()->orderBy('id')->get();
});
/** @deprecated */
app()->singleton('banks', function ($app) {
return Bank::query()->orderBy('id')->get();
});
app()->singleton('templates', function ($app) {
return [
'invoice' => [
'subject' => EmailTemplateDefaults::emailInvoiceSubject(),
'body' => EmailTemplateDefaults::emailInvoiceTemplate(),
],
'quote' => [
'subject' => EmailTemplateDefaults::emailQuoteSubject(),
'body' => EmailTemplateDefaults::emailQuoteTemplate(),
],
'payment' => [
'subject' => EmailTemplateDefaults::emailPaymentSubject(),
'body' => EmailTemplateDefaults::emailPaymentTemplate(),
],
'reminder1' => [
'subject' => EmailTemplateDefaults::emailReminder1Subject(),
'body' => EmailTemplateDefaults::emailReminder1Template(),
],
'reminder2' => [
'subject' => EmailTemplateDefaults::emailReminder2Subject(),
'body' => EmailTemplateDefaults::emailReminder2Template(),
],
'reminder3' => [
'subject' => EmailTemplateDefaults::emailReminder3Subject(),
'body' => EmailTemplateDefaults::emailReminder3Template(),
],
'reminder_endless' => [
'subject' => EmailTemplateDefaults::emailReminderEndlessSubject(),
'body' => EmailTemplateDefaults::emailReminderEndlessTemplate(),
],
'statement' => [
'subject' => EmailTemplateDefaults::emailStatementSubject(),
'body' => EmailTemplateDefaults::emailStatementTemplate(),
],
];
});
}
public function boot()
{
}
}

View File

@ -11,19 +11,20 @@
namespace App\Services\Email;
use App\DataMapper\EmailTemplateDefaults;
use App\Jobs\Entity\CreateRawPdf;
use App\Jobs\Invoice\CreateUbl;
use App\Models\Task;
use App\Utils\Ninja;
use App\Models\Quote;
use App\Models\Account;
use App\Models\Expense;
use App\Models\Invoice;
use App\Models\PurchaseOrder;
use App\Models\Quote;
use App\Models\Task;
use App\Utils\Ninja;
use App\Jobs\Invoice\CreateUbl;
use App\Utils\Traits\MakesHash;
use Illuminate\Mail\Mailables\Address;
use App\Jobs\Entity\CreateRawPdf;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
use Illuminate\Mail\Mailables\Address;
use App\DataMapper\EmailTemplateDefaults;
use League\CommonMark\CommonMarkConverter;
class EmailDefaults
@ -388,6 +389,7 @@ class EmailDefaults
{
if ($this->email->email_object->invitation_key) {
$this->email->email_object->headers = array_merge($this->email->email_object->headers, ['x-invitation' => $this->email->email_object->invitation_key]);
// $this->email->email_object->headers = array_merge($this->email->email_object->headers, ['x-invitation' => $this->email->email_object->invitation_key,'List-Unsubscribe' => URL::signedRoute('client.email_preferences', ['entity' => $this->email->email_object->invitation->getEntityString(), 'invitation_key' => $this->email->email_object->invitation->key])]);
}
return $this;

View File

@ -570,7 +570,7 @@ class InvoiceService
$this->invoice->exchange_rate = $this->invoice->client->setExchangeRate();
}
if ($is_recurring && $this->invoice->client->getSetting('auto_bill_standard_invoices')) {
if (!$is_recurring && $this->invoice->client->getSetting('auto_bill_standard_invoices')) {
$this->invoice->auto_bill_enabled = true;
}

View File

@ -341,7 +341,7 @@ class PdfMock
'$client.currency' => 'USD',
'$company.country' => $this->company->country()?->name ?? 'USA',
'$company.address' => $this->company->present()->address(),
'$tech_hero_image' => 'http://ninja.test:8000/images/pdf-designs/tech-hero-image.jpg',
'$tech_hero_image' => 'https://invoicing.co/images/pdf-designs/tech-hero-image.jpg',
'$task.tax_name1' => '',
'$task.tax_name2' => '',
'$task.tax_name3' => '',

View File

@ -164,6 +164,7 @@ class ClientTransformer extends EntityTransformer
'routing_id' => (string) $client->routing_id,
'tax_info' => $client->tax_data ?: new \stdClass(),
'classification' => $client->classification ?: '',
'e_invoice' => $client->e_invoice ?: new \stdClass(),
];
}
}

View File

@ -72,6 +72,9 @@ class CompanyShopProfileTransformer extends EntityTransformer
'email' => $company->settings->email,
'country_id' => $company->settings->country_id,
'vat_number' => $company->settings->vat_number,
'product' => $company->settings->translations->product ?? ctrans('texts.product'),
'products' => $company->settings->translations->products ?? ctrans('texts.products'),
'client_registration_fields' => $company->client_registration_fields,
];
$new_settings = new stdClass();

View File

@ -660,10 +660,12 @@ class HtmlEngine
if ($this->settings->signature_on_pdf) {
$data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
$data['$contact.signature_date'] = ['value' => $this->translateDate($this->invitation->signature_date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.date')];
$data['$contact.signature_ip'] = ['value' => $this->invitation->signature_ip ?? '', 'label' => ctrans('texts.address')];
} else {
$data['$contact.signature'] = ['value' => '', 'label' => ''];
$data['$contact.signature_date'] = ['value' => '', 'label' => ctrans('texts.date')];
$data['$contact.signature_ip'] = ['value' => '', 'label' => ctrans('texts.address')];
}
$data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')];

View File

@ -45,7 +45,6 @@
"braintree/braintree_php": "^6.0",
"btcpayserver/btcpayserver-greenfield-php": "^2.6",
"checkout/checkout-sdk-php": "^3.0",
"invoiceninja/ubl_invoice": "^2",
"doctrine/dbal": "^4.0",
"eway/eway-rapid-php": "^1.3",
"fakerphp/faker": "^1.14",
@ -56,10 +55,14 @@
"halaxa/json-machine": "^0.7.0",
"hashids/hashids": "^4.0",
"hedii/laravel-gelf-logger": "^9",
"horstoeko/orderx": "dev-master",
"horstoeko/zugferd": "^1",
"hyvor/php-json-exporter": "^0.0.3",
"imdhemy/laravel-purchases": "^1.7",
"intervention/image": "^2.5",
"invoiceninja/inspector": "^3.0",
"invoiceninja/einvoice": "dev-main",
"invoiceninja/ubl_invoice": "^2",
"josemmo/facturae-php": "^1.7",
"laracasts/presenter": "^0.2.1",
"laravel/framework": "^11.0",
@ -89,7 +92,7 @@
"setasign/fpdi": "^2.3",
"socialiteproviders/apple": "dev-master",
"socialiteproviders/microsoft": "^4.1",
"spatie/laravel-data": "^3.5",
"spatie/laravel-data": "^3.6",
"sprain/swiss-qr-bill": "^4.3",
"square/square": "30.0.0.*",
"stripe/stripe-php": "^12",
@ -102,10 +105,7 @@
"twig/twig": "^3",
"twilio/sdk": "^6.40",
"webpatser/laravel-countries": "dev-master#75992ad",
"wildbit/postmark-php": "^4.0",
"hyvor/php-json-exporter": "^0.0.3",
"invoiceninja/einvoice": "dev-main",
"horstoeko/orderx": "dev-master"
"wildbit/postmark-php": "^4.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.6",

8
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": "7a41ed3da96a8351f9ef162244dad6da",
"content-hash": "942c6a9765c10a4c48ad4904e2561cb7",
"packages": [
{
"name": "adrienrn/php-mimetyper",
@ -20357,10 +20357,10 @@
"minimum-stability": "dev",
"stability-flags": {
"asm/php-ansible": 20,
"socialiteproviders/apple": 20,
"webpatser/laravel-countries": 20,
"horstoeko/orderx": 20,
"invoiceninja/einvoice": 20,
"horstoeko/orderx": 20
"socialiteproviders/apple": 20,
"webpatser/laravel-countries": 20
},
"prefer-stable": true,
"prefer-lowest": false,

View File

@ -201,6 +201,7 @@ return [
App\Providers\MultiDBProvider::class,
App\Providers\ClientPortalServiceProvider::class,
App\Providers\NinjaTranslationServiceProvider::class,
App\Providers\StaticServiceProvider::class,
],
/*
@ -215,8 +216,8 @@ return [
*/
'aliases' => Facade::defaultAliases()->merge([
'Collector' => Turbo124\Collector\CollectorFacade::class,
'Countries' => 'Webpatser\Countries\CountriesFacade',
'Collector' => Turbo124\Beacon\CollectorFacade::class,
// 'Countries' => 'Webpatser\Countries\CountriesFacade',
'CustomMessage' => App\Utils\ClientPortal\CustomMessage\CustomMessageFacade::class,
'Redis' => Illuminate\Support\Facades\Redis::class,
])->toArray(),

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.58'),
'app_tag' => env('APP_TAG', '5.8.58'),
'app_version' => env('APP_VERSION', '5.9.2'),
'app_tag' => env('APP_TAG', '5.9.2'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),

View File

@ -36,7 +36,6 @@ return new class extends Migration
$table->mediumText('e_invoice')->nullable();
});
Schema::table('accounts', function (Blueprint $table) {
$table->integer('email_quota')->default(20)->nullable();
});

View File

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('clients', function (Blueprint $table) {
$table->mediumText('e_invoice')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
if($g = \App\Models\Gateway::find(62))
{
$g->fields = '{"btcpayUrl":"", "apiKey":"", "storeId":"", "webhookSecret":""}';
$g->save();
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

View File

@ -87,7 +87,7 @@ class PaymentLibrariesSeeder extends Seeder
['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'],
['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'],
['id' => 61, 'name' => 'PayPal Platform', 'provider' => 'PayPal_PPCP', 'key' => '80af24a6a691230bbec33e930ab40666', 'fields' => '{"testMode":false}'],
['id' => 62, 'name' => 'BTCPay', 'provider' => 'BTCPay', 'key' => 'vpyfbmdrkqcicpkjqdusgjfluebftuva', 'fields' => '{"btcpayUrl":"", "apiKey:"", "storeId":"", "webhookSecret":""}'],
['id' => 62, 'name' => 'BTCPay', 'provider' => 'BTCPay', 'key' => 'vpyfbmdrkqcicpkjqdusgjfluebftuva', 'fields' => '{"btcpayUrl":"", "apiKey":"", "storeId":"", "webhookSecret":""}'],
];
foreach ($gateways as $gateway) {

View File

@ -252,7 +252,7 @@ class RandomDataSeeder extends Seeder
$invoice->service()->createInvitations()->markSent()->save();
$invoice->ledger()->update_invoiceBalance($invoice->balance);
$invoice->ledger()->updateInvoiceBalance($invoice->balance);
if (rand(0, 1)) {
$payment = Payment::create([

View File

@ -199,7 +199,7 @@ $lang = array(
'removed_logo' => 'Successfully removed logo',
'sent_message' => 'Successfully sent message',
'invoice_error' => 'Please make sure to select a client and correct any errors',
'limit_clients' => 'You\'ve hit the :count client limit on Free accounts. Congrats on your success!.',
'limit_clients' => 'You\'ve hit the :count client limit on Free accounts. Congrats on your success!',
'payment_error' => 'There was an error processing your payment. Please try again later.',
'registration_required' => 'Registration Required',
'confirmation_required' => 'Please confirm your email address, :link to resend the confirmation email.',
@ -5147,7 +5147,7 @@ $lang = array(
'payment_refund_receipt' => 'Payment Refund Receipt # :number',
'payment_receipt' => 'Payment Receipt # :number',
'load_template_description' => 'The template will be applied to following:',
'run_template' => 'Run template',
'run_template' => 'Run Template',
'statement_design' => 'Statement Design',
'delivery_note_design' => 'Delivery Note Design',
'payment_receipt_design' => 'Payment Receipt Design',
@ -5306,18 +5306,20 @@ $lang = array(
'activity_140' => 'Statement sent to :client',
'invoice_net_amount' => 'Invoice Net Amount',
'round_to_minutes' => 'Round To Minutes',
'1_second' => '1 Second',
'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',
'round_tasks' => 'Task Rounding Direction',
'round_tasks_help' => 'Round task times up or down.',
'direction' => 'Direction',
'round_up' => 'Round Up',
'round_down' => 'Round Down',
'task_round_to_nearest' => 'Round To Nearest',
'task_round_to_nearest_help' => 'The interval to round the task to.',
'bulk_updated' => 'Successfully updated data',
'bulk_update' => 'Bulk Update',
'calculate' => 'Calculate',
@ -5328,9 +5330,10 @@ $lang = array(
'disconnected' => 'Disconnected',
'reconnect' => 'Reconnect',
'e_invoice_settings' => 'E-Invoice Settings',
'btcpay_refund_subject' => 'Refund of your invoice via BTCPay',
'btcpay_refund_body' => 'A refund intended for you has been issued. To claim it via BTCPay, please click on this link:',
'currency_mauritanian_ouguiya' => 'Mauritanian Ouguiya',
'currency_bhutan_ngultrum' => 'Bhutan Ngultrum',
);
return $lang;
return $lang;

View File

@ -5322,6 +5322,12 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'money' => 'Argent',
'web_app' => 'App web',
'desktop_app' => 'App de bureau',
'disconnected' => 'Déconnecté',
'reconnect' => 'Reconnecté',
'e_invoice_settings' => 'Paramètres E-Facture',
'currency_mauritanian_ouguiya' => 'Ouguiya mauritanien',
'currency_bhutan_ngultrum' => 'Ngultrum Bhoutan',
);
return $lang;

1982
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,18 +9,20 @@
"@babel/compat-data": "7.15.0",
"@babel/plugin-proposal-class-properties": "^7.14.5",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/line-clamp": "^0.4.4",
"@tailwindcss/typography": "^0.5.10",
"autoprefixer": "^10.4.18",
"cypress": "^12.5.1",
"laravel-mix-purgecss": "^6.0.0",
"laravel-vite-plugin": "^0.8.0",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"vite": "^4.4.9",
"vite-plugin-static-copy": "^0.17.0",
"vue-template-compiler": "^2.6.14"
},
"dependencies": {
"@tailwindcss/forms": "^0.3.4",
"@tailwindcss/line-clamp": "^0.3.1",
"@tailwindcss/typography": "^0.4.1",
"autoprefixer": "^10.3.7",
"axios": "^0.25",
"card-js": "^1.0.13",
"card-validator": "^8.1.1",
@ -31,11 +33,9 @@
"laravel-mix": "^6.0.34",
"linkify-urls": "^4.0.0",
"lodash": "^4.17.21",
"postcss": "^8.3.11",
"resolve-url-loader": "^4.0.0",
"sass": "^1.43.4",
"sass-loader": "^12.3.0",
"tailwindcss": "^2.2.17"
"sass-loader": "^12.3.0"
},
"type": "module"
}

109
public/build/assets/app-8722f22d.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
public/build/assets/app-c7c5fad4.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
]
},
"resources/js/app.js": {
"file": "assets/app-a52d5f77.js",
"file": "assets/app-8722f22d.js",
"imports": [
"_index-08e160a7.js",
"__commonjsHelpers-725317a4.js"
@ -240,7 +240,7 @@
"src": "resources/js/setup/setup.js"
},
"resources/sass/app.scss": {
"file": "assets/app-c6dc74fe.css",
"file": "assets/app-c7c5fad4.css",
"isEntry": true,
"src": "resources/sass/app.scss"
}

View File

@ -3,7 +3,7 @@
}
.alert-success {
@apply border-green-500;
@apply border-emerald-500;
}
.alert-failure {

View File

@ -15,7 +15,7 @@
}
.badge-success {
@apply bg-green-100 text-green-500;
@apply bg-emerald-100 text-emerald-500;
}
.badge-secondary {
@ -23,7 +23,7 @@
}
.badge-warning {
@apply bg-blue-500 text-yellow-600;
@apply bg-blue-500 text-amber-600;
}
.badge-info {

View File

@ -7,5 +7,5 @@
}
.validation-pass {
@apply border-green-500 text-gray-700 text-sm;
@apply border-emerald-500 text-gray-700 text-sm;
}

View File

@ -132,7 +132,7 @@
<div class="flex justify-between items-center mt-8">
<a href="{{route('client.login')}}" class="button button-info bg-green-600 text-white">{{ ctrans('texts.login_label') }}</a>
<a href="{{route('client.login')}}" class="button button-info bg-emerald-600 text-white">{{ ctrans('texts.login_label') }}</a>
<span class="inline-flex items-center" x-data="{ terms_of_service: false, privacy_policy: false }">
@if(!empty($register_company->settings->client_portal_terms) || !empty($register_company->settings->client_portal_privacy_policy))

View File

@ -25,7 +25,7 @@
@foreach($multiple_contacts as $contact)
<a data-turbolinks="false"
href="{{ route('client.switch_company', $contact->hashed_id) }}"
class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900">{{ $contact->client->present()->name()}}
class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900">{{ $contact->client->present()->name()}} - ({{$contact->company->present()->name()}})
</a>
@endforeach
</div>

View File

@ -250,7 +250,7 @@
@if($steps['passwordless_login_sent'])
<span
class="block mt-2 text-sm text-green-600">{!! ctrans('texts.sent') !!}</span>
class="block mt-2 text-sm text-emerald-600">{!! ctrans('texts.sent') !!}</span>
@endif
@endif

View File

@ -15,22 +15,22 @@
<table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table bg-white">
<thead>
<tr>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary task_description">
<span role="button" wire:click="sortBy('description')" class="cursor-pointer">
{{ ctrans('texts.description') }}
</span>
</th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary task_project">
<span role="button" wire:click="sortBy('description')" class="cursor-pointer">
{{ ctrans('texts.project') }}
</span>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider task_status">
<span role="button" wire:click="sortBy('status_id')" class="cursor-pointer">
{{ ctrans('texts.status') }}
</span>
</th>
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider task_duration">
<span role="button" class="cursor-pointer">
{{ ctrans('texts.duration') }}
</span>
@ -40,13 +40,13 @@
<tbody>
@foreach($tasks as $task)
<tr class="bg-white group hover:bg-gray-100">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500 task_descripton">
{{ \Illuminate\Support\Str::limit($task->description, 80) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500 task_project">
{{ $task->project?->name }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500 task_status">
<div class="flex">
{!! $task->stringStatus() !!}
@ -59,7 +59,7 @@
@endif
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500 task_duration">
{{ \Carbon\CarbonInterval::seconds($task->calcDuration())->cascade()->forHumans() }}
</td>
</tr>
@ -68,17 +68,17 @@
<table class="min-w-full ml-5">
<thead>
<tr>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500 task_date">
<span>
{{ ctrans('texts.date') }}
</span>
</th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500 task_duration">
<span>
{{ ctrans('texts.duration') }}
</span>
</th>
<th colspan="4" class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<th colspan="4" class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500 task_description">
<span>
{{ ctrans('texts.description') }}
</span>
@ -89,13 +89,13 @@
@foreach($task->processLogsExpandedNotation() as $log)
@if(strlen($log['description']) > 1)
<tr class="bg-white group border-b border-gray-100">
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6 task_date">
{{ $log['start_date']}}
</td>
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6 task_duration">
{{ $log['duration']}}
</td>
<td colspan="4" class="px-6 py-4 text-sm leading-5 text-gray-500 w-4/6">
<td colspan="4" class="px-6 py-4 text-sm leading-5 text-gray-500 w-4/6 task_description">
{!! nl2br(e($log['description'])) !!}
</td>
</tr>

View File

@ -5,10 +5,10 @@
<div class="flex flex-col xl:flex-row gap-4">
<div class="w-full rounded-md border border-[#E5E7EB] bg-white p-5 text-sm text-[#6C727F]">
<h3 class="mb-4 text-xl font-semibold text-[#212529]">{{ $contact->first_name }} {{ $contact->last_name }}</h3>
<p class="mb-1.5">{{ $contact->phone }}</p>
<p class="mb-4">{{ $client->address1 }}</p>
<p class="mb-1.5">{{ $client->city }}, {{ $client->state }}</p>
<p class="mb-1.5">{{ $client->postal_code }}</p>
<p>{{ $contact->phone }}</p>
<p>{{ $client->address1 }}</p>
<p>{{ $client->city }}, {{ $client->state }}</p>
<p>{{ $client->postal_code }}</p>
<p>{{ App\Models\Country::find($client->country_id)?->name }}</p>
</div>
@ -81,16 +81,24 @@
</div>
</div>
<div class="text-light-grey-text flex grow basis-full flex-col justify-center pt-5 text-sm md:basis-1/2 md:border-r md:border-[#E5E7EB] md:pt-0 xl:basis-auto xl:px-5">
<p class="mb-2">{{ $client->company->settings->address1 }}</p>
<p class="mb-2">{{ $client->company->settings->address2 }}</p>
<p class="mb-2">{{ $client->company->settings->postal_code }}</p>
<div class="text-light-grey-text flex grow basis-full flex-col justify-center pt-5 text-sm md:basis-1/2 md:border-r md:border-[#E5E7EB] md:pt-0 xl:basis-auto xl:px-5 space-y-2">
<p>{{ $client->company->settings->address1 }}</p>
<p>{{ $client->company->settings->city }} {{ $client->company->settings->state }}</p>
<p>{{ $client->company->settings->postal_code }}</p>
<p>{{ App\Models\Country::find($client->company->settings->country_id)?->name }}</p>
</div>
<div class="text-light-grey-text flex grow basis-full flex-col justify-center text-sm md:basis-1/2 md:pl-4 xl:basis-auto xl:px-5">
<p class="mb-2">{{ $client->company->settings->email }}</p>
<p class="mb-2">{{ $client->company->settings->phone }}</p>
<p>{{ $client->company->settings->website }}</p>
<div class="text-light-grey-text flex grow basis-full flex-col justify-center text-sm md:basis-1/2 md:pl-4 xl:basis-auto xl:px-5 space-y-2 mt-3 xl:mt-0">
<p><span class="font-semibold">{{ ctrans('texts.vat') }}</span>: {{ $client->company->settings->vat_number }}</p>
<p>
<a class="underline" href="mailto:{{ $client->company->settings->email }}" target="_blank">{{ $client->company->settings->email }}</a>
</p>
<p>{{ $client->company->settings->phone }}</p>
<p>
<a class="underline" href="{{ $client->company->settings->website }}" target="_blank">
{{ $client->company->settings->website }}
</a>
</p>
</div>
</div>
@stop

View File

@ -34,7 +34,7 @@
@if(Request::isSecure())
<span class="block mx-4 mb-4 text-xs inline-flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-600"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-emerald-600"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
<span class="ml-1">Secure 256-bit encryption</span>
</span>
@endif

View File

@ -56,7 +56,7 @@
</div>
</div>
</div>
<div class="bg-white shadow rounded-sm mb-4 mt-4 border-l-2 border-green-500" translate>
<div class="bg-white shadow rounded-sm mb-4 mt-4 border-l-2 border-emerald-500" translate>
<div class="px-4 py-5 sm:p-6">
<div class="sm:flex sm:items-start sm:justify-between">
<div>

View File

@ -1,27 +1,24 @@
const defaultTheme = require("tailwindcss/defaultTheme");
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
purge: [
content: [
'./resources/views/portal/ninja2020/**/*.blade.php',
'./resources/views/email/template/**/*.blade.php',
'./resources/views/email/components/**/*.blade.php',
'./resources/views/themes/ninja2020/**/*.blade.php',
'./resources/views/auth/**/*.blade.php',
'./resources/views/setup/**/*.blade.php',
'./resources/views/billing-portal/**/*.blade.php',
'./resources/views/billing-portal/**/*.blade.php'
],
theme: {
extend: {
fontFamily: {
sans: ["Open Sans", ...defaultTheme.fontFamily.sans]
}
}
sans: ['Open Sans', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {},
plugins: [
require('@tailwindcss/line-clamp'),
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
]
],
};

View File

@ -28,6 +28,8 @@ class BankIntegrationApiTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
protected $faker;
protected function setUp() :void
{
parent::setUp();

View File

@ -60,6 +60,7 @@ class DesignApiTest extends TestCase
$q = Design::query()
->where('is_template', true)
->where('company_id', $this->company->id)
->whereRaw('FIND_IN_SET( ? ,entities)', [$searchable]);
$this->assertEquals(1, $q->count());

View File

@ -42,7 +42,7 @@ class FatturaPATest extends TestCase
$this->makeTestData();
$this->markTestSkipped('prevent running in CI');
// $this->markTestSkipped('prevent running in CI');
$this->withoutMiddleware(
ThrottleRequests::class
@ -56,9 +56,9 @@ class FatturaPATest extends TestCase
$settings->address1 = 'Via Silvio Spaventa 108';
$settings->city = 'Calcinelli';
$settings->state = 'PA';
$settings->state = 'PA';
// $settings->state = 'Perugia';
// $settings->state = 'Perugia';
$settings->postal_code = '61030';
$settings->country_id = '380';
$settings->currency_id = '3';
@ -129,6 +129,9 @@ $settings->state = 'PA';
$encoder = new Encode($fe);
$xml = $encoder->toXml();
nlog($xml);
$this->assertNotNull($xml);

View File

@ -11,17 +11,18 @@
namespace Tests\Feature\Notify;
use App\DataMapper\CompanySettings;
use App\Models\CompanyToken;
use App\Models\CompanyUser;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Models\Product;
use App\Models\User;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Support\Str;
use Tests\MockAccountData;
use Tests\TestCase;
use App\Models\User;
use App\Models\Invoice;
use App\Models\Product;
use Tests\MockAccountData;
use App\Models\CompanyUser;
use Illuminate\Support\Str;
use App\Models\CompanyToken;
use App\Models\InvoiceInvitation;
use App\DataMapper\CompanySettings;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Routing\Middleware\ThrottleRequests;
/**
* @test
@ -32,6 +33,8 @@ class NotificationTest extends TestCase
use UserNotifies;
use MockAccountData;
protected $faker;
protected function setUp() :void
{
parent::setUp();

View File

@ -27,6 +27,7 @@ class ShopInvoiceTest extends TestCase
{
use MakesHash;
use MockAccountData;
protected $faker;
protected function setUp() :void
{

View File

@ -48,4 +48,60 @@ class ShopProfileTest extends TestCase
$this->assertArrayHasKey('custom_value1', $arr['data']['settings']);
$this->assertEquals($this->company->company_key, $arr['data']['company_key']);
}
public function testProfileSettingsUpdate()
{
$this->company->enable_shop_api = true;
$settings = $this->company->settings;
$trans = new \stdClass;
$trans->product = "Service";
$trans->products = "Services";
$settings->translations = $trans;
$this->company->settings = $settings;
$this->company->save();
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-COMPANY-KEY' => $this->company->company_key,
])->getJson('/api/v1/shop/profile');
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals("Service", $arr['data']['settings']['product']);
$this->assertEquals("Services", $arr['data']['settings']['products']);
}
public function testProfileSettingsUpdate2()
{
$this->company->enable_shop_api = true;
$this->company->save();
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-COMPANY-KEY' => $this->company->company_key,
])->getJson('/api/v1/shop/profile');
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals("Product", $arr['data']['settings']['product']);
$this->assertEquals("Products", $arr['data']['settings']['products']);
$this->assertIsArray($arr['data']['settings']['client_registration_fields']);
}
}

View File

@ -11,12 +11,13 @@
namespace Tests\Unit\ValidationRules;
use App\Http\Requests\Invoice\StoreInvoiceRequest;
use Tests\TestCase;
use App\Models\Invoice;
use Tests\MockAccountData;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Validator;
use Tests\MockAccountData;
use Tests\TestCase;
use App\Http\Requests\Invoice\StoreInvoiceRequest;
use Illuminate\Routing\Middleware\ThrottleRequests;
/**
* @test