mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 21:22:58 +01:00
commit
6265cee79e
4
.github/workflows/phpunit.yml
vendored
4
.github/workflows/phpunit.yml
vendored
@ -16,8 +16,8 @@ jobs:
|
||||
operating-system: ['ubuntu-20.04', 'ubuntu-22.04']
|
||||
php-versions: ['8.1','8.2']
|
||||
phpunit-versions: ['latest']
|
||||
ci_node_total: [ 6 ]
|
||||
ci_node_index: [ 0, 1, 2, 3, 4, 5]
|
||||
ci_node_total: [ 8 ]
|
||||
ci_node_index: [ 0, 1, 2, 3, 4, 5, 6, 7]
|
||||
laravel: [9.*]
|
||||
dependency-version: [prefer-stable]
|
||||
|
||||
|
@ -160,7 +160,7 @@ class BaseRule implements RuleInterface
|
||||
return $this;
|
||||
|
||||
//determine if we are taxing locally or if we are taxing globally
|
||||
$tax_data = $this->invoice->client->tax_data ?? new Response([]);
|
||||
$tax_data = is_object($this->invoice->client->tax_data) ? $this->invoice->client->tax_data : new Response([]);
|
||||
|
||||
if(strlen($this->invoice->tax_data?->originDestination) == 0 && $this->client->company->tax_data->seller_subregion != $this->client_subregion) {
|
||||
$tax_data->originDestination = "D";
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
namespace App\Http\Requests\User;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\Ninja\CanRestoreUserRule;
|
||||
use App\Utils\Ninja;
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use App\Http\ValidationRules\Ninja\CanRestoreUserRule;
|
||||
|
||||
class BulkUserRequest extends Request
|
||||
{
|
||||
@ -24,6 +25,9 @@ class BulkUserRequest extends Request
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
if($this->action == 'delete' && in_array(auth()->user()->hashed_id, $this->ids))
|
||||
return false;
|
||||
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
@ -44,4 +48,9 @@ class BulkUserRequest extends Request
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
protected function failedAuthorization()
|
||||
{
|
||||
throw new AuthorizationException("This Action is unauthorized.");
|
||||
}
|
||||
}
|
||||
|
@ -95,11 +95,12 @@ class Document extends BaseModel
|
||||
const DOCUMENT_PREVIEW_SIZE = 300; // pixels
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'is_default',
|
||||
'is_public',
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -543,7 +543,8 @@ class ACH
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_STRIPE,
|
||||
$this->stripe->client
|
||||
$this->stripe->client,
|
||||
$this->stripe->client->company,
|
||||
);
|
||||
|
||||
throw new PaymentFailed('Failed to process the payment.', 500);
|
||||
@ -570,6 +571,20 @@ class ACH
|
||||
'payment_method_id' => $payment_method_id,
|
||||
];
|
||||
|
||||
/**
|
||||
* Ensure the method does not already exist!!
|
||||
*/
|
||||
|
||||
$token = ClientGatewayToken::where([
|
||||
'gateway_customer_reference' => $customer->id,
|
||||
'token' => $method->id,
|
||||
'client_id' => $this->stripe->client->id,
|
||||
'company_id' => $this->stripe->client->company_id,
|
||||
])->first();
|
||||
|
||||
if($token)
|
||||
return $token;
|
||||
|
||||
return $this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
|
||||
} catch (Exception $e) {
|
||||
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
|
||||
|
@ -194,17 +194,14 @@ class Charge
|
||||
switch ($type) {
|
||||
case 'visa':
|
||||
return PaymentType::VISA;
|
||||
break;
|
||||
case 'mastercard':
|
||||
return PaymentType::MASTERCARD;
|
||||
break;
|
||||
case PaymentType::SEPA:
|
||||
return PaymentType::SEPA;
|
||||
case PaymentType::BACS:
|
||||
return PaymentType::BACS;
|
||||
default:
|
||||
return PaymentType::CREDIT_CARD_OTHER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,15 @@
|
||||
|
||||
namespace App\PaymentDrivers\Stripe;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\SystemLog;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\PaymentType;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\PaymentDrivers\StripePaymentDriver;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
|
||||
class SEPA
|
||||
{
|
||||
@ -159,6 +160,17 @@ class SEPA
|
||||
'payment_method_id' => GatewayType::SEPA,
|
||||
];
|
||||
|
||||
$token = ClientGatewayToken::where([
|
||||
'gateway_customer_reference' => $method->customer,
|
||||
'token' => $method->id,
|
||||
'client_id' => $this->stripe->client->id,
|
||||
'company_id' => $this->stripe->client->company_id,
|
||||
])->first();
|
||||
|
||||
if($token) {
|
||||
return $token;
|
||||
}
|
||||
|
||||
$this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $method->customer]);
|
||||
} catch (\Exception $e) {
|
||||
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
|
||||
|
@ -106,7 +106,7 @@ class StripePaymentDriver extends BaseDriver
|
||||
|
||||
/**
|
||||
* Initializes the Stripe API.
|
||||
* @return void
|
||||
* @return self
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
|
@ -169,6 +169,7 @@ class FacturaEInvoice extends AbstractService
|
||||
|
||||
foreach($this->invoice->line_items as $item) {
|
||||
$this->fac->addItem(new FacturaeItem([
|
||||
'name' => $item->product_key,
|
||||
'description' => $item->notes,
|
||||
'quantity' => $item->quantity,
|
||||
'unitPrice' => $item->cost,
|
||||
@ -211,6 +212,9 @@ class FacturaEInvoice extends AbstractService
|
||||
|
||||
}
|
||||
|
||||
if(count($data) == 0)
|
||||
$data[Facturae::TAX_IVA] = 0;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@ -257,29 +261,30 @@ class FacturaEInvoice extends AbstractService
|
||||
$company = $this->invoice->company;
|
||||
|
||||
$seller = new FacturaeParty([
|
||||
"isLegalEntity" => true, // Se asume true si se omite
|
||||
"taxNumber" => $company->settings->vat_number,
|
||||
"name" => $company->present()->name(),
|
||||
"address" => $company->settings->address1,
|
||||
"postCode" => $company->settings->postal_code,
|
||||
"town" => $company->settings->city,
|
||||
"province" => $company->settings->state,
|
||||
"countryCode" => $company->country()->iso_3166_3, // Se asume España si se omite
|
||||
"book" => "0", // Libro
|
||||
"merchantRegister" => "RG", // Registro Mercantil
|
||||
"sheet" => "1", // Hoja
|
||||
"folio" => "2", // Folio
|
||||
"section" => "3", // Sección
|
||||
"volume" => "4", // Tomo
|
||||
"email" => $company->settings->email,
|
||||
"phone" => $company->settings->phone,
|
||||
"fax" => "",
|
||||
"website" => $company->settings->website,
|
||||
"contactPeople" => $company->owner()->present()->name(),
|
||||
// "cnoCnae" => "04647", // Clasif. Nacional de Act. Económicas
|
||||
// "ineTownCode" => "280796" // Cód. de municipio del INE
|
||||
"isLegalEntity" => true, // Se asume true si se omite
|
||||
"taxNumber" => $company->settings->vat_number,
|
||||
"name" => substr($company->present()->name(), 0, 40),
|
||||
"address" => substr($company->settings->address1, 0, 80),
|
||||
"postCode" => substr($this->invoice->client->postal_code, 0, 5),
|
||||
"town" => substr($company->settings->city, 0, 50),
|
||||
"province" => substr($company->settings->state, 0, 20),
|
||||
"countryCode" => $company->country()->iso_3166_3, // Se asume España si se omite
|
||||
"book" => "0", // Libro
|
||||
"merchantRegister" => "RG", // Registro Mercantil
|
||||
"sheet" => "1", // Hoja
|
||||
"folio" => "2", // Folio
|
||||
"section" => "3", // Sección
|
||||
"volume" => "4", // Tomo
|
||||
"email" => substr($company->settings->email, 0, 60),
|
||||
"phone" => substr($company->settings->phone, 0, 15),
|
||||
"fax" => "",
|
||||
"website" => substr($company->settings->website, 0, 50),
|
||||
"contactPeople" => substr($company->owner()->present()->name(), 0, 40),
|
||||
// "cnoCnae" => "04647", // Clasif. Nacional de Act. Económicas
|
||||
// "ineTownCode" => "280796" // Cód. de municipio del INE
|
||||
]);
|
||||
|
||||
|
||||
$this->fac->setSeller($seller);
|
||||
|
||||
return $this;
|
||||
@ -291,19 +296,19 @@ class FacturaEInvoice extends AbstractService
|
||||
$buyer = new FacturaeParty([
|
||||
"isLegalEntity" => $this->invoice->client->has_valid_vat_number,
|
||||
"taxNumber" => $this->invoice->client->vat_number,
|
||||
"name" => $this->invoice->client->present()->name(),
|
||||
"firstSurname" => $this->invoice->client->present()->first_name(),
|
||||
"lastSurname" => $this->invoice->client->present()->last_name(),
|
||||
"address" => $this->invoice->client->address1,
|
||||
"postCode" => $this->invoice->client->postal_code,
|
||||
"town" => $this->invoice->client->city,
|
||||
"province" => $this->invoice->client->state,
|
||||
"name" => substr($this->invoice->client->present()->name(),0, 40),
|
||||
"firstSurname" => substr($this->invoice->client->present()->first_name(),0, 40),
|
||||
"lastSurname" => substr($this->invoice->client->present()->last_name(),0, 40),
|
||||
"address" => substr($this->invoice->client->address1,0, 80),
|
||||
"postCode" => substr($this->invoice->client->postal_code,0,5),
|
||||
"town" => substr($this->invoice->client->city,0, 50),
|
||||
"province" => substr($this->invoice->client->state,0, 20),
|
||||
"countryCode" => $this->invoice->client->country->iso_3166_3, // Se asume España si se omite
|
||||
"email" => $this->invoice->client->present()->email(),
|
||||
"phone" => $this->invoice->client->present()->phone(),
|
||||
"email" => substr($this->invoice->client->present()->email(),0, 60),
|
||||
"phone" => substr($this->invoice->client->present()->phone(),0, 15),
|
||||
"fax" => "",
|
||||
"website" => $this->invoice->client->present()->website(),
|
||||
"contactPeople" => $this->invoice->client->present()->first_name()." ".$this->invoice->client->present()->last_name(),
|
||||
"website" => substr($this->invoice->client->present()->website(), 0 ,60),
|
||||
"contactPeople" => substr($this->invoice->client->present()->first_name()." ".$this->invoice->client->present()->last_name(), 0, 40),
|
||||
// "cnoCnae" => "04791", // Clasif. Nacional de Act. Económicas
|
||||
// "ineTownCode" => "280796" // Cód. de municipio del INE
|
||||
]);
|
||||
@ -317,7 +322,7 @@ class FacturaEInvoice extends AbstractService
|
||||
{
|
||||
// $ssl_cert = file_get_contents(base_path('e_invoice_cert.p12'));
|
||||
|
||||
// $this->fac->sign($ssl_cert, null, "SuperSecrethere");
|
||||
// $this->fac->sign($ssl_cert, null, "SuperSecretPassword");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -254,24 +254,41 @@ class Design extends BaseDesign
|
||||
return $elements;
|
||||
}
|
||||
|
||||
$elements = [
|
||||
['element' => 'p', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']],
|
||||
['element' => 'p', 'content' => $this->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.name']],
|
||||
['element' => 'p', 'content' => $this->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address1']],
|
||||
['element' => 'p', 'content' => $this->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address2']],
|
||||
['element' => 'p', 'show_empty' => false, 'elements' => [
|
||||
['element' => 'span', 'content' => "{$this->client->shipping_city} ", 'properties' => ['ref' => 'shipping_address-client.shipping_city']],
|
||||
['element' => 'span', 'content' => "{$this->client->shipping_state} ", 'properties' => ['ref' => 'shipping_address-client.shipping_state']],
|
||||
['element' => 'span', 'content' => "{$this->client->shipping_postal_code} ", 'properties' => ['ref' => 'shipping_address-client.shipping_postal_code']],
|
||||
]],
|
||||
['element' => 'p', 'content' => optional($this->client->shipping_country)->name, 'show_empty' => false],
|
||||
// $elements = [
|
||||
// ['element' => 'p', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']],
|
||||
// ['element' => 'p', 'content' => $this->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.name']],
|
||||
// ['element' => 'p', 'content' => $this->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address1']],
|
||||
// ['element' => 'p', 'content' => $this->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address2']],
|
||||
// ['element' => 'p', 'show_empty' => false, 'elements' => [
|
||||
// ['element' => 'span', 'content' => "{$this->client->shipping_city} ", 'properties' => ['ref' => 'shipping_address-client.shipping_city']],
|
||||
// ['element' => 'span', 'content' => "{$this->client->shipping_state} ", 'properties' => ['ref' => 'shipping_address-client.shipping_state']],
|
||||
// ['element' => 'span', 'content' => "{$this->client->shipping_postal_code} ", 'properties' => ['ref' => 'shipping_address-client.shipping_postal_code']],
|
||||
// ]],
|
||||
// ['element' => 'p', 'content' => optional($this->client->shipping_country)->name, 'show_empty' => false],
|
||||
// ];
|
||||
|
||||
$address_variables = [
|
||||
'$client.address1',
|
||||
'$client.address2',
|
||||
'$client.city_state_postal',
|
||||
'$client.country',
|
||||
'$client.postal_city_state',
|
||||
'$client.postal_city',
|
||||
];
|
||||
|
||||
// if (!is_null($this->context['contact'])) {
|
||||
// $elements[] = ['element' => 'p', 'content' => $this->context['contact']->email, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-contact.email']];
|
||||
// }
|
||||
$variables = $this->context['pdf_variables']['client_details'];
|
||||
|
||||
$elements = collect($variables)->filter(function ($variable) use ($address_variables){
|
||||
return in_array($variable, $address_variables);
|
||||
})->map(function ($variable){
|
||||
|
||||
$variable = str_replace('$client.', '$client.shipping_', $variable);
|
||||
return ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => "client_details-shipping-" . substr($variable, 1)]];
|
||||
|
||||
})->toArray();
|
||||
|
||||
return $elements;
|
||||
|
||||
}
|
||||
|
||||
public function clientDetails(): array
|
||||
@ -312,71 +329,72 @@ class Design extends BaseDesign
|
||||
return $elements;
|
||||
}
|
||||
|
||||
public function entityDetailsx(): array
|
||||
{
|
||||
if ($this->type === 'statement') {
|
||||
$s_date = $this->translateDate($this->options['start_date'], $this->client->date_format(), $this->client->locale()) . " - " . $this->translateDate($this->options['end_date'], $this->client->date_format(), $this->client->locale());
|
||||
//@deprecated
|
||||
// public function entityDetailsx(): array
|
||||
// {
|
||||
// if ($this->type === 'statement') {
|
||||
// $s_date = $this->translateDate($this->options['start_date'], $this->client->date_format(), $this->client->locale()) . " - " . $this->translateDate($this->options['end_date'], $this->client->date_format(), $this->client->locale());
|
||||
|
||||
return [
|
||||
['element' => 'p', 'content' => "<h2>".ctrans('texts.statement')."</h2>", 'properties' => ['data-ref' => 'statement-label']],
|
||||
['element' => 'p', 'content' => ctrans('texts.statement_date'), 'properties' => ['data-ref' => 'statement-label'],'elements' =>
|
||||
['element' => 'span', 'content' => "{$s_date} "]
|
||||
],
|
||||
['element' => 'p', 'content' => '$balance_due_label', 'properties' => ['data-ref' => 'statement-label'],'elements' =>
|
||||
['element' => 'span', 'content' => Number::formatMoney($this->invoices->sum('balance'), $this->client)]
|
||||
],
|
||||
];
|
||||
}
|
||||
// return [
|
||||
// ['element' => 'p', 'content' => "<h2>".ctrans('texts.statement')."</h2>", 'properties' => ['data-ref' => 'statement-label']],
|
||||
// ['element' => 'p', 'content' => ctrans('texts.statement_date'), 'properties' => ['data-ref' => 'statement-label'],'elements' =>
|
||||
// ['element' => 'span', 'content' => "{$s_date} "]
|
||||
// ],
|
||||
// ['element' => 'p', 'content' => '$balance_due_label', 'properties' => ['data-ref' => 'statement-label'],'elements' =>
|
||||
// ['element' => 'span', 'content' => Number::formatMoney($this->invoices->sum('balance'), $this->client)]
|
||||
// ],
|
||||
// ];
|
||||
// }
|
||||
|
||||
$variables = $this->context['pdf_variables']['invoice_details'];
|
||||
// $variables = $this->context['pdf_variables']['invoice_details'];
|
||||
|
||||
if ($this->entity instanceof Quote) {
|
||||
$variables = $this->context['pdf_variables']['quote_details'];
|
||||
// if ($this->entity instanceof Quote) {
|
||||
// $variables = $this->context['pdf_variables']['quote_details'];
|
||||
|
||||
if ($this->entity->partial > 0) {
|
||||
$variables[] = '$quote.balance_due';
|
||||
}
|
||||
}
|
||||
// if ($this->entity->partial > 0) {
|
||||
// $variables[] = '$quote.balance_due';
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($this->entity instanceof Credit) {
|
||||
$variables = $this->context['pdf_variables']['credit_details'];
|
||||
}
|
||||
// if ($this->entity instanceof Credit) {
|
||||
// $variables = $this->context['pdf_variables']['credit_details'];
|
||||
// }
|
||||
|
||||
if ($this->vendor) {
|
||||
$variables = $this->context['pdf_variables']['purchase_order_details'];
|
||||
}
|
||||
// if ($this->vendor) {
|
||||
// $variables = $this->context['pdf_variables']['purchase_order_details'];
|
||||
// }
|
||||
|
||||
$elements = [];
|
||||
// $elements = [];
|
||||
|
||||
// We don't want to show account balance or invoice total on PDF.. or any amount with currency.
|
||||
if ($this->type == self::DELIVERY_NOTE) {
|
||||
$variables = array_filter($variables, function ($m) {
|
||||
return !in_array($m, ['$invoice.balance_due', '$invoice.total']);
|
||||
});
|
||||
}
|
||||
// // We don't want to show account balance or invoice total on PDF.. or any amount with currency.
|
||||
// if ($this->type == self::DELIVERY_NOTE) {
|
||||
// $variables = array_filter($variables, function ($m) {
|
||||
// return !in_array($m, ['$invoice.balance_due', '$invoice.total']);
|
||||
// });
|
||||
// }
|
||||
|
||||
foreach ($variables as $variable) {
|
||||
$_variable = explode('.', $variable)[1];
|
||||
$_customs = ['custom1', 'custom2', 'custom3', 'custom4'];
|
||||
// foreach ($variables as $variable) {
|
||||
// $_variable = explode('.', $variable)[1];
|
||||
// $_customs = ['custom1', 'custom2', 'custom3', 'custom4'];
|
||||
|
||||
/* 2/7/2022 don't show custom values if they are empty */
|
||||
$var = str_replace("custom", "custom_value", $_variable);
|
||||
// /* 2/7/2022 don't show custom values if they are empty */
|
||||
// $var = str_replace("custom", "custom_value", $_variable);
|
||||
|
||||
if (in_array($_variable, $_customs) && !empty($this->entity->{$var})) {
|
||||
$elements[] = ['element' => 'div', 'properties' => ['style' => "display: table-row; visibility: {$this->entityVariableCheck($_variable)};"],'elements' => [
|
||||
['element' => 'div', 'content' => $variable . '_label', 'properties' => ['class' => 'entity-details-cell', 'data-ref' => 'entity_details-' . substr($variable, 1) . '_label']],
|
||||
['element' => 'div', 'content' => $variable, 'properties' => ['class' => 'entity-details-cell', 'data-ref' => 'entity_details-' . substr($variable, 1)]],
|
||||
]];
|
||||
} else {
|
||||
$elements[] = ['element' => 'div', 'properties' => ['style' => "display: table-row; visibility: {$this->entityVariableCheck($variable)};"], 'elements' => [
|
||||
['element' => 'div', 'content' => $variable . '_label', 'properties' => ['class' => 'entity-details-cell','data-ref' => 'entity_details-' . substr($variable, 1) . '_label']],
|
||||
['element' => 'div', 'content' => $variable, 'properties' => ['class' => 'entity-details-cell','data-ref' => 'entity_details-' . substr($variable, 1)]],
|
||||
]];
|
||||
}
|
||||
}
|
||||
// if (in_array($_variable, $_customs) && !empty($this->entity->{$var})) {
|
||||
// $elements[] = ['element' => 'div', 'properties' => ['style' => "display: table-row; visibility: {$this->entityVariableCheck($_variable)};"],'elements' => [
|
||||
// ['element' => 'div', 'content' => $variable . '_label', 'properties' => ['class' => 'entity-details-cell', 'data-ref' => 'entity_details-' . substr($variable, 1) . '_label']],
|
||||
// ['element' => 'div', 'content' => $variable, 'properties' => ['class' => 'entity-details-cell', 'data-ref' => 'entity_details-' . substr($variable, 1)]],
|
||||
// ]];
|
||||
// } else {
|
||||
// $elements[] = ['element' => 'div', 'properties' => ['style' => "display: table-row; visibility: {$this->entityVariableCheck($variable)};"], 'elements' => [
|
||||
// ['element' => 'div', 'content' => $variable . '_label', 'properties' => ['class' => 'entity-details-cell','data-ref' => 'entity_details-' . substr($variable, 1) . '_label']],
|
||||
// ['element' => 'div', 'content' => $variable, 'properties' => ['class' => 'entity-details-cell','data-ref' => 'entity_details-' . substr($variable, 1)]],
|
||||
// ]];
|
||||
// }
|
||||
// }
|
||||
|
||||
return $elements;
|
||||
}
|
||||
// return $elements;
|
||||
// }
|
||||
|
||||
public function entityDetails(): array
|
||||
{
|
||||
|
@ -12,18 +12,15 @@
|
||||
namespace App\Services\Tax;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Services\Tax\Providers\ZipTax;
|
||||
|
||||
|
||||
class TaxService
|
||||
{
|
||||
|
||||
public function __construct(protected Company $company, protected Client $client)
|
||||
public function __construct(public Client $client)
|
||||
{
|
||||
}
|
||||
|
||||
private function validateVat(): self
|
||||
public function validateVat(): self
|
||||
{
|
||||
$client_country_code = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : $this->client->country->iso_3166_2;
|
||||
|
||||
|
@ -460,6 +460,12 @@ class HtmlEngine
|
||||
$data['$client.shipping_state'] = ['value' => $this->client->shipping_state ?: ' ', 'label' => ctrans('texts.shipping_state')];
|
||||
$data['$client.shipping_postal_code'] = ['value' => $this->client->shipping_postal_code ?: ' ', 'label' => ctrans('texts.shipping_postal_code')];
|
||||
$data['$client.shipping_country'] = ['value' => isset($this->client->shipping_country->name) ? ctrans('texts.country_' . $this->client->shipping_country->name) : '', 'label' => ctrans('texts.shipping_country')];
|
||||
$data['$shipping_postal_city_state'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, $this->client->shipping_state, $this->client->shipping_postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
|
||||
$data['$client.shipping_postal_city_state'] = &$data['$shipping_postal_city_state'];
|
||||
$data['$shipping_postal_city'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, null, $this->client->shipping_postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city')];
|
||||
$data['$client.shipping_postal_city'] = &$data['$shipping_postal_city'];
|
||||
$data['$shipping_city_state_postal'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, $this->client->shipping_state, $this->client->shipping_postal_code, false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
|
||||
$data['$client.shipping_city_state_postal'] = &$data['$shipping_city_state_postal'];
|
||||
|
||||
$data['$client.currency'] = ['value' => $this->client->currency()->code, 'label' => ''];
|
||||
|
||||
|
@ -16907,9 +16907,10 @@ components:
|
||||
type: number
|
||||
example: 8.00
|
||||
line_items:
|
||||
description: "Array of line items included in the invoice"
|
||||
type: object
|
||||
example: "[{item1}, {item2}]"
|
||||
type: array
|
||||
description: 'An array of objects which define the line items of the invoice'
|
||||
items:
|
||||
$ref: '#/components/schemas/InvoiceItem'
|
||||
discount:
|
||||
description: "The discount applied to the invoice"
|
||||
type: number
|
||||
@ -17324,83 +17325,116 @@ components:
|
||||
quantity:
|
||||
type: integer
|
||||
example: 1
|
||||
description: 'The quantity of the product offered for this line item'
|
||||
cost:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The cost of the product offered for this line item'
|
||||
product_key:
|
||||
type: string
|
||||
example: 'Product key'
|
||||
description: 'The product key of the product offered for this line item (Referred to as Product in the product tab)'
|
||||
product_cost:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The cost of the product offered for this line item (Referred to as Cost in the product tab)'
|
||||
notes:
|
||||
type: string
|
||||
example: 'Item notes'
|
||||
description: 'The notes/description for the product offered for this line item'
|
||||
discount:
|
||||
type: number
|
||||
format: float
|
||||
example: 5.00
|
||||
description: 'The discount applied to the product offered for this line item'
|
||||
is_amount_discount:
|
||||
type: boolean
|
||||
example: false
|
||||
description: 'Indicates whether the discount applied to the product offered for this line item is a fixed amount or a percentage'
|
||||
tax_name1:
|
||||
type: string
|
||||
example: 'Tax name 1'
|
||||
example: 'GST'
|
||||
description: 'The name of the first tax applied to the product offered for this line item'
|
||||
tax_rate1:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The rate of the first tax applied to the product offered for this line item'
|
||||
tax_name2:
|
||||
type: string
|
||||
example: 'Tax name 2'
|
||||
example: 'VAT'
|
||||
description: 'The name of the second tax applied to the product offered for this line item'
|
||||
tax_rate2:
|
||||
type: number
|
||||
format: float
|
||||
example: 5.00
|
||||
description: 'The rate of the second tax applied to the product offered for this line item'
|
||||
tax_name3:
|
||||
type: string
|
||||
example: 'Tax name 3'
|
||||
example: 'CA Sales Tax'
|
||||
description: 'The name of the third tax applied to the product offered for this line item'
|
||||
tax_rate3:
|
||||
type: number
|
||||
format: float
|
||||
example: 3.00
|
||||
description: 'The rate of the third tax applied to the product offered for this line item'
|
||||
sort_id:
|
||||
type: string
|
||||
example: '0'
|
||||
description: 'Deprecated'
|
||||
deprecated: true
|
||||
line_total:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The total amount of the product offered for this line item'
|
||||
readOnly: true
|
||||
gross_line_total:
|
||||
type: number
|
||||
format: float
|
||||
example: 15.00
|
||||
description: 'The total amount of the product offered for this line item before discounts'
|
||||
readOnly: true
|
||||
tax_amount:
|
||||
type: number
|
||||
format: float
|
||||
example: 1.00
|
||||
description: 'The total amount of tax applied to the product offered for this line item'
|
||||
readOnly: true
|
||||
date:
|
||||
type: string
|
||||
format: date-time
|
||||
example: '2023-03-19T00:00:00Z'
|
||||
description: 'Deprecated'
|
||||
deprecated: true
|
||||
custom_value1:
|
||||
type: string
|
||||
example: 'Custom value 1'
|
||||
description: 'The first custom value of the product offered for this line item'
|
||||
custom_value2:
|
||||
type: string
|
||||
example: 'Custom value 2'
|
||||
description: 'The second custom value of the product offered for this line item'
|
||||
custom_value3:
|
||||
type: string
|
||||
example: 'Custom value 3'
|
||||
description: 'The third custom value of the product offered for this line item'
|
||||
custom_value4:
|
||||
type: string
|
||||
example: 'Custom value 4'
|
||||
description: 'The fourth custom value of the product offered for this line item'
|
||||
type_id:
|
||||
type: string
|
||||
example: '1'
|
||||
description: '1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense'
|
||||
default: '1'
|
||||
tax_id:
|
||||
type: string
|
||||
example: '1'
|
||||
default: '1'
|
||||
description: 'The tax ID of the product: 1 product, 2 service, 3 digital, 4 shipping, 5 exempt, 5 reduced tax, 7 override, 8 zero rate, 9 reverse tax'
|
||||
CompanyUser:
|
||||
properties:
|
||||
permissions:
|
||||
@ -19431,17 +19465,17 @@ components:
|
||||
cost:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The cost of the product.'
|
||||
description: 'The cost of the product. (Your purchase price for this product)'
|
||||
example: 10.0
|
||||
price:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The price of the product.'
|
||||
description: 'The price of the product that you are charging.'
|
||||
example: 20.0
|
||||
quantity:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The quantity of the product.'
|
||||
description: 'The quantity of the product. (used as a default)'
|
||||
example: 5.0
|
||||
tax_name1:
|
||||
type: string
|
||||
|
@ -73,9 +73,10 @@
|
||||
type: number
|
||||
example: 8.00
|
||||
line_items:
|
||||
description: "Array of line items included in the invoice"
|
||||
type: object
|
||||
example: "[{item1}, {item2}]"
|
||||
type: array
|
||||
description: 'An array of objects which define the line items of the invoice'
|
||||
items:
|
||||
$ref: '#/components/schemas/InvoiceItem'
|
||||
discount:
|
||||
description: "The discount applied to the invoice"
|
||||
type: number
|
||||
|
@ -4,80 +4,113 @@
|
||||
quantity:
|
||||
type: integer
|
||||
example: 1
|
||||
description: 'The quantity of the product offered for this line item'
|
||||
cost:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The cost of the product offered for this line item'
|
||||
product_key:
|
||||
type: string
|
||||
example: 'Product key'
|
||||
description: 'The product key of the product offered for this line item (Referred to as Product in the product tab)'
|
||||
product_cost:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The cost of the product offered for this line item (Referred to as Cost in the product tab)'
|
||||
notes:
|
||||
type: string
|
||||
example: 'Item notes'
|
||||
description: 'The notes/description for the product offered for this line item'
|
||||
discount:
|
||||
type: number
|
||||
format: float
|
||||
example: 5.00
|
||||
description: 'The discount applied to the product offered for this line item'
|
||||
is_amount_discount:
|
||||
type: boolean
|
||||
example: false
|
||||
description: 'Indicates whether the discount applied to the product offered for this line item is a fixed amount or a percentage'
|
||||
tax_name1:
|
||||
type: string
|
||||
example: 'Tax name 1'
|
||||
example: 'GST'
|
||||
description: 'The name of the first tax applied to the product offered for this line item'
|
||||
tax_rate1:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The rate of the first tax applied to the product offered for this line item'
|
||||
tax_name2:
|
||||
type: string
|
||||
example: 'Tax name 2'
|
||||
example: 'VAT'
|
||||
description: 'The name of the second tax applied to the product offered for this line item'
|
||||
tax_rate2:
|
||||
type: number
|
||||
format: float
|
||||
example: 5.00
|
||||
description: 'The rate of the second tax applied to the product offered for this line item'
|
||||
tax_name3:
|
||||
type: string
|
||||
example: 'Tax name 3'
|
||||
example: 'CA Sales Tax'
|
||||
description: 'The name of the third tax applied to the product offered for this line item'
|
||||
tax_rate3:
|
||||
type: number
|
||||
format: float
|
||||
example: 3.00
|
||||
description: 'The rate of the third tax applied to the product offered for this line item'
|
||||
sort_id:
|
||||
type: string
|
||||
example: '0'
|
||||
description: 'Deprecated'
|
||||
deprecated: true
|
||||
line_total:
|
||||
type: number
|
||||
format: float
|
||||
example: 10.00
|
||||
description: 'The total amount of the product offered for this line item'
|
||||
readOnly: true
|
||||
gross_line_total:
|
||||
type: number
|
||||
format: float
|
||||
example: 15.00
|
||||
description: 'The total amount of the product offered for this line item before discounts'
|
||||
readOnly: true
|
||||
tax_amount:
|
||||
type: number
|
||||
format: float
|
||||
example: 1.00
|
||||
description: 'The total amount of tax applied to the product offered for this line item'
|
||||
readOnly: true
|
||||
date:
|
||||
type: string
|
||||
format: date-time
|
||||
example: '2023-03-19T00:00:00Z'
|
||||
description: 'Deprecated'
|
||||
deprecated: true
|
||||
custom_value1:
|
||||
type: string
|
||||
example: 'Custom value 1'
|
||||
description: 'The first custom value of the product offered for this line item'
|
||||
custom_value2:
|
||||
type: string
|
||||
example: 'Custom value 2'
|
||||
description: 'The second custom value of the product offered for this line item'
|
||||
custom_value3:
|
||||
type: string
|
||||
example: 'Custom value 3'
|
||||
description: 'The third custom value of the product offered for this line item'
|
||||
custom_value4:
|
||||
type: string
|
||||
example: 'Custom value 4'
|
||||
description: 'The fourth custom value of the product offered for this line item'
|
||||
type_id:
|
||||
type: string
|
||||
example: '1'
|
||||
description: '1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense'
|
||||
description: '1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense'
|
||||
default: '1'
|
||||
tax_id:
|
||||
type: string
|
||||
example: '1'
|
||||
default: '1'
|
||||
description: 'The tax ID of the product: 1 product, 2 service, 3 digital, 4 shipping, 5 exempt, 5 reduced tax, 7 override, 8 zero rate, 9 reverse tax'
|
@ -55,17 +55,17 @@
|
||||
cost:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The cost of the product.'
|
||||
description: 'The cost of the product. (Your purchase price for this product)'
|
||||
example: 10.0
|
||||
price:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The price of the product.'
|
||||
description: 'The price of the product that you are charging.'
|
||||
example: 20.0
|
||||
quantity:
|
||||
type: number
|
||||
format: double
|
||||
description: 'The quantity of the product.'
|
||||
description: 'The quantity of the product. (used as a default)'
|
||||
example: 5.0
|
||||
tax_name1:
|
||||
type: string
|
||||
|
@ -28,7 +28,7 @@
|
||||
margin-left: $global_margin;
|
||||
margin-right: $global_margin;
|
||||
margin-top: 5;
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 5;
|
||||
size: $page_size $page_layout;
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,14 @@
|
||||
|
||||
namespace Tests\Feature\EInvoice;
|
||||
|
||||
use App\Services\Invoice\EInvoice\FacturaEInvoice;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
use Tests\MockAccountData;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Services\Invoice\EInvoice\FacturaEInvoice;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
use function Amp\Iterator\toArray;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -40,10 +43,95 @@ class FacturaeTest extends TestCase
|
||||
{
|
||||
|
||||
$f = new FacturaEInvoice($this->invoice, "3.2.2");
|
||||
$f->run();
|
||||
$path = $f->run();
|
||||
|
||||
$this->assertNotNull($f->run());
|
||||
|
||||
nlog($f->run());
|
||||
|
||||
// $this->assertTrue($this->validateInvoiceXML($path));
|
||||
}
|
||||
|
||||
|
||||
// protected function validateInvoiceXML($path, $validateSignature=false) {
|
||||
// // Prepare file to upload
|
||||
// if (function_exists('curl_file_create')) {
|
||||
// $postFile = curl_file_create($path);
|
||||
// } else {
|
||||
// $postFile = "@" . realpath($path);
|
||||
// }
|
||||
|
||||
// // Send upload request
|
||||
// $ch = curl_init();
|
||||
// curl_setopt_array($ch, array(
|
||||
// CURLOPT_RETURNTRANSFER => true,
|
||||
// CURLOPT_FOLLOWLOCATION => true,
|
||||
// CURLOPT_URL => "http://plataforma.firma-e.com/VisualizadorFacturae/index2.jsp",
|
||||
// CURLOPT_POST => 1,
|
||||
// CURLOPT_POSTFIELDS => array(
|
||||
// "referencia" => $postFile,
|
||||
// "valContable" => "on",
|
||||
// "valFirma" => $validateSignature ? "on" : "off",
|
||||
// "aceptarCondiciones" => "on",
|
||||
// "submit" => "Siguiente"
|
||||
// ),
|
||||
// CURLOPT_COOKIEJAR => base_path()."/cookie.txt"
|
||||
// ));
|
||||
// $res = curl_exec($ch);
|
||||
// curl_close($ch);
|
||||
// unset($ch);
|
||||
|
||||
// nlog($res);
|
||||
|
||||
// if (strpos($res, "window.open('facturae.jsp'") === false) {
|
||||
// $this->expectException(\UnexpectedValueException::class);
|
||||
// }
|
||||
|
||||
// // Fetch results
|
||||
// $ch = curl_init();
|
||||
// curl_setopt_array($ch, array(
|
||||
// CURLOPT_RETURNTRANSFER => true,
|
||||
// CURLOPT_FOLLOWLOCATION => true,
|
||||
// CURLOPT_URL => "http://plataforma.firma-e.com/VisualizadorFacturae/facturae.jsp",
|
||||
// CURLOPT_COOKIEFILE => base_path()."/cookie.txt"
|
||||
// ));
|
||||
// $res = curl_exec($ch);
|
||||
// curl_close($ch);
|
||||
// unset($ch);
|
||||
|
||||
// nlog($res);
|
||||
|
||||
// // Validate results
|
||||
// $this->assertNotEmpty($res, 'Invalid Validator Response');
|
||||
// $this->assertNotEmpty(strpos($res, 'euro_ok.png'), 'Invalid XML Format');
|
||||
// if ($validateSignature) {
|
||||
// $this->assertNotEmpty(strpos($res, '>Nivel de Firma Válido<'), 'Invalid Signature');
|
||||
// }
|
||||
// if (strpos($res, '>Sellos de Tiempo<') !== false) {
|
||||
// $this->assertNotEmpty(strpos($res, '>XAdES_T<'), 'Invalid Timestamp');
|
||||
// }
|
||||
// }
|
||||
|
||||
// private function validateInvoiceXML($path)
|
||||
// {
|
||||
// $client = new \GuzzleHttp\Client(['cookies' => true]);
|
||||
|
||||
// $response = $client->request('POST', 'https://face.gob.es/api/v1/herramientas/validador',[
|
||||
// 'multipart' => [
|
||||
// [
|
||||
// 'name' => 'validador[factura]',
|
||||
// 'contents' => Storage::get($path),
|
||||
// ],
|
||||
// ]
|
||||
// ]);
|
||||
|
||||
// $response = $client->request('POST', 'http://plataforma.firma-e.com/VisualizadorFacturae/facturae.jsp');
|
||||
// $body = $response->getBody();
|
||||
// $stringBody = (string) $body;
|
||||
|
||||
// echo print_r($stringBody,1);
|
||||
|
||||
|
||||
// }
|
||||
|
||||
}
|
@ -11,19 +11,21 @@
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use App\Http\Middleware\PasswordProtection;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
use App\Models\User;
|
||||
use App\Models\Account;
|
||||
use App\Models\Company;
|
||||
use Tests\MockAccountData;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Models\CompanyToken;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use App\Http\Middleware\PasswordProtection;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -56,6 +58,64 @@ class UserTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testUserAttemptingtToDeleteThemselves()
|
||||
{
|
||||
|
||||
|
||||
$account = Account::factory()->create([
|
||||
'hosted_client_count' => 1000,
|
||||
'hosted_company_count' => 1000,
|
||||
]);
|
||||
|
||||
$account->num_users = 3;
|
||||
$account->save();
|
||||
|
||||
$user = User::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'confirmation_code' => 'xyz123',
|
||||
'email' => $this->faker->unique()->safeEmail(),
|
||||
]);
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->client_online_payment_notification = false;
|
||||
$settings->client_manual_payment_notification = false;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
|
||||
$cu = CompanyUserFactory::create($user->id, $company->id, $account->id);
|
||||
$cu->is_owner = true;
|
||||
$cu->is_admin = true;
|
||||
$cu->is_locked = false;
|
||||
$cu->save();
|
||||
|
||||
$token = \Illuminate\Support\Str::random(64);
|
||||
|
||||
$company_token = new CompanyToken();
|
||||
$company_token->user_id = $user->id;
|
||||
$company_token->company_id = $company->id;
|
||||
$company_token->account_id = $account->id;
|
||||
$company_token->name = 'test token';
|
||||
$company_token->token = $token;
|
||||
$company_token->is_system = true;
|
||||
|
||||
$data = [
|
||||
'ids' => [$user->hashed_id],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token,
|
||||
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
|
||||
])->postJson('/api/v1/users/bulk?action=dete', $data)
|
||||
->assertStatus(403);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testDisconnectUserOauthMailer()
|
||||
{
|
||||
$user =
|
||||
|
Loading…
Reference in New Issue
Block a user