mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 20:22:42 +01:00
Merge branch 'v5-develop' into einvoicing-peppol-form-api
Signed-off-by: David Bomba <turbo124@gmail.com>
This commit is contained in:
commit
73364b5707
@ -1 +1 @@
|
||||
5.10.34
|
||||
5.10.42
|
@ -385,9 +385,12 @@ class CreateSingleAccount extends Command
|
||||
|
||||
});
|
||||
|
||||
|
||||
$this->countryClients($company, $user);
|
||||
|
||||
$cc = ClientContact::where('company_id', $company->id)->latest()->first();
|
||||
$cc->email = 'user@example.com';
|
||||
$cc->save();
|
||||
|
||||
$this->info("finished");
|
||||
|
||||
}
|
||||
@ -472,13 +475,13 @@ class CreateSingleAccount extends Command
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
'is_primary' => 1,
|
||||
'email' => 'user@example.com',
|
||||
]);
|
||||
// ClientContact::factory()->create([
|
||||
// 'user_id' => $user->id,
|
||||
// 'client_id' => $client->id,
|
||||
// 'company_id' => $company->id,
|
||||
// 'is_primary' => 1,
|
||||
// 'email' => 'user@example.com',
|
||||
// ]);
|
||||
|
||||
ClientContact::factory()->count(rand(1, 2))->create([
|
||||
'user_id' => $user->id,
|
||||
@ -490,7 +493,6 @@ class CreateSingleAccount extends Command
|
||||
|
||||
$settings = $client->settings;
|
||||
$settings->currency_id = "1";
|
||||
// $settings->use_credits_payment = "always";
|
||||
|
||||
$client->settings = $settings;
|
||||
|
||||
|
@ -11,15 +11,18 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||
use App\Models\Invoice;
|
||||
use App\Libraries\MultiDB;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||
|
||||
class TypeCheck extends Command
|
||||
{
|
||||
use ClientGroupSettingsSaver;
|
||||
use CleanLineItems;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
@ -126,6 +129,13 @@ class TypeCheck extends Command
|
||||
$this->logMessage("Checking company {$company->id}");
|
||||
$company->saveSettings($company->settings, $company);
|
||||
});
|
||||
|
||||
Invoice::query()->cursor()->each(function ($invoice){
|
||||
$this->logMessage("Checking invoice {$invoice->id}");
|
||||
$invoice->line_items = $this->cleanItems($invoice->line_items);
|
||||
$invoice->saveQuietly();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private function logMessage($str)
|
||||
|
@ -35,7 +35,7 @@ class TaxModel
|
||||
$this->regions = $this->init();
|
||||
} else {
|
||||
|
||||
if(is_null($model->seller_subregion)) {
|
||||
if(is_null($model->seller_subregion)) {//@phpstan-ignore-line
|
||||
$this->seller_subregion = '';
|
||||
}
|
||||
|
||||
|
@ -11,17 +11,21 @@
|
||||
|
||||
namespace App\Events\Credit;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Credit;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultResourceBroadcast;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CreditWasCreated
|
||||
class CreditWasCreated implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithSockets;
|
||||
use SerializesModels;
|
||||
use DefaultResourceBroadcast;
|
||||
|
||||
public $credit;
|
||||
|
||||
@ -41,5 +45,12 @@ class CreditWasCreated
|
||||
$this->credit = $credit;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
|
||||
$this->dontBroadcastToCurrentUser();
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
return $this->credit;
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,21 @@
|
||||
|
||||
namespace App\Events\Credit;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Credit;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultResourceBroadcast;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CreditWasUpdated
|
||||
class CreditWasUpdated implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithSockets;
|
||||
use SerializesModels;
|
||||
use DefaultResourceBroadcast;
|
||||
|
||||
public $credit;
|
||||
|
||||
@ -41,5 +45,12 @@ class CreditWasUpdated
|
||||
$this->credit = $credit;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
|
||||
$this->dontBroadcastToCurrentUser();
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
return $this->credit;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,11 @@
|
||||
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultInvoiceBroadcast;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultResourceBroadcast;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
@ -25,7 +26,7 @@ use Illuminate\Queue\SerializesModels;
|
||||
*/
|
||||
class InvoiceWasPaid implements ShouldBroadcast
|
||||
{
|
||||
use SerializesModels, DefaultInvoiceBroadcast, InteractsWithSockets;
|
||||
use SerializesModels, DefaultResourceBroadcast, InteractsWithSockets;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
@ -39,4 +40,9 @@ class InvoiceWasPaid implements ShouldBroadcast
|
||||
{
|
||||
$this->dontBroadcastToCurrentUser();
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
return $this->invoice;
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,23 @@
|
||||
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultResourceBroadcast;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use League\Fractal\Manager;
|
||||
|
||||
/**
|
||||
* Class InvoiceWasViewed.
|
||||
*/
|
||||
class InvoiceWasViewed
|
||||
class InvoiceWasViewed implements ShouldBroadcast
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
use InteractsWithSockets;
|
||||
use DefaultResourceBroadcast;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
@ -32,5 +38,18 @@ class InvoiceWasViewed
|
||||
*/
|
||||
public function __construct(public InvoiceInvitation $invitation, public Company $company, public array $event_vars)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
return $this->invitation->invoice;
|
||||
}
|
||||
|
||||
public function broadcastManager(Manager $manager): Manager
|
||||
{
|
||||
$manager->parseIncludes('client');
|
||||
|
||||
return $manager;
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,20 @@
|
||||
|
||||
namespace App\Events\Payment;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Traits\Invoice\Broadcasting\DefaultResourceBroadcast;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PaymentWasUpdated.
|
||||
*/
|
||||
class PaymentWasUpdated
|
||||
class PaymentWasUpdated implements ShouldBroadcast
|
||||
{
|
||||
use SerializesModels;
|
||||
use SerializesModels, InteractsWithSockets, DefaultResourceBroadcast;
|
||||
|
||||
/**
|
||||
* @var Payment
|
||||
@ -43,5 +47,12 @@ class PaymentWasUpdated
|
||||
$this->payment = $payment;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
|
||||
$this->dontBroadcastToCurrentUser();
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
return $this->payment;
|
||||
}
|
||||
}
|
||||
|
@ -62,10 +62,9 @@ class TaskExport extends BaseExport
|
||||
|
||||
if (count($this->input['report_keys']) == 0) {
|
||||
$this->input['report_keys'] = array_values($this->task_report_keys);
|
||||
$this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys']));
|
||||
}
|
||||
|
||||
$this->input['report_keys'] = array_merge($this->input['report_keys'], array_diff($this->forced_client_fields, $this->input['report_keys']));
|
||||
|
||||
$query = Task::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id);
|
||||
@ -207,15 +206,23 @@ class TaskExport extends BaseExport
|
||||
$entity['task.end_time'] = ctrans('texts.is_running');
|
||||
}
|
||||
|
||||
$seconds = $task->calcDuration();
|
||||
$time_log_entry = (isset($item[1]) && $item[1] != 0) ? $item[1] - $item[0] : ctrans('texts.is_running');
|
||||
|
||||
if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) {
|
||||
$seconds = $task->calcDuration();
|
||||
$entity['task.duration'] = $seconds;
|
||||
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
|
||||
}
|
||||
|
||||
$time_log_entry = (isset($item[1]) && $item[1] != 0) ? $item[1] - $item[0] : ctrans('texts.is_running');
|
||||
if (in_array('task.time_log', $this->input['report_keys']) || in_array('time_log', $this->input['report_keys'])) {
|
||||
$entity['task.time_log'] = $time_log_entry;
|
||||
$entity['task.time_log_duration_words'] = is_int($time_log_entry) && $time_log_entry > 86400 ? CarbonInterval::seconds($time_log_entry)->locale($this->company->locale())->cascade()->forHumans() : $time_log_entry;
|
||||
}
|
||||
|
||||
if (in_array('task.time_log_duration_words', $this->input['report_keys']) || in_array('time_log_duration_words', $this->input['report_keys'])) {
|
||||
$entity['task.time_log_duration_words'] = is_int($time_log_entry) ? CarbonInterval::seconds($time_log_entry)->locale($this->company->locale())->cascade()->forHumans() : $time_log_entry;
|
||||
}
|
||||
|
||||
if (in_array('task.duration_words', $this->input['report_keys']) || in_array('duration_words', $this->input['report_keys'])) {
|
||||
$entity['task.duration_words'] = $seconds > 86400 ? CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans() : now()->startOfDay()->addSeconds($seconds)->format('H:i:s');
|
||||
}
|
||||
|
||||
if (in_array('task.billable', $this->input['report_keys']) || in_array('billable', $this->input['report_keys'])) {
|
||||
@ -227,7 +234,6 @@ class TaskExport extends BaseExport
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->storage_array[] = $entity;
|
||||
|
||||
$entity['task.start_date'] = '';
|
||||
@ -237,7 +243,7 @@ class TaskExport extends BaseExport
|
||||
$entity['task.duration'] = '';
|
||||
$entity['task.duration_words'] = '';
|
||||
$entity['task.time_log'] = '';
|
||||
$entity['task.time_log_duration_words'];
|
||||
$entity['task.time_log_duration_words'] = '';
|
||||
$entity['task.billable'] = '';
|
||||
$entity['task.item_notes'] = '';
|
||||
|
||||
|
@ -177,6 +177,15 @@ class ExpenseFilters extends QueryFilters
|
||||
return $this->builder->whereIn('category_id', $categories_keys);
|
||||
}
|
||||
|
||||
public function amount(string $amount = ''): Builder
|
||||
{
|
||||
if (strlen($amount) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where('amount', $amount);
|
||||
}
|
||||
|
||||
public function number(string $number = ''): Builder
|
||||
{
|
||||
if (strlen($number) == 0) {
|
||||
|
@ -276,7 +276,7 @@ class InvoiceFilters extends QueryFilters
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
if (!is_array($sort_col) || count($sort_col) != 2 || in_array($sort_col[0], ['documents'])) {
|
||||
if (!is_array($sort_col) || count($sort_col) != 2 || !in_array($sort_col[0], \Illuminate\Support\Facades\Schema::getColumnListing($this->builder->getModel()->getTable()))) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
@ -290,9 +290,6 @@ class InvoiceFilters extends QueryFilters
|
||||
}
|
||||
|
||||
if($sort_col[0] == 'number') {
|
||||
// return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
|
||||
// return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number");
|
||||
// return $this->builder->orderByRaw('ABS(number) ' . $dir);
|
||||
return $this->builder->orderByRaw("REGEXP_REPLACE(invoices.number,'[^0-9]+','')+0 " . $dir);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class InvoiceController extends Controller
|
||||
public function show(ShowInvoiceRequest $request, Invoice $invoice, ?string $hash = null)
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
|
||||
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
@ -91,7 +91,6 @@ class InvoiceController extends Controller
|
||||
|
||||
return auth()->guard('contact')->user()->client->getSetting('payment_flow') == 'default' ? $this->render('invoices.show', $data) : $this->render('invoices.show_smooth', $data);
|
||||
|
||||
// return $this->render('invoices.show_smooth', $data);
|
||||
}
|
||||
|
||||
public function showBlob($hash)
|
||||
|
@ -644,8 +644,6 @@ class CreditController extends BaseController
|
||||
EmailEntity::dispatch($invitation, $credit->company, 'credit');
|
||||
});
|
||||
|
||||
// $credit->sendEvent(Webhook::EVENT_SENT_CREDIT, "client");
|
||||
|
||||
if (! $bulk) {
|
||||
return response()->json(['message' => 'email sent'], 200);
|
||||
}
|
||||
|
@ -647,7 +647,7 @@ class ExpenseController extends BaseController
|
||||
$user = auth()->user();
|
||||
|
||||
foreach ($request->file("documents") as $file) {
|
||||
ImportEDocument::dispatch($file->get(), $file->getClientOriginalName(), $request->file("documents")->getMimeType(), $user->company());
|
||||
ImportEDocument::dispatch($file->get(), $file->getClientOriginalName(), $file->getMimeType(), $user->company());
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'Processing....'], 200);
|
||||
|
@ -285,7 +285,10 @@ class ImportController extends Controller
|
||||
'WINDOWS-1251', // CP1251
|
||||
'UTF-16',
|
||||
'UTF-32',
|
||||
'ASCII'
|
||||
'ASCII',
|
||||
'WINDOWS-1254', // Turkish, which sometimes includes Georgian
|
||||
'WINDOWS-1256', // Arabic, which sometimes includes Georgian
|
||||
'ISO-8859-10',
|
||||
];
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
|
@ -165,9 +165,17 @@ class InvoiceController extends BaseController
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var \App\Models\Company $company */
|
||||
$company = auth()->user()->company();
|
||||
|
||||
$invoice = InvoiceFactory::create($user->company()->id, $user->id);
|
||||
$invoice->date = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d');
|
||||
|
||||
$invoice->custom_surcharge_tax1 = $company->custom_surcharge_taxes1;
|
||||
$invoice->custom_surcharge_tax2 = $company->custom_surcharge_taxes2;
|
||||
$invoice->custom_surcharge_tax3 = $company->custom_surcharge_taxes3;
|
||||
$invoice->custom_surcharge_tax4 = $company->custom_surcharge_taxes4;
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
|
||||
|
@ -83,9 +83,14 @@ class LicenseController extends BaseController
|
||||
{
|
||||
$this->checkLicense();
|
||||
|
||||
nlog("License Check::");
|
||||
nlog(config('ninja.environment'));
|
||||
nlog(request()->has('license_key'));
|
||||
nlog(request()->input('license_key','No License Found'));
|
||||
|
||||
/* Catch claim license requests */
|
||||
if (config('ninja.environment') == 'selfhost' && request()->has('license_key')) {
|
||||
$license_key = request()->input('license_key');
|
||||
$license_key = trim(request()->input('license_key'));
|
||||
$product_id = 3;
|
||||
|
||||
if(substr($license_key, 0, 3) == 'v5_') {
|
||||
@ -144,6 +149,8 @@ class LicenseController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
nlog("No license key or environment not set to selfhost");
|
||||
|
||||
$error = [
|
||||
'message' => ctrans('texts.invoice_license_or_environment', ['environment' => config('ninja.environment')]),
|
||||
'errors' => new stdClass(),
|
||||
@ -156,15 +163,22 @@ class LicenseController extends BaseController
|
||||
{
|
||||
$this->checkLicense();
|
||||
|
||||
/* Catch claim license requests */
|
||||
/* Catch claim license requests */
|
||||
if (config('ninja.environment') == 'selfhost') {
|
||||
|
||||
nlog("Claiming v5 license");
|
||||
|
||||
$response = Http::get("https://invoicing.co/claim_license", [
|
||||
'license_key' => $license_key,
|
||||
'product_id' => 3,
|
||||
]);
|
||||
|
||||
$payload = $response->json();
|
||||
|
||||
nlog("Ninja Server Response");
|
||||
nlog($payload);
|
||||
|
||||
if ($response->successful()) {
|
||||
$payload = $response->json();
|
||||
|
||||
$account = auth()->user()->account;
|
||||
|
||||
@ -189,6 +203,8 @@ class LicenseController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
nlog("Environment not set to selfhost - failing");
|
||||
|
||||
$error = [
|
||||
'message' => ctrans('texts.invoice_license_or_environment', ['environment' => config('ninja.environment')]),
|
||||
'errors' => new stdClass(),
|
||||
|
@ -71,6 +71,12 @@ class PreviewController extends BaseController
|
||||
$entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer;
|
||||
$entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms;
|
||||
$entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes;
|
||||
|
||||
$entity_obj->custom_surcharge_tax1 = $client->company->custom_surcharge_taxes1;
|
||||
$entity_obj->custom_surcharge_tax2 = $client->company->custom_surcharge_taxes2;
|
||||
$entity_obj->custom_surcharge_tax3 = $client->company->custom_surcharge_taxes3;
|
||||
$entity_obj->custom_surcharge_tax4 = $client->company->custom_surcharge_taxes4;
|
||||
|
||||
$invitation->setRelation($request->entity, $entity_obj);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ class SmtpController extends BaseController
|
||||
$company = $user->company();
|
||||
|
||||
$smtp_host = $request->input('smtp_host', $company->smtp_host);
|
||||
$smtp_port = $request->input('smtp_port', $company->smtp_port);
|
||||
$smtp_port = (int)$request->input('smtp_port', $company->smtp_port);
|
||||
$smtp_username = $request->input('smtp_username', $company->smtp_username);
|
||||
$smtp_password = $request->input('smtp_password', $company->smtp_password);
|
||||
$smtp_encryption = $request->input('smtp_encryption', $company->smtp_encryption ?? 'tls');
|
||||
|
@ -25,13 +25,20 @@ class SubdomainController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
$user = auth()->user();
|
||||
$company = $user->company();
|
||||
|
||||
if($company->subdomain == trim(request()->input('subdomain'))){
|
||||
return response()->json(['message' => 'Current subdomain name.'], 200);
|
||||
}
|
||||
|
||||
if (!MultiDB::checkDomainAvailable(request()->input('subdomain'))) {
|
||||
return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401);
|
||||
}
|
||||
|
||||
|
||||
if (!preg_match('/^[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/', request()->input('subdomain'))) {
|
||||
return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401);
|
||||
return response()->json(['message' => "Invalid subdomain format."], 401);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,6 @@ class CheckClientExistence
|
||||
auth()->guard('contact')->user()->loadMissing(['company']); // @phpstan-ignore method.notFound
|
||||
|
||||
$multiple_contacts = ClientContact::query()
|
||||
// ->with('client.gateway_tokens', 'company')
|
||||
->where('email', auth()->guard('contact')->user()->email)
|
||||
->whereNotNull('email')
|
||||
->where('email', '<>', '')
|
||||
@ -66,7 +65,6 @@ class CheckClientExistence
|
||||
}
|
||||
|
||||
session()->put('multiple_contacts', $multiple_contacts);
|
||||
|
||||
session()->put('is_silent', request()->has('silent'));
|
||||
|
||||
return $next($request);
|
||||
|
@ -37,9 +37,9 @@ class CreateAccountRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
if (Ninja::isHosted()) {
|
||||
$email_rules = ['bail', 'required', 'email:rfc,dns', new NewUniqueUserRule(), new BlackListRule(), new EmailBlackListRule()];
|
||||
$email_rules = ['bail', 'required', 'max:255', 'email:rfc,dns', new NewUniqueUserRule(), new BlackListRule(), new EmailBlackListRule()];
|
||||
} else {
|
||||
$email_rules = ['bail', 'required', 'email:rfc,dns', new NewUniqueUserRule()];
|
||||
$email_rules = ['bail', 'required', 'max:255', 'email:rfc,dns', new NewUniqueUserRule()];
|
||||
}
|
||||
|
||||
return [
|
||||
|
@ -74,7 +74,7 @@ class UpdateCompanyRequest extends Request
|
||||
}
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
$rules['subdomain'] = ['nullable', 'regex:/^[a-zA-Z0-9.-]+[a-zA-Z0-9]$/', new ValidSubdomain()];
|
||||
$rules['subdomain'] = ['nullable', 'regex:/^[a-zA-Z0-9-]+[a-zA-Z0-9]$/', new ValidSubdomain()];
|
||||
}
|
||||
|
||||
$rules['expense_mailbox'] = ['sometimes','email', 'nullable', new ValidExpenseMailbox(), Rule::unique('companies')->ignore($this->company->id)];
|
||||
|
@ -22,7 +22,7 @@ class SendEmailRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
private string $entity_plural = '';
|
||||
private string $entity_plural = 'invoices';
|
||||
private string $error_message = '';
|
||||
|
||||
public array $templates = [
|
||||
@ -92,9 +92,8 @@ class SendEmailRequest extends Request
|
||||
$input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
|
||||
}
|
||||
|
||||
$this->entity_plural = Str::plural($input['entity']) ?? '';
|
||||
|
||||
if (isset($input['entity']) && in_array($input['entity'], ['invoice','quote','credit','recurring_invoice','purchase_order','payment'])) {
|
||||
$this->entity_plural = Str::plural($input['entity']) ?? '';
|
||||
$input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity']));
|
||||
}
|
||||
|
||||
@ -106,13 +105,15 @@ class SendEmailRequest extends Request
|
||||
})->slice(0, 4)->toArray();
|
||||
}
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
public function message()
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'template' => 'Invalid template.',
|
||||
'template.in' => 'Template :input is anot a valid template.',
|
||||
'entity.in' => 'Entity :input is not a valid entity.'
|
||||
];
|
||||
}
|
||||
|
||||
@ -134,8 +135,7 @@ class SendEmailRequest extends Request
|
||||
}
|
||||
|
||||
/*Make sure we have all the require ingredients to send a template*/
|
||||
if (isset($input['entity']) && array_key_exists('entity_id', $input) && is_string($input['entity']) && $input['entity_id']) {
|
||||
|
||||
if (isset($input['entity']) && array_key_exists('entity_id', $input) && in_array($input['entity'], ['App\Models\Invoice','App\Models\Quote','App\Models\Credit','App\Models\RecurringInvoice','App\Models\PurchaseOrder','App\Models\Payment'])) {
|
||||
|
||||
$company = $user->company();
|
||||
|
||||
@ -148,11 +148,12 @@ class SendEmailRequest extends Request
|
||||
if ($entity_obj && ($company->id == $entity_obj->company_id) && $user->can('edit', $entity_obj)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$this->error_message = "Invalid entity or entity_id";
|
||||
}
|
||||
else {
|
||||
$this->error_message = "Invalid entity or entity_id";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function failedAuthorization()
|
||||
|
@ -331,6 +331,7 @@ class CompanyImport implements ShouldQueue
|
||||
->purgeCompanyData()
|
||||
->importCompany()
|
||||
->importData()
|
||||
->miscTransformations()
|
||||
->postImportCleanup();
|
||||
|
||||
$data = [
|
||||
@ -359,6 +360,52 @@ class CompanyImport implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
private function miscTransformations()
|
||||
{
|
||||
Invoice::withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->cursor()
|
||||
->each(function ($invoice){
|
||||
|
||||
$items = $invoice->line_items;
|
||||
|
||||
foreach($items as $key => $value)
|
||||
{
|
||||
|
||||
if(isset($value->task_id) && strlen($value->task_id) >1) {
|
||||
|
||||
$t_id = $this->transformId('tasks',$value->task_id);
|
||||
|
||||
if($t = Task::withTrashed()->where('company_id', $this->company->id)->where('id',$t_id)->first())
|
||||
{
|
||||
$items[$key]->task_id = $t->hashed_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isset($value->expense_id) && strlen($value->expense_id) > 1) {
|
||||
|
||||
$e_id = $this->transformId('expenses', $value->expense_id);
|
||||
|
||||
if ($e = Expense::withTrashed()->where('company_id', $this->company->id)->where('id', $e_id)->first()) {
|
||||
$items[$key]->expense_id = $e->hashed_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$invoice->line_items = array_values($items);
|
||||
$invoice->saveQuietly();
|
||||
|
||||
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//
|
||||
private function postImportCleanup()
|
||||
{
|
||||
|
@ -11,16 +11,17 @@
|
||||
|
||||
namespace App\Jobs\EDocument;
|
||||
|
||||
use App\Models\Expense;
|
||||
use App\Services\EDocument\Imports\ParseEDocument;
|
||||
use App\Utils\TempFile;
|
||||
use Exception;
|
||||
use App\Models\Company;
|
||||
use App\Models\Expense;
|
||||
use App\Utils\TempFile;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use App\Services\EDocument\Imports\ParseEDocument;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use App\Services\EDocument\Imports\ZugferdEDocument;
|
||||
|
||||
@ -31,8 +32,6 @@ class ImportEDocument implements ShouldQueue
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(private readonly string $file_content, private string $file_name, private string $file_mime_type, private Company $company)
|
||||
{
|
||||
|
||||
@ -46,7 +45,6 @@ class ImportEDocument implements ShouldQueue
|
||||
*/
|
||||
public function handle(): Expense
|
||||
{
|
||||
|
||||
$file = TempFile::UploadedFileFromRaw($this->file_content, $this->file_name, $this->file_mime_type);
|
||||
|
||||
return (new ParseEDocument($file, $this->company))->run();
|
||||
@ -55,7 +53,7 @@ class ImportEDocument implements ShouldQueue
|
||||
|
||||
public function middleware()
|
||||
{
|
||||
return [new WithoutOverlapping($this->company->company_key)];
|
||||
return [new WithoutOverlapping($this->company->company_key."_expense_import_".$this->file_name)];
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
@ -63,7 +61,8 @@ class ImportEDocument implements ShouldQueue
|
||||
if ($exception) {
|
||||
nlog("EXCEPTION:: ImportEDocument:: " . $exception->getMessage());
|
||||
}
|
||||
|
||||
|
||||
$this->fail($exception); //manually fail - prevents future jobs with the same name from being discarded
|
||||
config(['queue.failed.driver' => null]);
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$company = $this->company;
|
||||
|
||||
$smtp_host = $company->smtp_host ?? '';
|
||||
$smtp_port = $company->smtp_port;
|
||||
$smtp_port = (int)$company->smtp_port;
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
|
@ -59,7 +59,7 @@ class CleanStaleInvoiceOrder implements ShouldQueue
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||
->where('status_id', Invoice::STATUS_SENT)
|
||||
->where('updated_at', '<', now()->subHour())
|
||||
->where('balance', '>', 0)
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
@ -68,6 +68,85 @@ class CleanStaleInvoiceOrder implements ShouldQueue
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
});
|
||||
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('status_id', Invoice::STATUS_PARTIAL)
|
||||
->where('balance', '>', 0)
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
->cursor()
|
||||
->each(function ($invoice) {
|
||||
|
||||
$type_3_count = 0;
|
||||
$type_4_count = 0;
|
||||
|
||||
foreach ($invoice->line_items as $line_item) {
|
||||
if ($line_item->type_id == '3') {
|
||||
$type_3_count++;
|
||||
} elseif ($line_item->type_id == '4') {
|
||||
$type_4_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_4_count == 1) {
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
} elseif ($type_3_count == 1) {
|
||||
|
||||
$items = $invoice->line_items;
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
|
||||
if ($value->type_id == "3") {
|
||||
$items[$key]->type_id = "4";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$invoice->line_items = array_values($items);
|
||||
$invoice->calc()->getInvoice();
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('status_id', Invoice::STATUS_PAID)
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
->cursor()
|
||||
->each(function ($invoice) {
|
||||
|
||||
$type_3_count = 0;
|
||||
$type_4_count = 0;
|
||||
|
||||
foreach ($invoice->line_items as $line_item) {
|
||||
if ($line_item->type_id == '3') {
|
||||
$type_3_count++;
|
||||
} elseif ($line_item->type_id == '4') {
|
||||
$type_4_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_4_count == 0 && $type_3_count == 1) {
|
||||
|
||||
$items = $invoice->line_items;
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
|
||||
if ($value->type_id == "3") {
|
||||
$items[$key]->type_id = "4";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$invoice->line_items = array_values($items);
|
||||
$invoice->saveQuietly();
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -76,14 +155,15 @@ class CleanStaleInvoiceOrder implements ShouldQueue
|
||||
MultiDB::setDB($db);
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('is_proforma', 1)
|
||||
->where('created_at', '<', now()->subHour())
|
||||
->cursor()
|
||||
->each(function ($invoice) use ($repo) {
|
||||
$invoice->is_proforma = false;
|
||||
$repo->delete($invoice);
|
||||
});
|
||||
->withTrashed()
|
||||
->where('status_id', Invoice::STATUS_SENT)
|
||||
->where('is_proforma', 1)
|
||||
->where('created_at', '<', now()->subHour())
|
||||
->cursor()
|
||||
->each(function ($invoice) use ($repo) {
|
||||
$invoice->is_proforma = false;
|
||||
$repo->delete($invoice);
|
||||
});
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
@ -96,6 +176,85 @@ class CleanStaleInvoiceOrder implements ShouldQueue
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
});
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('status_id', Invoice::STATUS_PARTIAL)
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
->cursor()
|
||||
->each(function ($invoice) {
|
||||
|
||||
$type_3_count = 0;
|
||||
$type_4_count = 0;
|
||||
|
||||
foreach ($invoice->line_items as $line_item) {
|
||||
if ($line_item->type_id == '3') {
|
||||
$type_3_count++;
|
||||
} elseif ($line_item->type_id == '4') {
|
||||
$type_4_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_4_count == 1) {
|
||||
$invoice->service()->removeUnpaidGatewayFees();
|
||||
} elseif ($type_3_count == 1) {
|
||||
|
||||
$items = $invoice->line_items;
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
|
||||
if ($value->type_id == "3") {
|
||||
$items[$key]->type_id = "4";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$invoice->line_items = array_values($items);
|
||||
$invoice->calc()->getInvoice();
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('status_id', Invoice::STATUS_PAID)
|
||||
->whereJsonContains('line_items', ['type_id' => '3'])
|
||||
->cursor()
|
||||
->each(function ($invoice) {
|
||||
|
||||
$type_3_count = 0;
|
||||
$type_4_count = 0;
|
||||
|
||||
|
||||
foreach ($invoice->line_items as $line_item) {
|
||||
if ($line_item->type_id == '3') {
|
||||
$type_3_count++;
|
||||
} elseif ($line_item->type_id == '4') {
|
||||
$type_4_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_4_count == 0 && $type_3_count == 1) {
|
||||
|
||||
$items = $invoice->line_items;
|
||||
|
||||
foreach ($items as $key => $value) {
|
||||
|
||||
if ($value->type_id == "3") {
|
||||
$items[$key]->type_id = "4";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$invoice->line_items = array_values($items);
|
||||
$invoice->saveQuietly();
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
\DB::connection($db)->table('password_resets')->where('created_at', '<', now()->subHours(12))->delete();
|
||||
|
||||
}
|
||||
|
@ -432,15 +432,20 @@ class Import implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
$rules = (new UpdateCompanyRequest())->rules();
|
||||
// $rules = (new UpdateCompanyRequest())->rules();
|
||||
|
||||
unset($rules['expense_mailbox']);
|
||||
|
||||
$validator = Validator::make($data, $rules);
|
||||
// unset($rules['expense_mailbox']);
|
||||
// unset($rules['e_invoice']);
|
||||
// unset($rules['smtp_port']);
|
||||
// unset($rules['settings']);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||
}
|
||||
// $validator = Validator::make($data, $rules);
|
||||
|
||||
// nlog($validator->errors());
|
||||
|
||||
// if ($validator->fails()) {
|
||||
// throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||
// }
|
||||
|
||||
if (isset($data['account_id'])) {
|
||||
unset($data['account_id']);
|
||||
@ -1566,6 +1571,7 @@ class Import implements ShouldQueue
|
||||
|
||||
|
||||
} catch(\Exception $e) {
|
||||
nlog($e->getMessage());
|
||||
//do nothing, gracefully :)
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ class Register extends Component
|
||||
|
||||
$this->register_fields = [...collect($this->subscription->company->client_registration_fields ?? [])->toArray()];
|
||||
|
||||
$first_gateway = collect($this->subscription->company->company_gateways)
|
||||
$first_gateway = collect($this->subscription->company->company_gateways()->withoutTrashed()->get())
|
||||
->sortBy('sort_order')
|
||||
->first();
|
||||
|
||||
|
@ -202,11 +202,7 @@ class RegisterOrLogin extends Component
|
||||
|
||||
$this->register_fields = [...collect($this->subscription->company->client_registration_fields ?? [])->toArray()];
|
||||
|
||||
// if ($this->subscription->company->settings->client_portal_terms || $this->subscription->company->settings->client_portal_privacy_policy) {
|
||||
// $this->register_fields[] = ['key' => 'terms', 'required' => true, 'visible' => 'true'];
|
||||
// }
|
||||
|
||||
$first_gateway = collect($this->subscription->company->company_gateways)
|
||||
$first_gateway = collect($this->subscription->company->company_gateways()->withoutTrashed()->get())
|
||||
->sortBy('sort_order')
|
||||
->first();
|
||||
|
||||
|
@ -116,7 +116,7 @@ class Summary extends Component
|
||||
return \sprintf(
|
||||
'%s/%s',
|
||||
Number::formatMoney($recurring + $recurring_optional, $this->subscription->company),
|
||||
RecurringInvoice::frequencyForKey($this->subscription->frequency_id)
|
||||
RecurringInvoice::frequencyForKey($this->subscription->frequency_id ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -105,15 +105,12 @@ class InvoicePay extends Component
|
||||
#[On('terms-accepted')]
|
||||
public function termsAccepted()
|
||||
{
|
||||
nlog("Terms accepted");
|
||||
// $this->invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id)->withoutRelations();
|
||||
$this->terms_accepted = true;
|
||||
}
|
||||
|
||||
#[On('signature-captured')]
|
||||
public function signatureCaptured($base64)
|
||||
{
|
||||
nlog("signature captured");
|
||||
|
||||
$this->signature_accepted = true;
|
||||
$invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id);
|
||||
@ -141,7 +138,6 @@ class InvoicePay extends Component
|
||||
$this->setContext('amount', $amount);
|
||||
$this->setContext('pre_payment', false);
|
||||
$this->setContext('is_recurring', false);
|
||||
$this->setContext('invitation_id', $this->invitation_id);
|
||||
|
||||
$this->payment_method_accepted = true;
|
||||
|
||||
@ -178,9 +174,7 @@ class InvoicePay extends Component
|
||||
empty($contact->client->{$_field})
|
||||
|| is_null($contact->client->{$_field}) //@phpstan-ignore-line
|
||||
) {
|
||||
|
||||
return $this->required_fields = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +184,7 @@ class InvoicePay extends Component
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->required_fields = false;
|
||||
|
||||
}
|
||||
@ -231,21 +225,27 @@ class InvoicePay extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
|
||||
$this->resetContext();
|
||||
|
||||
MultiDB::setDb($this->db);
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$invite = \App\Models\InvoiceInvitation::with('contact.client', 'company')->withTrashed()->find($this->invitation_id);
|
||||
|
||||
$client = $invite->contact->client;
|
||||
$settings = $client->getMergedSettings();
|
||||
$this->setContext('contact', $invite->contact); // $this->context['contact'] = $invite->contact;
|
||||
$this->setContext('settings', $settings); // $this->context['settings'] = $settings;
|
||||
$this->setContext('db', $this->db); // $this->context['db'] = $this->db;
|
||||
$this->setContext('invitation_id', $this->invitation_id);
|
||||
|
||||
if(is_array($this->invoices))
|
||||
$this->invoices = Invoice::find($this->transformKeys($this->invoices));
|
||||
|
||||
elseif ($this->invoices instanceof \Illuminate\Support\Collection) {
|
||||
$this->invoices = Invoice::find($this->invoices->pluck('id'));
|
||||
}
|
||||
|
||||
$invoices = $this->invoices->filter(function ($i) {
|
||||
$i = $i->service()
|
||||
->markSent()
|
||||
@ -292,9 +292,9 @@ class InvoicePay extends Component
|
||||
|
||||
public function exception($e, $stopPropagation)
|
||||
{
|
||||
|
||||
|
||||
app('sentry')->captureException($e);
|
||||
nlog($e->getMessage());
|
||||
|
||||
$stopPropagation();
|
||||
|
||||
}
|
||||
|
@ -78,9 +78,7 @@ class PaymentMethod extends Component
|
||||
|
||||
public function exception($e, $stopPropagation)
|
||||
{
|
||||
|
||||
nlog($e->getMessage());
|
||||
app('sentry')->captureException($e);
|
||||
$stopPropagation();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -58,16 +58,22 @@ class ProcessPayment extends Component
|
||||
throw new PaymentFailed($responder_data['error'], 400);
|
||||
}
|
||||
|
||||
$driver = $company_gateway
|
||||
->driver($invitation->contact->client) // @phpstan-ignore-line
|
||||
->setPaymentMethod($data['payment_method_id'])
|
||||
->setPaymentHash($responder_data['payload']['ph']);
|
||||
if(isset($responder_data['component']) && $responder_data['component'] == 'CreditPaymentComponent'){
|
||||
$this->payment_view = $responder_data['view'];
|
||||
$this->payment_data_payload = $responder_data['payload'];
|
||||
}
|
||||
else {
|
||||
$driver = $company_gateway
|
||||
->driver($invitation->contact->client) // @phpstan-ignore-line
|
||||
->setPaymentMethod($data['payment_method_id'])
|
||||
->setPaymentHash($responder_data['payload']['ph']);
|
||||
|
||||
$this->payment_data_payload = $driver->processPaymentViewData($responder_data['payload']);
|
||||
|
||||
$this->payment_view = $driver->livewirePaymentView(
|
||||
$this->payment_data_payload,
|
||||
);
|
||||
$this->payment_data_payload = $driver->processPaymentViewData($responder_data['payload']);
|
||||
|
||||
$this->payment_view = $driver->livewirePaymentView(
|
||||
$this->payment_data_payload,
|
||||
);
|
||||
}
|
||||
|
||||
$this->isLoading = false;
|
||||
|
||||
@ -87,6 +93,8 @@ class ProcessPayment extends Component
|
||||
public function exception($e, $stopPropagation)
|
||||
{
|
||||
|
||||
app('sentry')->captureException($e);
|
||||
|
||||
$errors = session()->get('errors', new \Illuminate\Support\ViewErrorBag());
|
||||
|
||||
$bag = new \Illuminate\Support\MessageBag();
|
||||
|
@ -61,12 +61,12 @@ class RequiredFields extends Component
|
||||
|
||||
$this->fields = $this->getContext()['fields'];
|
||||
|
||||
$contact = auth()->guard('contact')->user();
|
||||
|
||||
$this->company_gateway = CompanyGateway::withTrashed()
|
||||
->with('company')
|
||||
->find($this->getContext()['company_gateway_id']);
|
||||
|
||||
$contact = auth()->guard('contact')->user();
|
||||
|
||||
|
||||
$this->client_name = $contact->client->name;
|
||||
$this->contact_first_name = $contact->first_name;
|
||||
$this->contact_last_name = $contact->last_name;
|
||||
@ -138,9 +138,8 @@ class RequiredFields extends Component
|
||||
|
||||
public function exception($e, $stopPropagation)
|
||||
{
|
||||
|
||||
app('sentry')->captureException($e);
|
||||
nlog($e->getMessage());
|
||||
|
||||
$stopPropagation();
|
||||
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property bool $is_scheduler_running
|
||||
* @property int|null $trial_duration
|
||||
* @property bool $is_onboarding
|
||||
* @property object|null $onboarding
|
||||
* @property object|array|null $onboarding
|
||||
* @property bool $is_migrated
|
||||
* @property string|null $platform
|
||||
* @property int|null $hosted_client_count
|
||||
|
@ -41,10 +41,10 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property bool $update_products
|
||||
* @property bool $show_product_details
|
||||
* @property bool $client_can_register
|
||||
* @property int $custom_surcharge_taxes1
|
||||
* @property int $custom_surcharge_taxes2
|
||||
* @property int $custom_surcharge_taxes3
|
||||
* @property int $custom_surcharge_taxes4
|
||||
* @property bool $custom_surcharge_taxes1
|
||||
* @property bool $custom_surcharge_taxes2
|
||||
* @property bool $custom_surcharge_taxes3
|
||||
* @property bool $custom_surcharge_taxes4
|
||||
* @property int $show_product_cost
|
||||
* @property int $enabled_tax_rates
|
||||
* @property int $enabled_modules
|
||||
@ -577,8 +577,8 @@ class Company extends BaseModel
|
||||
}
|
||||
|
||||
public function activities(): HasMany
|
||||
{
|
||||
return $this->hasMany(Activity::class)->where('account_id', $this->account_id)->orderBy('id', 'DESC')->take(50);
|
||||
{
|
||||
return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(50);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,12 +146,9 @@ class Expense extends BaseModel
|
||||
];
|
||||
|
||||
public static array $bulk_update_columns = [
|
||||
'tax_rate1',
|
||||
'tax_name1',
|
||||
'tax_rate2',
|
||||
'tax_name2',
|
||||
'tax_rate3',
|
||||
'tax_name3',
|
||||
'tax1',
|
||||
'tax2',
|
||||
'tax3',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
|
@ -467,7 +467,7 @@ class Invoice extends BaseModel
|
||||
|
||||
public function isPayable(): bool
|
||||
{
|
||||
if($this->is_deleted || $this->status_id == self::STATUS_PAID) {
|
||||
if($this->is_deleted || $this->status_id == self::STATUS_PAID || $this->balance < 0) {
|
||||
return false;
|
||||
} elseif ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
|
||||
return true;
|
||||
|
@ -216,7 +216,7 @@ class Product extends BaseModel
|
||||
return $converter->convert($this->notes ?? '');
|
||||
}
|
||||
|
||||
public static function markdownHelp(string $notes = '')
|
||||
public static function markdownHelp(?string $notes = '')
|
||||
{
|
||||
|
||||
$converter = new CommonMarkConverter([
|
||||
@ -226,7 +226,7 @@ class Product extends BaseModel
|
||||
],
|
||||
]);
|
||||
|
||||
return $converter->convert($notes);
|
||||
return $converter->convert($notes ?? '');
|
||||
|
||||
}
|
||||
|
||||
|
@ -247,12 +247,9 @@ class RecurringInvoice extends BaseModel
|
||||
protected $touches = [];
|
||||
|
||||
public static array $bulk_update_columns = [
|
||||
'tax_rate1',
|
||||
'tax_name1',
|
||||
'tax_rate2',
|
||||
'tax_name2',
|
||||
'tax_rate3',
|
||||
'tax_name3',
|
||||
'tax1',
|
||||
'tax2',
|
||||
'tax3',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
|
@ -201,4 +201,23 @@ class Subscription extends BaseModel
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum product quantity available
|
||||
*
|
||||
* @param mixed $product
|
||||
* @return int
|
||||
*/
|
||||
public function maxQuantity(mixed $product): int
|
||||
{
|
||||
$max_quantity = data_get($product, 'max_quantity', 0);
|
||||
$in_stock_quantity = data_get($product, 'in_stock_quantity', 0);
|
||||
$max_limit = 100;
|
||||
|
||||
if(!$this->use_inventory_management)
|
||||
return $max_quantity != 0 ? $max_quantity : $max_limit;
|
||||
|
||||
return $max_quantity !=0 ? $max_quantity : min($max_limit, $in_stock_quantity);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ class Vendor extends BaseModel
|
||||
'language_id',
|
||||
'classification',
|
||||
'is_tax_exempt',
|
||||
'routing_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
@ -404,8 +404,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
$item->gross_line_total = round($item->gross_line_total, 2);
|
||||
return $item;
|
||||
})
|
||||
->whereIn('type_id', ['3'])
|
||||
// ->where('gross_line_total', '<=', round($fee_total,2))
|
||||
->whereIn('type_id', ['3','4'])
|
||||
->count();
|
||||
|
||||
if($invoice && $fee_count == 0){
|
||||
@ -456,12 +455,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
$new_balance = $invoice->balance;
|
||||
|
||||
if (floatval($new_balance) - floatval($balance) != 0) {
|
||||
$adjustment = $new_balance - $balance;
|
||||
|
||||
$invoice
|
||||
->ledger()
|
||||
->updateInvoiceBalance($adjustment, 'Adjustment for adding gateway fee **Base Driver**');
|
||||
|
||||
$adjustment = $new_balance - $balance;
|
||||
$invoice->client->service()->calculateBalance();
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ class ACH implements MethodInterface, LivewireMethodInterface
|
||||
]);
|
||||
|
||||
if ($result->success) {
|
||||
$this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash], SystemLog::TYPE_BRAINTREE);
|
||||
$this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash->data], SystemLog::TYPE_BRAINTREE);
|
||||
|
||||
return $this->processSuccessfulPayment($result);
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
}
|
||||
|
||||
if ($result->success) {
|
||||
$this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash], SystemLog::TYPE_BRAINTREE);
|
||||
$this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash->data], SystemLog::TYPE_BRAINTREE);
|
||||
|
||||
if ($request->store_card && is_null($request->token)) {
|
||||
$payment_method = $this->braintree->gateway->paymentMethod()->find($token);
|
||||
|
@ -83,7 +83,7 @@ class PayPal implements LivewireMethodInterface
|
||||
|
||||
if ($result->success) {
|
||||
$this->braintree->logSuccessfulGatewayResponse(
|
||||
['response' => $request->server_response, 'data' => $this->braintree->payment_hash],
|
||||
['response' => $request->server_response, 'data' => $this->braintree->payment_hash->data],
|
||||
SystemLog::TYPE_BRAINTREE
|
||||
);
|
||||
|
||||
|
@ -120,7 +120,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
if ($charge->status == 'complete') {
|
||||
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash], SystemLog::TYPE_POWERBOARD);
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash->data], SystemLog::TYPE_POWERBOARD);
|
||||
|
||||
$vt = $charge->customer->payment_source->vault_token;
|
||||
|
||||
@ -264,7 +264,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
return 'gateways.powerboard.credit_card.pay_livewire';
|
||||
}
|
||||
|
||||
public function tokenBilling($request, $cgt, $client_present = false)
|
||||
public function tokenBilling($cgt, $client_present = false)
|
||||
{
|
||||
|
||||
$payload = [
|
||||
@ -291,7 +291,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
nlog($charge);
|
||||
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash], SystemLog::TYPE_POWERBOARD);
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash->data], SystemLog::TYPE_POWERBOARD);
|
||||
|
||||
return $this->processSuccessfulPayment($charge);
|
||||
}
|
||||
@ -352,7 +352,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
->where('token', $request->token)
|
||||
->first();
|
||||
|
||||
return $this->tokenBilling($request, $cgt, true);
|
||||
return $this->tokenBilling($cgt, true);
|
||||
|
||||
}
|
||||
elseif($request->browser_details)
|
||||
@ -389,7 +389,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
nlog($charge);
|
||||
|
||||
if ($charge->status == 'complete') {
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash], SystemLog::TYPE_POWERBOARD);
|
||||
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash->data], SystemLog::TYPE_POWERBOARD);
|
||||
|
||||
$vt = $charge->customer->payment_source->vault_token;
|
||||
|
||||
|
@ -175,6 +175,15 @@ class CBAPowerBoardPaymentDriver extends BaseDriver
|
||||
|
||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||
{
|
||||
|
||||
$this->init();
|
||||
|
||||
$this->setPaymentMethod($cgt->gateway_type_id);
|
||||
$this->setPaymentHash($payment_hash);
|
||||
$this->setClient($cgt->client);
|
||||
|
||||
return $this->payment_method->tokenBilling($cgt, false);
|
||||
|
||||
}
|
||||
|
||||
public function importCustomers()
|
||||
|
@ -58,14 +58,9 @@ class CustomPaymentDriver extends BaseDriver
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* View for displaying custom content of the driver.
|
||||
*
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function processPaymentView($data)
|
||||
public function paymentData(array $data): array
|
||||
{
|
||||
|
||||
$variables = [];
|
||||
|
||||
if (count($this->payment_hash->invoices()) > 0) {
|
||||
@ -87,9 +82,33 @@ class CustomPaymentDriver extends BaseDriver
|
||||
$data['gateway'] = $this;
|
||||
$data['payment_hash'] = $this->payment_hash->hash;
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* View for displaying custom content of the driver.
|
||||
*
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function processPaymentView($data)
|
||||
{
|
||||
$data = $this->paymentData($data);
|
||||
|
||||
return render('gateways.custom.payment', $data);
|
||||
}
|
||||
|
||||
public function livewirePaymentView(array $data): string
|
||||
{
|
||||
return 'gateways.custom.pay_livewire';
|
||||
}
|
||||
|
||||
public function processPaymentViewData(array $data): array
|
||||
{
|
||||
return $this->paymentData($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing method for payment. Should never be reached with this driver.
|
||||
*
|
||||
@ -117,7 +136,7 @@ class CustomPaymentDriver extends BaseDriver
|
||||
$gateway_response = json_decode($request->gateway_response);
|
||||
|
||||
if ($gateway_response->status == 'COMPLETED') {
|
||||
$this->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $payment_hash], SystemLog::TYPE_CUSTOM);
|
||||
$this->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $payment_hash->data], SystemLog::TYPE_CUSTOM);
|
||||
|
||||
$data = [
|
||||
'payment_method' => '',
|
||||
|
@ -84,7 +84,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
if ($payment->status === 'paid') {
|
||||
$this->mollie->logSuccessfulGatewayResponse(
|
||||
['response' => $payment, 'data' => $this->mollie->payment_hash],
|
||||
['response' => $payment, 'data' => $this->mollie->payment_hash->data],
|
||||
SystemLog::TYPE_MOLLIE
|
||||
);
|
||||
|
||||
@ -149,7 +149,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
|
||||
if ($payment->status === 'paid') {
|
||||
$this->mollie->logSuccessfulGatewayResponse(
|
||||
['response' => $payment, 'data' => $this->mollie->payment_hash],
|
||||
['response' => $payment, 'data' => $this->mollie->payment_hash->data],
|
||||
SystemLog::TYPE_MOLLIE
|
||||
);
|
||||
|
||||
|
@ -208,7 +208,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
$this->payfast->payment_hash->save();
|
||||
|
||||
if ($response_array['payment_status'] == 'COMPLETE') {
|
||||
$this->payfast->logSuccessfulGatewayResponse(['response' => $response_array, 'data' => $this->payfast->payment_hash], SystemLog::TYPE_PAYFAST);
|
||||
$this->payfast->logSuccessfulGatewayResponse(['response' => $response_array, 'data' => $this->payfast->payment_hash->data], SystemLog::TYPE_PAYFAST);
|
||||
|
||||
return $this->processSuccessfulPayment($response_array);
|
||||
} else {
|
||||
|
@ -187,7 +187,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
$response = $this->paytrace->gatewayRequest('/v1/transactions/sale/by_customer', $data);
|
||||
|
||||
if ($response->success ?? false) {
|
||||
$this->paytrace->logSuccessfulGatewayResponse(['response' => $response, 'data' => $this->paytrace->payment_hash], SystemLog::TYPE_PAYTRACE);
|
||||
$this->paytrace->logSuccessfulGatewayResponse(['response' => $response, 'data' => $this->paytrace->payment_hash->data], SystemLog::TYPE_PAYTRACE);
|
||||
|
||||
return $this->processSuccessfulPayment($response);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ class ApplePay
|
||||
$response_handler = new CreditCard($this->stripe_driver);
|
||||
|
||||
if ($server_response->status == 'succeeded') {
|
||||
$this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE);
|
||||
$this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash->data], SystemLog::TYPE_STRIPE);
|
||||
|
||||
return $response_handler->processSuccessfulPayment();
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ class BACS implements LivewireMethodInterface
|
||||
$this->stripe->payment_hash->save();
|
||||
|
||||
if ($state['payment_intent']->status == 'processing') {
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => $state['payment_intent'], 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE);
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => $state['payment_intent'], 'data' => $this->stripe->payment_hash->data], SystemLog::TYPE_STRIPE);
|
||||
|
||||
return $this->processSuccessfulPayment($state['payment_intent']);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ class BrowserPay implements MethodInterface, LivewireMethodInterface
|
||||
$gateway_response = $this->stripe->payment_hash->data->gateway_response;
|
||||
$payment_intent = $this->stripe->payment_hash->data->payment_intent;
|
||||
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => $gateway_response, 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE);
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => $gateway_response, 'data' => $this->stripe->payment_hash->data], SystemLog::TYPE_STRIPE);
|
||||
|
||||
$payment_method = $this->stripe->getStripePaymentMethod($gateway_response->payment_method);
|
||||
|
||||
|
@ -118,7 +118,7 @@ class CreditCard implements LivewireMethodInterface
|
||||
$server_response = $this->stripe->payment_hash->data->server_response;
|
||||
|
||||
if ($server_response->status == 'succeeded') {
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE);
|
||||
$this->stripe->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe->payment_hash->data], SystemLog::TYPE_STRIPE);
|
||||
|
||||
return $this->processSuccessfulPayment();
|
||||
}
|
||||
|
@ -396,23 +396,24 @@ class BaseRepository
|
||||
public function bulkUpdate(\Illuminate\Database\Eloquent\Builder $model, string $column, mixed $new_value): void
|
||||
{
|
||||
/** Handle taxes being updated */
|
||||
if(in_array($column, ['tax_name1','tax_name2','tax_name3'])) {
|
||||
if(in_array($column, ['tax1','tax2','tax3'])) {
|
||||
|
||||
$parts = explode("||", $new_value);
|
||||
|
||||
if (count($parts) !== 2)
|
||||
return;
|
||||
|
||||
$tax_name = trim($parts[0]);
|
||||
$tax_name_column = str_replace("tax", "tax_name", $column);
|
||||
$rate = filter_var($parts[1], FILTER_VALIDATE_FLOAT);
|
||||
|
||||
$tax_name = $parts[0];
|
||||
|
||||
if ($rate === false)
|
||||
return;
|
||||
|
||||
$taxrate_column = str_replace("name", "rate", $column);
|
||||
$taxrate_column = str_replace("tax", "tax_rate", $column);
|
||||
|
||||
$model->update([
|
||||
$column => $tax_name,
|
||||
$tax_name_column => $tax_name,
|
||||
$taxrate_column => $rate,
|
||||
]);
|
||||
return;
|
||||
|
@ -78,7 +78,7 @@ class ClientRepository extends BaseRepository
|
||||
|
||||
$client->save();
|
||||
|
||||
if (! isset($client->number) || empty($client->number) || strlen($client->number) == 0) {
|
||||
if (! isset($client->number) || empty($client->number) || strlen($client->number ?? '') == 0) {//@phpstan-ignore-line
|
||||
$x = 1;
|
||||
|
||||
do {
|
||||
|
@ -105,7 +105,7 @@ class PaymentMigrationRepository extends BaseRepository
|
||||
}
|
||||
|
||||
/*Ensure payment number generated*/
|
||||
if (! $payment->number || strlen($payment->number) == 0) {
|
||||
if (! $payment->number || strlen($payment->number) == 0) {//@phpstan-ignore-line
|
||||
$payment->number = $payment->client->getNextPaymentNumber($payment->client, $payment);
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ class PaymentRepository extends BaseRepository
|
||||
}
|
||||
|
||||
/*Ensure payment number generated*/
|
||||
if (! $payment->number || strlen($payment->number) == 0) {
|
||||
if (! $payment->number || strlen($payment->number ?? '') == 0) { //@phpstan-ignore-line
|
||||
$payment->service()->applyNumber();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,12 @@ class UserRepository extends BaseRepository
|
||||
$user->confirmation_code = $this->createDbHash($company->db);
|
||||
}
|
||||
|
||||
$user->account_id = $account->id;
|
||||
//@18-10-2024 - ensure no cross account linkage.
|
||||
if(is_numeric($user->account_id) && $user->account_id != $account->id){
|
||||
throw new \Illuminate\Auth\Access\AuthorizationException("Illegal operation encountered for {$user->hashed_id}",401);
|
||||
}
|
||||
|
||||
$user->account_id = $account->id;//@todo we should never change the account_id if it is set at this point.
|
||||
|
||||
if (strlen($user->password) >= 1) {
|
||||
$user->has_password = true;
|
||||
|
@ -71,6 +71,9 @@ class Merge extends AbstractService
|
||||
|
||||
$this->mergable_client->forceDelete();
|
||||
|
||||
$this->client->credit_balance = $this->client->service()->getCreditBalance();
|
||||
$this->client->saveQuietly();
|
||||
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
|
@ -232,8 +232,7 @@ class LivewireInstantPayment
|
||||
];
|
||||
|
||||
if ($this->is_credit_payment) {
|
||||
|
||||
$this->mergeResponder(['success' => true, 'component' => 'CreditPaymentComponent', 'payload' => $data]);
|
||||
$this->mergeResponder(['success' => true, 'view' => 'gateways.credit.pay_livewire', 'component' => 'CreditPaymentComponent', 'payload' => $data]);
|
||||
return $this->getResponder();
|
||||
}
|
||||
|
||||
|
@ -152,9 +152,9 @@ class CreditService
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markSent()
|
||||
public function markSent($fire_event = false)
|
||||
{
|
||||
$this->credit = (new MarkSent($this->credit->client, $this->credit))->run();
|
||||
$this->credit = (new MarkSent($this->credit->client, $this->credit))->run($fire_event);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class TriggeredActions extends AbstractService
|
||||
}
|
||||
|
||||
if ($this->request->has('mark_sent') && $this->request->input('mark_sent') == 'true') {
|
||||
$this->credit = $this->credit->service()->markSent()->save();
|
||||
$this->credit = $this->credit->service()->markSent(true)->save();
|
||||
}
|
||||
|
||||
if ($this->request->has('save_default_footer') && $this->request->input('save_default_footer') == 'true') {
|
||||
|
203
app/Services/EDocument/Adapters/CII/PaymentMeans.php
Normal file
203
app/Services/EDocument/Adapters/CII/PaymentMeans.php
Normal file
@ -0,0 +1,203 @@
|
||||
<?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\Adapters\CII;
|
||||
|
||||
use App\Services\EDocument\Interfaces\PaymentMeansInterface;
|
||||
|
||||
class PaymentMeans implements PaymentMeansInterface
|
||||
{
|
||||
|
||||
public array $payment_means_codelist = [
|
||||
'1' => 'Instrument not defined',
|
||||
'2' => 'Automated clearing house credit',
|
||||
'3' => 'Automated clearing house debit',
|
||||
'4' => 'ACH demand debit reversal',
|
||||
'5' => 'ACH demand credit reversal',
|
||||
'6' => 'ACH demand credit',
|
||||
'7' => 'ACH demand debit',
|
||||
'8' => 'Hold',
|
||||
'9' => 'National or regional clearing',
|
||||
'10' => 'In cash',
|
||||
'11' => 'ACH savings credit reversal',
|
||||
'12' => 'ACH savings debit reversal',
|
||||
'13' => 'ACH savings credit',
|
||||
'14' => 'ACH savings debit',
|
||||
'15' => 'Bookentry credit',
|
||||
'16' => 'Bookentry debit',
|
||||
'17' => 'ACH demand cash concentration/disbursement (CCD) credit',
|
||||
'18' => 'ACH demand cash concentration/disbursement (CCD) debit',
|
||||
'19' => 'ACH demand corporate trade payment (CTP) credit',
|
||||
'20' => 'Cheque',
|
||||
'21' => 'Banker\'s draft',
|
||||
'22' => 'Certified banker\'s draft',
|
||||
'23' => 'Bank cheque (issued by a banking or similar establishment)',
|
||||
'24' => 'Bill of exchange awaiting acceptance',
|
||||
'25' => 'Certified cheque',
|
||||
'26' => 'Local cheque',
|
||||
'27' => 'ACH demand corporate trade payment (CTP) debit',
|
||||
'28' => 'ACH demand corporate trade exchange (CTX) credit',
|
||||
'29' => 'ACH demand corporate trade exchange (CTX) debit',
|
||||
'30' => 'Credit transfer',
|
||||
'31' => 'Debit transfer',
|
||||
'32' => 'ACH demand cash concentration/disbursement plus (CCD+)',
|
||||
'33' => 'ACH demand cash concentration/disbursement plus (CCD+)',
|
||||
'34' => 'ACH prearranged payment and deposit (PPD)',
|
||||
'35' => 'ACH savings cash concentration/disbursement (CCD) credit',
|
||||
'36' => 'ACH savings cash concentration/disbursement (CCD) debit',
|
||||
'37' => 'ACH savings corporate trade payment (CTP) credit',
|
||||
'38' => 'ACH savings corporate trade payment (CTP) debit',
|
||||
'39' => 'ACH savings corporate trade exchange (CTX) credit',
|
||||
'40' => 'ACH savings corporate trade exchange (CTX) debit',
|
||||
'41' => 'ACH savings cash concentration/disbursement plus (CCD+)',
|
||||
'42' => 'Payment to bank account',
|
||||
'43' => 'ACH savings cash concentration/disbursement plus (CCD+)',
|
||||
'44' => 'Accepted bill of exchange',
|
||||
'45' => 'Referenced home-banking credit transfer',
|
||||
'46' => 'Interbank debit transfer',
|
||||
'47' => 'Home-banking debit transfer',
|
||||
'48' => 'Bank card',
|
||||
'49' => 'Direct debit',
|
||||
'50' => 'Payment by postgiro',
|
||||
'51' => 'FR, norme 6 97-Telereglement CFONB (French Organisation for',
|
||||
'52' => 'Urgent commercial payment',
|
||||
'53' => 'Urgent Treasury Payment',
|
||||
'54' => 'Credit card',
|
||||
'55' => 'Debit card',
|
||||
'56' => 'Bankgiro',
|
||||
'57' => 'Standing agreement',
|
||||
'58' => 'SEPA credit transfer',
|
||||
'59' => 'SEPA direct debit',
|
||||
'60' => 'Promissory note',
|
||||
'61' => 'Promissory note signed by the debtor',
|
||||
'62' => 'Promissory note signed by the debtor and endorsed by a bank',
|
||||
'63' => 'Promissory note signed by the debtor and endorsed by a',
|
||||
'64' => 'Promissory note signed by a bank',
|
||||
'65' => 'Promissory note signed by a bank and endorsed by another',
|
||||
'66' => 'Promissory note signed by a third party',
|
||||
'67' => 'Promissory note signed by a third party and endorsed by a',
|
||||
'68' => 'Online payment service',
|
||||
'69' => 'Transfer Advice',
|
||||
'70' => 'Bill drawn by the creditor on the debtor',
|
||||
'74' => 'Bill drawn by the creditor on a bank',
|
||||
'75' => 'Bill drawn by the creditor, endorsed by another bank',
|
||||
'76' => 'Bill drawn by the creditor on a bank and endorsed by a',
|
||||
'77' => 'Bill drawn by the creditor on a third party',
|
||||
'78' => 'Bill drawn by creditor on third party, accepted and',
|
||||
'91' => 'Not transferable banker\'s draft',
|
||||
'92' => 'Not transferable local cheque',
|
||||
'93' => 'Reference giro',
|
||||
'94' => 'Urgent giro',
|
||||
'95' => 'Free format giro',
|
||||
'96' => 'Requested method for payment was not used',
|
||||
'97' => 'Clearing between partners',
|
||||
'ZZZ' => 'Mutually defined',
|
||||
];
|
||||
|
||||
public string $typecode = '1';
|
||||
|
||||
public ?string $information = null;
|
||||
|
||||
public ?string $cardType = null;
|
||||
|
||||
public ?string $cardId = null;
|
||||
|
||||
public ?string $cardHolderName = null;
|
||||
|
||||
public ?string $buyerIban = null;
|
||||
|
||||
public ?string $payeeIban = null;
|
||||
|
||||
public ?string $payeeAccountName = null;
|
||||
|
||||
public ?string $payeePropId = null;
|
||||
|
||||
public ?string $payeeBic = null;
|
||||
|
||||
public function __construct(mixed $existing_payment_means = null)
|
||||
{
|
||||
if($existing_payment_means){
|
||||
|
||||
$properties = get_object_vars($this);
|
||||
foreach ($properties as $property => $value) {
|
||||
if (property_exists($existing_payment_means, $property)) {
|
||||
$this->$property = $existing_payment_means->$property;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//requires an object which looks like this
|
||||
// @param string $typecode __BT-81, From BASIC WL__ The expected or used means of payment, expressed as a code. The entries from the UNTDID 4461 code list must be used. A distinction should be made between SEPA and non-SEPA payments as well
|
||||
// as between credit payments, direct debits, card payments and other means of payment
|
||||
// In particular, the following codes can be used:
|
||||
// * 10: cash -
|
||||
// 20: check -
|
||||
// 30: transfer -
|
||||
// 42: Payment to bank account -
|
||||
// 48: Card payment -
|
||||
// 49: direct debit -
|
||||
// 57: Standing order -
|
||||
// 58: SEPA Credit Transfer -
|
||||
// 59: SEPA Direct Debit -
|
||||
// 97: Report
|
||||
// *
|
||||
// * @param string|null $information __BT-82, From EN 16931__ The expected or used means of payment expressed in text form, e.g. cash, bank transfer, direct debit, credit card, etc.
|
||||
// * @param string|null $cardType __BT-, From __ The type of the card
|
||||
// * @param string|null $cardId __BT-84, From BASIC WL__ The primary account number (PAN) to which the card used for payment belongs. In accordance with card payment security standards, an invoice should never contain a full payment card master account number.
|
||||
//The following specification of the PCI Security Standards Council currently applies: The first 6 and last 4 digits at most are to be displayed
|
||||
// * @param string|null $cardHolderName __BT-, From __ Name of the payment card holder
|
||||
// * @param string|null $buyerIban __BT-91, From BASIC WL__ Direct debit: ID of the account to be debited
|
||||
// * @param string|null $payeeIban __BT-, From __ Transfer: A unique identifier for the financial account held with a payment service provider to which the payment should be made, e.g. Use an IBAN (in the case of a SEPA payment) for a national
|
||||
//ProprietaryID account number
|
||||
// * @param string|null $payeeAccountName __BT-, From __ The name of the payment account held with a payment service provider to which the payment should be made. Information only required if different from the name of the payee / seller
|
||||
// * @param string|null $payeePropId __BT-, From __ National account number (not for SEPA)
|
||||
// * @param string|null $payeeBic __BT-, From __ Seller's banking institution, An identifier for the payment service provider with whom the payment account is managed, such as the BIC or a national bank code, if required. No identification scheme is to be used.
|
||||
// *
|
||||
public function run()
|
||||
{
|
||||
|
||||
|
||||
// ->getTradeSettlementPaymentMeansType($typecode, $information);
|
||||
// ->getTradeSettlementFinancialCardType($cardType, $cardId, $cardHolderName);
|
||||
|
||||
|
||||
$TradeSettlementFinancialCardType = new \horstoeko\zugferd\entities\extended\ram\TradeSettlementFinancialCardType();
|
||||
$TradeSettlementFinancialCardType->setCardholderName($this->cardHolderName)
|
||||
->setID(new \horstoeko\zugferd\entities\extended\udt\IDType($this->cardId));
|
||||
|
||||
$DebtorFinancialAccountType = new \horstoeko\zugferd\entities\extended\ram\DebtorFinancialAccountType();
|
||||
$DebtorFinancialAccountType->setIBANID(new \horstoeko\zugferd\entities\extended\udt\IDType($this->buyerIban));
|
||||
|
||||
$CreditorFinancialAccountType = new \horstoeko\zugferd\entities\extended\ram\CreditorFinancialAccountType();
|
||||
$CreditorFinancialAccountType->setAccountName($this->payeeAccountName)
|
||||
->setProprietaryID(new \horstoeko\zugferd\entities\extended\udt\IDType($this->payeePropId))
|
||||
->setIBANID(new \horstoeko\zugferd\entities\extended\udt\IDType($this->payeeIban));
|
||||
|
||||
$CreditorFinancialInstitutionType = new \horstoeko\zugferd\entities\extended\ram\CreditorFinancialInstitutionType();
|
||||
$CreditorFinancialInstitutionType->setBICID(new \horstoeko\zugferd\entities\extended\udt\IDType($this->payeeBic));
|
||||
|
||||
$TradeSettlementPaymentMeansType = new \horstoeko\zugferd\entities\extended\ram\TradeSettlementPaymentMeansType();
|
||||
$TradeSettlementPaymentMeansType->setTypeCode($this->typecode)->setInformation($this->information);
|
||||
$TradeSettlementPaymentMeansType->setPayeePartyCreditorFinancialAccount($CreditorFinancialAccountType);
|
||||
$TradeSettlementPaymentMeansType->setPayerPartyDebtorFinancialAccount($DebtorFinancialAccountType);
|
||||
$TradeSettlementPaymentMeansType->setApplicableTradeSettlementFinancialCard($TradeSettlementFinancialCardType);
|
||||
$TradeSettlementPaymentMeansType->setPayeeSpecifiedCreditorFinancialInstitution($CreditorFinancialInstitutionType);
|
||||
|
||||
$HeaderTradeSettlementType = new \horstoeko\zugferd\entities\extended\ram\HeaderTradeSettlementType();
|
||||
$HeaderTradeSettlementType->addToSpecifiedTradeSettlementPaymentMeans($TradeSettlementPaymentMeansType);
|
||||
|
||||
$SupplyChainTradeTransactionType = new \horstoeko\zugferd\entities\extended\ram\SupplyChainTradeTransactionType();
|
||||
$SupplyChainTradeTransactionType->setApplicableHeaderTradeSettlement($HeaderTradeSettlementType);
|
||||
|
||||
}
|
||||
|
||||
}
|
108
app/Services/EDocument/Adapters/UBL/PaymentMeans.php
Normal file
108
app/Services/EDocument/Adapters/UBL/PaymentMeans.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?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\Adapters\UBL;
|
||||
|
||||
use App\Services\EDocument\Interfaces\PaymentMeansInterface;
|
||||
|
||||
class PaymentMeans implements PaymentMeansInterface
|
||||
{
|
||||
public array $payment_means_codelist = [
|
||||
'1' => 'Instrument not defined',
|
||||
'2' => 'Automated clearing house credit',
|
||||
'3' => 'Automated clearing house debit',
|
||||
'4' => 'ACH demand debit reversal',
|
||||
'5' => 'ACH demand credit reversal',
|
||||
'6' => 'ACH demand credit',
|
||||
'7' => 'ACH demand debit',
|
||||
'8' => 'Hold',
|
||||
'9' => 'National or regional clearing',
|
||||
'10' => 'In cash',
|
||||
'11' => 'ACH savings credit reversal',
|
||||
'12' => 'ACH savings debit reversal',
|
||||
'13' => 'ACH savings credit',
|
||||
'14' => 'ACH savings debit',
|
||||
'15' => 'Bookentry credit',
|
||||
'16' => 'Bookentry debit',
|
||||
'17' => 'ACH demand cash concentration/disbursement (CCD) credit',
|
||||
'18' => 'ACH demand cash concentration/disbursement (CCD) debit',
|
||||
'19' => 'ACH demand corporate trade payment (CTP) credit',
|
||||
'20' => 'Cheque',
|
||||
'21' => 'Banker\'s draft',
|
||||
'22' => 'Certified banker\'s draft',
|
||||
'23' => 'Bank cheque (issued by a banking or similar establishment)',
|
||||
'24' => 'Bill of exchange awaiting acceptance',
|
||||
'25' => 'Certified cheque',
|
||||
'26' => 'Local cheque',
|
||||
'27' => 'ACH demand corporate trade payment (CTP) debit',
|
||||
'28' => 'ACH demand corporate trade exchange (CTX) credit',
|
||||
'29' => 'ACH demand corporate trade exchange (CTX) debit',
|
||||
'30' => 'Credit transfer',
|
||||
'31' => 'Debit transfer',
|
||||
'32' => 'ACH demand cash concentration/disbursement plus (CCD+)',
|
||||
'33' => 'ACH demand cash concentration/disbursement plus (CCD+)',
|
||||
'34' => 'ACH prearranged payment and deposit (PPD)',
|
||||
'35' => 'ACH savings cash concentration/disbursement (CCD) credit',
|
||||
'36' => 'ACH savings cash concentration/disbursement (CCD) debit',
|
||||
'37' => 'ACH savings corporate trade payment (CTP) credit',
|
||||
'38' => 'ACH savings corporate trade payment (CTP) debit',
|
||||
'39' => 'ACH savings corporate trade exchange (CTX) credit',
|
||||
'40' => 'ACH savings corporate trade exchange (CTX) debit',
|
||||
'41' => 'ACH savings cash concentration/disbursement plus (CCD+)',
|
||||
'42' => 'Payment to bank account',
|
||||
'43' => 'ACH savings cash concentration/disbursement plus (CCD+)',
|
||||
'44' => 'Accepted bill of exchange',
|
||||
'45' => 'Referenced home-banking credit transfer',
|
||||
'46' => 'Interbank debit transfer',
|
||||
'47' => 'Home-banking debit transfer',
|
||||
'48' => 'Bank card',
|
||||
'49' => 'Direct debit',
|
||||
'50' => 'Payment by postgiro',
|
||||
'51' => 'FR, norme 6 97-Telereglement CFONB (French Organisation for',
|
||||
'52' => 'Urgent commercial payment',
|
||||
'53' => 'Urgent Treasury Payment',
|
||||
'54' => 'Credit card',
|
||||
'55' => 'Debit card',
|
||||
'56' => 'Bankgiro',
|
||||
'57' => 'Standing agreement',
|
||||
'58' => 'SEPA credit transfer',
|
||||
'59' => 'SEPA direct debit',
|
||||
'60' => 'Promissory note',
|
||||
'61' => 'Promissory note signed by the debtor',
|
||||
'62' => 'Promissory note signed by the debtor and endorsed by a bank',
|
||||
'63' => 'Promissory note signed by the debtor and endorsed by a',
|
||||
'64' => 'Promissory note signed by a bank',
|
||||
'65' => 'Promissory note signed by a bank and endorsed by another',
|
||||
'66' => 'Promissory note signed by a third party',
|
||||
'67' => 'Promissory note signed by a third party and endorsed by a',
|
||||
'68' => 'Online payment service',
|
||||
'69' => 'Transfer Advice',
|
||||
'70' => 'Bill drawn by the creditor on the debtor',
|
||||
'74' => 'Bill drawn by the creditor on a bank',
|
||||
'75' => 'Bill drawn by the creditor, endorsed by another bank',
|
||||
'76' => 'Bill drawn by the creditor on a bank and endorsed by a',
|
||||
'77' => 'Bill drawn by the creditor on a third party',
|
||||
'78' => 'Bill drawn by creditor on third party, accepted and',
|
||||
'91' => 'Not transferable banker\'s draft',
|
||||
'92' => 'Not transferable local cheque',
|
||||
'93' => 'Reference giro',
|
||||
'94' => 'Urgent giro',
|
||||
'95' => 'Free format giro',
|
||||
'96' => 'Requested method for payment was not used',
|
||||
'97' => 'Clearing between partners',
|
||||
'ZZZ' => 'Mutually defined',
|
||||
];
|
||||
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -222,7 +222,7 @@ class Storecove
|
||||
}
|
||||
|
||||
$company_defaults = [
|
||||
'acts_as_receiver' => true,
|
||||
'acts_as_receiver' => false,
|
||||
'acts_as_sender' => true,
|
||||
'advertisements' => ['invoice'],
|
||||
];
|
||||
|
@ -11,12 +11,13 @@
|
||||
|
||||
namespace App\Services\EDocument\Imports;
|
||||
|
||||
use Exception;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Company;
|
||||
use App\Models\Expense;
|
||||
use App\Services\AbstractService;
|
||||
use App\Utils\Ninja;
|
||||
use Exception;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use App\Services\EDocument\Imports\UblEDocument;
|
||||
|
||||
class ParseEDocument extends AbstractService
|
||||
{
|
||||
@ -36,10 +37,12 @@ class ParseEDocument extends AbstractService
|
||||
* @developer the function should be implemented with local first aproach to save costs of external providers (like mindee ocr)
|
||||
*
|
||||
* @return Expense
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function run(): Expense
|
||||
{
|
||||
nlog("starting");
|
||||
nlog($this->company->id);
|
||||
|
||||
/** @var \App\Models\Account $account */
|
||||
$account = $this->company->owner()->account;
|
||||
@ -50,14 +53,23 @@ class ParseEDocument extends AbstractService
|
||||
// ZUGFERD - try to parse via Zugferd lib
|
||||
switch (true) {
|
||||
case ($extension == 'pdf' || $mimetype == 'application/pdf'):
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:cen.eu:en16931:2017"):
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0"):
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_2.1"):
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_2.0"):
|
||||
try {
|
||||
return (new ZugferdEDocument($this->file, $this->company))->run();
|
||||
} catch (Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
nlog("Zugferd Exception: " . $e->getMessage());
|
||||
break;
|
||||
}
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:cen.eu:en16931:2017"):
|
||||
case ($extension == 'xml' || $mimetype == 'application/xml') && stristr($this->file->get(), "urn:oasis:names:specification:ubl"):
|
||||
try {
|
||||
return (new UblEDocument($this->file, $this->company))->run();
|
||||
}
|
||||
catch(\Throwable $e){
|
||||
nlog("UBL Import Exception: " . $e->getMessage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
284
app/Services/EDocument/Imports/Ubl2Pdf.php
Normal file
284
app/Services/EDocument/Imports/Ubl2Pdf.php
Normal file
@ -0,0 +1,284 @@
|
||||
<?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\Imports;
|
||||
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Company;
|
||||
use App\Models\Country;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Currency;
|
||||
use App\Factory\VendorFactory;
|
||||
use App\Factory\ExpenseFactory;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use InvoiceNinja\EInvoice\EInvoice;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use App\Factory\VendorContactFactory;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
use App\Services\Template\TemplateService;
|
||||
|
||||
class Ubl2Pdf extends AbstractService
|
||||
{
|
||||
|
||||
/**
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function __construct(public \InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice, public Company $company)
|
||||
{
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
App::setLocale($this->company->locale());
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
$template = file_get_contents(resource_path('views/templates/ubl/td14.html'));
|
||||
// nlog($client);
|
||||
// nlog($supplier);
|
||||
// nlog($invoiceDetails);
|
||||
// nlog($totals);
|
||||
|
||||
$data = [
|
||||
'client' => $this->clientDetails(),
|
||||
'supplier' => $this->supplierDetails(),
|
||||
'invoiceDetails' => $this->invoiceDetails(),
|
||||
'totals' => $this->totals(),
|
||||
'metadata' => $this->metadata(),
|
||||
'translations' => $this->getGenericTranslations(),
|
||||
'css' => $this->customCss(),
|
||||
];
|
||||
|
||||
$ts = new TemplateService();
|
||||
|
||||
$ts_instance = $ts->setCompany($this->company)
|
||||
->setData($data)
|
||||
->setRawTemplate($template)
|
||||
->parseNinjaBlocks()
|
||||
->save();
|
||||
|
||||
nlog($ts_instance->getHtml());
|
||||
|
||||
}
|
||||
|
||||
private function getGenericTranslations(): array
|
||||
{
|
||||
return [
|
||||
'to' => ctrans('texts.to'),
|
||||
'from' => ctrans('texts.from'),
|
||||
'invoice' => ctrans('texts.invoice'),
|
||||
'credit' => ctrans('texts.credit'),
|
||||
'details' => ctrans('texts.details'),
|
||||
'number' => ctrans('texts.number'),
|
||||
'tax' => ctrans('texts.tax'),
|
||||
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
// 'from' => ctrans('texts.from'),
|
||||
];
|
||||
}
|
||||
|
||||
private function processValues(array $array): array
|
||||
{
|
||||
|
||||
foreach($array as $key => $value)
|
||||
{
|
||||
if($value === null || $value === '')
|
||||
unset($array[$key]);
|
||||
|
||||
if($value instanceof \DateTime)
|
||||
$array[$key] = $value->format($this->company->date_format());
|
||||
}
|
||||
|
||||
return $array;
|
||||
|
||||
}
|
||||
|
||||
private function clientDetails(): array
|
||||
{
|
||||
return $this->processValues([
|
||||
ctrans('texts.name') => data_get($this->invoice, 'AccountingCustomerParty.Party.PartyName.0.Name',''),
|
||||
ctrans('texts.address1') => data_get($this->invoice, 'AccountingCustomerParty.Party.PostalAddress.StreetName',''),
|
||||
ctrans('texts.address2') => data_get($this->invoice, 'AccountingCustomerParty.Party.PostalAddress.AdditionalStreetName',''),
|
||||
ctrans('texts.city') => data_get($this->invoice, 'AccountingCustomerParty.Party.PostalAddress.CityName',''),
|
||||
ctrans('texts.state') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.CountrySubentity',''),
|
||||
ctrans('texts.postal_code') => data_get($this->invoice, 'AccountingCustomerParty.Party.PostalAddress.PostalZone',''),
|
||||
ctrans('texts.country_id') => data_get($this->invoice, 'AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode.value',''),
|
||||
ctrans('texts.vat_number') => data_get($this->invoice, 'AccountingCustomerParty.Party.PartyTaxScheme.0.CompanyID.value',''),
|
||||
ctrans('texts.contact_name') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.Name',''),
|
||||
ctrans('texts.phone') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.Telephone',''),
|
||||
ctrans('texts.email') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.ElectronicMail',''),
|
||||
]);
|
||||
}
|
||||
|
||||
private function supplierDetails(): array
|
||||
{
|
||||
return $this->processValues([
|
||||
ctrans('texts.name') => data_get($this->invoice, 'AccountingSupplierParty.Party.PartyName.0.Name', ''),
|
||||
ctrans('texts.address1') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.StreetName', ''),
|
||||
ctrans('texts.address2') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.AdditionalStreetName', ''),
|
||||
ctrans('texts.city') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.CityName', ''),
|
||||
ctrans('texts.state') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.CountrySubentity', ''),
|
||||
ctrans('texts.postal_code') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.PostalZone', ''),
|
||||
ctrans('texts.country_id') => data_get($this->invoice, 'AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode.value', ''),
|
||||
ctrans('texts.routing_id') => data_get($this->invoice, 'AccountingSupplierParty.Party.EndpointID.value', ''),
|
||||
ctrans('texts.id_number') => data_get($this->invoice, 'AccountingSupplierParty.Party.PartyIdentification.0.ID.value', false),
|
||||
ctrans('texts.vat_number') => data_get($this->invoice, 'AccountingSupplierParty.Party.PartyTaxScheme.0.CompanyID.value', ''),
|
||||
// ctrans('texts.currency_id') => $this->resolveCurrencyId(data_get($this->invoice, 'DocumentCurrencyCode.value', $this->company->currency()->code)),
|
||||
ctrans('texts.contact_name') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.Name', ''),
|
||||
ctrans('texts.phone') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.Telephone', ''),
|
||||
ctrans('texts.email') => data_get($this->invoice, 'AccountingCustomerParty.Party.Contact.ElectronicMail', ''),
|
||||
]);
|
||||
}
|
||||
|
||||
private function customCss(): string
|
||||
{
|
||||
$css = '';
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.product_key'))." { width: 15%;} ";
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.quantity'))." { width: 8%;} ";
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.notes'))." { width: 40%; } ";
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.cost'))." { width:10%;} ";
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.tax'))." { width:10%;} ";
|
||||
$css .= ".".str_replace(" ", "", ctrans('texts.line_total'))." { width:15%;} ";
|
||||
|
||||
return $css;
|
||||
|
||||
}
|
||||
|
||||
private function invoiceDetails(): array
|
||||
{
|
||||
|
||||
$data = $this->processValues([
|
||||
ctrans('texts.currency') => data_get($this->invoice, 'DocumentCurrencyCode.value', $this->company->currency()->code),
|
||||
ctrans('texts.currency_code') => data_get($this->invoice, 'InvoiceTypeCode.value', "380"),
|
||||
ctrans('texts.number') => data_get($this->invoice, 'ID.value', ''),
|
||||
ctrans('texts.date') => data_get($this->invoice, 'IssueDate', ''),
|
||||
ctrans('texts.due_date') => data_get($this->invoice, 'DueDate', ''),
|
||||
]);
|
||||
|
||||
$data['line_items'] = $this->invoiceLines();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function metadata(): array
|
||||
{
|
||||
|
||||
return $this->processValues([
|
||||
'currency' => data_get($this->invoice, 'DocumentCurrencyCode.value', $this->company->currency()->code),
|
||||
ctrans('texts.terms') => $this->harvestTerms(),
|
||||
ctrans('texts.public_notes') => data_get($this->invoice, 'Note', '')
|
||||
]);
|
||||
}
|
||||
|
||||
private function harvestTerms(): string
|
||||
{
|
||||
|
||||
$payment_means = [];
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentMeans.0.PaymentMeansCode.name', false);
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentMeans.0.PaymentID.value', false);
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentMeans.0.PayeeFinancialAccount.ID.value', false);
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentMeans.0.PayeeFinancialAccount.Name', false);
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentMeans.0.PayeeFinancialAccount.FinancialInstitutionBranch.ID.value', false);
|
||||
$payment_means[] = data_get($this->invoice, 'PaymentTerms.0.Note', false);
|
||||
|
||||
$private_notes = collect($payment_means)
|
||||
->reject(function ($means) {
|
||||
return $means === false;
|
||||
})->implode("\n");
|
||||
|
||||
return $private_notes;
|
||||
|
||||
}
|
||||
|
||||
private function invoiceLines(): array
|
||||
{
|
||||
$lines = data_get($this->invoice, 'InvoiceLine', []);
|
||||
|
||||
return array_map(function ($line) {
|
||||
return [
|
||||
ctrans('texts.product_key') => data_get($line, 'Item.Name', ''),
|
||||
// ctrans('texts.ocde') => data_get($line, 'InvoicedQuantity.UnitCode',''),
|
||||
ctrans('texts.quantity') => Number::formatValue(data_get($line, 'InvoicedQuantity.amount', 0), $this->company->currency()),
|
||||
ctrans('texts.notes') => data_get($line, 'Item.Description', ''),
|
||||
ctrans('texts.cost') => Number::formatValue(data_get($line, 'Price.PriceAmount.amount', 0), $this->company->currency()),
|
||||
'tax_name1' => data_get($line, 'Item.ClassifiedTaxCategory.0.TaxScheme.ID.value', ''),
|
||||
'tax_rate1' => data_get($line, 'Item.ClassifiedTaxCategory.0.Percent', 0),
|
||||
'tax_name2' => data_get($line, 'Item.ClassifiedTaxCategory.1.TaxScheme.ID.value', ''),
|
||||
'tax_rate2' => data_get($line, 'Item.ClassifiedTaxCategory.1.Percent', 0),
|
||||
'tax_name3' => data_get($line, 'Item.ClassifiedTaxCategory.2.TaxScheme.ID.value', ''),
|
||||
'tax_rate3' => data_get($line, 'Item.ClassifiedTaxCategory.2.Percent', 0),
|
||||
ctrans('texts.line_total') => Number::formatValue(data_get($line, 'LineExtensionAmount.amount', 0), $this->company->currency()),
|
||||
];
|
||||
}, $lines);
|
||||
}
|
||||
|
||||
private function totals(): array
|
||||
{
|
||||
$tax_inc = data_get($this->invoice, 'LegalMonetaryTotal.TaxInclusiveAmount.amount', 0);
|
||||
$tax_ex = data_get($this->invoice, 'LegalMonetaryTotal.TaxExclusiveAmount.amount', 0);
|
||||
$tax_amount = data_get($this->invoice, 'TaxTotal.0.TaxAmount', 0);
|
||||
|
||||
$taxes = [];
|
||||
|
||||
foreach(data_get($this->invoice, 'TaxTotal.0.TaxSubtotal', []) as $tax_subtotal)
|
||||
{
|
||||
$taxes[] = [
|
||||
'subtotal' => data_get($tax_subtotal, 'TaxAmount.amount', 0),
|
||||
'tax_name' => data_get($tax_subtotal, 'TaxCategory.TaxScheme.ID.value', ''),
|
||||
'tax_rate' => data_get($tax_subtotal, 'TaxCategory.Percent', 0),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'subtotal' => [
|
||||
ctrans('texts.subtotal') => data_get($this->invoice, 'LegalMonetaryTotal.LineExtensionAmount.amount', 0),
|
||||
],
|
||||
'balance' => [
|
||||
ctrans('texts.balance_due') => data_get($this->invoice, 'LegalMonetaryTotal.TaxInclusiveAmount.amount', 0),
|
||||
],
|
||||
'taxes' => $taxes,
|
||||
];
|
||||
}
|
||||
|
||||
// private function resolveCountry(?string $iso_country_code): int
|
||||
// {
|
||||
// return Country::query()
|
||||
// ->where('iso_3166_2', $iso_country_code)
|
||||
// ->orWhere('iso_3166_3', $iso_country_code)
|
||||
// ->first()?->id ?? (int)$this->company->settings->country_id;
|
||||
// }
|
||||
|
||||
|
||||
// private function resolveCurrencyId(string $currency_code): int
|
||||
// {
|
||||
|
||||
// /** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
||||
// $currencies = app('currencies');
|
||||
|
||||
// return $currencies->first(function (Currency $c) use ($currency_code) {
|
||||
// return $c->code === $currency_code;
|
||||
// })?->id ?? (int) $this->company->settings->currency_id;
|
||||
// }
|
||||
}
|
271
app/Services/EDocument/Imports/UblEDocument.php
Normal file
271
app/Services/EDocument/Imports/UblEDocument.php
Normal file
@ -0,0 +1,271 @@
|
||||
<?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\Imports;
|
||||
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Company;
|
||||
use App\Models\Country;
|
||||
use App\Models\Expense;
|
||||
use App\Factory\VendorFactory;
|
||||
use App\Factory\ExpenseFactory;
|
||||
use App\Services\AbstractService;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
|
||||
use InvoiceNinja\EInvoice\EInvoice;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use App\Factory\VendorContactFactory;
|
||||
use App\Models\Currency;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
|
||||
class UblEDocument extends AbstractService
|
||||
{
|
||||
use SavesDocuments;
|
||||
|
||||
/**
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function __construct(public UploadedFile $file, public Company $company)
|
||||
{
|
||||
# curl -X POST http://localhost:8000/api/v1/edocument/upload -H "Content-Type: multipart/form-data" -H "X-API-TOKEN: 7tdDdkz987H3AYIWhNGXy8jTjJIoDhkAclCDLE26cTCj1KYX7EBHC66VEitJwWhn" -H "X-Requested-With: XMLHttpRequest" -F _method=PUT -F documents[]=@einvoice.xml
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function run(): \App\Models\Expense
|
||||
{
|
||||
|
||||
$e = new EInvoice();
|
||||
|
||||
$invoice = $e->decode('Peppol', $this->file->get(), 'xml');
|
||||
|
||||
return $this->buildAndSaveExpense($invoice);
|
||||
|
||||
}
|
||||
|
||||
private function buildAndSaveExpense(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice): Expense
|
||||
{
|
||||
|
||||
$vendor = $this->findOrCreateVendor($invoice);
|
||||
|
||||
$TaxExclusiveAmount = data_get($invoice, 'LegalMonetaryTotal.TaxExclusiveAmount.amount', 0);
|
||||
$TaxInclusiveAmount = data_get($invoice, 'LegalMonetaryTotal.TaxExclusiveAmount.amount', 0);
|
||||
$ChargeTotalAmount = data_get($invoice, 'LegalMonetaryTotal.ChargeTotalAmount.amount', 0);
|
||||
$PayableAmount = data_get($invoice, 'LegalMonetaryTotal.PayableAmount.amount', 0);
|
||||
$TaxAmount = data_get($invoice, 'TaxTotal.0.TaxAmount.amount', 0);
|
||||
$tax_sub_totals = data_get($invoice, 'TaxTotal.0.TaxSubtotal', []);
|
||||
$currency_code = data_get($invoice, 'DocumentCurrencyCode.value', $this->company->currency()->code);
|
||||
$date = data_get($invoice, 'IssueDate', now()->format('Y-m-d'));
|
||||
|
||||
$payment_means = [];
|
||||
$payment_means[] = data_get($invoice, 'PaymentMeans.0.PaymentMeansCode.name', false);
|
||||
$payment_means[] = data_get($invoice, 'PaymentMeans.0.PaymentID.value', false);
|
||||
$payment_means[] = data_get($invoice, 'PaymentMeans.0.PayeeFinancialAccount.ID.value', false);
|
||||
$payment_means[] = data_get($invoice, 'PaymentMeans.0.PayeeFinancialAccount.Name', false);
|
||||
$payment_means[] = data_get($invoice, 'PaymentMeans.0.PayeeFinancialAccount.FinancialInstitutionBranch.ID.value', false);
|
||||
$payment_means[] = data_get($invoice, 'PaymentTerms.0.Note', false);
|
||||
|
||||
$private_notes = collect($payment_means)
|
||||
->reject(function ($means){
|
||||
return $means === false;
|
||||
})->implode("\n");
|
||||
|
||||
$invoice_items = data_get($invoice, 'InvoiceLine', []);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach($invoice_items as $key => $item)
|
||||
{
|
||||
$items[$key]['name'] = data_get($item, 'Item.Name', false);
|
||||
$items[$key]['description'] = data_get($item, 'Item.Description', false);
|
||||
}
|
||||
|
||||
$public_notes = collect($items)->reject(function ($item){
|
||||
return $item['name'] === false && $item['description'] === false;
|
||||
})->map(function ($item){
|
||||
return $item['name'] ?? ' ' . ' ## '. $item['description'] ?? ' '; //@phpstan-ignore-line
|
||||
})->implode("\n");
|
||||
|
||||
/** @var \App\Models\Expense $expense */
|
||||
$expense = ExpenseFactory::create($this->company->id, $this->company->owner()->id);
|
||||
$expense->vendor_id = $vendor->id;
|
||||
$expense->amount = $this->company->expense_inclusive_taxes ? $TaxInclusiveAmount : $TaxExclusiveAmount;
|
||||
$expense->currency_id = $this->resolveCurrencyId($currency_code);
|
||||
$expense->date = $date;
|
||||
$expense->private_notes = $private_notes;
|
||||
$expense->public_notes = $public_notes;
|
||||
|
||||
$tax_level = 1;
|
||||
|
||||
foreach ($tax_sub_totals as $key => $sub_tax) {
|
||||
$amount = data_get($sub_tax, 'TaxAmount.amount', 0);
|
||||
$taxable_amount = data_get($sub_tax, 'TaxableAmount.amount', 0);
|
||||
$tax_rate = data_get($sub_tax, 'TaxCategory.Percent', 0);
|
||||
$id = data_get($sub_tax, 'TaxCategory.ID.value', '');
|
||||
$tax_name = data_get($sub_tax, 'TaxCategory.TaxScheme.ID.value', '');
|
||||
|
||||
if (!$this->company->calculate_expense_tax_by_amount && $tax_rate > 0) {
|
||||
|
||||
$expense->{"tax_rate{$tax_level}"} = $tax_rate;
|
||||
$expense->{"tax_name{$tax_level}"} = $tax_name;
|
||||
$expense->calculate_tax_by_amount = false;
|
||||
|
||||
}
|
||||
else {
|
||||
$expense->calculate_tax_by_amount = true;
|
||||
$expense->{"tax_amount{$tax_level}"} = $amount; //@phpstan-ignore-line
|
||||
|
||||
}
|
||||
|
||||
$tax_level++;
|
||||
|
||||
if ($tax_level == 4) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$expense->save();
|
||||
|
||||
$repo = new ExpenseRepository();
|
||||
|
||||
$data = [];
|
||||
$data['documents'][] = $this->file;
|
||||
|
||||
$expense = $repo->save($data, $expense);
|
||||
|
||||
return $expense;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function resolveCurrencyId(string $currency_code): int
|
||||
{
|
||||
|
||||
/** @var \Illuminate\Support\Collection<\App\Models\Currency> */
|
||||
$currencies = app('currencies');
|
||||
|
||||
return $currencies->first(function (Currency $c) use ($currency_code) {
|
||||
return $c->code === $currency_code;
|
||||
})?->id ?? (int) $this->company->settings->currency_id;
|
||||
}
|
||||
|
||||
private function findOrCreateVendor(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice): Vendor
|
||||
{
|
||||
$asp = $invoice->AccountingSupplierParty;
|
||||
|
||||
$vat_number = $this->resolveVendorVat($invoice);
|
||||
$id_number = $this->resolveVendorIdNumber($invoice);
|
||||
$routing_id = data_get($invoice, 'AccountingSupplierParty.Party.EndpointID.value', false);
|
||||
$vendor_name = $this->resolveSupplierName($invoice);
|
||||
|
||||
$vendor = Vendor::query()
|
||||
->where('company_id', $this->company->id)
|
||||
->where(function ($q) use ($vat_number, $routing_id, $id_number, $vendor_name){
|
||||
|
||||
$q->when($routing_id, function ($q) use ($routing_id){
|
||||
$q->where('routing_id', $routing_id);
|
||||
})
|
||||
->when(strlen($vat_number) > 1, function ($q) use ($vat_number){
|
||||
$q->orWhere('vat_number', $vat_number);
|
||||
})
|
||||
->when(strlen($id_number) > 1, function ($q) use ($id_number){
|
||||
$q->orWhere('id_number', $id_number);
|
||||
})
|
||||
->when(strlen($vendor_name) > 1, function ($q) use ($vendor_name){
|
||||
$q->orWhere('name', $vendor_name);
|
||||
});
|
||||
|
||||
})->first();
|
||||
|
||||
return $vendor ?? $this->newVendor($invoice);
|
||||
}
|
||||
|
||||
private function resolveSupplierName(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice): string
|
||||
{
|
||||
if(data_get($invoice, 'AccountingSupplierParty.Party.PartyName', false)){
|
||||
$party_name = data_get($invoice, 'AccountingSupplierParty.Party.PartyName', false);
|
||||
return data_get($party_name[0], 'Name', '');
|
||||
}
|
||||
|
||||
if (data_get($invoice, 'AccountingSupplierParty.Party.PartyLegalEntity', false)) {
|
||||
$ple = data_get($invoice, 'AccountingSupplierParty.Party.PartyName', false);
|
||||
return data_get($ple[0], 'RegistrationName', '');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function resolveVendorIdNumber(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice):string
|
||||
{
|
||||
|
||||
$pts = data_get($invoice, 'AccountingSupplierParty.Party.PartyIdentification', false);
|
||||
|
||||
return $pts ? data_get($pts[0], 'ID.value', '') : '';
|
||||
|
||||
}
|
||||
|
||||
private function resolveVendorVat(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice):string
|
||||
{
|
||||
|
||||
$pts = data_get($invoice, 'AccountingSupplierParty.Party.PartyTaxScheme', false);
|
||||
|
||||
return $pts ? data_get($pts[0], 'CompanyID.value', '') : '';
|
||||
|
||||
}
|
||||
|
||||
private function newVendor(\InvoiceNinja\EInvoice\Models\Peppol\Invoice $invoice): Vendor
|
||||
{
|
||||
$vendor = VendorFactory::create($this->company->id, $this->company->owner()->id);
|
||||
|
||||
|
||||
$data = [
|
||||
'name' => $this->resolveSupplierName($invoice),
|
||||
'routing_id' => data_get($invoice, 'AccountingSupplierParty.Party.EndpointID.value', ''),
|
||||
'vat_number' => $this->resolveVendorVat($invoice),
|
||||
'id_number' => $this->resolveVendorIdNumber($invoice),
|
||||
'address1' => data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.StreetName',''),
|
||||
'address2' => data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.AdditionalStreetName',''),
|
||||
'city' => data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.CityName',''),
|
||||
'state' => data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.CountrySubentity',''),
|
||||
'postal_code' => data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.PostalZone',''),
|
||||
'country_id' => $this->resolveCountry(data_get($invoice, 'AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode.value','')),
|
||||
'currency_id' => $this->resolveCurrencyId(data_get($invoice, 'DocumentCurrencyCode.value', $this->company->currency()->code)),
|
||||
];
|
||||
|
||||
$vendor->fill($data);
|
||||
$vendor->save();
|
||||
|
||||
$vendor->service()->applyNumber();
|
||||
|
||||
if(data_get($invoice, 'AccountingSupplierParty.Party.Contact',false))
|
||||
{
|
||||
$vc = VendorContactFactory::create($this->company->id, $this->company->owner()->id);
|
||||
$vc->vendor_id = $vendor->id;
|
||||
$vc->first_name = data_get($invoice, 'AccountingSupplierParty.Party.Contact.Name','');
|
||||
$vc->phone = data_get($invoice, 'AccountingSupplierParty.Party.Contact.Telephone', '');
|
||||
$vc->email = data_get($invoice, 'AccountingSupplierParty.Party.Contact.ElectronicMail', '');
|
||||
$vc->save();
|
||||
}
|
||||
|
||||
return $vendor->fresh();
|
||||
|
||||
}
|
||||
|
||||
private function resolveCountry(?string $iso_country_code): int
|
||||
{
|
||||
return Country::query()
|
||||
->where('iso_3166_2', $iso_country_code)
|
||||
->orWhere('iso_3166_3', $iso_country_code)
|
||||
->first()?->id ?? (int)$this->company->settings->country_id;
|
||||
}
|
||||
}
|
@ -24,6 +24,9 @@ use App\Utils\TempFile;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use Exception;
|
||||
use App\Models\Company;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
use App\Repositories\VendorContactRepository;
|
||||
use App\Repositories\VendorRepository;
|
||||
use horstoeko\zugferd\ZugferdDocumentReader;
|
||||
use horstoeko\zugferdvisualizer\ZugferdVisualizer;
|
||||
use horstoeko\zugferdvisualizer\renderer\ZugferdVisualizerLaravelRenderer;
|
||||
@ -90,6 +93,7 @@ class ZugferdEDocument extends AbstractService
|
||||
$this->document->getDocumentTax($categoryCode, $typeCode, $basisAmount, $calculatedAmount, $rateApplicablePercent, $exemptionReason, $exemptionReasonCode, $lineTotalBasisAmount, $allowanceChargeBasisAmount, $taxPointDate, $dueDateTypeCode);
|
||||
$expense->{"tax_amount$counter"} = $calculatedAmount;
|
||||
$expense->{"tax_rate$counter"} = $rateApplicablePercent;
|
||||
$expense->{"tax_name$counter"} = $typeCode;
|
||||
$counter++;
|
||||
} while ($this->document->nextDocumentTax());
|
||||
}
|
||||
@ -137,17 +141,22 @@ class ZugferdEDocument extends AbstractService
|
||||
if ($country)
|
||||
$vendor->country_id = $country->id;
|
||||
|
||||
$vendor->save();
|
||||
$vendor_repo = new VendorRepository(new VendorContactRepository());
|
||||
$vendor = $vendor_repo->save([], $vendor);
|
||||
|
||||
$expense->vendor_id = $vendor->id;
|
||||
}
|
||||
$expense->transaction_reference = $documentno;
|
||||
} else {
|
||||
// The document exists as an expense
|
||||
// Handle accordingly
|
||||
nlog("Zugferd: Document already exists");
|
||||
nlog("Zugferd: Document already exists {$expense->hashed_id}");
|
||||
$expense->private_notes = $expense->private_notes . ctrans("texts.edocument_import_already_exists", ["date" => time()]);
|
||||
}
|
||||
$expense->save();
|
||||
|
||||
$expense_repo = new ExpenseRepository();
|
||||
$expense = $expense_repo->save([],$expense);
|
||||
|
||||
return $expense;
|
||||
}
|
||||
}
|
||||
|
17
app/Services/EDocument/Interfaces/PaymentMeansInterface.php
Normal file
17
app/Services/EDocument/Interfaces/PaymentMeansInterface.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?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\Interfaces;
|
||||
|
||||
interface PaymentMeansInterface
|
||||
{
|
||||
public function run();
|
||||
}
|
@ -992,7 +992,6 @@ class Peppol extends AbstractService
|
||||
$physical_location->Address = $address;
|
||||
|
||||
$party->PhysicalLocation = $physical_location;
|
||||
;
|
||||
|
||||
$contact = new Contact();
|
||||
$contact->ElectronicMail = $this->invoice->client->present()->email();
|
||||
|
@ -622,7 +622,7 @@ class Email implements ShouldQueue
|
||||
$company = $this->company;
|
||||
|
||||
$smtp_host = $company->smtp_host ?? '';
|
||||
$smtp_port = $company->smtp_port;
|
||||
$smtp_port = (int)$company->smtp_port;
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
|
@ -174,8 +174,19 @@ class AutoBillInvoice extends AbstractService
|
||||
$this->invoice->auto_bill_tries += 1;
|
||||
|
||||
if ($this->invoice->auto_bill_tries == 3) {
|
||||
$this->invoice->auto_bill_enabled = false;
|
||||
$this->invoice->auto_bill_tries = 0; //reset the counter here in case auto billing is turned on again in the future.
|
||||
|
||||
\App\Models\Invoice::where('id', $this->invoice->id)->update([
|
||||
'auto_bill_enabled' => false,
|
||||
'auto_bill_tries' => 0
|
||||
]);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
\App\Models\Invoice::where('id', $this->invoice->id)->update([
|
||||
'auto_bill_tries' => $this->invoice->auto_bill_tries
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
if ($payment) {
|
||||
@ -347,6 +358,8 @@ class AutoBillInvoice extends AbstractService
|
||||
$payload = ['client_id' => $this->invoice->client_id, 'invoices' => [['invoice_id' => $this->invoice->id,'amount' => $payment_balance]]];
|
||||
$payment_repo->save($payload, $payment);
|
||||
|
||||
$this->invoice = $this->invoice->fresh();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,31 @@ class DeletePayment
|
||||
|
||||
nlog("net deletable amount - refunded = {$net_deletable}");
|
||||
|
||||
if (! $paymentable_invoice->is_deleted) {
|
||||
if($paymentable_invoice->status_id == Invoice::STATUS_CANCELLED){
|
||||
|
||||
$is_trashed = false;
|
||||
|
||||
if($paymentable_invoice->trashed()){
|
||||
$is_trashed = true;
|
||||
$paymentable_invoice->restore();
|
||||
}
|
||||
|
||||
$paymentable_invoice->service()
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
$this->payment
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
if($is_trashed){
|
||||
$paymentable_invoice->delete();
|
||||
}
|
||||
|
||||
}
|
||||
elseif (! $paymentable_invoice->is_deleted) {
|
||||
$paymentable_invoice->restore();
|
||||
|
||||
$paymentable_invoice->service()
|
||||
@ -133,11 +157,16 @@ class DeletePayment
|
||||
|
||||
//sometimes the payment is NOT created properly, this catches the payment and prevents the paid to date reducing inappropriately.
|
||||
if ($this->update_client_paid_to_date) {
|
||||
|
||||
$reduced_paid_to_date = $this->payment->amount < 0 ? $this->payment->amount * -1 : min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
||||
|
||||
// $reduced_paid_to_date = min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
||||
|
||||
$this->payment
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate(min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1))
|
||||
->save();
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate($reduced_paid_to_date)
|
||||
->save();
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -88,6 +88,7 @@ class PdfService
|
||||
*/
|
||||
public function getPdf()
|
||||
{
|
||||
|
||||
try {
|
||||
$pdf = $this->resolvePdfEngine($this->getHtml());
|
||||
|
||||
|
@ -120,116 +120,116 @@ class QuickbooksImport implements ShouldQueue
|
||||
};
|
||||
}
|
||||
|
||||
private function syncQbToNinjaInvoices($records): void
|
||||
{
|
||||
// private function syncQbToNinjaInvoices($records): void
|
||||
// {
|
||||
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
|
||||
|
||||
private function syncQbToNinjaVendors(array $records): void
|
||||
{
|
||||
// private function syncQbToNinjaVendors(array $records): void
|
||||
// {
|
||||
|
||||
$transformer = new VendorTransformer($this->company);
|
||||
// $transformer = new VendorTransformer($this->company);
|
||||
|
||||
foreach($records as $record)
|
||||
{
|
||||
$ninja_data = $transformer->qbToNinja($record);
|
||||
// foreach($records as $record)
|
||||
// {
|
||||
// $ninja_data = $transformer->qbToNinja($record);
|
||||
|
||||
if($vendor = $this->findVendor($ninja_data))
|
||||
{
|
||||
$vendor->fill($ninja_data[0]);
|
||||
$vendor->saveQuietly();
|
||||
// if($vendor = $this->findVendor($ninja_data))
|
||||
// {
|
||||
// $vendor->fill($ninja_data[0]);
|
||||
// $vendor->saveQuietly();
|
||||
|
||||
$contact = $vendor->contacts()->where('email', $ninja_data[1]['email'])->first();
|
||||
// $contact = $vendor->contacts()->where('email', $ninja_data[1]['email'])->first();
|
||||
|
||||
if(!$contact)
|
||||
{
|
||||
$contact = VendorContactFactory::create($this->company->id, $this->company->owner()->id);
|
||||
$contact->vendor_id = $vendor->id;
|
||||
$contact->send_email = true;
|
||||
$contact->is_primary = true;
|
||||
$contact->fill($ninja_data[1]);
|
||||
$contact->saveQuietly();
|
||||
}
|
||||
elseif($this->qbs->syncable('vendor', \App\Enum\SyncDirection::PULL)){
|
||||
$contact->fill($ninja_data[1]);
|
||||
$contact->saveQuietly();
|
||||
}
|
||||
// if(!$contact)
|
||||
// {
|
||||
// $contact = VendorContactFactory::create($this->company->id, $this->company->owner()->id);
|
||||
// $contact->vendor_id = $vendor->id;
|
||||
// $contact->send_email = true;
|
||||
// $contact->is_primary = true;
|
||||
// $contact->fill($ninja_data[1]);
|
||||
// $contact->saveQuietly();
|
||||
// }
|
||||
// elseif($this->qbs->syncable('vendor', \App\Enum\SyncDirection::PULL)){
|
||||
// $contact->fill($ninja_data[1]);
|
||||
// $contact->saveQuietly();
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
private function syncQbToNinjaExpenses(array $records): void
|
||||
{
|
||||
// private function syncQbToNinjaExpenses(array $records): void
|
||||
// {
|
||||
|
||||
$transformer = new ExpenseTransformer($this->company);
|
||||
// $transformer = new ExpenseTransformer($this->company);
|
||||
|
||||
foreach($records as $record)
|
||||
{
|
||||
$ninja_data = $transformer->qbToNinja($record);
|
||||
// foreach($records as $record)
|
||||
// {
|
||||
// $ninja_data = $transformer->qbToNinja($record);
|
||||
|
||||
if($expense = $this->findExpense($ninja_data))
|
||||
{
|
||||
$expense->fill($ninja_data);
|
||||
$expense->saveQuietly();
|
||||
}
|
||||
// if($expense = $this->findExpense($ninja_data))
|
||||
// {
|
||||
// $expense->fill($ninja_data);
|
||||
// $expense->saveQuietly();
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
private function findExpense(array $qb_data): ?Expense
|
||||
{
|
||||
$expense = $qb_data;
|
||||
// private function findExpense(array $qb_data): ?Expense
|
||||
// {
|
||||
// $expense = $qb_data;
|
||||
|
||||
$search = Expense::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where('number', $expense['number']);
|
||||
// $search = Expense::query()
|
||||
// ->withTrashed()
|
||||
// ->where('company_id', $this->company->id)
|
||||
// ->where('number', $expense['number']);
|
||||
|
||||
if($search->count() == 0) {
|
||||
return ExpenseFactory::create($this->company->id, $this->company->owner()->id);
|
||||
}
|
||||
elseif($search->count() == 1) {
|
||||
return $this->qbs->syncable('expense', \App\Enum\SyncDirection::PULL) ? $search->first() : null;
|
||||
}
|
||||
// if($search->count() == 0) {
|
||||
// return ExpenseFactory::create($this->company->id, $this->company->owner()->id);
|
||||
// }
|
||||
// elseif($search->count() == 1) {
|
||||
// return $this->qbs->syncable('expense', \App\Enum\SyncDirection::PULL) ? $search->first() : null;
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
// return null;
|
||||
// }
|
||||
|
||||
private function findVendor(array $qb_data) :?Vendor
|
||||
{
|
||||
$vendor = $qb_data[0];
|
||||
$contact = $qb_data[1];
|
||||
$vendor_meta = $qb_data[2];
|
||||
// private function findVendor(array $qb_data) :?Vendor
|
||||
// {
|
||||
// $vendor = $qb_data[0];
|
||||
// $contact = $qb_data[1];
|
||||
// $vendor_meta = $qb_data[2];
|
||||
|
||||
$search = Vendor::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where(function ($q) use ($vendor, $vendor_meta, $contact){
|
||||
// $search = Vendor::query()
|
||||
// ->withTrashed()
|
||||
// ->where('company_id', $this->company->id)
|
||||
// ->where(function ($q) use ($vendor, $vendor_meta, $contact){
|
||||
|
||||
$q->where('vendor_hash', $vendor_meta['vendor_hash'])
|
||||
->orWhere('number', $vendor['number'])
|
||||
->orWhereHas('contacts', function ($q) use ($contact){
|
||||
$q->where('email', $contact['email']);
|
||||
});
|
||||
// $q->where('vendor_hash', $vendor_meta['vendor_hash'])
|
||||
// ->orWhere('number', $vendor['number'])
|
||||
// ->orWhereHas('contacts', function ($q) use ($contact){
|
||||
// $q->where('email', $contact['email']);
|
||||
// });
|
||||
|
||||
});
|
||||
// });
|
||||
|
||||
if($search->count() == 0) {
|
||||
//new client
|
||||
return VendorFactory::create($this->company->id, $this->company->owner()->id);
|
||||
}
|
||||
elseif($search->count() == 1) {
|
||||
// if($search->count() == 0) {
|
||||
// //new client
|
||||
// return VendorFactory::create($this->company->id, $this->company->owner()->id);
|
||||
// }
|
||||
// elseif($search->count() == 1) {
|
||||
|
||||
return $this->qbs->syncable('vendor', \App\Enum\SyncDirection::PULL) ? $search->first() : null;
|
||||
}
|
||||
// return $this->qbs->syncable('vendor', \App\Enum\SyncDirection::PULL) ? $search->first() : null;
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
// return null;
|
||||
// }
|
||||
|
||||
public function middleware()
|
||||
{
|
||||
|
@ -11,38 +11,41 @@
|
||||
|
||||
namespace App\Services\Template;
|
||||
|
||||
use App\Models\Task;
|
||||
use App\Models\User;
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Number;
|
||||
use Twig\Error\Error;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Design;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Project;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\HostedPDF\NinjaPdf;
|
||||
use App\Utils\HtmlEngine;
|
||||
use App\Utils\Number;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\VendorHtmlEngine;
|
||||
use Twig\Sandbox\SecurityError;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Utils\PaymentHtmlEngine;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\HostedPDF\NinjaPdf;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use App\Utils\VendorHtmlEngine;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Twig\Error\Error;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Extra\Intl\IntlExtension;
|
||||
use Twig\Sandbox\SecurityError;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class TemplateService
|
||||
{
|
||||
use MakesDates;
|
||||
use PdfMaker;
|
||||
|
||||
use MakesHash;
|
||||
|
||||
private \DomDocument $document;
|
||||
|
||||
public \Twig\Environment $twig;
|
||||
@ -61,7 +64,7 @@ class TemplateService
|
||||
|
||||
private ?Vendor $vendor = null;
|
||||
|
||||
private Invoice | Quote | Credit | PurchaseOrder | RecurringInvoice $entity;
|
||||
private Invoice | Quote | Credit | PurchaseOrder | RecurringInvoice | Task | Project $entity;
|
||||
|
||||
private Payment $payment;
|
||||
|
||||
@ -92,7 +95,7 @@ class TemplateService
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader(storage_path());
|
||||
$this->twig = new \Twig\Environment($loader, [
|
||||
'debug' => true,
|
||||
'debug' => true,
|
||||
]);
|
||||
|
||||
$string_extension = new \Twig\Extension\StringLoaderExtension();
|
||||
@ -100,7 +103,6 @@ class TemplateService
|
||||
$this->twig->addExtension(new IntlExtension());
|
||||
$this->twig->addExtension(new \Twig\Extension\DebugExtension());
|
||||
|
||||
|
||||
$function = new \Twig\TwigFunction('img', function ($string, $style = '') {
|
||||
return '<img src="' . $string . '" style="' . $style . '"></img>';
|
||||
});
|
||||
@ -124,7 +126,7 @@ class TemplateService
|
||||
$this->twig->addFilter($filter);
|
||||
|
||||
$allowedTags = ['if', 'for', 'set', 'filter'];
|
||||
$allowedFilters = ['replace', 'escape', 'e', 'upper', 'lower', 'capitalize', 'filter', 'length', 'merge','format_currency', 'format_number','format_percent_number','map', 'join', 'first', 'date', 'sum', 'number_format','nl2br'];
|
||||
$allowedFilters = ['replace', 'escape', 'e', 'upper', 'lower', 'capitalize', 'filter', 'length', 'merge','format_currency', 'format_number','format_percent_number','map', 'join', 'first', 'date', 'sum', 'number_format','nl2br','striptags'];
|
||||
$allowedFunctions = ['range', 'cycle', 'constant', 'date',];
|
||||
$allowedProperties = ['type_id'];
|
||||
$allowedMethods = ['img','t'];
|
||||
@ -292,7 +294,7 @@ class TemplateService
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function parseNinjaBlocks(): self
|
||||
public function parseNinjaBlocks(): self
|
||||
{
|
||||
$replacements = [];
|
||||
|
||||
@ -350,6 +352,12 @@ class TemplateService
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setData(array $data): self
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Parses all variables in the document
|
||||
*
|
||||
@ -379,7 +387,7 @@ class TemplateService
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function save(): self
|
||||
public function save(): self
|
||||
{
|
||||
$this->compiled_html = str_replace('%24', '$', $this->document->saveHTML());
|
||||
|
||||
@ -409,6 +417,14 @@ class TemplateService
|
||||
|
||||
}
|
||||
|
||||
public function setRawTemplate(string $template):self
|
||||
{
|
||||
|
||||
@$this->document->loadHTML(mb_convert_encoding($template, 'HTML-ENTITIES', 'UTF-8'));
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
/**
|
||||
* Inject the template components
|
||||
* manually
|
||||
@ -612,7 +628,8 @@ class TemplateService
|
||||
$item->gross_line_total = Number::formatMoney($item->gross_line_total_raw, $client_or_vendor);
|
||||
$item->tax_amount = Number::formatMoney($item->tax_amount_raw, $client_or_vendor);
|
||||
$item->product_cost = Number::formatMoney($item->product_cost_raw, $client_or_vendor);
|
||||
|
||||
$item->task = strlen($item->task_id ?? '') > 1 ? $this->processInvoiceTask($item->task_id) : [];
|
||||
|
||||
return (array)$item;
|
||||
|
||||
})->toArray();
|
||||
@ -929,6 +946,35 @@ class TemplateService
|
||||
'locale' => substr($entity->client->locale(), 0, 2),
|
||||
] : [];
|
||||
}
|
||||
|
||||
private function processInvoiceTask(string $task_id): array
|
||||
{
|
||||
$task = Task::where('company_id', $this->company->id)
|
||||
->where('id', $this->decodePrimaryKey($task_id))
|
||||
->first();
|
||||
|
||||
return $task ? [
|
||||
'number' => (string) $task->number ?: '',
|
||||
'description' => (string) $task->description ?: '',
|
||||
'duration' => $task->calcDuration() ?: 0,
|
||||
'rate' => Number::formatMoney($task->rate ?? 0, $task->client ?? $task->company),
|
||||
'rate_raw' => $task->rate ?? 0,
|
||||
'created_at' => $this->translateDate($task->created_at, $task->client ? $task->client->date_format() : $task->company->date_format(), $task->client ? $task->client->locale() : $task->company->locale()),
|
||||
'updated_at' => $this->translateDate($task->updated_at, $task->client ? $task->client->date_format() : $task->company->date_format(), $task->client ? $task->client->locale() : $task->company->locale()),
|
||||
'date' => $task->calculated_start_date ? $this->translateDate($task->calculated_start_date, $task->client ? $task->client->date_format() : $task->company->date_format(), $task->client ? $task->client->locale() : $task->company->locale()) : '',
|
||||
'project' => $task->project ? $this->transformProject($task->project, true) : [],
|
||||
'time_log' => $task->processLogsExpandedNotation(),
|
||||
'custom_value1' => $task->custom_value1 ?: '',
|
||||
'custom_value2' => $task->custom_value2 ?: '',
|
||||
'custom_value3' => $task->custom_value3 ?: '',
|
||||
'custom_value4' => $task->custom_value4 ?: '',
|
||||
'status' => $task->status ? $task->status->name : '',
|
||||
'user' => $this->userInfo($task->user),
|
||||
'assigned_user' => $task->assigned_user ? $this->userInfo($task->assigned_user) : [],
|
||||
] : [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo refactor
|
||||
*
|
||||
@ -1311,19 +1357,21 @@ class TemplateService
|
||||
*/
|
||||
private function resolveEntity(): string
|
||||
{
|
||||
$entity_string = '';
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
match($this->entity) {
|
||||
($this->entity instanceof Invoice) => $entity_string = 'invoice',
|
||||
($this->entity instanceof Quote) => $entity_string = 'quote',
|
||||
($this->entity instanceof Credit) => $entity_string = 'credit',
|
||||
($this->entity instanceof RecurringInvoice) => $entity_string = 'invoice',
|
||||
($this->entity instanceof PurchaseOrder) => $entity_string = 'purchase_order',
|
||||
default => $entity_string = 'invoice',
|
||||
};
|
||||
|
||||
return $entity_string;
|
||||
switch ($this->entity) {
|
||||
case ($this->entity instanceof Invoice):
|
||||
return 'invoice';
|
||||
case ($this->entity instanceof Quote):
|
||||
return 'quote';
|
||||
case ($this->entity instanceof Credit):
|
||||
return 'credit';
|
||||
case ($this->entity instanceof RecurringInvoice):
|
||||
return 'invoice';
|
||||
case ($this->entity instanceof PurchaseOrder):
|
||||
return 'purchase_order';
|
||||
|
||||
default:
|
||||
return 'invoice';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ use App\Models\Document;
|
||||
use App\Models\Expense;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Project;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@ -41,6 +42,7 @@ class ExpenseTransformer extends EntityTransformer
|
||||
'vendor',
|
||||
'category',
|
||||
'invoice',
|
||||
'project',
|
||||
];
|
||||
|
||||
public function includeDocuments(Expense $expense)
|
||||
@ -50,6 +52,17 @@ class ExpenseTransformer extends EntityTransformer
|
||||
return $this->includeCollection($expense->documents, $transformer, Document::class);
|
||||
}
|
||||
|
||||
public function includeProject(Expense $expense): ?Item
|
||||
{
|
||||
$transformer = new ProjectTransformer($this->serializer);
|
||||
|
||||
if (!$expense->project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->includeItem($expense->project, $transformer, Project::class);
|
||||
}
|
||||
|
||||
public function includeClient(Expense $expense): ?Item
|
||||
{
|
||||
$transformer = new ClientTransformer($this->serializer);
|
||||
|
@ -830,7 +830,7 @@ class HtmlEngine
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->entity->company->tax_data->regions->EU->has_sales_above_threshold ?? false){
|
||||
if (!$this->entity->company->tax_data->regions->EU->has_sales_above_threshold ?? false){ //@phpstan-ignore-line
|
||||
$tax_label .= ctrans('text.small_company_info') ."<br>";
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,8 @@ class Statics
|
||||
|
||||
$data['bulk_updates'] = [
|
||||
'client' => \App\Models\Client::$bulk_update_columns,
|
||||
'expense' => \App\Models\Expense::$bulk_update_columns,
|
||||
'recurring_invoice' => \App\Models\RecurringInvoice::$bulk_update_columns,
|
||||
];
|
||||
|
||||
return $data;
|
||||
|
@ -12,12 +12,13 @@
|
||||
|
||||
namespace App\Utils\Traits\Invoice\Broadcasting;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Transformers\ArraySerializer;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
trait DefaultInvoiceBroadcast
|
||||
trait DefaultResourceBroadcast
|
||||
{
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
@ -26,17 +27,40 @@ trait DefaultInvoiceBroadcast
|
||||
];
|
||||
}
|
||||
|
||||
public function broadcastModel(): BaseModel
|
||||
{
|
||||
throw new \LogicException('Make sure to pass a model to the broadcastModel method.');
|
||||
}
|
||||
|
||||
public function broadcastManager(Manager $manager): Manager
|
||||
{
|
||||
return $manager;
|
||||
}
|
||||
|
||||
public function broadcastWith(): array
|
||||
{
|
||||
$entity = $this->broadcastModel();
|
||||
|
||||
$manager = new Manager();
|
||||
|
||||
$manager->setSerializer(new ArraySerializer());
|
||||
$class = sprintf('App\\Transformers\\%sTransformer', class_basename($this->invoice));
|
||||
|
||||
$class = sprintf('App\\Transformers\\%sTransformer', class_basename($entity));
|
||||
|
||||
$transformer = new $class();
|
||||
|
||||
$resource = new Item($this->invoice, $transformer, $this->invoice->getEntityType());
|
||||
$resource = new Item($entity, $transformer, $entity->getEntityType());
|
||||
|
||||
$manager = $this->broadcastManager($manager);
|
||||
|
||||
$data = $manager->createData($resource)->toArray();
|
||||
|
||||
return [...$data, 'x-socket-id' => $this->socket];
|
||||
$data = [...$data];
|
||||
|
||||
if (\property_exists($this, 'socket')) {
|
||||
$data['x-socket-id'] = $this->socket;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
237
composer.lock
generated
237
composer.lock
generated
@ -535,16 +535,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.323.2",
|
||||
"version": "3.324.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "030b93340f0e7d6fd20276037087d3eab8f16575"
|
||||
"reference": "5b824a9b8015a38f18c53b023975c0f63c7bd3dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/030b93340f0e7d6fd20276037087d3eab8f16575",
|
||||
"reference": "030b93340f0e7d6fd20276037087d3eab8f16575",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5b824a9b8015a38f18c53b023975c0f63c7bd3dc",
|
||||
"reference": "5b824a9b8015a38f18c53b023975c0f63c7bd3dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -627,9 +627,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.323.2"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.324.1"
|
||||
},
|
||||
"time": "2024-10-07T18:11:24+00:00"
|
||||
"time": "2024-10-11T18:22:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "babenkoivan/elastic-adapter",
|
||||
@ -1580,16 +1580,16 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "4.1.1",
|
||||
"version": "4.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/dbal.git",
|
||||
"reference": "7a8252418689feb860ea8dfeab66d64a56a64df8"
|
||||
"reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/7a8252418689feb860ea8dfeab66d64a56a64df8",
|
||||
"reference": "7a8252418689feb860ea8dfeab66d64a56a64df8",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/dadd35300837a3a2184bd47d403333b15d0a9bd0",
|
||||
"reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1602,7 +1602,7 @@
|
||||
"doctrine/coding-standard": "12.0.0",
|
||||
"fig/log-test": "^1",
|
||||
"jetbrains/phpstorm-stubs": "2023.2",
|
||||
"phpstan/phpstan": "1.12.0",
|
||||
"phpstan/phpstan": "1.12.6",
|
||||
"phpstan/phpstan-phpunit": "1.4.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.6",
|
||||
"phpunit/phpunit": "10.5.30",
|
||||
@ -1668,7 +1668,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/dbal/issues",
|
||||
"source": "https://github.com/doctrine/dbal/tree/4.1.1"
|
||||
"source": "https://github.com/doctrine/dbal/tree/4.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1684,7 +1684,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-03T08:58:39+00:00"
|
||||
"time": "2024-10-10T18:01:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
@ -2035,16 +2035,16 @@
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"version": "v3.3.3",
|
||||
"version": "v3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dragonmantank/cron-expression.git",
|
||||
"reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
|
||||
"reference": "8c784d071debd117328803d86b2097615b457500"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
|
||||
"reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500",
|
||||
"reference": "8c784d071debd117328803d86b2097615b457500",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2057,10 +2057,14 @@
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-webmozart-assert": "^1.0",
|
||||
"phpunit/phpunit": "^7.0|^8.0|^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cron\\": "src/Cron/"
|
||||
@ -2084,7 +2088,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dragonmantank/cron-expression/issues",
|
||||
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
|
||||
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2092,7 +2096,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-10T19:36:49+00:00"
|
||||
"time": "2024-10-09T13:47:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "egulias/email-validator",
|
||||
@ -3882,16 +3886,16 @@
|
||||
},
|
||||
{
|
||||
"name": "horstoeko/zugferd",
|
||||
"version": "v1.0.65",
|
||||
"version": "v1.0.66",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/horstoeko/zugferd.git",
|
||||
"reference": "ccafcda546f6867b3203420331fd436baf028187"
|
||||
"reference": "2a009cd78d6aab7771f2a6dbf31c8c0cfd4f3fc5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/ccafcda546f6867b3203420331fd436baf028187",
|
||||
"reference": "ccafcda546f6867b3203420331fd436baf028187",
|
||||
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/2a009cd78d6aab7771f2a6dbf31c8c0cfd4f3fc5",
|
||||
"reference": "2a009cd78d6aab7771f2a6dbf31c8c0cfd4f3fc5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3951,9 +3955,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/horstoeko/zugferd/issues",
|
||||
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.65"
|
||||
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.66"
|
||||
},
|
||||
"time": "2024-10-06T09:56:35+00:00"
|
||||
"time": "2024-10-11T09:37:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "horstoeko/zugferdvisualizer",
|
||||
@ -4883,16 +4887,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v11.26.0",
|
||||
"version": "v11.27.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b"
|
||||
"reference": "a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b",
|
||||
"reference": "b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9",
|
||||
"reference": "a51d1f2b771c542324a3d9b76a98b1bbc75c0ee9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -5088,7 +5092,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2024-10-01T14:29:34+00:00"
|
||||
"time": "2024-10-09T04:17:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@ -5620,38 +5624,38 @@
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "5.3.0",
|
||||
"version": "5.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lcobucci/jwt.git",
|
||||
"reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83"
|
||||
"reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
|
||||
"reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
|
||||
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/aac4fd512681fd5cb4b77d2105ab7ec700c72051",
|
||||
"reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-sodium": "*",
|
||||
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
|
||||
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
|
||||
"psr/clock": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.27.0",
|
||||
"lcobucci/clock": "^3.0",
|
||||
"infection/infection": "^0.29",
|
||||
"lcobucci/clock": "^3.2",
|
||||
"lcobucci/coding-standard": "^11.0",
|
||||
"phpbench/phpbench": "^1.2.9",
|
||||
"phpbench/phpbench": "^1.2",
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan": "^1.10.7",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1.3",
|
||||
"phpstan/phpstan-phpunit": "^1.3.10",
|
||||
"phpstan/phpstan-strict-rules": "^1.5.0",
|
||||
"phpunit/phpunit": "^10.2.6"
|
||||
"phpunit/phpunit": "^11.1"
|
||||
},
|
||||
"suggest": {
|
||||
"lcobucci/clock": ">= 3.0"
|
||||
"lcobucci/clock": ">= 3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -5677,7 +5681,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/lcobucci/jwt/issues",
|
||||
"source": "https://github.com/lcobucci/jwt/tree/5.3.0"
|
||||
"source": "https://github.com/lcobucci/jwt/tree/5.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -5689,7 +5693,7 @@
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-11T23:07:54+00:00"
|
||||
"time": "2024-10-08T22:06:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
@ -5881,16 +5885,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
"version": "9.16.0",
|
||||
"version": "9.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/csv.git",
|
||||
"reference": "998280c6c34bd67d8125fdc8b45bae28d761b440"
|
||||
"reference": "8cab815fb11ec93aa2f7b8a57b3daa1f1a364011"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/998280c6c34bd67d8125fdc8b45bae28d761b440",
|
||||
"reference": "998280c6c34bd67d8125fdc8b45bae28d761b440",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/8cab815fb11ec93aa2f7b8a57b3daa1f1a364011",
|
||||
"reference": "8cab815fb11ec93aa2f7b8a57b3daa1f1a364011",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -5898,17 +5902,16 @@
|
||||
"php": "^8.1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/collections": "^2.2.2",
|
||||
"ext-dom": "*",
|
||||
"ext-xdebug": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.57.1",
|
||||
"phpbench/phpbench": "^1.2.15",
|
||||
"phpstan/phpstan": "^1.11.1",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.2.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.64.0",
|
||||
"phpbench/phpbench": "^1.3.1",
|
||||
"phpstan/phpstan": "^1.12.5",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.2.1",
|
||||
"phpstan/phpstan-phpunit": "^1.4.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.6.0",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.1.3",
|
||||
"symfony/var-dumper": "^6.4.6 || ^7.0.7"
|
||||
"phpstan/phpstan-strict-rules": "^1.6.1",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.4.0",
|
||||
"symfony/var-dumper": "^6.4.8 || ^7.1.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
|
||||
@ -5926,7 +5929,7 @@
|
||||
"src/functions_include.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"League\\Csv\\": "src"
|
||||
"League\\Csv\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@ -5965,20 +5968,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-24T11:04:54+00:00"
|
||||
"time": "2024-10-10T10:30:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "3.29.0",
|
||||
"version": "3.29.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem.git",
|
||||
"reference": "0adc0d9a51852e170e0028a60bd271726626d3f0"
|
||||
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/0adc0d9a51852e170e0028a60bd271726626d3f0",
|
||||
"reference": "0adc0d9a51852e170e0028a60bd271726626d3f0",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319",
|
||||
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -6046,9 +6049,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.29.0"
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.29.1"
|
||||
},
|
||||
"time": "2024-09-29T11:59:11+00:00"
|
||||
"time": "2024-10-08T08:58:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem-aws-s3-v3",
|
||||
@ -6358,16 +6361,16 @@
|
||||
},
|
||||
{
|
||||
"name": "livewire/livewire",
|
||||
"version": "v3.5.9",
|
||||
"version": "v3.5.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/livewire/livewire.git",
|
||||
"reference": "d04a229058afa76116d0e39209943a8ea3a7f888"
|
||||
"reference": "774092003edb2670615ef09f3a9fbdd335d6d0d7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/livewire/livewire/zipball/d04a229058afa76116d0e39209943a8ea3a7f888",
|
||||
"reference": "d04a229058afa76116d0e39209943a8ea3a7f888",
|
||||
"url": "https://api.github.com/repos/livewire/livewire/zipball/774092003edb2670615ef09f3a9fbdd335d6d0d7",
|
||||
"reference": "774092003edb2670615ef09f3a9fbdd335d6d0d7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -6422,7 +6425,7 @@
|
||||
"description": "A front-end framework for Laravel.",
|
||||
"support": {
|
||||
"issues": "https://github.com/livewire/livewire/issues",
|
||||
"source": "https://github.com/livewire/livewire/tree/v3.5.9"
|
||||
"source": "https://github.com/livewire/livewire/tree/v3.5.10"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -6430,20 +6433,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-01T12:40:06+00:00"
|
||||
"time": "2024-10-10T20:03:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maennchen/zipstream-php",
|
||||
"version": "3.1.0",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||
"reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1"
|
||||
"reference": "6187e9cc4493da94b9b63eb2315821552015fca9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
|
||||
"reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9",
|
||||
"reference": "6187e9cc4493da94b9b63eb2315821552015fca9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -6499,19 +6502,15 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0"
|
||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/maennchen",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/zipstream",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-21T14:59:35+00:00"
|
||||
"time": "2024-10-10T12:33:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mailgun/mailgun-php",
|
||||
@ -6802,16 +6801,16 @@
|
||||
},
|
||||
{
|
||||
"name": "mindee/mindee",
|
||||
"version": "v1.11.1",
|
||||
"version": "v1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mindee/mindee-api-php.git",
|
||||
"reference": "1ffbbdab646202f6b9547d12399841feba75c68e"
|
||||
"reference": "4088e5d7e5aef72162dbea10386c64c3f071aa23"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mindee/mindee-api-php/zipball/1ffbbdab646202f6b9547d12399841feba75c68e",
|
||||
"reference": "1ffbbdab646202f6b9547d12399841feba75c68e",
|
||||
"url": "https://api.github.com/repos/mindee/mindee-api-php/zipball/4088e5d7e5aef72162dbea10386c64c3f071aa23",
|
||||
"reference": "4088e5d7e5aef72162dbea10386c64c3f071aa23",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -6850,9 +6849,9 @@
|
||||
"description": "Mindee Client Library for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/mindee/mindee-api-php/issues",
|
||||
"source": "https://github.com/mindee/mindee-api-php/tree/v1.11.1"
|
||||
"source": "https://github.com/mindee/mindee-api-php/tree/v1.12.0"
|
||||
},
|
||||
"time": "2024-09-20T14:46:42+00:00"
|
||||
"time": "2024-10-11T15:47:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mollie/mollie-api-php",
|
||||
@ -7675,16 +7674,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.3.0",
|
||||
"version": "v5.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a"
|
||||
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a",
|
||||
"reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b",
|
||||
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -7727,9 +7726,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1"
|
||||
},
|
||||
"time": "2024-09-29T13:56:26+00:00"
|
||||
"time": "2024-10-08T18:51:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nordigen/nordigen-php",
|
||||
@ -15196,16 +15195,16 @@
|
||||
},
|
||||
{
|
||||
"name": "turbo124/beacon",
|
||||
"version": "v2.0.2",
|
||||
"version": "v2.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/turbo124/beacon.git",
|
||||
"reference": "95f3de3bdcbb786329cd7050f319520588920466"
|
||||
"reference": "eb7ff81a49b2aa75d62459f36ad06b88181e1e00"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/turbo124/beacon/zipball/95f3de3bdcbb786329cd7050f319520588920466",
|
||||
"reference": "95f3de3bdcbb786329cd7050f319520588920466",
|
||||
"url": "https://api.github.com/repos/turbo124/beacon/zipball/eb7ff81a49b2aa75d62459f36ad06b88181e1e00",
|
||||
"reference": "eb7ff81a49b2aa75d62459f36ad06b88181e1e00",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15252,9 +15251,9 @@
|
||||
"turbo124"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/turbo124/beacon/tree/v2.0.2"
|
||||
"source": "https://github.com/turbo124/beacon/tree/v2.0.3"
|
||||
},
|
||||
"time": "2024-06-27T01:23:05+00:00"
|
||||
"time": "2024-10-12T06:57:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/intl-extra",
|
||||
@ -17458,35 +17457,35 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "11.0.6",
|
||||
"version": "11.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45"
|
||||
"reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ebdffc9e09585dafa71b9bffcdb0a229d4704c45",
|
||||
"reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca",
|
||||
"reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"nikic/php-parser": "^5.1.0",
|
||||
"nikic/php-parser": "^5.3.1",
|
||||
"php": ">=8.2",
|
||||
"phpunit/php-file-iterator": "^5.0.1",
|
||||
"phpunit/php-file-iterator": "^5.1.0",
|
||||
"phpunit/php-text-template": "^4.0.1",
|
||||
"sebastian/code-unit-reverse-lookup": "^4.0.1",
|
||||
"sebastian/complexity": "^4.0.1",
|
||||
"sebastian/environment": "^7.2.0",
|
||||
"sebastian/lines-of-code": "^3.0.1",
|
||||
"sebastian/version": "^5.0.1",
|
||||
"sebastian/version": "^5.0.2",
|
||||
"theseer/tokenizer": "^1.2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0"
|
||||
"phpunit/phpunit": "^11.4.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pcov": "PHP extension that provides line coverage",
|
||||
@ -17524,7 +17523,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.6"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -17532,7 +17531,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-22T04:37:56+00:00"
|
||||
"time": "2024-10-09T06:21:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -17781,16 +17780,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "11.4.0",
|
||||
"version": "11.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "89fe0c530133c08f7fff89d3d727154e4e504925"
|
||||
"reference": "7875627f15f4da7e7f0823d1f323f7295a77334e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89fe0c530133c08f7fff89d3d727154e4e504925",
|
||||
"reference": "89fe0c530133c08f7fff89d3d727154e4e504925",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7875627f15f4da7e7f0823d1f323f7295a77334e",
|
||||
"reference": "7875627f15f4da7e7f0823d1f323f7295a77334e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -17861,7 +17860,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.0"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -17877,7 +17876,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-05T08:39:03+00:00"
|
||||
"time": "2024-10-08T15:38:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/cache",
|
||||
@ -19280,16 +19279,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
"version": "5.0.1",
|
||||
"version": "5.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/version.git",
|
||||
"reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4"
|
||||
"reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4",
|
||||
"reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
|
||||
"reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -19322,7 +19321,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/version/issues",
|
||||
"security": "https://github.com/sebastianbergmann/version/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/version/tree/5.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -19330,7 +19329,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-03T05:13:08+00:00"
|
||||
"time": "2024-10-09T05:16:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/backtrace",
|
||||
|
@ -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.10.34'),
|
||||
'app_tag' => env('APP_TAG', '5.10.34'),
|
||||
'app_version' => env('APP_VERSION', '5.10.42'),
|
||||
'app_tag' => env('APP_TAG', '5.10.42'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('vendors', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('vendors', 'routing_id')) {
|
||||
$table->string('routing_id')->nullable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
}
|
||||
};
|
56
database/migrations/2024_10_18_211558_updated_currencies.php
Normal file
56
database/migrations/2024_10_18_211558_updated_currencies.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Currency;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
|
||||
Model::unguard();
|
||||
|
||||
$currencies = [
|
||||
['id' => 124, 'name' => 'Bermudian Dollar', 'code' => 'BMD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 125, 'name' => 'Central African CFA Franc', 'code' => 'XAF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 126, 'name' => 'Congolese Franc', 'code' => 'CDF', 'symbol' => 'Fr', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 127, 'name' => 'Djiboutian Franc', 'code' => 'DJF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 128, 'name' => 'Eritrean Nakfa', 'code' => 'ERN', 'symbol' => 'Nfk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 129, 'name' => 'Falkland Islands Pound', 'code' => 'FKP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 130, 'name' => 'Guinean Franc', 'code' => 'GNF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => ''],
|
||||
['id' => 131, 'name' => 'Iraqi Dinar', 'code' => 'IQD', 'symbol' => 'ع.د', 'precision' => '3', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 132, 'name' => 'Lesotho Loti', 'code' => 'LSL', 'symbol' => 'L', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 133, 'name' => 'Mongolian Tugrik', 'code' => 'MNT', 'symbol' => '₮', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 134, 'name' => 'Seychellois Rupee', 'code' => 'SCR', 'symbol' => '₨', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 135, 'name' => 'Solomon Islands Dollar', 'code' => 'SBD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 136, 'name' => 'Somali Shilling', 'code' => 'SOS', 'symbol' => 'Sh', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 137, 'name' => 'South Sudanese Pound', 'code' => 'SSP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 138, 'name' => 'Sudanese Pound', 'code' => 'SDG', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 139, 'name' => 'Tajikistani Somoni', 'code' => 'TJS', 'symbol' => 'ЅM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 140, 'name' => 'Turkmenistani Manat', 'code' => 'TMT', 'symbol' => 'T', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 141, 'name' => 'Uzbekistani Som', 'code' => 'UZS', 'symbol' => 'so\'m', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
];
|
||||
|
||||
foreach ($currencies as $currency) {
|
||||
$record = Currency::where('code', $currency['code'])->first();
|
||||
if (!$record) {
|
||||
Currency::create($currency);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -146,6 +146,25 @@ class CurrenciesSeeder extends Seeder
|
||||
['id' => 121, 'name' => "Lao kip", 'code' => 'LAK', 'symbol' => '₭', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 122, 'name' => "Bhutan Ngultrum", 'code' => 'BTN', 'symbol' => 'Nu', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 123, 'name' => "Mauritanian Ouguiya", 'code' => 'MRU', 'symbol' => 'UM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 124, 'name' => 'Bermudian Dollar', 'code' => 'BMD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 125, 'name' => 'Central African CFA Franc', 'code' => 'XAF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 126, 'name' => 'Congolese Franc', 'code' => 'CDF', 'symbol' => 'Fr', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 127, 'name' => 'Djiboutian Franc', 'code' => 'DJF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 128, 'name' => 'Eritrean Nakfa', 'code' => 'ERN', 'symbol' => 'Nfk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 129, 'name' => 'Falkland Islands Pound', 'code' => 'FKP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 130, 'name' => 'Guinean Franc', 'code' => 'GNF', 'symbol' => 'Fr', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => ''],
|
||||
['id' => 131, 'name' => 'Iraqi Dinar', 'code' => 'IQD', 'symbol' => 'ع.د', 'precision' => '3', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 132, 'name' => 'Lesotho Loti', 'code' => 'LSL', 'symbol' => 'L', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 133, 'name' => 'Mongolian Tugrik', 'code' => 'MNT', 'symbol' => '₮', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 134, 'name' => 'Seychellois Rupee', 'code' => 'SCR', 'symbol' => '₨', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 135, 'name' => 'Solomon Islands Dollar', 'code' => 'SBD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 136, 'name' => 'Somali Shilling', 'code' => 'SOS', 'symbol' => 'Sh', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 137, 'name' => 'South Sudanese Pound', 'code' => 'SSP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 138, 'name' => 'Sudanese Pound', 'code' => 'SDG', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 139, 'name' => 'Tajikistani Somoni', 'code' => 'TJS', 'symbol' => 'ЅM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 140, 'name' => 'Turkmenistani Manat', 'code' => 'TMT', 'symbol' => 'T', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 141, 'name' => 'Uzbekistani Som', 'code' => 'UZS', 'symbol' => 'so\'m', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
|
||||
];
|
||||
|
||||
foreach ($currencies as $currency) {
|
||||
|
@ -5359,7 +5359,6 @@ $lang = array(
|
||||
'updated_records' => 'Updated Records',
|
||||
'vat_not_registered' => 'Seller not VAT registered',
|
||||
'small_company_info' => 'No disclosure of sales tax in accordance with § 19 UStG',
|
||||
'log_duration_words' => 'Log duration in words',
|
||||
'peppol_onboarding' => 'Looks like it\'s your first time using PEPPOL.',
|
||||
'get_started' => 'Get Started',
|
||||
'configure_peppol' => 'Configure PEPPOL',
|
||||
@ -5374,6 +5373,35 @@ $lang = array(
|
||||
'peppol_disconnect' => 'Disconnect PEPPOL',
|
||||
'peppol_disconnect_short' => 'Disconnect from PEPPOL.',
|
||||
'peppol_disconnect_long' => 'PEPPOL will be disconnected from your account and...',
|
||||
'log_duration_words' => 'Time log duration in words',
|
||||
'log_duration' => 'Time log duration',
|
||||
'merged_vendors' => 'Successfully merged vendors',
|
||||
'hidden_taxes_warning' => 'Somes taxes are hidden due to current tax settings. :link',
|
||||
'tax3' => 'Third Tax',
|
||||
'negative_payment_warning' => 'Are you sure you want to create a negative payment? This cannot be used as a credit or payment.',
|
||||
'currency_Bermudian_Dollar' => 'Bermudian Dollar',
|
||||
'currency_Central_African_CFA_Franc' => 'Central African CFA Franc',
|
||||
'currency_Congolese_Franc' => 'Congolese Franc',
|
||||
'currency_Djiboutian_Franc' => 'Djiboutian Franc',
|
||||
'currency_Eritrean_Nakfa' => 'Eritrean Nakfa',
|
||||
'currency_Falkland_Islands_Pound' => 'Falklan IslandsPound',
|
||||
'currency_Guinean_Franc' => 'Guinean Franc',
|
||||
'currency_Iraqi_Dinar' => 'Iraqi Dinar',
|
||||
'currency_Lesotho_Loti' => 'Lesotho Loti',
|
||||
'currency_Mongolian_Tugrik' => 'Mongolian Tugrik',
|
||||
'currency_Seychellois_Rupee' => 'Seychellois Rupee',
|
||||
'currency_Solomon_Islands_Dollar' => 'Solomon Islands Dollar',
|
||||
'currency_Somali_Shilling' => 'Somali Shilling',
|
||||
'currency_South_Sudanese_Pound' => 'South Sudanese Pound',
|
||||
'currency_Sudanese_Pound' => 'Sudanese Pound',
|
||||
'currency_Tajikistani_Somoni' => 'Tajikistani Somoni',
|
||||
'currency_Turkmenistani_Manat' => 'Turkmenistani Manat',
|
||||
'currency_Uzbekistani_Som' => 'Uzbekistani Som',
|
||||
'payment_status_changed' => 'Please note that the status of your payment has been updated. We recommend refreshing the page to view the most current version.',
|
||||
'credit_status_changed' => 'Please note that the status of your credit has been updated. We recommend refreshing the page to view the most current version.',
|
||||
'credit_updated' => 'Credit Updated',
|
||||
'payment_updated' => 'Payment Updated',
|
||||
'search_placeholder' => 'Find invoices, clients, and more',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -5355,6 +5355,10 @@ Développe automatiquement la section des notes dans le tableau de produits pour
|
||||
'quick_actions' => 'Actions rapides',
|
||||
'end_all_sessions_help' => 'Déconnecte tous les utilisateurs et oblige tous les utilisateurs actifs à se réauthentifier.',
|
||||
'updated_records' => 'Enregistrements mis à jour',
|
||||
'vat_not_registered' => 'Vendeur non enregistré aux taxes',
|
||||
'small_company_info' => 'Aucune déclaration de taxe de vente conformément à l\'article 19 UStG',
|
||||
'log_duration_words' => 'Durée du journal de temps exprimée en mots',
|
||||
'log_duration' => 'Durée du journal de temps'
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -2361,7 +2361,7 @@ Kom terug naar deze betaalmethode pagina zodra u de bedragen heeft ontvangen en
|
||||
'currency_gold_troy_ounce' => 'Gouden Troy Ounce',
|
||||
'currency_nicaraguan_córdoba' => 'Nicaraguaans Córdoba',
|
||||
'currency_malagasy_ariary' => 'Malagassische ariarium',
|
||||
"currency_tongan_paanga" => "Tongaanse pa'anga",
|
||||
"currency_tongan_pa_anga" => "Tongaanse pa'anga",
|
||||
|
||||
'review_app_help' => 'We hopen dat u veel gemak heeft aan het gebruik van deze app.<br/> Als u :link zou overwegen, stellen wij dat zeer op prijs!',
|
||||
'writing_a_review' => 'een recensie schrijven',
|
||||
@ -5338,6 +5338,29 @@ E-mail: :email<b><br><b>',
|
||||
'no_unread_notifications' => 'U bent weer helemaal bij! Er zijn geen nieuwe notificaties.',
|
||||
'how_to_import_data' => 'Hoe u gegevens kunt importeren',
|
||||
'download_example_file' => 'Download voorbeeldbestand',
|
||||
'expense_mailbox' => 'Inkomend e-mailadres',
|
||||
'expense_mailbox_help' => 'Het inkomende e-mailadres waarop declaraties ontvangen kunnen worden. Bijv. declaratie@invoiceninja.com',
|
||||
'expense_mailbox_active' => 'Mailbox voor declaraties',
|
||||
'expense_mailbox_active_help' => 'Maakt het mogelijk om declaraties zoals kassabonnen te verwerken voor kostenrapportages',
|
||||
'inbound_mailbox_allow_company_users' => 'Bedrijfsafzenders toestaan',
|
||||
'inbound_mailbox_allow_company_users_help' => 'Sta gebruikers binnen het bedrijf toe om declaraties in te sturen',
|
||||
'inbound_mailbox_allow_vendors' => 'Leveranciersafzenders toestaan',
|
||||
'inbound_mailbox_allow_vendors_help' => 'Sta bedrijfsafzenders toe om declaraties in te sturen',
|
||||
'inbound_mailbox_allow_clients' => 'Sta klantafzenders toe',
|
||||
'inbound_mailbox_allow_clients_help' => 'Sta klanten toe om declaraties in te sturen',
|
||||
'inbound_mailbox_whitelist' => 'Lijst met toegestane afzenders',
|
||||
'inbound_mailbox_whitelist_help' => 'Door komma\'s gescheiden lijst met e-mailadressen die declaraties mogen insturen voor verwerking',
|
||||
'inbound_mailbox_blacklist' => 'Lijst met geblokkeerde afzenders',
|
||||
'inbound_mailbox_blacklist_help' => 'Door komma\'s gescheiden lijst met e-mailadressen die geblokkeerd zijn en declaraties niet mogen insturen voor verwerking',
|
||||
'inbound_mailbox_allow_unknown' => 'Sta alle afzenders toe',
|
||||
'inbound_mailbox_allow_unknown_help' => 'Sta iedereen toe om declaraties in te sturen voor verwerking',
|
||||
'quick_actions' => 'Snelle acties',
|
||||
'end_all_sessions_help' => 'Logt alle gebruikers uit en vereist dat alle actieve gebruikers opnieuw inloggen.',
|
||||
'updated_records' => 'Items bijgewerkt',
|
||||
'vat_not_registered' => 'Verkoper is niet btw-plichtig',
|
||||
'small_company_info' => 'Geen openbaarmaking van omzetbelasting in overeenstemming met § 19 UStG',
|
||||
'log_duration_words' => 'Maximale lengte logboek in woorden',
|
||||
'log_duration' => 'Maximale lengte logboek'
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -1065,7 +1065,7 @@ $lang = array(
|
||||
'user_create_all' => 'Ustvarja stranke, račune, itd.',
|
||||
'user_view_all' => 'Vidi stranke, račune, itd.',
|
||||
'user_edit_all' => 'Ureja stranke, račune, itd.',
|
||||
'partial_due' => 'Delno plačilo do',
|
||||
'partial_due' => 'Delno plačilo',
|
||||
'restore_vendor' => 'Obnovi dobavitelja',
|
||||
'restored_vendor' => 'Dobavitelj uspešno obnovljen',
|
||||
'restored_expense' => 'Strošek uspešno obnovljen',
|
||||
@ -2365,7 +2365,7 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'currency_gold_troy_ounce' => 'Gold Troy Ounce',
|
||||
'currency_nicaraguan_córdoba' => 'Nicaraguan Córdoba',
|
||||
'currency_malagasy_ariary' => 'Malagasy ariary',
|
||||
"currency_tongan_paanga" => "Tongan Pa'anga",
|
||||
"currency_tongan_pa_anga" => "Tongan Pa'anga",
|
||||
|
||||
'review_app_help' => 'Upamo da uživate v uporabi aplikacije.<br/>Zelo bi cenili klik na :link!',
|
||||
'writing_a_review' => 'pisanje pregleda (kritike)',
|
||||
@ -2493,6 +2493,8 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'local_storage_required' => 'Napaka: Lokalna hramba ni na voljo.',
|
||||
'your_password_reset_link' => 'Povezava za ponastavitev gesla',
|
||||
'subdomain_taken' => 'Poddomena že v uporabi',
|
||||
'expense_mailbox_taken' => 'The inbound mailbox is already in use',
|
||||
'expense_mailbox_invalid' => 'The inbound mailbox does not match the required schema',
|
||||
'client_login' => 'Vpis stranke',
|
||||
'converted_amount' => 'Pretvorjeni znesek',
|
||||
'default' => 'Privzeto',
|
||||
@ -3890,7 +3892,7 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'payment_method_saving_failed' => 'Payment method can\'t be saved for future use.',
|
||||
'pay_with' => 'Pay with',
|
||||
'n/a' => 'N/A',
|
||||
'by_clicking_next_you_accept_terms' => 'By clicking "Next step" you accept terms.',
|
||||
'by_clicking_next_you_accept_terms' => 'By clicking "Next" you accept terms.',
|
||||
'not_specified' => 'Not specified',
|
||||
'before_proceeding_with_payment_warning' => 'Before proceeding with payment, you have to fill following fields',
|
||||
'after_completing_go_back_to_previous_page' => 'After completing, go back to previous page.',
|
||||
@ -5125,7 +5127,7 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'all_contacts' => 'All Contacts',
|
||||
'insert_below' => 'Insert Below',
|
||||
'nordigen_handler_subtitle' => 'Bank account authentication. Selecting your institution to complete the request with your account credentials.',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occured',
|
||||
'nordigen_handler_error_heading_unknown' => 'An error has occurred',
|
||||
'nordigen_handler_error_contents_unknown' => 'An unknown error has occurred! Reason:',
|
||||
'nordigen_handler_error_heading_token_invalid' => 'Invalid Token',
|
||||
'nordigen_handler_error_contents_token_invalid' => 'The provided token was invalid. Contact support for help, if this issue persists.',
|
||||
@ -5239,7 +5241,7 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields' => 'Always show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
@ -5302,6 +5304,63 @@ Ko imate zneske, se vrnite na to stran plačilnega sredstva in kliknite na "Comp
|
||||
'latest_requires_php_version' => 'Note: the latest version requires PHP :version',
|
||||
'auto_expand_product_table_notes' => 'Automatically expand products table notes',
|
||||
'auto_expand_product_table_notes_help' => 'Automatically expands the notes section within the products table to display more lines.',
|
||||
'institution_number' => 'Institution Number',
|
||||
'transit_number' => 'Transit Number',
|
||||
'personal' => 'Personal',
|
||||
'address_information' => 'Address Information',
|
||||
'enter_the_information_for_the_bank_account' => 'Enter the Information for the Bank Account',
|
||||
'account_holder_information' => 'Account Holder Information',
|
||||
'enter_information_for_the_account_holder' => 'Enter Information for the Account Holder',
|
||||
'customer_type' => 'Customer Type',
|
||||
'process_date' => 'Process Date',
|
||||
'forever_free' => 'Forever Free',
|
||||
'comments_only' => 'Comments Only',
|
||||
'payment_balance_on_file' => 'Payment Balance On File',
|
||||
'ubl_email_attachment_help' => 'For more e-invoice settings please navigate :here',
|
||||
'stop_task_to_add_task_entry' => 'You need to stop the task before adding a new item.',
|
||||
'xml_file' => 'XML File',
|
||||
'one_page_checkout' => 'One-Page Checkout',
|
||||
'one_page_checkout_help' => 'Enable the new single page payment flow',
|
||||
'applies_to' => 'Applies To',
|
||||
'accept_purchase_order' => 'Accept Purchase Order',
|
||||
'round_to_seconds' => 'Round To Seconds',
|
||||
'activity_142' => 'Quote :number reminder 1 sent',
|
||||
'activity_143' => 'Auto Bill succeeded for invoice :invoice',
|
||||
'activity_144' => 'Auto Bill failed for invoice :invoice. :notes',
|
||||
'activity_145' => 'EInvoice :invoice for :client was e-delivered. :notes',
|
||||
'payment_failed' => 'Payment Failed',
|
||||
'ssl_host_override' => 'SSL Host Override',
|
||||
'upload_logo_short' => 'Upload Logo',
|
||||
'country_Melilla' => 'Melilla',
|
||||
'country_Ceuta' => 'Ceuta',
|
||||
'country_Canary Islands' => 'Canary Islands',
|
||||
'lang_Vietnamese' => 'Vietnamese',
|
||||
'invoice_status_changed' => 'Please note that the status of your invoice has been updated. We recommend refreshing the page to view the most current version.',
|
||||
'no_unread_notifications' => 'You’re all caught up! No new notifications.',
|
||||
'how_to_import_data' => 'How to import data',
|
||||
'download_example_file' => 'Download example file',
|
||||
'expense_mailbox' => 'Inbound e-mail address',
|
||||
'expense_mailbox_help' => 'The inbound email address which accepts expense documents. ie. expense@invoiceninja.com',
|
||||
'expense_mailbox_active' => 'Expense Mailbox',
|
||||
'expense_mailbox_active_help' => 'Enables processing of documents such as receipts for expense reporting',
|
||||
'inbound_mailbox_allow_company_users' => 'Allow Company Senders',
|
||||
'inbound_mailbox_allow_company_users_help' => 'Allows users within the company to send expense documents.',
|
||||
'inbound_mailbox_allow_vendors' => 'Allow Vendor Senders',
|
||||
'inbound_mailbox_allow_vendors_help' => 'Allows company vendors to send expense documents',
|
||||
'inbound_mailbox_allow_clients' => 'Allow Client Senders',
|
||||
'inbound_mailbox_allow_clients_help' => 'Allows clients to send expense documents',
|
||||
'inbound_mailbox_whitelist' => 'Inbound sender allow list',
|
||||
'inbound_mailbox_whitelist_help' => 'Comma separated list of emails that should be allowed to send emails for processing',
|
||||
'inbound_mailbox_blacklist' => 'Inbound sender banned list',
|
||||
'inbound_mailbox_blacklist_help' => 'Comma separate list of emails that are disallowed to send emails for processing',
|
||||
'inbound_mailbox_allow_unknown' => 'Allow All Senders',
|
||||
'inbound_mailbox_allow_unknown_help' => 'Allow anyone to send an expense email for processing',
|
||||
'quick_actions' => 'Quick Actions',
|
||||
'end_all_sessions_help' => 'Logs out all users and requires all active users to reauthenticate.',
|
||||
'updated_records' => 'Updated Records',
|
||||
'vat_not_registered' => 'Seller not VAT registered',
|
||||
'small_company_info' => 'No disclosure of sales tax in accordance with § 19 UStG',
|
||||
'log_duration_words' => 'Log duration in words'
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -13,7 +13,7 @@ $lang = array(
|
||||
'postal_code' => 'Mã bưu chính',
|
||||
'country_id' => 'Quốc gia',
|
||||
'contacts' => 'Liên hệ',
|
||||
'first_name' => 'Họ & tên',
|
||||
'first_name' => 'Họ',
|
||||
'last_name' => 'Tên',
|
||||
'phone' => 'Số điện thoại',
|
||||
'email' => 'Email',
|
||||
@ -26,7 +26,7 @@ $lang = array(
|
||||
'invoice' => 'Hóa đơn',
|
||||
'client' => 'Khách hàng',
|
||||
'invoice_date' => 'Ngày hóa đơn',
|
||||
'due_date' => 'Hạn thanh toán',
|
||||
'due_date' => 'Đã thanh toán',
|
||||
'invoice_number' => 'Số hóa đơn',
|
||||
'invoice_number_short' => 'Hóa đơn #',
|
||||
'po_number' => 'Số PO',
|
||||
@ -42,7 +42,7 @@ $lang = array(
|
||||
'line_total' => 'Tổng',
|
||||
'subtotal' => 'Thành tiền',
|
||||
'net_subtotal' => 'Tính',
|
||||
'paid_to_date' => 'Hạn thanh toán',
|
||||
'paid_to_date' => 'Đã thanh toán đến ngày',
|
||||
'balance_due' => 'Số tiền thanh toán',
|
||||
'invoice_design_id' => 'Thiết kế',
|
||||
'terms' => 'Điều khoản',
|
||||
@ -135,7 +135,7 @@ $lang = array(
|
||||
'status' => 'Trạng thái',
|
||||
'invoice_total' => 'Tổng hóa đơn',
|
||||
'frequency' => 'Chu kỳ',
|
||||
'range' => 'phạm vi',
|
||||
'range' => 'Phạm vi',
|
||||
'start_date' => 'Ngày bắt đầu',
|
||||
'end_date' => 'Ngày kết thúc',
|
||||
'transaction_reference' => 'Tham chiếu giao dịch',
|
||||
@ -386,7 +386,7 @@ $lang = array(
|
||||
'more_designs_self_host_text' => '',
|
||||
'buy' => 'Mua',
|
||||
'bought_designs' => 'Đã thêm thành công các thiết kế hóa đơn bổ sung',
|
||||
'sent' => 'gởi',
|
||||
'sent' => 'Đã gửi',
|
||||
'vat_number' => 'Số VAT',
|
||||
'payment_title' => 'Nhập địa chỉ thanh toán và thông tin thẻ tín dụng của bạn',
|
||||
'payment_cvv' => '* Đây là số 3-4 chữ số ở mặt sau thẻ của bạn',
|
||||
@ -738,7 +738,7 @@ $lang = array(
|
||||
'activity_7' => ':contact đã xem hóa đơn :invoice gửi đến :client',
|
||||
'activity_8' => ':user hóa đơn lưu trữ :invoice',
|
||||
'activity_9' => ':user đã xóa hóa đơn :invoice',
|
||||
'activity_10' => ':user đã nhập thanh toán :payment cho :payment _số tiền trên hóa đơn :invoice cho :client',
|
||||
'activity_10' => ':user đã nhập thanh toán :payment bởi :payment _số tiền trên hóa đơn :invoice cho :client',
|
||||
'activity_11' => ':user cập nhật thanh toán :payment',
|
||||
'activity_12' => ':user thanh toán đã lưu trữ :payment',
|
||||
'activity_13' => ':user đã xóa thanh toán :payment',
|
||||
@ -835,7 +835,7 @@ $lang = array(
|
||||
'invalid_csv_header' => 'Tiêu đề CSV không hợp lệ',
|
||||
'client_portal' => 'Cổng thông tin khách hàng',
|
||||
'admin' => 'Quản trị viên',
|
||||
'disabled' => 'Tàn tật',
|
||||
'disabled' => 'Vô hiệu hóa',
|
||||
'show_archived_users' => 'Hiển thị người dùng đã lưu trữ',
|
||||
'notes' => 'Ghi chú',
|
||||
'invoice_will_create' => 'hóa đơn sẽ được tạo',
|
||||
@ -959,7 +959,7 @@ $lang = array(
|
||||
'quote_message_button' => 'Để xem báo giá cho :amount , hãy nhấp vào nút bên dưới.',
|
||||
'payment_message_button' => 'Cảm ơn bạn đã thanh toán :amount .',
|
||||
'payment_type_direct_debit' => 'Ghi nợ trực tiếp',
|
||||
'bank_accounts' => 'Thẻ tín dụng & ngân hàng',
|
||||
'bank_accounts' => 'Thẻ tín dụng & Ngân hàng',
|
||||
'add_bank_account' => 'Thêm tài khoản ngân hàng',
|
||||
'setup_account' => 'Thiết lập tài khoản',
|
||||
'import_expenses' => 'Chi phí nhập khẩu',
|
||||
@ -2364,7 +2364,7 @@ $lang = array(
|
||||
'currency_gold_troy_ounce' => 'Ounce vàng Troy',
|
||||
'currency_nicaraguan_córdoba' => 'Córdoba Nicaragua',
|
||||
'currency_malagasy_ariary' => 'Tiếng Malagasy',
|
||||
"currency_tongan_paanga" => "Tonga Pa'anga",
|
||||
"currency_tongan_pa_anga" => "Tongan Pa'anga",
|
||||
|
||||
'review_app_help' => 'Chúng tôi hy vọng bạn thích sử dụng ứng dụng này.<br/> Nếu bạn cân nhắc :link chúng tôi sẽ rất cảm kích!',
|
||||
'writing_a_review' => 'viết đánh giá',
|
||||
@ -3097,7 +3097,7 @@ $lang = array(
|
||||
'uploaded_logo' => 'Đã tải logo thành công',
|
||||
'saved_settings' => 'Đã lưu cài đặt thành công',
|
||||
'device_settings' => 'Cài đặt thiết bị',
|
||||
'credit_cards_and_banks' => 'Thẻ tín dụng & ngân hàng',
|
||||
'credit_cards_and_banks' => 'Thẻ tín dụng & Ngân hàng',
|
||||
'price' => 'Giá',
|
||||
'email_sign_up' => 'Đăng ký Email',
|
||||
'google_sign_up' => 'Đăng ký Google',
|
||||
@ -3738,8 +3738,8 @@ $lang = array(
|
||||
'document_upload_help' => 'Cho phép khách hàng tải lên tài liệu',
|
||||
'expense_total' => 'Tổng chi phí',
|
||||
'enter_taxes' => 'Nhập Thuế',
|
||||
'by_rate' => 'Theo Tỷ giá',
|
||||
'by_amount' => 'Theo Số Lượng',
|
||||
'by_rate' => 'Theo tỷ giá',
|
||||
'by_amount' => 'Theo số lượng',
|
||||
'enter_amount' => 'Nhập số tiền',
|
||||
'before_taxes' => 'Trước thuế',
|
||||
'after_taxes' => 'Sau thuế',
|
||||
@ -4106,7 +4106,7 @@ $lang = array(
|
||||
'auto_bill_disabled' => 'Tự động hóa đơn bị vô hiệu hóa',
|
||||
'select_payment_method' => 'Chọn phương thức thanh toán:',
|
||||
'login_without_password' => 'Đăng nhập không cần mật khẩu',
|
||||
'email_sent' => 'Email khi một hóa đơn được <b>gởi</b>',
|
||||
'email_sent' => 'Email khi một hóa đơn được <b>đã gửi</b>',
|
||||
'one_time_purchases' => 'Mua một lần',
|
||||
'recurring_purchases' => 'Mua hàng định kỳ',
|
||||
'you_might_be_interested_in_following' => 'Bạn có thể quan tâm đến những điều sau đây',
|
||||
@ -4266,7 +4266,7 @@ $lang = array(
|
||||
'uninvoiced' => 'Chưa xuất hóa đơn',
|
||||
'subdomain_guide' => 'Tên miền phụ được sử dụng trong cổng thông tin khách hàng để cá nhân hóa các liên kết phù hợp với thương hiệu của bạn. Ví dụ: https://your-brand.invoicing.co',
|
||||
'send_time' => 'Gửi thời gian',
|
||||
'import_settings' => 'Nhập Cài Đặt',
|
||||
'import_settings' => 'Nhập cài đặt',
|
||||
'json_file_missing' => 'Vui lòng cung cấp tệp JSON',
|
||||
'json_option_missing' => 'Vui lòng chọn để nhập cài đặt và/hoặc dữ liệu',
|
||||
'json' => 'JSON',
|
||||
@ -4975,7 +4975,7 @@ $lang = array(
|
||||
'e_invoice' => 'Hóa đơn điện tử',
|
||||
'light_dark_mode' => 'Chế độ sáng/tối',
|
||||
'activities' => 'Các hoạt động',
|
||||
'recent_transactions' => "Sau đây là các giao dịch gần đây nhất của công ty bạn:",
|
||||
'recent_transactions' => "Các giao dịch gần đây nhất của công ty bạn:",
|
||||
'country_Palestine' => "Palestine",
|
||||
'country_Taiwan' => 'Đài Loan',
|
||||
'duties' => 'Nhiệm vụ',
|
||||
@ -5031,7 +5031,7 @@ $lang = array(
|
||||
'county' => 'Quận',
|
||||
'tax_details' => 'Chi tiết thuế',
|
||||
'activity_10_online' => ':contact đã thanh toán :payment cho hóa đơn :invoice cho :client',
|
||||
'activity_10_manual' => ':user đã nhập thanh toán :payment cho hóa đơn :invoice cho :client',
|
||||
'activity_10_manual' => ':user đã nhập thanh toán :payment bởi hóa đơn :invoice cho :client',
|
||||
'default_payment_type' => 'Loại thanh toán mặc định',
|
||||
'number_precision' => 'Độ chính xác của số',
|
||||
'number_precision_help' => 'Kiểm soát số lượng số thập phân được hỗ trợ trong giao diện',
|
||||
@ -5355,7 +5355,12 @@ $lang = array(
|
||||
'inbound_mailbox_allow_unknown' => 'Cho phép tất cả người gửi',
|
||||
'inbound_mailbox_allow_unknown_help' => 'Cho phép bất cứ ai đến gửi email Chi phí để xử lý',
|
||||
'quick_actions' => 'Hành động nhanh',
|
||||
'end_all_sessions_help' => 'Đăng xuất tất cả người dùng và yêu cầu tất cả người dùng đang hoạt động đến xác thực lại.'
|
||||
'end_all_sessions_help' => 'Đăng xuất tất cả người dùng và yêu cầu tất cả người dùng đang hoạt động đến xác thực lại.',
|
||||
'updated_records' => 'Hồ sơ đã cập nhật',
|
||||
'vat_not_registered' => 'Người bán không đăng ký VAT',
|
||||
'small_company_info' => 'Không tiết lộ thuế bán hàng theo § 19 UStG',
|
||||
'log_duration_words' => 'Thời gian ghi nhật ký bằng từ',
|
||||
'log_duration' => 'Thời gian ghi nhật ký'
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,9 +0,0 @@
|
||||
import{i,w as d}from"./wait-8f4ae121.js";/**
|
||||
* 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
|
||||
*/class s{constructor(){this.appId=document.querySelector("meta[name=square-appId]").content,this.locationId=document.querySelector("meta[name=square-locationId]").content,this.isLoaded=!1}async init(){this.payments=Square.payments(this.appId,this.locationId),this.card=await this.payments.card(),await this.card.attach("#card-container"),this.isLoaded=!0;let e=document.querySelector(".sq-card-iframe-container");e&&e.setAttribute("style","150px !important"),document.querySelector(".toggle-payment-with-token")&&document.getElementById("card-container").classList.add("hidden")}async completePaymentWithoutToken(e){document.getElementById("errors").hidden=!0,e.target.parentElement.disabled=!0;let t=await this.card.tokenize(),o;try{const n={amount:document.querySelector("meta[name=amount]").content,billingContact:JSON.parse(document.querySelector("meta[name=square_contact]").content),currencyCode:document.querySelector("meta[name=currencyCode]").content,intent:"CHARGE"};o=(await this.payments.verifyBuyer(t.token,n)).token}catch{e.target.parentElement.disabled=!0}if(document.querySelector('input[name="verificationToken"]').value=o,t.status==="OK"){document.getElementById("sourceId").value=t.token;let n=document.querySelector('input[name="token-billing-checkbox"]:checked');return n&&(document.querySelector('input[name="store_card"]').value=n.value),document.getElementById("server_response").submit()}document.getElementById("errors").textContent=t.errors[0].message,document.getElementById("errors").hidden=!1,e.target.parentElement.disabled=!1}async completePaymentUsingToken(e){return e.target.parentElement.disabled=!0,document.getElementById("server_response").submit()}async verifyBuyer(e){const t={amount:document.querySelector("meta[name=amount]").content,billingContact:document.querySelector("meta[name=square_contact]").content,currencyCode:document.querySelector("meta[name=currencyCode]").content,intent:"CHARGE"};return(await this.payments.verifyBuyer(e,t)).token}async handle(){document.getElementById("payment-list").classList.add("hidden"),await this.init().then(()=>{var e,t,o,n;(e=document.getElementById("authorize-card"))==null||e.addEventListener("click",a=>this.completePaymentWithoutToken(a)),(t=document.getElementById("pay-now"))==null||t.addEventListener("click",a=>document.querySelector("input[name=token]").value?this.completePaymentUsingToken(a):this.completePaymentWithoutToken(a)),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(a=>a.addEventListener("click",async r=>{document.getElementById("card-container").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=r.target.dataset.token})),(o=document.getElementById("toggle-payment-with-credit-card"))==null||o.addEventListener("click",async a=>{document.getElementById("card-container").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value=""}),document.getElementById("loader").classList.add("hidden"),document.getElementById("payment-list").classList.remove("hidden"),(n=document.getElementById("toggle-payment-with-credit-card"))==null||n.click()})}}function c(){new s().handle()}i()?c():d("#square-credit-card-payment").then(()=>c());
|
9
public/build/assets/square-credit-card-9e88c754.js
vendored
Normal file
9
public/build/assets/square-credit-card-9e88c754.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import{i as c,w as d}from"./wait-8f4ae121.js";/**
|
||||
* 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
|
||||
*/class s{constructor(){this.appId=document.querySelector("meta[name=square-appId]").content,this.locationId=document.querySelector("meta[name=square-locationId]").content,this.isLoaded=!1}async init(){this.payments=Square.payments(this.appId,this.locationId),this.card=await this.payments.card(),await this.card.attach("#card-container"),this.isLoaded=!0;let t=document.querySelector(".sq-card-iframe-container");t&&t.setAttribute("style","150px !important"),document.querySelector(".toggle-payment-with-token")&&document.getElementById("card-container").classList.add("hidden")}async completePaymentWithoutToken(t){document.getElementById("errors").hidden=!0,t.target.parentElement.disabled=!0;let n=document.getElementById("pay-now");this.payNowButton=n,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden");let a=await this.card.tokenize(),o;try{const e={amount:document.querySelector("meta[name=amount]").content,billingContact:JSON.parse(document.querySelector("meta[name=square_contact]").content),currencyCode:document.querySelector("meta[name=currencyCode]").content,intent:"CHARGE"};o=(await this.payments.verifyBuyer(a.token,e)).token}catch{t.target.parentElement.disabled=!0}if(document.querySelector('input[name="verificationToken"]').value=o,a.status==="OK"){document.getElementById("sourceId").value=a.token;let e=document.querySelector('input[name="token-billing-checkbox"]:checked');return e&&(document.querySelector('input[name="store_card"]').value=e.value),document.getElementById("server_response").submit()}document.getElementById("errors").textContent=a.errors[0].message,document.getElementById("errors").hidden=!1,t.target.parentElement.disabled=!1,this.payNowButton.disabled=!1,this.payNowButton.querySelector("svg").classList.add("hidden"),this.payNowButton.querySelector("span").classList.remove("hidden")}async completePaymentUsingToken(t){t.target.parentElement.disabled=!0;let n=document.getElementById("pay-now");return this.payNowButton=n,this.payNowButton.disabled=!0,this.payNowButton.querySelector("svg").classList.remove("hidden"),this.payNowButton.querySelector("span").classList.add("hidden"),document.getElementById("server_response").submit()}async verifyBuyer(t){const n={amount:document.querySelector("meta[name=amount]").content,billingContact:document.querySelector("meta[name=square_contact]").content,currencyCode:document.querySelector("meta[name=currencyCode]").content,intent:"CHARGE"};return(await this.payments.verifyBuyer(t,n)).token}async handle(){document.getElementById("payment-list").classList.add("hidden"),await this.init().then(()=>{var t,n,a,o;(t=document.getElementById("authorize-card"))==null||t.addEventListener("click",e=>this.completePaymentWithoutToken(e)),(n=document.getElementById("pay-now"))==null||n.addEventListener("click",e=>document.querySelector("input[name=token]").value?this.completePaymentUsingToken(e):this.completePaymentWithoutToken(e)),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(e=>e.addEventListener("click",async r=>{document.getElementById("card-container").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=r.target.dataset.token})),(a=document.getElementById("toggle-payment-with-credit-card"))==null||a.addEventListener("click",async e=>{document.getElementById("card-container").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value=""}),Array.from(document.getElementsByClassName("loader")).forEach(e=>{e.classList.add("hidden")}),document.getElementById("payment-list").classList.remove("hidden"),(o=document.getElementById("toggle-payment-with-credit-card"))==null||o.click()})}}function i(){new s().handle()}c()?i():d("#square-credit-card-payment").then(()=>i());
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user