diff --git a/VERSION.txt b/VERSION.txt index 6f75c330fa4c..078558401440 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.6.18 \ No newline at end of file +5.6.19 \ No newline at end of file diff --git a/app/Casts/EncryptedCast.php b/app/Casts/EncryptedCast.php index e13c69625d32..7be926072c3a 100644 --- a/app/Casts/EncryptedCast.php +++ b/app/Casts/EncryptedCast.php @@ -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) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index d9731c49b680..ccbf10b45057 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -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; } diff --git a/app/Export/CSV/ClientExport.php b/app/Export/CSV/ClientExport.php index 1f45c2b97569..bcf93bf5897f 100644 --- a/app/Export/CSV/ClientExport.php +++ b/app/Export/CSV/ClientExport.php @@ -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'); diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index a1d9411ea5af..9f542fea2316 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -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; diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php new file mode 100644 index 000000000000..0b4202ce5af0 --- /dev/null +++ b/app/Export/CSV/PurchaseOrderExport.php @@ -0,0 +1,172 @@ + '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; + } +} diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php new file mode 100644 index 000000000000..4847a162f9c0 --- /dev/null +++ b/app/Export/CSV/PurchaseOrderItemExport.php @@ -0,0 +1,246 @@ + '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; + } +} diff --git a/app/Export/CSV/VendorExport.php b/app/Export/CSV/VendorExport.php new file mode 100644 index 000000000000..e978c36e1432 --- /dev/null +++ b/app/Export/CSV/VendorExport.php @@ -0,0 +1,172 @@ + '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'); + } +} diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index e7ada0ce11ac..1e07412eda4c 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -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 diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index fc33f283a554..036b7a892ed0 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -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) { diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index ac850442125e..cf69f531cbfd 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -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() */ diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 8a0013c6d8f9..6e04f4a7e938 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -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. * diff --git a/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php new file mode 100644 index 000000000000..a708f1300ab4 --- /dev/null +++ b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php @@ -0,0 +1,53 @@ +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); + } +} diff --git a/app/Http/Controllers/Reports/PurchaseOrderReportController.php b/app/Http/Controllers/Reports/PurchaseOrderReportController.php new file mode 100644 index 000000000000..4bd0057aa91a --- /dev/null +++ b/app/Http/Controllers/Reports/PurchaseOrderReportController.php @@ -0,0 +1,53 @@ +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); + } +} diff --git a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php index 01d9a0f1f72a..eaae55bd1351 100644 --- a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php +++ b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php @@ -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')) { diff --git a/app/Http/Controllers/Reports/VendorReportController.php b/app/Http/Controllers/Reports/VendorReportController.php new file mode 100644 index 000000000000..2494daadb923 --- /dev/null +++ b/app/Http/Controllers/Reports/VendorReportController.php @@ -0,0 +1,53 @@ +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); + } +} diff --git a/app/Http/Controllers/VendorPortal/PurchaseOrderController.php b/app/Http/Controllers/VendorPortal/PurchaseOrderController.php index 9cf21be66421..65ce601a7c6a 100644 --- a/app/Http/Controllers/VendorPortal/PurchaseOrderController.php +++ b/app/Http/Controllers/VendorPortal/PurchaseOrderController.php @@ -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; diff --git a/app/Http/Livewire/PdfSlot.php b/app/Http/Livewire/PdfSlot.php index 8eda7b1c4ded..52736fb4e90b 100644 --- a/app/Http/Livewire/PdfSlot.php +++ b/app/Http/Livewire/PdfSlot.php @@ -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'; } diff --git a/app/Http/Livewire/RequiredClientInfo.php b/app/Http/Livewire/RequiredClientInfo.php index df184eff52bf..f8777538673a 100644 --- a/app/Http/Livewire/RequiredClientInfo.php +++ b/app/Http/Livewire/RequiredClientInfo.php @@ -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; diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 9805160ab9e7..0a6992192e93 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -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'), ]; } } diff --git a/app/Http/ValidationRules/Credit/ValidCreditsRules.php b/app/Http/ValidationRules/Credit/ValidCreditsRules.php index 7b6fc32aed88..b0892da7330e 100644 --- a/app/Http/ValidationRules/Credit/ValidCreditsRules.php +++ b/app/Http/ValidationRules/Credit/ValidCreditsRules.php @@ -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; } } diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index e4de8ecc5244..1df1683a212e 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -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; diff --git a/app/Jobs/Vendor/CreatePurchaseOrderPdf.php b/app/Jobs/Vendor/CreatePurchaseOrderPdf.php index 5961c3c8564e..607f78d0b97a 100644 --- a/app/Jobs/Vendor/CreatePurchaseOrderPdf.php +++ b/app/Jobs/Vendor/CreatePurchaseOrderPdf.php @@ -188,7 +188,7 @@ class CreatePurchaseOrderPdf implements ShouldQueue } if (config('ninja.log_pdf_html')) { - info($maker->getCompiledHTML()); + nlog($maker->getCompiledHTML()); } $maker = null; diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 00a16129fc9f..3bb6ff894ba4 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -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'); + } } diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index e7eeae12c41a..84ca29d6f31d 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -108,50 +108,6 @@ use Laracasts\Presenter\PresentableTrait; * @property-read \Illuminate\Database\Eloquent\Collection $contacts * @property-read \Illuminate\Database\Eloquent\Collection $documents * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact - * @property-read \Illuminate\Database\Eloquent\Collection $activities - * @property-read \Illuminate\Database\Eloquent\Collection $contacts - * @property-read \Illuminate\Database\Eloquent\Collection $documents - * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact * @mixin \Eloquent */ class Vendor extends BaseModel diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index d8a11fba07e5..3d9dc442150b 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -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()); + }); + + } /** diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index 3fdb6d402608..575a2499ab14 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -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; } diff --git a/app/Services/Invoice/HandleRestore.php b/app/Services/Invoice/HandleRestore.php index 4dc9621f4acf..c3e2947e8732 100644 --- a/app/Services/Invoice/HandleRestore.php +++ b/app/Services/Invoice/HandleRestore.php @@ -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; diff --git a/app/Services/Invoice/MarkInvoiceDeleted.php b/app/Services/Invoice/MarkInvoiceDeleted.php index 27291123d56e..72cfe0136de3 100644 --- a/app/Services/Invoice/MarkInvoiceDeleted.php +++ b/app/Services/Invoice/MarkInvoiceDeleted.php @@ -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(); diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index f5c02d1e86e5..fb50797b64f5 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -109,6 +109,8 @@ class DeletePayment $paymentable_invoice->service() ->updatePaidToDate($net_deletable * -1) ->save(); + $paymentable_invoice->delete(); + } }); } diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index 8f41938b4540..89aa0ea21420 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -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 { diff --git a/app/Utils/Ninja.php b/app/Utils/Ninja.php index 16f357d4df0b..42e6ee271254 100644 --- a/app/Utils/Ninja.php +++ b/app/Utils/Ninja.php @@ -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, ]; } diff --git a/app/Utils/VendorHtmlEngine.php b/app/Utils/VendorHtmlEngine.php index 0f1df93278a7..fa0bff0b8deb 100644 --- a/app/Utils/VendorHtmlEngine.php +++ b/app/Utils/VendorHtmlEngine.php @@ -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']; diff --git a/composer.json b/composer.json index c5907c5a1803..7e1bf4f4ba1d 100644 --- a/composer.json +++ b/composer.json @@ -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", diff --git a/composer.lock b/composer.lock index 3f353f7a4788..294a1edc5334 100644 --- a/composer.lock +++ b/composer.lock @@ -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", diff --git a/config/ninja.php b/config/ninja.php index ec48c4dfa316..cddb4bd32ea7 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -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', ''), diff --git a/database/migrations/2023_07_12_074829_add_thai_baht_currency_symbol.php b/database/migrations/2023_07_12_074829_add_thai_baht_currency_symbol.php new file mode 100644 index 000000000000..fe959e037436 --- /dev/null +++ b/database/migrations/2023_07_12_074829_add_thai_baht_currency_symbol.php @@ -0,0 +1,34 @@ +symbol = '฿'; + $tb->save(); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}; diff --git a/database/seeders/CurrenciesSeeder.php b/database/seeders/CurrenciesSeeder.php index 71a482d726c1..82d92b6595b7 100644 --- a/database/seeders/CurrenciesSeeder.php +++ b/database/seeders/CurrenciesSeeder.php @@ -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' => '.'], diff --git a/lang/cs/texts.php b/lang/cs/texts.php index b9bb377be16c..e28dc4e0770a 100644 --- a/lang/cs/texts.php +++ b/lang/cs/texts.php @@ -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', diff --git a/lang/en/texts.php b/lang/en/texts.php index 69b4e7e79fa1..de8f17ea971e 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -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', ); diff --git a/lang/en_GB/texts.php b/lang/en_GB/texts.php index 27268d7857c3..c687b7b8d9cd 100644 --- a/lang/en_GB/texts.php +++ b/lang/en_GB/texts.php @@ -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', diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php index 9d812017526c..94189ac73af5 100644 --- a/lang/fr_CA/texts.php +++ b/lang/fr_CA/texts.php @@ -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 l\'entente de service de requête de débit direct, 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. Plus d\'information.', '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', + ); diff --git a/lang/ja/texts.php b/lang/ja/texts.php index a68c333c9d73..ba1fecbd22ff 100644 --- a/lang/ja/texts.php +++ b/lang/ja/texts.php @@ -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', diff --git a/lang/lt/texts.php b/lang/lt/texts.php index cc10c19bdfc3..bc2567e18b5e 100644 --- a/lang/lt/texts.php +++ b/lang/lt/texts.php @@ -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', diff --git a/lang/nb_NO/texts.php b/lang/nb_NO/texts.php index 5f0c308c69a9..c74cc5ae23c2 100644 --- a/lang/nb_NO/texts.php +++ b/lang/nb_NO/texts.php @@ -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', diff --git a/lang/sq/texts.php b/lang/sq/texts.php index df7d91d568eb..f706e13e1de3 100644 --- a/lang/sq/texts.php +++ b/lang/sq/texts.php @@ -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', diff --git a/lang/tr_TR/texts.php b/lang/tr_TR/texts.php index e85d8f2d30bb..aad64be4899c 100644 --- a/lang/tr_TR/texts.php +++ b/lang/tr_TR/texts.php @@ -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', diff --git a/public/js/clients/invoices/payment.js b/public/js/clients/invoices/payment.js index 7ee77190ede0..13aec242561a 100644 --- a/public/js/clients/invoices/payment.js +++ b/public/js/clients/invoices/payment.js @@ -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) { diff --git a/public/js/clients/purchase_orders/accept.js b/public/js/clients/purchase_orders/accept.js index 41deb8c75c53..bb5964c59018 100644 --- a/public/js/clients/purchase_orders/accept.js +++ b/public/js/clients/purchase_orders/accept.js @@ -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 () { diff --git a/public/js/clients/quotes/approve.js b/public/js/clients/quotes/approve.js index 9234dee40475..4fe3a7bbd9d6 100644 --- a/public/js/clients/quotes/approve.js +++ b/public/js/clients/quotes/approve.js @@ -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 () { diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 5d7f7371c1b5..2dffe7a09247 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -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", diff --git a/resources/js/clients/invoices/payment.js b/resources/js/clients/invoices/payment.js index 463735982e3b..588a3dfcfc58 100644 --- a/resources/js/clients/invoices/payment.js +++ b/resources/js/clients/invoices/payment.js @@ -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") diff --git a/resources/js/clients/purchase_orders/accept.js b/resources/js/clients/purchase_orders/accept.js index bd39e20b87bc..dfcf83d80722 100644 --- a/resources/js/clients/purchase_orders/accept.js +++ b/resources/js/clients/purchase_orders/accept.js @@ -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(); diff --git a/resources/js/clients/quotes/approve.js b/resources/js/clients/quotes/approve.js index 536c218d0e20..ebbeb00f45da 100644 --- a/resources/js/clients/quotes/approve.js +++ b/resources/js/clients/quotes/approve.js @@ -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', () => { diff --git a/resources/views/portal/ninja2020/components/html-viewer.blade.php b/resources/views/portal/ninja2020/components/html-viewer.blade.php index 8b27738e3a54..e471ed24fa57 100644 --- a/resources/views/portal/ninja2020/components/html-viewer.blade.php +++ b/resources/views/portal/ninja2020/components/html-viewer.blade.php @@ -1,4 +1,4 @@ - +@push('head') +@endpush
@@ -43,7 +44,6 @@ span {
-
@@ -77,7 +77,15 @@ span {
-

{{ $product['quantity'] }} × {{ $product['cost'] }}

+

+ @if($show_quantity) + {{ $product['quantity'] }} x + @endif + + @if($show_cost) + {{ $product['cost'] }} + @endif +

{{ $product['notes'] }}

@@ -174,10 +182,10 @@ span { {{ strip_tags($entity->footer) }}
-
@endif +@push('head') +@endpush \ No newline at end of file diff --git a/resources/views/portal/ninja2020/components/livewire/pdf-slot.blade.php b/resources/views/portal/ninja2020/components/livewire/pdf-slot.blade.php index 553b96d9bf8c..ddde1a25a703 100644 --- a/resources/views/portal/ninja2020/components/livewire/pdf-slot.blade.php +++ b/resources/views/portal/ninja2020/components/livewire/pdf-slot.blade.php @@ -1,63 +1,64 @@
-
- -
- + -
-
-@include('portal.ninja2020.components.html-viewer') -
+
+ @include('portal.ninja2020.components.html-viewer') +
\ No newline at end of file diff --git a/resources/views/portal/ninja2020/components/pdf-viewer.blade.php b/resources/views/portal/ninja2020/components/pdf-viewer.blade.php index 75008ab7e424..8bf2d69be1dd 100644 --- a/resources/views/portal/ninja2020/components/pdf-viewer.blade.php +++ b/resources/views/portal/ninja2020/components/pdf-viewer.blade.php @@ -4,8 +4,8 @@ @endphp @push('head') - - + @endpush
@@ -56,18 +56,18 @@
-@if($mobile) + @livewire('pdf-slot', ['entity' => $entity, 'invitation' => $invitation, 'db' => $invitation->company->db]) -@endif + @if($mobile) @push('footer') - + @endpush @endif diff --git a/resources/views/portal/ninja2020/credits/show.blade.php b/resources/views/portal/ninja2020/credits/show.blade.php index c8cccc0f7c82..2960a301e3c0 100644 --- a/resources/views/portal/ninja2020/credits/show.blade.php +++ b/resources/views/portal/ninja2020/credits/show.blade.php @@ -32,8 +32,7 @@ @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 diff --git a/resources/views/portal/ninja2020/invoices/includes/signature.blade.php b/resources/views/portal/ninja2020/invoices/includes/signature.blade.php index eaa17d80e736..5464b607502e 100644 --- a/resources/views/portal/ninja2020/invoices/includes/signature.blade.php +++ b/resources/views/portal/ninja2020/invoices/includes/signature.blade.php @@ -1,4 +1,4 @@ - -
-
+
+
-
-
diff --git a/resources/views/portal/ninja2020/invoices/includes/terms.blade.php b/resources/views/portal/ninja2020/invoices/includes/terms.blade.php index a963926e9de9..299bf9fc3f1d 100644 --- a/resources/views/portal/ninja2020/invoices/includes/terms.blade.php +++ b/resources/views/portal/ninja2020/invoices/includes/terms.blade.php @@ -1,4 +1,4 @@ -
-
+
-
-
diff --git a/resources/views/portal/ninja2020/invoices/show.blade.php b/resources/views/portal/ninja2020/invoices/show.blade.php index e62ef6e12c34..7f090a4f7ecc 100644 --- a/resources/views/portal/ninja2020/invoices/show.blade.php +++ b/resources/views/portal/ninja2020/invoices/show.blade.php @@ -5,7 +5,6 @@ @include('portal.ninja2020.components.no-cache') - @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') - - + @include('portal.ninja2020.invoices.includes.signature') + @include('portal.ninja2020.invoices.includes.terms', ['entities' => [$invoice], 'entity_type' => ctrans('texts.invoice')]) +@endsection + +@push('head') + + -@endsection +@endpush diff --git a/resources/views/portal/ninja2020/purchase_orders/show.blade.php b/resources/views/portal/ninja2020/purchase_orders/show.blade.php index c95648b5d875..172beb0291fc 100644 --- a/resources/views/portal/ninja2020/purchase_orders/show.blade.php +++ b/resources/views/portal/ninja2020/purchase_orders/show.blade.php @@ -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') - - +@push('head') + + -@endsection +@endpush diff --git a/resources/views/portal/ninja2020/quotes/includes/signature.blade.php b/resources/views/portal/ninja2020/quotes/includes/signature.blade.php index ae3e73d4e5eb..5f39e58b3997 100644 --- a/resources/views/portal/ninja2020/quotes/includes/signature.blade.php +++ b/resources/views/portal/ninja2020/quotes/includes/signature.blade.php @@ -1,5 +1,5 @@