1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-11 05:32:39 +01:00

Merge pull request #8462 from turbo124/v5-develop

V5 develop
This commit is contained in:
David Bomba 2023-04-23 08:16:45 +10:00 committed by GitHub
commit b9bcbe0015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 3241 additions and 2916 deletions

View File

@ -11,11 +11,12 @@
namespace App\Console\Commands;
use App\Libraries\MultiDB;
use App\Utils\Ninja;
use App\Models\Backup;
use App\Models\Client;
use App\Models\Company;
use App\Models\Document;
use App\Libraries\MultiDB;
use App\Models\GroupSetting;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
@ -55,6 +56,9 @@ class BackupUpdate extends Command
{
//always return state to first DB
if(Ninja::isSelfHost())
return;
$current_db = config('database.default');
if (! config('ninja.db.multi_db_enabled')) {

View File

@ -12,6 +12,7 @@
namespace App\DataMapper\Tax;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Product;
use App\DataMapper\Tax\ZipTax\Response;
@ -117,6 +118,8 @@ class BaseRule implements RuleInterface
protected ?Response $tax_data;
public ?Invoice $invoice;
public function __construct()
{
}
@ -126,18 +129,29 @@ class BaseRule implements RuleInterface
return $this;
}
public function setClient(Client $client): self
public function setInvoice(Invoice $invoice): self
{
$this->client = $client;
$this->invoice = $invoice;
$this->configTaxData();
$this->client = $invoice->client;
$this->tax_data = new Response($this->invoice->tax_data);
$this->resolveRegions();
return $this;
}
public function setTaxData(Response $tax_data): self
private function configTaxData(): self
{
$this->tax_data = $tax_data;
if($this->invoice->tax_data && $this->invoice->status_id > 1)
return $this;
//determine if we are taxing locally or if we are taxing globally
// $this->invoice->tax_data = $this->invoice->client->tax_data;
return $this;
}
@ -176,10 +190,10 @@ class BaseRule implements RuleInterface
return $this;
}
elseif($this->client_region == 'AU'){
elseif($this->client_region == 'AU'){ //these are defaults and are only stubbed out for now, for AU we can actually remove these
$this->tax_rate1 = 10;
$this->tax_name1 = 'GST';
$this->tax_rate1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_rate;
$this->tax_name1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_name;
return $this;
}

View File

@ -14,19 +14,19 @@ namespace App\DataMapper\Tax;
class TaxModel
{
/** @var mixed $seller_subregion */
/** @var string $seller_subregion */
public string $seller_subregion = 'CA';
/** @var mixed $version */
/** @var string $version */
public string $version = 'alpha';
/** @var mixed $regions */
/** @var object $regions */
public object $regions;
/**
* __construct
*
* @param mixed $model
* @param TaxModel $model
* @return void
*/
public function __construct(public ?TaxModel $model = null)
@ -42,9 +42,9 @@ class TaxModel
/**
* Initializes the rules and builds any required data.
*
* @return void
* @return object
*/
public function init()
public function init(): object
{
$this->regions = new \stdClass();
$this->regions->US = new \stdClass();

View File

@ -65,6 +65,7 @@ class Response
public string $geoCounty = "";
public string $geoState = "";
public float $taxSales = 0;
public string $taxName = "";
public float $taxUse = 0;
public string $txbService = ""; // N = No, Y = Yes
public string $txbFreight = ""; // N = No, Y = Yes
@ -73,6 +74,8 @@ class Response
public float $citySalesTax = 0;
public float $cityUseTax = 0;
public string $cityTaxCode = "";
/* US SPECIFIC TAX CODES */
public float $countySalesTax = 0;
public float $countyUseTax = 0;
public string $countyTaxCode = "";
@ -93,7 +96,9 @@ class Response
public string $district5Code = "";
public float $district5SalesTax = 0;
public float $district5UseTax = 0;
public string $originDestination = "";
/* US SPECIFIC TAX CODES */
public string $originDestination = ""; // defines if the client origin is the locale where the tax is remitted to
public function __construct($data)
{

View File

@ -116,7 +116,7 @@ class RecurringInvoiceFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Eloquent\Builder
* @return Builder
*/
public function entityFilter(): Builder
{
@ -126,7 +126,7 @@ class RecurringInvoiceFilters extends QueryFilters
/**
* Filter based on line_items product_key
*
* @param string value Product keys
* @param string $value Product keys
* @return Builder
*/
public function product_key(string $value = ''): Builder

View File

@ -146,12 +146,9 @@ class InvoiceItemSum
$class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule";
$tax_data = new Response($this->invoice?->tax_data);
$this->rule = new $class();
$this->rule
->setTaxData($tax_data)
->setClient($this->client)
->setInvoice($this->invoice)
->init();
$this->calc_tax = true;

View File

@ -140,10 +140,6 @@ class EmailController extends BaseController
$mo->cc[] = new Address($request->cc_email);
}
// if ($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order' || $entity == 'App\Models\PurchaseOrder') {
// return $this->sendPurchaseOrder($entity_obj, $data, $template);
// }
$entity_obj->invitations->each(function ($invitation) use ($data, $entity_obj, $template, $mo) {
if (! $invitation->contact->trashed() && $invitation->contact->email) {
$entity_obj->service()->markSent()->save();

View File

@ -162,6 +162,9 @@ class SelfUpdateController extends BaseController
$this->deleteDirectory(base_path('vendor/beganovich/snappdf/versions/'.$file->getFileName()));
}
}
$iterator = null;
}
private function deleteDirectory($dir)
@ -206,6 +209,8 @@ class SelfUpdateController extends BaseController
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) {
unlink(base_path('bootstrap/cache/').$file->getFileName());
}
$directoryIterator = null;
}
private function testWritable()
@ -225,6 +230,8 @@ class SelfUpdateController extends BaseController
}
}
$directoryIterator = null;
return true;
}

