diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 8ddd16ea36..0cb14e9b96 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -479,6 +479,8 @@ class CompanySettings extends BaseSettings public $e_invoice_type = 'EN16931'; + public $e_quote_type = 'OrderX_Comfort'; + public $default_expense_payment_type_id = '0'; public $enable_e_invoice = false; @@ -502,6 +504,7 @@ class CompanySettings extends BaseSettings public $enable_rappen_rounding = false; public static $casts = [ + 'e_quote_type' => 'string', 'enable_rappen_rounding' => 'bool', 'use_unapplied_payment' => 'string', 'show_pdfhtml_on_mobile' => 'bool', diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index da0ca9a0d1..dff7763ec9 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -427,8 +427,11 @@ class BaseExport protected array $task_report_keys = [ 'start_date' => 'task.start_date', + 'start_time' => 'task.start_time', 'end_date' => 'task.end_date', + 'end_time' => 'task.end_time', 'duration' => 'task.duration', + 'duration_words' => 'task.duration_words', 'rate' => 'task.rate', 'number' => 'task.number', 'description' => 'task.description', diff --git a/app/Export/CSV/TaskExport.php b/app/Export/CSV/TaskExport.php index 33685b5092..e70609307b 100644 --- a/app/Export/CSV/TaskExport.php +++ b/app/Export/CSV/TaskExport.php @@ -11,18 +11,19 @@ namespace App\Export\CSV; -use App\Export\Decorators\Decorator; -use App\Libraries\MultiDB; -use App\Models\Company; -use App\Models\DateFormat; use App\Models\Task; -use App\Models\Timezone; -use App\Transformers\TaskTransformer; use App\Utils\Ninja; -use Illuminate\Database\Eloquent\Builder; +use League\Csv\Writer; +use App\Models\Company; +use App\Models\Timezone; +use App\Libraries\MultiDB; +use App\Models\DateFormat; +use Carbon\CarbonInterval; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; -use League\Csv\Writer; +use App\Export\Decorators\Decorator; +use App\Transformers\TaskTransformer; +use Illuminate\Database\Eloquent\Builder; class TaskExport extends BaseExport { @@ -177,19 +178,26 @@ class TaskExport extends BaseExport foreach ($logs as $key => $item) { if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) { - $entity['task.start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default); + $carbon_object = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name); + $entity['task.start_date'] = $carbon_object->format($date_format_default); + $entity['task.start_time'] = $carbon_object->format('H:i:s'); } if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) { - $entity['task.end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default); + $carbon_object = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name); + $entity['task.end_date'] = $carbon_object->format($date_format_default); + $entity['task.end_time'] = $carbon_object->format('H:i:s'); } if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) { $entity['task.end_date'] = ctrans('texts.is_running'); + $entity['task.end_time'] = ctrans('texts.is_running'); } if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) { - $entity['task.duration'] = $task->calcDuration(); + $seconds = $task->calcDuration(); + $entity['task.duration'] = $seconds; + $entity['task.duration_words'] = CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans(); } $entity = $this->decorateAdvancedFields($task, $entity); @@ -197,8 +205,12 @@ class TaskExport extends BaseExport $this->storage_array[] = $entity; $entity['task.start_date'] = ''; + $entity['task.start_time'] = ''; $entity['task.end_date'] = ''; + $entity['task.end_time'] = ''; $entity['task.duration'] = ''; + $entity['task.duration_words'] = ''; + } } diff --git a/app/Export/Decorators/InvoiceDecorator.php b/app/Export/Decorators/InvoiceDecorator.php index 5ce6d936c6..8c308f55df 100644 --- a/app/Export/Decorators/InvoiceDecorator.php +++ b/app/Export/Decorators/InvoiceDecorator.php @@ -23,7 +23,7 @@ class InvoiceDecorator extends Decorator implements DecoratorInterface $invoice = $entity; } elseif($entity->invoice) { $invoice = $entity->invoice; - } elseif($entity->invoices()->exists()) { + } elseif(method_exists($entity, 'invoices') && $entity->invoices()->exists()) { $invoice = $entity->invoices()->first(); } diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index bd03ca01d4..0d6d2ff247 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -200,14 +200,16 @@ class InvoiceFilters extends QueryFilters */ public function payable(string $client_id = ''): Builder { + if (strlen($client_id) == 0) { return $this->builder; } - return $this->builder->whereIn('status_id', [Invoice::STATUS_DRAFT, Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->where('balance', '>', 0) - ->where('is_deleted', 0) - ->where('client_id', $this->decodePrimaryKey($client_id)); + return $this->builder + ->where('client_id', $this->decodePrimaryKey($client_id)) + ->whereIn('status_id', [Invoice::STATUS_DRAFT, Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('is_deleted', 0) + ->where('balance', '>', 0); } diff --git a/app/Helpers/Invoice/InvoiceSum.php b/app/Helpers/Invoice/InvoiceSum.php index f142ce0b9f..52cd745418 100644 --- a/app/Helpers/Invoice/InvoiceSum.php +++ b/app/Helpers/Invoice/InvoiceSum.php @@ -246,8 +246,6 @@ class InvoiceSum if ($this->invoice->status_id != Invoice::STATUS_DRAFT) { if ($this->invoice->amount != $this->invoice->balance) { - // $paid_to_date = $this->invoice->amount - $this->invoice->balance; - $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; //21-02-2024 cannot use the calculated $paid_to_date here as it could send the balance backward. } else { $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision); @@ -256,8 +254,10 @@ class InvoiceSum /* Set new calculated total */ $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); - if($this->rappen_rounding) + if($this->rappen_rounding){ $this->invoice->amount = $this->roundRappen($this->invoice->amount); + $this->invoice->balance = $this->roundRappen($this->invoice->balance); + } $this->invoice->total_taxes = $this->getTotalTaxes(); diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index d7c8a75dbe..aae9c08481 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -272,11 +272,11 @@ class InvoiceSumInclusive } /* Set new calculated total */ - /** @todo - rappen rounding here */ $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); if($this->rappen_rounding) { $this->invoice->amount = $this->roundRappen($this->invoice->amount); + $this->invoice->balance = $this->roundRappen($this->invoice->balance); } $this->invoice->total_taxes = $this->getTotalTaxes(); diff --git a/app/Http/Controllers/Auth/ContactLoginController.php b/app/Http/Controllers/Auth/ContactLoginController.php index 42add3851d..6060dabae2 100644 --- a/app/Http/Controllers/Auth/ContactLoginController.php +++ b/app/Http/Controllers/Auth/ContactLoginController.php @@ -43,7 +43,7 @@ class ContactLoginController extends Controller if ($request->session()->has('company_key')) { MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key')); - $company = Company::where('company_key', $request->input('company_key'))->first(); + $company = Company::where('company_key', $request->session()->get('company_key'))->first(); } elseif ($request->has('company_key')) { MultiDB::findAndSetDbByCompanyKey($request->input('company_key')); $company = Company::where('company_key', $request->input('company_key'))->first(); diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 61f52cafa0..7657f889ca 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -390,13 +390,20 @@ class LoginController extends BaseController $truth->setUser($user); $truth->setCompany($set_company); - $user->account->companies->each(function ($company) use ($user) { - if ($company->tokens()->where('is_system', true)->count() == 0) { - (new CreateCompanyToken($company, $user, request()->server('HTTP_USER_AGENT')))->handle(); + //21-03-2024 + $cu->each(function ($cu){ + if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()){ + (new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle(); } }); - $truth->setCompanyToken(CompanyToken::where('user_id', $user->id)->where('company_id', $set_company->id)->first()); + // $user->account->companies->each(function ($company) use ($user) { + // if ($company->tokens()->where('user_id',$user->id)->where('is_system', true)->count() == 0) { + // (new CreateCompanyToken($company, $user, request()->server('HTTP_USER_AGENT')))->handle(); + // } + // }); + + $truth->setCompanyToken(CompanyToken::where('user_id', $user->id)->where('company_id', $set_company->id)->where('is_system', true)->first()); return CompanyUser::query()->where('user_id', $user->id); } diff --git a/app/Http/Controllers/Bank/YodleeController.php b/app/Http/Controllers/Bank/YodleeController.php index e6a154060d..8fd10c95de 100644 --- a/app/Http/Controllers/Bank/YodleeController.php +++ b/app/Http/Controllers/Bank/YodleeController.php @@ -90,14 +90,13 @@ class YodleeController extends BaseController $bank_integration->balance = $account['current_balance']; $bank_integration->currency = $account['account_currency']; $bank_integration->from_date = now()->subYear(); - + $bank_integration->integration_type = BankIntegration::INTEGRATION_TYPE_YODLEE; $bank_integration->auto_sync = true; $bank_integration->save(); } } - $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->each(function ($bank_integration) use ($company) { // TODO: filter to yodlee only ProcessBankTransactionsYodlee::dispatch($company->account->id, $bank_integration); }); diff --git a/app/Http/Controllers/ClientPortal/DashboardController.php b/app/Http/Controllers/ClientPortal/DashboardController.php index e2f30b2797..ca5e8825b1 100644 --- a/app/Http/Controllers/ClientPortal/DashboardController.php +++ b/app/Http/Controllers/ClientPortal/DashboardController.php @@ -1,4 +1,5 @@ route('client.invoices.index'); - //return $this->render('dashboard.index'); + $total_invoices = Invoice::withTrashed() + ->where('client_id', auth()->guard('contact')->user()->client_id) + ->where('is_deleted', 0) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID]) + ->sum('amount'); + + return $this->render('dashboard.index', [ + 'total_invoices' => $total_invoices, + ]); } } diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 3eedd8fe2f..e0db0722c1 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -727,6 +727,74 @@ class CreditController extends BaseController }, $credit->numberFormatter() . '.pdf', $headers); } + /** + * @OA\Get( + * path="/api/v1/credit/{invitation_key}/download_e_credit", + * operationId="downloadXcredit", + * tags={"credit"}, + * summary="Download a specific x-credit by invitation key", + * description="Downloads a specific x-credit", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="invitation_key", + * in="path", + * description="The credit Invitation Key", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the x-credit pdf", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + * @param $invitation_key + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + */ + public function downloadECredit($invitation_key) + { + $invitation = $this->credit_repository->getInvitationByKey($invitation_key); + + if (! $invitation) { + return response()->json(['message' => 'no record found'], 400); + } + + $contact = $invitation->contact; + $credit = $invitation->credit; + + $file = $credit->service()->getEInvoice($contact); + $file_name = $credit->getFileName("xml"); + + $headers = ['Content-Type' => 'application/xml']; + + if (request()->input('inline') == 'true') { + $headers = array_merge($headers, ['Content-Disposition' => 'inline']); + } + + return response()->streamDownload(function () use ($file) { + echo $file; + }, $file_name, $headers); + } + /** * Update the specified resource in storage. diff --git a/app/Http/Controllers/PurchaseOrderController.php b/app/Http/Controllers/PurchaseOrderController.php index 12b8cb143d..1682380e02 100644 --- a/app/Http/Controllers/PurchaseOrderController.php +++ b/app/Http/Controllers/PurchaseOrderController.php @@ -851,4 +851,71 @@ class PurchaseOrderController extends BaseController echo $file; }, $purchase_order->numberFormatter().".pdf", $headers); } + /** + * @OA\Get( + * path="/api/v1/credit/{invitation_key}/download_e_purchase_order", + * operationId="downloadEPurchaseOrder", + * tags={"purchase_orders"}, + * summary="Download a specific E-Purchase-Order by invitation key", + * description="Downloads a specific E-Purchase-Order", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="invitation_key", + * in="path", + * description="The E-Purchase-Order Invitation Key", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the E-Purchase-Order pdf", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + * @param $invitation_key + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + */ + public function downloadEPurchaseOrder($invitation_key) + { + $invitation = $this->purchase_order_repository->getInvitationByKey($invitation_key); + + if (! $invitation) { + return response()->json(['message' => 'no record found'], 400); + } + + $contact = $invitation->contact; + $purchase_order = $invitation->purchase_order; + + $file = $purchase_order->service()->getEPurchaseOrder($contact); + $file_name = $purchase_order->getFileName("xml"); + + $headers = ['Content-Type' => 'application/xml']; + + if (request()->input('inline') == 'true') { + $headers = array_merge($headers, ['Content-Disposition' => 'inline']); + } + + return response()->streamDownload(function () use ($file) { + echo $file; + }, $file_name, $headers); + } } diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 78a5bf6252..1ac67895f0 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -860,6 +860,75 @@ class QuoteController extends BaseController } + /** + * @OA\Get( + * path="/api/v1/invoice/{invitation_key}/download_e_quote", + * operationId="downloadXQuote", + * tags={"quotes"}, + * summary="Download a specific x-quote by invitation key", + * description="Downloads a specific x-quote", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="invitation_key", + * in="path", + * description="The Quote Invitation Key", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the x-quote pdf", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + * @param $invitation_key + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + */ + public function downloadEQuote($invitation_key) + { + $invitation = $this->quote_repo->getInvitationByKey($invitation_key); + + if (! $invitation) { + return response()->json(['message' => 'no record found'], 400); + } + + $contact = $invitation->contact; + $quote = $invitation->quote; + + $file = $quote->service()->getEInvoice($contact); + $file_name = $quote->getFileName("xml"); + + $headers = ['Content-Type' => 'application/xml']; + + if (request()->input('inline') == 'true') { + $headers = array_merge($headers, ['Content-Disposition' => 'inline']); + } + + return response()->streamDownload(function () use ($file) { + echo $file; + }, $file_name, $headers); + } + + /** * Update the specified resource in storage. * diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 8ff9f3070a..f8ffe75fb6 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -260,8 +260,8 @@ class UserController extends BaseController /** @var \App\Models\User $logged_in_user */ $logged_in_user = auth()->user(); - $company_user = CompanyUser::whereUserId($user->id) - ->whereCompanyId($logged_in_user->companyId()) + $company_user = CompanyUser::where('user_id',$user->id) + ->where('company_id', $logged_in_user->companyId()) ->withTrashed() ->first(); @@ -269,14 +269,10 @@ class UserController extends BaseController return response()->json(['message', 'Cannot detach owner.'], 401); } - $token = $company_user->token->where('company_id', $company_user->company_id)->where('user_id', $company_user->user_id)->first(); - - if ($token) { - $token->delete(); - } + $company_user->tokens()->where('company_id', $company_user->company_id)->where('user_id', $company_user->user_id)->forceDelete(); if ($company_user) { - $company_user->delete(); + $company_user->forceDelete(); } return response()->json(['message' => ctrans('texts.user_detached')], 200); diff --git a/app/Http/Requests/Payment/RefundPaymentRequest.php b/app/Http/Requests/Payment/RefundPaymentRequest.php index bf43b65f70..abcb694fbb 100644 --- a/app/Http/Requests/Payment/RefundPaymentRequest.php +++ b/app/Http/Requests/Payment/RefundPaymentRequest.php @@ -57,8 +57,6 @@ class RefundPaymentRequest extends Request if (isset($input['credits'])) { unset($input['credits']); - // foreach($input['credits'] as $key => $credit) - // $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']); } $this->replace($input); diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index 1bb5808b82..554d729dbe 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -16,7 +16,6 @@ use App\Http\ValidationRules\Credit\CreditsSumRule; use App\Http\ValidationRules\Credit\ValidCreditsRules; use App\Http\ValidationRules\Payment\ValidInvoicesRules; use App\Http\ValidationRules\PaymentAmountsBalanceRule; -use App\Http\ValidationRules\ValidCreditsPresentRule; use App\Http\ValidationRules\ValidPayableInvoicesRule; use App\Models\Payment; use App\Utils\Traits\MakesHash; @@ -39,6 +38,41 @@ class StorePaymentRequest extends Request return $user->can('create', Payment::class); } + public function rules() + { + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $rules = [ + 'client_id' => ['bail','required',Rule::exists('clients','id')->where('company_id',$user->company()->id)->where('is_deleted', 0)], + 'amount' => ['bail', 'numeric', new PaymentAmountsBalanceRule()], + 'invoices.*.amount' => ['bail','required'], + 'invoices.*.invoice_id' => ['bail','required','distinct', new ValidInvoicesRules($this->all()),Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], + 'credits.*.credit_id' => ['bail','required','distinct', new ValidCreditsRules($this->all()),Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], + 'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())], + 'invoices' => ['bail','sometimes', 'nullable', 'array', new ValidPayableInvoicesRule()], + 'number' => ['bail', 'nullable', Rule::unique('payments')->where('company_id', $user->company()->id)], + 'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)], + ]; + + if ($this->file('documents') && is_array($this->file('documents'))) { + $rules['documents.*'] = $this->fileValidation(); + } elseif ($this->file('documents')) { + $rules['documents'] = $this->fileValidation(); + }else { + $rules['documents'] = 'bail|sometimes|array'; + } + + if ($this->file('file') && is_array($this->file('file'))) { + $rules['file.*'] = $this->fileValidation(); + } elseif ($this->file('file')) { + $rules['file'] = $this->fileValidation(); + } + + return $rules; + } + + public function prepareForValidation() { @@ -78,7 +112,6 @@ class StorePaymentRequest extends Request foreach ($input['credits'] as $key => $value) { if (array_key_exists('credit_id', $input['credits'][$key])) { $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']); - $credits_total += $value['amount']; } } @@ -103,39 +136,5 @@ class StorePaymentRequest extends Request $this->replace($input); } - public function rules() - { - /** @var \App\Models\User $user */ - $user = auth()->user(); - $rules = [ - 'amount' => ['numeric', 'bail', new PaymentAmountsBalanceRule(), new ValidCreditsPresentRule($this->all())], - 'client_id' => 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0', - 'invoices.*.invoice_id' => 'bail|required|distinct|exists:invoices,id', - 'invoices.*.amount' => 'bail|required', - 'invoices.*.invoice_id' => new ValidInvoicesRules($this->all()), - 'credits.*.credit_id' => 'bail|required|exists:credits,id', - 'credits.*.credit_id' => new ValidCreditsRules($this->all()), - 'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())], - 'invoices' => new ValidPayableInvoicesRule(), - 'number' => ['nullable', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)], - 'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)], - ]; - - if ($this->file('documents') && is_array($this->file('documents'))) { - $rules['documents.*'] = $this->fileValidation(); - } elseif ($this->file('documents')) { - $rules['documents'] = $this->fileValidation(); - }else { - $rules['documents'] = 'bail|sometimes|array'; - } - - if ($this->file('file') && is_array($this->file('file'))) { - $rules['file.*'] = $this->fileValidation(); - } elseif ($this->file('file')) { - $rules['file'] = $this->fileValidation(); - } - - return $rules; - } } diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index f4b90758ad..02cc11d45e 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -13,7 +13,6 @@ namespace App\Http\Requests\Payment; use App\Http\Requests\Request; use App\Http\ValidationRules\PaymentAppliedValidAmount; -use App\Http\ValidationRules\ValidCreditsPresentRule; use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\MakesHash; use Illuminate\Validation\Rule; @@ -41,16 +40,17 @@ class UpdatePaymentRequest extends Request /** @var \App\Models\User $user */ $user = auth()->user(); - + $rules = [ - 'invoices' => ['array', new PaymentAppliedValidAmount($this->all()), new ValidCreditsPresentRule($this->all())], - 'invoices.*.invoice_id' => 'distinct', + 'client_id' => ['sometimes', 'bail', Rule::in([$this->payment->client_id])], + 'number' => ['sometimes', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id)], + 'invoices' => ['sometimes', 'bail', 'nullable', 'array', new PaymentAppliedValidAmount($this->all())], + 'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], + 'invoices.*.amount' => ['sometimes','numeric','min:0'], + 'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], + 'credits.*.amount' => ['required', 'bail'], ]; - if ($this->number) { - $rules['number'] = Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id); - } - if ($this->file('documents') && is_array($this->file('documents'))) { $rules['documents.*'] = $this->fileValidation(); } elseif ($this->file('documents')) { @@ -74,10 +74,6 @@ class UpdatePaymentRequest extends Request $input = $this->decodePrimaryKeys($input); - if (isset($input['client_id'])) { - unset($input['client_id']); - } - if (isset($input['amount'])) { unset($input['amount']); } @@ -85,7 +81,6 @@ class UpdatePaymentRequest extends Request if (isset($input['invoices']) && is_array($input['invoices']) !== false) { foreach ($input['invoices'] as $key => $value) { if(isset($input['invoices'][$key]['invoice_id'])) { - // if (array_key_exists('invoice_id', $input['invoices'][$key])) { $input['invoices'][$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']); } } @@ -93,7 +88,6 @@ class UpdatePaymentRequest extends Request if (isset($input['credits']) && is_array($input['credits']) !== false) { foreach ($input['credits'] as $key => $value) { - // if (array_key_exists('credits', $input['credits'][$key])) { if (isset($input['credits'][$key]['credit_id'])) { $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']); } diff --git a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php index 49530bca72..093aba14c8 100644 --- a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php +++ b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php @@ -57,9 +57,6 @@ class ValidRefundableRequest implements Rule if ($payment->invoices()->exists()) { $this->checkInvoice($payment->invoices, $request_invoices); - // foreach ($payment->invoices as $paymentable_invoice) { - // $this->checkInvoice($paymentable_invoice, $request_invoices); - // } } foreach ($request_invoices as $request_invoice) { diff --git a/app/Http/ValidationRules/PaymentAppliedValidAmount.php b/app/Http/ValidationRules/PaymentAppliedValidAmount.php index c6257fde8d..863b56d689 100644 --- a/app/Http/ValidationRules/PaymentAppliedValidAmount.php +++ b/app/Http/ValidationRules/PaymentAppliedValidAmount.php @@ -61,7 +61,10 @@ class PaymentAppliedValidAmount implements Rule $payment_amounts = 0; $invoice_amounts = 0; - $payment_amounts = $payment->amount - $payment->refunded - $payment->applied; + // $payment_amounts = $payment->amount - $payment->refunded - $payment->applied; + + //20-03-2024 - applied amounts are never tainted by refunded amount. + $payment_amounts = $payment->amount - $payment->applied; if (request()->has('credits') && is_array(request()->input('credits')) @@ -84,10 +87,6 @@ class PaymentAppliedValidAmount implements Rule $inv = $inv_collection->firstWhere('id', $invoice['invoice_id']); - nlog($inv->status_id); - nlog($inv->amount); - nlog($invoice['amount']); - if($inv->status_id == Invoice::STATUS_DRAFT && $inv->amount >= $invoice['amount']) { } elseif ($inv->balance < $invoice['amount']) { diff --git a/app/Http/ValidationRules/ValidCreditsPresentRule.php b/app/Http/ValidationRules/ValidCreditsPresentRule.php index 7dfb07df5f..50d3b32af5 100644 --- a/app/Http/ValidationRules/ValidCreditsPresentRule.php +++ b/app/Http/ValidationRules/ValidCreditsPresentRule.php @@ -17,6 +17,7 @@ use Illuminate\Contracts\Validation\Rule; /** * Class ValidCreditsPresentRule. + * @deprecated 20-03-2024 */ class ValidCreditsPresentRule implements Rule { @@ -49,11 +50,8 @@ class ValidCreditsPresentRule implements Rule private function validCreditsPresent(): bool { - //todo need to ensure the clients credits are here not random ones! - if (array_key_exists('credits', $this->input) && is_array($this->input['credits']) && count($this->input['credits']) > 0) { $credit_collection = Credit::query()->whereIn('id', array_column($this->input['credits'], 'credit_id'))->count(); - return $credit_collection == count($this->input['credits']); } diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index a9656846dc..4bec30aeaf 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -101,9 +101,7 @@ class PortalComposer $enabled_modules = auth()->guard('contact')->user()->company->enabled_modules; $data = []; - // TODO: Enable dashboard once it's completed. - // $this->settings->enable_client_portal_dashboard - // $data[] = [ 'title' => ctrans('texts.dashboard'), 'url' => 'client.dashboard', 'icon' => 'activity']; + $data[] = [ 'title' => ctrans('texts.dashboard'), 'url' => 'client.dashboard', 'icon' => 'activity']; if (self::MODULE_INVOICES & $enabled_modules) { $data[] = ['title' => ctrans('texts.invoices'), 'url' => 'client.invoices.index', 'icon' => 'file-text']; diff --git a/app/Jobs/Cron/UpdateCalculatedFields.php b/app/Jobs/Cron/UpdateCalculatedFields.php index 9145ab8f98..8abf9a2bd4 100644 --- a/app/Jobs/Cron/UpdateCalculatedFields.php +++ b/app/Jobs/Cron/UpdateCalculatedFields.php @@ -63,11 +63,14 @@ class UpdateCalculatedFields Project::query()->with('tasks')->whereHas('tasks', function ($query) { $query->where('updated_at', '>', now()->subHours(2)); }) - ->cursor() - ->each(function ($project) { - $project->current_hours = $this->calculateDuration($project); - $project->save(); - }); + ->cursor() + ->each(function ($project) { + $project->current_hours = $this->calculateDuration($project); + $project->save(); + }); + + //Clean password resets table + \DB::connection($db)->table('password_resets')->where('created_at', '<', now()->subHour())->delete(); } } diff --git a/app/Jobs/EDocument/CreateEDocument.php b/app/Jobs/EDocument/CreateEDocument.php new file mode 100644 index 0000000000..a2520b417a --- /dev/null +++ b/app/Jobs/EDocument/CreateEDocument.php @@ -0,0 +1,139 @@ +document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client; + App::setLocale($settings_entity->locale()); + + /* Set customized translations _NOW_ */ + $t->replace(Ninja::transformTranslations($this->document->client->getMergedSettings())); + + $e_document_type = strlen($settings_entity->getSetting('e_invoice_type')) > 2 ? $settings_entity->getSetting('e_invoice_type') : "XInvoice_3_0"; + $e_quote_type = strlen($settings_entity->getSetting('e_quote_type')) > 2 ? $settings_entity->getSetting('e_quote_type') : "OrderX_Extended"; + + if ($this->document instanceof Invoice){ + switch ($e_document_type) { + case "EN16931": + case "XInvoice_3_0": + case "XInvoice_2_3": + case "XInvoice_2_2": + case "XInvoice_2_1": + case "XInvoice_2_0": + case "XInvoice_1_0": + case "XInvoice-Extended": + case "XInvoice-BasicWL": + case "XInvoice-Basic": + $zugferd = (new ZugferdEDokument($this->document))->run(); + + return $this->returnObject ? $zugferd->xdocument : $zugferd->getXml(); + case "Facturae_3.2": + case "Facturae_3.2.1": + case "Facturae_3.2.2": + return (new FacturaEInvoice($this->document, str_replace("Facturae_", "", $e_document_type)))->run(); + default: + + $zugferd = (new ZugferdEDokument($this->document))->run(); + + return $this->returnObject ? $zugferd : $zugferd->getXml(); + + } + } + elseif ($this->document instanceof Quote){ + switch ($e_quote_type){ + case "OrderX_Basic": + case "OrderX_Comfort": + case "OrderX_Extended": + $orderx = (new OrderXDocument($this->document))->run(); + return $this->returnObject ? $orderx->orderxdocument : $orderx->getXml(); + default: + $orderx = (new OrderXDocument($this->document))->run(); + return $this->returnObject ? $orderx->orderxdocument : $orderx->getXml(); + } + } + elseif ($this->document instanceof PurchaseOrder){ + switch ($e_quote_type){ + case "OrderX_Basic": + case "OrderX_Comfort": + case "OrderX_Extended": + $orderx = (new OrderXDocument($this->document))->run(); + return $this->returnObject ? $orderx->orderxdocument : $orderx->getXml(); + default: + $orderx = (new OrderXDocument($this->document))->run(); + return $this->returnObject ? $orderx->orderxdocument : $orderx->getXml(); + } + } + elseif ($this->document instanceof Credit) { + switch ($e_document_type) { + case "EN16931": + case "XInvoice_3_0": + case "XInvoice_2_3": + case "XInvoice_2_2": + case "XInvoice_2_1": + case "XInvoice_2_0": + case "XInvoice_1_0": + case "XInvoice-Extended": + case "XInvoice-BasicWL": + case "XInvoice-Basic": + $zugferd = (new ZugferdEDokument($this->document))->run(); + return $this->returnObject ? $zugferd->xdocument : $zugferd->getXml(); + default: + $zugferd = (new ZugferdEDokument($this->document))->run(); + return $this->returnObject ? $zugferd : $zugferd->getXml(); + } + } + else{ + return ""; + } + } +} diff --git a/app/Jobs/Invoice/CreateEInvoice.php b/app/Jobs/Invoice/CreateEInvoice.php deleted file mode 100644 index 0ea7ae8a96..0000000000 --- a/app/Jobs/Invoice/CreateEInvoice.php +++ /dev/null @@ -1,86 +0,0 @@ -invoice->client->locale()); - - /* Set customized translations _NOW_ */ - $t->replace(Ninja::transformTranslations($this->invoice->client->getMergedSettings())); - - $e_invoice_type = $this->invoice->client->getSetting('e_invoice_type'); - - switch ($e_invoice_type) { - case "EN16931": - case "XInvoice_3_0": - case "XInvoice_2_3": - case "XInvoice_2_2": - case "XInvoice_2_1": - case "XInvoice_2_0": - case "XInvoice_1_0": - case "XInvoice-Extended": - case "XInvoice-BasicWL": - case "XInvoice-Basic": - $zugferd = (new ZugferdEInvoice($this->invoice))->run(); - - return $this->returnObject ? $zugferd->xrechnung : $zugferd->getXml(); - case "Facturae_3.2": - case "Facturae_3.2.1": - case "Facturae_3.2.2": - return (new FacturaEInvoice($this->invoice, str_replace("Facturae_", "", $e_invoice_type)))->run(); - default: - - $zugferd = (new ZugferdEInvoice($this->invoice))->run(); - - return $this->returnObject ? $zugferd : $zugferd->getXml(); - - } - - } -} diff --git a/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php b/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php index 76a91d6bee..401e2e5f48 100644 --- a/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php +++ b/app/Jobs/PurchaseOrder/ZipPurchaseOrders.php @@ -67,6 +67,11 @@ class ZipPurchaseOrders implements ShouldQueue try { foreach ($invitations as $invitation) { + if ($invitation->purchase_order->vendor->getSetting("enable_e_invoice")) { + $xml = $invitation->purchase_order->service()->getEInvoice(); + $zipFile->addFromString($invitation->purchase_order->getFileName("xml"), $xml); + } + $file = (new CreateRawPdf($invitation))->handle(); $zipFile->addFromString($invitation->purchase_order->numberFormatter().".pdf", $file); diff --git a/app/Jobs/Quote/ZipQuotes.php b/app/Jobs/Quote/ZipQuotes.php index a39c7615a4..fad4377189 100644 --- a/app/Jobs/Quote/ZipQuotes.php +++ b/app/Jobs/Quote/ZipQuotes.php @@ -63,6 +63,10 @@ class ZipQuotes implements ShouldQueue try { foreach ($invitations as $invitation) { + if ($invitation->quote->client->getSetting('enable_e_invoice')) { + $xml = $invitation->quote->service()->getEInvoice(); + $zipFile->addFromString($invitation->quote->getFileName("xml"), $xml); + } $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $zipFile->addFromString($invitation->quote->numberFormatter() . '.pdf', $file); } diff --git a/app/Livewire/PdfSlot.php b/app/Livewire/PdfSlot.php index 1322d6a966..81ad1fab61 100644 --- a/app/Livewire/PdfSlot.php +++ b/app/Livewire/PdfSlot.php @@ -12,7 +12,7 @@ namespace App\Livewire; -use App\Jobs\Invoice\CreateEInvoice; +use App\Jobs\EDocument\CreateEDocument; use App\Libraries\MultiDB; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; @@ -113,7 +113,7 @@ class PdfSlot extends Component $file_name = $this->entity->numberFormatter().'.xml'; - $file = (new CreateEInvoice($this->entity))->handle(); + $file = (new CreateEDocument($this->entity))->handle(); $headers = ['Content-Type' => 'application/xml']; diff --git a/app/Livewire/RequiredClientInfo.php b/app/Livewire/RequiredClientInfo.php index c661bbcb8c..5daabf4b29 100644 --- a/app/Livewire/RequiredClientInfo.php +++ b/app/Livewire/RequiredClientInfo.php @@ -222,6 +222,8 @@ class RequiredClientInfo extends Component $this->show_form = true; $hash = Cache::get(request()->input('hash')); + + /** @var \App\Models\Invoice $invoice */ $invoice = Invoice::find($this->decodePrimaryKey($hash['invoice_id'])); $this->invoice_terms = $invoice->terms; diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index 9beac3dbe3..da9cfa4fbf 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -140,7 +140,7 @@ class TemplateEmail extends Mailable 'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'logo' => $this->company->present()->logo($settings), 'links' => $this->build_email->getAttachmentLinks(), - 'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? $this->company->domain() . URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key], absolute: false) : false, + 'email_preferences' => (Ninja::isHosted() && $this->invitation && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? $this->company->domain() . URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key], absolute: false) : false, ]); foreach ($this->build_email->getAttachments() as $file) { @@ -159,15 +159,46 @@ class TemplateEmail extends Mailable } } - if ($this->invitation && $this->invitation->invoice && $this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { - $xml_string = $this->invitation->invoice->service()->getEInvoice($this->invitation->contact); + if ($this->invitation->invoice) { + if ($this->invitation && $this->invitation->invoice && $this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { + $xml_string = $this->invitation->invoice->service()->getEInvoice($this->invitation->contact); + + if ($xml_string) { + $this->attachData($xml_string, $this->invitation->invoice->getEFileName("xml")); + } - if($xml_string) { - $this->attachData($xml_string, $this->invitation->invoice->getEFileName("xml")); } - } + elseif ($this->invitation->credit){ + if ($this->invitation && $this->invitation->credit && $this->invitation->credit->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { + $xml_string = $this->invitation->credit->service()->getECredit($this->invitation->contact); + if ($xml_string) { + $this->attachData($xml_string, $this->invitation->credit->getEFileName("xml")); + } + + } + } + elseif ($this->invitation->quote){ + if ($this->invitation && $this->invitation->quote && $this->invitation->quote->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { + $xml_string = $this->invitation->quote->service()->getEQuote($this->invitation->contact); + + if ($xml_string) { + $this->attachData($xml_string, $this->invitation->quote->getEFileName("xml")); + } + + } + } + elseif ($this->invitation->purchase_order){ + if ($this->invitation && $this->invitation->purchase_order && $this->invitation->purchase_order->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { + $xml_string = $this->invitation->purchase_order->service()->getEPurchaseOrder($this->invitation->contact); + + if ($xml_string) { + $this->attachData($xml_string, $this->invitation->purchase_order->getEFileName("xml")); + } + + } + } return $this; } } diff --git a/app/Models/Client.php b/app/Models/Client.php index 6ac021a4bc..8525cde278 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -754,7 +754,7 @@ class Client extends BaseModel implements HasLocalePreference return $this->company->company_key.'/'.$this->client_hash.'/'.$contact_key.'/invoices/'; } - public function e_invoice_filepath($invitation): string + public function e_document_filepath($invitation): string { $contact_key = $invitation->contact->contact_key; diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index c9e3aa74b9..4f8352e23b 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -202,7 +202,6 @@ class CompanyUser extends Pivot */ public function portalType(): bool { - nlog(isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link); return isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link; } diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index c87375b3dc..61bfda77f8 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -698,7 +698,7 @@ class RecurringInvoice extends BaseModel public function subscription(): \Illuminate\Database\Eloquent\Relations\BelongsTo { - return $this->belongsTo(Subscription::class); + return $this->belongsTo(Subscription::class)->withTrashed(); } public function translate_entity() diff --git a/app/Models/Task.php b/app/Models/Task.php index f1716b15a8..a5d63760c1 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -12,6 +12,7 @@ namespace App\Models; use App\Utils\Traits\MakesHash; +use Carbon\CarbonInterval; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Carbon; @@ -248,6 +249,7 @@ class Task extends BaseModel $duration += max($end_time - $start_time, 0); } + // return CarbonInterval::seconds(round($duration))->locale($this->company->locale())->cascade()->forHumans(); return round($duration); } diff --git a/app/Models/User.php b/app/Models/User.php index 35441ff43d..7d8e2474e4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -226,6 +226,7 @@ class User extends Authenticatable implements MustVerifyEmail return $truth->getCompanyToken(); } + // if (request()->header('X-API-TOKEN')) { if (request()->header('X-API-TOKEN')) { return CompanyToken::with(['cu'])->where('token', request()->header('X-API-TOKEN'))->first(); } diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 51223b449a..8bc9e054fb 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -41,6 +41,7 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $phone * @property string|null $private_notes * @property string|null $website + * @property string|null $routing_id * @property bool $is_deleted * @property string|null $vat_number * @property string|null $transaction_name diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index a8ffd38cd6..3be4137148 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -126,14 +126,14 @@ class BaseDriver extends AbstractPaymentDriver $fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required']; } - if ($this->company_gateway->require_contact_name) { + // if ($this->company_gateway->require_contact_name) { $fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required']; - } + // } - if ($this->company_gateway->require_contact_email) { + // if ($this->company_gateway->require_contact_email) { $fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc']; - } + // } if ($this->company_gateway->require_client_phone) { $fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required']; @@ -579,15 +579,18 @@ class BaseDriver extends AbstractPaymentDriver $nmo->company = $this->client->company; $nmo->settings = $this->client->company->settings; - $invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get(); - - $invoices->first()->invitations->each(function ($invitation) use ($nmo) { - if (! $invitation->contact->trashed()) { - $nmo->to_user = $invitation->contact; - NinjaMailerJob::dispatch($nmo); - } - }); + if($this->payment_hash) + { + $invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get(); + $invoices->first()->invitations->each(function ($invitation) use ($nmo) { + if (! $invitation->contact->trashed()) { + $nmo->to_user = $invitation->contact; + NinjaMailerJob::dispatch($nmo); + } + }); + } + $message = [ 'server_response' => $response, 'data' => $this->payment_hash->data, diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index 5c86fae72a..35709850a5 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -292,7 +292,32 @@ class PayPalPPCPPaymentDriver extends BaseDriver } - $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + try { + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + } catch(\Exception $e) { + + //Rescue for duplicate invoice_id + if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) { + + + $_invoice = collect($this->payment_hash->data->invoices)->first(); + $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id)); + $new_invoice_number = $invoice->number."_".Str::random(5); + + $update_data = + [[ + "op" => "replace", + "path" => "/purchase_units/@reference_id=='default'/invoice_id", + "value" => $new_invoice_number, + ]]; + + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data); + + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + + } + + } $response = $r; diff --git a/app/PaymentDrivers/PayPalRestPaymentDriver.php b/app/PaymentDrivers/PayPalRestPaymentDriver.php index 1d2bbd90ba..464177737f 100644 --- a/app/PaymentDrivers/PayPalRestPaymentDriver.php +++ b/app/PaymentDrivers/PayPalRestPaymentDriver.php @@ -18,6 +18,7 @@ use App\Models\Invoice; use App\Models\SystemLog; use App\Models\GatewayType; use App\Models\PaymentType; +use Illuminate\Support\Str; use App\Jobs\Util\SystemLogger; use App\Utils\Traits\MakesHash; use App\Exceptions\PaymentFailed; @@ -211,7 +212,8 @@ class PayPalRestPaymentDriver extends BaseDriver $request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']); $response = json_decode($request['gateway_response'], true); - + + // nlog($response); //capture $orderID = $response['orderID']; @@ -235,7 +237,33 @@ class PayPalRestPaymentDriver extends BaseDriver } - $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + try{ + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + } + catch(\Exception $e) { + + //Rescue for duplicate invoice_id + if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false){ + + + $_invoice = collect($this->payment_hash->data->invoices)->first(); + $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id)); + $new_invoice_number = $invoice->number."_".Str::random(5); + + $update_data = + [[ + "op" => "replace", + "path" => "/purchase_units/@reference_id=='default'/invoice_id", + "value" => $new_invoice_number, + ]]; + + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data); + + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); + + } + + } $response = $r; diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 05278300bc..7d7838c561 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -252,6 +252,19 @@ class PaytracePaymentDriver extends BaseDriver return false; } + public function getClientRequiredFields(): array + { + $fields = parent::getClientRequiredFields(); + + $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; + + return $fields; + } + public function auth(): bool { try { diff --git a/app/PaymentDrivers/Stripe/ACH.php b/app/PaymentDrivers/Stripe/ACH.php index 4015fde435..d7594ea1c0 100644 --- a/app/PaymentDrivers/Stripe/ACH.php +++ b/app/PaymentDrivers/Stripe/ACH.php @@ -109,15 +109,36 @@ class ACH public function verificationView(ClientGatewayToken $token) { - if (isset($token->meta->state) && $token->meta->state === 'authorized') { - return redirect() - ->route('client.payment_methods.show', $token->hashed_id) - ->with('message', __('texts.payment_method_verified')); - } //double check here if we need to show the verification view. $this->stripe->init(); + if(substr($token->token,0,2) == 'pm'){ + $pm = $this->stripe->getStripePaymentMethod($token->token); + + if(!$pm->customer){ + + $meta = $token->meta; + $meta->state = 'unauthorized'; + $token->meta = $meta; + $token->save(); + + return redirect() + ->route('client.payment_methods.show', $token->hashed_id); + + } + + if (isset($token->meta->state) && $token->meta->state === 'authorized') { + return redirect() + ->route('client.payment_methods.show', $token->hashed_id) + ->with('message', __('texts.payment_method_verified')); + } + + if($token->meta->next_action) + return redirect($token->meta->next_action); + + } + $bank_account = Customer::retrieveSource($token->gateway_customer_reference, $token->token, [], $this->stripe->stripe_connect_auth); /* Catch externally validated bank accounts and mark them as verified */ @@ -319,6 +340,9 @@ class ACH $data['message'] = 'Too many requests made to the API too quickly'; break; case $e instanceof InvalidRequestException: + + return redirect()->route('client.payment_methods.verification', ['payment_method' => $cgt->hashed_id, 'method' => GatewayType::BANK_TRANSFER]); + $data['message'] = 'Invalid parameters were supplied to Stripe\'s API'; break; case $e instanceof AuthenticationException: diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index f440debb02..1b110cc0cd 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -332,14 +332,14 @@ class StripePaymentDriver extends BaseDriver $fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required']; } - if ($this->company_gateway->require_contact_name) { + // if ($this->company_gateway->require_contact_name) { $fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required']; - } + // } - if ($this->company_gateway->require_contact_email) { + // if ($this->company_gateway->require_contact_email) { $fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc']; - } + // } if ($this->company_gateway->require_client_phone) { $fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required']; diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 8a4996e045..c3a9313c5f 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -206,7 +206,8 @@ class UserRepository extends BaseRepository ->first(); $cu->restore(); - + $cu->tokens()->restore(); + event(new UserWasRestored($user, auth()->user(), auth()->user()->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); } diff --git a/app/Services/Credit/CreditService.php b/app/Services/Credit/CreditService.php index deb2f3dffe..77409f913e 100644 --- a/app/Services/Credit/CreditService.php +++ b/app/Services/Credit/CreditService.php @@ -12,6 +12,7 @@ namespace App\Services\Credit; use App\Factory\PaymentFactory; +use App\Jobs\EDocument\CreateEDocument; use App\Models\Credit; use App\Models\Payment; use App\Models\PaymentType; @@ -37,6 +38,11 @@ class CreditService return (new GetCreditPdf($invitation))->run(); } + public function getECredit($contact = null) + { + return (new CreateEDocument($this->credit))->handle(); + } + /** * Applies the invoice number. * @return $this InvoiceService object @@ -232,6 +238,27 @@ class CreditService return $this; } + public function deleteECredit() + { + $this->credit->load('invitations'); + + $this->credit->invitations->each(function ($invitation) { + try { + // if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + Storage::disk(config('filesystems.default'))->delete($this->credit->client->e_document_filepath($invitation).$this->credit->getFileName("xml")); + // } + + // if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + if (Ninja::isHosted()) { + Storage::disk('public')->delete($this->credit->client->e_document_filepath($invitation).$this->credit->getFileName("xml")); + } + } catch (\Exception $e) { + nlog($e->getMessage()); + } + }); + + return $this; + } public function triggeredActions($request) { $this->credit = (new TriggeredActions($this->credit, $request))->run(); diff --git a/app/Services/Invoice/EInvoice/FacturaEInvoice.php b/app/Services/EDocument/Standards/FacturaEInvoice.php similarity index 99% rename from app/Services/Invoice/EInvoice/FacturaEInvoice.php rename to app/Services/EDocument/Standards/FacturaEInvoice.php index e4b7f28bd9..c4182efbbb 100644 --- a/app/Services/Invoice/EInvoice/FacturaEInvoice.php +++ b/app/Services/EDocument/Standards/FacturaEInvoice.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Invoice\EInvoice; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Models\PaymentType; diff --git a/app/Services/Invoice/EInvoice/FatturaPA.php b/app/Services/EDocument/Standards/FatturaPA.php similarity index 99% rename from app/Services/Invoice/EInvoice/FatturaPA.php rename to app/Services/EDocument/Standards/FatturaPA.php index 2c448c7cfa..e8c0ad2145 100644 --- a/app/Services/Invoice/EInvoice/FatturaPA.php +++ b/app/Services/EDocument/Standards/FatturaPA.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Invoice\EInvoice; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Services\AbstractService; diff --git a/app/Services/EDocument/Standards/OrderXDocument.php b/app/Services/EDocument/Standards/OrderXDocument.php new file mode 100644 index 0000000000..fb43153140 --- /dev/null +++ b/app/Services/EDocument/Standards/OrderXDocument.php @@ -0,0 +1,250 @@ +document->company; + $settings_entity = ($this->document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client; + $profile = $settings_entity->getSetting('e_quote_type') ? $settings_entity->getSetting('e_quote_type') : "OrderX_Extended"; + + $profile = match ($profile) { + "OrderX_Basic" => OrderProfiles::PROFILE_BASIC, + "OrderX_Comfort" => OrderProfiles::PROFILE_COMFORT, + "OrderX_Extended" => OrderProfiles::PROFILE_EXTENDED, + default => OrderProfiles::PROFILE_EXTENDED, + }; + + $this->orderxdocument = OrderDocumentBuilder::CreateNew($profile); + + $this->orderxdocument + ->setDocumentSeller($company->getSetting('name')) + ->setDocumentSellerAddress($company->getSetting("address1"), $company->getSetting("address2"), "", $company->getSetting("postal_code"), $company->getSetting("city"), $company->country()->iso_3166_2, $company->getSetting("state")) + ->setDocumentSellerContact($this->document->user->present()->getFullName(), "", $this->document->user->present()->phone(), "", $this->document->user->email) + ->setDocumentBuyer($settings_entity->present()->name(), $settings_entity->number) + ->setDocumentBuyerAddress($settings_entity->address1, "", "", $settings_entity->postal_code, $settings_entity->city, $settings_entity->country->iso_3166_2, $settings_entity->state) + ->setDocumentBuyerContact($settings_entity->present()->primary_contact_name(), "", $settings_entity->present()->phone(), "", $settings_entity->present()->email()) + ->addDocumentPaymentTerm(ctrans("texts.xinvoice_payable", ['payeddue' => date_create($this->document->date ?? now()->format('Y-m-d'))->diff(date_create($this->document->due_date ?? now()->format('Y-m-d')))->format("%d"), 'paydate' => $this->document->due_date])); + + if (!empty($this->document->public_notes)) { + $this->orderxdocument->addDocumentNote($this->document->public_notes ?? ''); + } + // Document type + $document_class = get_class($this->document); + switch ($document_class){ + case Quote::class: + // Probably wrong file code https://github.com/horstoeko/zugferd/blob/master/src/codelists/ZugferdInvoiceType.php + if (empty($this->document->number)) { + $this->orderxdocument->setDocumentInformation("DRAFT", OrderDocumentTypes::ORDER, date_create($this->document->date ?? now()->format('Y-m-d')), $settings_entity->getCurrencyCode()); + $this->orderxdocument->setIsTestDocument(true); + } else { + $this->orderxdocument->setDocumentInformation($this->document->number, OrderDocumentTypes::ORDER, date_create($this->document->date ?? now()->format('Y-m-d')), $settings_entity->getCurrencyCode()); + }; + break; + case PurchaseOrder::class: + if (empty($this->document->number)) { + $this->orderxdocument->setDocumentInformation("DRAFT", OrderDocumentTypes::ORDER_RESPONSE, date_create($this->document->date ?? now()->format('Y-m-d')), $settings_entity->getCurrencyCode()); + $this->orderxdocument->setIsTestDocument(true); + } else { + $this->orderxdocument->setDocumentInformation($this->document->number, OrderDocumentTypes::ORDER_RESPONSE, date_create($this->document->date ?? now()->format('Y-m-d')), $settings_entity->getCurrencyCode()); + } + break; + } + if (isset($this->document->po_number)) { + $this->orderxdocument->setDocumentBuyerOrderReferencedDocument($this->document->po_number); + } + + if (empty($settings_entity->routing_id)) { + $this->orderxdocument->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference")); + } else { + $this->orderxdocument->setDocumentBuyerReference($settings_entity->routing_id); + } + if (isset($settings_entity->shipping_address1) && $settings_entity->shipping_country) { + $this->orderxdocument->setDocumentShipToAddress($settings_entity->shipping_address1, $settings_entity->shipping_address2, "", $settings_entity->shipping_postal_code, $settings_entity->shipping_city, $settings_entity->shipping_country->iso_3166_2, $settings_entity->shipping_state); + } + + $this->orderxdocument->addDocumentPaymentMean(68, ctrans("texts.xinvoice_online_payment")); + + if (str_contains($company->getSetting('vat_number'), "/")) { + $this->orderxdocument->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); + } else { + $this->orderxdocument->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); + } + + $invoicing_data = $this->document->calc(); + + //Create line items and calculate taxes + foreach ($this->document->line_items as $index => $item) { + /** @var \App\DataMapper\InvoiceItem $item **/ + $this->orderxdocument->addNewPosition($index) + ->setDocumentPositionGrossPrice($item->gross_line_total) + ->setDocumentPositionNetPrice($item->line_total); + if (!empty($item->product_key)) { + if (!empty($item->notes)) { + $this->orderxdocument->setDocumentPositionProductDetails($item->product_key, $item->notes); + } else { + $this->orderxdocument->setDocumentPositionProductDetails($item->product_key); + } + } else { + if (!empty($item->notes)) { + $this->orderxdocument->setDocumentPositionProductDetails($item->notes); + } else { + $this->orderxdocument->setDocumentPositionProductDetails("no product name defined"); + } + } +// TODO: add item classification (kg, m^3, ...) +// if (isset($item->task_id)) { +// $this->orderxdocument->setDocumentPositionQuantity($item->quantity, "HUR"); +// } else { +// $this->orderxdocument->setDocumentPositionQuantity($item->quantity, "H87"); +// } + $linenetamount = $item->line_total; + if ($item->discount > 0) { + if ($this->document->is_amount_discount) { + $linenetamount -= $item->discount; + } else { + $linenetamount -= $linenetamount * ($item->discount / 100); + } + } + $this->orderxdocument->setDocumentPositionLineSummation($linenetamount); + // According to european law, each line item can only have one tax rate + if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) { + $taxtype = $this->getTaxType($item->tax_id); + if (!empty($item->tax_name1)) { + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); + $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate1); + } elseif (!empty($item->tax_name2)) { + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); + $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate2); + } elseif (!empty($item->tax_name3)) { + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); + $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate3); + } else { + nlog("Can't add correct tax position"); + } + } else { + if (!empty($this->document->tax_name1)) { + $taxtype = $this->getTaxType($this->document->tax_name1); + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate1); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate1); + } elseif (!empty($this->document->tax_name2)) { + $taxtype = $this->getTaxType($this->document->tax_name2); + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate2); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate2); + } elseif (!empty($this->document->tax_name3)) { + $taxtype = $this->getTaxType($this->document->tax_name3); + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate3); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate3); + } else { + $taxtype = OrderDutyTaxFeeCategories::ZERO_RATED_GOODS; + $this->orderxdocument->addDocumentPositionTax($taxtype, 'VAT', 0); + $this->addtoTaxMap($taxtype, $linenetamount, 0); + // nlog("Can't add correct tax position"); + } + } + } + + $this->orderxdocument->setDocumentSummation($this->document->amount, $this->document->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->document->amount - $this->document->balance); + + foreach ($this->tax_map as $item) { + $this->orderxdocument->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100); + } + + // The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload + return $this; + + } + + /** + * Returns the XML document + * in string format + * + * @return string + */ + public function getXml(): string + { + return $this->orderxdocument->getContent(); + } + + private function getTaxType($name): string + { + $tax_type = null; + switch ($name) { + case Product::PRODUCT_TYPE_SERVICE: + case Product::PRODUCT_TYPE_DIGITAL: + case Product::PRODUCT_TYPE_PHYSICAL: + case Product::PRODUCT_TYPE_SHIPPING: + case Product::PRODUCT_TYPE_REDUCED_TAX: + $tax_type = OrderDutyTaxFeeCategories::STANDARD_RATE; + break; + case Product::PRODUCT_TYPE_EXEMPT: + $tax_type = OrderDutyTaxFeeCategories::EXEMPT_FROM_TAX; + break; + case Product::PRODUCT_TYPE_ZERO_RATED: + $tax_type = OrderDutyTaxFeeCategories::ZERO_RATED_GOODS; + break; + case Product::PRODUCT_TYPE_REVERSE_TAX: + $tax_type = OrderDutyTaxFeeCategories::VAT_REVERSE_CHARGE; + break; + } + $eu_states = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "EL", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "IS", "LI", "NO", "CH"]; + if (empty($tax_type)) { + if ((in_array($this->document->company->country()->iso_3166_2, $eu_states) && in_array($this->document->client->country->iso_3166_2, $eu_states)) && $this->document->company->country()->iso_3166_2 != $this->document->client->country->iso_3166_2) { + $tax_type = OrderDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES; + } elseif (!in_array($this->document->client->country->iso_3166_2, $eu_states)) { + $tax_type = OrderDutyTaxFeeCategories::SERVICE_OUTSIDE_SCOPE_OF_TAX; + } elseif ($this->document->client->country->iso_3166_2 == "ES-CN") { + $tax_type = OrderDutyTaxFeeCategories::CANARY_ISLANDS_GENERAL_INDIRECT_TAX; + } elseif (in_array($this->document->client->country->iso_3166_2, ["ES-CE", "ES-ML"])) { + $tax_type = OrderDutyTaxFeeCategories::TAX_FOR_PRODUCTION_SERVICES_AND_IMPORTATION_IN_CEUTA_AND_MELILLA; + } else { + nlog("Unkown tax case for xinvoice"); + $tax_type = OrderDutyTaxFeeCategories::STANDARD_RATE; + } + } + return $tax_type; + } + private function addtoTaxMap(string $tax_type, float $net_amount, float $tax_rate): void + { + $hash = hash("md5", $tax_type."-".$tax_rate); + if (array_key_exists($hash, $this->tax_map)) { + $this->tax_map[$hash]["net_amount"] += $net_amount; + } else { + $this->tax_map[$hash] = [ + "tax_type" => $tax_type, + "net_amount" => $net_amount, + "tax_rate" => $tax_rate / 100 + ]; + } + } + +} diff --git a/app/Services/Invoice/EInvoice/RoEInvoice.php b/app/Services/EDocument/Standards/RoEInvoice.php similarity index 99% rename from app/Services/Invoice/EInvoice/RoEInvoice.php rename to app/Services/EDocument/Standards/RoEInvoice.php index d01aae4920..d9945e9834 100644 --- a/app/Services/Invoice/EInvoice/RoEInvoice.php +++ b/app/Services/EDocument/Standards/RoEInvoice.php @@ -9,28 +9,28 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Invoice\EInvoice; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Services\AbstractService; use CleverIt\UBL\Invoice\Address; +use CleverIt\UBL\Invoice\ClassifiedTaxCategory; use CleverIt\UBL\Invoice\Contact; use CleverIt\UBL\Invoice\Country; use CleverIt\UBL\Invoice\Generator; use CleverIt\UBL\Invoice\Invoice as UBLInvoice; use CleverIt\UBL\Invoice\InvoiceLine; use CleverIt\UBL\Invoice\Item; +use CleverIt\UBL\Invoice\LegalEntity; use CleverIt\UBL\Invoice\LegalMonetaryTotal; use CleverIt\UBL\Invoice\Party; +use CleverIt\UBL\Invoice\PayeeFinancialAccount; +use CleverIt\UBL\Invoice\PaymentMeans; +use CleverIt\UBL\Invoice\Price; use CleverIt\UBL\Invoice\TaxCategory; use CleverIt\UBL\Invoice\TaxScheme; use CleverIt\UBL\Invoice\TaxSubTotal; use CleverIt\UBL\Invoice\TaxTotal; -use CleverIt\UBL\Invoice\PaymentMeans; -use CleverIt\UBL\Invoice\PayeeFinancialAccount; -use CleverIt\UBL\Invoice\LegalEntity; -use CleverIt\UBL\Invoice\ClassifiedTaxCategory; -use CleverIt\UBL\Invoice\Price; class RoEInvoice extends AbstractService { diff --git a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php b/app/Services/EDocument/Standards/ZugferdEDokument.php similarity index 56% rename from app/Services/Invoice/EInvoice/ZugferdEInvoice.php rename to app/Services/EDocument/Standards/ZugferdEDokument.php index 59ab32605a..918a96a617 100644 --- a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php +++ b/app/Services/EDocument/Standards/ZugferdEDokument.php @@ -9,28 +9,31 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\Invoice\EInvoice; +namespace App\Services\EDocument\Standards; +use App\Models\Credit; use App\Models\Invoice; use App\Models\Product; +use App\Models\PurchaseOrder; +use App\Models\Quote; use App\Services\AbstractService; use horstoeko\zugferd\codelists\ZugferdDutyTaxFeeCategories; use horstoeko\zugferd\ZugferdDocumentBuilder; use horstoeko\zugferd\ZugferdProfiles; -class ZugferdEInvoice extends AbstractService +class ZugferdEDokument extends AbstractService { - public ZugferdDocumentBuilder $xrechnung; + public ZugferdDocumentBuilder $xdocument; - public function __construct(public Invoice $invoice, private readonly bool $returnObject = false, private array $tax_map = []) + public function __construct(public object $document, private readonly bool $returnObject = false, private array $tax_map = []) { } public function run(): self { - $company = $this->invoice->company; - $client = $this->invoice->client; + $company = $this->document->company; + $client = $this->document->client; $profile = $client->getSetting('e_invoice_type'); $profile = match ($profile) { @@ -46,123 +49,143 @@ class ZugferdEInvoice extends AbstractService default => ZugferdProfiles::PROFILE_EN16931, }; - $this->xrechnung = ZugferdDocumentBuilder::CreateNew($profile); + $this->xdocument = ZugferdDocumentBuilder::CreateNew($profile); - $this->xrechnung - ->setDocumentSupplyChainEvent(date_create($this->invoice->date ?? now()->format('Y-m-d'))) + $this->xdocument + ->setDocumentSupplyChainEvent(date_create($this->document->date ?? now()->format('Y-m-d'))) ->setDocumentSeller($company->getSetting('name')) ->setDocumentSellerAddress($company->getSetting("address1"), $company->getSetting("address2"), "", $company->getSetting("postal_code"), $company->getSetting("city"), $company->country()->iso_3166_2, $company->getSetting("state")) - ->setDocumentSellerContact($this->invoice->user->present()->getFullName(), "", $this->invoice->user->present()->phone(), "", $this->invoice->user->email) + ->setDocumentSellerContact($this->document->user->present()->getFullName(), "", $this->document->user->present()->phone(), "", $this->document->user->email) ->setDocumentBuyer($client->present()->name(), $client->number) ->setDocumentBuyerAddress($client->address1, "", "", $client->postal_code, $client->city, $client->country->iso_3166_2, $client->state) ->setDocumentBuyerContact($client->present()->primary_contact_name(), "", $client->present()->phone(), "", $client->present()->email()) - ->addDocumentPaymentTerm(ctrans("texts.xinvoice_payable", ['payeddue' => date_create($this->invoice->date ?? now()->format('Y-m-d'))->diff(date_create($this->invoice->due_date ?? now()->format('Y-m-d')))->format("%d"), 'paydate' => $this->invoice->due_date])); + ->addDocumentPaymentTerm(ctrans("texts.xinvoice_payable", ['payeddue' => date_create($this->document->date ?? now()->format('Y-m-d'))->diff(date_create($this->document->due_date ?? now()->format('Y-m-d')))->format("%d"), 'paydate' => $this->document->due_date])); - if (!empty($this->invoice->public_notes)) { - $this->xrechnung->addDocumentNote($this->invoice->public_notes ?? ''); + if (!empty($this->document->public_notes)) { + $this->xdocument->addDocumentNote($this->document->public_notes ?? ''); } - if (empty($this->invoice->number)) { - $this->xrechnung->setDocumentInformation("DRAFT", "380", date_create($this->invoice->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); - } else { - $this->xrechnung->setDocumentInformation($this->invoice->number, "380", date_create($this->invoice->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + // Document type + $document_class = get_class($this->document); + switch ($document_class){ + case Quote::class: + // Probably wrong file code https://github.com/horstoeko/zugferd/blob/master/src/codelists/ZugferdInvoiceType.php + if (empty($this->document->number)) { + $this->xdocument->setDocumentInformation("DRAFT", "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + } else { + $this->xdocument->setDocumentInformation($this->document->number, "84", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + }; + break; + case Invoice::class: + if (empty($this->document->number)) { + $this->xdocument->setDocumentInformation("DRAFT", "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + } else { + $this->xdocument->setDocumentInformation($this->document->number, "380", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + } + break; + case Credit::class: + if (empty($this->document->number)) { + $this->xdocument->setDocumentInformation("DRAFT", "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + } else { + $this->xdocument->setDocumentInformation($this->document->number, "389", date_create($this->document->date ?? now()->format('Y-m-d')), $client->getCurrencyCode()); + } } - if (isset($this->invoice->po_number)) { - $this->xrechnung->setDocumentBuyerOrderReferencedDocument($this->invoice->po_number); + if (isset($this->document->po_number)) { + $this->xdocument->setDocumentBuyerOrderReferencedDocument($this->document->po_number); } if (empty($client->routing_id)) { - $this->xrechnung->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference")); + $this->xdocument->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference")); } else { - $this->xrechnung->setDocumentBuyerReference($client->routing_id); + $this->xdocument->setDocumentBuyerReference($client->routing_id); } if (isset($client->shipping_address1) && $client->shipping_country) { - $this->xrechnung->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); + $this->xdocument->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); } - $this->xrechnung->addDocumentPaymentMean(68, ctrans("texts.xinvoice_online_payment")); + $this->xdocument->addDocumentPaymentMean(68, ctrans("texts.xinvoice_online_payment")); if (str_contains($company->getSetting('vat_number'), "/")) { - $this->xrechnung->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); + $this->xdocument->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); } else { - $this->xrechnung->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); + $this->xdocument->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); } - $invoicing_data = $this->invoice->calc(); + $invoicing_data = $this->document->calc(); //Create line items and calculate taxes - foreach ($this->invoice->line_items as $index => $item) { + foreach ($this->document->line_items as $index => $item) { /** @var \App\DataMapper\InvoiceItem $item **/ - $this->xrechnung->addNewPosition($index) + $this->xdocument->addNewPosition($index) ->setDocumentPositionGrossPrice($item->gross_line_total) ->setDocumentPositionNetPrice($item->line_total); if (!empty($item->product_key)) { if (!empty($item->notes)) { - $this->xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes); + $this->xdocument->setDocumentPositionProductDetails($item->product_key, $item->notes); } else { - $this->xrechnung->setDocumentPositionProductDetails($item->product_key); + $this->xdocument->setDocumentPositionProductDetails($item->product_key); } } else { if (!empty($item->notes)) { - $this->xrechnung->setDocumentPositionProductDetails($item->notes); + $this->xdocument->setDocumentPositionProductDetails($item->notes); } else { - $this->xrechnung->setDocumentPositionProductDetails("no product name defined"); + $this->xdocument->setDocumentPositionProductDetails("no product name defined"); } } - if (isset($item->task_id)) { - $this->xrechnung->setDocumentPositionQuantity($item->quantity, "HUR"); + if ($item->type_id == 2) { + $this->xdocument->setDocumentPositionQuantity($item->quantity, "HUR"); } else { - $this->xrechnung->setDocumentPositionQuantity($item->quantity, "H87"); + $this->xdocument->setDocumentPositionQuantity($item->quantity, "H87"); } $linenetamount = $item->line_total; if ($item->discount > 0) { - if ($this->invoice->is_amount_discount) { + if ($this->document->is_amount_discount) { $linenetamount -= $item->discount; } else { $linenetamount -= $linenetamount * ($item->discount / 100); } } - $this->xrechnung->setDocumentPositionLineSummation($linenetamount); + $this->xdocument->setDocumentPositionLineSummation($linenetamount); // According to european law, each line item can only have one tax rate if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) { $taxtype = $this->getTaxType($item->tax_id); if (!empty($item->tax_name1)) { - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate1); } elseif (!empty($item->tax_name2)) { - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate2); } elseif (!empty($item->tax_name3)) { - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate3); } else { // nlog("Can't add correct tax position"); } } else { - if (!empty($this->invoice->tax_name1)) { - $taxtype = $this->getTaxType($this->invoice->tax_name1); - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate1); - $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate1); - } elseif (!empty($this->invoice->tax_name2)) { - $taxtype = $this->getTaxType($this->invoice->tax_name2); - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate2); - $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate2); - } elseif (!empty($this->invoice->tax_name3)) { - $taxtype = $this->getTaxType($this->invoice->tax_name3); - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate3); - $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate3); + if (!empty($this->document->tax_name1)) { + $taxtype = $this->getTaxType($this->document->tax_name1); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate1); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate1); + } elseif (!empty($this->document->tax_name2)) { + $taxtype = $this->getTaxType($this->document->tax_name2); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate2); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate2); + } elseif (!empty($this->document->tax_name3)) { + $taxtype = $this->getTaxType($this->document->tax_name3); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', $this->document->tax_rate3); + $this->addtoTaxMap($taxtype, $linenetamount, $this->document->tax_rate3); } else { $taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS; - $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', 0); + $this->xdocument->addDocumentPositionTax($taxtype, 'VAT', 0); $this->addtoTaxMap($taxtype, $linenetamount, 0); // nlog("Can't add correct tax position"); } } } - $this->xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->invoice->amount - $this->invoice->balance); + $this->xdocument->setDocumentSummation($this->document->amount, $this->document->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->document->amount - $this->document->balance); foreach ($this->tax_map as $item) { - $this->xrechnung->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100); + $this->xdocument->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"] * $item["net_amount"], $item["tax_rate"] * 100); } // The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload @@ -178,7 +201,7 @@ class ZugferdEInvoice extends AbstractService */ public function getXml(): string { - return $this->xrechnung->getContent(); + return $this->xdocument->getContent(); } private function getTaxType($name): string @@ -204,13 +227,13 @@ class ZugferdEInvoice extends AbstractService } $eu_states = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "EL", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "IS", "LI", "NO", "CH"]; if (empty($tax_type)) { - if ((in_array($this->invoice->company->country()->iso_3166_2, $eu_states) && in_array($this->invoice->client->country->iso_3166_2, $eu_states)) && $this->invoice->company->country()->iso_3166_2 != $this->invoice->client->country->iso_3166_2) { + if ((in_array($this->document->company->country()->iso_3166_2, $eu_states) && in_array($this->document->client->country->iso_3166_2, $eu_states)) && $this->document->company->country()->iso_3166_2 != $this->document->client->country->iso_3166_2) { $tax_type = ZugferdDutyTaxFeeCategories::VAT_EXEMPT_FOR_EEA_INTRACOMMUNITY_SUPPLY_OF_GOODS_AND_SERVICES; - } elseif (!in_array($this->invoice->client->country->iso_3166_2, $eu_states)) { + } elseif (!in_array($this->document->client->country->iso_3166_2, $eu_states)) { $tax_type = ZugferdDutyTaxFeeCategories::SERVICE_OUTSIDE_SCOPE_OF_TAX; - } elseif ($this->invoice->client->country->iso_3166_2 == "ES-CN") { + } elseif ($this->document->client->country->iso_3166_2 == "ES-CN") { $tax_type = ZugferdDutyTaxFeeCategories::CANARY_ISLANDS_GENERAL_INDIRECT_TAX; - } elseif (in_array($this->invoice->client->country->iso_3166_2, ["ES-CE", "ES-ML"])) { + } elseif (in_array($this->document->client->country->iso_3166_2, ["ES-CE", "ES-ML"])) { $tax_type = ZugferdDutyTaxFeeCategories::TAX_FOR_PRODUCTION_SERVICES_AND_IMPORTATION_IN_CEUTA_AND_MELILLA; } else { nlog("Unkown tax case for xinvoice"); diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index 04b945ff47..5346c0636f 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -17,6 +17,8 @@ use App\Jobs\Invoice\CreateUbl; use App\Models\Account; use App\Models\Expense; use App\Models\Invoice; +use App\Models\PurchaseOrder; +use App\Models\Quote; use App\Models\Task; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; @@ -318,7 +320,7 @@ class EmailDefaults } } /** E-Invoice xml file */ - if ($this->email->email_object->settings->enable_e_invoice && $this->email->email_object->entity instanceof Invoice) { + if ($this->email->email_object->settings->enable_e_invoice && ! $this->email->email_object->entity instanceof PurchaseOrder) { $xml_string = $this->email->email_object->entity->service()->getEInvoice(); if($xml_string) { diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index dbe57e361b..c89c246a49 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -11,21 +11,21 @@ namespace App\Services\Invoice; -use App\Models\Task; -use App\Utils\Ninja; +use App\Events\Invoice\InvoiceWasArchived; +use App\Jobs\EDocument\CreateEDocument; +use App\Jobs\Entity\CreateRawPdf; +use App\Jobs\Inventory\AdjustProductInventory; +use App\Libraries\Currency\Conversion\CurrencyApi; +use App\Models\CompanyGateway; use App\Models\Expense; use App\Models\Invoice; use App\Models\Payment; use App\Models\Subscription; -use App\Models\CompanyGateway; -use Illuminate\Support\Carbon; +use App\Models\Task; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; -use App\Jobs\Entity\CreateRawPdf; -use App\Jobs\Invoice\CreateEInvoice; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Storage; -use App\Events\Invoice\InvoiceWasArchived; -use App\Jobs\Inventory\AdjustProductInventory; -use App\Libraries\Currency\Conversion\CurrencyApi; class InvoiceService { @@ -201,7 +201,7 @@ class InvoiceService public function getEInvoice($contact = null) { - return (new CreateEInvoice($this->invoice))->handle(); + return (new CreateEDocument($this->invoice))->handle(); } public function sendEmail($contact = null) @@ -409,12 +409,12 @@ class InvoiceService $this->invoice->invitations->each(function ($invitation) { try { // if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { - Storage::disk(config('filesystems.default'))->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml")); + Storage::disk(config('filesystems.default'))->delete($this->invoice->client->e_document_filepath($invitation).$this->invoice->getFileName("xml")); // } // if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { if (Ninja::isHosted()) { - Storage::disk('public')->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml")); + Storage::disk('public')->delete($this->invoice->client->e_document_filepath($invitation).$this->invoice->getFileName("xml")); } } catch (\Exception $e) { nlog($e->getMessage()); diff --git a/app/Services/Pdf/PdfService.php b/app/Services/Pdf/PdfService.php index e0db7d4064..4a579db80c 100644 --- a/app/Services/Pdf/PdfService.php +++ b/app/Services/Pdf/PdfService.php @@ -11,7 +11,7 @@ namespace App\Services\Pdf; -use App\Jobs\Invoice\CreateEInvoice; +use App\Jobs\EDocument\CreateEDocument; use App\Models\Company; use App\Models\CreditInvitation; use App\Models\Invoice; @@ -216,7 +216,7 @@ class PdfService { try { - $e_rechnung = (new CreateEInvoice($this->config->entity, true))->handle(); + $e_rechnung = (new CreateEDocument($this->config->entity, true))->handle(); $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $pdf); $pdfBuilder->generateDocument(); diff --git a/app/Services/PurchaseOrder/PurchaseOrderService.php b/app/Services/PurchaseOrder/PurchaseOrderService.php index b7bc07cb2c..686329599f 100644 --- a/app/Services/PurchaseOrder/PurchaseOrderService.php +++ b/app/Services/PurchaseOrder/PurchaseOrderService.php @@ -11,8 +11,11 @@ namespace App\Services\PurchaseOrder; +use App\Jobs\EDocument\CreateEDocument; use App\Models\PurchaseOrder; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; +use Illuminate\Support\Facades\Storage; class PurchaseOrderService { @@ -75,6 +78,32 @@ class PurchaseOrderService return (new GetPurchaseOrderPdf($this->purchase_order, $contact))->run(); } + public function getEPurchaseOrder($contact = null) + { + return (new CreateEDocument($this->purchase_order))->handle(); + } + public function deleteEPurchaseOrder() + { + $this->purchase_order->load('invitations'); + + $this->purchase_order->invitations->each(function ($invitation) { + try { + // if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + Storage::disk(config('filesystems.default'))->delete($this->purchase_order->vendor->e_document_filepath($invitation).$this->purchase_order->getFileName("xml")); + // } + + // if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + if (Ninja::isHosted()) { + Storage::disk('public')->delete($this->purchase_order->vendor->e_document_filepath($invitation).$this->purchase_order->getFileName("xml")); + } + } catch (\Exception $e) { + nlog($e->getMessage()); + } + }); + + return $this; + } + public function setStatus($status) { $this->purchase_order->status_id = $status; diff --git a/app/Services/Quote/QuoteService.php b/app/Services/Quote/QuoteService.php index ddfebbe00b..f2ee47666a 100644 --- a/app/Services/Quote/QuoteService.php +++ b/app/Services/Quote/QuoteService.php @@ -13,6 +13,7 @@ namespace App\Services\Quote; use App\Events\Quote\QuoteWasApproved; use App\Exceptions\QuoteConversion; +use App\Jobs\EDocument\CreateEDocument; use App\Models\Project; use App\Models\Quote; use App\Repositories\QuoteRepository; @@ -72,6 +73,11 @@ class QuoteService return (new GetQuotePdf($this->quote, $contact))->run(); } + public function getEQuote($contact = null) + { + return (new CreateEDocument($this->quote))->handle(); + } + public function sendEmail($contact = null): self { $send_email = new SendEmail($this->quote, null, $contact); @@ -226,6 +232,27 @@ class QuoteService return $this; } + public function deleteEQuote() + { + $this->quote->load('invitations'); + + $this->quote->invitations->each(function ($invitation) { + try { + // if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + Storage::disk(config('filesystems.default'))->delete($this->quote->client->e_document_filepath($invitation).$this->quote->getFileName("xml")); + // } + + // if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { + if (Ninja::isHosted()) { + Storage::disk('public')->delete($this->quote->client->e_document_filepath($invitation).$this->quote->getFileName("xml")); + } + } catch (\Exception $e) { + nlog($e->getMessage()); + } + }); + + return $this; + } /** * Saves the quote. diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 4e38ee26a3..30023ce962 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -92,7 +92,8 @@ class AccountTransformer extends EntityTransformer 'account_sms_verified' => (bool) $account->account_sms_verified, 'has_iap_plan' => (bool)$account->inapp_transaction_id, 'tax_api_enabled' => (bool) config('services.tax.zip_tax.key') ? true : false, - 'nordigen_enabled' => (bool) (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')) ? true : false + 'nordigen_enabled' => (bool) (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')) ? true : false, + 'upload_extensions' => (string) config('ninja.upload_extensions'), ]; } diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index c0274a3e81..78cbf8e718 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -109,7 +109,10 @@ class UserTransformer extends EntityTransformer $transformer = new CompanyUserTransformer($this->serializer); - $cu = $user->company_users()->whereCompanyId($user->company_id)->first(); + $cu = $user->company_users()->where('company_id',$user->company_id)->first(); + + if(!$cu) + return null; return $this->includeItem($cu, $transformer, CompanyUser::class); } diff --git a/app/Transformers/VendorTransformer.php b/app/Transformers/VendorTransformer.php index de73267182..6fc6c9968a 100644 --- a/app/Transformers/VendorTransformer.php +++ b/app/Transformers/VendorTransformer.php @@ -107,6 +107,7 @@ class VendorTransformer extends EntityTransformer 'display_name' => (string) $vendor->present()->name(), 'invoicing_email' => (string) $vendor->invoicing_email ?: '', 'invoicing_domain' => (string) $vendor->invoicing_domain ?: '', + 'routing_id' => (string) $vendor->routing_id ?: '', ]; } } diff --git a/composer.json b/composer.json index 21ea79984b..bca5882fba 100644 --- a/composer.json +++ b/composer.json @@ -56,6 +56,7 @@ "hashids/hashids": "^4.0", "hedii/laravel-gelf-logger": "^8", "horstoeko/zugferd": "^1", + "horstoeko/orderx": "^1", "imdhemy/laravel-purchases": "^1.7", "intervention/image": "^2.5", "invoiceninja/inspector": "^2.0", @@ -115,7 +116,6 @@ "barryvdh/laravel-ide-helper": "^2.13", "beyondcode/laravel-query-detector": "^1.8", "brianium/paratest": "^7", - "fakerphp/faker": "^1.14", "filp/whoops": "^2.7", "friendsofphp/php-cs-fixer": "^3.14", "laracasts/cypress": "^3.0", diff --git a/composer.lock b/composer.lock index fed2fd9e57..df236124fc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,48 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fdea921aefca562c17db327acd8df062", + "content-hash": "a7fb762c099a95d6168ef390844bb87b", "packages": [ + { + "name": "adrienrn/php-mimetyper", + "version": "0.2.2", + "source": { + "type": "git", + "url": "https://github.com/adrienrn/php-mimetyper.git", + "reference": "702e00a604b4baed34d69730ce055e05c0f43932" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/adrienrn/php-mimetyper/zipball/702e00a604b4baed34d69730ce055e05c0f43932", + "reference": "702e00a604b4baed34d69730ce055e05c0f43932", + "shasum": "" + }, + "require": { + "dflydev/apache-mime-types": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "MimeTyper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Hussard", + "email": "adrien.ricartnoblet@gmail.com" + } + ], + "description": "PHP mime type and extension mapping library: compatible with Symfony, powered by jshttp/mime-db", + "support": { + "issues": "https://github.com/adrienrn/php-mimetyper/issues", + "source": "https://github.com/adrienrn/php-mimetyper/tree/0.2.2" + }, + "time": "2018-09-27T09:45:05+00:00" + }, { "name": "afosto/yaac", "version": "v1.5.2", @@ -2096,6 +2136,65 @@ ], "time": "2023-11-20T14:41:54+00:00" }, + { + "name": "dflydev/apache-mime-types", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-apache-mime-types.git", + "reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-apache-mime-types/zipball/f30a57e59b7476e4c5270b6a0727d79c9c0eb861", + "reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "twig/twig": "1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\ApacheMimeTypes": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + } + ], + "description": "Apache MIME Types", + "keywords": [ + "apache", + "mime", + "mimetypes" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-apache-mime-types/issues", + "source": "https://github.com/dflydev/dflydev-apache-mime-types/tree/v1.0.1" + }, + "time": "2013-05-14T02:02:01+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.2", @@ -4379,6 +4478,74 @@ }, "time": "2023-09-22T20:17:48+00:00" }, + { + "name": "horstoeko/orderx", + "version": "v1.0.20", + "source": { + "type": "git", + "url": "https://github.com/horstoeko/orderx.git", + "reference": "d8957cc0fea19b098d799a0c438a73504e7b326c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/horstoeko/orderx/zipball/d8957cc0fea19b098d799a0c438a73504e7b326c", + "reference": "d8957cc0fea19b098d799a0c438a73504e7b326c", + "shasum": "" + }, + "require": { + "adrienrn/php-mimetyper": "^0.2", + "ext-simplexml": "*", + "goetas-webservices/xsd2php-runtime": "^0.2.13", + "horstoeko/stringmanagement": "^1", + "jms/serializer": "^3", + "php": "^7.3|^7.4|^8", + "setasign/fpdf": "^1", + "setasign/fpdi": "^2", + "smalot/pdfparser": "^0", + "symfony/validator": "^5|^6", + "symfony/yaml": "^5|^6" + }, + "require-dev": { + "goetas-webservices/xsd2php": "^0", + "pdepend/pdepend": "^2", + "phploc/phploc": "^7", + "phpmd/phpmd": "^2", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9", + "sebastian/phpcpd": "^6", + "squizlabs/php_codesniffer": "^3" + }, + "type": "package", + "autoload": { + "psr-4": { + "horstoeko\\orderx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Erling", + "email": "daniel@erling.com.de", + "role": "lead" + } + ], + "description": "A library for creating and reading Order-X document", + "homepage": "https://github.com/horstoeko/orderx", + "keywords": [ + "electronic", + "order", + "order-x", + "orderx" + ], + "support": { + "issues": "https://github.com/horstoeko/orderx/issues", + "source": "https://github.com/horstoeko/orderx/tree/v1.0.20" + }, + "time": "2024-03-21T04:28:54+00:00" + }, { "name": "horstoeko/stringmanagement", "version": "v1.0.11", @@ -4435,16 +4602,16 @@ }, { "name": "horstoeko/zugferd", - "version": "v1.0.36", + "version": "v1.0.37", "source": { "type": "git", "url": "https://github.com/horstoeko/zugferd.git", - "reference": "0d15c305328c137365648fe1c34a584d877127fa" + "reference": "05f58ad4dbcc23d767fceb15f46b46097ffd43f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/0d15c305328c137365648fe1c34a584d877127fa", - "reference": "0d15c305328c137365648fe1c34a584d877127fa", + "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/05f58ad4dbcc23d767fceb15f46b46097ffd43f1", + "reference": "05f58ad4dbcc23d767fceb15f46b46097ffd43f1", "shasum": "" }, "require": { @@ -4462,6 +4629,7 @@ }, "require-dev": { "goetas-webservices/xsd2php": "^0", + "nette/php-generator": "*", "pdepend/pdepend": "^2", "phploc/phploc": "^7", "phpmd/phpmd": "^2", @@ -4502,9 +4670,9 @@ ], "support": { "issues": "https://github.com/horstoeko/zugferd/issues", - "source": "https://github.com/horstoeko/zugferd/tree/v1.0.36" + "source": "https://github.com/horstoeko/zugferd/tree/v1.0.37" }, - "time": "2024-03-11T04:34:59+00:00" + "time": "2024-03-24T11:31:03+00:00" }, { "name": "http-interop/http-factory-guzzle", @@ -11638,24 +11806,27 @@ }, { "name": "smalot/pdfparser", - "version": "v2.9.0", + "version": "v0.19.0", "source": { "type": "git", "url": "https://github.com/smalot/pdfparser.git", - "reference": "6b53144fcb24af77093d4150dd7d0dd571f25761" + "reference": "1895c17417aefa4508e35836c46da61988d61f26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smalot/pdfparser/zipball/6b53144fcb24af77093d4150dd7d0dd571f25761", - "reference": "6b53144fcb24af77093d4150dd7d0dd571f25761", + "url": "https://api.github.com/repos/smalot/pdfparser/zipball/1895c17417aefa4508e35836c46da61988d61f26", + "reference": "1895c17417aefa4508e35836c46da61988d61f26", "shasum": "" }, "require": { - "ext-iconv": "*", "ext-zlib": "*", - "php": ">=7.1", + "php": ">=5.6", "symfony/polyfill-mbstring": "^1.18" }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "symfony/phpunit-bridge": "^5.2" + }, "type": "library", "autoload": { "psr-0": { @@ -11683,9 +11854,9 @@ ], "support": { "issues": "https://github.com/smalot/pdfparser/issues", - "source": "https://github.com/smalot/pdfparser/tree/v2.9.0" + "source": "https://github.com/smalot/pdfparser/tree/v0.19.0" }, - "time": "2024-03-01T09:51:10+00:00" + "time": "2021-04-13T08:27:56+00:00" }, { "name": "socialiteproviders/apple", diff --git a/config/open-telemetry.php b/config/open-telemetry.php deleted file mode 100644 index 355c0118e8..0000000000 --- a/config/open-telemetry.php +++ /dev/null @@ -1,98 +0,0 @@ - null, - - /* - * A driver is responsible for transmitting any measurements. - */ - 'drivers' => [ - Spatie\OpenTelemetry\Drivers\HttpDriver::class => [ - 'url' => 'http://localhost:9411/api/v2/spans', - // 'url' => 'http://localhost:4318/v1/traces' - ], - ], - - /* - * This class determines if your measurements should actually be sent - * to the reporting drivers. - */ - 'sampler' => Spatie\OpenTelemetry\Support\Samplers\AlwaysSampler::class, - - /* - * Tags can be added to any measurement. These classes will determine the - * values of the tags when a new trace starts. - */ - 'trace_tag_providers' => [ - \Spatie\OpenTelemetry\Support\TagProviders\DefaultTagsProvider::class, - ], - - /* - * Tags can be added to any measurement. These classes will determine the - * values of the tags when a new span starts. - */ - 'span_tag_providers' => [ - - ], - - 'queue' => [ - /* - * When enabled, any measurements (spans) you make in a queued job that implements - * `TraceAware` will automatically belong to the same trace that was - * started in the process that dispatched the job. - */ - 'make_queue_trace_aware' => true, - - /* - * When this is set to `false`, only jobs the implement - * `TraceAware` will be trace aware. - */ - 'all_jobs_are_trace_aware_by_default' => true, - - /* - * When set to `true` all jobs will - * automatically start a span. - */ - 'all_jobs_auto_start_a_span' => true, - - /* - * These jobs will be trace aware even if they don't - * implement the `TraceAware` interface. - */ - 'trace_aware_jobs' => [ - - ], - - /* - * These jobs will never trace aware, regardless of `all_jobs_are_trace_aware_by_default`. - */ - 'not_trace_aware_jobs' => [ - - ], - ], - - /* - * These actions can be overridden to have fine-grained control over how - * the package performs certain tasks. - * - * In most cases, you should use the default values. - */ - 'actions' => [ - 'make_queue_trace_aware' => Spatie\OpenTelemetry\Actions\MakeQueueTraceAwareAction::class, - ], - - /* - * This class determines how the package measures time. - */ - 'stopwatch' => Spatie\OpenTelemetry\Support\Stopwatch::class, - - /* - * This class generates IDs for traces and spans. - */ - 'id_generator' => Spatie\OpenTelemetry\Support\IdGenerator::class, -]; diff --git a/database/migrations/2024_03_19_346785_add_routing_id_to_vendor b/database/migrations/2024_03_19_346785_add_routing_id_to_vendor new file mode 100644 index 0000000000..bdf4223b83 --- /dev/null +++ b/database/migrations/2024_03_19_346785_add_routing_id_to_vendor @@ -0,0 +1,42 @@ +string('routing_id')->nullable(); + }); + + \App\Models\Company::query() + ->cursor() + ->each(function ($c){ + $settings = $c->settings; + $settings->e_quote_type = 'OrderX_Comfort'; + $settings->enable_rappen_rounding = false; + + $c->settings = $settings; + $c->save(); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +}; diff --git a/lang/en/texts.php b/lang/en/texts.php index b721758bb7..7ec111242c 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -461,8 +461,8 @@ $lang = array( 'delete_token' => 'Delete Token', 'token' => 'Token', 'add_gateway' => 'Add Payment Gateway', - 'delete_gateway' => 'Delete Gateway', - 'edit_gateway' => 'Edit Gateway', + 'delete_gateway' => 'Delete Payment Gateway', + 'edit_gateway' => 'Edit Payment Gateway', 'updated_gateway' => 'Successfully updated gateway', 'created_gateway' => 'Successfully created gateway', 'deleted_gateway' => 'Successfully deleted gateway', @@ -5104,6 +5104,8 @@ $lang = array( 'drop_files_here' => 'Drop files here', 'upload_files' => 'Upload Files', 'download_e_invoice' => 'Download E-Invoice', + 'download_e_credit' => 'Download E-Credit', + 'download_e_quote' => 'Download E-Quote', 'triangular_tax_info' => 'Intra-community triangular transaction', 'intracommunity_tax_info' => 'Tax-free intra-community delivery', 'reverse_tax_info' => 'Please note that this supply is subject to reverse charge', @@ -5262,8 +5264,13 @@ $lang = array( 'purchase_order_items' => 'Purchase Order Items', 'csv_rows_length' => 'No data found in this CSV file', 'accept_payments_online' => 'Accept Payments Online', - 'all_payment_gateways' => 'View all payment gateways', + 'all_payment_gateways' => 'View all payment gateways', 'product_cost' => 'Product cost', + 'enable_rappen_roudning' => 'Enable Rappen Rounding', + 'enable_rappen_rounding_help' => 'Rounds totals to nearest 5', + 'duration_words' => 'Duration in words', + 'upcoming_recurring_invoices' => 'Upcoming Recurring Invoices', + 'total_invoices' => 'Total Invoices', ); return $lang; diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php index b69b5fca52..2e408bf5a7 100644 --- a/lang/fr_CA/texts.php +++ b/lang/fr_CA/texts.php @@ -2194,6 +2194,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'encryption' => 'Cryptage', 'mailgun_domain' => 'Domaine Mailgun', 'mailgun_private_key' => 'Clé privée Mailgun', + 'brevo_domain' => 'Domaine Brevo', + 'brevo_private_key' => 'Clé privée Brevo', 'send_test_email' => 'Envoyer un courriel test', 'select_label' => 'Sélectionnez le libellé', 'label' => 'Libellé', @@ -4844,6 +4846,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'email_alignment' => 'Justification du courriel', 'pdf_preview_location' => 'Emplacement de prévisualisation du PDF', 'mailgun' => 'Mailgun', + 'brevo' => 'Brevo', 'postmark' => 'Postmark', 'microsoft' => 'Microsoft', 'click_plus_to_create_record' => 'Cliquez sur + pour créer un enregistrement', @@ -5096,6 +5099,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'drop_files_here' => 'Déposez les fichiers ici', 'upload_files' => 'Téléverser les fichiers', 'download_e_invoice' => 'Télécharger la facture électronique', + 'download_e_credit' => 'Télécharger E-Credit', + 'download_e_quote' => 'Télécharger E-Quote', 'triangular_tax_info' => 'Transactions intra-communautaire triangulaire', 'intracommunity_tax_info' => 'Livraison intra-communautaure sans taxe', 'reverse_tax_info' => 'Veuillez noter que cette provision est sujette à une charge renversée', @@ -5253,6 +5258,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'select_email_provider' => 'Définir le courriel pour l\'envoi', 'purchase_order_items' => 'Articles du bon d\'achat', 'csv_rows_length' => 'Aucune donnée dans ce fichier CSV', + 'accept_payments_online' => 'Accepter les paiements en ligne', + 'all_payment_gateways' => 'Voir toutes les passerelles de paiements', + 'product_cost' => 'Coût du produit', ); return $lang; diff --git a/package-lock.json b/package-lock.json index f1466debb8..1e4593041b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "@invoiceninja/invoiceninja", + "name": "invoiceninja", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/public/build/assets/app-17bd8d2c.css b/public/build/assets/app-91a05c24.css similarity index 68% rename from public/build/assets/app-17bd8d2c.css rename to public/build/assets/app-91a05c24.css index 5dddc63a2b..bece146ece 100644 --- a/public/build/assets/app-17bd8d2c.css +++ b/public/build/assets/app-91a05c24.css @@ -1 +1 @@ -/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com *//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */*,:before,:after{box-sizing:border-box}html{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}button{background-color:transparent;background-image:none}fieldset{margin:0;padding:0}ol,ul{list-style:none;margin:0;padding:0}html{font-family:Open Sans,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{font-family:inherit;line-height:inherit}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}pre,code,kbd,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}[type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=month],[type=search],[type=time],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=month]:focus,[type=search]:focus,[type=time]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;color-adjust:exact}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto -webkit-focus-ring-color}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.prose{color:#374151;max-width:65ch}.prose [class~=lead]{color:#4b5563;font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose a{color:#111827;text-decoration:underline;font-weight:500}.prose strong{color:#111827;font-weight:600}.prose ol[type=A]{--list-counter-style: upper-alpha}.prose ol[type=a]{--list-counter-style: lower-alpha}.prose ol[type=A s]{--list-counter-style: upper-alpha}.prose ol[type=a s]{--list-counter-style: lower-alpha}.prose ol[type=i]{--list-counter-style: lower-roman}.prose ol[type=i s]{--list-counter-style: lower-roman}.prose ol[type="1"]{--list-counter-style: decimal}.prose ol>li{position:relative;padding-left:1.75em}.prose ol>li:before{content:counter(list-item,var(--list-counter-style, decimal)) ".";position:absolute;font-weight:400;color:#6b7280;left:0}.prose ul>li{position:relative;padding-left:1.75em}.prose ul>li:before{content:"";position:absolute;background-color:#d1d5db;border-radius:50%;width:.375em;height:.375em;top:.6875em;left:.25em}.prose hr{border-color:#e5e7eb;border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose blockquote{font-weight:500;font-style:italic;color:#111827;border-left-width:.25rem;border-left-color:#e5e7eb;quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose blockquote p:first-of-type:before{content:open-quote}.prose blockquote p:last-of-type:after{content:close-quote}.prose h1{color:#111827;font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose h2{color:#111827;font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose h3{color:#111827;font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose h4{color:#111827;font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose figure figcaption{color:#6b7280;font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose code{color:#111827;font-weight:600;font-size:.875em}.prose code:before{content:"`"}.prose code:after{content:"`"}.prose a code{color:#111827}.prose pre{color:#e5e7eb;background-color:#1f2937;overflow-x:auto;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose pre code{background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:400;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose pre code:before{content:none}.prose pre code:after{content:none}.prose table{width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose thead{color:#111827;font-weight:600;border-bottom-width:1px;border-bottom-color:#d1d5db}.prose thead th{vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose tbody tr{border-bottom-width:1px;border-bottom-color:#e5e7eb}.prose tbody tr:last-child{border-bottom-width:0}.prose tbody td{vertical-align:top;padding:.5714286em}.prose{font-size:1rem;line-height:1.75}.prose p{margin-top:1.25em;margin-bottom:1.25em}.prose img{margin-top:2em;margin-bottom:2em}.prose video{margin-top:2em;margin-bottom:2em}.prose figure{margin-top:2em;margin-bottom:2em}.prose figure>*{margin-top:0;margin-bottom:0}.prose h2 code{font-size:.875em}.prose h3 code{font-size:.9em}.prose ol,.prose ul{margin-top:1.25em;margin-bottom:1.25em}.prose li{margin-top:.5em;margin-bottom:.5em}.prose>ul>li p{margin-top:.75em;margin-bottom:.75em}.prose>ul>li>*:first-child{margin-top:1.25em}.prose>ul>li>*:last-child{margin-bottom:1.25em}.prose>ol>li>*:first-child{margin-top:1.25em}.prose>ol>li>*:last-child{margin-bottom:1.25em}.prose ul ul,.prose ul ol,.prose ol ul,.prose ol ol{margin-top:.75em;margin-bottom:.75em}.prose hr+*{margin-top:0}.prose h2+*{margin-top:0}.prose h3+*{margin-top:0}.prose h4+*{margin-top:0}.prose thead th:first-child{padding-left:0}.prose thead th:last-child{padding-right:0}.prose tbody td:first-child{padding-left:0}.prose tbody td:last-child{padding-right:0}.prose>:first-child{margin-top:0}.prose>:last-child{margin-bottom:0}.button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}button:disabled{cursor:not-allowed;opacity:.5}.button-primary{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.button-primary:hover{font-weight:600}.button-block{display:block;width:100%}.button-danger{--tw-bg-opacity: 1;background-color:rgba(239,68,68,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgba(220,38,38,var(--tw-bg-opacity))}.button-secondary{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.button-secondary:hover{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.button-link{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.button-link:hover{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity));text-decoration:underline}.button-link:focus{text-decoration:underline;outline:2px solid transparent;outline-offset:2px}.validation{margin-top:.5rem;margin-bottom:.25rem;border-left-width:2px;--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));padding:.25rem .75rem}.validation-fail{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.validation-pass{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.input{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.input:focus{--tw-bg-opacity: 1;background-color:rgba(249,250,251,var(--tw-bg-opacity));outline:2px solid transparent;outline-offset:2px}.input-label{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.input-slim{padding-top:.5rem;padding-bottom:.5rem}.form-checkbox{cursor:pointer;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.form-select{border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.alert{margin-top:.5rem;margin-top:1rem;margin-bottom:.25rem;border-left-width:2px;--tw-border-opacity: 1;border-color:rgba(156,163,175,var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem}.alert-success{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity))}.alert-failure{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity))}.badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;font-weight:500;line-height:1rem}.badge-light{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.badge-primary{--tw-bg-opacity: 1;background-color:rgba(191,219,254,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}.badge-danger{--tw-bg-opacity: 1;background-color:rgba(254,226,226,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.badge-success{--tw-bg-opacity: 1;background-color:rgba(209,250,229,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(16,185,129,var(--tw-text-opacity))}.badge-secondary{--tw-bg-opacity: 1;background-color:rgba(31,41,55,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(229,231,235,var(--tw-text-opacity))}.badge-warning{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(217,119,6,var(--tw-text-opacity))}.badge-info{--tw-bg-opacity: 1;background-color:rgba(219,234,254,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}@media (min-width: 640px){.dataTables_length{margin-top:1.25rem!important;margin-bottom:1.25rem!important}}@media (min-width: 1024px){.dataTables_length{margin-top:1rem!important;margin-bottom:1rem!important}}.dataTables_length select{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.dataTables_length select:focus{--tw-bg-opacity: 1 !important;background-color:rgba(249,250,251,var(--tw-bg-opacity))!important;outline:2px solid transparent!important;outline-offset:2px!important}.dataTables_length select{margin-left:.5rem!important;margin-right:.5rem!important;--tw-bg-opacity: 1 !important;background-color:rgba(255,255,255,var(--tw-bg-opacity))!important;padding:.5rem!important}.dataTables_filter{margin-bottom:1rem}.dataTables_filter input{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.dataTables_filter input:focus{--tw-bg-opacity: 1 !important;background-color:rgba(249,250,251,var(--tw-bg-opacity))!important;outline:2px solid transparent!important;outline-offset:2px!important}@media (min-width: 1024px){.dataTables_filter{margin-top:-3rem!important}}.dataTables_paginate{padding-top:.5rem!important;padding-bottom:1.5rem!important}.dataTables_paginate .paginate_button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-right:.25rem!important;cursor:pointer!important;border-radius:.25rem!important;border-width:1px!important;--tw-border-opacity: 1 !important;border-color:rgba(209,213,219,var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgba(255,255,255,var(--tw-bg-opacity))!important;padding-top:.5rem!important;padding-bottom:.5rem!important;font-size:.875rem!important;line-height:1.25rem!important;font-weight:500!important;line-height:1rem!important;--tw-text-opacity: 1 !important;color:rgba(55,65,81,var(--tw-text-opacity))!important}.dataTables_paginate .current{--tw-bg-opacity: 1 !important;background-color:rgba(37,99,235,var(--tw-bg-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(255,255,255,var(--tw-text-opacity))!important}.dataTables_info{font-size:.875rem!important;line-height:1.25rem!important}.dataTables_empty{padding-top:1rem!important;padding-bottom:1rem!important}.pagination{display:flex!important;align-items:center!important}.pagination .page-link{margin-top:-1px!important;display:inline-flex!important;cursor:pointer!important;align-items:center!important;border-top-width:2px!important;border-color:transparent!important;padding-left:1rem!important;padding-right:1rem!important;padding-top:1rem!important;font-size:.875rem!important;font-weight:500!important;line-height:1.25rem!important;--tw-text-opacity: 1 !important;color:rgba(107,114,128,var(--tw-text-opacity))!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter!important;transition-duration:.15s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.pagination .page-link:hover{--tw-border-opacity: 1 !important;border-color:rgba(209,213,219,var(--tw-border-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(55,65,81,var(--tw-text-opacity))!important}.pagination .page-link:focus{--tw-border-opacity: 1;border-color:rgba(156,163,175,var(--tw-border-opacity));--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px}.pagination .active>span{--tw-border-opacity: 1 !important;border-color:rgba(37,99,235,var(--tw-border-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(37,99,235,var(--tw-text-opacity))!important}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.top-0{top:0}.top-1{top:.25rem}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.left-1{left:.25rem}.z-0{z-index:0}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.focus-within\:z-10:focus-within{z-index:10}.col-auto{grid-column:auto}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-4{grid-column:span 4 / span 4}.col-span-6{grid-column:span 6 / span 6}.col-span-8{grid-column:span 8 / span 8}.col-span-12{grid-column:span 12 / span 12}.float-right{float:right}.m-0{margin:0}.m-auto{margin:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.-my-6{margin-top:-1.5rem;margin-bottom:-1.5rem}.mt-0{margin-top:0}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mt-20{margin-top:5rem}.-mt-4{margin-top:-1rem}.-mt-6{margin-top:-1.5rem}.mr-0{margin-right:0}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mr-5{margin-right:1.25rem}.-mr-1{margin-right:-.25rem}.-mr-14{margin-right:-3.5rem}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-1\.5{margin-bottom:.375rem}.ml-0{margin-left:0}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-5{margin-left:1.25rem}.-ml-1{margin-left:-.25rem}.-ml-4{margin-left:-1rem}.-ml-px{margin-left:-1px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0{height:0px}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-24{height:6rem}.h-64{height:16rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-0{width:0px}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-24{width:6rem}.w-48{width:12rem}.w-56{width:14rem}.w-64{width:16rem}.w-80{width:20rem}.w-auto{width:auto}.w-1\/2{width:50%}.w-3\/4{width:75%}.w-4\/5{width:80%}.w-1\/6{width:16.666667%}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-full{width:100%}.w-screen{width:100vw}.min-w-full{min-width:100%}.max-w-xs{max-width:20rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.border-collapse{border-collapse:collapse}.origin-top-right{transform-origin:top right}.transform{--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px}.-translate-x-full{--tw-translate-x: -100%}.translate-y-0{--tw-translate-y: 0px}.translate-y-4{--tw-translate-y: 1rem}.scale-95{--tw-scale-x: .95;--tw-scale-y: .95}.scale-100{--tw-scale-x: 1;--tw-scale-y: 1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.place-content-end{place-content:end}.place-items-center{place-items:center}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgba(229,231,235,var(--tw-divide-opacity))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.overflow-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.border-0{border-width:0px}.border-2{border-width:2px}.border-4{border-width:4px}.border{border-width:1px}.border-t-2{border-top-width:2px}.border-t-4{border-top-width:4px}.border-t{border-top-width:1px}.border-r{border-right-width:1px}.border-b-2{border-bottom-width:2px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-transparent{border-color:transparent}.border-gray-100{--tw-border-opacity: 1;border-color:rgba(243,244,246,var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.border-gray-500{--tw-border-opacity: 1;border-color:rgba(107,114,128,var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity: 1;border-color:rgba(75,85,99,var(--tw-border-opacity))}.border-red-300{--tw-border-opacity: 1;border-color:rgba(252,165,165,var(--tw-border-opacity))}.border-red-400{--tw-border-opacity: 1;border-color:rgba(248,113,113,var(--tw-border-opacity))}.border-red-900{--tw-border-opacity: 1;border-color:rgba(127,29,29,var(--tw-border-opacity))}.border-green-500{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity))}.border-blue-500{--tw-border-opacity: 1;border-color:rgba(59,130,246,var(--tw-border-opacity))}.group:hover .group-hover\:border-transparent,.hover\:border-transparent:hover{border-color:transparent}.hover\:border-gray-600:hover{--tw-border-opacity: 1;border-color:rgba(75,85,99,var(--tw-border-opacity))}.hover\:border-gray-800:hover{--tw-border-opacity: 1;border-color:rgba(31,41,55,var(--tw-border-opacity))}.hover\:border-blue-600:hover{--tw-border-opacity: 1;border-color:rgba(37,99,235,var(--tw-border-opacity))}.focus\:border-red-500:focus{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity))}.focus\:border-blue-300:focus{--tw-border-opacity: 1;border-color:rgba(147,197,253,var(--tw-border-opacity))}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgba(59,130,246,var(--tw-border-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgba(99,102,241,var(--tw-border-opacity))}.border-opacity-50{--tw-border-opacity: .5}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgba(249,250,251,var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgba(107,114,128,var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgba(75,85,99,var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgba(254,226,226,var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgba(239,68,68,var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgba(5,150,105,var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgba(239,246,255,var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgba(37,99,235,var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgba(29,78,216,var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.hover\:bg-red-900:hover{--tw-bg-opacity: 1;background-color:rgba(127,29,29,var(--tw-bg-opacity))}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgba(37,99,235,var(--tw-bg-opacity))}.focus\:bg-white:focus{--tw-bg-opacity: 1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.focus\:bg-gray-100:focus{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.focus\:bg-gray-600:focus{--tw-bg-opacity: 1;background-color:rgba(75,85,99,var(--tw-bg-opacity))}.bg-opacity-100{--tw-bg-opacity: 1}.bg-clip-padding{background-clip:padding-box}.fill-current{fill:currentColor}.object-cover{-o-object-fit:cover;object-fit:cover}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-center{-o-object-position:center;object-position:center}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.p-10{padding:2.5rem}.p-2\.5{padding:.625rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-12{padding-left:3rem;padding-right:3rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.pt-0{padding-top:0}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pr-10{padding-right:2.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pb-10{padding-bottom:2.5rem}.pb-20{padding-bottom:5rem}.pl-0{padding-left:0}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-5xl{font-size:3rem;line-height:1}.font-light{font-weight:300}.font-normal{font-weight:400}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-black{--tw-text-opacity: 1;color:rgba(0,0,0,var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgba(209,213,219,var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgba(156,163,175,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgba(248,113,113,var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.text-red-600{--tw-text-opacity: 1;color:rgba(220,38,38,var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgba(185,28,28,var(--tw-text-opacity))}.text-red-900{--tw-text-opacity: 1;color:rgba(127,29,29,var(--tw-text-opacity))}.text-green-600{--tw-text-opacity: 1;color:rgba(5,150,105,var(--tw-text-opacity))}.text-blue-500{--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity: 1;color:rgba(37,99,235,var(--tw-text-opacity))}.text-blue-700{--tw-text-opacity: 1;color:rgba(29,78,216,var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity: 1;color:rgba(79,70,229,var(--tw-text-opacity))}.group:hover .group-hover\:text-white,.hover\:text-white:hover{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.hover\:text-gray-300:hover{--tw-text-opacity: 1;color:rgba(209,213,219,var(--tw-text-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgba(37,99,235,var(--tw-text-opacity))}.hover\:text-indigo-900:hover{--tw-text-opacity: 1;color:rgba(49,46,129,var(--tw-text-opacity))}.focus\:text-gray-500:focus{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.focus\:text-gray-600:focus{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.focus\:text-gray-900:focus{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.underline{text-decoration:underline}.line-through{text-decoration:line-through}.no-underline{text-decoration:none}.hover\:underline:hover{text-decoration:underline}.focus\:underline:focus{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.opacity-100{opacity:1}.hover\:opacity-80:hover{opacity:.8}*,:before,:after{--tw-shadow: 0 0 #0000}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 10px 10px -5px rgba(0, 0, 0, .04);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-2xl:hover{--tw-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}*,:before,:after{--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgba(59, 130, 246, .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-black{--tw-ring-opacity: 1;--tw-ring-color: rgba(0, 0, 0, var(--tw-ring-opacity))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(239, 68, 68, var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(59, 130, 246, var(--tw-ring-opacity))}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(99, 102, 241, var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(79, 70, 229, var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity: .05}.focus\:ring-opacity-50:focus{--tw-ring-opacity: .5}.filter{--tw-blur: var(--tw-empty, );--tw-brightness: var(--tw-empty, );--tw-contrast: var(--tw-empty, );--tw-grayscale: var(--tw-empty, );--tw-hue-rotate: var(--tw-empty, );--tw-invert: var(--tw-empty, );--tw-saturate: var(--tw-empty, );--tw-sepia: var(--tw-empty, );--tw-drop-shadow: var(--tw-empty, );filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-linear{transition-timing-function:linear}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@media (min-width: 640px){.sm\:inset-0{top:0;right:0;bottom:0;left:0}.sm\:col-span-2{grid-column:span 2 / span 2}.sm\:col-span-3{grid-column:span 3 / span 3}.sm\:col-span-4{grid-column:span 4 / span 4}.sm\:col-span-6{grid-column:span 6 / span 6}.sm\:mx-0{margin-left:0;margin-right:0}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:mt-0{margin-top:0}.sm\:mt-4{margin-top:1rem}.sm\:mt-6{margin-top:1.5rem}.sm\:ml-3{margin-left:.75rem}.sm\:ml-4{margin-left:1rem}.sm\:ml-6{margin-left:1.5rem}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:h-10{height:2.5rem}.sm\:h-screen{height:100vh}.sm\:w-10{width:2.5rem}.sm\:w-auto{width:auto}.sm\:w-full{width:100%}.sm\:max-w-sm{max-width:24rem}.sm\:max-w-lg{max-width:32rem}.sm\:flex-shrink-0{flex-shrink:0}.sm\:translate-y-0{--tw-translate-y: 0px}.sm\:scale-95{--tw-scale-x: .95;--tw-scale-y: .95}.sm\:scale-100{--tw-scale-x: 1;--tw-scale-y: 1}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-0{padding:0}.sm\:p-6{padding:1.5rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-left{text-align:left}.sm\:align-middle{vertical-align:middle}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width: 768px){.md\:col-span-1{grid-column:span 1 / span 1}.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-span-4{grid-column:span 4 / span 4}.md\:col-span-5{grid-column:span 5 / span 5}.md\:col-span-6{grid-column:span 6 / span 6}.md\:col-start-2{grid-column-start:2}.md\:col-start-4{grid-column-start:4}.md\:mx-0{margin-left:0;margin-right:0}.md\:mt-0{margin-top:0}.md\:mt-5{margin-top:1.25rem}.md\:mt-10{margin-top:2.5rem}.md\:mr-2{margin-right:.5rem}.md\:-mr-1{margin-right:-.25rem}.md\:ml-2{margin-left:.5rem}.md\:ml-6{margin-left:1.5rem}.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:max-w-3xl{max-width:48rem}.md\:flex-shrink-0{flex-shrink:0}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}.md\:gap-6{gap:1.5rem}.md\:p-24{padding:6rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:text-left{text-align:left}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-2xl{font-size:1.5rem;line-height:2rem}}@media (min-width: 1024px){.lg\:col-span-3{grid-column:span 3 / span 3}.lg\:col-span-6{grid-column:span 6 / span 6}.lg\:col-span-7{grid-column:span 7 / span 7}.lg\:col-span-8{grid-column:span 8 / span 8}.lg\:col-start-3{grid-column-start:3}.lg\:col-start-4{grid-column-start:4}.lg\:-mx-8{margin-left:-2rem;margin-right:-2rem}.lg\:mt-24{margin-top:6rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:grid{display:grid}.lg\:hidden{display:none}.lg\:h-screen{height:100vh}.lg\:w-1\/2{width:50%}.lg\:w-1\/4{width:25%}.lg\:w-1\/5{width:20%}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:items-center{align-items:center}.lg\:gap-4{gap:1rem}.lg\:rounded-lg{border-radius:.5rem}.lg\:px-2{padding-left:.5rem;padding-right:.5rem}.lg\:px-4{padding-left:1rem;padding-right:1rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:px-16{padding-left:4rem;padding-right:4rem}.lg\:py-2{padding-top:.5rem;padding-bottom:.5rem}}@media (min-width: 1280px){.xl\:col-span-4{grid-column:span 4 / span 4}.xl\:col-span-6{grid-column:span 6 / span 6}.xl\:col-span-8{grid-column:span 8 / span 8}.xl\:col-span-9{grid-column:span 9 / span 9}.xl\:col-start-4{grid-column-start:4}.xl\:mt-32{margin-top:8rem}.xl\:flex{display:flex}.xl\:justify-center{justify-content:center}.xl\:px-16{padding-left:4rem;padding-right:4rem}} +/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com *//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */*,:before,:after{box-sizing:border-box}html{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}button{background-color:transparent;background-image:none}fieldset{margin:0;padding:0}ol,ul{list-style:none;margin:0;padding:0}html{font-family:Open Sans,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{font-family:inherit;line-height:inherit}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}pre,code,kbd,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}[type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=month],[type=search],[type=time],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=month]:focus,[type=search]:focus,[type=time]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;color-adjust:exact}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto -webkit-focus-ring-color}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.prose{color:#374151;max-width:65ch}.prose [class~=lead]{color:#4b5563;font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose a{color:#111827;text-decoration:underline;font-weight:500}.prose strong{color:#111827;font-weight:600}.prose ol[type=A]{--list-counter-style: upper-alpha}.prose ol[type=a]{--list-counter-style: lower-alpha}.prose ol[type=A s]{--list-counter-style: upper-alpha}.prose ol[type=a s]{--list-counter-style: lower-alpha}.prose ol[type=i]{--list-counter-style: lower-roman}.prose ol[type=i s]{--list-counter-style: lower-roman}.prose ol[type="1"]{--list-counter-style: decimal}.prose ol>li{position:relative;padding-left:1.75em}.prose ol>li:before{content:counter(list-item,var(--list-counter-style, decimal)) ".";position:absolute;font-weight:400;color:#6b7280;left:0}.prose ul>li{position:relative;padding-left:1.75em}.prose ul>li:before{content:"";position:absolute;background-color:#d1d5db;border-radius:50%;width:.375em;height:.375em;top:.6875em;left:.25em}.prose hr{border-color:#e5e7eb;border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose blockquote{font-weight:500;font-style:italic;color:#111827;border-left-width:.25rem;border-left-color:#e5e7eb;quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose blockquote p:first-of-type:before{content:open-quote}.prose blockquote p:last-of-type:after{content:close-quote}.prose h1{color:#111827;font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose h2{color:#111827;font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose h3{color:#111827;font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose h4{color:#111827;font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose figure figcaption{color:#6b7280;font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose code{color:#111827;font-weight:600;font-size:.875em}.prose code:before{content:"`"}.prose code:after{content:"`"}.prose a code{color:#111827}.prose pre{color:#e5e7eb;background-color:#1f2937;overflow-x:auto;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose pre code{background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:400;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose pre code:before{content:none}.prose pre code:after{content:none}.prose table{width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose thead{color:#111827;font-weight:600;border-bottom-width:1px;border-bottom-color:#d1d5db}.prose thead th{vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose tbody tr{border-bottom-width:1px;border-bottom-color:#e5e7eb}.prose tbody tr:last-child{border-bottom-width:0}.prose tbody td{vertical-align:top;padding:.5714286em}.prose{font-size:1rem;line-height:1.75}.prose p{margin-top:1.25em;margin-bottom:1.25em}.prose img{margin-top:2em;margin-bottom:2em}.prose video{margin-top:2em;margin-bottom:2em}.prose figure{margin-top:2em;margin-bottom:2em}.prose figure>*{margin-top:0;margin-bottom:0}.prose h2 code{font-size:.875em}.prose h3 code{font-size:.9em}.prose ol,.prose ul{margin-top:1.25em;margin-bottom:1.25em}.prose li{margin-top:.5em;margin-bottom:.5em}.prose>ul>li p{margin-top:.75em;margin-bottom:.75em}.prose>ul>li>*:first-child{margin-top:1.25em}.prose>ul>li>*:last-child{margin-bottom:1.25em}.prose>ol>li>*:first-child{margin-top:1.25em}.prose>ol>li>*:last-child{margin-bottom:1.25em}.prose ul ul,.prose ul ol,.prose ol ul,.prose ol ol{margin-top:.75em;margin-bottom:.75em}.prose hr+*{margin-top:0}.prose h2+*{margin-top:0}.prose h3+*{margin-top:0}.prose h4+*{margin-top:0}.prose thead th:first-child{padding-left:0}.prose thead th:last-child{padding-right:0}.prose tbody td:first-child{padding-left:0}.prose tbody td:last-child{padding-right:0}.prose>:first-child{margin-top:0}.prose>:last-child{margin-bottom:0}.button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}button:disabled{cursor:not-allowed;opacity:.5}.button-primary{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.button-primary:hover{font-weight:600}.button-block{display:block;width:100%}.button-danger{--tw-bg-opacity: 1;background-color:rgba(239,68,68,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.button-danger:hover{--tw-bg-opacity: 1;background-color:rgba(220,38,38,var(--tw-bg-opacity))}.button-secondary{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.button-secondary:hover{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.button-link{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.button-link:hover{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity));text-decoration:underline}.button-link:focus{text-decoration:underline;outline:2px solid transparent;outline-offset:2px}.validation{margin-top:.5rem;margin-bottom:.25rem;border-left-width:2px;--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));padding:.25rem .75rem}.validation-fail{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.validation-pass{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.input{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.input:focus{--tw-bg-opacity: 1;background-color:rgba(249,250,251,var(--tw-bg-opacity));outline:2px solid transparent;outline-offset:2px}.input-label{font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.input-slim{padding-top:.5rem;padding-bottom:.5rem}.form-checkbox{cursor:pointer;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.form-select{border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.alert{margin-top:.5rem;margin-top:1rem;margin-bottom:.25rem;border-left-width:2px;--tw-border-opacity: 1;border-color:rgba(156,163,175,var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem}.alert-success{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity))}.alert-failure{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity))}.badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .625rem;font-size:.75rem;font-weight:500;line-height:1rem}.badge-light{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.badge-primary{--tw-bg-opacity: 1;background-color:rgba(191,219,254,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}.badge-danger{--tw-bg-opacity: 1;background-color:rgba(254,226,226,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.badge-success{--tw-bg-opacity: 1;background-color:rgba(209,250,229,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(16,185,129,var(--tw-text-opacity))}.badge-secondary{--tw-bg-opacity: 1;background-color:rgba(31,41,55,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(229,231,235,var(--tw-text-opacity))}.badge-warning{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(217,119,6,var(--tw-text-opacity))}.badge-info{--tw-bg-opacity: 1;background-color:rgba(219,234,254,var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}@media (min-width: 640px){.dataTables_length{margin-top:1.25rem!important;margin-bottom:1.25rem!important}}@media (min-width: 1024px){.dataTables_length{margin-top:1rem!important;margin-bottom:1rem!important}}.dataTables_length select{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.dataTables_length select:focus{--tw-bg-opacity: 1 !important;background-color:rgba(249,250,251,var(--tw-bg-opacity))!important;outline:2px solid transparent!important;outline-offset:2px!important}.dataTables_length select{margin-left:.5rem!important;margin-right:.5rem!important;--tw-bg-opacity: 1 !important;background-color:rgba(255,255,255,var(--tw-bg-opacity))!important;padding:.5rem!important}.dataTables_filter{margin-bottom:1rem}.dataTables_filter input{margin-top:.5rem;align-items:center;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity));padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem}.dataTables_filter input:focus{--tw-bg-opacity: 1 !important;background-color:rgba(249,250,251,var(--tw-bg-opacity))!important;outline:2px solid transparent!important;outline-offset:2px!important}@media (min-width: 1024px){.dataTables_filter{margin-top:-3rem!important}}.dataTables_paginate{padding-top:.5rem!important;padding-bottom:1.5rem!important}.dataTables_paginate .paginate_button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-right:.25rem!important;cursor:pointer!important;border-radius:.25rem!important;border-width:1px!important;--tw-border-opacity: 1 !important;border-color:rgba(209,213,219,var(--tw-border-opacity))!important;--tw-bg-opacity: 1 !important;background-color:rgba(255,255,255,var(--tw-bg-opacity))!important;padding-top:.5rem!important;padding-bottom:.5rem!important;font-size:.875rem!important;line-height:1.25rem!important;font-weight:500!important;line-height:1rem!important;--tw-text-opacity: 1 !important;color:rgba(55,65,81,var(--tw-text-opacity))!important}.dataTables_paginate .current{--tw-bg-opacity: 1 !important;background-color:rgba(37,99,235,var(--tw-bg-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(255,255,255,var(--tw-text-opacity))!important}.dataTables_info{font-size:.875rem!important;line-height:1.25rem!important}.dataTables_empty{padding-top:1rem!important;padding-bottom:1rem!important}.pagination{display:flex!important;align-items:center!important}.pagination .page-link{margin-top:-1px!important;display:inline-flex!important;cursor:pointer!important;align-items:center!important;border-top-width:2px!important;border-color:transparent!important;padding-left:1rem!important;padding-right:1rem!important;padding-top:1rem!important;font-size:.875rem!important;font-weight:500!important;line-height:1.25rem!important;--tw-text-opacity: 1 !important;color:rgba(107,114,128,var(--tw-text-opacity))!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter!important;transition-duration:.15s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.pagination .page-link:hover{--tw-border-opacity: 1 !important;border-color:rgba(209,213,219,var(--tw-border-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(55,65,81,var(--tw-text-opacity))!important}.pagination .page-link:focus{--tw-border-opacity: 1;border-color:rgba(156,163,175,var(--tw-border-opacity));--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity));outline:2px solid transparent;outline-offset:2px}.pagination .active>span{--tw-border-opacity: 1 !important;border-color:rgba(37,99,235,var(--tw-border-opacity))!important;--tw-text-opacity: 1 !important;color:rgba(37,99,235,var(--tw-text-opacity))!important}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.top-0{top:0}.top-1{top:.25rem}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.left-1{left:.25rem}.z-0{z-index:0}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.focus-within\:z-10:focus-within{z-index:10}.col-auto{grid-column:auto}.col-span-1{grid-column:span 1 / span 1}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-4{grid-column:span 4 / span 4}.col-span-6{grid-column:span 6 / span 6}.col-span-8{grid-column:span 8 / span 8}.col-span-12{grid-column:span 12 / span 12}.float-right{float:right}.m-0{margin:0}.m-auto{margin:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.-my-6{margin-top:-1.5rem;margin-bottom:-1.5rem}.mt-0{margin-top:0}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mt-20{margin-top:5rem}.-mt-4{margin-top:-1rem}.-mt-6{margin-top:-1.5rem}.mr-0{margin-right:0}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mr-5{margin-right:1.25rem}.-mr-1{margin-right:-.25rem}.-mr-14{margin-right:-3.5rem}.mb-0{margin-bottom:0}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-1\.5{margin-bottom:.375rem}.ml-0{margin-left:0}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-5{margin-left:1.25rem}.-ml-1{margin-left:-.25rem}.-ml-4{margin-left:-1rem}.-ml-px{margin-left:-1px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0{height:0px}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-24{height:6rem}.h-64{height:16rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-0{width:0px}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-24{width:6rem}.w-48{width:12rem}.w-56{width:14rem}.w-64{width:16rem}.w-80{width:20rem}.w-auto{width:auto}.w-1\/2{width:50%}.w-3\/4{width:75%}.w-4\/5{width:80%}.w-1\/6{width:16.666667%}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-full{width:100%}.w-screen{width:100vw}.min-w-full{min-width:100%}.max-w-xs{max-width:20rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.border-collapse{border-collapse:collapse}.origin-top-right{transform-origin:top right}.transform{--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px}.-translate-x-full{--tw-translate-x: -100%}.translate-y-0{--tw-translate-y: 0px}.translate-y-4{--tw-translate-y: 1rem}.scale-95{--tw-scale-x: .95;--tw-scale-y: .95}.scale-100{--tw-scale-x: 1;--tw-scale-y: 1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.place-content-end{place-content:end}.place-items-center{place-items:center}.content-center{align-content:center}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.25rem * var(--tw-space-x-reverse));margin-left:calc(.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgba(229,231,235,var(--tw-divide-opacity))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.overflow-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.border-0{border-width:0px}.border-2{border-width:2px}.border-4{border-width:4px}.border{border-width:1px}.border-t-2{border-top-width:2px}.border-t-4{border-top-width:4px}.border-t{border-top-width:1px}.border-r{border-right-width:1px}.border-b-2{border-bottom-width:2px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-transparent{border-color:transparent}.border-gray-100{--tw-border-opacity: 1;border-color:rgba(243,244,246,var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity: 1;border-color:rgba(209,213,219,var(--tw-border-opacity))}.border-gray-500{--tw-border-opacity: 1;border-color:rgba(107,114,128,var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity: 1;border-color:rgba(75,85,99,var(--tw-border-opacity))}.border-red-300{--tw-border-opacity: 1;border-color:rgba(252,165,165,var(--tw-border-opacity))}.border-red-400{--tw-border-opacity: 1;border-color:rgba(248,113,113,var(--tw-border-opacity))}.border-red-900{--tw-border-opacity: 1;border-color:rgba(127,29,29,var(--tw-border-opacity))}.border-green-500{--tw-border-opacity: 1;border-color:rgba(16,185,129,var(--tw-border-opacity))}.border-blue-500{--tw-border-opacity: 1;border-color:rgba(59,130,246,var(--tw-border-opacity))}.group:hover .group-hover\:border-transparent,.hover\:border-transparent:hover{border-color:transparent}.hover\:border-gray-600:hover{--tw-border-opacity: 1;border-color:rgba(75,85,99,var(--tw-border-opacity))}.hover\:border-gray-800:hover{--tw-border-opacity: 1;border-color:rgba(31,41,55,var(--tw-border-opacity))}.hover\:border-blue-600:hover{--tw-border-opacity: 1;border-color:rgba(37,99,235,var(--tw-border-opacity))}.focus\:border-red-500:focus{--tw-border-opacity: 1;border-color:rgba(239,68,68,var(--tw-border-opacity))}.focus\:border-blue-300:focus{--tw-border-opacity: 1;border-color:rgba(147,197,253,var(--tw-border-opacity))}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgba(59,130,246,var(--tw-border-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgba(99,102,241,var(--tw-border-opacity))}.border-opacity-50{--tw-border-opacity: .5}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgba(249,250,251,var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgba(107,114,128,var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgba(75,85,99,var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgba(254,226,226,var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgba(239,68,68,var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgba(5,150,105,var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgba(239,246,255,var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgba(37,99,235,var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgba(29,78,216,var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.hover\:bg-red-900:hover{--tw-bg-opacity: 1;background-color:rgba(127,29,29,var(--tw-bg-opacity))}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgba(59,130,246,var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgba(37,99,235,var(--tw-bg-opacity))}.focus\:bg-white:focus{--tw-bg-opacity: 1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.focus\:bg-gray-100:focus{--tw-bg-opacity: 1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.focus\:bg-gray-600:focus{--tw-bg-opacity: 1;background-color:rgba(75,85,99,var(--tw-bg-opacity))}.bg-opacity-100{--tw-bg-opacity: 1}.bg-clip-padding{background-clip:padding-box}.fill-current{fill:currentColor}.object-cover{-o-object-fit:cover;object-fit:cover}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-center{-o-object-position:center;object-position:center}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-8{padding:2rem}.p-10{padding:2.5rem}.p-2\.5{padding:.625rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-12{padding-left:3rem;padding-right:3rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.pt-0{padding-top:0}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pr-10{padding-right:2.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pb-10{padding-bottom:2.5rem}.pb-20{padding-bottom:5rem}.pl-0{padding-left:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-1\.5{padding-left:.375rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-5xl{font-size:3rem;line-height:1}.font-light{font-weight:300}.font-normal{font-weight:400}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-tight{line-height:1.25}.leading-normal{line-height:1.5}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-black{--tw-text-opacity: 1;color:rgba(0,0,0,var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgba(209,213,219,var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgba(156,163,175,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.text-red-400{--tw-text-opacity: 1;color:rgba(248,113,113,var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.text-red-600{--tw-text-opacity: 1;color:rgba(220,38,38,var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgba(185,28,28,var(--tw-text-opacity))}.text-red-900{--tw-text-opacity: 1;color:rgba(127,29,29,var(--tw-text-opacity))}.text-green-600{--tw-text-opacity: 1;color:rgba(5,150,105,var(--tw-text-opacity))}.text-blue-500{--tw-text-opacity: 1;color:rgba(59,130,246,var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity: 1;color:rgba(37,99,235,var(--tw-text-opacity))}.text-blue-700{--tw-text-opacity: 1;color:rgba(29,78,216,var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity: 1;color:rgba(79,70,229,var(--tw-text-opacity))}.group:hover .group-hover\:text-white,.hover\:text-white:hover{--tw-text-opacity: 1;color:rgba(255,255,255,var(--tw-text-opacity))}.hover\:text-gray-300:hover{--tw-text-opacity: 1;color:rgba(209,213,219,var(--tw-text-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgba(55,65,81,var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgba(31,41,55,var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgba(239,68,68,var(--tw-text-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgba(37,99,235,var(--tw-text-opacity))}.hover\:text-indigo-900:hover{--tw-text-opacity: 1;color:rgba(49,46,129,var(--tw-text-opacity))}.focus\:text-gray-500:focus{--tw-text-opacity: 1;color:rgba(107,114,128,var(--tw-text-opacity))}.focus\:text-gray-600:focus{--tw-text-opacity: 1;color:rgba(75,85,99,var(--tw-text-opacity))}.focus\:text-gray-900:focus{--tw-text-opacity: 1;color:rgba(17,24,39,var(--tw-text-opacity))}.underline{text-decoration:underline}.line-through{text-decoration:line-through}.no-underline{text-decoration:none}.hover\:underline:hover{text-decoration:underline}.focus\:underline:focus{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.opacity-100{opacity:1}.hover\:opacity-80:hover{opacity:.8}*,:before,:after{--tw-shadow: 0 0 #0000}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 10px 10px -5px rgba(0, 0, 0, .04);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-2xl:hover{--tw-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}*,:before,:after{--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgba(59, 130, 246, .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-black{--tw-ring-opacity: 1;--tw-ring-color: rgba(0, 0, 0, var(--tw-ring-opacity))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(239, 68, 68, var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(59, 130, 246, var(--tw-ring-opacity))}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(99, 102, 241, var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(79, 70, 229, var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity: .05}.focus\:ring-opacity-50:focus{--tw-ring-opacity: .5}.filter{--tw-blur: var(--tw-empty, );--tw-brightness: var(--tw-empty, );--tw-contrast: var(--tw-empty, );--tw-grayscale: var(--tw-empty, );--tw-hue-rotate: var(--tw-empty, );--tw-invert: var(--tw-empty, );--tw-saturate: var(--tw-empty, );--tw-sepia: var(--tw-empty, );--tw-drop-shadow: var(--tw-empty, );filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-linear{transition-timing-function:linear}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@media (min-width: 640px){.sm\:inset-0{top:0;right:0;bottom:0;left:0}.sm\:col-span-2{grid-column:span 2 / span 2}.sm\:col-span-3{grid-column:span 3 / span 3}.sm\:col-span-4{grid-column:span 4 / span 4}.sm\:col-span-6{grid-column:span 6 / span 6}.sm\:mx-0{margin-left:0;margin-right:0}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:mt-0{margin-top:0}.sm\:mt-4{margin-top:1rem}.sm\:mt-6{margin-top:1.5rem}.sm\:ml-3{margin-left:.75rem}.sm\:ml-4{margin-left:1rem}.sm\:ml-6{margin-left:1.5rem}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:h-10{height:2.5rem}.sm\:h-screen{height:100vh}.sm\:w-10{width:2.5rem}.sm\:w-auto{width:auto}.sm\:w-full{width:100%}.sm\:max-w-sm{max-width:24rem}.sm\:max-w-lg{max-width:32rem}.sm\:flex-shrink-0{flex-shrink:0}.sm\:translate-y-0{--tw-translate-y: 0px}.sm\:scale-95{--tw-scale-x: .95;--tw-scale-y: .95}.sm\:scale-100{--tw-scale-x: 1;--tw-scale-y: 1}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-0{padding:0}.sm\:p-6{padding:1.5rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-left{text-align:left}.sm\:align-middle{vertical-align:middle}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width: 768px){.md\:col-span-1{grid-column:span 1 / span 1}.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-span-4{grid-column:span 4 / span 4}.md\:col-span-5{grid-column:span 5 / span 5}.md\:col-span-6{grid-column:span 6 / span 6}.md\:col-start-2{grid-column-start:2}.md\:col-start-4{grid-column-start:4}.md\:mx-0{margin-left:0;margin-right:0}.md\:mt-0{margin-top:0}.md\:mt-5{margin-top:1.25rem}.md\:mt-10{margin-top:2.5rem}.md\:mr-0{margin-right:0}.md\:mr-2{margin-right:.5rem}.md\:-mr-1{margin-right:-.25rem}.md\:mb-6{margin-bottom:1.5rem}.md\:ml-2{margin-left:.5rem}.md\:ml-6{margin-left:1.5rem}.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:max-w-3xl{max-width:48rem}.md\:flex-shrink-0{flex-shrink:0}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:justify-between{justify-content:space-between}.md\:gap-6{gap:1.5rem}.md\:gap-y-6{row-gap:1.5rem}.md\:border-r{border-right-width:1px}.md\:p-24{padding:6rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:pt-0{padding-top:0}.md\:pl-4{padding-left:1rem}.md\:text-left{text-align:left}.md\:text-center{text-align:center}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-2xl{font-size:1.5rem;line-height:2rem}}@media (min-width: 1024px){.lg\:col-span-3{grid-column:span 3 / span 3}.lg\:col-span-6{grid-column:span 6 / span 6}.lg\:col-span-7{grid-column:span 7 / span 7}.lg\:col-span-8{grid-column:span 8 / span 8}.lg\:col-start-3{grid-column-start:3}.lg\:col-start-4{grid-column-start:4}.lg\:-mx-8{margin-left:-2rem;margin-right:-2rem}.lg\:mt-24{margin-top:6rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:grid{display:grid}.lg\:hidden{display:none}.lg\:h-screen{height:100vh}.lg\:w-1\/2{width:50%}.lg\:w-1\/4{width:25%}.lg\:w-1\/5{width:20%}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:items-center{align-items:center}.lg\:gap-4{gap:1rem}.lg\:rounded-lg{border-radius:.5rem}.lg\:px-2{padding-left:.5rem;padding-right:.5rem}.lg\:px-4{padding-left:1rem;padding-right:1rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:px-16{padding-left:4rem;padding-right:4rem}.lg\:py-2{padding-top:.5rem;padding-bottom:.5rem}}@media (min-width: 1280px){.xl\:col-span-4{grid-column:span 4 / span 4}.xl\:col-span-6{grid-column:span 6 / span 6}.xl\:col-span-8{grid-column:span 8 / span 8}.xl\:col-span-9{grid-column:span 9 / span 9}.xl\:col-start-4{grid-column-start:4}.xl\:mt-0{margin-top:0}.xl\:mt-32{margin-top:8rem}.xl\:flex{display:flex}.xl\:w-auto{width:auto}.xl\:flex-row{flex-direction:row}.xl\:flex-nowrap{flex-wrap:nowrap}.xl\:justify-center{justify-content:center}.xl\:border-r{border-right-width:1px}.xl\:px-5{padding-left:1.25rem;padding-right:1.25rem}.xl\:px-16{padding-left:4rem;padding-right:4rem}.xl\:px-20{padding-left:5rem;padding-right:5rem}.xl\:pr-20{padding-right:5rem}} diff --git a/public/build/assets/app-b98bbdda.js b/public/build/assets/app-c80ec97e.js similarity index 97% rename from public/build/assets/app-b98bbdda.js rename to public/build/assets/app-c80ec97e.js index 95ac296eec..0a8f6cc399 100644 --- a/public/build/assets/app-b98bbdda.js +++ b/public/build/assets/app-c80ec97e.js @@ -1,9 +1,9 @@ import{A as pl}from"./index-08e160a7.js";import{c as Ht,g as hl}from"./_commonjsHelpers-725317a4.js";var gl={visa:{niceType:"Visa",type:"visa",patterns:[4],gaps:[4,8,12],lengths:[16,18,19],code:{name:"CVV",size:3}},mastercard:{niceType:"Mastercard",type:"mastercard",patterns:[[51,55],[2221,2229],[223,229],[23,26],[270,271],2720],gaps:[4,8,12],lengths:[16],code:{name:"CVC",size:3}},"american-express":{niceType:"American Express",type:"american-express",patterns:[34,37],gaps:[4,10],lengths:[15],code:{name:"CID",size:4}},"diners-club":{niceType:"Diners Club",type:"diners-club",patterns:[[300,305],36,38,39],gaps:[4,10],lengths:[14,16,19],code:{name:"CVV",size:3}},discover:{niceType:"Discover",type:"discover",patterns:[6011,[644,649],65],gaps:[4,8,12],lengths:[16,19],code:{name:"CID",size:3}},jcb:{niceType:"JCB",type:"jcb",patterns:[2131,1800,[3528,3589]],gaps:[4,8,12],lengths:[16,17,18,19],code:{name:"CVV",size:3}},unionpay:{niceType:"UnionPay",type:"unionpay",patterns:[620,[624,626],[62100,62182],[62184,62187],[62185,62197],[62200,62205],[622010,622999],622018,[622019,622999],[62207,62209],[622126,622925],[623,626],6270,6272,6276,[627700,627779],[627781,627799],[6282,6289],6291,6292,810,[8110,8131],[8132,8151],[8152,8163],[8164,8171]],gaps:[4,8,12],lengths:[14,15,16,17,18,19],code:{name:"CVN",size:3}},maestro:{niceType:"Maestro",type:"maestro",patterns:[493698,[5e5,504174],[504176,506698],[506779,508999],[56,59],63,67,6],gaps:[4,8,12],lengths:[12,13,14,15,16,17,18,19],code:{name:"CVC",size:3}},elo:{niceType:"Elo",type:"elo",patterns:[401178,401179,438935,457631,457632,431274,451416,457393,504175,[506699,506778],[509e3,509999],627780,636297,636368,[650031,650033],[650035,650051],[650405,650439],[650485,650538],[650541,650598],[650700,650718],[650720,650727],[650901,650978],[651652,651679],[655e3,655019],[655021,655058]],gaps:[4,8,12],lengths:[16],code:{name:"CVE",size:3}},mir:{niceType:"Mir",type:"mir",patterns:[[2200,2204]],gaps:[4,8,12],lengths:[16,17,18,19],code:{name:"CVP2",size:3}},hiper:{niceType:"Hiper",type:"hiper",patterns:[637095,63737423,63743358,637568,637599,637609,637612],gaps:[4,8,12],lengths:[16],code:{name:"CVC",size:3}},hipercard:{niceType:"Hipercard",type:"hipercard",patterns:[606282],gaps:[4,8,12],lengths:[16],code:{name:"CVC",size:3}}},ml=gl,ti={},bn={};Object.defineProperty(bn,"__esModule",{value:!0});bn.clone=void 0;function vl(e){return e?JSON.parse(JSON.stringify(e)):null}bn.clone=vl;var ri={};Object.defineProperty(ri,"__esModule",{value:!0});ri.matches=void 0;function yl(e,r,n){var a=String(r).length,s=e.substr(0,a),l=parseInt(s,10);return r=parseInt(String(r).substr(0,s.length),10),n=parseInt(String(n).substr(0,s.length),10),l>=r&&l<=n}function bl(e,r){return r=String(r),r.substring(0,e.length)===e.substring(0,r.length)}function _l(e,r){return Array.isArray(r)?yl(e,r[0],r[1]):bl(e,r)}ri.matches=_l;Object.defineProperty(ti,"__esModule",{value:!0});ti.addMatchingCardsToResults=void 0;var wl=bn,xl=ri;function Sl(e,r,n){var a,s;for(a=0;a=s&&(y.matchStrength=s),n.push(y);break}}}ti.addMatchingCardsToResults=Sl;var ni={};Object.defineProperty(ni,"__esModule",{value:!0});ni.isValidInputType=void 0;function El(e){return typeof e=="string"||e instanceof String}ni.isValidInputType=El;var ii={};Object.defineProperty(ii,"__esModule",{value:!0});ii.findBestMatch=void 0;function Ol(e){var r=e.filter(function(n){return n.matchStrength}).length;return r>0&&r===e.length}function Cl(e){return Ol(e)?e.reduce(function(r,n){return!r||Number(r.matchStrength)Ml?pn(!1,!1):Nl.test(e)?pn(!1,!0):pn(!0,!0)}ai.cardholderName=kl;var oi={};function Ll(e){for(var r=0,n=!1,a=e.length-1,s;a>=0;)s=parseInt(e.charAt(a),10),n&&(s*=2,s>9&&(s=s%10+1)),n=!n,r+=s,a--;return r%10===0}var jl=Ll;Object.defineProperty(oi,"__esModule",{value:!0});oi.cardNumber=void 0;var Il=jl,Ga=No;function gr(e,r,n){return{card:e,isPotentiallyValid:r,isValid:n}}function Dl(e,r){r===void 0&&(r={});var n,a,s;if(typeof e!="string"&&typeof e!="number")return gr(null,!1,!1);var l=String(e).replace(/-|\s/g,"");if(!/^\d*$/.test(l))return gr(null,!1,!1);var y=Ga(l);if(y.length===0)return gr(null,!1,!1);if(y.length!==1)return gr(null,!0,!1);var m=y[0];if(r.maxLength&&l.length>r.maxLength)return gr(m,!1,!1);m.type===Ga.types.UNIONPAY&&r.luhnValidateUnionPay!==!0?a=!0:a=Il(l),s=Math.max.apply(null,m.lengths),r.maxLength&&(s=Math.min(r.maxLength,s));for(var L=0;L4)return er(!1,!1);var m=parseInt(e,10),L=Number(String(s).substr(2,2)),q=!1;if(a===2){if(String(s).substr(0,2)===e)return er(!1,!0);n=L===m,q=m>=L&&m<=L+r}else a===4&&(n=s===m,q=m>=s&&m<=s+r);return er(q,q,n)}zr.expirationYear=Fl;var ui={};Object.defineProperty(ui,"__esModule",{value:!0});ui.isArray=void 0;ui.isArray=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"};Object.defineProperty(li,"__esModule",{value:!0});li.parseDate=void 0;var Bl=zr,Ul=ui;function Hl(e){var r=Number(e[0]),n;return r===0?2:r>1||r===1&&Number(e[1])>2?1:r===1?(n=e.substr(1),Bl.expirationYear(n).isPotentiallyValid?1:2):e.length===5?1:e.length>5?2:1}function ql(e){var r;if(/^\d{4}-\d{1,2}$/.test(e)?r=e.split("-").reverse():/\//.test(e)?r=e.split(/\s*\/\s*/g):/\s/.test(e)&&(r=e.split(/ +/g)),Ul.isArray(r))return{month:r[0]||"",year:r.slice(1).join()};var n=Hl(e),a=e.substr(0,n);return{month:a,year:e.substr(a.length)}}li.parseDate=ql;var wn={};Object.defineProperty(wn,"__esModule",{value:!0});wn.expirationMonth=void 0;function hn(e,r,n){return{isValid:e,isPotentiallyValid:r,isValidForThisYear:n||!1}}function Vl(e){var r=new Date().getMonth()+1;if(typeof e!="string")return hn(!1,!1);if(e.replace(/\s/g,"")===""||e==="0")return hn(!1,!0);if(!/^\d*$/.test(e))return hn(!1,!1);var n=parseInt(e,10);if(isNaN(Number(e)))return hn(!1,!1);var a=n>0&&n<13;return hn(a,a,a&&n>=r)}wn.expirationMonth=Vl;var Zi=Ht&&Ht.__assign||function(){return Zi=Object.assign||function(e){for(var r,n=1,a=arguments.length;nr?e[n]:r;return r}function Ir(e,r){return{isValid:e,isPotentiallyValid:r}}function Xl(e,r){return r===void 0&&(r=Mo),r=r instanceof Array?r:[r],typeof e!="string"||!/^\d*$/.test(e)?Ir(!1,!1):Gl(r,e.length)?Ir(!0,!0):e.lengthYl(r)?Ir(!1,!1):Ir(!0,!0)}ci.cvv=Xl;var fi={};Object.defineProperty(fi,"__esModule",{value:!0});fi.postalCode=void 0;var Ql=3;function Wi(e,r){return{isValid:e,isPotentiallyValid:r}}function Zl(e,r){r===void 0&&(r={});var n=r.minLength||Ql;return typeof e!="string"?Wi(!1,!1):e.lengthfunction(){return r||(0,e[Lo(e)[0]])((r={exports:{}}).exports,r),r.exports},yu=(e,r,n,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of Lo(r))!vu.call(e,s)&&s!==n&&ko(e,s,{get:()=>r[s],enumerable:!(a=gu(r,s))||a.enumerable});return e},rt=(e,r,n)=>(n=e!=null?hu(mu(e)):{},yu(r||!e||!e.__esModule?ko(n,"default",{value:e,enumerable:!0}):n,e)),wt=Yt({"../alpine/packages/alpinejs/dist/module.cjs.js"(e,r){var n=Object.create,a=Object.defineProperty,s=Object.getOwnPropertyDescriptor,l=Object.getOwnPropertyNames,y=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,L=(t,i)=>function(){return i||(0,t[l(t)[0]])((i={exports:{}}).exports,i),i.exports},q=(t,i)=>{for(var o in i)a(t,o,{get:i[o],enumerable:!0})},ce=(t,i,o,c)=>{if(i&&typeof i=="object"||typeof i=="function")for(let p of l(i))!m.call(t,p)&&p!==o&&a(t,p,{get:()=>i[p],enumerable:!(c=s(i,p))||c.enumerable});return t},se=(t,i,o)=>(o=t!=null?n(y(t)):{},ce(i||!t||!t.__esModule?a(o,"default",{value:t,enumerable:!0}):o,t)),K=t=>ce(a({},"__esModule",{value:!0}),t),Y=L({"node_modules/@vue/shared/dist/shared.cjs.js"(t){Object.defineProperty(t,"__esModule",{value:!0});function i(b,W){const ee=Object.create(null),le=b.split(",");for(let qe=0;qe!!ee[qe.toLowerCase()]:qe=>!!ee[qe]}var o={1:"TEXT",2:"CLASS",4:"STYLE",8:"PROPS",16:"FULL_PROPS",32:"HYDRATE_EVENTS",64:"STABLE_FRAGMENT",128:"KEYED_FRAGMENT",256:"UNKEYED_FRAGMENT",512:"NEED_PATCH",1024:"DYNAMIC_SLOTS",2048:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},c={1:"STABLE",2:"DYNAMIC",3:"FORWARDED"},p="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt",d=i(p),g=2;function x(b,W=0,ee=b.length){let le=b.split(/(\r?\n)/);const qe=le.filter((yt,ct)=>ct%2===1);le=le.filter((yt,ct)=>ct%2===0);let tt=0;const vt=[];for(let yt=0;yt=W){for(let ct=yt-g;ct<=yt+g||ee>tt;ct++){if(ct<0||ct>=le.length)continue;const fn=ct+1;vt.push(`${fn}${" ".repeat(Math.max(3-String(fn).length,0))}| ${le[ct]}`);const Lr=le[ct].length,Gn=qe[ct]&&qe[ct].length||0;if(ct===yt){const jr=W-(tt-(Lr+Gn)),Vi=Math.max(1,ee>tt?Lr-jr:ee-W);vt.push(" | "+" ".repeat(jr)+"^".repeat(Vi))}else if(ct>yt){if(ee>tt){const jr=Math.max(Math.min(ee-tt,Lr),1);vt.push(" | "+"^".repeat(jr))}tt+=Lr+Gn}}break}return vt.join(` -`)}var k="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",Z=i(k),Me=i(k+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected"),Qe=/[>/="'\u0009\u000a\u000c\u0020]/,$e={};function Ke(b){if($e.hasOwnProperty(b))return $e[b];const W=Qe.test(b);return W&&console.error(`unsafe attribute name: ${b}`),$e[b]=!W}var At={acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},Ft=i("animation-iteration-count,border-image-outset,border-image-slice,border-image-width,box-flex,box-flex-group,box-ordinal-group,column-count,columns,flex,flex-grow,flex-positive,flex-shrink,flex-negative,flex-order,grid-row,grid-row-end,grid-row-span,grid-row-start,grid-column,grid-column-end,grid-column-span,grid-column-start,font-weight,line-clamp,line-height,opacity,order,orphans,tab-size,widows,z-index,zoom,fill-opacity,flood-opacity,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-miterlimit,stroke-opacity,stroke-width"),Se=i("accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap");function Ue(b){if(Nt(b)){const W={};for(let ee=0;ee{if(ee){const le=ee.split(He);le.length>1&&(W[le[0].trim()]=le[1].trim())}}),W}function Rt(b){let W="";if(!b)return W;for(const ee in b){const le=b[ee],qe=ee.startsWith("--")?ee:Kn(ee);(fr(le)||typeof le=="number"&&Ft(qe))&&(W+=`${qe}:${le};`)}return W}function Bt(b){let W="";if(fr(b))W=b;else if(Nt(b))for(let ee=0;ee]/;function Li(b){const W=""+b,ee=ki.exec(W);if(!ee)return W;let le="",qe,tt,vt=0;for(tt=ee.index;tt||--!>|Or(ee,W))}var In=b=>b==null?"":Ut(b)?JSON.stringify(b,Di,2):String(b),Di=(b,W)=>cr(W)?{[`Map(${W.size})`]:[...W.entries()].reduce((ee,[le,qe])=>(ee[`${le} =>`]=qe,ee),{})}:Mt(W)?{[`Set(${W.size})`]:[...W.values()]}:Ut(W)&&!Nt(W)&&!Hn(W)?String(W):W,$i=["bigInt","optionalChaining","nullishCoalescingOperator"],an=Object.freeze({}),on=Object.freeze([]),sn=()=>{},Cr=()=>!1,Ar=/^on[^a-z]/,Tr=b=>Ar.test(b),Pr=b=>b.startsWith("onUpdate:"),Dn=Object.assign,$n=(b,W)=>{const ee=b.indexOf(W);ee>-1&&b.splice(ee,1)},Fn=Object.prototype.hasOwnProperty,Bn=(b,W)=>Fn.call(b,W),Nt=Array.isArray,cr=b=>dr(b)==="[object Map]",Mt=b=>dr(b)==="[object Set]",ln=b=>b instanceof Date,un=b=>typeof b=="function",fr=b=>typeof b=="string",Fi=b=>typeof b=="symbol",Ut=b=>b!==null&&typeof b=="object",Rr=b=>Ut(b)&&un(b.then)&&un(b.catch),Un=Object.prototype.toString,dr=b=>Un.call(b),Bi=b=>dr(b).slice(8,-1),Hn=b=>dr(b)==="[object Object]",qn=b=>fr(b)&&b!=="NaN"&&b[0]!=="-"&&""+parseInt(b,10)===b,Vn=i(",key,ref,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),pr=b=>{const W=Object.create(null);return ee=>W[ee]||(W[ee]=b(ee))},zn=/-(\w)/g,Wn=pr(b=>b.replace(zn,(W,ee)=>ee?ee.toUpperCase():"")),Ui=/\B([A-Z])/g,Kn=pr(b=>b.replace(Ui,"-$1").toLowerCase()),hr=pr(b=>b.charAt(0).toUpperCase()+b.slice(1)),Hi=pr(b=>b?`on${hr(b)}`:""),cn=(b,W)=>b!==W&&(b===b||W===W),qi=(b,W)=>{for(let ee=0;ee{Object.defineProperty(b,W,{configurable:!0,enumerable:!1,value:ee})},Mr=b=>{const W=parseFloat(b);return isNaN(W)?b:W},kr,Jn=()=>kr||(kr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});t.EMPTY_ARR=on,t.EMPTY_OBJ=an,t.NO=Cr,t.NOOP=sn,t.PatchFlagNames=o,t.babelParserDefaultPlugins=$i,t.camelize=Wn,t.capitalize=hr,t.def=Nr,t.escapeHtml=Li,t.escapeHtmlComment=ji,t.extend=Dn,t.generateCodeFrame=x,t.getGlobalThis=Jn,t.hasChanged=cn,t.hasOwn=Bn,t.hyphenate=Kn,t.invokeArrayFns=qi,t.isArray=Nt,t.isBooleanAttr=Me,t.isDate=ln,t.isFunction=un,t.isGloballyWhitelisted=d,t.isHTMLTag=Sr,t.isIntegerKey=qn,t.isKnownAttr=Se,t.isMap=cr,t.isModelListener=Pr,t.isNoUnitNumericStyleProp=Ft,t.isObject=Ut,t.isOn=Tr,t.isPlainObject=Hn,t.isPromise=Rr,t.isReservedProp=Vn,t.isSSRSafeAttrName=Ke,t.isSVGTag=Mi,t.isSet=Mt,t.isSpecialBooleanAttr=Z,t.isString=fr,t.isSymbol=Fi,t.isVoidTag=Er,t.looseEqual=Or,t.looseIndexOf=jn,t.makeMap=i,t.normalizeClass=Bt,t.normalizeStyle=Ue,t.objectToString=Un,t.parseStringStyle=mt,t.propsToAttrMap=At,t.remove=$n,t.slotFlagsText=c,t.stringifyStyle=Rt,t.toDisplayString=In,t.toHandlerKey=Hi,t.toNumber=Mr,t.toRawType=Bi,t.toTypeString=dr}}),E=L({"node_modules/@vue/shared/index.js"(t,i){i.exports=Y()}}),v=L({"node_modules/@vue/reactivity/dist/reactivity.cjs.js"(t){Object.defineProperty(t,"__esModule",{value:!0});var i=E(),o=new WeakMap,c=[],p,d=Symbol("iterate"),g=Symbol("Map key iterate");function x(u){return u&&u._isEffect===!0}function k(u,T=i.EMPTY_OBJ){x(u)&&(u=u.raw);const N=Qe(u,T);return T.lazy||N(),N}function Z(u){u.active&&($e(u),u.options.onStop&&u.options.onStop(),u.active=!1)}var Me=0;function Qe(u,T){const N=function(){if(!N.active)return u();if(!c.includes(N)){$e(N);try{return Se(),c.push(N),p=N,u()}finally{c.pop(),Ue(),p=c[c.length-1]}}};return N.id=Me++,N.allowRecurse=!!T.allowRecurse,N._isEffect=!0,N.active=!0,N.raw=u,N.deps=[],N.options=T,N}function $e(u){const{deps:T}=u;if(T.length){for(let N=0;N{ht&&ht.forEach(kt=>{(kt!==p||kt.allowRecurse)&&it.add(kt)})};if(T==="clear")je.forEach(bt);else if(N==="length"&&i.isArray(u))je.forEach((ht,kt)=>{(kt==="length"||kt>=ie)&&bt(ht)});else switch(N!==void 0&&bt(je.get(N)),T){case"add":i.isArray(u)?i.isIntegerKey(N)&&bt(je.get("length")):(bt(je.get(d)),i.isMap(u)&&bt(je.get(g)));break;case"delete":i.isArray(u)||(bt(je.get(d)),i.isMap(u)&&bt(je.get(g)));break;case"set":i.isMap(u)&&bt(je.get(d));break}const dn=ht=>{ht.options.onTrigger&&ht.options.onTrigger({effect:ht,target:u,key:N,type:T,newValue:ie,oldValue:J,oldTarget:me}),ht.options.scheduler?ht.options.scheduler(ht):ht()};it.forEach(dn)}var mt=i.makeMap("__proto__,__v_isRef,__isVue"),Rt=new Set(Object.getOwnPropertyNames(Symbol).map(u=>Symbol[u]).filter(i.isSymbol)),Bt=Er(),xr=Er(!1,!0),rn=Er(!0),nn=Er(!0,!0),Sr=Mi();function Mi(){const u={};return["includes","indexOf","lastIndexOf"].forEach(T=>{u[T]=function(...N){const ie=b(this);for(let me=0,je=this.length;me{u[T]=function(...N){Ft();const ie=b(this)[T].apply(this,N);return Ue(),ie}}),u}function Er(u=!1,T=!1){return function(ie,J,me){if(J==="__v_isReactive")return!u;if(J==="__v_isReadonly")return u;if(J==="__v_raw"&&me===(u?T?Wn:zn:T?pr:Vn).get(ie))return ie;const je=i.isArray(ie);if(!u&&je&&i.hasOwn(Sr,J))return Reflect.get(Sr,J,me);const it=Reflect.get(ie,J,me);return(i.isSymbol(J)?Rt.has(J):mt(J))||(u||Le(ie,"get",J),T)?it:le(it)?!je||!i.isIntegerKey(J)?it.value:it:i.isObject(it)?u?cn(it):hr(it):it}}var ki=Ln(),Li=Ln(!0);function Ln(u=!1){return function(N,ie,J,me){let je=N[ie];if(!u&&(J=b(J),je=b(je),!i.isArray(N)&&le(je)&&!le(J)))return je.value=J,!0;const it=i.isArray(N)&&i.isIntegerKey(ie)?Number(ie)i.isObject(u)?hr(u):u,on=u=>i.isObject(u)?cn(u):u,sn=u=>u,Cr=u=>Reflect.getPrototypeOf(u);function Ar(u,T,N=!1,ie=!1){u=u.__v_raw;const J=b(u),me=b(T);T!==me&&!N&&Le(J,"get",T),!N&&Le(J,"get",me);const{has:je}=Cr(J),it=ie?sn:N?on:an;if(je.call(J,T))return it(u.get(T));if(je.call(J,me))return it(u.get(me));u!==J&&u.get(T)}function Tr(u,T=!1){const N=this.__v_raw,ie=b(N),J=b(u);return u!==J&&!T&&Le(ie,"has",u),!T&&Le(ie,"has",J),u===J?N.has(u):N.has(u)||N.has(J)}function Pr(u,T=!1){return u=u.__v_raw,!T&&Le(b(u),"iterate",d),Reflect.get(u,"size",u)}function Dn(u){u=b(u);const T=b(this);return Cr(T).has.call(T,u)||(T.add(u),He(T,"add",u,u)),this}function $n(u,T){T=b(T);const N=b(this),{has:ie,get:J}=Cr(N);let me=ie.call(N,u);me?qn(N,ie,u):(u=b(u),me=ie.call(N,u));const je=J.call(N,u);return N.set(u,T),me?i.hasChanged(T,je)&&He(N,"set",u,T,je):He(N,"add",u,T),this}function Fn(u){const T=b(this),{has:N,get:ie}=Cr(T);let J=N.call(T,u);J?qn(T,N,u):(u=b(u),J=N.call(T,u));const me=ie?ie.call(T,u):void 0,je=T.delete(u);return J&&He(T,"delete",u,void 0,me),je}function Bn(){const u=b(this),T=u.size!==0,N=i.isMap(u)?new Map(u):new Set(u),ie=u.clear();return T&&He(u,"clear",void 0,void 0,N),ie}function Nt(u,T){return function(ie,J){const me=this,je=me.__v_raw,it=b(je),bt=T?sn:u?on:an;return!u&&Le(it,"iterate",d),je.forEach((dn,ht)=>ie.call(J,bt(dn),bt(ht),me))}}function cr(u,T,N){return function(...ie){const J=this.__v_raw,me=b(J),je=i.isMap(me),it=u==="entries"||u===Symbol.iterator&&je,bt=u==="keys"&&je,dn=J[u](...ie),ht=N?sn:T?on:an;return!T&&Le(me,"iterate",bt?g:d),{next(){const{value:kt,done:zi}=dn.next();return zi?{value:kt,done:zi}:{value:it?[ht(kt[0]),ht(kt[1])]:ht(kt),done:zi}},[Symbol.iterator](){return this}}}}function Mt(u){return function(...T){{const N=T[0]?`on key "${T[0]}" `:"";console.warn(`${i.capitalize(u)} operation ${N}failed: target is readonly.`,b(this))}return u==="delete"?!1:this}}function ln(){const u={get(me){return Ar(this,me)},get size(){return Pr(this)},has:Tr,add:Dn,set:$n,delete:Fn,clear:Bn,forEach:Nt(!1,!1)},T={get(me){return Ar(this,me,!1,!0)},get size(){return Pr(this)},has:Tr,add:Dn,set:$n,delete:Fn,clear:Bn,forEach:Nt(!1,!0)},N={get(me){return Ar(this,me,!0)},get size(){return Pr(this,!0)},has(me){return Tr.call(this,me,!0)},add:Mt("add"),set:Mt("set"),delete:Mt("delete"),clear:Mt("clear"),forEach:Nt(!0,!1)},ie={get(me){return Ar(this,me,!0,!0)},get size(){return Pr(this,!0)},has(me){return Tr.call(this,me,!0)},add:Mt("add"),set:Mt("set"),delete:Mt("delete"),clear:Mt("clear"),forEach:Nt(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(me=>{u[me]=cr(me,!1,!1),N[me]=cr(me,!0,!1),T[me]=cr(me,!1,!0),ie[me]=cr(me,!0,!0)}),[u,N,T,ie]}var[un,fr,Fi,Ut]=ln();function Rr(u,T){const N=T?u?Ut:Fi:u?fr:un;return(ie,J,me)=>J==="__v_isReactive"?!u:J==="__v_isReadonly"?u:J==="__v_raw"?ie:Reflect.get(i.hasOwn(N,J)&&J in ie?N:ie,J,me)}var Un={get:Rr(!1,!1)},dr={get:Rr(!1,!0)},Bi={get:Rr(!0,!1)},Hn={get:Rr(!0,!0)};function qn(u,T,N){const ie=b(N);if(ie!==N&&T.call(u,ie)){const J=i.toRawType(u);console.warn(`Reactive ${J} contains both the raw and reactive versions of the same object${J==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var Vn=new WeakMap,pr=new WeakMap,zn=new WeakMap,Wn=new WeakMap;function Ui(u){switch(u){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Kn(u){return u.__v_skip||!Object.isExtensible(u)?0:Ui(i.toRawType(u))}function hr(u){return u&&u.__v_isReadonly?u:Nr(u,!1,jn,Un,Vn)}function Hi(u){return Nr(u,!1,Di,dr,pr)}function cn(u){return Nr(u,!0,In,Bi,zn)}function qi(u){return Nr(u,!0,$i,Hn,Wn)}function Nr(u,T,N,ie,J){if(!i.isObject(u))return console.warn(`value cannot be made reactive: ${String(u)}`),u;if(u.__v_raw&&!(T&&u.__v_isReactive))return u;const me=J.get(u);if(me)return me;const je=Kn(u);if(je===0)return u;const it=new Proxy(u,je===2?ie:N);return J.set(u,it),it}function Mr(u){return kr(u)?Mr(u.__v_raw):!!(u&&u.__v_isReactive)}function kr(u){return!!(u&&u.__v_isReadonly)}function Jn(u){return Mr(u)||kr(u)}function b(u){return u&&b(u.__v_raw)||u}function W(u){return i.def(u,"__v_skip",!0),u}var ee=u=>i.isObject(u)?hr(u):u;function le(u){return!!(u&&u.__v_isRef===!0)}function qe(u){return yt(u)}function tt(u){return yt(u,!0)}var vt=class{constructor(u,T=!1){this._shallow=T,this.__v_isRef=!0,this._rawValue=T?u:b(u),this._value=T?u:ee(u)}get value(){return Le(b(this),"get","value"),this._value}set value(u){u=this._shallow?u:b(u),i.hasChanged(u,this._rawValue)&&(this._rawValue=u,this._value=this._shallow?u:ee(u),He(b(this),"set","value",u))}};function yt(u,T=!1){return le(u)?u:new vt(u,T)}function ct(u){He(b(u),"set","value",u.value)}function fn(u){return le(u)?u.value:u}var Lr={get:(u,T,N)=>fn(Reflect.get(u,T,N)),set:(u,T,N,ie)=>{const J=u[T];return le(J)&&!le(N)?(J.value=N,!0):Reflect.set(u,T,N,ie)}};function Gn(u){return Mr(u)?u:new Proxy(u,Lr)}var jr=class{constructor(u){this.__v_isRef=!0;const{get:T,set:N}=u(()=>Le(this,"get","value"),()=>He(this,"set","value"));this._get=T,this._set=N}get value(){return this._get()}set value(u){this._set(u)}};function Vi(u){return new jr(u)}function ul(u){Jn(u)||console.warn("toRefs() expects a reactive object but received a plain one.");const T=i.isArray(u)?new Array(u.length):{};for(const N in u)T[N]=Ja(u,N);return T}var cl=class{constructor(u,T){this._object=u,this._key=T,this.__v_isRef=!0}get value(){return this._object[this._key]}set value(u){this._object[this._key]=u}};function Ja(u,T){return le(u[T])?u[T]:new cl(u,T)}var fl=class{constructor(u,T,N){this._setter=T,this._dirty=!0,this.__v_isRef=!0,this.effect=k(u,{lazy:!0,scheduler:()=>{this._dirty||(this._dirty=!0,He(b(this),"set","value"))}}),this.__v_isReadonly=N}get value(){const u=b(this);return u._dirty&&(u._value=this.effect(),u._dirty=!1),Le(u,"get","value"),u._value}set value(u){this._setter(u)}};function dl(u){let T,N;return i.isFunction(u)?(T=u,N=()=>{console.warn("Write operation failed: computed value is readonly")}):(T=u.get,N=u.set),new fl(T,N,i.isFunction(u)||!u.set)}t.ITERATE_KEY=d,t.computed=dl,t.customRef=Vi,t.effect=k,t.enableTracking=Se,t.isProxy=Jn,t.isReactive=Mr,t.isReadonly=kr,t.isRef=le,t.markRaw=W,t.pauseTracking=Ft,t.proxyRefs=Gn,t.reactive=hr,t.readonly=cn,t.ref=qe,t.resetTracking=Ue,t.shallowReactive=Hi,t.shallowReadonly=qi,t.shallowRef=tt,t.stop=Z,t.toRaw=b,t.toRef=Ja,t.toRefs=ul,t.track=Le,t.trigger=He,t.triggerRef=ct,t.unref=fn}}),_=L({"node_modules/@vue/reactivity/index.js"(t,i){i.exports=v()}}),O={};q(O,{Alpine:()=>Ka,default:()=>ll}),r.exports=K(O);var R=!1,I=!1,U=[],Re=-1;function D(t){C(t)}function C(t){U.includes(t)||U.push(t),te()}function M(t){let i=U.indexOf(t);i!==-1&&i>Re&&U.splice(i,1)}function te(){!I&&!R&&(R=!0,queueMicrotask(be))}function be(){R=!1,I=!0;for(let t=0;tt.effect(i,{scheduler:o=>{Ge?D(o):o()}}),Je=t.raw}function dt(t){Q=t}function xt(t){let i=()=>{};return[c=>{let p=Q(c);return t._x_effects||(t._x_effects=new Set,t._x_runEffects=()=>{t._x_effects.forEach(d=>d())}),t._x_effects.add(p),i=()=>{p!==void 0&&(t._x_effects.delete(p),Pe(p))},p},()=>{i()}]}function Et(t,i){let o=!0,c,p=Q(()=>{let d=t();JSON.stringify(d),o?c=d:queueMicrotask(()=>{i(d,c),c=d}),o=!1});return()=>Pe(p)}function we(t,i,o={}){t.dispatchEvent(new CustomEvent(i,{detail:o,bubbles:!0,composed:!0,cancelable:!0}))}function ue(t,i){if(typeof ShadowRoot=="function"&&t instanceof ShadowRoot){Array.from(t.children).forEach(p=>ue(p,i));return}let o=!1;if(i(t,()=>o=!0),o)return;let c=t.firstElementChild;for(;c;)ue(c,i),c=c.nextElementSibling}function fe(t,...i){console.warn(`Alpine Warning: ${t}`,...i)}var Ee=!1;function ve(){Ee&&fe("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),Ee=!0,document.body||fe("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `