mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-03 19:04:36 -04:00
commit
a322dc2511
@ -1 +1 @@
|
||||
5.6.18
|
||||
5.6.19
|
@ -17,7 +17,7 @@ class EncryptedCast implements CastsAttributes
|
||||
{
|
||||
public function get($model, string $key, $value, array $attributes)
|
||||
{
|
||||
return strlen($value) > 1 ? decrypt($value) : null;
|
||||
return is_string($value) && strlen($value) > 1 ? decrypt($value) : null;
|
||||
}
|
||||
|
||||
public function set($model, string $key, $value, array $attributes)
|
||||
|
@ -13,6 +13,7 @@ namespace App\Export\CSV;
|
||||
|
||||
use App\Utils\Number;
|
||||
use App\Models\Client;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Payment;
|
||||
@ -42,9 +43,41 @@ class BaseExport
|
||||
|
||||
public array $forced_keys = [];
|
||||
|
||||
protected array $vendor_report_keys = [
|
||||
'address1' => 'vendor.address1',
|
||||
'address2' => 'vendor.address2',
|
||||
'city' => 'vendor.city',
|
||||
'country' => 'vendor.country_id',
|
||||
'custom_value1' => 'vendor.custom_value1',
|
||||
'custom_value2' => 'vendor.custom_value2',
|
||||
'custom_value3' => 'vendor.custom_value3',
|
||||
'custom_value4' => 'vendor.custom_value4',
|
||||
'id_number' => 'vendor.id_number',
|
||||
'name' => 'vendor.name',
|
||||
'number' => 'vendor.number',
|
||||
'client_phone' => 'vendor.phone',
|
||||
'postal_code' => 'vendor.postal_code',
|
||||
'private_notes' => 'vendor.private_notes',
|
||||
'public_notes' => 'vendor.public_notes',
|
||||
'state' => 'vendor.state',
|
||||
'vat_number' => 'vendor.vat_number',
|
||||
'website' => 'vendor.website',
|
||||
'currency' => 'vendor.currency',
|
||||
'first_name' => 'vendor_contact.first_name',
|
||||
'last_name' => 'vendor_contact.last_name',
|
||||
'contact_phone' => 'vendor_contact.phone',
|
||||
'contact_custom_value1' => 'vendor_contact.custom_value1',
|
||||
'contact_custom_value2' => 'vendor_contact.custom_value2',
|
||||
'contact_custom_value3' => 'vendor_contact.custom_value3',
|
||||
'contact_custom_value4' => 'vendor_contact.custom_value4',
|
||||
'email' => 'vendor_contact.email',
|
||||
'status' => 'vendor.status',
|
||||
];
|
||||
|
||||
protected array $client_report_keys = [
|
||||
"name" => "client.name",
|
||||
"user" => "client.user_id",
|
||||
"user" => "client.user",
|
||||
"assigned_user" => "client.assigned_user",
|
||||
"balance" => "client.balance",
|
||||
"paid_to_date" => "client.paid_to_date",
|
||||
"currency" => "client.currency_id",
|
||||
@ -103,6 +136,42 @@ class BaseExport
|
||||
"user" => "invoice.user_id",
|
||||
];
|
||||
|
||||
protected array $purchase_order_report_keys = [
|
||||
'amount' => 'purchase_order.amount',
|
||||
'balance' => 'purchase_order.balance',
|
||||
'vendor' => 'purchase_order.vendor_id',
|
||||
// 'custom_surcharge1' => 'purchase_order.custom_surcharge1',
|
||||
// 'custom_surcharge2' => 'purchase_order.custom_surcharge2',
|
||||
// 'custom_surcharge3' => 'purchase_order.custom_surcharge3',
|
||||
// 'custom_surcharge4' => 'purchase_order.custom_surcharge4',
|
||||
'custom_value1' => 'purchase_order.custom_value1',
|
||||
'custom_value2' => 'purchase_order.custom_value2',
|
||||
'custom_value3' => 'purchase_order.custom_value3',
|
||||
'custom_value4' => 'purchase_order.custom_value4',
|
||||
'date' => 'purchase_order.date',
|
||||
'discount' => 'purchase_order.discount',
|
||||
'due_date' => 'purchase_order.due_date',
|
||||
'exchange_rate' => 'purchase_order.exchange_rate',
|
||||
'footer' => 'purchase_order.footer',
|
||||
'number' => 'purchase_order.number',
|
||||
'paid_to_date' => 'purchase_order.paid_to_date',
|
||||
'partial' => 'purchase_order.partial',
|
||||
'partial_due_date' => 'purchase_order.partial_due_date',
|
||||
'po_number' => 'purchase_order.po_number',
|
||||
'private_notes' => 'purchase_order.private_notes',
|
||||
'public_notes' => 'purchase_order.public_notes',
|
||||
'status' => 'purchase_order.status_id',
|
||||
'tax_name1' => 'purchase_order.tax_name1',
|
||||
'tax_name2' => 'purchase_order.tax_name2',
|
||||
'tax_name3' => 'purchase_order.tax_name3',
|
||||
'tax_rate1' => 'purchase_order.tax_rate1',
|
||||
'tax_rate2' => 'purchase_order.tax_rate2',
|
||||
'tax_rate3' => 'purchase_order.tax_rate3',
|
||||
'terms' => 'purchase_order.terms',
|
||||
'total_taxes' => 'purchase_order.total_taxes',
|
||||
'currency_id' => 'purchase_order.currency_id',
|
||||
];
|
||||
|
||||
protected array $item_report_keys = [
|
||||
"quantity" => "item.quantity",
|
||||
"cost" => "item.cost",
|
||||
@ -197,6 +266,58 @@ class BaseExport
|
||||
"assigned_user" => "payment.assigned_user_id",
|
||||
];
|
||||
|
||||
protected array $expense_report_keys = [
|
||||
'amount' => 'expense.amount',
|
||||
'category' => 'expense.category_id',
|
||||
'client' => 'expense.client_id',
|
||||
'custom_value1' => 'expense.custom_value1',
|
||||
'custom_value2' => 'expense.custom_value2',
|
||||
'custom_value3' => 'expense.custom_value3',
|
||||
'custom_value4' => 'expense.custom_value4',
|
||||
'currency' => 'expense.currency_id',
|
||||
'date' => 'expense.date',
|
||||
'exchange_rate' => 'expense.exchange_rate',
|
||||
'converted_amount' => 'expense.foreign_amount',
|
||||
'invoice_currency_id' => 'expense.invoice_currency_id',
|
||||
'payment_date' => 'expense.payment_date',
|
||||
'number' => 'expense.number',
|
||||
'payment_type_id' => 'expense.payment_type_id',
|
||||
'private_notes' => 'expense.private_notes',
|
||||
'project' => 'expense.project_id',
|
||||
'public_notes' => 'expense.public_notes',
|
||||
'tax_amount1' => 'expense.tax_amount1',
|
||||
'tax_amount2' => 'expense.tax_amount2',
|
||||
'tax_amount3' => 'expense.tax_amount3',
|
||||
'tax_name1' => 'expense.tax_name1',
|
||||
'tax_name2' => 'expense.tax_name2',
|
||||
'tax_name3' => 'expense.tax_name3',
|
||||
'tax_rate1' => 'expense.tax_rate1',
|
||||
'tax_rate2' => 'expense.tax_rate2',
|
||||
'tax_rate3' => 'expense.tax_rate3',
|
||||
'transaction_reference' => 'expense.transaction_reference',
|
||||
'vendor' => 'expense.vendor_id',
|
||||
'invoice' => 'expense.invoice_id',
|
||||
'user' => 'expense.user',
|
||||
'assigned_user' => 'expense.assigned_user',
|
||||
];
|
||||
|
||||
protected array $task_report_keys = [
|
||||
'start_date' => 'task.start_date',
|
||||
'end_date' => 'task.end_date',
|
||||
'duration' => 'task.duration',
|
||||
'rate' => 'task.rate',
|
||||
'number' => 'task.number',
|
||||
'description' => 'task.description',
|
||||
'custom_value1' => 'task.custom_value1',
|
||||
'custom_value2' => 'task.custom_value2',
|
||||
'custom_value3' => 'task.custom_value3',
|
||||
'custom_value4' => 'task.custom_value4',
|
||||
'status' => 'task.status_id',
|
||||
'project' => 'task.project_id',
|
||||
'invoice' => 'task.invoice_id',
|
||||
'client' => 'task.client_id',
|
||||
];
|
||||
|
||||
protected function filterByClients($query)
|
||||
{
|
||||
if (isset($this->input['client_id']) && $this->input['client_id'] != 'all') {
|
||||
@ -222,7 +343,11 @@ class BaseExport
|
||||
match($parts[0]) {
|
||||
'contact' => $value = $this->resolveClientContactKey($parts[1], $entity, $transformer),
|
||||
'client' => $value = $this->resolveClientKey($parts[1], $entity, $transformer),
|
||||
'expense' => $value = $this->resolveExpenseKey($parts[1], $entity, $transformer),
|
||||
'vendor' => $value = $this->resolveVendorKey($parts[1], $entity, $transformer),
|
||||
'vendor_contact' => $value = $this->resolveVendorContactKey($parts[1], $entity, $transformer),
|
||||
'invoice' => $value = $this->resolveInvoiceKey($parts[1], $entity, $transformer),
|
||||
'purchase_order' => $value = $this->resolvePurchaseOrderKey($parts[1], $entity, $transformer),
|
||||
'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
|
||||
default => $value = ''
|
||||
};
|
||||
@ -233,14 +358,106 @@ class BaseExport
|
||||
private function resolveClientContactKey($column, $entity, $transformer)
|
||||
{
|
||||
|
||||
if(!$entity->client) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$primary_contact = $entity->client->primary_contact()->first() ?? $entity->client->contacts()->first();
|
||||
|
||||
return $primary_contact?->{$column} ?? '';
|
||||
return $primary_contact ? $primary_contact?->{$column} ?? '' : '';
|
||||
|
||||
}
|
||||
|
||||
private function resolveVendorContactKey($column, $entity, $transformer)
|
||||
{
|
||||
if(!$entity->vendor)
|
||||
return "";
|
||||
|
||||
$primary_contact = $entity->vendor->primary_contact()->first() ?? $entity->vendor->contacts()->first();
|
||||
|
||||
return $primary_contact ? $primary_contact?->{$column} ?? '' : '';
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function resolveExpenseKey($column, $entity, $transformer)
|
||||
{
|
||||
|
||||
if($column == 'user' && $entity?->expense?->user)
|
||||
return $entity->expense->user->present()->name() ?? ' ';
|
||||
|
||||
if($column == 'assigned_user' && $entity?->expense?->assigned_user)
|
||||
return $entity->expense->assigned_user->present()->name() ?? ' ';
|
||||
|
||||
if($column == 'category' && $entity->expense) {
|
||||
return $entity->expense->category?->name ?? ' ';
|
||||
}
|
||||
|
||||
if($entity instanceof Expense)
|
||||
return '';
|
||||
|
||||
$transformed_entity = $transformer->includeExpense($entity);
|
||||
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new ArraySerializer());
|
||||
$transformed_entity = $manager->createData($transformed_entity)->toArray();
|
||||
|
||||
if(array_key_exists($column, $transformed_entity))
|
||||
return $transformed_entity[$column];
|
||||
|
||||
if(property_exists($entity, $column))
|
||||
return $entity?->{$column} ?? '';
|
||||
|
||||
nlog("export: Could not resolve expense key: {$column}");
|
||||
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
private function resolveVendorKey($column, $entity, $transformer)
|
||||
{
|
||||
|
||||
if(!$entity->vendor)
|
||||
return '';
|
||||
|
||||
$transformed_entity = $transformer->includeVendor($entity);
|
||||
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new ArraySerializer());
|
||||
$transformed_entity = $manager->createData($transformed_entity)->toArray();
|
||||
|
||||
if($column == 'name')
|
||||
return $entity->vendor->present()->name() ?: '';
|
||||
|
||||
if($column == 'user_id')
|
||||
return $entity->vendor->user->present()->name() ?: '';
|
||||
|
||||
if($column == 'country_id')
|
||||
return $entity->vendor->country ? ctrans("texts.country_{$entity->vendor->country->name}") : '';
|
||||
|
||||
if ($column == 'currency_id') {
|
||||
return $entity->vendor->currency() ? $entity->vendor->currency()->code : $entity->company->currency()->code;
|
||||
}
|
||||
|
||||
if($column == 'status')
|
||||
return $entity->stringStatus($entity->status_id) ?: '';
|
||||
|
||||
if(array_key_exists($column, $transformed_entity))
|
||||
return $transformed_entity[$column];
|
||||
|
||||
nlog("export: Could not resolve vendor key: {$column}");
|
||||
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function resolveClientKey($column, $entity, $transformer)
|
||||
{
|
||||
|
||||
if(!$entity->client)
|
||||
return '';
|
||||
|
||||
$transformed_client = $transformer->includeClient($entity);
|
||||
|
||||
$manager = new Manager();
|
||||
@ -282,6 +499,18 @@ class BaseExport
|
||||
|
||||
}
|
||||
|
||||
private function resolvePurchaseOrderKey($column, $entity, $transformer)
|
||||
{
|
||||
nlog("searching for {$column}");
|
||||
|
||||
$transformed_entity = $transformer->transform($entity);
|
||||
|
||||
if($column == 'status')
|
||||
return $entity->stringStatus($entity->status_id);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function resolveInvoiceKey($column, $entity, $transformer)
|
||||
{
|
||||
nlog("searching for {$column}");
|
||||
@ -496,6 +725,8 @@ class BaseExport
|
||||
{
|
||||
$header = [];
|
||||
|
||||
// nlog($this->input['report_keys']);
|
||||
|
||||
foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) {
|
||||
|
||||
$key = array_search($value, $this->entity_keys);
|
||||
@ -503,48 +734,75 @@ class BaseExport
|
||||
$prefix = '';
|
||||
|
||||
if(!$key) {
|
||||
$prefix = stripos($value, 'client.') !== false ? ctrans('texts.client') : ctrans('texts.contact');
|
||||
$prefix = stripos($value, 'client.') !== false ? ctrans('texts.client')." " : ctrans('texts.contact')." ";
|
||||
$key = array_search($value, $this->client_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.invoice');
|
||||
$prefix = ctrans('texts.invoice')." ";
|
||||
$key = array_search($value, $this->invoice_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.payment');
|
||||
$prefix = ctrans('texts.payment')." ";
|
||||
$key = array_search($value, $this->payment_report_keys);
|
||||
}
|
||||
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.quote');
|
||||
$prefix = ctrans('texts.quote')." ";
|
||||
$key = array_search($value, $this->quote_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.credit');
|
||||
$prefix = ctrans('texts.credit')." ";
|
||||
$key = array_search($value, $this->credit_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.item');
|
||||
$prefix = ctrans('texts.item')." ";
|
||||
$key = array_search($value, $this->item_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.expense')." ";
|
||||
$key = array_search($value, $this->expense_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.task')." ";
|
||||
$key = array_search($value, $this->task_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.vendor')." ";
|
||||
$key = array_search($value, $this->vendor_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = ctrans('texts.purchase_order')." ";
|
||||
$key = array_search($value, $this->purchase_order_report_keys);
|
||||
}
|
||||
|
||||
if(!$key) {
|
||||
$prefix = '';
|
||||
}
|
||||
|
||||
$key = str_replace('item.', '', $key);
|
||||
$key = str_replace('recurring_invoice.', '', $key);
|
||||
$key = str_replace('invoice.', '', $key);
|
||||
$key = str_replace('quote.', '', $key);
|
||||
$key = str_replace('credit.', '', $key);
|
||||
$key = str_replace('task.', '', $key);
|
||||
$key = str_replace('client.', '', $key);
|
||||
$key = str_replace('vendor.', '', $key);
|
||||
$key = str_replace('contact.', '', $key);
|
||||
$key = str_replace('payment.', '', $key);
|
||||
$key = str_replace('expense.', '', $key);
|
||||
|
||||
$header[] = "{$prefix} " . ctrans("texts.{$key}");
|
||||
$header[] = "{$prefix}" . ctrans("texts.{$key}");
|
||||
}
|
||||
// nlog($header);
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
@ -82,7 +82,6 @@ class ClientExport extends BaseExport
|
||||
];
|
||||
|
||||
public array $forced_keys = [
|
||||
'status',
|
||||
];
|
||||
|
||||
public function __construct(Company $company, array $input)
|
||||
@ -132,6 +131,8 @@ class ClientExport extends BaseExport
|
||||
|
||||
$transformed_client = $this->client_transformer->transform($client);
|
||||
|
||||
$transformed_contact = [];
|
||||
|
||||
if ($contact = $client->contacts()->first()) {
|
||||
$transformed_contact = $this->contact_transformer->transform($contact);
|
||||
}
|
||||
@ -140,15 +141,13 @@ class ClientExport extends BaseExport
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) {
|
||||
$parts = explode('.', $key);
|
||||
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
|
||||
if (is_array($parts) && $parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) {
|
||||
$entity[$keyval] = $transformed_client[$parts[1]];
|
||||
$entity[$key] = $transformed_client[$parts[1]];
|
||||
} elseif (is_array($parts) && $parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
|
||||
$entity[$keyval] = $transformed_contact[$parts[1]];
|
||||
$entity[$key] = $transformed_contact[$parts[1]];
|
||||
} else {
|
||||
$entity[$keyval] = '';
|
||||
$entity[$key] = '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +156,14 @@ class ClientExport extends BaseExport
|
||||
|
||||
private function decorateAdvancedFields(Client $client, array $entity) :array
|
||||
{
|
||||
if (in_array('client.user', $this->input['report_keys'])) {
|
||||
$entity['client.user'] = $client->user->present()->name();
|
||||
}
|
||||
|
||||
if (in_array('client.assigned_user', $this->input['report_keys'])) {
|
||||
$entity['client.assigned_user'] = $client->assigned_user ? $client->user->present()->name() : '';
|
||||
}
|
||||
|
||||
if (in_array('client.country_id', $this->input['report_keys'])) {
|
||||
$entity['country'] = $client->country ? ctrans("texts.country_{$client->country->name}") : '';
|
||||
}
|
||||
@ -173,8 +180,6 @@ class ClientExport extends BaseExport
|
||||
$entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
|
||||
}
|
||||
|
||||
$entity['status'] = $this->calculateStatus($client);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
@ -185,7 +190,7 @@ class ClientExport extends BaseExport
|
||||
}
|
||||
|
||||
if ($client->deleted_at) {
|
||||
return ctrans('texts.arcvived');
|
||||
return ctrans('texts.archived');
|
||||
}
|
||||
|
||||
return ctrans('texts.active');
|
||||
|
@ -30,36 +30,38 @@ class ExpenseExport extends BaseExport
|
||||
public Writer $csv;
|
||||
|
||||
public array $entity_keys = [
|
||||
'amount' => 'amount',
|
||||
'category' => 'category_id',
|
||||
'client' => 'client_id',
|
||||
'custom_value1' => 'custom_value1',
|
||||
'custom_value2' => 'custom_value2',
|
||||
'custom_value3' => 'custom_value3',
|
||||
'custom_value4' => 'custom_value4',
|
||||
'currency' => 'currency_id',
|
||||
'date' => 'date',
|
||||
'exchange_rate' => 'exchange_rate',
|
||||
'converted_amount' => 'foreign_amount',
|
||||
'invoice_currency_id' => 'invoice_currency_id',
|
||||
'payment_date' => 'payment_date',
|
||||
'number' => 'number',
|
||||
'payment_type_id' => 'payment_type_id',
|
||||
'private_notes' => 'private_notes',
|
||||
'project' => 'project_id',
|
||||
'public_notes' => 'public_notes',
|
||||
'tax_amount1' => 'tax_amount1',
|
||||
'tax_amount2' => 'tax_amount2',
|
||||
'tax_amount3' => 'tax_amount3',
|
||||
'tax_name1' => 'tax_name1',
|
||||
'tax_name2' => 'tax_name2',
|
||||
'tax_name3' => 'tax_name3',
|
||||
'tax_rate1' => 'tax_rate1',
|
||||
'tax_rate2' => 'tax_rate2',
|
||||
'tax_rate3' => 'tax_rate3',
|
||||
'transaction_reference' => 'transaction_reference',
|
||||
'vendor' => 'vendor_id',
|
||||
'invoice' => 'invoice_id',
|
||||
'amount' => 'expense.amount',
|
||||
'category' => 'expense.category',
|
||||
'client' => 'expense.client_id',
|
||||
'custom_value1' => 'expense.custom_value1',
|
||||
'custom_value2' => 'expense.custom_value2',
|
||||
'custom_value3' => 'expense.custom_value3',
|
||||
'custom_value4' => 'expense.custom_value4',
|
||||
'currency' => 'expense.currency_id',
|
||||
'date' => 'expense.date',
|
||||
'exchange_rate' => 'expense.exchange_rate',
|
||||
'converted_amount' => 'expense.foreign_amount',
|
||||
'invoice_currency_id' => 'expense.invoice_currency_id',
|
||||
'payment_date' => 'expense.payment_date',
|
||||
'number' => 'expense.number',
|
||||
'payment_type_id' => 'expense.payment_type_id',
|
||||
'private_notes' => 'expense.private_notes',
|
||||
'project' => 'expense.project_id',
|
||||
'public_notes' => 'expense.public_notes',
|
||||
'tax_amount1' => 'expense.tax_amount1',
|
||||
'tax_amount2' => 'expense.tax_amount2',
|
||||
'tax_amount3' => 'expense.tax_amount3',
|
||||
'tax_name1' => 'expense.tax_name1',
|
||||
'tax_name2' => 'expense.tax_name2',
|
||||
'tax_name3' => 'expense.tax_name3',
|
||||
'tax_rate1' => 'expense.tax_rate1',
|
||||
'tax_rate2' => 'expense.tax_rate2',
|
||||
'tax_rate3' => 'expense.tax_rate3',
|
||||
'transaction_reference' => 'expense.transaction_reference',
|
||||
'vendor' => 'expense.vendor_id',
|
||||
'invoice' => 'expense.invoice_id',
|
||||
'user' => 'expense.user',
|
||||
'assigned_user' => 'expense.assigned_user',
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
@ -120,13 +122,17 @@ class ExpenseExport extends BaseExport
|
||||
$entity = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) {
|
||||
$parts = explode('.', $key);
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
if (array_key_exists($key, $transformed_expense)) {
|
||||
$entity[$keyval] = $transformed_expense[$key];
|
||||
if (is_array($parts) && $parts[0] == 'expense' && array_key_exists($parts[1], $transformed_expense)) {
|
||||
$entity[$key] = $transformed_expense[$parts[1]];
|
||||
} elseif (array_key_exists($key, $transformed_expense)) {
|
||||
$entity[$key] = $transformed_expense[$key];
|
||||
} else {
|
||||
$entity[$keyval] = '';
|
||||
$entity[$key] = $this->resolveKey($key, $expense, $this->expense_transformer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->decorateAdvancedFields($expense, $entity);
|
||||
@ -134,32 +140,40 @@ class ExpenseExport extends BaseExport
|
||||
|
||||
private function decorateAdvancedFields(Expense $expense, array $entity) :array
|
||||
{
|
||||
if (in_array('currency_id', $this->input['report_keys'])) {
|
||||
$entity['currency'] = $expense->currency ? $expense->currency->code : '';
|
||||
if (in_array('expense.currency_id', $this->input['report_keys'])) {
|
||||
$entity['expense.currency_id'] = $expense->currency ? $expense->currency->code : '';
|
||||
}
|
||||
|
||||
if (in_array('client_id', $this->input['report_keys'])) {
|
||||
$entity['client'] = $expense->client ? $expense->client->present()->name() : '';
|
||||
if (in_array('expense.client_id', $this->input['report_keys'])) {
|
||||
$entity['expense.client'] = $expense->client ? $expense->client->present()->name() : '';
|
||||
}
|
||||
|
||||
if (in_array('invoice_id', $this->input['report_keys'])) {
|
||||
$entity['invoice'] = $expense->invoice ? $expense->invoice->number : '';
|
||||
if (in_array('expense.invoice_id', $this->input['report_keys'])) {
|
||||
$entity['expense.invoice_id'] = $expense->invoice ? $expense->invoice->number : '';
|
||||
}
|
||||
|
||||
if (in_array('category_id', $this->input['report_keys'])) {
|
||||
$entity['category'] = $expense->category ? $expense->category->name : '';
|
||||
if (in_array('expense.category', $this->input['report_keys'])) {
|
||||
$entity['expense.category'] = $expense->category ? $expense->category->name : '';
|
||||
}
|
||||
|
||||
if (in_array('vendor_id', $this->input['report_keys'])) {
|
||||
$entity['vendor'] = $expense->vendor ? $expense->vendor->name : '';
|
||||
if (in_array('expense.vendor_id', $this->input['report_keys'])) {
|
||||
$entity['expense.vendor'] = $expense->vendor ? $expense->vendor->name : '';
|
||||
}
|
||||
|
||||
if (in_array('payment_type_id', $this->input['report_keys'])) {
|
||||
$entity['payment_type'] = $expense->payment_type ? $expense->payment_type->name : '';
|
||||
if (in_array('expense.payment_type_id', $this->input['report_keys'])) {
|
||||
$entity['expense.payment_type_id'] = $expense->payment_type ? $expense->payment_type->name : '';
|
||||
}
|
||||
|
||||
if (in_array('project_id', $this->input['report_keys'])) {
|
||||
$entity['project'] = $expense->project ? $expense->project->name : '';
|
||||
if (in_array('expense.project_id', $this->input['report_keys'])) {
|
||||
$entity['expense.project_id'] = $expense->project ? $expense->project->name : '';
|
||||
}
|
||||
|
||||
if (in_array('expense.user', $this->input['report_keys'])) {
|
||||
$entity['expense.user'] = $expense->user ? $expense->user->present()->name() : '';
|
||||
}
|
||||
|
||||
if (in_array('expense.assigned_user', $this->input['report_keys'])) {
|
||||
$entity['expense.assigned_user'] = $expense->assigned_user ? $expense->assigned_user->present()->name() : '';
|
||||
}
|
||||
|
||||
return $entity;
|
||||
|
172
app/Export/CSV/PurchaseOrderExport.php
Normal file
172
app/Export/CSV/PurchaseOrderExport.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* PurchaseOrder Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. PurchaseOrder Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Export\CSV;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use League\Csv\Writer;
|
||||
|
||||
class PurchaseOrderExport extends BaseExport
|
||||
{
|
||||
private Company $company;
|
||||
|
||||
private $purchase_order_transformer;
|
||||
|
||||
public string $date_key = 'date';
|
||||
|
||||
public Writer $csv;
|
||||
|
||||
public array $entity_keys = [
|
||||
'amount' => 'amount',
|
||||
'balance' => 'balance',
|
||||
'vendor' => 'vendor_id',
|
||||
'custom_surcharge1' => 'custom_surcharge1',
|
||||
'custom_surcharge2' => 'custom_surcharge2',
|
||||
'custom_surcharge3' => 'custom_surcharge3',
|
||||
'custom_surcharge4' => 'custom_surcharge4',
|
||||
'custom_value1' => 'custom_value1',
|
||||
'custom_value2' => 'custom_value2',
|
||||
'custom_value3' => 'custom_value3',
|
||||
'custom_value4' => 'custom_value4',
|
||||
'date' => 'date',
|
||||
'discount' => 'discount',
|
||||
'due_date' => 'due_date',
|
||||
'exchange_rate' => 'exchange_rate',
|
||||
'footer' => 'footer',
|
||||
'number' => 'number',
|
||||
'paid_to_date' => 'paid_to_date',
|
||||
'partial' => 'partial',
|
||||
'partial_due_date' => 'partial_due_date',
|
||||
'po_number' => 'po_number',
|
||||
'private_notes' => 'private_notes',
|
||||
'public_notes' => 'public_notes',
|
||||
'status' => 'status_id',
|
||||
'tax_name1' => 'tax_name1',
|
||||
'tax_name2' => 'tax_name2',
|
||||
'tax_name3' => 'tax_name3',
|
||||
'tax_rate1' => 'tax_rate1',
|
||||
'tax_rate2' => 'tax_rate2',
|
||||
'tax_rate3' => 'tax_rate3',
|
||||
'terms' => 'terms',
|
||||
'total_taxes' => 'total_taxes',
|
||||
'currency_id' => 'currency_id',
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
'country',
|
||||
'currency_id',
|
||||
'status',
|
||||
'vendor',
|
||||
'project',
|
||||
];
|
||||
|
||||
|
||||
public function __construct(Company $company, array $input)
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->input = $input;
|
||||
$this->purchase_order_transformer = new PurchaseOrderTransformer();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
App::forgetInstance('translator');
|
||||
App::setLocale($this->company->locale());
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
//load the CSV document from a string
|
||||
$this->csv = Writer::createFromString();
|
||||
|
||||
if (count($this->input['report_keys']) == 0) {
|
||||
$this->input['report_keys'] = array_values($this->entity_keys);
|
||||
}
|
||||
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = PurchaseOrder::query()
|
||||
->withTrashed()
|
||||
->with('vendor')
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
// if(isset($this->input['status'])) {
|
||||
// $query = $this->addPurchaseOrderStatusFilter($query, $this->input['status']);
|
||||
// }
|
||||
|
||||
$query->cursor()
|
||||
->each(function ($purchase_order) {
|
||||
$this->csv->insertOne($this->buildRow($purchase_order));
|
||||
});
|
||||
|
||||
return $this->csv->toString();
|
||||
}
|
||||
|
||||
private function buildRow(PurchaseOrder $purchase_order) :array
|
||||
{
|
||||
$transformed_purchase_order = $this->purchase_order_transformer->transform($purchase_order);
|
||||
|
||||
$entity = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) {
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
if(!$keyval) {
|
||||
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
|
||||
}
|
||||
|
||||
if(!$keyval) {
|
||||
$keyval = $key;
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $transformed_purchase_order)) {
|
||||
$entity[$keyval] = $transformed_purchase_order[$key];
|
||||
} elseif (array_key_exists($keyval, $transformed_purchase_order)) {
|
||||
$entity[$keyval] = $transformed_purchase_order[$keyval];
|
||||
} else {
|
||||
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->decorateAdvancedFields($purchase_order, $entity);
|
||||
}
|
||||
|
||||
private function decorateAdvancedFields(PurchaseOrder $purchase_order, array $entity) :array
|
||||
{
|
||||
if (in_array('country_id', $this->input['report_keys'])) {
|
||||
$entity['country'] = $purchase_order->vendor->country ? ctrans("texts.country_{$purchase_order->vendor->country->name}") : '';
|
||||
}
|
||||
|
||||
if (in_array('currency_id', $this->input['report_keys'])) {
|
||||
$entity['currency_id'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
|
||||
}
|
||||
|
||||
if (in_array('vendor_id', $this->input['report_keys'])) {
|
||||
$entity['vendor'] = $purchase_order->vendor->present()->name();
|
||||
}
|
||||
|
||||
if (in_array('status_id', $this->input['report_keys'])) {
|
||||
$entity['status'] = $purchase_order->stringStatus($purchase_order->status_id);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
246
app/Export/CSV/PurchaseOrderItemExport.php
Normal file
246
app/Export/CSV/PurchaseOrderItemExport.php
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/**
|
||||
* PurchaseOrder Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. PurchaseOrder Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Export\CSV;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use League\Csv\Writer;
|
||||
|
||||
class PurchaseOrderItemExport extends BaseExport
|
||||
{
|
||||
private Company $company;
|
||||
|
||||
private $purchase_order_transformer;
|
||||
|
||||
public string $date_key = 'date';
|
||||
|
||||
public Writer $csv;
|
||||
|
||||
private bool $force_keys = false;
|
||||
|
||||
public array $entity_keys = [
|
||||
'amount' => 'amount',
|
||||
'balance' => 'balance',
|
||||
'vendor' => 'vendor_id',
|
||||
'vendor_number' => 'vendor.number',
|
||||
'vendor_id_number' => 'vendor.id_number',
|
||||
'custom_surcharge1' => 'custom_surcharge1',
|
||||
'custom_surcharge2' => 'custom_surcharge2',
|
||||
'custom_surcharge3' => 'custom_surcharge3',
|
||||
'custom_surcharge4' => 'custom_surcharge4',
|
||||
// 'custom_value1' => 'custom_value1',
|
||||
// 'custom_value2' => 'custom_value2',
|
||||
// 'custom_value3' => 'custom_value3',
|
||||
// 'custom_value4' => 'custom_value4',
|
||||
'date' => 'date',
|
||||
'discount' => 'discount',
|
||||
'due_date' => 'due_date',
|
||||
'exchange_rate' => 'exchange_rate',
|
||||
'footer' => 'footer',
|
||||
'number' => 'number',
|
||||
'paid_to_date' => 'paid_to_date',
|
||||
'partial' => 'partial',
|
||||
'partial_due_date' => 'partial_due_date',
|
||||
'po_number' => 'po_number',
|
||||
'private_notes' => 'private_notes',
|
||||
'public_notes' => 'public_notes',
|
||||
'status' => 'status_id',
|
||||
'tax_name1' => 'tax_name1',
|
||||
'tax_name2' => 'tax_name2',
|
||||
'tax_name3' => 'tax_name3',
|
||||
'tax_rate1' => 'tax_rate1',
|
||||
'tax_rate2' => 'tax_rate2',
|
||||
'tax_rate3' => 'tax_rate3',
|
||||
'terms' => 'terms',
|
||||
'total_taxes' => 'total_taxes',
|
||||
'currency' => 'currency_id',
|
||||
'quantity' => 'item.quantity',
|
||||
'cost' => 'item.cost',
|
||||
'product_key' => 'item.product_key',
|
||||
'buy_price' => 'item.product_cost',
|
||||
'notes' => 'item.notes',
|
||||
'discount' => 'item.discount',
|
||||
'is_amount_discount' => 'item.is_amount_discount',
|
||||
'tax_rate1' => 'item.tax_rate1',
|
||||
'tax_rate2' => 'item.tax_rate2',
|
||||
'tax_rate3' => 'item.tax_rate3',
|
||||
'tax_name1' => 'item.tax_name1',
|
||||
'tax_name2' => 'item.tax_name2',
|
||||
'tax_name3' => 'item.tax_name3',
|
||||
'line_total' => 'item.line_total',
|
||||
'gross_line_total' => 'item.gross_line_total',
|
||||
// 'invoice1' => 'item.custom_value1',
|
||||
// 'invoice2' => 'item.custom_value2',
|
||||
// 'invoice3' => 'item.custom_value3',
|
||||
// 'invoice4' => 'item.custom_value4',
|
||||
'tax_category' => 'item.tax_id',
|
||||
'type' => 'item.type_id',
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
'client',
|
||||
'currency_id',
|
||||
'status'
|
||||
];
|
||||
|
||||
public function __construct(Company $company, array $input)
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->input = $input;
|
||||
$this->purchase_order_transformer = new PurchaseOrderTransformer();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
App::forgetInstance('translator');
|
||||
App::setLocale($this->company->locale());
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
//load the CSV document from a string
|
||||
$this->csv = Writer::createFromString();
|
||||
|
||||
if (count($this->input['report_keys']) == 0) {
|
||||
$this->force_keys = true;
|
||||
$this->input['report_keys'] = array_values($this->entity_keys);
|
||||
}
|
||||
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = PurchaseOrder::query()
|
||||
->withTrashed()
|
||||
->with('vendor')->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
$query->cursor()
|
||||
->each(function ($purchase_order) {
|
||||
$this->iterateItems($purchase_order);
|
||||
});
|
||||
|
||||
return $this->csv->toString();
|
||||
}
|
||||
|
||||
private function iterateItems(PurchaseOrder $purchase_order)
|
||||
{
|
||||
$transformed_invoice = $this->buildRow($purchase_order);
|
||||
|
||||
$transformed_items = [];
|
||||
|
||||
foreach ($purchase_order->line_items as $item) {
|
||||
$item_array = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array
|
||||
|
||||
if (str_contains($key, "item.")) {
|
||||
|
||||
$key = str_replace("item.", "", $key);
|
||||
|
||||
$keyval = $key;
|
||||
|
||||
$keyval = str_replace("custom_value", "invoice", $key);
|
||||
|
||||
if($key == 'type_id') {
|
||||
$keyval = 'type';
|
||||
}
|
||||
|
||||
if($key == 'tax_id') {
|
||||
$keyval = 'tax_category';
|
||||
}
|
||||
|
||||
if (property_exists($item, $key)) {
|
||||
$item_array[$keyval] = $item->{$key};
|
||||
} else {
|
||||
$item_array[$keyval] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$entity = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
if (array_key_exists($key, $transformed_items)) {
|
||||
$entity[$keyval] = $transformed_items[$key];
|
||||
} else {
|
||||
$entity[$keyval] = "";
|
||||
}
|
||||
}
|
||||
|
||||
$transformed_items = array_merge($transformed_invoice, $item_array);
|
||||
$entity = $this->decorateAdvancedFields($purchase_order, $transformed_items);
|
||||
|
||||
$this->csv->insertOne($entity);
|
||||
}
|
||||
}
|
||||
|
||||
private function buildRow(PurchaseOrder $purchase_order) :array
|
||||
{
|
||||
$transformed_invoice = $this->purchase_order_transformer->transform($purchase_order);
|
||||
|
||||
$entity = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) {
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
if(!$keyval) {
|
||||
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
|
||||
}
|
||||
|
||||
if(!$keyval) {
|
||||
$keyval = $key;
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $transformed_invoice)) {
|
||||
$entity[$keyval] = $transformed_invoice[$key];
|
||||
} elseif (array_key_exists($keyval, $transformed_invoice)) {
|
||||
$entity[$keyval] = $transformed_invoice[$keyval];
|
||||
} else {
|
||||
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->decorateAdvancedFields($purchase_order, $entity);
|
||||
}
|
||||
|
||||
private function decorateAdvancedFields(PurchaseOrder $purchase_order, array $entity) :array
|
||||
{
|
||||
if (in_array('currency_id', $this->input['report_keys'])) {
|
||||
$entity['currency'] = $purchase_order->vendor->currency() ? $purchase_order->vendor->currency()->code : $purchase_order->company->currency()->code;
|
||||
}
|
||||
|
||||
if(array_key_exists('type', $entity)) {
|
||||
$entity['type'] = $purchase_order->typeIdString($entity['type']);
|
||||
}
|
||||
|
||||
if(array_key_exists('tax_category', $entity)) {
|
||||
$entity['tax_category'] = $purchase_order->taxTypeString($entity['tax_category']);
|
||||
}
|
||||
|
||||
if($this->force_keys) {
|
||||
$entity['vendor'] = $purchase_order->vendor->present()->name();
|
||||
$entity['vendor_id_number'] = $purchase_order->vendor->id_number;
|
||||
$entity['vendor_number'] = $purchase_order->vendor->number;
|
||||
$entity['status'] = $purchase_order->stringStatus($purchase_order->status_id);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
172
app/Export/CSV/VendorExport.php
Normal file
172
app/Export/CSV/VendorExport.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Export\CSV;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Company;
|
||||
use App\Transformers\VendorContactTransformer;
|
||||
use App\Transformers\VendorTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use League\Csv\Writer;
|
||||
|
||||
class VendorExport extends BaseExport
|
||||
{
|
||||
private $company;
|
||||
|
||||
private $vendor_transformer;
|
||||
|
||||
private $contact_transformer;
|
||||
|
||||
public Writer $csv;
|
||||
|
||||
public string $date_key = 'created_at';
|
||||
|
||||
public array $entity_keys = [
|
||||
'address1' => 'vendor.address1',
|
||||
'address2' => 'vendor.address2',
|
||||
'city' => 'vendor.city',
|
||||
'country' => 'vendor.country_id',
|
||||
'custom_value1' => 'vendor.custom_value1',
|
||||
'custom_value2' => 'vendor.custom_value2',
|
||||
'custom_value3' => 'vendor.custom_value3',
|
||||
'custom_value4' => 'vendor.custom_value4',
|
||||
'id_number' => 'vendor.id_number',
|
||||
'name' => 'vendor.name',
|
||||
'number' => 'vendor.number',
|
||||
'phone' => 'vendor.phone',
|
||||
'postal_code' => 'vendor.postal_code',
|
||||
'private_notes' => 'vendor.private_notes',
|
||||
'public_notes' => 'vendor.public_notes',
|
||||
'state' => 'vendor.state',
|
||||
'vat_number' => 'vendor.vat_number',
|
||||
'website' => 'vendor.website',
|
||||
'currency' => 'vendor.currency',
|
||||
'first_name' => 'vendor_contact.first_name',
|
||||
'last_name' => 'vendor_contact.last_name',
|
||||
'contact_phone' => 'vendor_contact.phone',
|
||||
'contact_custom_value1' => 'vendor_contact.custom_value1',
|
||||
'contact_custom_value2' => 'vendor_contact.custom_value2',
|
||||
'contact_custom_value3' => 'vendor_contact.custom_value3',
|
||||
'contact_custom_value4' => 'vendor_contact.custom_value4',
|
||||
'email' => 'vendor_contact.email',
|
||||
'status' => 'vendor.status'
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
'vendor.country_id',
|
||||
'vendor.currency',
|
||||
];
|
||||
|
||||
public array $forced_keys = [
|
||||
// 'vendor.status'
|
||||
];
|
||||
|
||||
public function __construct(Company $company, array $input)
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->input = $input;
|
||||
$this->vendor_transformer = new VendorTransformer();
|
||||
$this->contact_transformer = new VendorContactTransformer();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
App::forgetInstance('translator');
|
||||
App::setLocale($this->company->locale());
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
//load the CSV document from a string
|
||||
$this->csv = Writer::createFromString();
|
||||
|
||||
if (count($this->input['report_keys']) == 0) {
|
||||
$this->input['report_keys'] = array_values($this->entity_keys);
|
||||
}
|
||||
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Vendor::query()->with('contacts')
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
$query->cursor()
|
||||
->each(function ($vendor) {
|
||||
$this->csv->insertOne($this->buildRow($vendor));
|
||||
});
|
||||
|
||||
return $this->csv->toString();
|
||||
}
|
||||
|
||||
private function buildRow(Vendor $vendor) :array
|
||||
{
|
||||
$transformed_contact = false;
|
||||
|
||||
$transformed_vendor = $this->vendor_transformer->transform($vendor);
|
||||
|
||||
if ($contact = $vendor->contacts()->first()) {
|
||||
$transformed_contact = $this->contact_transformer->transform($contact);
|
||||
}
|
||||
|
||||
$entity = [];
|
||||
|
||||
foreach (array_values($this->input['report_keys']) as $key) {
|
||||
$parts = explode('.', $key);
|
||||
|
||||
$keyval = array_search($key, $this->entity_keys);
|
||||
|
||||
if (is_array($parts) && $parts[0] == 'vendor' && array_key_exists($parts[1], $transformed_vendor)) {
|
||||
$entity[$keyval] = $transformed_vendor[$parts[1]];
|
||||
} elseif (is_array($parts) && $parts[0] == 'vendor_contact' && array_key_exists($parts[1], $transformed_contact)) {
|
||||
$entity[$keyval] = $transformed_contact[$parts[1]];
|
||||
} else {
|
||||
$entity[$keyval] = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $this->decorateAdvancedFields($vendor, $entity);
|
||||
}
|
||||
|
||||
private function decorateAdvancedFields(Vendor $vendor, array $entity) :array
|
||||
{
|
||||
if (in_array('vendor.country_id', $this->input['report_keys'])) {
|
||||
$entity['country'] = $vendor->country ? ctrans("texts.country_{$vendor->country->name}") : '';
|
||||
}
|
||||
|
||||
if (in_array('vendor.currency', $this->input['report_keys'])) {
|
||||
$entity['currency'] = $vendor->currency() ? $vendor->currency()->code : $vendor->company->currency()->code;
|
||||
}
|
||||
|
||||
$entity['status'] = $this->calculateStatus($vendor);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
private function calculateStatus($vendor)
|
||||
{
|
||||
if ($vendor->is_deleted) {
|
||||
return ctrans('texts.deleted');
|
||||
}
|
||||
|
||||
if ($vendor->deleted_at) {
|
||||
return ctrans('texts.archived');
|
||||
}
|
||||
|
||||
return ctrans('texts.active');
|
||||
}
|
||||
}
|
@ -55,6 +55,10 @@ class InvoiceFilters extends QueryFilters
|
||||
$this->builder->where(function ($query) use ($status_parameters) {
|
||||
$invoice_filters = [];
|
||||
|
||||
if (in_array('draft', $status_parameters)) {
|
||||
$invoice_filters[] = Invoice::STATUS_DRAFT;
|
||||
}
|
||||
|
||||
if (in_array('paid', $status_parameters)) {
|
||||
$invoice_filters[] = Invoice::STATUS_PAID;
|
||||
}
|
||||
@ -131,19 +135,6 @@ class InvoiceFilters extends QueryFilters
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function without_deleted_clients(): Builder
|
||||
{
|
||||
return $this->builder->whereHas('client', function ($query) {
|
||||
$query->where('is_deleted', 0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
* @return Builder
|
||||
|
@ -288,6 +288,33 @@ abstract class QueryFilters
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function without_deleted_clients(): Builder
|
||||
{
|
||||
return $this->builder->where(function ($query) {
|
||||
$query->whereHas('client', function ($sub_query) {
|
||||
$sub_query->where('is_deleted', 0);
|
||||
})->orWhere('client_id', null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function without_deleted_vendors(): Builder
|
||||
{
|
||||
return $this->builder->where(function ($query) {
|
||||
$query->whereHas('vendor', function ($sub_query) {
|
||||
$sub_query->where('is_deleted', 0);
|
||||
})->orWhere('vendor_id', null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function with(string $value = ''): Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
|
@ -91,47 +91,7 @@ class ActivityController extends BaseController
|
||||
->orderBy('created_at', 'DESC')
|
||||
->company()
|
||||
->take($default_activities);
|
||||
|
||||
// if ($request->has('react')) {
|
||||
|
||||
// /** @var \App\Models\User auth()->user() */
|
||||
// $user = auth()->user();
|
||||
|
||||
// if (!$user->isAdmin()) {
|
||||
// $activities->where('user_id', auth()->user()->id);
|
||||
// }
|
||||
|
||||
// $system = ctrans('texts.system');
|
||||
|
||||
// $data = $activities->cursor()->map(function ($activity) {
|
||||
|
||||
// $arr =
|
||||
// [
|
||||
// 'client' => $activity->client ? $activity->client : '',
|
||||
// 'contact' => $activity->client ? $activity->contact : '',
|
||||
// 'quote' => $activity->quote ? $activity->quote : '',
|
||||
// 'user' => $activity->user ? $activity->user : '',
|
||||
// 'expense' => $activity->expense ? $activity->expense : '',
|
||||
// 'invoice' => $activity->invoice ? $activity->invoice : '',
|
||||
// 'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice : '',
|
||||
// 'payment' => $activity->payment ? $activity->payment : '',
|
||||
// 'credit' => $activity->credit ? $activity->credit : '',
|
||||
// 'task' => $activity->task ? $activity->task : '',
|
||||
// 'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||
// 'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
||||
// 'subscription' => $activity->subscription ? $activity->subscription : '',
|
||||
// 'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||
// 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense : '',
|
||||
// ];
|
||||
|
||||
// $activity_array = $activity->toArray();
|
||||
|
||||
// return array_merge($arr, $activity_array);
|
||||
// });
|
||||
|
||||
// return response()->json(['data' => $data->toArray()], 200);
|
||||
// }
|
||||
// else
|
||||
|
||||
if($request->has('reactv2')) {
|
||||
|
||||
/** @var \App\Models\User auth()->user() */
|
||||
|
@ -11,22 +11,29 @@
|
||||
|
||||
namespace App\Http\Controllers\ClientPortal;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasViewed;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ShowInvoiceRequest;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ShowInvoicesRequest;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Events\Invoice\InvoiceWasViewed;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ShowInvoiceRequest;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ShowInvoicesRequest;
|
||||
use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
@ -77,6 +84,31 @@ class InvoiceController extends Controller
|
||||
return $this->render('invoices.show', $data);
|
||||
}
|
||||
|
||||
public function showBlob($hash)
|
||||
{
|
||||
$data = Cache::pull($hash);
|
||||
|
||||
match($data['entity_type']){
|
||||
'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']),
|
||||
'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']),
|
||||
'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']),
|
||||
'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']),
|
||||
};
|
||||
|
||||
$file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
|
||||
|
||||
// $headers = ['Content-Type' => 'application/pdf'];
|
||||
// $entity_string = $data['entity_type'];
|
||||
// $file_name = $invitation->{$entity_string}->numberFormatter().'.pdf';
|
||||
// return response()->streamDownload(function () use ($file) {
|
||||
// echo $file;
|
||||
// }, $file_name, $headers);
|
||||
|
||||
$headers = ['Content-Type' => 'application/pdf'];
|
||||
return response()->make($file, 200, $headers);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay one or more invoices.
|
||||
*
|
||||
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Reports;
|
||||
|
||||
use App\Export\CSV\PurchaseOrderItemExport;
|
||||
use App\Http\Controllers\BaseController;
|
||||
use App\Http\Requests\Report\GenericReportRequest;
|
||||
use App\Jobs\Report\SendToAdmin;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class PurchaseOrderItemReportController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
private string $filename = 'purchase_order_items.csv';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __invoke(GenericReportRequest $request)
|
||||
{
|
||||
if ($request->has('send_email') && $request->get('send_email')) {
|
||||
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename);
|
||||
|
||||
return response()->json(['message' => 'working...'], 200);
|
||||
}
|
||||
// expect a list of visible fields, or use the default
|
||||
|
||||
$export = new PurchaseOrderItemExport(auth()->user()->company(), $request->all());
|
||||
|
||||
$csv = $export->run();
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'attachment',
|
||||
'Content-Type' => 'text/csv',
|
||||
];
|
||||
|
||||
return response()->streamDownload(function () use ($csv) {
|
||||
echo $csv;
|
||||
}, $this->filename, $headers);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* PurchaseOrder Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. PurchaseOrder Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Reports;
|
||||
|
||||
use App\Export\CSV\PurchaseOrderExport;
|
||||
use App\Http\Controllers\BaseController;
|
||||
use App\Http\Requests\Report\GenericReportRequest;
|
||||
use App\Jobs\Report\SendToAdmin;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class PurchaseOrderReportController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
private string $filename = 'purchase_orders.csv';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __invoke(GenericReportRequest $request)
|
||||
{
|
||||
if ($request->has('send_email') && $request->get('send_email')) {
|
||||
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderExport::class, $this->filename);
|
||||
|
||||
return response()->json(['message' => 'working...'], 200);
|
||||
}
|
||||
// expect a list of visible fields, or use the default
|
||||
|
||||
$export = new PurchaseOrderExport(auth()->user()->company(), $request->all());
|
||||
|
||||
$csv = $export->run();
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'attachment',
|
||||
'Content-Type' => 'text/csv',
|
||||
];
|
||||
|
||||
return response()->streamDownload(function () use ($csv) {
|
||||
echo $csv;
|
||||
}, $this->filename, $headers);
|
||||
}
|
||||
}
|
@ -29,37 +29,6 @@ class RecurringInvoiceReportController extends BaseController
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/reports/recurring_invoices",
|
||||
* operationId="getRecurringInvoiceReport",
|
||||
* tags={"reports"},
|
||||
* summary="Recurring Invoice reports",
|
||||
* description="Export recurring invoice reports",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/GenericReportSchema")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function __invoke(GenericReportRequest $request)
|
||||
{
|
||||
if ($request->has('send_email') && $request->get('send_email')) {
|
||||
|
53
app/Http/Controllers/Reports/VendorReportController.php
Normal file
53
app/Http/Controllers/Reports/VendorReportController.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Reports;
|
||||
|
||||
use App\Export\CSV\VendorExport;
|
||||
use App\Http\Controllers\BaseController;
|
||||
use App\Http\Requests\Report\GenericReportRequest;
|
||||
use App\Jobs\Report\SendToAdmin;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class VendorReportController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
private string $filename = 'vendors.csv';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __invoke(GenericReportRequest $request)
|
||||
{
|
||||
if ($request->has('send_email') && $request->get('send_email')) {
|
||||
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), VendorExport::class, $this->filename);
|
||||
|
||||
return response()->json(['message' => 'working...'], 200);
|
||||
}
|
||||
// expect a list of visible fields, or use the default
|
||||
|
||||
$export = new VendorExport(auth()->user()->company(), $request->all());
|
||||
|
||||
$csv = $export->run();
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'attachment',
|
||||
'Content-Type' => 'text/csv',
|
||||
];
|
||||
|
||||
return response()->streamDownload(function () use ($csv) {
|
||||
echo $csv;
|
||||
}, $this->filename, $headers);
|
||||
}
|
||||
}
|
@ -11,21 +11,24 @@
|
||||
|
||||
namespace App\Http\Controllers\VendorPortal;
|
||||
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\View\View;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
|
||||
use App\Jobs\Invoice\InjectSignature;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrdersRequest;
|
||||
use App\Jobs\Invoice\InjectSignature;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\View\View;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
|
||||
|
||||
class PurchaseOrderController extends Controller
|
||||
{
|
||||
@ -108,6 +111,28 @@ class PurchaseOrderController extends Controller
|
||||
return $this->render('purchase_orders.show', $data);
|
||||
}
|
||||
|
||||
public function showBlob($hash)
|
||||
{
|
||||
$data = Cache::pull($hash);
|
||||
|
||||
$invitation = PurchaseOrderInvitation::withTrashed()->find($data['invitation_id']);
|
||||
|
||||
$file = (new CreatePurchaseOrderPdf($invitation, $invitation->company->db))->rawPdf();
|
||||
|
||||
// $headers = ['Content-Type' => 'application/pdf'];
|
||||
// $entity_string = $data['entity_type'];
|
||||
// $file_name = $invitation->{$entity_string}->numberFormatter().'.pdf';
|
||||
// return response()->streamDownload(function () use ($file) {
|
||||
// echo $file;
|
||||
// }, $file_name, $headers);
|
||||
|
||||
$headers = ['Content-Type' => 'application/pdf'];
|
||||
return response()->make($file, 200, $headers);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function sidebarMenu() :array
|
||||
{
|
||||
$enabled_modules = auth()->guard('vendor')->user()->company->enabled_modules;
|
||||
|
@ -16,6 +16,7 @@ use App\Utils\Number;
|
||||
use Livewire\Component;
|
||||
use App\Utils\HtmlEngine;
|
||||
use App\Libraries\MultiDB;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Utils\VendorHtmlEngine;
|
||||
use App\Models\CreditInvitation;
|
||||
@ -23,6 +24,7 @@ use App\Services\Pdf\PdfBuilder;
|
||||
use App\Services\Pdf\PdfService;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Services\Pdf\PdfDesigner;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Services\Pdf\PdfConfiguration;
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
@ -48,6 +50,12 @@ class PdfSlot extends Component
|
||||
|
||||
protected $listeners = ['viewportChanged' => 'getPdf'];
|
||||
|
||||
public $show_cost = true;
|
||||
|
||||
public $show_quantity = true;
|
||||
|
||||
public $route_entity = 'client';
|
||||
|
||||
public function mount()
|
||||
{
|
||||
MultiDB::setDb($this->db);
|
||||
@ -55,7 +63,21 @@ class PdfSlot extends Component
|
||||
|
||||
public function getPdf()
|
||||
{
|
||||
$this->pdf = $this->entity->fullscreenPdfViewer($this->invitation);
|
||||
// $this->pdf = $this->entity->fullscreenPdfViewer($this->invitation);
|
||||
|
||||
$blob = [
|
||||
'entity_type' => $this->resolveEntityType(),
|
||||
'entity_id' => $this->entity->id,
|
||||
'invitation_id' => $this->invitation->id,
|
||||
'download' => false,
|
||||
];
|
||||
|
||||
$hash = Str::random(64);
|
||||
|
||||
Cache::put($hash, $blob, now()->addMinutes(2));
|
||||
|
||||
$this->pdf = $hash;
|
||||
|
||||
}
|
||||
|
||||
public function downloadPdf()
|
||||
@ -78,10 +100,19 @@ class PdfSlot extends Component
|
||||
|
||||
public function render()
|
||||
{
|
||||
|
||||
$this->entity_type = $this->resolveEntityType();
|
||||
|
||||
$this->settings = $this->entity->client ? $this->entity->client->getMergedSettings() : $this->entity->company->settings;
|
||||
|
||||
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_columns);
|
||||
$this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_columns);
|
||||
|
||||
if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){
|
||||
$this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns);
|
||||
$this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_quote_columns);
|
||||
}
|
||||
|
||||
$this->html_variables = $this->entity->client ?
|
||||
(new HtmlEngine($this->invitation))->generateLabelsAndValues() :
|
||||
(new VendorHtmlEngine($this->invitation))->generateLabelsAndValues();
|
||||
@ -100,7 +131,6 @@ class PdfSlot extends Component
|
||||
'entity_details' => $this->getEntityDetails(),
|
||||
'user_details' => $this->getUserDetails(),
|
||||
'user_name' => $this->getUserName(),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
@ -243,6 +273,7 @@ class PdfSlot extends Component
|
||||
} elseif ($this->invitation instanceof RecurringInvoiceInvitation) {
|
||||
return 'recurring_invoice';
|
||||
} elseif ($this->invitation instanceof PurchaseOrderInvitation) {
|
||||
$this->route_entity = 'vendor';
|
||||
return 'purchase_order';
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,8 @@ class RequiredClientInfo extends Component
|
||||
}
|
||||
|
||||
if (Str::startsWith($field['name'], 'contact_')) {
|
||||
if (empty($this->contact->{$_field}) || is_null($this->contact->{$_field})) {
|
||||
|
||||
if (empty($this->contact->{$_field}) || is_null($this->contact->{$_field}) || str_contains($this->contact->{$_field}, '@example.com')) {
|
||||
$this->show_form = true;
|
||||
} else {
|
||||
$this->fields[$index]['filled'] = true;
|
||||
|
@ -71,6 +71,7 @@ class UpdateInvoiceRequest extends Request
|
||||
$rules['tax_name1'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name2'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
|
||||
$rules['status_id'] = 'bail|sometimes|not_in:5'; //do not all cancelled invoices to be modfified.
|
||||
|
||||
// not needed.
|
||||
// $rules['partial_due_date'] = 'bail|sometimes|required_unless:partial,0,null';
|
||||
@ -100,7 +101,8 @@ class UpdateInvoiceRequest extends Request
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'id' => ctrans('text.locked_invoice'),
|
||||
'id' => ctrans('texts.locked_invoice'),
|
||||
'status_id' => ctrans('texts.locked_invoice'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -69,13 +69,16 @@ class ValidCreditsRules implements Rule
|
||||
|
||||
if (! $cred) {
|
||||
$this->error_msg = ctrans('texts.credit_not_found');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cred->client_id != $this->input['client_id']) {
|
||||
$this->error_msg = ctrans('texts.invoices_dont_match_client');
|
||||
return false;
|
||||
}
|
||||
|
||||
if($cred->balance < $credit['amount']) {
|
||||
$this->error_msg = ctrans('texts.insufficient_credit_balance');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1173,11 +1173,26 @@ class Import implements ShouldQueue
|
||||
|
||||
unset($modified['id']);
|
||||
|
||||
|
||||
$credit = $credit_repository->save(
|
||||
$modified,
|
||||
CreditFactory::create($this->company->id, $modified['user_id'])
|
||||
);
|
||||
|
||||
if($credit->status_id == 4)
|
||||
{
|
||||
|
||||
$client = $credit->client;
|
||||
$client->balance -= $credit->balance;
|
||||
$client->credit_balance -= $credit->amount;
|
||||
$client->saveQuietly();
|
||||
|
||||
$credit->paid_to_date = $credit->amount;
|
||||
$credit->balance = 0;
|
||||
$credit->saveQuietly();
|
||||
|
||||
}
|
||||
|
||||
//remove credit balance from ledger
|
||||
if ($credit->balance > 0 && $credit->client->balance > 0) {
|
||||
$client = $credit->client;
|
||||
|
2
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
2
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
@ -188,7 +188,7 @@ class CreatePurchaseOrderPdf implements ShouldQueue
|
||||
}
|
||||
|
||||
if (config('ninja.log_pdf_html')) {
|
||||
info($maker->getCompiledHTML());
|
||||
nlog($maker->getCompiledHTML());
|
||||
}
|
||||
|
||||
$maker = null;
|
||||
|
@ -275,4 +275,19 @@ class Expense extends BaseModel
|
||||
return $this->belongsTo(BankTransaction::class);
|
||||
}
|
||||
|
||||
public function stringStatus()
|
||||
{
|
||||
if($this->is_deleted)
|
||||
return ctrans('texts.deleted');
|
||||
elseif($this->payment_date)
|
||||
return ctrans('texts.paid');
|
||||
elseif($this->invoice_id)
|
||||
return ctrans('texts.invoiced');
|
||||
elseif($this->should_be_invoiced)
|
||||
return ctrans('texts.pending');
|
||||
elseif($this->trashed())
|
||||
return ctrans('texts.archived');
|
||||
|
||||
return ctrans('texts.logged');
|
||||
}
|
||||
}
|
||||
|
@ -108,50 +108,6 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Vendor extends BaseModel
|
||||
|
@ -57,7 +57,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
if (Ninja::isSelfHost()) {
|
||||
return Limit::none();
|
||||
} else {
|
||||
return Limit::perMinute(50)->by($request->ip());
|
||||
return Limit::perMinute(30)->by($request->ip());
|
||||
}
|
||||
});
|
||||
|
||||
@ -89,6 +89,11 @@ class RouteServiceProvider extends ServiceProvider
|
||||
return Limit::perMinute(2)->by($request->ip());
|
||||
});
|
||||
|
||||
RateLimiter::for('portal', function (Request $request) {
|
||||
return Limit::perMinute(15)->by($request->ip());
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,6 +50,9 @@ class ActivityRepository extends BaseRepository
|
||||
$activity->{$key} = $value;
|
||||
}
|
||||
|
||||
if($entity->company)
|
||||
$activity->account_id = $entity->company->account_id;
|
||||
|
||||
if ($token_id = $this->getTokenId($event_vars)) {
|
||||
$activity->token_id = $token_id;
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ class HandleRestore extends AbstractService
|
||||
//cannot restore an invoice with a deleted payment
|
||||
foreach ($this->invoice->payments as $payment) {
|
||||
if (($this->invoice->paid_to_date == 0) && $payment->is_deleted) {
|
||||
$this->invoice->delete(); //set it back to deleted so that it can be restored from repository
|
||||
return $this->invoice;
|
||||
}
|
||||
}
|
||||
@ -81,8 +80,8 @@ class HandleRestore extends AbstractService
|
||||
Paymentable::query()
|
||||
->withTrashed()
|
||||
->where('payment_id', $payment->id)
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
// ->where('paymentable_type', '=', 'invoices')
|
||||
// ->where('paymentable_id', $this->invoice->id)
|
||||
->update(['deleted_at' => null]);
|
||||
});
|
||||
|
||||
@ -102,6 +101,12 @@ class HandleRestore extends AbstractService
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('refunded'));
|
||||
|
||||
//14/07/2023 - do not include credits in the payment amount
|
||||
$this->adjustment_amount -= $payment->paymentables
|
||||
->where('paymentable_type', '=', 'App\Models\Credit')
|
||||
->sum(DB::raw('amount'));
|
||||
|
||||
}
|
||||
|
||||
$this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');
|
||||
@ -130,11 +135,16 @@ class HandleRestore extends AbstractService
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('refunded'));
|
||||
|
||||
$payment_adjustment -= $payment->paymentables
|
||||
->where('paymentable_type', '=', 'App\Models\Credit')
|
||||
->sum(DB::raw('amount'));
|
||||
|
||||
$payment->amount += $payment_adjustment;
|
||||
$payment->applied += $payment_adjustment;
|
||||
$payment->is_deleted = false;
|
||||
$payment->restore();
|
||||
$payment->saveQuietly();
|
||||
|
||||
});
|
||||
|
||||
return $this;
|
||||
|
@ -11,11 +11,12 @@
|
||||
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Jobs\Inventory\AdjustProductInventory;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Services\AbstractService;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Jobs\Inventory\AdjustProductInventory;
|
||||
|
||||
class MarkInvoiceDeleted extends AbstractService
|
||||
{
|
||||
@ -94,6 +95,11 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('refunded'));
|
||||
|
||||
//14-07-2023 - Do not include credits in the payment adjustment.
|
||||
$payment_adjustment -= $payment->paymentables
|
||||
->where('paymentable_type', '=', 'App\Models\Credit')
|
||||
->sum(DB::raw('amount'));
|
||||
|
||||
$payment->amount -= $payment_adjustment;
|
||||
$payment->applied -= $payment_adjustment;
|
||||
$payment->save();
|
||||
|
@ -109,6 +109,8 @@ class DeletePayment
|
||||
$paymentable_invoice->service()
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
$paymentable_invoice->delete();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -274,6 +274,10 @@ trait DesignHelpers
|
||||
// Some variables don't map 1:1 to table columns. This gives us support for such cases.
|
||||
$aliases = [
|
||||
'$quote.balance_due' => 'partial',
|
||||
'$purchase_order.po_number' => 'number',
|
||||
'$purchase_order.total' => 'amount',
|
||||
'$purchase_order.due_date' => 'due_date',
|
||||
'$purchase_order.balance_due' => 'balance_due',
|
||||
];
|
||||
|
||||
try {
|
||||
|
@ -132,7 +132,7 @@ class Ninja
|
||||
'ip' => $ip,
|
||||
'token' => request()->header('X-API-TOKEN'),
|
||||
'is_system' => app()->runningInConsole(),
|
||||
'user_id' => $user_id,
|
||||
'user_id' => ($ip == '127.0.0.1') ? null : $user_id,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -133,16 +133,18 @@ class VendorHtmlEngine
|
||||
$data['$partial_due_date'] = ['value' => $this->translateDate($this->entity->partial_due_date, $this->company->date_format(), $this->company->locale()) ?: ' ', 'label' => ctrans('texts.'.$this->entity_string.'_due_date')];
|
||||
|
||||
$data['$dueDate'] = &$data['$due_date'];
|
||||
$data['$purchase_order.due_date'] = &$data['$due_date'];
|
||||
|
||||
$data['$payment_due'] = ['value' => $this->translateDate($this->entity->due_date, $this->company->date_format(), $this->company->locale()) ?: ' ', 'label' => ctrans('texts.payment_due')];
|
||||
$data['$poNumber'] = ['value' => $this->entity->po_number, 'label' => ctrans('texts.po_number')];
|
||||
$data['$purchase_order.po_number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.po_number')];
|
||||
|
||||
$data['$poNumber'] = &$data['$purchase_order.po_number'];
|
||||
|
||||
$data['$entity.datetime'] = ['value' => $this->formatDatetime($this->entity->created_at, $this->company->date_format()), 'label' => ctrans('texts.date')];
|
||||
|
||||
$data['$po_number'] = &$data['$poNumber'];
|
||||
$data['$status_logo'] = ['value' => ' ', 'label' => ' '];
|
||||
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.purchase_order')];
|
||||
$data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.purchase_order_number')];
|
||||
$data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.number')];
|
||||
$data['$number_short'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.purchase_order_number_short')];
|
||||
$data['$entity.terms'] = ['value' => Helpers::processReservedKeywords(\nl2br($this->entity->terms), $this->company) ?: '', 'label' => ctrans('texts.invoice_terms')];
|
||||
$data['$terms'] = &$data['$entity.terms'];
|
||||
@ -155,7 +157,6 @@ class VendorHtmlEngine
|
||||
|
||||
$data['$purchase_order.number'] = &$data['$number'];
|
||||
$data['$purchase_order.date'] = &$data['$date'];
|
||||
$data['$purchase_order.po_number'] = &$data['$poNumber'];
|
||||
$data['$purchase_order.due_date'] = &$data['$due_date'];
|
||||
$data['$entity_issued_to'] = ['value' => '', 'label' => ctrans("texts.purchase_order_issued_to")];
|
||||
|
||||
@ -189,8 +190,9 @@ class VendorHtmlEngine
|
||||
}
|
||||
}
|
||||
|
||||
// $data['$balance_due'] = $data['$balance_due'];
|
||||
$data['$outstanding'] = &$data['$balance_due'];
|
||||
$data['$purchase_order.balance_due'] = &$data['$balance_due'];
|
||||
|
||||
$data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->vendor) ?: ' ', 'label' => ctrans('texts.partial_due')];
|
||||
$data['$partial'] = &$data['$partial_due'];
|
||||
|
||||
|
@ -95,7 +95,8 @@
|
||||
"turbo124/predis": "1.1.11",
|
||||
"twilio/sdk": "^6.40",
|
||||
"webpatser/laravel-countries": "dev-master#75992ad",
|
||||
"wepay/php-sdk": "^0.3"
|
||||
"wepay/php-sdk": "^0.3",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php": "^8.1",
|
||||
|
255
composer.lock
generated
255
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "135eec9ab7a1e8c0ab3820ff27cf1488",
|
||||
"content-hash": "be16996524279f340c44e2f6c9a0ba53",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adrienrn/php-mimetyper",
|
||||
@ -424,16 +424,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.269.0",
|
||||
"version": "3.275.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78"
|
||||
"reference": "54dcef3349c81b46c0f5f6e54b5f9bfb5db19903"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
|
||||
"reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/54dcef3349c81b46c0f5f6e54b5f9bfb5db19903",
|
||||
"reference": "54dcef3349c81b46c0f5f6e54b5f9bfb5db19903",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -445,7 +445,8 @@
|
||||
"guzzlehttp/promises": "^1.4.0",
|
||||
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
|
||||
"mtdowling/jmespath.php": "^2.6",
|
||||
"php": ">=5.5"
|
||||
"php": ">=5.5",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"andrewsville/php-token-reflection": "^1.4",
|
||||
@ -462,7 +463,6 @@
|
||||
"paragonie/random_compat": ">= 2",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5",
|
||||
"psr/cache": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"sebastian/comparator": "^1.2.3 || ^4.0",
|
||||
"yoast/phpunit-polyfills": "^1.0"
|
||||
@ -513,9 +513,9 @@
|
||||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.269.0"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.275.7"
|
||||
},
|
||||
"time": "2023-04-26T18:21:04+00:00"
|
||||
"time": "2023-07-13T18:21:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@ -2485,16 +2485,16 @@
|
||||
},
|
||||
{
|
||||
"name": "google/apiclient-services",
|
||||
"version": "v0.307.0",
|
||||
"version": "v0.308.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/googleapis/google-api-php-client-services.git",
|
||||
"reference": "5f7d451aa912355dda61aa29ac3a4afa8b252467"
|
||||
"reference": "85cf00383e6bf6eca131bd3261b7859ea418a578"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/5f7d451aa912355dda61aa29ac3a4afa8b252467",
|
||||
"reference": "5f7d451aa912355dda61aa29ac3a4afa8b252467",
|
||||
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/85cf00383e6bf6eca131bd3261b7859ea418a578",
|
||||
"reference": "85cf00383e6bf6eca131bd3261b7859ea418a578",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2523,9 +2523,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
|
||||
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.307.0"
|
||||
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.308.0"
|
||||
},
|
||||
"time": "2023-07-01T01:02:13+00:00"
|
||||
"time": "2023-07-09T01:06:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "google/auth",
|
||||
@ -4554,16 +4554,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/socialite",
|
||||
"version": "v5.6.3",
|
||||
"version": "v5.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/socialite.git",
|
||||
"reference": "00ea7f8630673ea49304fc8a9fca5a64eb838c7e"
|
||||
"reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/00ea7f8630673ea49304fc8a9fca5a64eb838c7e",
|
||||
"reference": "00ea7f8630673ea49304fc8a9fca5a64eb838c7e",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/f5996f499e14db15407201a6bfbaba3ce6ce736c",
|
||||
"reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4620,7 +4620,7 @@
|
||||
"issues": "https://github.com/laravel/socialite/issues",
|
||||
"source": "https://github.com/laravel/socialite"
|
||||
},
|
||||
"time": "2023-06-06T13:42:43+00:00"
|
||||
"time": "2023-07-08T20:51:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
@ -5768,16 +5768,16 @@
|
||||
},
|
||||
{
|
||||
"name": "mollie/mollie-api-php",
|
||||
"version": "v2.57.0",
|
||||
"version": "v2.58.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mollie/mollie-api-php.git",
|
||||
"reference": "be201657b00a197e5238bbec81fad2a0fc0b83e4"
|
||||
"reference": "5120e5b3e4622a290b64acf87266ea47d10d7301"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/be201657b00a197e5238bbec81fad2a0fc0b83e4",
|
||||
"reference": "be201657b00a197e5238bbec81fad2a0fc0b83e4",
|
||||
"url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/5120e5b3e4622a290b64acf87266ea47d10d7301",
|
||||
"reference": "5120e5b3e4622a290b64acf87266ea47d10d7301",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -5854,9 +5854,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mollie/mollie-api-php/issues",
|
||||
"source": "https://github.com/mollie/mollie-api-php/tree/v2.57.0"
|
||||
"source": "https://github.com/mollie/mollie-api-php/tree/v2.58.0"
|
||||
},
|
||||
"time": "2023-06-23T09:09:15+00:00"
|
||||
"time": "2023-07-11T12:01:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "moneyphp/money",
|
||||
@ -7280,16 +7280,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-http/discovery",
|
||||
"version": "1.19.0",
|
||||
"version": "1.19.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-http/discovery.git",
|
||||
"reference": "1856a119a0b0ba8da8b5c33c080aa7af8fac25b4"
|
||||
"reference": "57f3de01d32085fea20865f9b16fb0e69347c39e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-http/discovery/zipball/1856a119a0b0ba8da8b5c33c080aa7af8fac25b4",
|
||||
"reference": "1856a119a0b0ba8da8b5c33c080aa7af8fac25b4",
|
||||
"url": "https://api.github.com/repos/php-http/discovery/zipball/57f3de01d32085fea20865f9b16fb0e69347c39e",
|
||||
"reference": "57f3de01d32085fea20865f9b16fb0e69347c39e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -7352,9 +7352,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-http/discovery/issues",
|
||||
"source": "https://github.com/php-http/discovery/tree/1.19.0"
|
||||
"source": "https://github.com/php-http/discovery/tree/1.19.1"
|
||||
},
|
||||
"time": "2023-06-19T08:45:36+00:00"
|
||||
"time": "2023-07-11T07:02:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/guzzle7-adapter",
|
||||
@ -7844,16 +7844,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.20",
|
||||
"version": "3.0.21",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67"
|
||||
"reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67",
|
||||
"reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1",
|
||||
"reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -7934,7 +7934,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.20"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.21"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -7950,7 +7950,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-13T06:30:34+00:00"
|
||||
"time": "2023-07-09T15:24:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
@ -8360,16 +8360,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "2.0",
|
||||
"version": "1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
|
||||
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
|
||||
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -8378,7 +8378,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -8393,7 +8393,7 @@
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
@ -8407,9 +8407,9 @@
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/2.0"
|
||||
"source": "https://github.com/php-fig/http-message/tree/1.1"
|
||||
},
|
||||
"time": "2023-04-04T09:54:51+00:00"
|
||||
"time": "2023-04-04T09:50:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
@ -15117,16 +15117,16 @@
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.15.2",
|
||||
"version": "2.15.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73"
|
||||
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
|
||||
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187",
|
||||
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -15176,7 +15176,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.15.2"
|
||||
"source": "https://github.com/filp/whoops/tree/2.15.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -15184,7 +15184,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-12T12:00:00+00:00"
|
||||
"time": "2023-07-13T12:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
@ -15392,79 +15392,6 @@
|
||||
},
|
||||
"time": "2023-02-16T20:00:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/dusk",
|
||||
"version": "v6.25.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/dusk.git",
|
||||
"reference": "25a595ac3dc82089a91af10dd23b0d58fd3f6d0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/dusk/zipball/25a595ac3dc82089a91af10dd23b0d58fd3f6d0b",
|
||||
"reference": "25a595ac3dc82089a91af10dd23b0d58fd3f6d0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"illuminate/console": "^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/support": "^6.0|^7.0|^8.0|^9.0",
|
||||
"nesbot/carbon": "^2.0",
|
||||
"php": "^7.2|^8.0",
|
||||
"php-webdriver/webdriver": "^1.9.0",
|
||||
"symfony/console": "^4.3|^5.0|^6.0",
|
||||
"symfony/finder": "^4.3|^5.0|^6.0",
|
||||
"symfony/process": "^4.3|^5.0|^6.0",
|
||||
"vlucas/phpdotenv": "^3.0|^4.0|^5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"orchestra/testbench": "^4.16|^5.17.1|^6.12.1|^7.0",
|
||||
"phpunit/phpunit": "^7.5.15|^8.4|^9.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pcntl": "Used to gracefully terminate Dusk when tests are running."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Dusk\\DuskServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Dusk\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Dusk provides simple end-to-end testing and browser automation.",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"testing",
|
||||
"webdriver"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/dusk/issues",
|
||||
"source": "https://github.com/laravel/dusk/tree/v6.25.2"
|
||||
},
|
||||
"time": "2022-09-29T09:37:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maximebf/debugbar",
|
||||
"version": "v1.18.2",
|
||||
@ -16067,72 +15994,6 @@
|
||||
},
|
||||
"time": "2022-02-21T01:04:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-webdriver/webdriver",
|
||||
"version": "1.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-webdriver/php-webdriver.git",
|
||||
"reference": "3ea4f924afb43056bf9c630509e657d951608563"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/3ea4f924afb43056bf9c630509e657d951608563",
|
||||
"reference": "3ea4f924afb43056bf9c630509e657d951608563",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"symfony/polyfill-mbstring": "^1.12",
|
||||
"symfony/process": "^5.0 || ^6.0"
|
||||
},
|
||||
"replace": {
|
||||
"facebook/webdriver": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ergebnis/composer-normalize": "^2.20.0",
|
||||
"ondram/ci-detector": "^4.0",
|
||||
"php-coveralls/php-coveralls": "^2.4",
|
||||
"php-mock/php-mock-phpunit": "^2.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"symfony/var-dumper": "^5.0 || ^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-SimpleXML": "For Firefox profile creation"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/Exception/TimeoutException.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Facebook\\WebDriver\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.",
|
||||
"homepage": "https://github.com/php-webdriver/php-webdriver",
|
||||
"keywords": [
|
||||
"Chromedriver",
|
||||
"geckodriver",
|
||||
"php",
|
||||
"selenium",
|
||||
"webdriver"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
|
||||
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.14.0"
|
||||
},
|
||||
"time": "2023-02-09T12:12:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "5.3.0",
|
||||
@ -16659,16 +16520,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.6.9",
|
||||
"version": "9.6.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "a9aceaf20a682aeacf28d582654a1670d8826778"
|
||||
"reference": "a6d351645c3fe5a30f5e86be6577d946af65a328"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778",
|
||||
"reference": "a9aceaf20a682aeacf28d582654a1670d8826778",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328",
|
||||
"reference": "a6d351645c3fe5a30f5e86be6577d946af65a328",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -16742,7 +16603,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.9"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -16758,7 +16619,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-11T06:13:56+00:00"
|
||||
"time": "2023-07-10T04:04:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
@ -15,8 +15,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => env('APP_VERSION','5.6.18'),
|
||||
'app_tag' => env('APP_TAG','5.6.18'),
|
||||
'app_version' => env('APP_VERSION','5.6.19'),
|
||||
'app_tag' => env('APP_TAG','5.6.19'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Currency;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$tb = Currency::find(21);
|
||||
|
||||
if($tb) {
|
||||
$tb->symbol = '฿';
|
||||
$tb->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -43,7 +43,7 @@ class CurrenciesSeeder extends Seeder
|
||||
['id' => 18, 'name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 19, 'name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 20, 'name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||
['id' => 21, 'name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 21, 'name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '฿', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 22, 'name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
['id' => 23, 'name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||
['id' => 24, 'name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||
|
@ -753,7 +753,7 @@ $LANG = array(
|
||||
'activity_7' => 'Klient :contact zobrazil fakturu :invoice pro :client',
|
||||
'activity_8' => ':user archivoval fakturu :invoice',
|
||||
'activity_9' => ':user smazal fakturu :invoice',
|
||||
'activity_10' => ':contact entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_11' => ':user změnil platbu :payment',
|
||||
'activity_12' => ':user archivoval platbu :payment',
|
||||
'activity_13' => ':user smazal platbu :payment',
|
||||
|
@ -5122,7 +5122,8 @@ $LANG = array(
|
||||
'lang_French - Swiss' => 'French - Swiss',
|
||||
'currency_swazi_lilangeni' => 'Swazi Lilangeni',
|
||||
'income' => 'Income',
|
||||
|
||||
'amount_received_help' => 'Enter a value here if the total amount received was MORE than the invoice amount, or when recording a payment with no invoices. Otherwise this field should be left blank.',
|
||||
'vendor_phone' => 'Vendor Phone',
|
||||
);
|
||||
|
||||
|
||||
|
@ -761,7 +761,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact viewed invoice :invoice for :client',
|
||||
'activity_8' => ':user archived invoice :invoice',
|
||||
'activity_9' => ':user deleted invoice :invoice',
|
||||
'activity_10' => ':contact entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_11' => ':user updated payment :payment',
|
||||
'activity_12' => ':user archived payment :payment',
|
||||
'activity_13' => ':user deleted payment :payment',
|
||||
|
@ -748,7 +748,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact a visualisé la facture :invoice pour :client',
|
||||
'activity_8' => ':user a archivé la facture :invoice',
|
||||
'activity_9' => ':user a supprimé la facture :invoice',
|
||||
'activity_10' => ':contact a saisi le paiement :payment de :payment_amount de la facture :invoice pour :client',
|
||||
'activity_10' => ':user a saisi le paiement :payment de :payment_amount de la facture :invoice pour :client',
|
||||
'activity_11' => ':user a mis à jour le paiement :payment',
|
||||
'activity_12' => ':user a archivé le paiement :payment',
|
||||
'activity_13' => ':user a supprimé le paiement :payment',
|
||||
@ -1433,7 +1433,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'payment_type_Swish' => 'Swish',
|
||||
'payment_type_Alipay' => 'Alipay',
|
||||
'payment_type_Sofort' => 'Sofort',
|
||||
'payment_type_SEPA' => 'SEPA Prélèvement automatique',
|
||||
'payment_type_SEPA' => 'Prélèvement automatique SEPA',
|
||||
'payment_type_Bitcoin' => 'Bitcoin',
|
||||
'payment_type_GoCardless' => 'GoCardless',
|
||||
'payment_type_Zelle' => 'Zelle',
|
||||
@ -2448,7 +2448,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
|
||||
'alipay' => 'Alipay',
|
||||
'sofort' => 'Sofort',
|
||||
'sepa' => 'SEPA Prélèvement automatique',
|
||||
'sepa' => 'Prélèvement automatique SEPA',
|
||||
'name_without_special_characters' => 'Veuillez entrer un nom en utilisant seulement les lettres de a à z et des espaces.',
|
||||
'enable_alipay' => 'Accepter Alipay',
|
||||
'enable_sofort' => 'Accepter les transferts d\'institutions bancaires de l\'Union européenne',
|
||||
@ -3130,7 +3130,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'number_padding' => 'Disposition du numéro',
|
||||
'general' => 'Général',
|
||||
'surcharge_field' => 'Champ Surcharge',
|
||||
'company_value' => 'Valeur de compagnie',
|
||||
'company_value' => 'Valeur de l\'entreprise',
|
||||
'credit_field' => 'Champ Crédit',
|
||||
'payment_field' => 'Champ Paiement',
|
||||
'group_field' => 'Champ Groupe',
|
||||
@ -3510,7 +3510,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'search_expenses' => 'Recherche de dépenses',
|
||||
'search_payments' => 'Recherche de paiements',
|
||||
'search_groups' => 'Recherche de groupes',
|
||||
'search_company' => 'Recherche d\'entreprises',
|
||||
'search_company' => 'Recherche d\'une entreprise',
|
||||
'cancelled_invoice' => 'La facture a été annulée',
|
||||
'cancelled_invoices' => 'Les factures ont été annulées',
|
||||
'reversed_invoice' => 'La facture a été inversée',
|
||||
@ -3972,8 +3972,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'account_balance' => 'Solde de compte',
|
||||
'thanks' => 'Merci',
|
||||
'minimum_required_payment' => 'Le paiement minimum requis est :amount',
|
||||
'under_payments_disabled' => 'La société ne tolère pas le sous-paiement.',
|
||||
'over_payments_disabled' => 'La société ne tolère pas le sur-paiement.',
|
||||
'under_payments_disabled' => 'L\'entreprise ne tolère pas le sous-paiement.',
|
||||
'over_payments_disabled' => 'L\'entreprise ne tolère pas le sur-paiement.',
|
||||
'saved_at' => 'Enregistré à :time',
|
||||
'credit_payment' => 'Le crédit a été appliqué à la facture :invoice_number',
|
||||
'credit_subject' => 'Nouveau crédit :credit de :account',
|
||||
@ -4109,7 +4109,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'migration_api_secret_notice' => 'Vous pouvez trouver API_SECRET dans le fichier .env ou Invoice Ninja v5. Si la propriété est manquante, laissez le champ vide.',
|
||||
'billing_coupon_notice' => 'Votre rabais sera appliqué au moment de régler votre facture.',
|
||||
'use_last_email' => 'Utiliser le dernier e-mail',
|
||||
'activate_company' => 'Activer la société',
|
||||
'activate_company' => 'Activer l\'entreprise',
|
||||
'activate_company_help' => 'Activez les courriels, les factures récurrentes et les notifications',
|
||||
'an_error_occurred_try_again' => 'Une erreur s\'est produite, veuillez réessayer',
|
||||
'please_first_set_a_password' => 'Veuillez d\'abord définir un mot de passe',
|
||||
@ -4242,9 +4242,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'giropay_law' => 'En saisissant vos information de client (tel que votre nom et numéro de compte), vous (le client) agréez à donner cette information volontairement.',
|
||||
'klarna' => 'Klarna',
|
||||
'eps' => 'EPS',
|
||||
'becs' => 'BECS Prélèvement automatique',
|
||||
'bacs' => 'Débit direct BACS',
|
||||
'payment_type_BACS' => 'Débit direct BACS',
|
||||
'becs' => 'Prélèvement automatique BECS',
|
||||
'bacs' => 'Prélèvement automatique BACS',
|
||||
'payment_type_BACS' => 'Prélèvement automatique BACS',
|
||||
'missing_payment_method' => 'Veuillez ajouter une méthode de paiement avant de payer.',
|
||||
'becs_mandate' => 'En fournissant vos coordonnées bancaires, vous acceptez <a class="underline" href="https://stripe.com/au-becs-dd-service-agreement/legal">l\'entente de service de requête de débit direct</a>, et autorisez Stripe Payments Australia Pty Ltd ACN 160 180 343 Direct Debit User ID number 507156 (“Stripe”) à prélever votre compte par le Bulk Electronic Clearing System (BECS) de la part du :company (“Merchant”) pour tout montant séparément communiqué à vous par le Marchand. Vous certifiez que vous êtes propriétaire du compte ou que vous êtes un signataire autorisé sur le compte indiqué plus haut.',
|
||||
'you_need_to_accept_the_terms_before_proceeding' => 'Vous devez accepter les conditions pour continuer.',
|
||||
@ -4257,12 +4257,12 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'browser_pay' => 'Google Pay, Apple Pay et Microsoft Pay',
|
||||
'no_available_methods' => 'Cartes de crédit introuvable sur cet appareil. <a href="https://invoiceninja.github.io/docs/payments#apple-pay-google-pay-microsoft-pay" target="_blank" class="underline">Plus d\'information.</a>',
|
||||
'gocardless_mandate_not_ready' => 'La demande de paiement n\'est pas prête. Veuillez essayer de nouveau plus tard.',
|
||||
'payment_type_instant_bank_pay' => 'Interac',
|
||||
'payment_type_instant_bank_pay' => 'Instant Bank Pay',
|
||||
'payment_type_iDEAL' => 'iDEAL',
|
||||
'payment_type_Przelewy24' => 'Przelewy24',
|
||||
'payment_type_Mollie Bank Transfer' => 'Virement bancaire Mollie',
|
||||
'payment_type_KBC/CBC' => 'KBC/CBC',
|
||||
'payment_type_Instant Bank Pay' => 'Interac',
|
||||
'payment_type_Instant Bank Pay' => 'Instant Bank Pay',
|
||||
'payment_type_Hosted Page' => 'Page hébergée',
|
||||
'payment_type_GiroPay' => 'GiroPay',
|
||||
'payment_type_EPS' => 'EPS',
|
||||
@ -4279,7 +4279,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'show_pdf_preview_help' => 'Afficher l\'aperçu PDF lors de la rédaction des factures',
|
||||
'print_pdf' => 'Imprimer le PDF',
|
||||
'remind_me' => 'Rappel',
|
||||
'instant_bank_pay' => 'Interac',
|
||||
'instant_bank_pay' => 'Instant Bank Pay',
|
||||
'click_selected' => 'Cliquer sur la sélection',
|
||||
'hide_preview' => 'Cacher l\'aperçu',
|
||||
'edit_record' => 'Modifier l\'enregistrement',
|
||||
@ -5111,7 +5111,10 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'admin_initiated_payments_help' => 'Permet la saisie d\'un paiement dans le portal d\'administration sans facture',
|
||||
'paid_date' => 'Date de paiement',
|
||||
'downloaded_entities' => 'Un courriel sera envoyé avec le ou les PDF',
|
||||
|
||||
'lang_French - Swiss' => 'Français - Suisse',
|
||||
'currency_swazi_lilangeni' => 'Lilangeni Eswatinien',
|
||||
'income' => 'Revenu',
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
@ -753,7 +753,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact が :client の請求書 :invoice を閲覧しました',
|
||||
'activity_8' => ':user は 請求書 :invoice をアーカイブしました。',
|
||||
'activity_9' => ':user は 請求書 :invoice をアーカイブしました。',
|
||||
'activity_10' => ':contact は、:client の請求書 :invoice に :payment_amount の支払い :payment を入力しました',
|
||||
'activity_10' => ':user は、:client の請求書 :invoice に :payment_amount の支払い :payment を入力しました',
|
||||
'activity_11' => ':user updated payment :payment',
|
||||
'activity_12' => ':user archived payment :payment',
|
||||
'activity_13' => ':user deleted payment :payment',
|
||||
|
@ -754,7 +754,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact viewed invoice :invoice for :client',
|
||||
'activity_8' => ':user archived invoice :invoice',
|
||||
'activity_9' => ':user deleted invoice :invoice',
|
||||
'activity_10' => ':contact entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_11' => ':user atnaujino mokėjimą :payment',
|
||||
'activity_12' => ':user archived payment :payment',
|
||||
'activity_13' => ':user deleted payment :payment',
|
||||
|
@ -754,7 +754,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact har sett fakturaen :invoice for :client',
|
||||
'activity_8' => ':user arkiverte faktura :invoice',
|
||||
'activity_9' => ':user slettet faktura :invoice',
|
||||
'activity_10' => ':contact la inn betaling :payment på :payment_amount',
|
||||
'activity_10' => ':user la inn betaling :payment på :payment_amount',
|
||||
'activity_11' => ':user oppdaterte betaling :payment',
|
||||
'activity_12' => ':user arkiverte betaling :payment',
|
||||
'activity_13' => ':user slettet betaling :payment',
|
||||
|
@ -751,7 +751,7 @@ $LANG = array(
|
||||
'activity_7' => ':contact viewed invoice :invoice for :client',
|
||||
'activity_8' => ':user ka arkivuar faturën :invoice',
|
||||
'activity_9' => ':user ka fshirë faturën :invoice',
|
||||
'activity_10' => ':contact entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_11' => ':user ka perditesuar pagesën :payment',
|
||||
'activity_12' => ':user ka arkivuar pagesën :payment',
|
||||
'activity_13' => ':user ka fshirë pagesën :payment',
|
||||
|
@ -753,7 +753,7 @@ adresine gönderildi. Müthiş tüm özelliklerin kilidini açmak için lütfen
|
||||
'activity_7' => ':contact viewed invoice :invoice for :client',
|
||||
'activity_8' => ':user :invoice nolu faturayı arşivledi',
|
||||
'activity_9' => ':user :invoice nolu faturayı sildi',
|
||||
'activity_10' => ':contact entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
|
||||
'activity_11' => ':user :payment tutarlı ödemeyi güncelledi',
|
||||
'activity_12' => ':user :payment tutarlı ödemeyi arşivledi',
|
||||
'activity_13' => ':user :payment tutarlı ödemeyi sildi',
|
||||
|
2
public/js/clients/invoices/payment.js
vendored
2
public/js/clients/invoices/payment.js
vendored
@ -77,6 +77,7 @@ var Payment = /*#__PURE__*/function () {
|
||||
}, {
|
||||
key: "displaySignature",
|
||||
value: function displaySignature() {
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
var displaySignatureModal = document.getElementById("displaySignatureModal");
|
||||
displaySignatureModal.removeAttribute("style");
|
||||
var signaturePad = new SignaturePad(document.getElementById("signature-pad"), {
|
||||
@ -91,7 +92,6 @@ var Payment = /*#__PURE__*/function () {
|
||||
key: "handle",
|
||||
value: function handle() {
|
||||
var _this2 = this;
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
document.querySelectorAll(".dropdown-gateway-button").forEach(function (element) {
|
||||
element.addEventListener("click", function () {
|
||||
if (!_this2.submitting) {
|
||||
|
5
public/js/clients/purchase_orders/accept.js
vendored
5
public/js/clients/purchase_orders/accept.js
vendored
@ -54,7 +54,12 @@ var Accept = /*#__PURE__*/function () {
|
||||
value: function handle() {
|
||||
var _this = this;
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
document.getElementById("close-button").addEventListener('click', function () {
|
||||
var approveButton = document.getElementById("approve-button");
|
||||
if (approveButton) approveButton.disabled = false;
|
||||
});
|
||||
document.getElementById('approve-button').addEventListener('click', function () {
|
||||
console.log("accepted ");
|
||||
if (_this.shouldDisplaySignature && _this.shouldDisplayTerms) {
|
||||
_this.displaySignature();
|
||||
document.getElementById('signature-next-step').addEventListener('click', function () {
|
||||
|
6
public/js/clients/quotes/approve.js
vendored
6
public/js/clients/quotes/approve.js
vendored
@ -61,12 +61,14 @@ var Approve = /*#__PURE__*/function () {
|
||||
value: function handle() {
|
||||
var _this = this;
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
document.getElementById("close_button").addEventListener('click', function () {
|
||||
document.getElementById("close-button").addEventListener('click', function () {
|
||||
var approveButton = document.getElementById("approve-button");
|
||||
console.log('close button');
|
||||
if (approveButton) approveButton.disabled = false;
|
||||
});
|
||||
document.getElementById("hide_close").addEventListener('click', function () {
|
||||
document.getElementById("close-terms-button").addEventListener('click', function () {
|
||||
var approveButton = document.getElementById("approve-button");
|
||||
console.log('close terms-button');
|
||||
if (approveButton) approveButton.disabled = false;
|
||||
});
|
||||
document.getElementById('approve-button').addEventListener('click', function () {
|
||||
|
@ -9,13 +9,13 @@
|
||||
"/js/clients/payments/stripe-bacs.js": "/js/clients/payments/stripe-bacs.js?id=a82927936510bbecc60de3e9742f9739",
|
||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=b7601721afa9599518ba894a0f88f947",
|
||||
"/js/clients/purchase_orders/action-selectors.js": "/js/clients/purchase_orders/action-selectors.js?id=b9c510dffa8420879983f04cd521564c",
|
||||
"/js/clients/purchase_orders/accept.js": "/js/clients/purchase_orders/accept.js?id=d13b4a7934c9f7ddf2154f8f233843f7",
|
||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=1bd5f983e7d9394fe9ac603dea94e901",
|
||||
"/js/clients/purchase_orders/accept.js": "/js/clients/purchase_orders/accept.js?id=e9040b9f5e9bbf5d04b8a02a284d0481",
|
||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=edeab1566d21cb93901d571bdcbb7c30",
|
||||
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=f0252b9b140b667794c252ae200cd844",
|
||||
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=360b39d82a1a7dd90a8351776fbd9edb",
|
||||
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=a2168c43060a7de40da20b5fc599bcab",
|
||||
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=4158693089b29ee8e13cb7d9ce4480a9",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=4e596cec23cdd6487534e6ed5499d791",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=4091846cf28ded010380cc2678fbe831",
|
||||
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=bfa116c1df42c641bc7a3ff4fa8d50dd",
|
||||
"/js/setup/setup.js": "/js/setup/setup.js?id=086b9e114b0b9ee01f909d686f489162",
|
||||
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=cf50b5ba1fcd1d184bf0c10d710672c8",
|
||||
|
3
resources/js/clients/invoices/payment.js
vendored
3
resources/js/clients/invoices/payment.js
vendored
@ -84,6 +84,8 @@ class Payment {
|
||||
}
|
||||
|
||||
displaySignature() {
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
|
||||
let displaySignatureModal = document.getElementById(
|
||||
"displaySignatureModal"
|
||||
);
|
||||
@ -104,7 +106,6 @@ class Payment {
|
||||
}
|
||||
|
||||
handle() {
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
|
||||
document
|
||||
.querySelectorAll(".dropdown-gateway-button")
|
||||
|
11
resources/js/clients/purchase_orders/accept.js
vendored
11
resources/js/clients/purchase_orders/accept.js
vendored
@ -48,9 +48,20 @@ class Accept {
|
||||
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
|
||||
document.getElementById("close-button").addEventListener('click', () => {
|
||||
const approveButton = document.getElementById("approve-button");
|
||||
|
||||
if (approveButton)
|
||||
approveButton.disabled = false;
|
||||
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById('approve-button')
|
||||
.addEventListener('click', () => {
|
||||
|
||||
console.log("accepted ");
|
||||
|
||||
if (this.shouldDisplaySignature && this.shouldDisplayTerms) {
|
||||
this.displaySignature();
|
||||
|
||||
|
11
resources/js/clients/quotes/approve.js
vendored
11
resources/js/clients/quotes/approve.js
vendored
@ -55,22 +55,27 @@ class Approve {
|
||||
|
||||
document.getElementById("signature-next-step").disabled = true;
|
||||
|
||||
document.getElementById("close_button").addEventListener('click', () => {
|
||||
document.getElementById("close-button").addEventListener('click', () => {
|
||||
const approveButton = document.getElementById("approve-button");
|
||||
|
||||
console.log('close button');
|
||||
|
||||
if(approveButton)
|
||||
approveButton.disabled = false;
|
||||
|
||||
});
|
||||
|
||||
document.getElementById("hide_close").addEventListener('click', () => {
|
||||
document.getElementById("close-terms-button").addEventListener('click', () => {
|
||||
const approveButton = document.getElementById("approve-button");
|
||||
|
||||
if(approveButton)
|
||||
console.log('close terms-button');
|
||||
|
||||
if (approveButton)
|
||||
approveButton.disabled = false;
|
||||
|
||||
});
|
||||
|
||||
|
||||
document
|
||||
.getElementById('approve-button')
|
||||
.addEventListener('click', () => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
@push('head')
|
||||
<style>
|
||||
|
||||
table, th, td {
|
||||
@ -26,6 +26,7 @@ span {
|
||||
}
|
||||
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
<div class="w-full bg-white py-3 border-2 shadow sm:rounded-lg">
|
||||
|
||||
@ -43,7 +44,6 @@ span {
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="user-details" class="mt-3 px-3 border-b-2 border-fuschia-600 flex flex-col items-end">
|
||||
|
||||
<div x-data="{ show_user: false }" class="mb-3">
|
||||
@ -77,7 +77,15 @@ span {
|
||||
<td>
|
||||
<div class="product-information">
|
||||
<div class="item-details">
|
||||
<p class="mt-2">{{ $product['quantity'] }} × {{ $product['cost'] }}</p>
|
||||
<p class="mt-2">
|
||||
@if($show_quantity)
|
||||
{{ $product['quantity'] }} x
|
||||
@endif
|
||||
|
||||
@if($show_cost)
|
||||
{{ $product['cost'] }}
|
||||
@endif
|
||||
</p>
|
||||
<p class="overflow-ellipsis overflow-hidden px-1 mb-2">{{ $product['notes'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -174,10 +182,10 @@ span {
|
||||
{{ strip_tags($entity->footer) }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@push('head')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
@ -224,3 +232,4 @@ span {
|
||||
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -1,63 +1,64 @@
|
||||
<div>
|
||||
<div class="flex flex-col items-end mb-2">
|
||||
<button wire:loading.attr="disabled" wire:click="downloadPdf" class="bg-gray-100 hover:bg-gray-200 text-gray-800 font-bold px-2 rounded inline-flex">
|
||||
<span>{{ ctrans('texts.download_pdf') }}</span>
|
||||
<div wire:loading wire:target="downloadPdf">
|
||||
<svg class="animate-spin h-5 w-5 text-blue" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<div class="flex flex-col items-end mb-2">
|
||||
<button wire:loading.attr="disabled" wire:click="downloadPdf" class="bg-gray-100 hover:bg-gray-200 text-gray-800 font-bold px-2 rounded inline-flex">
|
||||
<span>{{ ctrans('texts.download_pdf') }}</span>
|
||||
<div wire:loading wire:target="downloadPdf">
|
||||
<svg class="animate-spin h-5 w-5 text-blue" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="hidden lg:block">
|
||||
<div wire:init="getPdf()">
|
||||
@if($pdf)
|
||||
<iframe id="pdf-iframe" src="{!! $pdf !!}" class="h-screen w-full border-0 mt-4"></iframe>
|
||||
@else
|
||||
<div class="flex mt-4 place-items-center">
|
||||
<span class="loader m-auto"></span>
|
||||
<style type="text/css">
|
||||
.loader {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
animation: rotate 1s linear infinite
|
||||
}
|
||||
.loader::before , .loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
inset: 0px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid #454545;
|
||||
animation: prixClipFix 2s linear infinite ;
|
||||
}
|
||||
.loader::after{
|
||||
border-color: #FF3D00;
|
||||
animation: prixClipFix 2s linear infinite , rotate 0.5s linear infinite reverse;
|
||||
inset: 6px;
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% {transform: rotate(0deg)}
|
||||
100% {transform: rotate(360deg)}
|
||||
}
|
||||
@keyframes prixClipFix {
|
||||
0% {clip-path:polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)}
|
||||
25% {clip-path:polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)}
|
||||
50% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)}
|
||||
75% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 100%)}
|
||||
100% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 0)}
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="hidden lg:block">
|
||||
<div wire:init="getPdf()">
|
||||
@if($pdf)
|
||||
<!-- <iframe id="pdf-iframe" src="{!! $pdf !!}" class="h-screen w-full border-0 mt-4"></iframe> -->
|
||||
<iframe id="pdf-iframe" src="/{{ $route_entity }}/showBlob/{{ $pdf }}" class="h-screen w-full border-0 mt-4"></iframe>
|
||||
@else
|
||||
<div class="flex mt-4 place-items-center">
|
||||
<span class="loader m-auto"></span>
|
||||
<style type="text/css">
|
||||
.loader {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
animation: rotate 1s linear infinite
|
||||
}
|
||||
.loader::before , .loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
inset: 0px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid #454545;
|
||||
animation: prixClipFix 2s linear infinite ;
|
||||
}
|
||||
.loader::after{
|
||||
border-color: #FF3D00;
|
||||
animation: prixClipFix 2s linear infinite , rotate 0.5s linear infinite reverse;
|
||||
inset: 6px;
|
||||
}
|
||||
@keyframes rotate {
|
||||
0% {transform: rotate(0deg)}
|
||||
100% {transform: rotate(360deg)}
|
||||
}
|
||||
@keyframes prixClipFix {
|
||||
0% {clip-path:polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)}
|
||||
25% {clip-path:polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)}
|
||||
50% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)}
|
||||
75% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 100%)}
|
||||
100% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 0)}
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block lg:hidden">
|
||||
@include('portal.ninja2020.components.html-viewer')
|
||||
</div>
|
||||
<div class="block lg:hidden">
|
||||
@include('portal.ninja2020.components.html-viewer')
|
||||
</div>
|
||||
</div>
|
@ -4,8 +4,8 @@
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
<meta name="pdf-url" content="{{ $url ?? $entity->pdf_file_path($invitation, 'url', true) }}?cache_buster={{time()}}">
|
||||
<script src="{{ asset('js/vendor/pdf.js/pdf.min.js') }}"></script>
|
||||
<!-- <meta name="pdf-url" content="{{ $url ?? $entity->pdf_file_path($invitation, 'url', true) }}?cache_buster={{time()}}">
|
||||
<script src="{{ asset('js/vendor/pdf.js/pdf.min.js') }}"></script> -->
|
||||
@endpush
|
||||
|
||||
<div class="flex items-center justify-between mt-4">
|
||||
@ -56,18 +56,18 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@if($mobile)
|
||||
<!-- @if($mobile)
|
||||
<div class="w-full h-full overflow-auto mt-4">
|
||||
<canvas id="pdf-placeholder" class="shadow rounded-lg bg-white"></canvas>
|
||||
</div>
|
||||
@else
|
||||
@else -->
|
||||
@livewire('pdf-slot', ['entity' => $entity, 'invitation' => $invitation, 'db' => $invitation->company->db])
|
||||
<!-- <iframe id="pdf-iframe" src="{{ $url ?? $entity->pdf_file_path($invitation, 'url', true) }}?cache_buster={{time()}}" class="h-screen w-full border-0 mt-4"></iframe> -->
|
||||
@endif
|
||||
<!-- @endif -->
|
||||
|
||||
|
||||
@if($mobile)
|
||||
@push('footer')
|
||||
<script src="{{ asset('js/clients/shared/pdf.js') }}" defer></script>
|
||||
<!-- <script src="{{ asset('js/clients/shared/pdf.js') }}" defer></script> -->
|
||||
@endpush
|
||||
@endif
|
||||
|
@ -32,8 +32,7 @@
|
||||
</div>
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $credit])
|
||||
|
||||
@include('portal.ninja2020.components.pdf-viewer', ['entity' => $credit, 'invitation' => $invitation])
|
||||
@livewire('pdf-slot', ['entity' => $credit, 'invitation' => $invitation, 'db' => $invitation->company->db])
|
||||
|
||||
@endsection
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div style="display: none;" id="displaySignatureModal" class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center">
|
||||
<div style="display: none;" id="displaySignatureModal" class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center" x-data>
|
||||
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="fixed inset-0 transition-opacity">
|
||||
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
|
||||
</div>
|
||||
@ -21,14 +21,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
||||
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
|
||||
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse" >
|
||||
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto" x-data>
|
||||
<button type="button" id="signature-next-step" class="button button-primary bg-primary" @click="document.getElementById('displaySignatureModal').style.display = 'none';">
|
||||
{{ ctrans('texts.next_step') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto" id="close_button">
|
||||
<button @click="document.getElementById('displaySignatureModal').style.display = 'none';" type="button" class="button button-secondary">
|
||||
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto" x-data>
|
||||
<button @click="document.getElementById('displaySignatureModal').style.display = 'none';" type="button" class="button button-secondary" id="close-button">
|
||||
{{ ctrans('texts.close') }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div style="display: none;" id="displayTermsModal" class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center">
|
||||
<div style="display: none;" id="displayTermsModal" class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center" x-data>
|
||||
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="fixed inset-0 transition-opacity">
|
||||
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
|
||||
</div>
|
||||
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
||||
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
|
||||
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto" x-data>
|
||||
<button
|
||||
type="button"
|
||||
id="accept-terms-button"
|
||||
@ -33,8 +33,8 @@
|
||||
{{ ctrans('texts.i_agree') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto" id="hide_close">
|
||||
<button @click="document.getElementById('displayTermsModal').style.display = 'none';" type="button" class="button button-secondary">
|
||||
<div class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto" x-data>
|
||||
<button @click="document.getElementById('displayTermsModal').style.display = 'none';" type="button" class="button button-secondary" id="close-terms-button">
|
||||
{{ ctrans('texts.close') }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -5,7 +5,6 @@
|
||||
<meta name="show-invoice-terms" content="{{ $settings->show_accept_invoice_terms ? true : false }}">
|
||||
<meta name="require-invoice-signature" content="{{ $client->user->account->hasFeature(\App\Models\Account::FEATURE_INVOICE_SETTINGS) && $settings->require_invoice_signature }}">
|
||||
@include('portal.ninja2020.components.no-cache')
|
||||
|
||||
<script src="{{ asset('vendor/signature_pad@2.3.2/signature_pad.min.js') }}"></script>
|
||||
|
||||
@endpush
|
||||
@ -96,18 +95,26 @@
|
||||
@endif
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $invoice])
|
||||
@include('portal.ninja2020.components.pdf-viewer', ['entity' => $invoice, 'invitation' => $invitation])
|
||||
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$invoice], 'entity_type' => ctrans('texts.invoice')])
|
||||
@include('portal.ninja2020.invoices.includes.signature')
|
||||
@livewire('pdf-slot', ['entity' => $invoice, 'invitation' => $invitation, 'db' => $invitation->company->db])
|
||||
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/invoices/payment.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
@include('portal.ninja2020.invoices.includes.signature')
|
||||
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$invoice], 'entity_type' => ctrans('texts.invoice')])
|
||||
@endsection
|
||||
|
||||
@push('head')
|
||||
<script src="{{ asset('js/clients/invoices/payment.js') }}" defer></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}" defer></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
@ -46,19 +46,27 @@
|
||||
@endif
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $purchase_order])
|
||||
@include('portal.ninja2020.components.pdf-viewer', ['entity' => $purchase_order, 'invitation' => $invitation])
|
||||
@livewire('pdf-slot', ['entity' => $purchase_order, 'invitation' => $invitation, 'db' => $invitation->company->db])
|
||||
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$purchase_order], 'entity_type' => ctrans('texts.purchase_order')])
|
||||
@include('portal.ninja2020.invoices.includes.signature')
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/purchase_orders/accept.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
@push('head')
|
||||
<script src="{{ asset('js/clients/purchase_orders/accept.js') }}" defer></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}" defer></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div style="display: none;" id="displaySignatureModal"
|
||||
class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center">
|
||||
class="fixed bottom-0 inset-x-0 px-4 pb-4 sm:inset-0 sm:flex sm:items-center sm:justify-center" x-data>
|
||||
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
|
||||
|
@ -106,19 +106,27 @@
|
||||
@endif
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $quote])
|
||||
@include('portal.ninja2020.components.pdf-viewer', ['entity' => $quote, 'invitation' => $invitation])
|
||||
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$quote], 'entity_type' => ctrans('texts.quote')])
|
||||
@include('portal.ninja2020.invoices.includes.signature')
|
||||
@include('portal.ninja2020.quotes.includes.user-input')
|
||||
@livewire('pdf-slot', ['entity' => $quote, 'invitation' => $invitation, 'db' => $invitation->company->db])
|
||||
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/quotes/approve.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
@include('portal.ninja2020.quotes.includes.user-input')
|
||||
@include('portal.ninja2020.invoices.includes.terms', ['entities' => [$quote], 'entity_type' => ctrans('texts.quote')])
|
||||
@include('portal.ninja2020.invoices.includes.signature')
|
||||
@endsection
|
||||
|
||||
<script type="text/javascript">
|
||||
@push('head')
|
||||
<script src="{{ asset('js/clients/quotes/approve.js') }}" defer></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}" defer></script>
|
||||
|
||||
<script type="text/javascript" defer>
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
@ -75,6 +75,7 @@ use App\Http\Controllers\HostedMigrationController;
|
||||
use App\Http\Controllers\ConnectedAccountController;
|
||||
use App\Http\Controllers\RecurringExpenseController;
|
||||
use App\Http\Controllers\RecurringInvoiceController;
|
||||
use App\Http\Controllers\ProtectedDownloadController;
|
||||
use App\Http\Controllers\ClientGatewayTokenController;
|
||||
use App\Http\Controllers\Reports\TaskReportController;
|
||||
use App\Http\Controllers\Auth\ForgotPasswordController;
|
||||
@ -85,6 +86,7 @@ use App\Http\Controllers\Auth\PasswordTimeoutController;
|
||||
use App\Http\Controllers\PreviewPurchaseOrderController;
|
||||
use App\Http\Controllers\Reports\ClientReportController;
|
||||
use App\Http\Controllers\Reports\CreditReportController;
|
||||
use App\Http\Controllers\Reports\VendorReportController;
|
||||
use App\Http\Controllers\Reports\ExpenseReportController;
|
||||
use App\Http\Controllers\Reports\InvoiceReportController;
|
||||
use App\Http\Controllers\Reports\PaymentReportController;
|
||||
@ -101,11 +103,12 @@ use App\Http\Controllers\Support\Messages\SendingController;
|
||||
use App\Http\Controllers\Reports\ClientSalesReportController;
|
||||
use App\Http\Controllers\Reports\InvoiceItemReportController;
|
||||
use App\Http\Controllers\PaymentNotificationWebhookController;
|
||||
use App\Http\Controllers\ProtectedDownloadController;
|
||||
use App\Http\Controllers\Reports\ProductSalesReportController;
|
||||
use App\Http\Controllers\Reports\ClientBalanceReportController;
|
||||
use App\Http\Controllers\Reports\ClientContactReportController;
|
||||
use App\Http\Controllers\Reports\PurchaseOrderReportController;
|
||||
use App\Http\Controllers\Reports\RecurringInvoiceReportController;
|
||||
use App\Http\Controllers\Reports\PurchaseOrderItemReportController;
|
||||
|
||||
Route::group(['middleware' => ['throttle:api', 'api_secret_check']], function () {
|
||||
Route::post('api/v1/signup', [AccountController::class, 'store'])->name('signup.submit');
|
||||
@ -272,7 +275,6 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
|
||||
Route::post('recurring_expenses/bulk', [RecurringExpenseController::class, 'bulk'])->name('recurring_expenses.bulk');
|
||||
Route::put('recurring_expenses/{recurring_expense}/upload', [RecurringExpenseController::class, 'upload']);
|
||||
|
||||
|
||||
Route::resource('recurring_invoices', RecurringInvoiceController::class); // name = (recurring_invoices. index / create / show / update / destroy / edit
|
||||
Route::post('recurring_invoices/bulk', [RecurringInvoiceController::class, 'bulk'])->name('recurring_invoices.bulk');
|
||||
Route::put('recurring_invoices/{recurring_invoice}/upload', [RecurringInvoiceController::class, 'upload']);
|
||||
@ -291,6 +293,8 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
|
||||
Route::post('reports/expenses', ExpenseReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/invoices', InvoiceReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/invoice_items', InvoiceItemReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/purchase_orders', PurchaseOrderReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/purchase_order_items', PurchaseOrderItemReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/quotes', QuoteReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/quote_items', QuoteItemReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/recurring_invoices', RecurringInvoiceReportController::class)->middleware('throttle:20,1');
|
||||
@ -298,7 +302,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
|
||||
Route::post('reports/products', ProductReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/product_sales', ProductSalesReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/tasks', TaskReportController::class)->middleware('throttle:20,1');
|
||||
|
||||
Route::post('reports/vendors', VendorReportController::class)->middleware('throttle:20,1');
|
||||
Route::post('reports/profitloss', ProfitAndLossController::class);
|
||||
Route::post('reports/ar_detail_report', ARDetailReportController::class);
|
||||
Route::post('reports/ar_summary_report', ARSummaryReportController::class);
|
||||
|
@ -18,18 +18,18 @@ use App\Http\Controllers\ClientPortal\SubscriptionController;
|
||||
use App\Http\Controllers\Auth\ContactForgotPasswordController;
|
||||
use App\Http\Controllers\ClientPortal\PaymentMethodController;
|
||||
|
||||
Route::get('client', [ContactLoginController::class, 'showLoginForm'])->name('client.catchall')->middleware(['domain_db', 'contact_account','locale']); //catch all
|
||||
Route::get('client', [ContactLoginController::class, 'showLoginForm'])->name('client.catchall')->middleware(['domain_db', 'contact_account','locale', 'throttle:portal']); //catch all
|
||||
|
||||
Route::get('client/login/{company_key?}', [ContactLoginController::class, 'showLoginForm'])->name('client.login')->middleware(['domain_db', 'contact_account','locale']);
|
||||
Route::get('client/login/{company_key?}', [ContactLoginController::class, 'showLoginForm'])->name('client.login')->middleware(['domain_db', 'contact_account','locale', 'throttle:portal']);
|
||||
Route::post('client/login/{company_key?}', [ContactLoginController::class, 'login'])->name('client.login.submit');
|
||||
|
||||
Route::get('client/register/{company_key?}', [ContactRegisterController::class, 'showRegisterForm'])->name('client.register')->middleware(['domain_db', 'contact_account', 'contact_register','locale']);
|
||||
Route::post('client/register/{company_key?}', [ContactRegisterController::class, 'register'])->middleware(['domain_db', 'contact_account', 'contact_register', 'locale', 'throttle:10,1']);
|
||||
Route::post('client/register/{company_key?}', [ContactRegisterController::class, 'register'])->middleware(['domain_db', 'contact_account', 'contact_register', 'locale', 'throttle:portal']);
|
||||
|
||||
Route::get('client/password/reset', [ContactForgotPasswordController::class, 'showLinkRequestForm'])->name('client.password.request')->middleware(['domain_db', 'contact_account','locale']);
|
||||
Route::post('client/password/email', [ContactForgotPasswordController::class, 'sendResetLinkEmail'])->name('client.password.email')->middleware('locale');
|
||||
Route::get('client/password/reset/{token}', [ContactResetPasswordController::class, 'showResetForm'])->name('client.password.reset')->middleware(['domain_db', 'contact_account','locale']);
|
||||
Route::post('client/password/reset', [ContactResetPasswordController::class, 'reset'])->name('client.password.update')->middleware(['domain_db', 'contact_account','locale']);
|
||||
Route::get('client/password/reset', [ContactForgotPasswordController::class, 'showLinkRequestForm'])->name('client.password.request')->middleware(['domain_db', 'contact_account','locale', 'throttle:portal']);
|
||||
Route::post('client/password/email', [ContactForgotPasswordController::class, 'sendResetLinkEmail'])->name('client.password.email')->middleware(['locale', 'throttle:portal']);
|
||||
Route::get('client/password/reset/{token}', [ContactResetPasswordController::class, 'showResetForm'])->name('client.password.reset')->middleware(['domain_db', 'contact_account','locale', 'throttle:portal']);
|
||||
Route::post('client/password/reset', [ContactResetPasswordController::class, 'reset'])->name('client.password.update')->middleware(['domain_db', 'contact_account','locale', 'throttle:portal']);
|
||||
|
||||
Route::get('view/{entity_type}/{invitation_key}', [App\Http\Controllers\ClientPortal\EntityViewController::class, 'index'])->name('client.entity_view');
|
||||
Route::get('view/{entity_type}/{invitation_key}/password', [App\Http\Controllers\ClientPortal\EntityViewController::class ,'password'])->name('client.entity_view.password');
|
||||
@ -50,7 +50,8 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'domain_db','check_clie
|
||||
Route::get('dashboard', [App\Http\Controllers\ClientPortal\DashboardController::class, 'index'])->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit
|
||||
|
||||
Route::get('plan', [App\Http\Controllers\ClientPortal\NinjaPlanController::class, 'plan'])->name('plan'); // name = (dashboard. index / create / show / update / destroy / edit
|
||||
|
||||
|
||||
Route::get('showBlob/{hash}', [App\Http\Controllers\ClientPortal\InvoiceController::class, 'showBlob'])->name('invoices.showBlob');
|
||||
Route::get('invoices', [App\Http\Controllers\ClientPortal\InvoiceController::class, 'index'])->name('invoices.index')->middleware('portal_enabled');
|
||||
Route::post('invoices/payment', [App\Http\Controllers\ClientPortal\InvoiceController::class, 'bulk'])->name('invoices.bulk');
|
||||
Route::get('invoices/payment', [App\Http\Controllers\ClientPortal\InvoiceController::class, 'catch_bulk'])->name('invoices.catch_bulk');
|
||||
@ -78,7 +79,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'domain_db','check_clie
|
||||
Route::put('profile/{client_contact}/localization', [App\Http\Controllers\ClientPortal\ProfileController::class, 'updateClientLocalization'])->name('profile.edit_localization');
|
||||
|
||||
Route::get('payment_methods/{payment_method}/verification', [App\Http\Controllers\ClientPortal\PaymentMethodController::class, 'verify'])->name('payment_methods.verification');
|
||||
Route::post('payment_methods/{payment_method}/verification', [App\Http\Controllers\ClientPortal\PaymentMethodController::class, 'processVerification'])->middleware(['throttle:10,1']);
|
||||
Route::post('payment_methods/{payment_method}/verification', [App\Http\Controllers\ClientPortal\PaymentMethodController::class, 'processVerification'])->middleware(['throttle:portal']);
|
||||
|
||||
Route::get('payment_methods/confirm', [App\Http\Controllers\ClientPortal\PaymentMethodController::class, 'store'])->name('payment_methods.confirm');
|
||||
|
||||
|
@ -25,10 +25,6 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'vendor', 'as' => 'vend
|
||||
/*Invitation catches*/
|
||||
Route::get('purchase_order/{invitation_key}', [InvitationController::class, 'purchaseOrder']);
|
||||
Route::get('purchase_order/{invitation_key}/download', [InvitationController::class, 'download']);
|
||||
|
||||
// Route::get('purchase_order/{invitation_key}/download_pdf', 'PurchaseOrderController@downloadPdf')->name('recurring_invoice.download_invitation_key');
|
||||
// Route::get('purchase_order/{invitation_key}/download', 'ClientPortal\InvitationController@routerForDownload');
|
||||
|
||||
});
|
||||
|
||||
Route::group(['middleware' => ['auth:vendor', 'vendor_locale', 'domain_db'], 'prefix' => 'vendor', 'as' => 'vendor.'], function () {
|
||||
@ -37,6 +33,8 @@ Route::group(['middleware' => ['auth:vendor', 'vendor_locale', 'domain_db'], 'pr
|
||||
Route::get('purchase_orders', [PurchaseOrderController::class, 'index'])->name('purchase_orders.index');
|
||||
Route::get('purchase_orders/{purchase_order}', [PurchaseOrderController::class, 'show'])->name('purchase_order.show');
|
||||
|
||||
Route::get('showBlob/{hash}', [PurchaseOrderController::class, 'showBlob'])->name('purchase_order.showBlob');
|
||||
|
||||
Route::get('profile/{vendor_contact}/edit', [VendorContactController::class, 'edit'])->name('profile.edit');
|
||||
Route::put('profile/{vendor_contact}/edit', [VendorContactController::class, 'update'])->name('profile.update');
|
||||
|
||||
|
@ -37,6 +37,54 @@ class ClientCsvTest extends TestCase
|
||||
$this->withoutExceptionHandling();
|
||||
}
|
||||
|
||||
public function testRecurringInvoiceExportCsv()
|
||||
{
|
||||
$data = [
|
||||
'date_range' => 'this_year',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/recurring_invoices', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testVendorExportCsv()
|
||||
{
|
||||
$data = [
|
||||
'date_range' => 'this_year',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/vendors', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testPurchaseOrderExportCsv()
|
||||
{
|
||||
$data = [
|
||||
'date_range' => 'this_year',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/purchase_orders', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testClientExportCsv()
|
||||
{
|
||||
$data = [
|
||||
|
@ -46,7 +46,7 @@ class ExportCompanyTest extends TestCase
|
||||
|
||||
public function testCompanyExport()
|
||||
{
|
||||
$res = (new CompanyExport($this->company, $this->company->users->first()))->handle();
|
||||
$res = (new CompanyExport($this->company, $this->company->users->first(), '123'))->handle();
|
||||
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
259
tests/Feature/Export/ReportCsvGenerationTest.php
Normal file
259
tests/Feature/Export/ReportCsvGenerationTest.php
Normal file
@ -0,0 +1,259 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Export;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\User;
|
||||
use App\Models\Client;
|
||||
use League\Csv\Reader;
|
||||
use App\Models\Account;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use Tests\MockAccountData;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\ClientContact;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Services\Report\ARDetailReport;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class ReportCsvGenerationTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
public $faker;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->faker = \Faker\Factory::create();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
$this->buildData();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public $company;
|
||||
|
||||
public $user;
|
||||
|
||||
public $payload;
|
||||
|
||||
public $account;
|
||||
|
||||
public $client;
|
||||
|
||||
public $token;
|
||||
|
||||
public $cu;
|
||||
|
||||
/**
|
||||
* start_date - Y-m-d
|
||||
end_date - Y-m-d
|
||||
date_range -
|
||||
all
|
||||
last7
|
||||
last30
|
||||
this_month
|
||||
last_month
|
||||
this_quarter
|
||||
last_quarter
|
||||
this_year
|
||||
custom
|
||||
is_income_billed - true = Invoiced || false = Payments
|
||||
expense_billed - true = Expensed || false = Expenses marked as paid
|
||||
include_tax - true tax_included || false - tax_excluded
|
||||
*/
|
||||
private function buildData()
|
||||
{
|
||||
$this->account = Account::factory()->create([
|
||||
'hosted_client_count' => 1000,
|
||||
'hosted_company_count' => 1000,
|
||||
]);
|
||||
|
||||
$this->account->num_users = 3;
|
||||
$this->account->save();
|
||||
|
||||
$this->user = User::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'confirmation_code' => 'xyz123',
|
||||
'email' => $this->faker->unique()->safeEmail(),
|
||||
]);
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->client_online_payment_notification = false;
|
||||
$settings->client_manual_payment_notification = false;
|
||||
|
||||
$this->company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
$this->company->settings = $settings;
|
||||
$this->company->save();
|
||||
|
||||
$this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id);
|
||||
$this->cu->is_owner = true;
|
||||
$this->cu->is_admin = true;
|
||||
$this->cu->is_locked = false;
|
||||
$this->cu->save();
|
||||
|
||||
$this->token = \Illuminate\Support\Str::random(64);
|
||||
|
||||
$company_token = new CompanyToken;
|
||||
$company_token->user_id = $this->user->id;
|
||||
$company_token->company_id = $this->company->id;
|
||||
$company_token->account_id = $this->account->id;
|
||||
$company_token->name = 'test token';
|
||||
$company_token->token = $this->token;
|
||||
$company_token->is_system = true;
|
||||
|
||||
$company_token->save();
|
||||
|
||||
$this->payload = [
|
||||
'start_date' => '2000-01-01',
|
||||
'end_date' => '2030-01-11',
|
||||
'date_range' => 'custom',
|
||||
'is_income_billed' => true,
|
||||
'include_tax' => false,
|
||||
];
|
||||
|
||||
$this->client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_deleted' => 0,
|
||||
'name' => 'bob',
|
||||
'address1' => '1234'
|
||||
]);
|
||||
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'first_name' => 'john',
|
||||
'last_name' => 'doe',
|
||||
'email' => 'john@doe.com'
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function testClientCsvGeneration()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/clients', $data);
|
||||
|
||||
$csv = $response->streamedContent();
|
||||
|
||||
$reader = Reader::createFromString($csv);
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
$res = $reader->fetchColumnByName('Street');
|
||||
$res = iterator_to_array($res, true);
|
||||
|
||||
$this->assertEquals('1234', $res[1]);
|
||||
|
||||
$res = $reader->fetchColumnByName('Name');
|
||||
$res = iterator_to_array($res, true);
|
||||
|
||||
$this->assertEquals('bob', $res[1]);
|
||||
|
||||
}
|
||||
|
||||
public function testClientContactCsvGeneration()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/contacts', $data);
|
||||
|
||||
$csv = $response->streamedContent();
|
||||
|
||||
$reader = Reader::createFromString($csv);
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
$res = $reader->fetchColumnByName('First Name');
|
||||
$res = iterator_to_array($res, true);
|
||||
|
||||
$this->assertEquals('john', $res[1]);
|
||||
|
||||
$res = $reader->fetchColumnByName('Last Name');
|
||||
$res = iterator_to_array($res, true);
|
||||
|
||||
$this->assertEquals('doe', $res[1]);
|
||||
|
||||
$res = $reader->fetchColumnByName('Email');
|
||||
$res = iterator_to_array($res, true);
|
||||
|
||||
$this->assertEquals('john@doe.com', $res[1]);
|
||||
|
||||
}
|
||||
|
||||
public function testCreditCsvGeneration()
|
||||
{
|
||||
|
||||
Credit::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->client->id,
|
||||
'amount' => 100,
|
||||
'balance' => 50,
|
||||
'status_id' => 2,
|
||||
'discount' => 10,
|
||||
'po_number' => '1234',
|
||||
'public_notes' => 'Public',
|
||||
'private_notes' => 'Private',
|
||||
'terms' => 'Terms',
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'date_range' => 'all',
|
||||
'report_keys' => [],
|
||||
'send_email' => false,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/reports/credits', $data);
|
||||
|
||||
|
||||
|
||||
}
|
192
tests/Feature/PaymentV2Test.php
Normal file
192
tests/Feature/PaymentV2Test.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Foundation\Testing\WithoutEvents;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Http\Controllers\PaymentController
|
||||
*/
|
||||
class PaymentV2Test extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
use WithoutEvents;
|
||||
|
||||
public $faker;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Session::start();
|
||||
|
||||
$this->faker = \Faker\Factory::create();
|
||||
|
||||
Model::reguard();
|
||||
|
||||
$this->makeTestData();
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
}
|
||||
|
||||
public function testStorePaymentWithCreditsThenDeletingInvoices()
|
||||
{
|
||||
$client = Client::factory()->create(['company_id' =>$this->company->id, 'user_id' => $this->user->id, 'balance' => 20, 'paid_to_date' => 0]);
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
]);
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'amount' => 20,
|
||||
'balance' => 20,
|
||||
'discount' => 0,
|
||||
'number' => uniqid("st", true),
|
||||
'line_items' => []
|
||||
]);
|
||||
|
||||
$this->assertEquals(20, $client->balance);
|
||||
$this->assertEquals(0, $client->paid_to_date);
|
||||
$this->assertEquals(20, $invoice->amount);
|
||||
$this->assertEquals(20, $invoice->balance);
|
||||
|
||||
$credit = Credit::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'uses_inclusive_taxes' => false,
|
||||
'amount' => 20,
|
||||
'balance' => 20,
|
||||
'discount' => 0,
|
||||
'number' => uniqid("st", true),
|
||||
'line_items' => []
|
||||
]);
|
||||
|
||||
$this->assertEquals(20, $credit->amount);
|
||||
$this->assertEquals(20, $credit->balance);
|
||||
|
||||
$data = [
|
||||
'client_id' => $client->hashed_id,
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $invoice->hashed_id,
|
||||
'amount' => 20,
|
||||
],
|
||||
],
|
||||
'credits' => [
|
||||
[
|
||||
'credit_id' => $credit->hashed_id,
|
||||
'amount' => 20,
|
||||
],
|
||||
],
|
||||
'date' => '2020/12/12',
|
||||
|
||||
];
|
||||
|
||||
$response = null;
|
||||
|
||||
try {
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/payments?include=invoices', $data);
|
||||
} catch (ValidationException $e) {
|
||||
$message = json_decode($e->validator->getMessageBag(), 1);
|
||||
nlog($message);
|
||||
$this->assertNotNull($message);
|
||||
}
|
||||
|
||||
$arr = $response->json();
|
||||
$response->assertStatus(200);
|
||||
|
||||
$payment_id = $arr['data']['id'];
|
||||
|
||||
$payment = Payment::find($this->decodePrimaryKey($payment_id));
|
||||
|
||||
$this->assertNotNull($payment);
|
||||
$this->assertNotNull($payment->invoices());
|
||||
$this->assertEquals(1, $payment->invoices()->count());
|
||||
$this->assertEquals(0, $payment->amount);
|
||||
$this->assertEquals(0, $client->fresh()->balance);
|
||||
$this->assertEquals(20, $client->fresh()->paid_to_date);
|
||||
|
||||
$data = [
|
||||
'action' => 'delete',
|
||||
'ids' => [
|
||||
$invoice->hashed_id,
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/invoices/bulk', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$invoice = $invoice->fresh();
|
||||
$payment = $payment->fresh();
|
||||
|
||||
$this->assertEquals(true, $invoice->is_deleted);
|
||||
$this->assertEquals(0, $payment->amount);
|
||||
$this->assertEquals(0, $client->fresh()->balance);
|
||||
$this->assertEquals(0, $client->fresh()->paid_to_date);
|
||||
|
||||
$data = [
|
||||
'action' => 'restore',
|
||||
'ids' => [
|
||||
$invoice->hashed_id,
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/invoices/bulk', $data);
|
||||
|
||||
$invoice = $invoice->fresh();
|
||||
$this->assertEquals(false, $invoice->is_deleted);
|
||||
|
||||
$payment = $payment->fresh();
|
||||
|
||||
$this->assertEquals(0, $payment->amount);
|
||||
$this->assertEquals(20, $client->fresh()->paid_to_date);
|
||||
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ class PaymentTypeTest extends TestCase
|
||||
$payment_type_class = new PaymentType;
|
||||
|
||||
foreach($payment_type_class->type_names as $type)
|
||||
{nlog($type);
|
||||
{
|
||||
$this->assertTrue(Lang::has("texts.{$type}"));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user