View File

@ -30,6 +30,7 @@ class BlackListRule implements Rule
'sharklasers.com',
'100072641.help',
'yandex.com',
'bloheyz.com',
];
/**

View File

@ -136,7 +136,7 @@ class NinjaMailerJob implements ShouldQueue
->send($this->nmo->mailable);
/* Count the amount of emails sent across all the users accounts */
Cache::increment($this->company->account->key);
Cache::increment("email_quota".$this->company->account->key);
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
->send();
@ -486,8 +486,13 @@ class NinjaMailerJob implements ShouldQueue
*/
private function preFlightChecksFail(): bool
{
/* Always send regardless */
if($this->override) {
return false;
}
/* If we are migrating data we don't want to fire any emails */
if ($this->company->is_disabled && !$this->override) {
if ($this->company->is_disabled) {
return true;
}

View File

@ -550,7 +550,7 @@ class Account extends BaseModel
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 50;
} else {
$limit = $this->free_plan_email_quota;
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 10;
$limit += Carbon::createFromTimestamp($this->created_at)->diffInMonths() * 3;
}
return min($limit, 5000);

View File

@ -190,7 +190,7 @@ class BaseRepository
$this->new_model = true;
if (is_array($model->line_items) && !($model instanceof RecurringInvoice)) {
$model->line_items = (collect($model->line_items))->map(function ($item) use ($model, $client) {
$model->line_items = (collect($model->line_items))->map(function ($item) use ($client) {
$item->notes = Helpers::processReservedKeywords($item->notes, $client);
return $item;

View File

@ -247,7 +247,7 @@ class Email implements ShouldQueue
$mailer->send($this->mailable);
Cache::increment($this->company->account->key);
Cache::increment("email_quota".$this->company->account->key);
LightLogs::create(new EmailSuccess($this->company->company_key))
->send();
@ -329,8 +329,13 @@ class Email implements ShouldQueue
*/
public function preFlightChecksFail(): bool
{
/* Always send if disabled */
if($this->override) {
return false;
}
/* If we are migrating data we don't want to fire any emails */
if ($this->company->is_disabled && !$this->override) {
if ($this->company->is_disabled) {
return true;
}

View File

@ -95,7 +95,7 @@ class EmailMailer implements ShouldQueue
$mailer->send($this->email_mailable);
Cache::increment($this->email_service->company->account->key);
Cache::increment("email_quota".$this->email_service->company->account->key);
LightLogs::create(new EmailSuccess($this->email_service->company->company_key))
->send();

View File

@ -0,0 +1,140 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Invoice\EInvoice;
use SimpleXMLElement;
use App\Models\Invoice;
use App\Services\AbstractService;
/*
<?xml version="1.0" encoding="UTF-8"?>
<FatturaElettronica versione="FPR12" xmlns="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>00001</ProgressivoInvio>
<FormatoTrasmissione>FPR12</FormatoTrasmissione>
<CodiceDestinatario>ABCDE1</CodiceDestinatario>
</DatiTrasmissione>
<CedentePrestatore>
<!-- Company information of the sender (seller/provider) -->
</CedentePrestatore>
<CessionarioCommittente>
<!-- Company information of the receiver (buyer) -->
</CessionarioCommittente>
</FatturaElettronicaHeader>
<FatturaElettronicaBody>
<DatiGenerali>
<DatiGeneraliDocumento>
<TipoDocumento>TD01</TipoDocumento>
<Divisa>EUR</Divisa>
<Data>2023-04-21</Data>
<Numero>1</Numero>
<!-- Add other information as needed -->
</DatiGeneraliDocumento>
<!-- Add other general data as needed -->
</DatiGenerali>
<DatiBeniServizi>
<!-- List of items or services -->
</DatiBeniServizi>
<DatiPagamento>
<!-- Payment details -->
</DatiPagamento>
</FatturaElettronicaBody>
</FatturaElettronica>
*/
class FatturaPA extends AbstractService
{
private $xml;
public function __construct(public Invoice $invoice)
{
$this->xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><FatturaElettronica></FatturaElettronica>');
}
public function run()
{
return $this->addHeader()->getXml();
}
public function addHeader() {
$this->xml->addChild('FatturaElettronicaHeader');
return $this;
}
public function addTrasmissioneData($idPaese, $idCodice, $progressivoInvio, $formatoTrasmissione, $codiceDestinatario) {
$datiTrasmissione = $this->xml->FatturaElettronicaHeader->addChild('DatiTrasmissione');
$idTrasmittente = $datiTrasmissione->addChild('IdTrasmittente');
$idTrasmittente->addChild('IdPaese', $idPaese);
$idTrasmittente->addChild('IdCodice', $idCodice);
$datiTrasmissione->addChild('ProgressivoInvio', $progressivoInvio);
$datiTrasmissione->addChild('FormatoTrasmissione', $formatoTrasmissione);
$datiTrasmissione->addChild('CodiceDestinatario', $codiceDestinatario);
return $this;
}
public function addCedentePrestatore($data) {
// Add CedentePrestatore data
}
public function addCessionarioCommittente($data) {
// Add CessionarioCommittente data
}
public function addBody() {
$this->xml->addChild('FatturaElettronicaBody');
return $this;
}
public function addDatiGenerali($data) {
// Add DatiGenerali data
}
public function addLineItem($data) {
if (!isset($this->xml->FatturaElettronicaBody->DatiBeniServizi)) {
$this->xml->FatturaElettronicaBody->addChild('DatiBeniServizi');
}
$lineItem = $this->xml->FatturaElettronicaBody->DatiBeniServizi->addChild('DettaglioLinee');
$lineItem->addChild('NumeroLinea', $data['NumeroLinea']);
$lineItem->addChild('Descrizione', $data['notes']);
$lineItem->addChild('Quantita', $data['quantity']);
$lineItem->addChild('PrezzoUnitario', $data['cost']);
$lineItem->addChild('PrezzoTotale', $data['line_total']);
$lineItem->addChild('AliquotaIVA', $data['tax_rate1']);
if (isset($data['UnitaMisura'])) {
$lineItem->addChild('UnitaMisura', $data['UnitaMisura']);
}
return $this;
}
public function addDatiPagamento($data) {
// Add DatiPagamento data
}
public function getXml()
{
return $this->xml->asXML();
}
}
// $fattura = new FatturaPA();
// $fattura
// ->addHeader()
// ->addTrasmissioneData('IT', '01234567890', '00001', 'FPR12', 'ABCDE1');
// echo $fattura->getXml();

View File

@ -28,7 +28,7 @@ class EmailStats
*/
public static function inc($company_key)
{
Cache::increment(self::EMAIL.$company_key);
Cache::increment("email_quota".self::EMAIL.$company_key);
}
/**

View File

@ -155,7 +155,7 @@ class HtmlEngine
$data['$exchange_rate'] = ['value' => $this->entity->exchange_rate ?: ' ', 'label' => ctrans('texts.exchange_rate')];
if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') {
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')];
$data['$entity'] = ['value' => ctrans('texts.invoice'), 'label' => ctrans('texts.invoice')];
$data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
$data['$invoice'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
$data['$number_short'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number_short')];
@ -212,7 +212,7 @@ class HtmlEngine
}
if ($this->entity_string == 'quote') {
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.quote')];
$data['$entity'] = ['value' => ctrans('texts.quote'), 'label' => ctrans('texts.quote')];
$data['$number'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.quote_number')];
$data['$number_short'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.quote_number_short')];
$data['$entity.terms'] = ['value' => Helpers::processReservedKeywords(\nl2br($this->entity->terms ?: ''), $this->client) ?: '', 'label' => ctrans('texts.quote_terms')];
@ -256,7 +256,7 @@ class HtmlEngine
}
if ($this->entity_string == 'credit') {
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.credit')];
$data['$entity'] = ['value' => ctrans('texts.credit'), 'label' => ctrans('texts.credit')];
$data['$number'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.credit_number')];
$data['$number_short'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.credit_number_short')];
$data['$entity.terms'] = ['value' => Helpers::processReservedKeywords(\nl2br($this->entity->terms ?: ''), $this->client) ?: '', 'label' => ctrans('texts.credit_terms')];

View File

@ -4379,7 +4379,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'imported_customers' => 'Se comenzó a importar clientes con éxito',
'login_success' => 'Inicio de sesión correcto',
'login_failure' => 'Inicio de sesión fallido',
'exported_data' => 'Once the file is ready you\'ll receive an email with a download link',
'exported_data' => 'Una vez que el archivo esté listo, recibirá un correo electrónico con un enlace de descarga.',
'include_deleted_clients' => 'Incluir clientes eliminados',
'include_deleted_clients_help' => 'Cargar registros pertenecientes a clientes eliminados',
'step_1_sign_in' => 'Paso 1: Iniciar sesión',
@ -4468,7 +4468,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'activity_123' => ':user eliminó el gasto recurrente :recurring_expense',
'activity_124' => ':user restauró el gasto recurrente :recurring_expense',
'fpx' => "FPX",
'to_view_entity_set_password' => 'To view the :entity you need to set a password.',
'to_view_entity_set_password' => 'Para ver el :entity necesita establecer una contraseña.',
'unsubscribe' => 'Darse de baja',
'unsubscribed' => 'Dado de baja',
'unsubscribed_text' => 'Se le ha eliminado de las notificaciones de este documento',
@ -4566,7 +4566,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'purchase_order_number' => 'Número de orden de compra',
'purchase_order_number_short' => 'orden de compra n.°',
'inventory_notification_subject' => 'Notificación de umbral de inventario para el producto: :product',
'inventory_notification_body' => 'Threshold of :amount has been reached for product: :product',
'inventory_notification_body' => 'Se ha alcanzado el umbral de:amount para el producto: :product',
'activity_130' => ':user creó la orden de compra :purchase_order',
'activity_131' => ':user actualizó la orden de compra :purchase_order',
'activity_132' => ':user archivó la orden de compra :purchase_order',
@ -4598,7 +4598,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'vendor_document_upload' => 'Carga de documentos de proveedores',
'vendor_document_upload_help' => 'Permitir que los proveedores carguen documentos',
'are_you_enjoying_the_app' => '¿Estás disfrutando de la aplicación?',
'yes_its_great' => 'Yes, it\'s great!',
'yes_its_great' => '¡Sí, es genial!',
'not_so_much' => 'No tanto',
'would_you_rate_it' => '¡Me alegro de oirlo! ¿Te gustaría calificarlo?',
'would_you_tell_us_more' => '¡Siento escucharlo! ¿Te gustaría contarnos más?',
@ -4969,9 +4969,9 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'white_label_body' => 'Gracias por comprar una licencia de marca blanca.<br><br> Su clave de licencia es:<br><br> :license_key',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
'xinvoice_no_buyers_reference' => "No buyer's reference given",
'xinvoice_online_payment' => 'The invoice needs to be payed online via the provided link',
'xinvoice_payable' => 'Pagadero dentro de :payeddue días de pago vencido neto hasta :paydate',
'xinvoice_no_buyers_reference' => "No se da la referencia del comprador",
'xinvoice_online_payment' => 'La factura debe pagarse en línea a través del enlace proporcionado.',
'pre_payment' => 'Prepago',
'number_of_payments' => 'Numero de pagos',
'number_of_payments_helper' => 'El número de veces que se realizará este pago.',
@ -5034,24 +5034,24 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
'taxable_amount' => 'Base imponible',
'tax_summary' => 'Resumen de impuestos',
'oauth_mail' => 'OAuth / Mail',
'preferences' => 'Preferences',
'analytics' => 'Analytics',
'reduced_rate' => 'Reduced Rate',
'tax_all' => 'Tax All',
'tax_selected' => 'Tax Selected',
'version' => 'version',
'seller_subregion' => 'Seller Subregion',
'calculate_taxes' => 'Calculate Taxes',
'calculate_taxes_help' => 'Automatically calculate taxes when saving invoices',
'link_expenses' => 'Link Expenses',
'converted_client_balance' => 'Converted Client Balance',
'converted_payment_balance' => 'Converted Payment Balance',
'total_hours' => 'Total Hours',
'date_picker_hint' => 'Use +days to set the date in the future',
'app_help_link' => 'More information ',
'here' => 'here',
'industry_Restaurant & Catering' => 'Restaurant & Catering',
'show_credits_table' => 'Show Credits Table',
'preferences' => 'Preferencias',
'analytics' => 'Analítica',
'reduced_rate' => 'Tarifa Reducida',
'tax_all' => 'Impuestos Todos',
'tax_selected' => 'Impuesto Seleccionado',
'version' => 'versión',
'seller_subregion' => 'Subregión del vendedor',
'calculate_taxes' => 'Calcular impuestos',
'calculate_taxes_help' => 'Calcular automáticamente los impuestos al guardar las facturas',
'link_expenses' => 'Gastos de enlace',
'converted_client_balance' => 'Saldo de cliente convertido',
'converted_payment_balance' => 'Saldo de pago convertido',
'total_hours' => 'Horas totales',
'date_picker_hint' => 'Usa +días para establecer la fecha en el futuro',
'app_help_link' => 'Más información',
'here' => 'aquí',
'industry_Restaurant & Catering' => 'Restaurante y Catering',
'show_credits_table' => 'Mostrar tabla de créditos',
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,11 +14,11 @@
@if($invoice->isPayable() && $client->getSetting('custom_message_unpaid_invoice'))
@component('portal.ninja2020.components.message')
{{ $client->getSetting('custom_message_unpaid_invoice') }}
<pre>{{ $client->getSetting('custom_message_unpaid_invoice') }}</pre>
@endcomponent
@elseif($invoice->status_id === 4 && $client->getSetting('custom_message_paid_invoice'))
@component('portal.ninja2020.components.message')
{{ $client->getSetting('custom_message_paid_invoice') }}
<pre>{{ $client->getSetting('custom_message_paid_invoice') }}</pre>
@endcomponent
@endif

View File

@ -18,7 +18,7 @@
@if(!$quote->isApproved() && $client->getSetting('custom_message_unapproved_quote'))
@component('portal.ninja2020.components.message')
{{ $client->getSetting('custom_message_unapproved_quote') }}
<pre>{{ $client->getSetting('custom_message_unapproved_quote') }}</pre>
@endcomponent
@endif

View File

@ -0,0 +1,48 @@
<?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;
use App\Services\Invoice\EInvoice\FatturaPA;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\MockAccountData;
use Tests\TestCase;
/**
* @test
*/
class FatturaPATest extends TestCase
{
use DatabaseTransactions;
use MockAccountData;
protected function setUp(): void
{
parent::setUp();
$this->makeTestData();
$this->withoutMiddleware(
ThrottleRequests::class
);
}
public function testInvoiceBoot()
{
$fat = new FatturaPA($this->invoice);
$xml = $fat->run();
// nlog($xml);
$this->assertnotNull($xml);
}
}

View File

@ -579,7 +579,7 @@ class RecurringInvoiceTest extends TestCase
'user_id' => $this->user->id,
'cost' => 10,
'price' => 10,
'product_key' => $this->faker->word,
'product_key' => $this->faker->unique()->word(),
]);
$p2 = Product::factory()->create([
@ -587,7 +587,7 @@ class RecurringInvoiceTest extends TestCase
'user_id' => $this->user->id,
'cost' => 20,
'price' => 20,
'product_key' => $this->faker->word,
'product_key' => $this->faker->unique()->word(),
]);
$recurring_invoice = RecurringInvoiceFactory::create($this->company->id, $this->user->id);
@ -627,7 +627,7 @@ class RecurringInvoiceTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->get('/api/v1/recurring_invoices?product_key=' . $this->faker->word)
])->get('/api/v1/recurring_invoices?product_key=' . $this->faker->unique()->word())
->assertStatus(200);
$arr = $response->json();

View File

@ -11,18 +11,18 @@
namespace Tests\Unit\Tax;
use Tests\TestCase;
use App\DataMapper\CompanySettings;
use App\DataMapper\Tax\DE\Rule;
use App\DataMapper\Tax\TaxModel;
use App\DataMapper\Tax\ZipTax\Response;
use App\Models\Client;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Product;
use Tests\MockAccountData;
use App\DataMapper\Tax\DE\Rule;
use App\DataMapper\Tax\TaxModel;
use App\DataMapper\CompanySettings;
use App\DataMapper\Tax\ZipTax\Response;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\MockAccountData;
use Tests\TestCase;
/**
* @test App\Services\Tax\Providers\EuTax
@ -338,8 +338,18 @@ class EuTaxTest extends TestCase
'has_valid_vat_number' => false,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertEquals('EU', $process->seller_region);
@ -382,12 +392,21 @@ class EuTaxTest extends TestCase
'has_valid_vat_number' => false,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertEquals('EU', $process->seller_region);
$this->assertEquals('EU', $process->seller_region);
$this->assertEquals('BE', $process->client_subregion);
@ -428,11 +447,18 @@ $this->assertEquals('EU', $process->seller_region);
'has_valid_vat_number' => false,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setTaxData(new Response([
'geoState' => 'CA',
]));
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertEquals('EU', $process->seller_region);
@ -476,8 +502,18 @@ $this->assertEquals('EU', $process->seller_region);
'has_valid_vat_number' => false,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
@ -517,10 +553,21 @@ $this->assertEquals('EU', $process->seller_region);
'has_valid_vat_number' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
$this->assertTrue($client->has_valid_vat_number);
@ -556,11 +603,22 @@ $this->assertEquals('EU', $process->seller_region);
'shipping_country_id' => 56,
'has_valid_vat_number' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
$this->assertTrue($client->has_valid_vat_number);
@ -597,10 +655,21 @@ $this->assertEquals('EU', $process->seller_region);
'is_tax_exempt' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
$this->assertTrue($client->is_tax_exempt);
@ -637,8 +706,18 @@ $this->assertEquals('EU', $process->seller_region);
'is_tax_exempt' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
@ -676,11 +755,21 @@ $this->assertEquals('EU', $process->seller_region);
'is_tax_exempt' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $company->id,
'client_id' => $client->id,
'user_id' => $this->user->id,
'status_id' => Invoice::STATUS_SENT,
'tax_data' => new Response([
'geoState' => 'CA',
]),
]);
$process = new Rule();
$process->setTaxData(new Response([]));
$process->setClient($client);
$process->setInvoice($invoice);
$process->init();
$this->assertInstanceOf(Rule::class, $process);
$this->assertTrue($client->is_tax_exempt);