mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
dcf474a95c
4
.github/workflows/react_release.yml
vendored
4
.github/workflows/react_release.yml
vendored
@ -44,6 +44,7 @@ jobs:
|
||||
git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git
|
||||
cd ui
|
||||
git checkout develop
|
||||
cp ../vite.config.ts.react ./vite.config.js
|
||||
npm i
|
||||
npm run build
|
||||
cp -r dist/* ../public/
|
||||
@ -60,7 +61,8 @@ jobs:
|
||||
sudo rm -rf node_modules
|
||||
sudo rm -rf .git
|
||||
sudo rm .env
|
||||
|
||||
sudo rm -rf ui
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
shopt -s dotglob
|
||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -72,7 +72,6 @@ jobs:
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
zip -r /home/runner/work/invoiceninja/invoiceninja.zip .* -x "../*"
|
||||
shopt -s dotglob
|
||||
tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar *
|
||||
- name: Release
|
||||
@ -82,5 +81,4 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: |
|
||||
/home/runner/work/invoiceninja/invoiceninja.tar
|
||||
/home/runner/work/invoiceninja/invoiceninja.zip
|
||||
/home/runner/work/invoiceninja/invoiceninja.tar
|
@ -1 +1 @@
|
||||
5.9.2
|
||||
5.9.3
|
@ -66,12 +66,14 @@ class DbQuery extends GenericMixedMetric
|
||||
|
||||
public $double_metric2 = 1;
|
||||
|
||||
public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7)
|
||||
public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7, $string_metric8, $string_metric9)
|
||||
{
|
||||
$this->int_metric1 = $int_metric1;
|
||||
$this->string_metric5 = $string_metric5;
|
||||
$this->string_metric6 = $string_metric6;
|
||||
$this->double_metric2 = $double_metric2;
|
||||
$this->string_metric7 = $string_metric7;
|
||||
$this->string_metric8 = $string_metric8;
|
||||
$this->string_metric9 = $string_metric9;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public $besr_id = ''; //@implemented
|
||||
|
||||
public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented
|
||||
public $lock_invoices = 'off'; //off,when_sent,when_paid,end_of_month //@implemented
|
||||
|
||||
public $enable_client_portal_tasks = false; //@ben to implement
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataProviders;
|
||||
|
||||
/**
|
||||
* Class FACT1.
|
||||
*/
|
||||
class FACT1
|
||||
{
|
||||
public function build()
|
||||
{
|
||||
$i = new \InvoiceNinja\EInvoice\Models\FACT1\Invoice();
|
||||
}
|
||||
}
|
@ -24,9 +24,10 @@ use App\Services\Email\Email;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Services\Email\EmailObject;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer;
|
||||
use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
|
||||
class Nordigen
|
||||
{
|
||||
@ -149,6 +150,10 @@ class Nordigen
|
||||
|
||||
public function disabledAccountEmail(BankIntegration $bank_integration): void
|
||||
{
|
||||
$cache_key = "email_quota:{$bank_integration->company->company_key}:{$bank_integration->id}";
|
||||
|
||||
if(Cache::has($cache_key))
|
||||
return;
|
||||
|
||||
App::setLocale($bank_integration->company->getLocale());
|
||||
|
||||
@ -163,7 +168,8 @@ class Nordigen
|
||||
$mo->email_template_subject = 'nordigen_requisition_subject';
|
||||
|
||||
Email::dispatch($mo, $bank_integration->company);
|
||||
|
||||
|
||||
Cache::put($cache_key, true, 60 * 60 * 24);
|
||||
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ use App\Transformers\ArraySerializer;
|
||||
use App\Transformers\EntityTransformer;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Invoiceninja\Einvoice\Decoder\Schema;
|
||||
use InvoiceNinja\EInvoice\Decoder\Schema;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
@ -998,7 +998,7 @@ class BaseController extends Controller
|
||||
if(request()->has('einvoice')){
|
||||
|
||||
$ro = new Schema();
|
||||
$response_data['einvoice_schema'] = $ro('FACT1');
|
||||
$response_data['einvoice_schema'] = $ro('Peppol');
|
||||
|
||||
}
|
||||
|
||||
|
@ -117,11 +117,21 @@ class CompanyController extends BaseController
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$companies = Company::whereAccountId($user->company()->account->id);
|
||||
$companies = Company::where('account_id', $user->company()->account->id);
|
||||
|
||||
return $this->listResponse($companies);
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$company = Company::find($user->company()->id);
|
||||
|
||||
return $this->itemResponse($company);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
|
@ -408,7 +408,7 @@ class InvoiceController extends BaseController
|
||||
}
|
||||
|
||||
if ($invoice->isLocked()) {
|
||||
return response()->json(['message' => ctrans('texts.locked_invoice')], 422);
|
||||
return response()->json(['message' => '', 'errors' => ['number' => ctrans('texts.locked_invoice')]], 422);
|
||||
}
|
||||
|
||||
$old_invoice = $invoice->line_items;
|
||||
|
@ -13,7 +13,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Utils\Statics;
|
||||
use Illuminate\Http\Response;
|
||||
use Invoiceninja\Einvoice\Decoder\Schema;
|
||||
use InvoiceNinja\EInvoice\Decoder\Schema;
|
||||
|
||||
class StaticController extends BaseController
|
||||
{
|
||||
@ -62,7 +62,7 @@ class StaticController extends BaseController
|
||||
if(request()->has('einvoice')){
|
||||
|
||||
$schema = new Schema();
|
||||
$response_data['einvoice_schema'] = $schema('FACT1');
|
||||
$response_data['einvoice_schema'] = $schema('Peppol');
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ class UpdateInvoiceRequest extends Request
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->invoice->client_id])];
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
@ -80,7 +80,7 @@ $rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['partial'] = 'bail|sometimes|nullable|numeric';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
|
||||
// $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
|
||||
// $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
|
@ -16,6 +16,7 @@ use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
/**
|
||||
* Class LockedInvoiceRule.
|
||||
* @deprecated
|
||||
*/
|
||||
class LockedInvoiceRule implements Rule
|
||||
{
|
||||
@ -67,6 +68,13 @@ class LockedInvoiceRule implements Rule
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
//if now is greater than the end of month the invoice was dated - do not modify
|
||||
case 'end_of_month':
|
||||
if(\Carbon\Carbon::parse($this->invoice->date)->setTimezone($this->invoice->company->timezone()->name)->endOfMonth()->lte(now()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ class ProductMap
|
||||
12 => 'product.custom_value2',
|
||||
13 => 'product.custom_value3',
|
||||
14 => 'product.custom_value4',
|
||||
15 => 'product.image_url'
|
||||
];
|
||||
}
|
||||
|
||||
@ -52,6 +53,7 @@ class ProductMap
|
||||
12 => 'texts.custom_value',
|
||||
13 => 'texts.custom_value',
|
||||
14 => 'texts.custom_value',
|
||||
15 => 'texts.image_url',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ class ProductTransformer extends BaseTransformer
|
||||
'custom_value2' => $this->getString($data, 'product.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'product.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'product.custom_value4'),
|
||||
'product_image' => $this->getString($data, 'product.image_url'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class QuoteTransformer extends BaseTransformer
|
||||
),
|
||||
'footer' => $this->getString($quote_data, 'quote.footer'),
|
||||
'partial' => $this->getFloat($quote_data, 'quote.partial'),
|
||||
'partial_due_date' => isset($invoice_data['quote.partial_due_date']) ? $this->parseDate($quote_data['quote.partial_due_date']) : null,
|
||||
'partial_due_date' => isset($quote_data['quote.partial_due_date']) ? $this->parseDate($quote_data['quote.partial_due_date']) : null,
|
||||
'custom_surcharge1' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge1'
|
||||
|
@ -79,6 +79,7 @@ class SubscriptionCron
|
||||
->cursor()
|
||||
->each(function ($company_id){
|
||||
|
||||
/** @var \App\Models\Company $company */
|
||||
$company = Company::find($company_id);
|
||||
|
||||
$timezone_now = now()->setTimezone($company->timezone()->name ?? 'Pacific/Midway');
|
||||
|
@ -168,11 +168,6 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
||||
return;
|
||||
}
|
||||
catch(\Symfony\Component\Mailer\Transport\Dsn $e){
|
||||
nlog("Incorrectly configured mail server - setting to default mail driver.");
|
||||
$this->nmo->settings->email_sending_method = 'default';
|
||||
return $this->setMailDriver();
|
||||
}
|
||||
catch(\Google\Service\Exception $e){
|
||||
|
||||
if ($e->getCode() == '429') {
|
||||
@ -194,7 +189,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
* this merges a text string with a json object
|
||||
* need to harvest the ->Message property using the following
|
||||
*/
|
||||
if (stripos($e->getMessage(), 'code 300') || stripos($e->getMessage(), 'code 413')) {
|
||||
if (stripos($e->getMessage(), 'code 300') !== false || stripos($e->getMessage(), 'code 413') !== false) {
|
||||
$message = "Either Attachment too large, or recipient has been suppressed.";
|
||||
|
||||
$this->fail();
|
||||
@ -209,7 +204,15 @@ class NinjaMailerJob implements ShouldQueue
|
||||
return;
|
||||
}
|
||||
|
||||
if (stripos($e->getMessage(), 'code 406')) {
|
||||
if(stripos($e->getMessage(), 'Dsn') !== false){
|
||||
|
||||
nlog("Incorrectly configured mail server - setting to default mail driver.");
|
||||
$this->nmo->settings->email_sending_method = 'default';
|
||||
return $this->setMailDriver();
|
||||
|
||||
}
|
||||
|
||||
if (stripos($e->getMessage(), 'code 406') !== false) {
|
||||
|
||||
$email = $this->nmo->to_user->email ?? '';
|
||||
|
||||
@ -386,17 +389,17 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
$company = $this->company;
|
||||
|
||||
$smtp_host = $company->smtp_host;
|
||||
$smtp_host = $company->smtp_host ?? '';
|
||||
$smtp_port = $company->smtp_port;
|
||||
$smtp_username = $company->smtp_username;
|
||||
$smtp_password = $company->smtp_password;
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
|
||||
|
||||
if(strlen($smtp_host ?? '') <= 1 ||
|
||||
strlen($smtp_username ?? '') <= 1 ||
|
||||
strlen($smtp_password ?? '') <= 1
|
||||
if(strlen($smtp_host) <= 1 ||
|
||||
strlen($smtp_username) <= 1 ||
|
||||
strlen($smtp_password) <= 1
|
||||
)
|
||||
{
|
||||
$this->nmo->settings->email_sending_method = 'default';
|
||||
@ -790,6 +793,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
private function refreshOfficeToken(User $user)
|
||||
{
|
||||
$expiry = $user->oauth_user_token_expiry ?: now()->subDay();
|
||||
$token = false;
|
||||
|
||||
if ($expiry->lt(now())) {
|
||||
$guzzle = new \GuzzleHttp\Client();
|
||||
@ -798,7 +802,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
if (!$user->oauth_user_refresh_token || $user->oauth_user_refresh_token == '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$token = json_decode($guzzle->post($url, [
|
||||
'form_params' => [
|
||||
|
@ -38,7 +38,7 @@ class NinjaMailerObject
|
||||
|
||||
public $template = false;
|
||||
|
||||
/* @var bool | App\Models\Invoice | App\Models\Quote | App\Models\Credit | App\Models\RecurringInvoice | App\Models\PurchaseOrder | App\Models\Payment $entity */
|
||||
/* @var \bool | App\Models\Invoice | App\Models\Quote | App\Models\Credit | App\Models\RecurringInvoice | App\Models\PurchaseOrder | App\Models\Payment $entity */
|
||||
public $entity = false;
|
||||
|
||||
public $reminder_template = '';
|
||||
|
@ -168,46 +168,51 @@ class ReminderJob implements ShouldQueue
|
||||
$amount = $fees[0];
|
||||
$percent = $fees[1];
|
||||
|
||||
$temp_invoice_balance = $over_due_invoice->balance;
|
||||
$invoice = false;
|
||||
|
||||
if ($amount <= 0 && $percent <= 0) {
|
||||
return;
|
||||
//2024-06-07 this early return prevented any reminders from sending for users who enabled lock_invoices.
|
||||
if ($amount > 0 || $percent > 0) {
|
||||
// return;
|
||||
|
||||
$fee = $amount;
|
||||
|
||||
if ($over_due_invoice->partial > 0) {
|
||||
$fee += round($over_due_invoice->partial * $percent / 100, 2);
|
||||
} else {
|
||||
$fee += round($over_due_invoice->balance * $percent / 100, 2);
|
||||
}
|
||||
|
||||
/** @var \App\Models\Invoice $invoice */
|
||||
$invoice = InvoiceFactory::create($over_due_invoice->company_id, $over_due_invoice->user_id);
|
||||
$invoice->client_id = $over_due_invoice->client_id;
|
||||
$invoice->date = now()->format('Y-m-d');
|
||||
$invoice->due_date = now()->format('Y-m-d');
|
||||
|
||||
$invoice_item = new InvoiceItem();
|
||||
$invoice_item->type_id = '5';
|
||||
$invoice_item->product_key = trans('texts.fee');
|
||||
$invoice_item->notes = ctrans('texts.late_fee_added_locked_invoice', ['invoice' => $over_due_invoice->number, 'date' => $this->translateDate(now()->startOfDay(), $over_due_invoice->client->date_format(), $over_due_invoice->client->locale())]);
|
||||
$invoice_item->quantity = 1;
|
||||
$invoice_item->cost = $fee;
|
||||
|
||||
$invoice_items = [];
|
||||
$invoice_items[] = $invoice_item;
|
||||
|
||||
$invoice->line_items = $invoice_items;
|
||||
|
||||
/**Refresh Invoice values*/
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
$invoice->service()
|
||||
->createInvitations()
|
||||
->applyNumber()
|
||||
->markSent()
|
||||
->save();
|
||||
}
|
||||
|
||||
$fee = $amount;
|
||||
|
||||
if ($over_due_invoice->partial > 0) {
|
||||
$fee += round($over_due_invoice->partial * $percent / 100, 2);
|
||||
} else {
|
||||
$fee += round($over_due_invoice->balance * $percent / 100, 2);
|
||||
if(!$invoice){
|
||||
$invoice = $over_due_invoice;
|
||||
}
|
||||
|
||||
/** @var \App\Models\Invoice $invoice */
|
||||
$invoice = InvoiceFactory::create($over_due_invoice->company_id, $over_due_invoice->user_id);
|
||||
$invoice->client_id = $over_due_invoice->client_id;
|
||||
$invoice->date = now()->format('Y-m-d');
|
||||
$invoice->due_date = now()->format('Y-m-d');
|
||||
|
||||
$invoice_item = new InvoiceItem();
|
||||
$invoice_item->type_id = '5';
|
||||
$invoice_item->product_key = trans('texts.fee');
|
||||
$invoice_item->notes = ctrans('texts.late_fee_added_locked_invoice', ['invoice' => $over_due_invoice->number, 'date' => $this->translateDate(now()->startOfDay(), $over_due_invoice->client->date_format(), $over_due_invoice->client->locale())]);
|
||||
$invoice_item->quantity = 1;
|
||||
$invoice_item->cost = $fee;
|
||||
|
||||
$invoice_items = [];
|
||||
$invoice_items[] = $invoice_item;
|
||||
|
||||
$invoice->line_items = $invoice_items;
|
||||
|
||||
/**Refresh Invoice values*/
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
$invoice->service()
|
||||
->createInvitations()
|
||||
->applyNumber()
|
||||
->markSent()
|
||||
->save();
|
||||
|
||||
$enabled_reminder = 'enable_'.$reminder_template;
|
||||
if ($reminder_template == 'endless_reminder') {
|
||||
$enabled_reminder = 'enable_reminder_endless';
|
||||
|
@ -45,6 +45,7 @@ class RFF extends Component
|
||||
|
||||
$contact = auth()->guard('contact');
|
||||
|
||||
/** @var \App\Models\ClientContact $contact */
|
||||
$contact->user()->update([
|
||||
'first_name' => $data['contact_first_name'],
|
||||
'last_name' => $data['contact_last_name'],
|
||||
@ -65,6 +66,7 @@ class RFF extends Component
|
||||
|
||||
public function render()
|
||||
{
|
||||
/** @var \App\Models\CompanyGateway $gateway */
|
||||
$gateway = CompanyGateway::find($this->context['form']['company_gateway_id']);
|
||||
$countries = Cache::get('countries');
|
||||
|
||||
|
@ -402,7 +402,7 @@ class RequiredClientInfo extends Component
|
||||
if ($this->unfilled_fields === 0 && (!$this->company_gateway->always_show_required_fields || $this->is_subscription)) {
|
||||
$this->dispatch(
|
||||
'passed-required-fields-check',
|
||||
client_postal_code: $this->contact->client->postal_code
|
||||
client_postal_code: $_contact->client->postal_code
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -386,6 +386,7 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
// }
|
||||
|
||||
return $languages->first(function ($item) {
|
||||
/** @var \stdClass $item */
|
||||
return $item->id == $this->getSetting('language_id');
|
||||
});
|
||||
}
|
||||
@ -419,6 +420,8 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
// }
|
||||
|
||||
return $date_formats->first(function ($item) {
|
||||
|
||||
/** @var \stdClass $item */
|
||||
return $item->id == $this->getSetting('date_format_id');
|
||||
})->format;
|
||||
}
|
||||
@ -433,6 +436,8 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
// }
|
||||
|
||||
return $currencies->first(function ($item) {
|
||||
|
||||
/** @var \stdClass $item */
|
||||
return $item->id == $this->getSetting('currency_id');
|
||||
});
|
||||
}
|
||||
|
@ -636,17 +636,21 @@ class Company extends BaseModel
|
||||
|
||||
public function country()
|
||||
{
|
||||
$companies = Cache::get('countries');
|
||||
$countries = app('countries');
|
||||
|
||||
if (! $companies) {
|
||||
$this->buildCache(true);
|
||||
// $countries = Cache::get('countries');
|
||||
|
||||
$companies = Cache::get('countries');
|
||||
}
|
||||
// if (! $companies) {
|
||||
// $this->buildCache(true);
|
||||
|
||||
return $companies->filter(function ($item) {
|
||||
// $companies = Cache::get('countries');
|
||||
// }
|
||||
|
||||
return $countries->first(function ($item) {
|
||||
|
||||
/** @var \stdClass $item */
|
||||
return $item->id == $this->getSetting('country_id');
|
||||
})->first();
|
||||
});
|
||||
|
||||
// return $this->belongsTo(Country::class);
|
||||
// return Country::find($this->settings->country_id);
|
||||
@ -659,15 +663,18 @@ class Company extends BaseModel
|
||||
|
||||
public function timezone()
|
||||
{
|
||||
$timezones = Cache::get('timezones');
|
||||
// $timezones = Cache::get('timezones');
|
||||
|
||||
if (! $timezones) {
|
||||
$this->buildCache(true);
|
||||
}
|
||||
$timezones = app('timezones');
|
||||
|
||||
return $timezones->filter(function ($item) {
|
||||
// if (! $timezones) {
|
||||
// $this->buildCache(true);
|
||||
// }
|
||||
|
||||
return $timezones->first(function ($item) {
|
||||
/** @var \stdClass $item */
|
||||
return $item->id == $this->settings->timezone_id;
|
||||
})->first();
|
||||
});
|
||||
|
||||
// return Timezone::find($this->settings->timezone_id);
|
||||
}
|
||||
|
@ -563,6 +563,8 @@ class Invoice extends BaseModel
|
||||
return $this->status_id == self::STATUS_SENT;
|
||||
case 'when_paid':
|
||||
return $this->status_id == self::STATUS_PAID || $this->status_id == self::STATUS_PARTIAL;
|
||||
case 'end_of_month':
|
||||
return \Carbon\Carbon::parse($this->date)->setTimezone($this->company->timezone()->name)->endOfMonth()->lte(now());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -87,7 +87,8 @@ class BTCPayPaymentDriver extends BaseDriver
|
||||
public function processWebhookRequest()
|
||||
{
|
||||
$webhook_payload = file_get_contents('php://input');
|
||||
|
||||
$sig = false;
|
||||
/** @var \stdClass $btcpayRep */
|
||||
$btcpayRep = json_decode($webhook_payload);
|
||||
if ($btcpayRep == null) {
|
||||
throw new PaymentFailed('Empty data');
|
||||
|
@ -176,6 +176,27 @@ class PayPalBasePaymentDriver extends BaseDriver
|
||||
|
||||
}
|
||||
|
||||
public function handleDuplicateInvoiceId(string $orderID)
|
||||
{
|
||||
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
$new_invoice_number = $invoice->number."_".Str::random(5);
|
||||
|
||||
$update_data =
|
||||
[[
|
||||
"op" => "replace",
|
||||
"path" => "/purchase_units/@reference_id=='default'/invoice_id",
|
||||
"value" => $new_invoice_number,
|
||||
]];
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data);
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
public function getShippingAddress(): ?array
|
||||
{
|
||||
return $this->company_gateway->require_shipping_address ?
|
||||
@ -369,13 +390,30 @@ class PayPalBasePaymentDriver extends BaseDriver
|
||||
|
||||
}
|
||||
|
||||
public function handleProcessingFailure(array $response)
|
||||
{
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $response],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_PAYPAL,
|
||||
$this->client,
|
||||
$this->client->company ?? $this->company_gateway->company,
|
||||
);
|
||||
|
||||
switch ($response['name']) {
|
||||
case 'NOT_AUTHORIZED':
|
||||
throw new PaymentFailed("There was a permissions issue processing this payment, please contact the merchant. ", 401);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new PaymentFailed("Unknown error occurred processing payment. Please contact merchant.", 500);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -114,15 +114,19 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
|
||||
nlog("response");
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
//capture
|
||||
$orderID = $response['orderID'];
|
||||
$orderID = $response['orderID'] ?? $this->payment_hash->data->orderID;
|
||||
|
||||
if($this->company_gateway->require_shipping_address) {
|
||||
|
||||
@ -149,36 +153,26 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
if($r->status() == 422) {
|
||||
//handle conditions where the client may need to try again.
|
||||
return $this->handleRetry($r, $request);
|
||||
// return $this->handleRetry($r, $request);
|
||||
|
||||
$r = $this->handleDuplicateInvoiceId($orderID);
|
||||
|
||||
}
|
||||
|
||||
} catch(\Exception $e) {
|
||||
|
||||
//Rescue for duplicate invoice_id
|
||||
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) {
|
||||
|
||||
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
$new_invoice_number = $invoice->number."_".Str::random(5);
|
||||
|
||||
$update_data =
|
||||
[[
|
||||
"op" => "replace",
|
||||
"path" => "/purchase_units/@reference_id=='default'/invoice_id",
|
||||
"value" => $new_invoice_number,
|
||||
]];
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data);
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
|
||||
|
||||
$r = $this->handleDuplicateInvoiceId($orderID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$response = $r;
|
||||
|
||||
nlog("Process response =>");
|
||||
nlog($response->json());
|
||||
|
||||
if(isset($response['status']) && $response['status'] == 'COMPLETED' && isset($response['purchase_units'])) {
|
||||
|
||||
$data = [
|
||||
@ -222,7 +216,6 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
return response()->json(['message' => $message], 400);
|
||||
|
||||
// throw new PaymentFailed($message, 400);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,6 +296,8 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
||||
|
||||
$this->payment_hash->withData("orderID", $r->json()['id']);
|
||||
|
||||
return $r->json()['id'];
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
*/
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
|
||||
nlog("response");
|
||||
$this->init();
|
||||
|
||||
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
|
||||
@ -72,7 +72,8 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
return $this->processTokenPayment($request, $response);
|
||||
|
||||
//capture
|
||||
$orderID = $response['orderID'];
|
||||
|
||||
$orderID = $response['orderID'] ?? $this->payment_hash->data->orderID;
|
||||
|
||||
if($this->company_gateway->require_shipping_address) {
|
||||
|
||||
@ -100,7 +101,10 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
if($r->status() == 422){
|
||||
//handle conditions where the client may need to try again.
|
||||
return $this->handleRetry($r, $request);
|
||||
|
||||
$r = $this->handleDuplicateInvoiceId($orderID);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -109,21 +113,8 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
//Rescue for duplicate invoice_id
|
||||
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false){
|
||||
|
||||
|
||||
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||
$new_invoice_number = $invoice->number."_".Str::random(5);
|
||||
|
||||
$update_data =
|
||||
[[
|
||||
"op" => "replace",
|
||||
"path" => "/purchase_units/@reference_id=='default'/invoice_id",
|
||||
"value" => $new_invoice_number,
|
||||
]];
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data);
|
||||
|
||||
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
|
||||
|
||||
$r = $this->handleDuplicateInvoiceId($orderID);
|
||||
|
||||
}
|
||||
|
||||
@ -157,11 +148,12 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
return response()->json(['message' => $message], 400);
|
||||
|
||||
//throw new PaymentFailed($message, 400);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function createNinjaPayment($request, $response) {
|
||||
|
||||
$data = [
|
||||
@ -273,10 +265,19 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
||||
|
||||
nlog($r->json());
|
||||
return $r->json()['id'];
|
||||
$response = $r->json();
|
||||
|
||||
if(!isset($response['id']))
|
||||
$this->handleProcessingFailure($response);
|
||||
|
||||
$this->payment_hash->withData("orderID", $response['id']);
|
||||
|
||||
return $response['id'];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* processTokenPayment
|
||||
*
|
||||
@ -293,6 +294,7 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver
|
||||
*/
|
||||
public function processTokenPayment($request, array $response) {
|
||||
|
||||
/** @car \App\Models\ClientGatwayToken $cgt */
|
||||
$cgt = ClientGatewayToken::where('client_id', $this->client->id)
|
||||
->where('token', $request['token'])
|
||||
->firstOrFail();
|
||||
|
@ -161,9 +161,9 @@ class WePayPaymentDriver extends BaseDriver
|
||||
|
||||
}
|
||||
|
||||
public function detach(ClientGatewayToken $token)
|
||||
public function detach(ClientGatewayToken $token): bool
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientRequiredFields(): array
|
||||
|
@ -13,24 +13,24 @@ namespace App\Services\EDocument\Standards;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\IndirizzoType\Sede;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\AnagraficaType\Anagrafica;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\IdFiscaleType\IdFiscaleIVA;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\IdFiscaleType\IdTrasmittente;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiGeneraliType\DatiGenerali;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiPagamentoType\DatiPagamento;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiRiepilogoType\DatiRiepilogo;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DettaglioLineeType\DettaglioLinee;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiBeniServiziType\DatiBeniServizi;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiTrasmissioneType\DatiTrasmissione;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\CedentePrestatoreType\CedentePrestatore;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiAnagraficiCedenteType\DatiAnagrafici;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DettaglioPagamentoType\DettaglioPagamento;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\DatiGeneraliDocumentoType\DatiGeneraliDocumento;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\CessionarioCommittenteType\CessionarioCommittente;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronica;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\IndirizzoType\Sede;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\AnagraficaType\Anagrafica;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\IdFiscaleType\IdFiscaleIVA;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\IdFiscaleType\IdTrasmittente;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiGeneraliType\DatiGenerali;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiPagamentoType\DatiPagamento;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiRiepilogoType\DatiRiepilogo;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DettaglioLineeType\DettaglioLinee;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiBeniServiziType\DatiBeniServizi;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiTrasmissioneType\DatiTrasmissione;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\CedentePrestatoreType\CedentePrestatore;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiAnagraficiCedenteType\DatiAnagrafici;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DettaglioPagamentoType\DettaglioPagamento;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\DatiGeneraliDocumentoType\DatiGeneraliDocumento;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\CessionarioCommittenteType\CessionarioCommittente;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
|
||||
|
||||
class FatturaPANew extends AbstractService
|
||||
{
|
||||
@ -178,7 +178,7 @@ class FatturaPANew extends AbstractService
|
||||
$this->DatiGeneraliDocumento->Divisa = $this->invoice->client->currency()->code;
|
||||
$this->DatiGeneraliDocumento->Data = new \DateTime($this->invoice->date);
|
||||
$this->DatiGeneraliDocumento->Numero = $this->invoice->number;
|
||||
$this->DatiGeneraliDocumento->Causale[] = substr($this->invoice->public_notes ?? '',0, 200); //unsure..
|
||||
$this->DatiGeneraliDocumento->Causale[] = substr($this->invoice->public_notes ?? ' ', 0, 200); //unsure..
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -26,14 +26,17 @@ class OrderXDocument extends AbstractService
|
||||
{
|
||||
public OrderDocumentBuilder $orderxdocument;
|
||||
|
||||
public function __construct(public object $document, private readonly bool $returnObject = false, private array $tax_map = [])
|
||||
/** @var \App\Models\Invoice | \App\Models\Quote | \App\Models\PurchaseOrder | \App\Models\Credit $document */
|
||||
|
||||
public function __construct(public mixed $document, private readonly bool $returnObject = false, private array $tax_map = [])
|
||||
{
|
||||
}
|
||||
|
||||
public function run(): self
|
||||
{
|
||||
|
||||
|
||||
$company = $this->document->company;
|
||||
/** @var \App\Models\Client | \App\Models\Vendor $settings_entity */
|
||||
$settings_entity = ($this->document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client;
|
||||
$profile = $settings_entity->getSetting('e_quote_type') ? $settings_entity->getSetting('e_quote_type') : "OrderX_Extended";
|
||||
|
||||
|
518
app/Services/EDocument/Standards/Peppol.php
Normal file
518
app/Services/EDocument/Standards/Peppol.php
Normal file
@ -0,0 +1,518 @@
|
||||
<?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\Services\EDocument\Standards;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ItemType\Item;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyType\Party;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PriceType\Price;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AddressType\Address;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ContactType\Contact;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CountryType\Country;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxTotalType\TaxTotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyNameType\PartyName;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxSchemeType\TaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PayableAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\InvoiceLineType\InvoiceLine;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\TaxCategory;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxSubtotalType\TaxSubtotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxScheme as PeppolTaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxExclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxInclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\LineExtensionAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PriceAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxableAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\MonetaryTotalType\LegalMonetaryTotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\ClassifiedTaxCategory;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\SupplierPartyType\AccountingSupplierParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxTotal as PeppolTaxTotal;
|
||||
|
||||
class Peppol extends AbstractService
|
||||
{
|
||||
|
||||
private array $InvoiceTypeCodes = [
|
||||
"380" => "Commercial invoice",
|
||||
"381" => "Credit note",
|
||||
"383" => "Corrected invoice",
|
||||
"384" => "Prepayment invoice",
|
||||
"386" => "Proforma invoice",
|
||||
"875" => "Self-billed invoice",
|
||||
"976" => "Factored invoice",
|
||||
"84" => "Invoice for cross border services",
|
||||
"82" => "Simplified invoice",
|
||||
"80" => "Debit note",
|
||||
"875" => "Self-billed credit note",
|
||||
"896" => "Debit note related to self-billed invoice"
|
||||
];
|
||||
|
||||
private \InvoiceNinja\EInvoice\Models\Peppol\Invoice $p_invoice;
|
||||
|
||||
private InvoiceSum | InvoiceSumInclusive $calc;
|
||||
|
||||
/**
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
public function __construct(public Invoice $invoice)
|
||||
{
|
||||
$this->p_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice;
|
||||
$this->calc = $this->invoice->calc();
|
||||
}
|
||||
|
||||
public function getInvoice(): \InvoiceNinja\EInvoice\Models\Peppol\Invoice
|
||||
{
|
||||
return $this->p_invoice;
|
||||
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->p_invoice->ID = $this->invoice->number;
|
||||
$this->p_invoice->IssueDate = new \DateTime($this->invoice->date);
|
||||
$this->p_invoice->InvoiceTypeCode = 380; //
|
||||
$this->p_invoice->AccountingSupplierParty = $this->getAccountingSupplierParty();
|
||||
$this->p_invoice->AccountingCustomerParty = $this->getAccountingCustomerParty();
|
||||
$this->p_invoice->InvoiceLine = $this->getInvoiceLines();
|
||||
$this->p_invoice->TaxTotal = $this->getTotalTaxes();
|
||||
$this->p_invoice->LegalMonetaryTotal = $this->getLegalMonetaryTotal();
|
||||
|
||||
// $payeeFinancialAccount = (new PayeeFinancialAccount())
|
||||
// ->setBankId($company->settings->custom_value1)
|
||||
// ->setBankName($company->settings->custom_value2);
|
||||
|
||||
// $paymentMeans = (new PaymentMeans())
|
||||
// ->setPaymentMeansCode($invoice->custom_value1)
|
||||
// ->setPayeeFinancialAccount($payeeFinancialAccount);
|
||||
// $ubl_invoice->setPaymentMeans($paymentMeans);
|
||||
|
||||
}
|
||||
|
||||
private function getLegalMonetaryTotal(): LegalMonetaryTotal
|
||||
{
|
||||
$taxable = $this->getTaxable();
|
||||
|
||||
$lmt = new LegalMonetaryTotal;
|
||||
|
||||
$lea = new LineExtensionAmount;
|
||||
$lea->currencyID = $this->invoice->client->currency()->code;
|
||||
$lea->amount = $taxable;
|
||||
$lmt->LineExtensionAmount = $lea;
|
||||
|
||||
$tea = new TaxExclusiveAmount;
|
||||
$tea->currencyID = $this->invoice->client->currency()->code;
|
||||
$tea->amount = $taxable;
|
||||
$lmt->TaxExclusiveAmount = $tea;
|
||||
|
||||
$tia = new TaxInclusiveAmount;
|
||||
$tia->currencyID = $this->invoice->client->currency()->code;
|
||||
$tia->amount = $this->invoice->amount;
|
||||
$lmt->TaxInclusiveAmount = $tia;
|
||||
|
||||
$pa = new PayableAmount;
|
||||
$pa->currencyID = $this->invoice->client->currency()->code;
|
||||
$pa->amount = $this->invoice->amount;
|
||||
$lmt->PayableAmount = $pa;
|
||||
|
||||
return $lmt;
|
||||
}
|
||||
|
||||
private function getTotalTaxes(): array
|
||||
{
|
||||
$taxes = [];
|
||||
|
||||
$type_id = $this->invoice->line_items[0]->type_id;
|
||||
|
||||
if( strlen($this->invoice->tax_name1 ?? '') > 1)
|
||||
{
|
||||
|
||||
$tax_amount = new TaxAmount();
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate1),2);
|
||||
|
||||
$tax_subtotal = new TaxSubtotal();
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
|
||||
$taxable_amount = new TaxableAmount();
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $this->invoice->amount;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
|
||||
|
||||
|
||||
$tc = new TaxCategory();
|
||||
$tc->ID = $type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $this->invoice->tax_rate1;
|
||||
$ts = new PeppolTaxScheme();
|
||||
$ts->ID = $this->invoice->tax_name1;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
$tax_total = new TaxTotal;
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal = $tax_subtotal;
|
||||
|
||||
$taxes[] = $tax_total;
|
||||
}
|
||||
|
||||
|
||||
if(strlen($this->invoice->tax_name2 ?? '') > 1) {
|
||||
|
||||
$tax_amount = new TaxAmount();
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate2), 2);
|
||||
|
||||
$tax_subtotal = new TaxSubtotal();
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
$taxable_amount = new TaxableAmount();
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $this->invoice->amount;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
|
||||
|
||||
$tc = new TaxCategory();
|
||||
$tc->ID = $type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $this->invoice->tax_rate2;
|
||||
$ts = new PeppolTaxScheme();
|
||||
$ts->ID = $this->invoice->tax_name2;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal = $tax_subtotal;
|
||||
|
||||
$taxes[] = $tax_total;
|
||||
|
||||
}
|
||||
|
||||
if(strlen($this->invoice->tax_name3 ?? '') > 1) {
|
||||
|
||||
$tax_amount = new TaxAmount();
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate1), 2);
|
||||
|
||||
$tax_subtotal = new TaxSubtotal();
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
$taxable_amount = new TaxableAmount();
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $this->invoice->amount;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
|
||||
|
||||
$tc = new TaxCategory();
|
||||
$tc->ID = $type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $this->invoice->tax_rate3;
|
||||
$ts = new PeppolTaxScheme();
|
||||
$ts->ID = $this->invoice->tax_name3;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal = $tax_subtotal;
|
||||
|
||||
$taxes[] = $tax_total;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $taxes;
|
||||
}
|
||||
|
||||
private function getInvoiceLines(): array
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
foreach($this->invoice->line_items as $key => $item)
|
||||
{
|
||||
|
||||
$_item = new Item;
|
||||
$_item->Name = $item->product_key;
|
||||
$_item->Description = $item->notes;
|
||||
|
||||
$line = new InvoiceLine;
|
||||
$line->ID = $key+1;
|
||||
$line->InvoicedQuantity = $item->quantity;
|
||||
|
||||
$lea = new LineExtensionAmount;
|
||||
$lea->currencyID = $this->invoice->client->currency()->code;
|
||||
$lea->amount = $item->line_total;
|
||||
$line->LineExtensionAmount = $lea;
|
||||
$line->Item = $_item;
|
||||
|
||||
// $ta = new TaxAmount;
|
||||
// $ta->amount = $this->getItemTaxes($item);
|
||||
// $ta->currencyID = $this->invoice->client->currency()->Code;
|
||||
// $tt->TaxAmount = $ta;
|
||||
$item_taxes = $this->getItemTaxes($item);
|
||||
|
||||
if(count($item_taxes) > 0)
|
||||
$line->TaxTotal = $item_taxes;
|
||||
|
||||
$price = new Price;
|
||||
$pa = new PriceAmount;
|
||||
$pa->currencyID = $this->invoice->client->currency()->code;
|
||||
$pa->amount = $this->costWithDiscount($item);
|
||||
$price->PriceAmount = $pa;
|
||||
|
||||
$line->Price = $price;
|
||||
|
||||
$lines[] = $line;
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
private function costWithDiscount($item)
|
||||
{
|
||||
$cost = $item->cost;
|
||||
|
||||
if ($item->discount != 0) {
|
||||
if ($this->invoice->is_amount_discount) {
|
||||
$cost -= $item->discount / $item->quantity;
|
||||
} else {
|
||||
$cost -= $cost * $item->discount / 100;
|
||||
}
|
||||
}
|
||||
|
||||
return $cost;
|
||||
}
|
||||
|
||||
private function getItemTaxes(object $item): array
|
||||
{
|
||||
$item_taxes = [];
|
||||
|
||||
if(strlen($item->tax_name1 ?? '') > 1)
|
||||
{
|
||||
|
||||
$tax_amount = new TaxAmount;
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round(($item->line_total * (1/$item->tax_rate1)),2);
|
||||
$tax_subtotal = new TaxSubtotal;
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
$taxable_amount = new TaxableAmount;
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $item->line_total;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
$tc = new TaxCategory;
|
||||
$tc->ID = $item->type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $item->tax_rate1;
|
||||
$ts = new PeppolTaxScheme;
|
||||
$ts->ID = $item->tax_name1;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal[] = $tax_subtotal;
|
||||
$item_taxes[] = $tax_total;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(strlen($item->tax_name2 ?? '') > 1) {
|
||||
|
||||
$tax_amount = new TaxAmount();
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round(($item->line_total * (1 / $item->tax_rate2)),2);
|
||||
|
||||
$tax_subtotal = new TaxSubtotal();
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
$taxable_amount = new TaxableAmount();
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $item->line_total;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
|
||||
|
||||
$tc = new TaxCategory();
|
||||
$tc->ID = $item->type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $item->tax_rate2;
|
||||
$ts = new PeppolTaxScheme();
|
||||
$ts->ID = $item->tax_name2;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal[] = $tax_subtotal;
|
||||
$item_taxes[] = $tax_total;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(strlen($item->tax_name3 ?? '') > 1) {
|
||||
|
||||
$tax_amount = new TaxAmount();
|
||||
$tax_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$tax_amount->amount = round(($item->line_total * (1 / $item->tax_rate3)),2);
|
||||
|
||||
$tax_subtotal = new TaxSubtotal();
|
||||
$tax_subtotal->TaxAmount = $tax_amount;
|
||||
|
||||
$taxable_amount = new TaxableAmount();
|
||||
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
|
||||
$taxable_amount->amount = $item->line_total;
|
||||
$tax_subtotal->TaxableAmount = $taxable_amount;
|
||||
|
||||
|
||||
$tc = new TaxCategory();
|
||||
$tc->ID = $item->type_id == '2' ? 'HUR' : 'C62';
|
||||
$tc->Percent = $item->tax_rate3;
|
||||
$ts = new PeppolTaxScheme();
|
||||
$ts->ID = $item->tax_name3;
|
||||
$tc->TaxScheme = $ts;
|
||||
$tax_subtotal->TaxCategory = $tc;
|
||||
|
||||
$tax_total = new TaxTotal();
|
||||
$tax_total->TaxAmount = $tax_amount;
|
||||
$tax_total->TaxSubtotal[] = $tax_subtotal;
|
||||
$item_taxes[] = $tax_total;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $item_taxes;
|
||||
}
|
||||
|
||||
private function getAccountingSupplierParty(): AccountingSupplierParty
|
||||
{
|
||||
|
||||
$asp = new AccountingSupplierParty();
|
||||
|
||||
$party = new Party();
|
||||
$party_name = new PartyName;
|
||||
$party_name->Name = $this->invoice->company->present()->name();
|
||||
$party->PartyName[] = $party_name;
|
||||
|
||||
$address = new Address();
|
||||
$address->CityName = $this->invoice->company->settings->city;
|
||||
$address->StreetName = $this->invoice->company->settings->address1;
|
||||
// $address->BuildingName = $this->invoice->company->settings->address2;
|
||||
$address->PostalZone = $this->invoice->company->settings->postal_code;
|
||||
$address->CountrySubentity = $this->invoice->company->settings->state;
|
||||
// $address->CountrySubentityCode = $this->invoice->company->settings->state;
|
||||
|
||||
$country = new Country();
|
||||
$country->IdentificationCode = $this->invoice->company->country()->iso_3166_2;
|
||||
$address->Country = $country;
|
||||
|
||||
$party->PostalAddress = $address;
|
||||
$party->PhysicalLocation = $address;
|
||||
|
||||
$contact = new Contact();
|
||||
$contact->ElectronicMail = $this->invoice->company->owner()->email ?? 'owner@gmail.com';
|
||||
|
||||
$party->Contact = $contact;
|
||||
|
||||
$asp->Party = $party;
|
||||
|
||||
return $asp;
|
||||
}
|
||||
|
||||
private function getAccountingCustomerParty(): AccountingCustomerParty
|
||||
{
|
||||
|
||||
$acp = new AccountingCustomerParty();
|
||||
|
||||
$party = new Party();
|
||||
|
||||
$party_name = new PartyName();
|
||||
$party_name->Name = $this->invoice->client->present()->name();
|
||||
$party->PartyName[] = $party_name;
|
||||
|
||||
$address = new Address();
|
||||
$address->CityName = $this->invoice->client->city;
|
||||
$address->StreetName = $this->invoice->client->address1;
|
||||
// $address->BuildingName = $this->invoice->client->address2;
|
||||
$address->PostalZone = $this->invoice->client->postal_code;
|
||||
$address->CountrySubentity = $this->invoice->client->state;
|
||||
// $address->CountrySubentityCode = $this->invoice->client->state;
|
||||
|
||||
|
||||
$country = new Country();
|
||||
$country->IdentificationCode = $this->invoice->client->country->iso_3166_2;
|
||||
$address->Country = $country;
|
||||
|
||||
$party->PostalAddress = $address;
|
||||
$party->PhysicalLocation = $address;
|
||||
|
||||
$contact = new Contact();
|
||||
$contact->ElectronicMail = $this->invoice->client->present()->email();
|
||||
|
||||
$party->Contact = $contact;
|
||||
|
||||
$acp->Party = $party;
|
||||
|
||||
return $acp;
|
||||
}
|
||||
|
||||
private function getTaxable(): float
|
||||
{
|
||||
$total = 0;
|
||||
|
||||
foreach ($this->invoice->line_items as $item) {
|
||||
$line_total = $item->quantity * $item->cost;
|
||||
|
||||
if ($item->discount != 0) {
|
||||
if ($this->invoice->is_amount_discount) {
|
||||
$line_total -= $item->discount;
|
||||
} else {
|
||||
$line_total -= $line_total * $item->discount / 100;
|
||||
}
|
||||
}
|
||||
|
||||
$total += $line_total;
|
||||
}
|
||||
|
||||
if ($this->invoice->discount > 0) {
|
||||
if ($this->invoice->is_amount_discount) {
|
||||
$total -= $this->invoice->discount;
|
||||
} else {
|
||||
$total *= (100 - $this->invoice->discount) / 100;
|
||||
$total = round($total, 2);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->invoice->custom_surcharge1 && $this->invoice->custom_surcharge_tax1) {
|
||||
$total += $this->invoice->custom_surcharge1;
|
||||
}
|
||||
|
||||
if ($this->invoice->custom_surcharge2 && $this->invoice->custom_surcharge_tax2) {
|
||||
$total += $this->invoice->custom_surcharge2;
|
||||
}
|
||||
|
||||
if ($this->invoice->custom_surcharge3 && $this->invoice->custom_surcharge_tax3) {
|
||||
$total += $this->invoice->custom_surcharge3;
|
||||
}
|
||||
|
||||
if ($this->invoice->custom_surcharge4 && $this->invoice->custom_surcharge_tax4) {
|
||||
$total += $this->invoice->custom_surcharge4;
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
}
|
@ -32,8 +32,13 @@ class ZugferdEDokument extends AbstractService
|
||||
public function run(): self
|
||||
{
|
||||
|
||||
/** @var \App\Models\Company $company */
|
||||
$company = $this->document->company;
|
||||
|
||||
|
||||
/** @var \App\Models\Client $client */
|
||||
$client = $this->document->client;
|
||||
|
||||
$profile = $client->getSetting('e_invoice_type');
|
||||
|
||||
$profile = match ($profile) {
|
||||
|
@ -303,11 +303,6 @@ class Email implements ShouldQueue
|
||||
$this->logMailError($e->getMessage(), $this->company->clients()->first());
|
||||
return;
|
||||
}
|
||||
catch(\Symfony\Component\Mailer\Transport\Dsn $e){
|
||||
nlog("Incorrectly configured mail server - setting to default mail driver.");
|
||||
$this->email_object->settings->email_sending_method = 'default';
|
||||
return $this->setMailDriver();
|
||||
}
|
||||
catch(\Google\Service\Exception $e){
|
||||
|
||||
if ($e->getCode() == '429') {
|
||||
@ -326,7 +321,7 @@ class Email implements ShouldQueue
|
||||
$message = $e->getMessage();
|
||||
|
||||
|
||||
if (stripos($e->getMessage(), 'code 300') || stripos($e->getMessage(), 'code 413')) {
|
||||
if (stripos($e->getMessage(), 'code 300') !== false || stripos($e->getMessage(), 'code 413') !== false) {
|
||||
$message = "Either Attachment too large, or recipient has been suppressed.";
|
||||
|
||||
$this->fail();
|
||||
@ -337,8 +332,16 @@ class Email implements ShouldQueue
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(stripos($e->getMessage(), 'Dsn') !== false) {
|
||||
|
||||
if (stripos($e->getMessage(), 'code 406')) {
|
||||
nlog("Incorrectly configured mail server - setting to default mail driver.");
|
||||
$this->email_object->settings->email_sending_method = 'default';
|
||||
return $this->setMailDriver();
|
||||
|
||||
}
|
||||
|
||||
if (stripos($e->getMessage(), 'code 406') !== false) {
|
||||
|
||||
$address_object = reset($this->email_object->to);
|
||||
|
||||
@ -613,17 +616,17 @@ class Email implements ShouldQueue
|
||||
|
||||
$company = $this->company;
|
||||
|
||||
$smtp_host = $company->smtp_host;
|
||||
$smtp_host = $company->smtp_host ?? '';
|
||||
$smtp_port = $company->smtp_port;
|
||||
$smtp_username = $company->smtp_username;
|
||||
$smtp_password = $company->smtp_password;
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
|
||||
|
||||
if(strlen($smtp_host ?? '') <= 1 ||
|
||||
strlen($smtp_username ?? '') <= 1 ||
|
||||
strlen($smtp_password ?? '') <= 1
|
||||
if(strlen($smtp_host) <= 1 ||
|
||||
strlen($smtp_username) <= 1 ||
|
||||
strlen($smtp_password) <= 1
|
||||
) {
|
||||
$this->email_object->settings->email_sending_method = 'default';
|
||||
return $this->setMailDriver();
|
||||
|
@ -11,22 +11,25 @@
|
||||
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasPaid;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Libraries\MultiDB;
|
||||
use Carbon\Carbon;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Models\PaymentType;
|
||||
use Illuminate\Support\Str;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Services\AbstractService;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Events\Invoice\InvoiceWasPaid;
|
||||
use App\Repositories\CreditRepository;
|
||||
use App\Repositories\PaymentRepository;
|
||||
use App\Services\AbstractService;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
|
||||
class AutoBillInvoice extends AbstractService
|
||||
{
|
||||
@ -205,11 +208,27 @@ class AutoBillInvoice extends AbstractService
|
||||
|
||||
info("adjusting credit balance {$current_credit->balance} by this amount ".$credit['amount']);
|
||||
|
||||
|
||||
$item_date = Carbon::parse($payment->date)->format($payment->client->date_format());
|
||||
$invoice_numbers = $this->invoice->number;
|
||||
|
||||
$item = new InvoiceItem();
|
||||
$item->quantity = 0;
|
||||
$item->cost = $credit['amount'] * -1;
|
||||
$item->notes = "{$item_date} - " . ctrans('texts.credit_payment', ['invoice_number' => $invoice_numbers]) . " ". Number::formatMoney($credit['amount'], $payment->client);
|
||||
$item->type_id = "1";
|
||||
|
||||
$line_items = $current_credit->line_items;
|
||||
$line_items[] = $item;
|
||||
$current_credit->line_items = $line_items;
|
||||
|
||||
|
||||
$current_credit->service()
|
||||
->adjustBalance($credit['amount'] * -1)
|
||||
->updatePaidToDate($credit['amount'])
|
||||
->setCalculatedStatus()
|
||||
->save();
|
||||
|
||||
}
|
||||
|
||||
$payment->ledger()
|
||||
@ -240,6 +259,7 @@ class AutoBillInvoice extends AbstractService
|
||||
return $this->invoice
|
||||
->service()
|
||||
->setCalculatedStatus()
|
||||
->workFlow() //07-06-2024 - run the workflow if paid!
|
||||
->save();
|
||||
}
|
||||
|
||||
|
183
composer.lock
generated
183
composer.lock
generated
@ -1385,16 +1385,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.309.0",
|
||||
"version": "3.311.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "9213b2101afa17fe8ea99b8ea2dad85c1b1166a8"
|
||||
"reference": "90218b9372469babf294f97bdd764c9d47ec8a57"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9213b2101afa17fe8ea99b8ea2dad85c1b1166a8",
|
||||
"reference": "9213b2101afa17fe8ea99b8ea2dad85c1b1166a8",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/90218b9372469babf294f97bdd764c9d47ec8a57",
|
||||
"reference": "90218b9372469babf294f97bdd764c9d47ec8a57",
|
||||
"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.309.0"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.311.1"
|
||||
},
|
||||
"time": "2024-06-03T18:10:07+00:00"
|
||||
"time": "2024-06-06T18:05:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@ -4630,16 +4630,16 @@
|
||||
},
|
||||
{
|
||||
"name": "horstoeko/zugferd",
|
||||
"version": "v1.0.51",
|
||||
"version": "v1.0.53",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/horstoeko/zugferd.git",
|
||||
"reference": "9e036d4a9660638b4f51d2babb397fcff29ef046"
|
||||
"reference": "939e93ab2e84ec476735e5957f4db7e7d58880c3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/9e036d4a9660638b4f51d2babb397fcff29ef046",
|
||||
"reference": "9e036d4a9660638b4f51d2babb397fcff29ef046",
|
||||
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/939e93ab2e84ec476735e5957f4db7e7d58880c3",
|
||||
"reference": "939e93ab2e84ec476735e5957f4db7e7d58880c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4699,9 +4699,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/horstoeko/zugferd/issues",
|
||||
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.51"
|
||||
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.53"
|
||||
},
|
||||
"time": "2024-05-31T17:20:07+00:00"
|
||||
"time": "2024-06-05T16:49:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "http-interop/http-factory-guzzle",
|
||||
@ -5076,16 +5076,17 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/invoiceninja/einvoice.git",
|
||||
"reference": "228560c6eea03d9ae10a174a0d9f1456efc5eabd"
|
||||
"reference": "1b9a488d65715272941f1ae6ddfe2d94ad25c2c1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/228560c6eea03d9ae10a174a0d9f1456efc5eabd",
|
||||
"reference": "228560c6eea03d9ae10a174a0d9f1456efc5eabd",
|
||||
"url": "https://api.github.com/repos/invoiceninja/einvoice/zipball/1b9a488d65715272941f1ae6ddfe2d94ad25c2c1",
|
||||
"reference": "1b9a488d65715272941f1ae6ddfe2d94ad25c2c1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/collections": "^10.48",
|
||||
"illuminate/collections": "^10|^11",
|
||||
"php": "^8.2",
|
||||
"phpdocumentor/reflection-docblock": "^5.4",
|
||||
"sabre/xml": "^4.0",
|
||||
"symfony/property-access": "^7",
|
||||
@ -5094,6 +5095,7 @@
|
||||
"symfony/validator": "^7"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.58",
|
||||
"milo/schematron": "^1.0",
|
||||
"nette/php-generator": "^4.1",
|
||||
"phpstan/phpstan": "^1.11",
|
||||
@ -5104,7 +5106,7 @@
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Invoiceninja\\Einvoice\\": "src/"
|
||||
"InvoiceNinja\\EInvoice\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
@ -5121,7 +5123,7 @@
|
||||
"source": "https://github.com/invoiceninja/einvoice/tree/main",
|
||||
"issues": "https://github.com/invoiceninja/einvoice/issues"
|
||||
},
|
||||
"time": "2024-06-03T07:03:23+00:00"
|
||||
"time": "2024-06-07T04:32:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "invoiceninja/inspector",
|
||||
@ -12517,16 +12519,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc"
|
||||
"reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc",
|
||||
"reference": "843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/1c7cee86c6f812896af54434f8ce29c8d94f9ff4",
|
||||
"reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -12562,7 +12564,7 @@
|
||||
"description": "Converts CSS selectors to XPath expressions",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/css-selector/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/css-selector/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -12578,7 +12580,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@ -12724,16 +12726,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "522d2772d6c7bab843b0c52466dc7844622bacc2"
|
||||
"reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/522d2772d6c7bab843b0c52466dc7844622bacc2",
|
||||
"reference": "522d2772d6c7bab843b0c52466dc7844622bacc2",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7",
|
||||
"reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -12784,7 +12786,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -12800,7 +12802,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@ -13372,16 +13374,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/intl",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/intl.git",
|
||||
"reference": "1b8974c7ff07c61d4acf0e873e34dfb75190b2bb"
|
||||
"reference": "66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/1b8974c7ff07c61d4acf0e873e34dfb75190b2bb",
|
||||
"reference": "1b8974c7ff07c61d4acf0e873e34dfb75190b2bb",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c",
|
||||
"reference": "66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -13438,7 +13440,7 @@
|
||||
"localization"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/intl/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/intl/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -13454,7 +13456,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
@ -13692,16 +13694,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "9564f64c16f99e29f252eafc642965e8fcb755ce"
|
||||
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/9564f64c16f99e29f252eafc642965e8fcb755ce",
|
||||
"reference": "9564f64c16f99e29f252eafc642965e8fcb755ce",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -13739,7 +13741,7 @@
|
||||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -13755,7 +13757,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@ -14685,16 +14687,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-access",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-access.git",
|
||||
"reference": "1e8c1e6ac1b19cf945d8094a0ee50296872c4cb2"
|
||||
"reference": "74e39e6a6276b8e384f34c6ddbc10a6c9a60193a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/1e8c1e6ac1b19cf945d8094a0ee50296872c4cb2",
|
||||
"reference": "1e8c1e6ac1b19cf945d8094a0ee50296872c4cb2",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/74e39e6a6276b8e384f34c6ddbc10a6c9a60193a",
|
||||
"reference": "74e39e6a6276b8e384f34c6ddbc10a6c9a60193a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -14741,7 +14743,7 @@
|
||||
"reflection"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-access/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/property-access/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -14757,20 +14759,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-info",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-info.git",
|
||||
"reference": "b10cb8cf0179aec96769df2affb881ecfc293f79"
|
||||
"reference": "0f80f818c6728f15de30a4f89866d68e4912ae84"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/b10cb8cf0179aec96769df2affb881ecfc293f79",
|
||||
"reference": "b10cb8cf0179aec96769df2affb881ecfc293f79",
|
||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/0f80f818c6728f15de30a4f89866d68e4912ae84",
|
||||
"reference": "0f80f818c6728f15de30a4f89866d68e4912ae84",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -14825,7 +14827,7 @@
|
||||
"validator"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-info/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/property-info/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -14841,7 +14843,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-30T12:09:55+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/psr-http-message-bridge",
|
||||
@ -15017,16 +15019,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/serializer.git",
|
||||
"reference": "972eb05320d06d07399b71b05e6da9032c865f1d"
|
||||
"reference": "74817ee48e37cce1a1b33c66ffdb750e7e048c3c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/serializer/zipball/972eb05320d06d07399b71b05e6da9032c865f1d",
|
||||
"reference": "972eb05320d06d07399b71b05e6da9032c865f1d",
|
||||
"url": "https://api.github.com/repos/symfony/serializer/zipball/74817ee48e37cce1a1b33c66ffdb750e7e048c3c",
|
||||
"reference": "74817ee48e37cce1a1b33c66ffdb750e7e048c3c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15094,7 +15096,7 @@
|
||||
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/serializer/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/serializer/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -15110,7 +15112,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-21T15:59:31+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@ -15197,16 +15199,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "6f41b185e742737917e6f2e3eca37767fba5f17a"
|
||||
"reference": "60bc311c74e0af215101235aa6f471bcbc032df2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/6f41b185e742737917e6f2e3eca37767fba5f17a",
|
||||
"reference": "6f41b185e742737917e6f2e3eca37767fba5f17a",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/60bc311c74e0af215101235aa6f471bcbc032df2",
|
||||
"reference": "60bc311c74e0af215101235aa6f471bcbc032df2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15264,7 +15266,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/string/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -15280,7 +15282,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-17T10:55:18+00:00"
|
||||
"time": "2024-06-04T06:40:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
@ -15457,16 +15459,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/type-info",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/type-info.git",
|
||||
"reference": "b429d0710588fc396ba5def5329cf637d9861f9f"
|
||||
"reference": "60b28eb733f1453287f1263ed305b96091e0d1dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/type-info/zipball/b429d0710588fc396ba5def5329cf637d9861f9f",
|
||||
"reference": "b429d0710588fc396ba5def5329cf637d9861f9f",
|
||||
"url": "https://api.github.com/repos/symfony/type-info/zipball/60b28eb733f1453287f1263ed305b96091e0d1dc",
|
||||
"reference": "60b28eb733f1453287f1263ed305b96091e0d1dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15519,7 +15521,7 @@
|
||||
"type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/type-info/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/type-info/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -15535,7 +15537,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-02T10:19:13+00:00"
|
||||
"time": "2024-05-31T14:59:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/uid",
|
||||
@ -15613,16 +15615,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/validator",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/validator.git",
|
||||
"reference": "ffcc8c56502f6adaeaf6307aef5b98b53a8d0326"
|
||||
"reference": "fcab7598968b21c361becc930fcae8846638c4c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/validator/zipball/ffcc8c56502f6adaeaf6307aef5b98b53a8d0326",
|
||||
"reference": "ffcc8c56502f6adaeaf6307aef5b98b53a8d0326",
|
||||
"url": "https://api.github.com/repos/symfony/validator/zipball/fcab7598968b21c361becc930fcae8846638c4c0",
|
||||
"reference": "fcab7598968b21c361becc930fcae8846638c4c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15669,7 +15671,8 @@
|
||||
"Symfony\\Component\\Validator\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
"/Tests/",
|
||||
"/Resources/bin/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@ -15689,7 +15692,7 @@
|
||||
"description": "Provides tools to validate values",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/validator/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/validator/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -15705,7 +15708,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-21T15:59:31+00:00"
|
||||
"time": "2024-06-04T05:58:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
@ -18242,16 +18245,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.11.3",
|
||||
"version": "1.11.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "e64220a05c1209fc856d58e789c3b7a32c0bb9a5"
|
||||
"reference": "9100a76ce8015b9aa7125b9171ae3a76887b6c82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e64220a05c1209fc856d58e789c3b7a32c0bb9a5",
|
||||
"reference": "e64220a05c1209fc856d58e789c3b7a32c0bb9a5",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9100a76ce8015b9aa7125b9171ae3a76887b6c82",
|
||||
"reference": "9100a76ce8015b9aa7125b9171ae3a76887b6c82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -18296,7 +18299,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-31T13:53:37+00:00"
|
||||
"time": "2024-06-06T12:19:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
@ -20613,16 +20616,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
"version": "v7.1.0",
|
||||
"version": "v7.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/stopwatch.git",
|
||||
"reference": "13c750a45ac43c45f45d944d22499768aa1b72d8"
|
||||
"reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/13c750a45ac43c45f45d944d22499768aa1b72d8",
|
||||
"reference": "13c750a45ac43c45f45d944d22499768aa1b72d8",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d",
|
||||
"reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -20655,7 +20658,7 @@
|
||||
"description": "Provides a way to profile code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.1.0"
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -20671,7 +20674,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
|
@ -201,7 +201,7 @@ return [
|
||||
App\Providers\MultiDBProvider::class,
|
||||
App\Providers\ClientPortalServiceProvider::class,
|
||||
App\Providers\NinjaTranslationServiceProvider::class,
|
||||
App\Providers\StaticServiceProvider::class,
|
||||
App\Providers\StaticServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
@ -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.9.2'),
|
||||
'app_tag' => env('APP_TAG', '5.9.2'),
|
||||
'app_version' => env('APP_VERSION', '5.9.3'),
|
||||
'app_tag' => env('APP_TAG', '5.9.3'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -5334,6 +5334,7 @@ $lang = array(
|
||||
'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',
|
||||
'end_of_month' => 'End Of Month'
|
||||
);
|
||||
|
||||
return $lang;
|
@ -1,4 +1,3 @@
|
||||
{
|
||||
"Admin": true,
|
||||
"Ronin": true
|
||||
"Admin": true
|
||||
}
|
||||
|
18503
openapi/api-docs.yaml
18503
openapi/api-docs.yaml
File diff suppressed because it is too large
Load Diff
@ -123,16 +123,16 @@
|
||||
examples:
|
||||
user:
|
||||
value: user
|
||||
summary: include=user will include the user object in the response
|
||||
summary: include=user will include the Cser object in the response
|
||||
company:
|
||||
value: company
|
||||
summary: include=company will include the company object in the response
|
||||
summary: include=company will include the Company object in the response
|
||||
token:
|
||||
value: token
|
||||
summary: include=token will include the token object in the response
|
||||
summary: include=token will include the Company Token object in the response
|
||||
account:
|
||||
value: account
|
||||
summary: include=account will include the account object in the response
|
||||
summary: include=account will include the Account object in the response
|
||||
per_page_meta:
|
||||
name: per_page
|
||||
in: query
|
||||
@ -160,7 +160,15 @@
|
||||
include_static:
|
||||
name: include_static
|
||||
in: query
|
||||
description: 'Returns static variables'
|
||||
description: |
|
||||
Static variables include:
|
||||
- Currencies
|
||||
- Countries
|
||||
- Languages
|
||||
- Payment Types
|
||||
- Email Templatees
|
||||
- Industries
|
||||
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
@ -168,7 +176,11 @@
|
||||
clear_cache:
|
||||
name: clear_cache
|
||||
in: query
|
||||
description: 'Clears the static cache'
|
||||
description: |
|
||||
Clears cache
|
||||
|
||||
Sometimes after a system update where the static variables have been updated, it may be necessary to clear the cache so that the static variables repopulate
|
||||
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,53 @@
|
||||
company:
|
||||
$ref: '#/components/schemas/Company'
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
$ref: '#/components/schemas/UserRef'
|
||||
token:
|
||||
$ref: '#/components/schemas/CompanyToken'
|
||||
type: object
|
||||
CompanyUserRef:
|
||||
properties:
|
||||
permissions:
|
||||
description: 'The user permissionsfor this company in a comma separated list'
|
||||
type: string
|
||||
example: 'create_invoice,create_client,view_client'
|
||||
settings:
|
||||
description: 'Settings that are used for the flutter applications to store user preferences / metadata'
|
||||
type: object
|
||||
readOnly: true
|
||||
react_settings:
|
||||
description: 'Dedicated settings object for the react web application'
|
||||
type: object
|
||||
readOnly: true
|
||||
is_owner:
|
||||
description: 'Determines whether the user owns this company'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
is_admin:
|
||||
description: 'Determines whether the user is the admin of this company'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
is_locked:
|
||||
description: 'Determines whether the users access to this company has been locked'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
updated_at:
|
||||
description: 'The last time the record was modified, format Unix Timestamp'
|
||||
type: integer
|
||||
example: '1231232312321'
|
||||
deleted_at:
|
||||
description: 'Timestamp when the user was archived, format Unix Timestamp'
|
||||
type: integer
|
||||
example: '12312312321'
|
||||
account:
|
||||
$ref: '#/components/schemas/Account'
|
||||
company:
|
||||
$ref: '#/components/schemas/Company'
|
||||
user:
|
||||
$ref: '#/components/schemas/UserRef'
|
||||
token:
|
||||
$ref: '#/components/schemas/CompanyToken'
|
||||
type: object
|
@ -100,5 +100,107 @@
|
||||
example: '123456'
|
||||
readOnly: true
|
||||
company_user:
|
||||
$ref: '#/components/schemas/CompanyUser'
|
||||
$ref: '#/components/schemas/CompanyUserRef'
|
||||
type: object
|
||||
UserRef:
|
||||
properties:
|
||||
id:
|
||||
description: 'The hashed id of the user'
|
||||
type: string
|
||||
example: Opnel5aKBz
|
||||
readOnly: true
|
||||
first_name:
|
||||
description: 'The first name of the user'
|
||||
type: string
|
||||
example: Brad
|
||||
last_name:
|
||||
description: 'The last name of the user'
|
||||
type: string
|
||||
example: Pitt
|
||||
email:
|
||||
description: 'The users email address'
|
||||
type: string
|
||||
example: brad@pitt.com
|
||||
phone:
|
||||
description: 'The users phone number'
|
||||
type: string
|
||||
example: 555-1233-23232
|
||||
signature:
|
||||
description: 'The users sign off signature'
|
||||
type: string
|
||||
example: 'Have a nice day!'
|
||||
avatar:
|
||||
description: 'The users avatar'
|
||||
type: string
|
||||
example: 'https://url.to.your/avatar.png'
|
||||
accepted_terms_version:
|
||||
description: 'The version of the invoice ninja terms that has been accepted by the user'
|
||||
type: string
|
||||
example: 1.0.1
|
||||
readOnly: true
|
||||
oauth_user_id:
|
||||
description: 'The provider id of the oauth entity'
|
||||
type: string
|
||||
example: jkhasdf789as6f675sdf768sdfs
|
||||
readOnly: true
|
||||
oauth_provider_id:
|
||||
description: 'The oauth entity id'
|
||||
type: string
|
||||
example: google
|
||||
readOnly: true
|
||||
language_id:
|
||||
description: 'The language id of the user'
|
||||
type: string
|
||||
example: 1
|
||||
verified_phone_number:
|
||||
description: 'Boolean flag if the user has their phone verified. Required to settings up 2FA'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
sms_verification_code:
|
||||
description: 'The sms verification code for the user. Required to settings up 2FA'
|
||||
type: string
|
||||
example: '123456'
|
||||
readOnly: true
|
||||
oauth_user_token_expiry:
|
||||
description: 'The expiry date of the oauth token'
|
||||
type: string
|
||||
example: '2022-10-10'
|
||||
readOnly: true
|
||||
has_password:
|
||||
description: 'Boolean flag determining if the user has a password'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
last_confirmed_email_address:
|
||||
description: 'The last confirmed email address of the user'
|
||||
type: string
|
||||
example: 'bob@gmail.com'
|
||||
readOnly: true
|
||||
custom_value1:
|
||||
description: 'A custom value'
|
||||
type: string
|
||||
example: 'Custom value 1'
|
||||
custom_value2:
|
||||
description: 'A custom value'
|
||||
type: string
|
||||
example: '$1000'
|
||||
custom_value3:
|
||||
description: 'A custom value'
|
||||
type: string
|
||||
example: 'Custom value 3'
|
||||
custom_value4:
|
||||
description: 'A custom value'
|
||||
type: string
|
||||
example: 'Custom value 4'
|
||||
is_deleted:
|
||||
description: 'Boolean flag determining if the user has been deleted'
|
||||
type: boolean
|
||||
example: true
|
||||
readOnly: true
|
||||
google_2fa_secret:
|
||||
description: 'The google 2fa secret for the user'
|
||||
type: string
|
||||
example: '123456'
|
||||
readOnly: true
|
||||
type: object
|
@ -3,22 +3,88 @@ info:
|
||||
title: 'Invoice Ninja API Reference.'
|
||||
description: |
|
||||
---
|
||||
<br>
|
||||
<div style="color: white; background-color:SlateBlue; padding: 12px; border-radius:2px">
|
||||
The Invoice Ninja API is organized around REST and returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
|
||||
</div>
|
||||
<br>
|
||||
## Introduction
|
||||
Welcome to the Invoice Ninja API documentation, your comprehensive guide to integrating Invoice Ninja's powerful features into your applications. Whether you're building a custom client, automating workflows, or integrating with other systems, our API provides the tools you need to streamline your invoicing and billing processes.
|
||||
|
||||
## What is Invoice Ninja?
|
||||
Invoice Ninja is a robust source-available platform designed to simplify invoicing, billing, and payment management for freelancers, small businesses, and enterprises alike. With a user-friendly interface, customizable templates, and a suite of powerful features, Invoice Ninja empowers businesses to create professional invoices, track expenses, manage clients, and get paid faster.
|
||||
|
||||
## Why use the Invoice Ninja API?
|
||||
The Invoice Ninja API allows developers to extend the functionality of Invoice Ninja by programmatically accessing and manipulating data within their Invoice Ninja accounts. With the API, you can automate repetitive tasks, integrate with third-party services, and build custom solutions tailored to your specific business needs.
|
||||
|
||||
## Getting Started
|
||||
To get started with the Invoice Ninja API, you'll need an active Invoice Ninja account (or your own self hosted installation) and API credentials. If you haven't already done so, sign up for an account at Invoice Ninja and generate your API keys from the settings section.
|
||||
|
||||
Once you have your API credentials, you can start exploring the API endpoints, authentication methods, request and response formats, and more using the documentation provided here.
|
||||
|
||||
## Explore the Documentation
|
||||
This documentation is organized into sections to help you navigate and understand the various aspects of the Invoice Ninja API:
|
||||
|
||||
Authentication: Learn how to authenticate your requests to the API using API tokens.
|
||||
Endpoints: Explore the available API endpoints for managing invoices, clients, payments, expenses, and more.
|
||||
Request and Response Formats: Understand the structure of API requests and responses, including parameters, headers, and payloads.
|
||||
Error Handling: Learn about error codes, status messages, and best practices for handling errors gracefully.
|
||||
Code Examples: Find code examples and tutorials to help you get started with integrating the Invoice Ninja API into your applications.
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you have any questions, encounter any issues, or need assistance with using the Invoice Ninja API, don't hesitate to reach out to our support team or join our community forums. We're here to help you succeed with Invoice Ninja and make the most of our API.
|
||||
|
||||
Let's start building together!
|
||||
|
||||
## Endpoints
|
||||
|
||||
<div style="background-color: #2D394E; color: #fff padding: 20px; border-radius: 5px; border: 4px solid #212A3B; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">
|
||||
<p style="padding:10px; color: #DBDBDB;"">Production: https://invoicing.co</p>
|
||||
<p style="padding:10px; color: #DBDBDB;">Demo: https://demo.invoiceninja.com</p>
|
||||
</div>
|
||||
|
||||
## Client Libraries
|
||||
|
||||
PHP SDK can be found [here](https://github.com/invoiceninja/sdk-php)
|
||||
|
||||
## Authentication:
|
||||
|
||||
Invoice Ninja uses API tokens to authenticate requests. You can view and manage your API keys in Settings > Account Management > Integrations > API tokens
|
||||
|
||||
API requests must be made over HTTPS. Calls made to HTTP will fail.
|
||||
|
||||
## Errors:
|
||||
|
||||
Invoice Ninja uses standard HTTP response codes to indicate the success or failure of a request. below is a table of standard status codes and responses
|
||||
|
||||
| Status Code | Explanation |
|
||||
|-------------|-----------------------------------------------------------------------------|
|
||||
| 200 | OK: The request has succeeded. The information returned with the response is dependent on the method used in the request. |
|
||||
| 301 | Moved Permanently: This and all future requests should be directed to the given URI. |
|
||||
| 303 | See Other: The response to the request can be found under another URI using the GET method. |
|
||||
| 400 | Bad Request: The server cannot or will not process the request due to an apparent client error. |
|
||||
| 401 | Unauthorized: Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided. |
|
||||
| 403 | Forbidden: The request was valid, but the server is refusing action. |
|
||||
| 404 | Not Found: The requested resource could not be found but may be available in the future. |
|
||||
| 405 | Method Not Allowed: A request method is not supported for the requested resource. |
|
||||
| 409 | Conflict: Indicates that the request could not be processed because of conflict in the request. |
|
||||
| 422 | Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors. |
|
||||
| 429 | Too Many Requests: The user has sent too many requests in a given amount of time ("rate limiting"). |
|
||||
| 500 | Internal Server Error: A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. |
|
||||
|
||||
## Pagination
|
||||
|
||||
When using index routes to retrieve lists of data, by default we limit the number of records returned to 20. You can using standard pagination to paginate results, ie:
|
||||
termsOfService: 'https://invoiceninja.github.io/docs/legal/terms_of_service/#page-content'
|
||||
contact:
|
||||
email: contact@invoiceninja.com
|
||||
name: Invoice Ninja Support
|
||||
url: 'https://www.invoiceninja.com'
|
||||
license:
|
||||
name: 'Elastic License'
|
||||
url: 'https://www.elastic.co/licensing/elastic-license'
|
||||
version: 5.8.34
|
||||
version: 5.9.2
|
||||
servers:
|
||||
-
|
||||
url: 'https://demo.invoiceninja.com'
|
||||
description: |
|
||||
## Demo API Server InvoiceNinja.
|
||||
You can use the demo API key `TOKEN` to test the endpoints from within this API spec
|
||||
- url: 'https://demo.invoiceninja.com'
|
||||
description: |
|
||||
## Demo API endpoint
|
||||
You can use the demo API key `TOKEN` to test the endpoints from within this API spec
|
||||
- url: 'https://invoicing.co'
|
||||
description: |
|
||||
## Production API endpoint
|
@ -116,12 +116,10 @@ paths:
|
||||
description: "The users email address."
|
||||
type: string
|
||||
example: "demo@invoiceninja.com"
|
||||
required: true
|
||||
password:
|
||||
description: "The user password. Must meet minimum criteria ~ > 6 characters"
|
||||
type: string
|
||||
example: "Password0"
|
||||
required: true
|
||||
one_time_password:
|
||||
description: "The one time password if 2FA is enabled"
|
||||
type: string
|
||||
|
@ -3,6 +3,17 @@
|
||||
tags:
|
||||
- clients
|
||||
summary: 'List clients'
|
||||
x-code-samples:
|
||||
- lang: go
|
||||
label: php
|
||||
source: |
|
||||
$ninja = new InvoiceNinja("your_token");
|
||||
$invoices = $ninja->clients->all();
|
||||
x-custom-element:
|
||||
type: markdown
|
||||
value: |
|
||||
### Custom Response Description
|
||||
This is a custom description for the response returned by the `/example` endpoint.
|
||||
description: |
|
||||
When retrieving a list of clients you can also chain query parameters in order to filter the dataset that is returned. For example, you can send a request to the following URL to retrieve clients that have a balance greater than 1000:\
|
||||
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@invoiceninja/invoiceninja",
|
||||
"name": "invoiceninja",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
File diff suppressed because one or more lines are too long
@ -240,7 +240,7 @@
|
||||
"src": "resources/js/setup/setup.js"
|
||||
},
|
||||
"resources/sass/app.scss": {
|
||||
"file": "assets/app-c7c5fad4.css",
|
||||
"file": "assets/app-f3b33400.css",
|
||||
"isEntry": true,
|
||||
"src": "resources/sass/app.scss"
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div wire:ignore.self class="@unless($form_only) container mx-auto grid grid-cols-12 @endunless mb-4" data-ref="required-fields-container">
|
||||
<div wire:ignore.self class="@unless($form_only) container mx-auto grid grid-cols-12 @endunless mb-4 transition ease-out duration-1000 h-500" data-ref="required-fields-container">
|
||||
<div class="col-span-12 lg:col-span-6 lg:col-start-4 overflow-hidden @unless($form_only) bg-white shadow rounded-lg @endunless">
|
||||
@unless($form_only)
|
||||
<div class="px-4 py-5 border-b border-gray-200 sm:px-6">
|
||||
|
@ -16,7 +16,12 @@
|
||||
|
||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||
|
||||
<div id="paypal-button-container" class="paypal-button-container"></div>
|
||||
<div id="paypal-button-container" class="paypal-button-container">
|
||||
</div>
|
||||
|
||||
<div id="is_working" class="flex mt-4 place-items-center hidden">
|
||||
<span class="loader m-auto"></span>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@ -24,7 +29,40 @@
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
|
||||
<style type="text/css">
|
||||
.loader {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
animation: rotate 1s linear infinite
|
||||
}
|
||||
.loader::before , .loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
inset: 0px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid #454545;
|
||||
animation: prixClipFix 2s linear infinite ;
|
||||
}
|
||||
.loader::after{
|
||||
border-color: #FF3D00;
|
||||
animation: prixClipFix 2s linear infinite , rotate 0.5s linear infinite reverse;
|
||||
inset: 6px;
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% {transform: rotate(0deg)}
|
||||
100% {transform: rotate(360deg)}
|
||||
}
|
||||
@keyframes prixClipFix {
|
||||
0% {clip-path:polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)}
|
||||
25% {clip-path:polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)}
|
||||
50% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)}
|
||||
75% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 100%)}
|
||||
100% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 0)}
|
||||
}
|
||||
</style>
|
||||
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}¤cy={!! $currency !!}&components=buttons,funding-eligibility&intent=capture&enable-funding={!! $funding_source !!}" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
|
||||
|
||||
<script>
|
||||
@ -106,6 +144,8 @@
|
||||
if(fundingSource != 'card')
|
||||
document.getElementById('paypal-button-container').hidden = true;
|
||||
|
||||
document.getElementById('is_working').classList.remove('hidden');
|
||||
|
||||
document.querySelector('div[data-ref="required-fields-container').classList.add('hidden');
|
||||
|
||||
},
|
||||
|
@ -75,7 +75,6 @@
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
<link rel="stylesheet" type="text/css" href=https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css />
|
||||
|
||||
@if(isset($merchantId))
|
||||
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&merchantId={!! $merchantId !!}&components=card-fields" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
|
||||
@ -87,24 +86,7 @@
|
||||
const clientId = "{{ $client_id }}";
|
||||
const orderId = "{!! $order_id !!}";
|
||||
|
||||
const cardStyle = {
|
||||
'input': {
|
||||
'font-size': '16px',
|
||||
'font-family': 'courier, monospace',
|
||||
'font-weight': 'lighter',
|
||||
'color': '#ccc',
|
||||
},
|
||||
'.invalid': {
|
||||
'color': 'purple',
|
||||
},
|
||||
'.expcvv': {
|
||||
'display': 'grid',
|
||||
'grid-template-columns': 'auto'
|
||||
}
|
||||
};
|
||||
|
||||
const cardField = paypal.CardFields({
|
||||
// style: cardStyle,
|
||||
client: clientId,
|
||||
createOrder: function(data, actions) {
|
||||
return orderId;
|
||||
@ -125,7 +107,6 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
let storeCard = document.querySelector('input[name=token-billing-checkbox]:checked');
|
||||
|
||||
if (storeCard) {
|
||||
@ -197,7 +178,6 @@
|
||||
const numberField = cardField.NumberField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
// console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -207,7 +187,6 @@
|
||||
const cvvField = cardField.CVVField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
// console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -216,7 +195,6 @@
|
||||
const expiryField = cardField.ExpiryField({
|
||||
inputEvents: {
|
||||
onChange: (event)=> {
|
||||
// console.log("returns a stateObject", event);
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -312,6 +290,18 @@
|
||||
document.getElementById("token").value = token.value;
|
||||
}
|
||||
|
||||
document.getElementById('errors').textContent = '';
|
||||
document.getElementById('errors').hidden = true;
|
||||
|
||||
document.getElementById('pay-now-token').disabled = true;
|
||||
document.querySelector('#pay-now-token > svg').classList.remove('hidden');
|
||||
document.querySelector('#pay-now-token > svg').classList.add('justify-center');
|
||||
|
||||
document.querySelector('#pay-now-token > svg').classList.add('mx-auto');
|
||||
document.querySelector('#pay-now-token > svg').classList.add('item-center');
|
||||
|
||||
document.querySelector('#pay-now-token > span').classList.add('hidden');
|
||||
|
||||
document.getElementById("gateway_response").value = JSON.stringify( {token: token.value, orderID: "{!! $order_id !!}"} );
|
||||
document.getElementById("server_response").submit();
|
||||
|
||||
|
@ -50,8 +50,10 @@
|
||||
document.addEventListener('livewire:init', () => {
|
||||
|
||||
Livewire.on('passed-required-fields-check', () => {
|
||||
document.querySelector('div[data-ref="required-fields-container"]').classList.add('opacity-25');
|
||||
document.querySelector('div[data-ref="required-fields-container"]').classList.add('pointer-events-none');
|
||||
|
||||
document.querySelector('div[data-ref="required-fields-container"]').classList.toggle('h-0');
|
||||
// document.querySelector('div[data-ref="required-fields-container"]').classList.add('opacity-25');
|
||||
// document.querySelector('div[data-ref="required-fields-container"]').classList.add('pointer-events-none');
|
||||
|
||||
document.querySelector('div[data-ref="gateway-container"]').classList.remove('opacity-25');
|
||||
document.querySelector('div[data-ref="gateway-container"]').classList.remove('pointer-events-none');
|
||||
|
@ -184,7 +184,10 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
|
||||
|
||||
Route::post('client_statement', [ClientStatementController::class, 'statement'])->name('client.statement');
|
||||
|
||||
Route::post('companies/purge/{company}', [MigrationController::class, 'purgeCompany'])->middleware('password_protected');
|
||||
|
||||
Route::post('companies/purge/{company}', [MigrationController::class, 'purgeCompany'])->middleware('password_protected');
|
||||
|
||||
Route::post('companies/current', [CompanyController::class, 'current'])->name('companies.current');
|
||||
Route::post('companies/purge_save_settings/{company}', [MigrationController::class, 'purgeCompanySaveSettings'])->middleware('password_protected');
|
||||
Route::resource('companies', CompanyController::class); // name = (companies. index / create / show / update / destroy / edit
|
||||
|
||||
|
@ -15,6 +15,9 @@ module.exports = {
|
||||
fontFamily: {
|
||||
sans: ['Open Sans', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
transitionProperty: {
|
||||
'height': 'height'
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
@ -72,6 +72,21 @@ class CompanyTest extends TestCase
|
||||
$this->assertEquals(1, TaxRate::count());
|
||||
}
|
||||
|
||||
public function testCompanyCurrent()
|
||||
{
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson("/api/v1/companies/current");
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals($arr['data']['id'], $this->company->hashed_id);
|
||||
|
||||
}
|
||||
|
||||
public function testCompanyLogoInline()
|
||||
{
|
||||
$response = $this->withHeaders([
|
||||
|
@ -19,13 +19,14 @@ use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Models\Invoice;
|
||||
use Invoiceninja\Einvoice\Symfony\Encode;
|
||||
use InvoiceNinja\EInvoice\Symfony\Encode;
|
||||
use App\Services\EDocument\Standards\FatturaPANew;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronica;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
|
||||
use Invoiceninja\Einvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
|
||||
use InvoiceNinja\EInvoice\EInvoice;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronica;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -125,15 +126,22 @@ class FatturaPATest extends TestCase
|
||||
$this->assertInstanceOf(FatturaElettronicaBody::class, $fe->FatturaElettronicaBody[0]);
|
||||
$this->assertInstanceOf(FatturaElettronicaHeader::class, $fe->FatturaElettronicaHeader);
|
||||
|
||||
$e = new EInvoice;
|
||||
$errors = $e->validate($fe);
|
||||
|
||||
$encoder = new Encode($fe);
|
||||
$xml = $encoder->toXml();
|
||||
if(count($errors) > 0)
|
||||
nlog($errors);
|
||||
|
||||
|
||||
nlog($xml);
|
||||
$this->assertCount(0, $errors);
|
||||
|
||||
$xml = $e->encode($fe, 'xml');
|
||||
$this->assertNotNull($xml);
|
||||
|
||||
$json = $e->encode($fe, 'json');
|
||||
$this->assertNotNull($json);
|
||||
|
||||
$decode = $e->decode('FatturaPA', $json, 'json');
|
||||
|
||||
$this->assertInstanceOf(FatturaElettronica::class, $decode);
|
||||
}
|
||||
}
|
||||
|
154
tests/Feature/EInvoice/PeppolTest.php
Normal file
154
tests/Feature/EInvoice/PeppolTest.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?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\Feature\EInvoice;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use Tests\MockAccountData;
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Models\Invoice;
|
||||
use InvoiceNinja\EInvoice\Symfony\Encode;
|
||||
use App\Services\EDocument\Standards\FatturaPANew;
|
||||
use App\Services\EDocument\Standards\Peppol;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use InvoiceNinja\EInvoice\EInvoice;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronica;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody;
|
||||
use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class PeppolTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
|
||||
// $this->markTestSkipped('prevent running in CI');
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvoiceBoot()
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->address1 = 'Via Silvio Spaventa 108';
|
||||
$settings->city = 'Calcinelli';
|
||||
|
||||
$settings->state = 'PA';
|
||||
|
||||
// $settings->state = 'Perugia';
|
||||
$settings->postal_code = '61030';
|
||||
$settings->country_id = '380';
|
||||
$settings->currency_id = '3';
|
||||
$settings->vat_number = '01234567890';
|
||||
$settings->id_number = '';
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
$client_settings = ClientSettings::defaults();
|
||||
$client_settings->currency_id = '3';
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'name' => 'Italian Client Name',
|
||||
'address1' => 'Via Antonio da Legnago 68',
|
||||
'city' => 'Monasterace',
|
||||
'state' => 'CR',
|
||||
// 'state' => 'Reggio Calabria',
|
||||
'postal_code' => '89040',
|
||||
'country_id' => 380,
|
||||
'routing_id' => 'ABC1234',
|
||||
'settings' => $client_settings,
|
||||
]);
|
||||
|
||||
$item = new InvoiceItem();
|
||||
$item->product_key = "Product Key";
|
||||
$item->notes = "Product Description";
|
||||
$item->cost = 10;
|
||||
$item->quantity = 10;
|
||||
$item->tax_rate1 = 22;
|
||||
$item->tax_name1 = 'IVA';
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'discount' => 0,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'status_id' => 1,
|
||||
'tax_rate1' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'line_items' => [$item],
|
||||
'number' => 'ITA-'.rand(1000, 100000),
|
||||
'date' => now()->format('Y-m-d')
|
||||
]);
|
||||
|
||||
$invoice->service()->markSent()->save();
|
||||
|
||||
$fat = new Peppol($invoice);
|
||||
$fat->run();
|
||||
|
||||
$fe = $fat->getInvoice();
|
||||
|
||||
$this->assertNotNull($fe);
|
||||
|
||||
$this->assertInstanceOf(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $fe);
|
||||
|
||||
$e = new EInvoice();
|
||||
$xml = $e->encode($fe, 'xml');
|
||||
$this->assertNotNull($xml);
|
||||
|
||||
nlog($xml);
|
||||
|
||||
$json = $e->encode($fe, 'json');
|
||||
$this->assertNotNull($json);
|
||||
|
||||
nlog($json);
|
||||
|
||||
$decode = $e->decode('Peppol', $json, 'json');
|
||||
|
||||
$this->assertInstanceOf(\InvoiceNinja\EInvoice\Models\Peppol\Invoice::class, $decode);
|
||||
|
||||
$errors = $e->validate($fe);
|
||||
|
||||
if(count($errors) > 0) {
|
||||
nlog($errors);
|
||||
}
|
||||
|
||||
$this->assertCount(0, $errors);
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -184,7 +184,7 @@ class ReminderTest extends TestCase
|
||||
$settings->schedule_reminder1 = 'after_invoice_date';
|
||||
$settings->schedule_reminder2 = 'after_invoice_date';
|
||||
$settings->schedule_reminder3 = 'after_invoice_date';
|
||||
|
||||
$settings->lock_invoices = true;
|
||||
$settings->num_days_reminder1 = 5;
|
||||
$settings->num_days_reminder2 = 10;
|
||||
$settings->num_days_reminder3 = 15;
|
||||
@ -231,7 +231,6 @@ class ReminderTest extends TestCase
|
||||
}
|
||||
while($x === false);
|
||||
|
||||
|
||||
$this->assertNotNull($invoice->reminder_last_sent);
|
||||
|
||||
//check next send date is on day "10"
|
||||
|
@ -23,51 +23,51 @@ use Illuminate\Support\Facades\Cache;
|
||||
use Symfony\Component\Validator\Validation;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Serializer\Encoder\XmlEncoder;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\ItemType\Item;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ItemType\Item;
|
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\PartyType\Party;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\PriceType\Price;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyType\Party;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PriceType\Price;
|
||||
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\ContactType\Contact;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\CountryType\Country;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\TaxAmount;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxTotalType\TaxTotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\ContactType\Contact;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CountryType\Country;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxTotalType\TaxTotal;
|
||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\PriceAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PriceAmount;
|
||||
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxSchemeType\TaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxSchemeType\TaxScheme;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AddressType\PostalAddress;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AddressType\PostalAddress;
|
||||
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\InvoiceLineType\InvoiceLine;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxScheme as FACT1TaxScheme;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxSubtotalType\TaxSubtotal;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\QuantityType\InvoicedQuantity;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\InvoiceLineType\InvoiceLine;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxScheme as PeppolTaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxSubtotalType\TaxSubtotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\QuantityType\InvoicedQuantity;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\LineExtensionAmount;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\PayableAmount;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\TaxableAmount;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\TaxExclusiveAmount;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\AmountType\TaxInclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\LineExtensionAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PayableAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxableAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxExclusiveAmount;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxInclusiveAmount;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\PartyTaxSchemeType\PartyTaxScheme;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyTaxSchemeType\PartyTaxScheme;
|
||||
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\MonetaryTotalType\LegalMonetaryTotal;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\PartyLegalEntityType\PartyLegalEntity;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxCategoryType\ClassifiedTaxCategory;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\MonetaryTotalType\LegalMonetaryTotal;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyLegalEntityType\PartyLegalEntity;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\ClassifiedTaxCategory;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\CustomerPartyType\AccountingCustomerParty;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\SupplierPartyType\AccountingSupplierParty;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\PartyIdentificationType\PartyIdentification;
|
||||
use Invoiceninja\Einvoice\Models\FACT1\TaxCategoryType\TaxCategory;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\SupplierPartyType\AccountingSupplierParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyIdentificationType\PartyIdentification;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\TaxCategory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class Fact1Test extends TestCase
|
||||
class FACT1Test extends TestCase
|
||||
{
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
@ -140,7 +140,7 @@ class Fact1Test extends TestCase
|
||||
$_invoice->service()->markSent()->save();
|
||||
$calc = $_invoice->calc();
|
||||
|
||||
$invoice = new \Invoiceninja\Einvoice\Models\FACT1\Invoice();
|
||||
$invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice();
|
||||
$invoice->UBLVersionID = '2.1';
|
||||
$invoice->CustomizationID = 'urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1';
|
||||
$invoice->ID = $_invoice->number;
|
||||
@ -298,7 +298,7 @@ class Fact1Test extends TestCase
|
||||
$i->Description = $item->notes;
|
||||
$i->Name = $item->product_key;
|
||||
|
||||
$tax_scheme = new FACT1TaxScheme();
|
||||
$tax_scheme = new PeppolTaxScheme();
|
||||
$tax_scheme->ID = $item->tax_name1;
|
||||
$tax_scheme->Name = $item->tax_rate1;
|
||||
|
||||
|
@ -31,6 +31,29 @@ class DatesTest extends TestCase
|
||||
// $this->makeTestData();
|
||||
}
|
||||
|
||||
public function testDateNotGreaterThanMonthsEnd()
|
||||
{
|
||||
$this->travelTo(now()->createFromDate(2024, 6, 20));
|
||||
$date = '2024-05-20';
|
||||
|
||||
$this->assertTrue(\Carbon\Carbon::parse($date)->endOfMonth()->lte(now()));
|
||||
|
||||
$this->travelBack();
|
||||
|
||||
}
|
||||
|
||||
public function testDatLessThanMonthsEnd()
|
||||
{
|
||||
$this->travelTo(now()->createFromDate(2024, 5, 30));
|
||||
$date = '2024-05-20';
|
||||
|
||||
$this->assertFalse(\Carbon\Carbon::parse($date)->endOfMonth()->lte(now()));
|
||||
|
||||
$this->travelBack();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testLastFinancialYear3()
|
||||
{
|
||||
$this->travelTo(now()->createFromDate(2020, 6, 30));
|
||||
|
21
vite.config.ts.react
Normal file
21
vite.config.ts.react
Normal file
@ -0,0 +1,21 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tsconfigPaths(), react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
},
|
||||
build: {
|
||||
assetsDir: '',
|
||||
chunkSizeWarningLimit: 1500,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
// This will output a single bundle file
|
||||
entryFileNames: 'bundle.js',
|
||||
chunkFileNames: 'bundle.js'
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user