Merge pull request #9013 from turbo124/v5-stable

v5.7.57
This commit is contained in:
David Bomba 2023-12-03 07:43:48 +11:00 committed by GitHub
commit edeae6aec8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
437 changed files with 346323 additions and 336657 deletions

View File

@ -1 +1 @@
5.7.47
5.7.57

View File

@ -14,4 +14,4 @@ namespace Illuminate\Contracts\Mail
return true;
}
}
}
}

View File

@ -85,7 +85,7 @@ class BackupUpdate extends Command
->each(function ($company) {
$company_logo_path = $company->settings->company_logo;
if ($company_logo_path == 'https://invoicing.co/images/new_logo.png' || $company_logo_path == '') {
if ($company_logo_path == config('ninja.app_logo') || $company_logo_path == '') {
return;
}

View File

@ -12,7 +12,6 @@
namespace App\Console\Commands;
use App;
use App\DataMapper\ClientSettings;
use App\Factory\ClientContactFactory;
use App\Factory\VendorContactFactory;
use App\Jobs\Company\CreateCompanyToken;
@ -977,7 +976,7 @@ class CheckData extends Command
$cc = ClientContact::on('db-ninja-01')->where('company_id', config('ninja.ninja_default_company_id'))->where('email', $cu->user->email)->first();
if ($cc) {
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$ninja_portal_url = config('ninja.ninja_client_portal')."/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$cu->ninja_portal_url = $ninja_portal_url;
$cu->save();
@ -990,7 +989,7 @@ class CheckData extends Command
$cc = $c->contacts()->first();
if ($cc) {
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$ninja_portal_url = config('ninja.ninja_client_portal')."/client/ninja/{$cc->contact_key}/{$cu->account->key}";
$cu->ninja_portal_url = $ninja_portal_url;
$cu->save();

View File

@ -42,6 +42,7 @@ use App\Models\Project;
use App\Models\Quote;
use App\Models\RecurringInvoice;
use App\Models\Task;
use App\Models\TaskStatus;
use App\Models\TaxRate;
use App\Models\User;
use App\Models\Vendor;
@ -72,6 +73,7 @@ class CreateSingleAccount extends Command
protected $gateway;
public $faker;
/**
* Execute the console command.
*
@ -79,6 +81,8 @@ class CreateSingleAccount extends Command
*/
public function handle()
{
$this->faker = Factory::create();
if (Ninja::isHosted() || config('ninja.is_docker') || !$this->confirm('Are you sure you want to inject dummy data?')) {
return;
}
@ -503,19 +507,61 @@ class CreateSingleAccount extends Command
private function createTask($client)
{
$vendor = Task::factory()->create([
$time_log = $this->createTimeLog(rand(1, 20));
$status = TaskStatus::where('company_id', $client->company_id)->get()->random();
return Task::factory()->create([
'user_id' => $client->user->id,
'company_id' => $client->company->id,
'time_log' => $time_log,
'description' => $this->faker->paragraph,
'status_id' => $status->id ?? null,
'number' => rand(10000, 100000000),
'rate' => rand(1, 150),
'client_id' => $client->id
]);
}
private function createTimeLog(int $count)
{
$time_log = [];
$min = 0;
for ($x = 0; $x < $count; $x++) {
$rando = rand(300, 87000);
$time_log[] = [
Carbon::now()->addSeconds($min)->timestamp,
Carbon::now()->addSeconds($min += $rando)->timestamp,
$this->faker->sentence,
rand(0, 1) === 0 ? false : true
];
$min += 300;
}
return json_encode($time_log);
}
private function createProject($client)
{
$vendor = Project::factory()->create([
$project = Project::factory()->create([
'user_id' => $client->user->id,
'company_id' => $client->company->id,
'client_id' => $client->id,
'due_date' => now()->addSeconds(rand(100000, 1000000))->format('Y-m-d'),
'budgeted_hours' => rand(100, 1000),
'task_rate' => rand(1, 200),
]);
for($x=0; $x < rand(2, 5); $x++) {
$task = $this->createTask($client);
$task->project_id = $project->id;
$task->save();
}
}
private function createInvoice($client)
@ -559,6 +605,7 @@ class CreateSingleAccount extends Command
$invoice->amount = 100; // Braintree sandbox only allows payments under 2,000 to complete successfully.
}
/** @var \App\Models\Invoice $invoice */
$invoice->save();
$invoice->service()->createInvitations()->markSent();
@ -586,6 +633,7 @@ class CreateSingleAccount extends Command
$credit = $invoice_calc->getCredit();
/** @var \App\Models\Credit $credit */
$credit->save();
$credit->service()->markSent()->save();
$credit->service()->createInvitations();
@ -628,6 +676,7 @@ class CreateSingleAccount extends Command
$quote->save();
/** @var \App\Models\Quote $quote */
$quote->service()->markSent()->save();
$quote->service()->createInvitations();
}

View File

@ -61,9 +61,9 @@ class MobileLocalization extends Command
private function laravelResources()
{
$resources = $this->getResources();
$resources =(array)$this->getResources();
if(is_iterable($resources)){
if(is_iterable($resources)) {
foreach ($resources as $key => $val) {
$transKey = "texts.{$key}";
if (trans($transKey) == $transKey) {

View File

@ -229,7 +229,7 @@ class CompanySettings extends BaseSettings
public $require_quote_signature = false; //@TODO ben to confirm
//email settings
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun'//@implemented
public $email_sending_method = 'default'; //enum 'default','gmail','office365' 'client_postmark', 'client_mailgun' //@implemented
public $gmail_sending_user_id = '0'; //@implemented
@ -491,7 +491,10 @@ class CompanySettings extends BaseSettings
public $classification = ''; // individual, business, partnership, trust, charity, government, other
public $payment_email_all_contacts = false;
public static $casts = [
'payment_email_all_contacts' => 'bool',
'statement_design_id' => 'string',
'delivery_note_design_id' => 'string',
'payment_receipt_design_id' => 'string',

View File

@ -92,6 +92,11 @@ class EmailTemplateDefaults
case 'email_subject_custom3':
return self::emailInvoiceSubject();
case 'email_vendor_notification_subject':
return self::emailVendorNotificationSubject();
case 'email_vendor_notification_body':
return self::emailVendorNotificationBody();
default:
return self::emailInvoiceTemplate();
@ -99,6 +104,16 @@ class EmailTemplateDefaults
}
}
public static function emailVendorNotificationSubject()
{
return self::transformText('vendor_notification_subject');
}
public static function emailVendorNotificationBody()
{
return self::transformText('vendor_notification_body');
}
public static function emailInvoiceSubject()
{
return ctrans('texts.invoice_subject', ['number'=>'$number', 'account'=>'$company.name']);

View File

@ -45,7 +45,7 @@ class EmailReport
/**
* The date range the statement should include
* The date range the report should include
*
* @var string
*/
@ -67,7 +67,45 @@ class EmailReport
*/
public string $end_date = '';
/******************************* Parameters **********************************/
/** @var string $report_name */
public string $report_name = '';
/**
* Optional array of report keys for
* filter the columns of the report
*
* @var array $report_keys
*
* */
public array $report_keys = [];
/** Profit Loss Parameters */
public bool $is_income_billed = true;
public bool $is_expense_billed = true;
public bool $include_tax = true;
/**
* Comma separated string of statuses for filtering the Invoice report
*
* all
* draft
* sent
* paid
* unpaid
* overdue
* viewed
*
* */
public string $status = '';
/**
* Comma separated list of product.product_keys
* to filter the report by
*/
public string $product_key = '';
}

View File

@ -219,7 +219,7 @@ class BaseRule implements RuleInterface
try {
$this->invoice->saveQuietly();
}catch(\Exception $e) {
} catch(\Exception $e) {
}
}

View File

@ -223,8 +223,8 @@ class Handler extends ExceptionHandler
return response()->json(['message' => $exception->getMessage()], 500);
} elseif ($exception instanceof ThrottleRequestsException && $request->expectsJson()) {
return response()->json(['message'=>'Too many requests'], 429);
// } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
// return response()->json(['message'=>'Fatal error'], 500); //@deprecated
// } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
// return response()->json(['message'=>'Fatal error'], 500); //@deprecated
} elseif ($exception instanceof AuthorizationException && $request->expectsJson()) {
return response()->json(['message'=> $exception->getMessage()], 401);
} elseif ($exception instanceof TokenMismatchException) {

View File

@ -105,8 +105,6 @@ class ActivityExport extends BaseExport
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
// ksort($this->entity_keys);
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
@ -142,8 +140,7 @@ class ActivityExport extends BaseExport
{
$this->csv->insertOne($this->buildActivityRow($activity));
}
private function decorateAdvancedFields(Task $task, array $entity) :array

View File

@ -628,11 +628,11 @@ class BaseExport
}
if(in_array($column, ['client.user_id', 'user_id'])) {
return $entity->client->user->present()->name();
return $entity->client->user ? $entity->client->user->present()->name() : '';
}
if(in_array($column, ['client.assigned_user_id', 'assigned_user_id'])) {
return $entity->client->assigned_user->present()->name();
return $entity->client->assigned_user ? $entity->client->assigned_user->present()->name() : '';
}
if(in_array($column, ['client.country_id', 'country_id'])) {

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company;
@ -32,6 +33,8 @@ class ClientExport extends BaseExport
public string $date_key = 'created_at';
private Decorator $decorator;
public array $entity_keys = [
'address1' => 'client.address1',
'address2' => 'client.address2',
@ -84,6 +87,8 @@ class ClientExport extends BaseExport
$this->input = $input;
$this->client_transformer = new ClientTransformer();
$this->contact_transformer = new ClientContactTransformer();
$this->decorator = new Decorator();
}
public function returnJson()
@ -170,11 +175,15 @@ class ClientExport extends BaseExport
} elseif (is_array($parts) && $parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
$entity[$key] = $transformed_contact[$parts[1]];
} else {
$entity[$key] = '';
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $client);
// $entity[$key] = '';
}
}
return $this->decorateAdvancedFields($client, $entity);
return $entity;
// return $this->decorateAdvancedFields($client, $entity);
}
public function processMetaData(array $row, $resource): array

View File

@ -11,16 +11,17 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Company;
use App\Transformers\ClientContactTransformer;
use App\Transformers\ClientTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use App\Models\Client;
use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Models\ClientContact;
use Illuminate\Support\Facades\App;
use App\Export\Decorators\Decorator;
use App\Transformers\ClientTransformer;
use App\Transformers\ClientContactTransformer;
use Illuminate\Database\Eloquent\Builder;
class ContactExport extends BaseExport
{
@ -29,6 +30,8 @@ class ContactExport extends BaseExport
private ClientContactTransformer $contact_transformer;
private Decorator $decorator;
public Writer $csv;
public string $date_key = 'created_at';
@ -39,6 +42,7 @@ class ContactExport extends BaseExport
$this->input = $input;
$this->client_transformer = new ClientTransformer();
$this->contact_transformer = new ClientContactTransformer();
$this->decorator = new Decorator();
}
private function init(): Builder
@ -119,11 +123,14 @@ class ContactExport extends BaseExport
} elseif ($parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
$entity[$key] = $transformed_contact[$parts[1]];
} else {
$entity[$key] = '';
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $contact);
// $entity[$key] = '';
}
}
return $this->decorateAdvancedFields($contact->client, $entity);
return $entity;
// return $this->decorateAdvancedFields($contact->client, $entity);
}
private function decorateAdvancedFields(Client $client, array $entity) :array

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Credit;
@ -26,6 +27,8 @@ class CreditExport extends BaseExport
private CreditTransformer $credit_transformer;
private Decorator $decorator;
public string $date_key = 'created_at';
public Writer $csv;
@ -35,6 +38,7 @@ class CreditExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->credit_transformer = new CreditTransformer();
$this->decorator = new Decorator();
}
public function returnJson()
@ -143,7 +147,11 @@ class CreditExport extends BaseExport
} elseif(isset($transformed_credit[$searched_credit_key])) {
$entity[$keyval] = $transformed_credit[$searched_credit_key];
} else {
$entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $credit);
// $entity[$key] = '';
// $entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer);
}
}
@ -177,6 +185,14 @@ class CreditExport extends BaseExport
$entity['credit.status'] = $credit->stringStatus($credit->status_id);
}
if (in_array('credit.assigned_user_id', $this->input['report_keys'])) {
$entity['credit.assigned_user_id'] = $credit->assigned_user ? $credit->assigned_user->present()->name(): '';
}
if (in_array('credit.user_id', $this->input['report_keys'])) {
$entity['credit.user_id'] = $credit->user ? $credit->user->present()->name(): '';
}
return $entity;
}
}

View File

@ -11,12 +11,13 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Expense;
use App\Transformers\ExpenseTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -25,6 +26,8 @@ class ExpenseExport extends BaseExport
private $expense_transformer;
private Decorator $decorator;
public string $date_key = 'date';
public Writer $csv;
@ -34,6 +37,7 @@ class ExpenseExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->expense_transformer = new ExpenseTransformer();
$this->decorator = new Decorator();
}
@ -102,7 +106,8 @@ class ExpenseExport extends BaseExport
private function buildRow(Expense $expense) :array
{
$transformed_expense = $this->expense_transformer->transform($expense);
$transformed_expense['currency_id'] = $expense->currency ? $expense->currency->code : $expense->company->currency()->code;
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
@ -113,12 +118,16 @@ class ExpenseExport extends BaseExport
} elseif (array_key_exists($key, $transformed_expense)) {
$entity[$key] = $transformed_expense[$key];
} else {
$entity[$key] = $this->resolveKey($key, $expense, $this->expense_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $expense);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $expense, $this->expense_transformer);
}
}
return $this->decorateAdvancedFields($expense, $entity);
return $entity;
// return $this->decorateAdvancedFields($expense, $entity);
}
private function decorateAdvancedFields(Expense $expense, array $entity) :array

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Invoice;
@ -28,11 +29,14 @@ class InvoiceExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public function __construct(Company $company, array $input)
{
$this->company = $company;
$this->input = $input;
$this->invoice_transformer = new InvoiceTransformer();
$this->decorator = new Decorator();
}
public function init(): Builder
@ -116,12 +120,16 @@ class InvoiceExport extends BaseExport
if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $invoice);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
}
}
return $this->decorateAdvancedFields($invoice, $entity);
return $entity;
// return $this->decorateAdvancedFields($invoice, $entity);
}
private function decorateAdvancedFields(Invoice $invoice, array $entity) :array
@ -151,7 +159,15 @@ class InvoiceExport extends BaseExport
$entity['invoice.auto_bill_enabled'] = $invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no');
}
if (in_array('invoice.assigned_user_id', $this->input['report_keys'])) {
$entity['invoice.assigned_user_id'] = $invoice->assigned_user ? $invoice->assigned_user->present()->name(): '';
}
if (in_array('invoice.user_id', $this->input['report_keys'])) {
$entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name(): '';
}
return $entity;
}
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Invoice;
@ -29,6 +30,8 @@ class InvoiceItemExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
private bool $force_keys = false;
private array $storage_array = [];
@ -46,6 +49,7 @@ class InvoiceItemExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->invoice_transformer = new InvoiceTransformer();
$this->decorator = new Decorator();
}
public function init(): Builder
@ -186,11 +190,14 @@ class InvoiceItemExport extends BaseExport
} elseif (array_key_exists($key, $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$key];
} else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $invoice);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
}
}
return $this->decorateAdvancedFields($invoice, $entity);
return $entity;
// return $this->decorateAdvancedFields($invoice, $entity);
}
private function decorateAdvancedFields(Invoice $invoice, array $entity) :array
@ -227,6 +234,13 @@ class InvoiceItemExport extends BaseExport
$entity['invoice.recurring_id'] = $invoice->recurring_invoice->number ?? '';
}
if (in_array('invoice.assigned_user_id', $this->input['report_keys'])) {
$entity['invoice.assigned_user_id'] = $invoice->assigned_user ? $invoice->assigned_user->present()->name(): '';
}
if (in_array('invoice.user_id', $this->input['report_keys'])) {
$entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name(): '';
}
return $entity;
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Payment;
@ -28,13 +29,16 @@ class PaymentExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public function __construct(Company $company, array $input)
{
$this->company = $company;
$this->input = $input;
$this->entity_transformer = new PaymentTransformer();
$this->decorator = new Decorator();
}
private function init(): Builder
{
@ -113,12 +117,16 @@ class PaymentExport extends BaseExport
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} else {
$entity[$key] = $this->resolveKey($key, $payment, $this->entity_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $payment);
// $entity[$key] = $this->resolveKey($key, $payment, $this->entity_transformer);
}
}
return $this->decorateAdvancedFields($payment, $entity);
return $entity;
// return $this->decorateAdvancedFields($payment, $entity);
}
private function decorateAdvancedFields(Payment $payment, array $entity) :array
@ -167,6 +175,14 @@ class PaymentExport extends BaseExport
$entity['gateway'] = $payment->gateway_type ? $payment->gateway_type->name : 'Unknown Type';
}
if (in_array('payment.assigned_user_id', $this->input['report_keys'])) {
$entity['payment.assigned_user_id'] = $payment->assigned_user ? $payment->assigned_user->present()->name() : '';
}
if (in_array('payment.user_id', $this->input['report_keys'])) {
$entity['payment.user_id'] = $payment->user ? $payment->user->present()->name() : '';
}
// $entity['invoices'] = $payment->invoices()->exists() ? $payment->invoices->pluck('number')->implode(',') : '';
return $entity;

View File

@ -11,14 +11,15 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Utils\Ninja;
use League\Csv\Writer;
use App\Models\Company;
use App\Models\Product;
use App\Transformers\ProductTransformer;
use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use App\Libraries\MultiDB;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
use App\Export\Decorators\Decorator;
use App\Transformers\ProductTransformer;
use Illuminate\Database\Eloquent\Builder;
class ProductExport extends BaseExport
{
@ -28,11 +29,14 @@ class ProductExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public function __construct(Company $company, array $input)
{
$this->company = $company;
$this->input = $input;
$this->entity_transformer = new ProductTransformer();
$this->decorator = new Decorator();
}
public function returnJson()
@ -109,11 +113,15 @@ class ProductExport extends BaseExport
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} else {
$entity[$keyval] = '';
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $product);
// $entity[$key] = '';
}
}
return $this->decorateAdvancedFields($product, $entity);
return $entity;
// return $this->decorateAdvancedFields($product, $entity);
}
private function decorateAdvancedFields(Product $product, array $entity) :array

View File

@ -11,14 +11,15 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Models\PurchaseOrder;
use Illuminate\Support\Facades\App;
use App\Export\Decorators\Decorator;
use Illuminate\Database\Eloquent\Builder;
use App\Transformers\PurchaseOrderTransformer;
class PurchaseOrderExport extends BaseExport
{
@ -29,6 +30,8 @@ class PurchaseOrderExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public array $entity_keys = [
'amount' => 'purchase_order.amount',
'balance' => 'purchase_order.balance',
@ -79,6 +82,7 @@ class PurchaseOrderExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->purchase_order_transformer = new PurchaseOrderTransformer();
$this->decorator = new Decorator();
}
@ -160,13 +164,17 @@ class PurchaseOrderExport extends BaseExport
if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $purchase_order);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
}
}
return $this->decorateAdvancedFields($purchase_order, $entity);
return $entity;
// return $this->decorateAdvancedFields($purchase_order, $entity);
}
private function decorateAdvancedFields(PurchaseOrder $purchase_order, array $entity) :array

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\PurchaseOrder;
@ -29,6 +30,8 @@ class PurchaseOrderItemExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
private bool $force_keys = false;
private array $storage_array = [];
@ -40,6 +43,7 @@ class PurchaseOrderItemExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->purchase_order_transformer = new PurchaseOrderTransformer();
$this->decorator = new Decorator();
}
private function init(): Builder
@ -171,7 +175,10 @@ class PurchaseOrderItemExport extends BaseExport
} elseif (array_key_exists($key, $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$key];
} else {
$entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $purchase_order);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
}
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Quote;
@ -29,6 +30,8 @@ class QuoteExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
private array $decorate_keys = [
'client',
'currency',
@ -40,6 +43,7 @@ class QuoteExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->quote_transformer = new QuoteTransformer();
$this->decorator = new Decorator();
}
private function init(): Builder
@ -122,15 +126,17 @@ class QuoteExport extends BaseExport
if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $quote);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
}
}
return $this->decorateAdvancedFields($quote, $entity);
return $entity;
// return $this->decorateAdvancedFields($quote, $entity);
}
private function decorateAdvancedFields(Quote $quote, array $entity) :array
{
if (in_array('quote.currency_id', $this->input['report_keys'])) {
@ -149,6 +155,15 @@ class QuoteExport extends BaseExport
$entity['quote.invoice'] = $quote->invoice ? $quote->invoice->number : '';
}
if (in_array('quote.assigned_user_id', $this->input['report_keys'])) {
$entity['quote.assigned_user_id'] = $quote->assigned_user ? $quote->assigned_user->present()->name(): '';
}
if (in_array('quote.user_id', $this->input['report_keys'])) {
$entity['quote.user_id'] = $quote->user ? $quote->user->present()->name(): '';
}
return $entity;
}
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Quote;
@ -29,7 +30,10 @@ class QuoteItemExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
private array $storage_array = [];
private array $storage_item_array = [];
private array $decorate_keys = [
@ -42,6 +46,7 @@ class QuoteItemExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->quote_transformer = new QuoteTransformer();
$this->decorator = new Decorator;
}
public function init(): Builder
@ -178,12 +183,14 @@ class QuoteItemExport extends BaseExport
} elseif (array_key_exists($key, $transformed_quote)) {
$entity[$key] = $transformed_quote[$key];
} else {
$entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $quote);
// $entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
}
}
return $this->decorateAdvancedFields($quote, $entity);
return $entity;
// return $this->decorateAdvancedFields($quote, $entity);
}
private function decorateAdvancedFields(Quote $quote, array $entity) :array
{
@ -198,6 +205,16 @@ class QuoteItemExport extends BaseExport
if (in_array('status_id', $this->input['report_keys'])) {
$entity['status'] = $quote->stringStatus($quote->status_id);
}
if (in_array('quote.assigned_user_id', $this->input['report_keys'])) {
$entity['quote.assigned_user_id'] = $quote->assigned_user ? $quote->assigned_user->present()->name(): '';
}
if (in_array('quote.user_id', $this->input['report_keys'])) {
$entity['quote.user_id'] = $quote->user ? $quote->user->present()->name(): '';
}
return $entity;
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\RecurringInvoice;
@ -29,11 +30,14 @@ class RecurringInvoiceExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public function __construct(Company $company, array $input)
{
$this->company = $company;
$this->input = $input;
$this->invoice_transformer = new RecurringInvoiceTransformer();
$this->decorator = new Decorator();
}
public function init(): Builder
@ -105,6 +109,8 @@ class RecurringInvoiceExport extends BaseExport
private function buildRow(RecurringInvoice $invoice) :array
{
$transformed_invoice = $this->invoice_transformer->transform($invoice);
$transformed_invoice['frequency_id'] = $invoice->frequencyForKey($invoice->frequency_id); //need to inject this here because it is also a valid key
// nlog($transformed_invoice);
$entity = [];
@ -114,13 +120,20 @@ class RecurringInvoiceExport extends BaseExport
if (is_array($parts) && $parts[0] == 'recurring_invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
} elseif($parts[0] == 'item'){
$entity[$key] = '';
}
else {
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $invoice);
// $entity[$key] = '';
// $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
}
}
return $this->decorateAdvancedFields($invoice, $entity);
// nlog($entity);
return $entity;
// return $this->decorateAdvancedFields($invoice, $entity);
}
private function decorateAdvancedFields(RecurringInvoice $invoice, array $entity) :array
@ -157,6 +170,15 @@ class RecurringInvoiceExport extends BaseExport
$entity['recurring_invoice.auto_bill_enabled'] = $invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no');
}
if (in_array('recurring_invoice.assigned_user_id', $this->input['report_keys'])) {
$entity['recurring_invoice.assigned_user_id'] = $invoice->assigned_user ? $invoice->assigned_user->present()->name() : '';
}
if (in_array('recurring_invoice.user_id', $this->input['report_keys'])) {
$entity['recurring_invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : '';
}
return $entity;
}
}

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\DateFormat;
@ -34,6 +35,8 @@ class TaskExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
private array $storage_array = [];
private array $storage_item_array = [];
@ -43,6 +46,7 @@ class TaskExport extends BaseExport
$this->company = $company;
$this->input = $input;
$this->entity_transformer = new TaskTransformer();
$this->decorator = new Decorator();
}
public function init(): Builder
@ -133,15 +137,21 @@ class TaskExport extends BaseExport
$entity[$key] = $transformed_entity[$parts[1]];
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} elseif (in_array($key, ['task.start_date', 'task.end_date', 'task.duration'])) {
$entity[$key] = '';
} else {
$entity[$key] = $this->resolveKey($key, $task, $this->entity_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $task);
// $entity[$key] = $this->resolveKey($key, $task, $this->entity_transformer);
}
// $entity['task.start_date'] = '';
// $entity['task.end_date'] = '';
// $entity['task.duration'] = '';
}
$entity['task.start_date'] = '';
$entity['task.end_date'] = '';
$entity['task.duration'] = '';
if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
$this->storage_array[] = $entity;
@ -187,7 +197,7 @@ class TaskExport extends BaseExport
$entity['task.duration'] = $task->calcDuration();
}
$entity = $this->decorateAdvancedFields($task, $entity);
// $entity = $this->decorateAdvancedFields($task, $entity);
$this->storage_array[] = $entity;

View File

@ -11,6 +11,7 @@
namespace App\Export\CSV;
use App\Export\Decorators\Decorator;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Vendor;
@ -30,6 +31,8 @@ class VendorExport extends BaseExport
public Writer $csv;
private Decorator $decorator;
public string $date_key = 'created_at';
public function __construct(Company $company, array $input)
@ -38,6 +41,7 @@ class VendorExport extends BaseExport
$this->input = $input;
$this->vendor_transformer = new VendorTransformer();
$this->contact_transformer = new VendorContactTransformer();
$this->decorator = new Decorator();
}
public function init(): Builder
@ -122,11 +126,15 @@ class VendorExport extends BaseExport
} elseif (is_array($parts) && $parts[0] == 'vendor_contact' && isset($transformed_contact[$parts[1]])) {
$entity[$key] = $transformed_contact[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $vendor, $this->vendor_transformer);
// nlog($key);
$entity[$key] = $this->decorator->transform($key, $vendor);
// $entity[$key] = $this->resolveKey($key, $vendor, $this->vendor_transformer);
}
}
return $this->decorateAdvancedFields($vendor, $entity);
return $entity;
// return $this->decorateAdvancedFields($vendor, $entity);
}
private function decorateAdvancedFields(Vendor $vendor, array $entity) :array

View File

@ -0,0 +1,113 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Client;
class ClientDecorator extends Decorator implements DecoratorInterface
{
private $entity_key = 'client';
public function transform(string $key, mixed $entity): mixed
{
$client = false;
if($entity instanceof Client) {
$client = $entity;
} elseif($entity->client) {
$client = $entity->client;
}
if($client && method_exists($this, $key)) {
return $this->{$key}($client);
}
elseif($client && $client->{$key}) {
return $client->{$key};
}
return '';
}
public function name(Client $client)
{
return $client->present()->name();
}
public function user(Client $client)
{
return $client->user->present()->name();
}
public function assigned_user(Client $client)
{
return $client->assigned_user ? $client->user->present()->name() : '';
}
public function currency_id(Client $client)
{
return $client->currency() ? $client->currency()->code : $client->company->currency()->code;
}
public function private_notes(Client $client)
{
return strip_tags($client->private_notes ?? '');
}
public function industry_id(Client $client)
{
return $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
}
public function size_id(Client $client)
{
return $client->size ? ctrans("texts.size_{$client->size->name}") : '';
}
public function country_id(Client $client)
{
return $client->country ? ctrans("texts.country_{$client->country->name}") : '';
}
public function shipping_country_id(Client $client)
{
return $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : '';
}
public function payment_terms(Client $client)
{
return $client?->settings?->payment_terms ?? $client->company->settings->payment_terms;
}
public function public_notes(Client $client)
{
return strip_tags($client->public_notes ?? '');
}
public function classification(Client $client)
{
ctrans("texts.{$client->classification}") ?? '';
}
public function status(Client $client)
{
if ($client->is_deleted) {
return ctrans('texts.deleted');
}
if ($client->deleted_at) {
return ctrans('texts.archived');
}
return ctrans('texts.active');
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\ClientContact;
class ContactDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$contact = false;
if($entity instanceof ClientContact) {
$contact = $entity;
} elseif($entity->contacts) {
$contact = $entity->contacts()->first();
}
if($contact && method_exists($this, $key)) {
return $this->{$key}($contact);
}
elseif($contact && $contact->{$key}){
return $contact->{$key};
}
return '';
}
}

View File

@ -0,0 +1,135 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Credit;
class CreditDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$credit = false;
if($entity instanceof Credit) {
$credit = $entity;
} elseif($entity->credit) {
$credit = $entity->credit;
}
if($credit && method_exists($this, $key)) {
return $this->{$key}($credit);
} elseif($credit && $credit->{$key}){
return $credit->{$key};
}
return '';
}
public function date(Credit $credit)
{
return $credit->date ?? '';
}
public function due_date(Credit $credit)
{
return $credit->due_date ?? '';
}
public function terms(Credit $credit)
{
return strip_tags($credit->terms ?? '');
}
public function discount(Credit $credit)
{
return $credit->discount ?? 0;
}
public function footer(Credit $credit)
{
return $credit->footer ?? '';
}
public function status(Credit $credit)
{
return $credit->stringStatus($credit->status_id);
}
public function public_notes(Credit $credit)
{
return $credit->public_notes ?? '';
}
public function private_notes(Credit $credit)
{
return $credit->private_notes ?? '';
}
public function uses_inclusive_taxes(Credit $credit)
{
return $credit->uses_inclusive_taxes ? ctrans('texts.yes') : ctrans('texts.no');
}
public function is_amount_discount(Credit $credit)
{
return $credit->is_amount_discount ? ctrans('texts.yes') : ctrans('texts.no');
}
public function partial(Credit $credit)
{
return $credit->partial ?? 0;
}
public function partial_due_date(Credit $credit)
{
return $credit->partial_due_date ?? '';
}
public function custom_surcharge1(Credit $credit)
{
return $credit->custom_surcharge1 ?? 0;
}
public function custom_surcharge2(Credit $credit)
{
return $credit->custom_surcharge2 ?? 0;
}
public function custom_surcharge3(Credit $credit)
{
return $credit->custom_surcharge3 ?? 0;
}
public function custom_surcharge4(Credit $credit)
{
return $credit->custom_surcharge4 ?? 0;
}
public function custom_value1(Credit $credit)
{
return $credit->custom_value1 ?? '';
}
public function custom_value2(Credit $credit)
{
return $credit->custom_value2 ?? '';
}
public function custom_value3(Credit $credit)
{
return $credit->custom_value3 ?? '';
}
public function custom_value4(Credit $credit)
{
return $credit->custom_value4 ?? '';
}
public function exchange_rate(Credit $credit)
{
return $credit->exchange_rate ?? 0;
}
public function total_taxes(Credit $credit)
{
return $credit->total_taxes ?? 0;
}
public function assigned_user_id(Credit $credit)
{
return $credit->assigned_user ? $credit->assigned_user->present()->name(): '';
}
public function user_id(Credit $credit)
{
return $credit->user ? $credit->user->present()->name(): '';
}
}

View File

@ -0,0 +1,106 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
class Decorator implements DecoratorInterface
{
public function __construct()
{
}
public function transform(string $key, mixed $entity): mixed
{
$index = $this->getKeyPart(0, $key);
$column = $this->getKeyPart(1, $key);
return $this->{$index}()->transform($column, $entity);
}
public function invoice(): InvoiceDecorator
{
return new InvoiceDecorator();
}
public function client(): ClientDecorator
{
return new ClientDecorator();
}
public function contact(): ContactDecorator
{
return new ContactDecorator();
}
public function vendor_contact(): VendorContactDecorator
{
return new VendorContactDecorator();
}
public function payment(): PaymentDecorator
{
return new PaymentDecorator();
}
public function credit(): CreditDecorator
{
return new CreditDecorator();
}
public function vendor(): VendorDecorator
{
return new VendorDecorator();
}
public function expense(): ExpenseDecorator
{
return new ExpenseDecorator();
}
public function product(): ProductDecorator
{
return new ProductDecorator();
}
public function project(): ProjectDecorator
{
return new ProjectDecorator();
}
public function task(): TaskDecorator
{
return new TaskDecorator();
}
public function quote(): QuoteDecorator
{
return new QuoteDecorator();
}
public function recurring_invoice(): RecurringInvoiceDecorator
{
return new RecurringInvoiceDecorator();
}
public function purchase_order(): PurchaseOrderDecorator
{
return new PurchaseOrderDecorator();
}
public function getKeyPart(int $index, string $key): string
{
$parts = explode('.', $key);
return $parts[$index];
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
interface DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed;
}

View File

@ -0,0 +1,107 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Expense;
class ExpenseDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$expense = false;
if($entity instanceof Expense) {
$expense = $entity;
} elseif($entity->expense) {
$expense = $entity->expense;
}
if($expense && method_exists($this, $key)) {
return $this->{$key}($expense);
} elseif($expense && $expense->{$key}) {
return $expense->{$key};
}
return '';
}
public function category_id(Expense $expense)
{
return $expense->category ? $expense->category->name : '';
}
public function client_id(Expense $expense)
{
return $expense->client ? $expense->client->present()->name() : '';
}
public function currency_id(Expense $expense)
{
return $expense->currency ? $expense->currency->code : $expense->company->currency()->code;
}
public function date(Expense $expense)
{
return $expense->date ?? '';
}
public function exchange_rate(Expense $expense)
{
return $expense->exchange_rate ?? 0;
}
public function foreign_amount(Expense $expense)
{
return $expense->foreign_amount ?? 0;
}
public function invoice_currency_id(Expense $expense)
{
return $expense->invoice_currency ? $expense->invoice_currency->code : $expense->company->currency()->code;
}
public function payment_date(Expense $expense)
{
return $expense->payment_date ?? '';
}
public function payment_type_id(Expense $expense)
{
return $expense->payment_type ? $expense->payment_type->name : '';
}
public function private_notes(Expense $expense)
{
return strip_tags($expense->private_notes ?? '');
}
public function project_id(Expense $expense)
{
return $expense->project ? $expense->project->name : '';
}
public function public_notes(Expense $expense)
{
return strip_tags($expense->public_notes ?? '');
}
public function vendor_id(Expense $expense)
{
return $expense->vendor ? $expense->vendor->name : '';
}
public function invoice_id(Expense $expense)
{
return $expense->invoice ? $expense->invoice->number : '';
}
public function user(Expense $expense)
{
return $expense->user ? $expense->user->present()->name() : '';
}
public function assigned_user(Expense $expense)
{
return $expense->assigned_user ? $expense->assigned_user->present()->name() : '';
}
}

View File

@ -0,0 +1,101 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Invoice;
class InvoiceDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$invoice = false;
if($entity instanceof Invoice) {
$invoice = $entity;
} elseif($entity->invoice) {
$invoice = $entity->invoice;
} elseif($entity->invoices()->exists()) {
$invoice = $entity->invoices()->first();
}
if($invoice && method_exists($this, $key)) {
return $this->{$key}($invoice);
}elseif($invoice && $invoice->{$key}){
return $invoice->{$key};
}
return '';
}
public function date(Invoice $invoice)
{
return $invoice->date ?? '';
}
public function due_date(Invoice $invoice)
{
return $invoice->due_date ?? '';
}
public function terms(Invoice $invoice)
{
return strip_tags($invoice->terms ?? '');
}
public function footer(Invoice $invoice)
{
return strip_tags($invoice->footer ?? '');
}
public function status(Invoice $invoice)
{
return $invoice->stringStatus($invoice->status_id);
}
public function public_notes(Invoice $invoice)
{
return strip_tags($invoice->public_notes ?? '');
}
public function private_notes(Invoice $invoice)
{
return $invoice->private_notes ?? '';
}
public function uses_inclusive_taxes(Invoice $invoice)
{
return $invoice->uses_inclusive_taxes ? ctrans('texts.yes') : ctrans('texts.no');
}
public function is_amount_discount(Invoice $invoice)
{
return $invoice->is_amount_discount ? ctrans('texts.yes') : ctrans('texts.no');
}
public function partial_due_date(Invoice $invoice)
{
return $invoice->partial_due_date ?? '';
}
public function assigned_user_id(Invoice $invoice)
{
return $invoice->assigned_user ? $invoice->assigned_user->present()->name(): '';
}
public function user_id(Invoice $invoice)
{
return $invoice->user ? $invoice->user->present()->name(): '';
}
public function recurring_id(Invoice $invoice)
{
return $invoice->recurring_invoice ? $invoice->recurring_invoice->number : '';
}
public function auto_bill_enabled(Invoice $invoice)
{
return $invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no');
}
}

View File

@ -0,0 +1,143 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Payment;
class PaymentDecorator extends Decorator implements DecoratorInterface
{
private $entity_key = 'payment';
public function transform(string $key, $entity): mixed
{
$payment = false;
if($entity instanceof Payment) {
$payment = $entity;
} elseif($entity->payment) {
$payment = $entity->payment;
} elseif($entity->payments()->exists()) {
$payment = $entity->payments()->first();
}
if($key == 'amount' && (!$entity instanceof Payment)) {
return $entity->payments()->exists() ? $entity->payments()->withoutTrashed()->sum('paymentables.amount') : ctrans('texts.unpaid');
} elseif($key == 'refunded' && (!$entity instanceof Payment)) {
return $entity->payments()->exists() ? $entity->payments()->withoutTrashed()->sum('paymentables.refunded') : '';
} elseif($key == 'applied' && (!$entity instanceof Payment)) {
$refunded = $entity->payments()->withoutTrashed()->sum('paymentables.refunded');
$amount = $entity->payments()->withoutTrashed()->sum('paymentables.amount');
return $entity->payments()->withoutTrashed()->exists() ? ($amount - $refunded) : '';
}
if($payment && method_exists($this, $key)) {
return $this->{$key}($payment);
}
elseif($payment && $payment->{$key}){
return $payment->{$key};
}
return '';
}
public function date(Payment $payment)
{
return $payment->date ?? '';
}
public function amount(Payment $payment)
{
return $payment->amount ?? '';
}
public function refunded(Payment $payment)
{
return $payment->refunded ?? '';
}
public function applied(Payment $payment)
{
return $payment->applied ?? '';
}
public function transaction_reference(Payment $payment)
{
return $payment->transaction_reference ?? '';
}
public function currency(Payment $payment)
{
return $payment->currency()->exists() ? $payment->currency->code : $payment->company->currency()->code;
}
public function exchange_rate(Payment $payment)
{
return $payment->exchange_rate ?? 1;
}
public function method(Payment $payment)
{
return $payment->translatedType();
}
public function status(Payment $payment)
{
return $payment->stringStatus($payment->status_id);
}
public function private_notes(Payment $payment)
{
return strip_tags($payment->private_notes) ?? '';
}
public function user_id(Payment $payment)
{
return $payment->user ? $payment->user->present()->name() : '';
}
public function assigned_user_id(Payment $payment)
{
return $payment->assigned_user ? $payment->assigned_user->present()->name() : '';
}
public function project_id(Payment $payment)
{
return $payment->project()->exists() ? $payment->project->name : '';
}
///////////////////////////////////////////////////
public function vendor_id(Payment $payment)
{
return $payment->vendor()->exists() ? $payment->vendor->name : '';
}
public function exchange_currency(Payment $payment)
{
return $payment->exchange_currency()->exists() ? $payment->exchange_currency->code : '';
}
public function gateway_type_id(Payment $payment)
{
return $payment->gateway_type ? $payment->gateway_type->name : 'Unknown Type';
}
public function client_id(Payment $payment)
{
return $payment->client->present()->name();
}
public function type_id(Payment $payment)
{
return $payment->translatedType();
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Product;
class ProductDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$product = false;
if($entity instanceof Product) {
$product = $entity;
} elseif($entity->product) {
$product = $entity->product;
}
if($product && method_exists($this, $key)) {
return $this->{$key}($product);
} elseif($product->{$key}) {
return $product->{$key} ?? '';
}
return '';
}
/*
public const PRODUCT_TYPE_PHYSICAL = 1;
public const PRODUCT_TYPE_SERVICE = 2;
public const PRODUCT_TYPE_DIGITAL = 3;
public const PRODUCT_TYPE_SHIPPING = 4;
public const PRODUCT_TYPE_EXEMPT = 5;
public const PRODUCT_TYPE_REDUCED_TAX = 6;
public const PRODUCT_TYPE_OVERRIDE_TAX = 7;
public const PRODUCT_TYPE_ZERO_RATED = 8;
public const PRODUCT_TYPE_REVERSE_TAX = 9;
*/
public function tax_category(Product $product)
{
$category = ctrans('texts.physical_goods');
match($product->tax_id) {
1 => $category = ctrans('texts.physical_goods'),
2 => $category = ctrans('texts.services'),
3 => $category = ctrans('texts.digital_products'),
4 => $category = ctrans('texts.shipping'),
5 => $category = ctrans('texts.tax_exempt'),
6 => $category = ctrans('texts.reduced_tax'),
7 => $category = ctrans('texts.override_tax'),
8 => $category = ctrans('texts.zero_rated'),
9 => $category = ctrans('texts.reverse_tax'),
default => $category = ctrans('texts.physical_goods'),
};
return $category;
}
}

View File

@ -0,0 +1,20 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
class ProjectDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
return 'Payment Decorator';
}
}

View File

@ -0,0 +1,48 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\PurchaseOrder;
class PurchaseOrderDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$purchase_order = false;
if($entity instanceof PurchaseOrder) {
$purchase_order = $entity;
} elseif($entity->purchase_order) {
$purchase_order = $entity->purchase_order;
}
if($purchase_order && method_exists($this, $key)) {
return $this->{$key}($purchase_order);
} elseif($purchase_order->{$key}) {
return $purchase_order->{$key} ?? '';
}
return '';
}
public function status(PurchaseOrder $purchase_order)
{
return $purchase_order->stringStatus($purchase_order->status_id);
}
public function currency_id(PurchaseOrder $purchase_order)
{
return $purchase_order->currency ? $purchase_order->currency->code : $purchase_order->company->currency()->code;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Quote;
class QuoteDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$quote = false;
if($entity instanceof Quote) {
$quote = $entity;
} elseif($entity->quote) {
$quote = $entity->quote;
}
if($quote && method_exists($this, $key)) {
return $this->{$key}($quote);
} elseif($quote->{$key}) {
return $quote->{$key} ?? '';
}
return '';
}
public function status(Quote $quote)
{
return $quote->stringStatus($quote->status_id);
}
public function uses_inclusive_taxes(Quote $quote)
{
return $quote->uses_inclusive_taxes ? ctrans('texts.yes') : ctrans('texts.no');
}
public function is_amount_discount(Quote $quote)
{
return $quote->is_amount_discount ? ctrans('texts.yes') : ctrans('texts.no');
}
public function assigned_user_id(Quote $quote)
{
return $quote->assigned_user ? $quote->assigned_user->present()->name() : '';
}
public function user_id(Quote $quote)
{
return $quote->user->present()->name();
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\RecurringInvoice;
class RecurringInvoiceDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$recurring_invoice = false;
if($entity instanceof RecurringInvoice) {
$recurring_invoice = $entity;
} elseif($entity->recurring_invoice) {
$recurring_invoice = $entity->recurring_invoice;
}
if($recurring_invoice && method_exists($this, $key)) {
return $this->{$key}($recurring_invoice);
} elseif($recurring_invoice->{$key}) {
return $recurring_invoice->{$key} ?? '';
}
return '';
}
public function status(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->stringStatus($recurring_invoice->status_id);
}
public function uses_inclusive_taxes(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->uses_inclusive_taxes ? ctrans('texts.yes') : ctrans('texts.no');
}
public function is_amount_discount(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->is_amount_discount ? ctrans('texts.yes') : ctrans('texts.no');
}
public function assigned_user_id(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->assigned_user ? $recurring_invoice->assigned_user->present()->name() : '';
}
public function user_id(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->user->present()->name() ?? '';
}
public function frequency_id(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->frequency_id ? $recurring_invoice->frequencyForKey($recurring_invoice->frequency_id) : '';
}
public function auto_bill(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->auto_bill ? ctrans("texts.{$recurring_invoice->auto_bill}") : '';
}
public function auto_bill_enabled(RecurringInvoice $recurring_invoice)
{
return $recurring_invoice->auto_bill_enabled ? ctrans('texts.yes') : ctrans('texts.no');
}
}

View File

@ -0,0 +1,114 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\DateFormat;
use App\Models\Task;
use App\Models\Timezone;
use Carbon\Carbon;
class TaskDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$task = false;
if($entity instanceof Task) {
$task = $entity;
} elseif($entity->task) {
$task = $entity->task;
}
if($task && method_exists($this, $key)) {
return $this->{$key}($task);
} elseif($task && $task->{$key}) {
return $task->{$key};
}
return '';
}
public function start_date(Task $task)
{
$timezone = Timezone::find($task->company->settings->timezone_id);
$timezone_name = 'US/Eastern';
if ($timezone) {
$timezone_name = $timezone->name;
}
$logs = json_decode($task->time_log, 1);
$date_format_default = 'Y-m-d';
$date_format = DateFormat::find($task->company->settings->date_format_id);
if ($date_format) {
$date_format_default = $date_format->format;
}
if(is_array($logs)) {
$item = $logs[0];
return Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default);
}
return '';
}
public function end_date(Task $task)
{
$timezone = Timezone::find($task->company->settings->timezone_id);
$timezone_name = 'US/Eastern';
if ($timezone) {
$timezone_name = $timezone->name;
}
$logs = json_decode($task->time_log, 1);
$date_format_default = 'Y-m-d';
$date_format = DateFormat::find($task->company->settings->date_format_id);
if ($date_format) {
$date_format_default = $date_format->format;
}
if(is_array($logs)) {
$item = $logs[1];
return Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default);
}
return '';
}
public function duration(Task $task)
{
return $task->calcDuration();
}
public function status_id(Task $task)
{
return $task->status()->exists() ? $task->status->name : '';
}
public function project_id(Task $task)
{
return $task->project()->exists() ? $task->project->name : '';
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\VendorContact;
class VendorContactDecorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$contact = false;
if($entity instanceof VendorContact) {
$contact = $entity;
} elseif($entity->contacts) {
$contact = $entity->contacts()->first();
}
if($contact && method_exists($this, $key)) {
return $this->{$key}($contact);
} elseif($contact && $contact->{$key}) {
return $contact->{$key} ?? '';
}
return '';
}
}

View File

@ -0,0 +1,71 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Export\Decorators;
use App\Models\Vendor;
class VendorDecorator extends Decorator implements DecoratorInterface
{
public function transform(string $key, mixed $entity): mixed
{
$vendor = false;
if($entity instanceof Vendor) {
$vendor = $entity;
} elseif($entity->vendor) {
$vendor = $entity->vendor;
}
if($vendor && method_exists($this, $key)) {
return $this->{$key}($vendor);
} elseif($vendor->{$key}) {
return $vendor->{$key} ?? '';
}
return '';
}
public function country_id(Vendor $vendor)
{
return $vendor->country ? $vendor->country->name : '';
}
public function name(Vendor $vendor)
{
return $vendor->present()->name();
}
public function currency(Vendor $vendor)
{
return $vendor->currency_id ? $vendor->currency()->code : $vendor->company->currency()->code;
}
public function classification(Vendor $vendor)
{
ctrans("texts.{$vendor->classification}") ?? '';
}
public function status(Vendor $vendor)
{
if ($vendor->is_deleted) {
return ctrans('texts.deleted');
}
if ($vendor->deleted_at) {
return ctrans('texts.archived');
}
return ctrans('texts.active');
}
}

View File

@ -48,7 +48,7 @@ class CompanyFactory
$company->markdown_email_enabled = true;
$company->markdown_enabled = false;
$company->tax_data = new TaxModel();
$company->first_month_of_year = 1;
return $company;
}
}

View File

@ -50,6 +50,7 @@ class PurchaseOrderFactory
$purchase_order->company_id = $company_id;
$purchase_order->recurring_id = null;
$purchase_order->exchange_rate = 1;
$purchase_order->total_taxes = 0;
return $purchase_order;
}

View File

@ -107,13 +107,13 @@ class CreditFilters extends QueryFilters
return $this->builder;
}
return $this->builder->where(function ($query){
$query->whereIn('status_id', [Credit::STATUS_SENT, Credit::STATUS_PARTIAL])
->where('balance', '>', 0)
->where(function ($q){
$q->whereNull('due_date')->orWhere('due_date', '>', now());
});
});
return $this->builder->where(function ($query) {
$query->whereIn('status_id', [Credit::STATUS_SENT, Credit::STATUS_PARTIAL])
->where('balance', '>', 0)
->where(function ($q) {
$q->whereNull('due_date')->orWhere('due_date', '>', now());
});
});
}
public function number(string $number = ''): Builder

View File

@ -93,6 +93,7 @@ class DesignFilters extends QueryFilters
return $this->builder->where('is_template', $bool_val);
}
/**
* Filter the designs by `is_custom` column.
*

View File

@ -33,6 +33,9 @@ class ProjectFilters extends QueryFilters
return $this->builder->where(function ($query) use ($filter) {
$query->where('name', 'like', '%'.$filter.'%')
->orWhereHas('client', function ($q) use ($filter) {
$q->where('name', 'like', '%'.$filter.'%');
})
->orWhere('public_notes', 'like', '%'.$filter.'%')
->orWhere('private_notes', 'like', '%'.$filter.'%');
});
@ -57,6 +60,11 @@ class ProjectFilters extends QueryFilters
{
$sort_col = explode('|', $sort);
if ($sort_col[0] == 'client_id') {
return $this->builder->orderBy(\App\Models\Client::select('name')
->whereColumn('clients.id', 'projects.client_id'), $sort_col[1]);
}
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}

View File

@ -36,6 +36,7 @@ class TaskFilters extends QueryFilters
return $this->builder->where(function ($query) use ($filter) {
$query->where('description', 'like', '%'.$filter.'%')
->orWhere('time_log', 'like', '%'.$filter.'%')
->orWhere('custom_value1', 'like', '%'.$filter.'%')
->orWhere('custom_value2', 'like', '%'.$filter.'%')
->orWhere('custom_value3', 'like', '%'.$filter.'%')
@ -97,6 +98,16 @@ class TaskFilters extends QueryFilters
return $this->builder->where('project_id', $this->decodePrimaryKey($project));
}
public function hash(string $hash = ''): Builder
{
if (strlen($hash) == 0) {
return $this->builder;
}
return $this->builder->where('hash', $hash);
}
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {

View File

@ -69,7 +69,6 @@ class EpcQrGenerator
return '';
}
}
public function encodeMessage()
@ -86,7 +85,7 @@ class EpcQrGenerator
$this->sepa['purpose'],
substr($this->invoice->number, 0, 34),
'',
''
' '
]), "\n");
}

View File

@ -55,7 +55,7 @@ class ContactLoginController extends Controller
/** @var \App\Models\Company $company **/
if ($company) {
$account = $company->account;
} elseif (! $company && strpos($request->getHost(), 'invoicing.co') !== false) {
} elseif (! $company && strpos($request->getHost(), config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $request->getHost())[0];
MultiDB::findAndSetDbByDomain(['subdomain' => $subdomain]);
$company = Company::where('subdomain', $subdomain)->first();

View File

@ -527,6 +527,8 @@ class LoginController extends BaseController
if (request()->has('id_token')) {
$user = $google->getTokenResponse(request()->input('id_token'));
} elseif(request()->has('access_token')) {
$user = $google->harvestUser(request()->input('access_token'));
} else {
return response()->json(['message' => 'Illegal request'], 403);
}

View File

@ -51,7 +51,7 @@ class YodleeController extends BaseController
$this->getAccounts($company, $token);
}
$redirect_url = isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react'] ? 'https://app.invoicing.co/#/' : 'https://invoicing.co/';
$redirect_url = isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react'] ? config('ninja.react_url') : config('ninja.app_url');
$data = [
'access_token' => $yodlee->getAccessToken(),

View File

@ -530,8 +530,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/
$query = $paginator->getCollection();
/** @phpstan-ignore-next-line */
$query = $paginator->getCollection(); // @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type);
@ -636,7 +636,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/
$query = $paginator->getCollection();
$query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
}
@ -885,7 +886,8 @@ class BaseController extends Controller
$paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line **/
$query = $paginator->getCollection();
$query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
@ -926,6 +928,8 @@ class BaseController extends Controller
} //allows us to selective display bank integrations back to the user if they can view / create bank transactions but without the bank balance being present in the response
elseif($this->entity_type == TaxRate::class && $user->hasIntersectPermissions(['create_invoice','edit_invoice','create_quote','edit_quote','create_purchase_order','edit_purchase_order'])) {
// need to show tax rates if the user has the ability to create documents.
} elseif($this->entity_type == ExpenseCategory::class && $user->hasPermission('create_expense')) {
// need to show expense categories if the user has the ability to create expenses.
} else {
$query->where('user_id', '=', $user->id);
}
@ -951,7 +955,8 @@ class BaseController extends Controller
if ($query instanceof Builder) {
$limit = $this->resolveQueryLimit();
$paginator = $query->paginate($limit);
$query = $paginator->getCollection();
$query = $paginator->getCollection();// @phpstan-ignore-line
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
}
@ -1092,8 +1097,8 @@ class BaseController extends Controller
/** @var \App\Models\Account $account */
//always redirect invoicing.co to invoicing.co
if (Ninja::isHosted() && !in_array(request()->getSchemeAndHttpHost(), ['https://staging.invoicing.co', 'https://invoicing.co', 'https://demo.invoicing.co', 'https://invoiceninja.net'])) {
return redirect()->secure('https://invoicing.co');
if (Ninja::isHosted() && !in_array(request()->getSchemeAndHttpHost(), ['https://staging.invoicing.co', 'https://invoicing.co', 'https://demo.invoicing.co', 'https://invoiceninja.net', config('ninja.app_url')])) {
return redirect()->secure(config('ninja.app_url'));
}
if (config('ninja.require_https') && ! request()->isSecure()) {

View File

@ -32,6 +32,7 @@ use App\Models\Client;
use App\Models\Company;
use App\Models\SystemLog;
use App\Repositories\ClientRepository;
use App\Services\Template\TemplateAction;
use App\Transformers\ClientTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions;
@ -217,12 +218,31 @@ class ClientController extends BaseController
$clients = Client::withTrashed()
->company()
->whereIn('id', $request->ids)
->cursor()
->each(function ($client) use ($action, $user) {
if ($user->can('edit', $client)) {
$this->client_repo->{$action}($client);
}
});
->get();
if($action == 'template' && $user->can('view', $clients->first())) {
$hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$clients->pluck('id')->toArray(),
$request->template_id,
Client::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
$clients->each(function ($client) use ($action, $user) {
if ($user->can('edit', $client)) {
$this->client_repo->{$action}($client);
}
});
return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids));
}
@ -364,8 +384,15 @@ class ClientController extends BaseController
try {
/** @var \Postmark\Models\DynamicResponseModel $response */
$response = $postmark->activateBounce((int)$bounce_id);
if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) {
$email = $response->Bounce->Email;
//remove email from quarantine. //@TODO
}
return response()->json(['message' => 'Success'], 200);
} catch(\Exception $e) {

View File

@ -44,7 +44,7 @@ class ApplePayDomainController extends Controller
$domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) {
if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0];
$query = [

View File

@ -167,11 +167,11 @@ class InvitationController extends Controller
{
set_time_limit(45);
if (Ninja::isHosted()) {
return $this->returnRawPdf($entity, $invitation_key);
}
// if (Ninja::isHosted()) {
return $this->returnRawPdf($entity, $invitation_key);
// }
return redirect('client/'.$entity.'/'.$invitation_key.'/download_pdf');
// return redirect('client/'.$entity.'/'.$invitation_key.'/download_pdf');
}
private function returnRawPdf(string $entity, string $invitation_key)

View File

@ -30,7 +30,6 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
class InvoiceController extends Controller
@ -252,11 +251,9 @@ class InvoiceController extends Controller
if ($invoices->count() == 1) {
$invoice = $invoices->first();
$file = $invoice->service()->getInvoicePdf(auth()->guard('contact')->user());
return response()->streamDownload(function () use ($file) {
echo Storage::get($file);
}, basename($file), ['Content-Type' => 'application/pdf']);
return response()->streamDownload(function () use ($invoice) {
echo $invoice->service()->getInvoicePdf(auth()->guard('contact')->user());
}, $invoice->getFileName(), ['Content-Type' => 'application/pdf']);
}
return $this->buildZip($invoices);

View File

@ -86,7 +86,10 @@ class NinjaPlanController extends Controller
public function trial_confirmation(Request $request)
{
$trial_started = "Trial Started @ ".now()->format('Y-m-d H:i:s');
$client = auth()->guard('contact')->user()->client;
$client->private_notes = $trial_started;
$client->fill($request->all());
$client->save();
@ -150,6 +153,7 @@ class NinjaPlanController extends Controller
$account->plan_expires = now()->addDays(14);
$account->is_trial=true;
$account->hosted_company_count = 10;
$account->trial_started = now();
$account->save();
}

View File

@ -194,21 +194,27 @@ class CompanyGatewayController extends BaseController
*/
public function store(StoreCompanyGatewayRequest $request)
{
$company_gateway = CompanyGatewayFactory::create(auth()->user()->company()->id, auth()->user()->id);
/** @var \App\Models\User $user */
$user = auth()->user();
$company_gateway = CompanyGatewayFactory::create($user->company()->id, $user->id);
$company_gateway->fill($request->all());
$company_gateway->save();
/*Always ensure at least one fees and limits object is set per gateway*/
if (! isset($company_gateway->fees_and_limits)) {
$gateway_types = $company_gateway->driver(new Client)->gatewayTypes();
$fees_and_limits = new \stdClass;
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits;
$company_gateway->fees_and_limits = $fees_and_limits;
$company_gateway->save();
$gateway_types = $company_gateway->driver(new Client)->getAvailableMethods();
$fees_and_limits = $company_gateway->fees_and_limits;
foreach($gateway_types as $key => $gateway_type) {
if(!property_exists($fees_and_limits, $key)) {
$fees_and_limits->{$key} = new FeesAndLimits;
}
}
$company_gateway->fees_and_limits = $fees_and_limits;
$company_gateway->save();
ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
if (in_array($company_gateway->gateway_key, $this->stripe_keys)) {
@ -381,10 +387,18 @@ class CompanyGatewayController extends BaseController
{
$company_gateway->fill($request->all());
if (! $request->has('fees_and_limits')) {
$company_gateway->fees_and_limits = '';
/*Always ensure at least one fees and limits object is set per gateway*/
$gateway_types = $company_gateway->driver(new Client)->getAvailableMethods();
$fees_and_limits = $company_gateway->fees_and_limits;
foreach($gateway_types as $key => $gateway_type) {
if(!property_exists($fees_and_limits, $key)) {
$fees_and_limits->{$key} = new FeesAndLimits;
}
}
$company_gateway->fees_and_limits = $fees_and_limits;
$company_gateway->save();
if($company_gateway->gateway_key == $this->checkout_key) {

View File

@ -33,6 +33,7 @@ use App\Models\Credit;
use App\Models\Invoice;
use App\Repositories\CreditRepository;
use App\Services\PdfMaker\PdfMerge;
use App\Services\Template\TemplateAction;
use App\Transformers\CreditTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
@ -550,6 +551,25 @@ class CreditController extends BaseController
}, 'print.pdf', ['Content-Type' => 'application/pdf']);
}
if($action == 'template' && $user->can('view', $credits->first())) {
$hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$credits->pluck('hashed_id')->toArray(),
$request->template_id,
Credit::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
$credits->each(function ($credit, $key) use ($action, $user) {
if ($user->can('edit', $credit)) {
$this->performAction($credit, $action, true);

View File

@ -69,8 +69,12 @@ class EmailController extends BaseController
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('cc_email') && $request->cc_email && (Ninja::isSelfHost() || $user->account->isPaidHostedClient())) {
$mo->cc[] = new Address($request->cc_email);
if ($request->cc_email && (Ninja::isSelfHost() || $user->account->isPaidHostedClient())) {
foreach($request->cc_email as $email) {
$mo->cc[] = new Address($email);
}
}
$entity_obj->invitations->each(function ($invitation) use ($entity_obj, $mo) {

View File

@ -11,28 +11,28 @@
namespace App\Http\Controllers;
use App\Utils\Ninja;
use App\Models\Account;
use App\Models\Expense;
use Illuminate\Http\Response;
use App\Factory\ExpenseFactory;
use App\Filters\ExpenseFilters;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Uploadable;
use App\Utils\Traits\BulkOptions;
use App\Utils\Traits\SavesDocuments;
use App\Repositories\ExpenseRepository;
use App\Transformers\ExpenseTransformer;
use App\Events\Expense\ExpenseWasCreated;
use App\Events\Expense\ExpenseWasUpdated;
use App\Factory\ExpenseFactory;
use App\Filters\ExpenseFilters;
use App\Http\Requests\Expense\BulkExpenseRequest;
use App\Http\Requests\Expense\CreateExpenseRequest;
use App\Http\Requests\Expense\DestroyExpenseRequest;
use App\Http\Requests\Expense\EditExpenseRequest;
use App\Http\Requests\Expense\ShowExpenseRequest;
use App\Http\Requests\Expense\StoreExpenseRequest;
use App\Http\Requests\Expense\CreateExpenseRequest;
use App\Http\Requests\Expense\UpdateExpenseRequest;
use App\Http\Requests\Expense\UploadExpenseRequest;
use App\Http\Requests\Expense\DestroyExpenseRequest;
use App\Models\Account;
use App\Models\Expense;
use App\Repositories\ExpenseRepository;
use App\Transformers\ExpenseTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\SavesDocuments;
use App\Utils\Traits\Uploadable;
use Illuminate\Http\Response;
/**
* Class ExpenseController.

View File

@ -56,11 +56,14 @@ class ExportController extends BaseController
*/
public function index(StoreExportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$hash = Str::uuid();
$url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]);
Cache::put($hash, $url, now()->addHour());
CompanyExport::dispatch(auth()->user()->getCompany(), auth()->user(), $hash);
CompanyExport::dispatch($user->getCompany(), $user, $hash);
return response()->json(['message' => 'Processing', 'url' => $url], 200);
}

View File

@ -416,7 +416,6 @@ class InvoiceController extends BaseController
$invoice->service()
->triggeredActions($request)
// ->deletePdf()
->adjustInventory($old_invoice);
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
@ -526,11 +525,12 @@ class InvoiceController extends BaseController
}
if ($action == 'download' && $invoices->count() >=1 && $user->can('view', $invoices->first())) {
$file = $invoices->first()->service()->getInvoicePdf();
return response()->streamDownload(function () use ($file) {
echo Storage::get($file);
}, basename($file), ['Content-Type' => 'application/pdf']);
$filename = $invoices->first()->getFileName();
return response()->streamDownload(function () use ($invoices) {
echo $invoices->first()->service()->getInvoicePdf();
}, $filename, ['Content-Type' => 'application/pdf']);
}
if ($action == 'bulk_print' && $user->can('view', $invoices->first())) {
@ -538,10 +538,10 @@ class InvoiceController extends BaseController
return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first()))->handle();
});
$merge = (new PdfMerge($paths->toArray()))->run();
return response()->streamDownload(function () use ($merge) {
echo($merge);
return response()->streamDownload(function () use ($paths) {
echo $merge = (new PdfMerge($paths->toArray()))->run();
}, 'print.pdf', ['Content-Type' => 'application/pdf']);
}
@ -700,11 +700,9 @@ class InvoiceController extends BaseController
break;
case 'download':
$file = $invoice->service()->getInvoicePdf();
return response()->streamDownload(function () use ($file) {
echo Storage::get($file);
}, basename($file), ['Content-Type' => 'application/pdf']);
return response()->streamDownload(function () use ($invoice) {
echo $invoice->service()->getInvoicePdf();
}, $invoice->getFileName(), ['Content-Type' => 'application/pdf']);
case 'restore':
$this->invoice_repo->restore($invoice);
@ -936,15 +934,11 @@ class InvoiceController extends BaseController
*/
public function deliveryNote(ShowInvoiceRequest $request, Invoice $invoice)
{
$file = $invoice->service()->getInvoiceDeliveryNote($invoice, $invoice->invitations->first()->contact);
return response()->streamDownload(function () use ($invoice) {
echo $invoice->service()->getInvoiceDeliveryNote($invoice, $invoice->invitations->first()->contact);
}, $invoice->getDeliveryNoteName(), ['Content-Type' => 'application/pdf']);
return response()->streamDownload(function () use ($file) {
echo $file;
}, basename($file), ['Content-Type' => 'application/pdf']);
// return response()->streamDownload(function () use ($file) {
// echo Storage::get($file);
// }, basename($file), ['Content-Type' => 'application/pdf']);
}
/**

View File

@ -14,6 +14,7 @@ namespace App\Http\Controllers;
use App\Events\Payment\PaymentWasUpdated;
use App\Factory\PaymentFactory;
use App\Filters\PaymentFilters;
use App\Http\Requests\Payment\BulkActionPaymentRequest;
use App\Http\Requests\Payment\CreatePaymentRequest;
use App\Http\Requests\Payment\DestroyPaymentRequest;
use App\Http\Requests\Payment\EditPaymentRequest;
@ -25,6 +26,7 @@ use App\Http\Requests\Payment\UploadPaymentRequest;
use App\Models\Account;
use App\Models\Payment;
use App\Repositories\PaymentRepository;
use App\Services\Template\TemplateAction;
use App\Transformers\PaymentTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
@ -499,16 +501,39 @@ class PaymentController extends BaseController
* ),
* )
*/
public function bulk()
public function bulk(BulkActionPaymentRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$action = request()->input('action');
$action = $request->input('action');
$ids = request()->input('ids');
$ids = $request->input('ids');
$payments = Payment::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
if (!$payments) {
return response()->json(['message' => ctrans('texts.record_not_found')]);
}
if($action == 'template' && $user->can('view', $payments->first())) {
$hash_or_response = request()->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
nlog($payments->pluck('hashed_id')->toArray());
TemplateAction::dispatch(
$payments->pluck('hashed_id')->toArray(),
$request->template_id,
Payment::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
$payments = Payment::withTrashed()->find($this->transformKeys($ids));
$payments->each(function ($payment, $key) use ($action, $user) {
if ($user->can('edit', $payment)) {

View File

@ -11,34 +11,31 @@
namespace App\Http\Controllers;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Invoice;
use App\Utils\HtmlEngine;
use Twig\Error\SyntaxError;
use App\Jobs\Util\PreviewPdf;
use App\Models\ClientContact;
use App\Services\Pdf\PdfMock;
use App\Utils\Traits\MakesHash;
use App\Services\Pdf\PdfService;
use App\Utils\PhantomJS\Phantom;
use App\Models\InvoiceInvitation;
use App\Services\PdfMaker\Design;
use App\Utils\HostedPDF\NinjaPdf;
use Illuminate\Support\Facades\DB;
use App\Services\PdfMaker\PdfMaker;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use App\Utils\Traits\MakesInvoiceHtml;
use Turbo124\Beacon\Facades\LightLogs;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\Response;
use App\DataMapper\Analytics\LivePreview;
use App\Services\Template\TemplateService;
use App\Http\Requests\Preview\DesignPreviewRequest;
use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Http\Requests\Preview\PreviewInvoiceRequest;
use App\Jobs\Util\PreviewPdf;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Invoice;
use App\Models\InvoiceInvitation;
use App\Services\Pdf\PdfMock;
use App\Services\Pdf\PdfService;
use App\Services\PdfMaker\Design;
use App\Services\PdfMaker\PdfMaker;
use App\Services\Template\TemplateService;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesInvoiceHtml;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Response;
use Turbo124\Beacon\Facades\LightLogs;
use Twig\Error\SyntaxError;
class PreviewController extends BaseController
{
@ -54,10 +51,6 @@ class PreviewController extends BaseController
public function live(PreviewInvoiceRequest $request): mixed
{
if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) {
return response()->json(['message' => 'This server cannot handle this request.'], 400);
}
$start = microtime(true);
/** Build models */
@ -84,7 +77,6 @@ class PreviewController extends BaseController
$pdf = $ps->boot()->getPdf();
if (Ninja::isHosted()) {
LightLogs::create(new LivePreview())
->increment()
@ -103,141 +95,6 @@ class PreviewController extends BaseController
}
/**
* Refactor - 2023-10-19
*
* New method does not require Transactions.
*
* @param PreviewInvoiceRequest $request
* @return mixed
*/
public function livexx(PreviewInvoiceRequest $request): mixed
{
if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) {
return response()->json(['message' => 'This server cannot handle this request.'], 400);
}
$start = microtime(true);
/** Build models */
$invitation = $request->resolveInvitation();
$client = $request->getClient();
$settings = $client->getMergedSettings();
/** Set translations */
App::forgetInstance('translator');
$t = app('translator');
App::setLocale($invitation->contact->preferredLocale());
$t->replace(Ninja::transformTranslations($settings));
$entity_prop = str_replace("recurring_", "", $request->entity);
$entity_obj = $invitation->{$request->entity};
$entity_obj->fill($request->all());
/** Update necessary objecty props */
if(!$entity_obj->id) {
$entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"}));
$entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer;
$entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms;
$entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes;
$invitation->{$request->entity} = $entity_obj;
}
if(empty($entity_obj->design_id)) {
$entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"}));
}
/** Generate variables */
$html = new HtmlEngine($invitation);
$html->settings = $settings;
$variables = $html->generateLabelsAndValues();
$design = \App\Models\Design::query()->withTrashed()->find($entity_obj->design_id ?? 2);
if ($design->is_custom) {
$options = [
'custom_partials' => json_decode(json_encode($design->design), true),
];
$template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options);
} else {
$template = new PdfMakerDesign(strtolower($design->name));
}
$state = [
'template' => $template->elements([
'client' => $client,
'entity' => $entity_obj,
'pdf_variables' => (array) $settings->pdf_variables,
'$product' => $design->design->product,
'variables' => $variables,
]),
'variables' => $variables,
'options' => [
'all_pages_header' => $client->getSetting('all_pages_header'),
'all_pages_footer' => $client->getSetting('all_pages_footer'),
'client' => $entity_obj->client ?? [],
'vendor' => $entity_obj->vendor ?? [],
$request->input('entity')."s" => [$entity_obj],
],
'process_markdown' => $client->company->markdown_enabled,
];
$maker = new PdfMaker($state);
$maker
->design($template)
->build();
/** Generate HTML */
$html = $maker->getCompiledHTML(true);
if (request()->query('html') == 'true') {
return $html;
}
//if phantom js...... inject here..
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
return (new Phantom)->convertHtmlToPdf($html);
}
/** @var \App\Models\User $user */
$user = auth()->user();
$company = $user->company();
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($html);
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
}
return $pdf;
}
$pdf = (new PreviewPdf($html, $company))->handle();
if (Ninja::isHosted()) {
LightLogs::create(new LivePreview())
->increment()
->batch();
}
/** Return PDF */
return response()->streamDownload(function () use ($pdf) {
echo $pdf;
}, 'preview.pdf', [
'Content-Disposition' => 'inline',
'Content-Type' => 'application/pdf',
'Cache-Control:' => 'no-cache',
'Server-Timing' => microtime(true)-$start
]);
}
/**
* Returns the mocked PDF for the invoice design preview.
*
@ -250,6 +107,10 @@ class PreviewController extends BaseController
{
$start = microtime(true);
if($request->has('entity_type') && in_array($request->entity_type, ['payment_receipt', 'payment_refund', 'statement', 'delivery_note'])) {
return $this->liveTemplate($request->all());
}
/** @var \App\Models\User $user */
$user = auth()->user();
@ -376,6 +237,44 @@ class PreviewController extends BaseController
return $this->blankEntity();
}
private function liveTemplate(array $request_data)
{
nlog($request_data['entity_type']);
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
$design = \App\Models\Design::query()
->where('id', $request_data['design_id'])
->where(function ($q) use ($user) {
$q->whereNull('company_id')->orWhere('company_id', $user->companyId());
})
->first();
$ts = (new TemplateService($design));
try {
if(isset($request_data['settings']) && is_array($request_data['settings'])) {
$ts->setSettings(json_decode(json_encode($request_data['settings'])));
}
$ts->setCompany($company)
->compose()
->mock();
} catch(SyntaxError $e) {
// return response()->json(['message' => 'Twig syntax is invalid.', 'errors' => new \stdClass], 422);
}
$response = Response::make($ts->getPdf(), 200);
$response->header('Content-Type', 'application/pdf');
return $response;
}
private function template()
{
@ -388,6 +287,7 @@ class PreviewController extends BaseController
$design_object = json_decode(json_encode(request()->input('design')), 1);
$ts = (new TemplateService());
try {
$ts->setCompany($company)
->setTemplate($design_object)
@ -395,45 +295,19 @@ class PreviewController extends BaseController
} catch(SyntaxError $e) {
// return response()->json(['message' => 'Twig syntax is invalid.', 'errors' => new \stdClass], 422);
}
$html = $ts->getHtml();
if (request()->query('html') == 'true') {
return $html;
return $ts->getHtml();
}
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
return (new Phantom)->convertHtmlToPdf($html);
}
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($html);
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
}
return $pdf;
}
$file_path = (new PreviewPdf($html, $company))->handle();
$response = Response::make($file_path, 200);
$response = Response::make($ts->getPdf(), 200);
$response->header('Content-Type', 'application/pdf');
return $response;
}
private function stubTemplateData()
{
}
private function blankEntity()
{

View File

@ -11,33 +11,33 @@
namespace App\Http\Controllers;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Vendor;
use App\Libraries\MultiDB;
use App\Jobs\Util\PreviewPdf;
use App\Models\PurchaseOrder;
use App\Models\VendorContact;
use App\Utils\Traits\MakesHash;
use App\Utils\VendorHtmlEngine;
use App\Services\Pdf\PdfService;
use App\Utils\PhantomJS\Phantom;
use App\Services\PdfMaker\Design;
use App\Utils\HostedPDF\NinjaPdf;
use Illuminate\Support\Facades\DB;
use App\Services\PdfMaker\PdfMaker;
use Illuminate\Support\Facades\App;
use App\Factory\PurchaseOrderFactory;
use App\Utils\Traits\MakesInvoiceHtml;
use Turbo124\Beacon\Facades\LightLogs;
use App\Models\PurchaseOrderInvitation;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\Response;
use App\DataMapper\Analytics\LivePreview;
use App\Factory\PurchaseOrderFactory;
use App\Http\Requests\Preview\PreviewPurchaseOrderRequest;
use App\Jobs\Util\PreviewPdf;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderInvitation;
use App\Models\Vendor;
use App\Models\VendorContact;
use App\Repositories\PurchaseOrderRepository;
use App\Services\Pdf\PdfService;
use App\Services\PdfMaker\Design;
use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Http\Requests\Preview\PreviewPurchaseOrderRequest;
use App\Services\PdfMaker\PdfMaker;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\Ninja;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesInvoiceHtml;
use App\Utils\Traits\Pdf\PageNumbering;
use App\Utils\VendorHtmlEngine;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Response;
use Turbo124\Beacon\Facades\LightLogs;
class PreviewPurchaseOrderController extends BaseController
{

View File

@ -13,6 +13,7 @@ namespace App\Http\Controllers;
use App\Factory\ProjectFactory;
use App\Filters\ProjectFilters;
use App\Http\Requests\Project\BulkProjectRequest;
use App\Http\Requests\Project\CreateProjectRequest;
use App\Http\Requests\Project\DestroyProjectRequest;
use App\Http\Requests\Project\EditProjectRequest;
@ -23,6 +24,7 @@ use App\Http\Requests\Project\UploadProjectRequest;
use App\Models\Account;
use App\Models\Project;
use App\Repositories\ProjectRepository;
use App\Services\Template\TemplateAction;
use App\Transformers\ProjectTransformer;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesHash;
@ -490,18 +492,36 @@ class ProjectController extends BaseController
* ),
* )
*/
public function bulk()
public function bulk(BulkProjectRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$action = request()->input('action');
$action = $request->input('action');
$ids = request()->input('ids');
$ids = $request->input('ids');
$projects = Project::withTrashed()->find($this->transformKeys($ids));
$projects = Project::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
$projects->each(function ($project, $key) use ($action, $user) {
if($action == 'template' && $user->can('view', $projects->first())) {
$hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$projects->pluck('hashed_id')->toArray(),
$request->template_id,
Project::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
$projects->each(function ($project) use ($action, $user) {
if ($user->can('edit', $project)) {
$this->project_repo->{$action}($project);
}

View File

@ -19,10 +19,10 @@ use Illuminate\Support\Facades\Storage;
class ProtectedDownloadController extends BaseController
{
public function index(Request $request)
public function index(Request $request, string $hash)
{
/** @var string $hashed_path */
$hashed_path = Cache::pull($request->hash);
$hashed_path = Cache::pull($hash);
if (!$hashed_path) {
throw new SystemError('File no longer available', 404);

View File

@ -32,6 +32,7 @@ use App\Models\Client;
use App\Models\PurchaseOrder;
use App\Repositories\PurchaseOrderRepository;
use App\Services\PdfMaker\PdfMerge;
use App\Services\Template\TemplateAction;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
@ -524,6 +525,24 @@ class PurchaseOrderController extends BaseController
}, 'print.pdf', ['Content-Type' => 'application/pdf']);
}
if($action == 'template' && $user->can('view', $purchase_orders->first())) {
$hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$purchase_orders->pluck('hashed_id')->toArray(),
$request->template_id,
PurchaseOrder::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
/*
* Send the other actions to the switch
*/

View File

@ -34,6 +34,7 @@ use App\Models\Project;
use App\Models\Quote;
use App\Repositories\QuoteRepository;
use App\Services\PdfMaker\PdfMerge;
use App\Services\Template\TemplateAction;
use App\Transformers\InvoiceTransformer;
use App\Transformers\ProjectTransformer;
use App\Transformers\QuoteTransformer;
@ -517,9 +518,9 @@ class QuoteController extends BaseController
/** @var \App\Models\User $user */
$user = auth()->user();
$action = request()->input('action');
$action = $request->input('action');
$ids = request()->input('ids');
$ids = $request->input('ids');
if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !$user->account->account_sms_verified) {
return response(['message' => 'Please verify your account to send emails.'], 400);
@ -584,6 +585,28 @@ class QuoteController extends BaseController
return $this->listResponse(Quote::query()->withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
}
if($action == 'template' && $user->can('view', $quotes->first())) {
$hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$ids,
$request->template_id,
Quote::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
/*
* Send the other actions to the switch
*/
@ -720,11 +743,9 @@ class QuoteController extends BaseController
break;
case 'download':
$file = $quote->service()->getQuotePdf();
return response()->streamDownload(function () use ($file) {
echo $file;
}, $quote->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']);
return response()->streamDownload(function () use ($quote) {
echo $quote->service()->getQuotePdf();
}, $quote->getFileName(), ['Content-Type' => 'application/pdf']);
case 'restore':
$this->quote_repo->restore($quote);
@ -833,11 +854,9 @@ class QuoteController extends BaseController
$headers = array_merge($headers, ['Content-Disposition' => 'inline']);
}
$file = $quote->service()->getQuotePdf($contact);
return response()->streamDownload(function () use ($file) {
echo $file;
}, $quote->numberFormatter().".pdf", $headers);
return response()->streamDownload(function () use ($quote, $contact) {
echo $quote->service()->getQuotePdf($contact);
}, $quote->getFileName(), $headers);
}

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Services\Report\ARDetailReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\ARDetailReport;
use App\Utils\Traits\MakesHash;
class ARDetailReportController extends BaseController
{

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Services\Report\ARSummaryReport;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\ARSummaryReport;
use App\Utils\Traits\MakesHash;
class ARSummaryReportController extends BaseController
{

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Services\Report\ClientBalanceReport;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\ClientBalanceReport;
use App\Utils\Traits\MakesHash;
class ClientBalanceReportController extends BaseController
{

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Services\Report\ClientSalesReport;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\ClientSalesReport;
use App\Utils\Traits\MakesHash;
class ClientSalesReportController extends BaseController
{

View File

@ -11,14 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\ProductSalesExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\ProductSalesReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ProductSalesReportController extends BaseController
{

View File

@ -11,14 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Services\Report\ProfitLoss;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\ProfitLossRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Services\Report\ProfitLoss;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ProfitAndLossController extends BaseController
{

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Services\Report\TaxSummaryReport;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\TaxSummaryReport;
use App\Utils\Traits\MakesHash;
class TaxSummaryReportController extends BaseController
{

View File

@ -11,12 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Services\Report\UserSalesReport;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Services\Report\UserSalesReport;
use App\Utils\Traits\MakesHash;
class UserSalesReportController extends BaseController
{

View File

@ -65,12 +65,10 @@ class SearchController extends Controller
$client->contacts->each(function ($contact) {
$this->client_contacts[] = [
'name' => $contact->present()->search_display(),
'type' => '/client_contact',
'id' => $contact->hashed_id,
'path' => "/clients/{$contact->hashed_id}"
'type' => '/client',
'id' => $contact->client->hashed_id,
'path' => "/clients/{$contact->client->hashed_id}"
];
});
}
@ -173,7 +171,7 @@ class SearchController extends Controller
'integrations,api_tokens' => '/settings/integrations/api_tokens',
'integrations,api_webhooks' => '/settings/integrations/api_webhooks',
'integrations,analytics' => '/settings/integrations/analytics',
'gateways' => '/settings/gateways',
'gateways' => '/settings/online_payments',
'gateways,create' => '/settings/gateways/create',
'bank_accounts,transaction_rules' => '/settings/bank_accounts/transaction_rules',
'bank_accounts,transaction_rules/create' => '/settings/bank_accounts/transaction_rules/create',

View File

@ -51,7 +51,7 @@ class StripeConnectController extends BaseController
}
$stripe_client_id = config('ninja.ninja_stripe_client_id');
$redirect_uri = 'https://invoicing.co/stripe/completed';
$redirect_uri = config('ninja.app_url').'/stripe/completed';
$endpoint = "https://connect.stripe.com/oauth/authorize?response_type=code&client_id={$stripe_client_id}&redirect_uri={$redirect_uri}&scope=read_write&state={$token}";
return redirect($endpoint);
@ -139,9 +139,9 @@ class StripeConnectController extends BaseController
// StripeWebhook::dispatch($company->company_key, $company_gateway->id);
if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) {
$redirect_uri = 'https://app.invoicing.co/#/settings/online_payments';
$redirect_uri = config('ninja.react_url').'/#/settings/online_payments';
} else {
$redirect_uri = 'https://invoicing.co/stripe/completed';
$redirect_uri = config('ninja.app_url').'/stripe/completed';
}
//response here

View File

@ -27,7 +27,7 @@ class SubdomainController extends BaseController
public function index()
{
if (!MultiDB::checkDomainAvailable(request()->input('subdomain'))) {
return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401);
return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401);
}
return response()->json(['message' => 'Domain available'], 200);

View File

@ -15,6 +15,7 @@ use App\Events\Task\TaskWasCreated;
use App\Events\Task\TaskWasUpdated;
use App\Factory\TaskFactory;
use App\Filters\TaskFilters;
use App\Http\Requests\Task\BulkTaskRequest;
use App\Http\Requests\Task\CreateTaskRequest;
use App\Http\Requests\Task\DestroyTaskRequest;
use App\Http\Requests\Task\EditTaskRequest;
@ -27,6 +28,7 @@ use App\Models\Account;
use App\Models\Task;
use App\Models\TaskStatus;
use App\Repositories\TaskRepository;
use App\Services\Template\TemplateAction;
use App\Transformers\TaskTransformer;
use App\Utils\Ninja;
use App\Utils\Traits\BulkOptions;
@ -497,16 +499,36 @@ class TaskController extends BaseController
* ),
* )
*/
public function bulk()
public function bulk(BulkTaskRequest $request)
{
$action = request()->input('action');
/** @var \App\Models\User $user */
$user = auth()->user();
$ids = request()->input('ids');
$tasks = Task::withTrashed()->find($this->transformKeys($ids));
$action = $request->input('action');
$tasks->each(function ($task, $key) use ($action) {
/** @var \App\Models\User $user */
$user = auth()->user();
$ids = $request->input('ids');
$tasks = Task::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
if($action == 'template' && $user->can('view', $tasks->first())) {
$hash_or_response = request()->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid();
TemplateAction::dispatch(
$tasks->pluck('hashed_id')->toArray(),
$request->template_id,
Task::class,
$user->id,
$user->company(),
$user->company()->db,
$hash_or_response,
$request->boolean('send_email')
);
return response()->json(['message' => $hash_or_response], 200);
}
$tasks->each(function ($task) use ($action, $user) {
if ($user->can('edit', $task)) {
$this->task_repo->{$action}($task);
}

View File

@ -11,23 +11,23 @@
namespace App\Http\Controllers\VendorPortal;
use App\Utils\Ninja;
use Illuminate\View\View;
use App\Models\PurchaseOrder;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesDates;
use App\Jobs\Entity\CreateRawPdf;
use App\Http\Controllers\Controller;
use App\Jobs\Invoice\InjectSignature;
use Illuminate\Support\Facades\Cache;
use Illuminate\Contracts\View\Factory;
use App\Models\PurchaseOrderInvitation;
use App\Events\Misc\InvitationWasViewed;
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
use App\Http\Controllers\Controller;
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest;
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrdersRequest;
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
use App\Jobs\Entity\CreateRawPdf;
use App\Jobs\Invoice\InjectSignature;
use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderInvitation;
use App\Utils\Ninja;
use App\Utils\Traits\MakesDates;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\View\Factory;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
class PurchaseOrderController extends Controller
{

View File

@ -22,7 +22,7 @@ class ContactRegister
$domain_name = $request->getHost();
/* Hosted */
if (strpos($domain_name, 'invoicing.co') !== false) {
if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0];
$query = [

View File

@ -17,6 +17,48 @@ use Illuminate\Support\Facades\App;
class Locale
{
private array $locales = [
'en',
'it',
'de',
'fr',
'pt_BR',
'nl',
'es',
'nb_NO',
'da',
'ja',
'sv',
'es_ES',
'fr_CA',
'lt',
'pl',
'cs',
'hr',
'sq',
'el',
'en_GB',
'pt_PT',
'sl',
'fi',
'ro',
'tr_TR',
'th',
'mk_MK',
'zh_TW',
'ru_RU',
'ar',
'fa',
'lv_LV',
'sr',
'sk',
'et',
'bg',
'he',
'km_KH',
'hu',
'fr_CH',
];
/**
* Handle an incoming request.
*
@ -27,8 +69,8 @@ class Locale
public function handle($request, Closure $next)
{
/*LOCALE SET */
if ($request->has('lang') && is_string($request->input('lang'))) {
$locale = $request->string('lang','en');
if ($request->has('lang') && in_array($request->input('lang', 'en'), $this->locales)) {
$locale = $request->input('lang');
App::setLocale($locale);
} elseif (auth()->guard('contact')->user()) {
App::setLocale(auth()->guard('contact')->user()->client()->setEagerLoads([])->first()->locale());

View File

@ -32,8 +32,7 @@ class SessionDomains
$domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) {
// config(['session.domain' => '.invoicing.co']);
if (strpos($domain_name, config('ninja.app_domain')) !== false) {
} else {
config(['session.domain' => $domain_name]);
}

View File

@ -41,7 +41,7 @@ class SetDomainNameDb
$domain_name = $request->getHost();
if (strpos($domain_name, 'invoicing.co') !== false) {
if (strpos($domain_name, config('ninja.app_domain')) !== false) {
$subdomain = explode('.', $domain_name)[0];
$query = [

View File

@ -17,6 +17,48 @@ use Illuminate\Support\Facades\App;
class VendorLocale
{
private array $locales = [
'en',
'it',
'de',
'fr',
'pt_BR',
'nl',
'es',
'nb_NO',
'da',
'ja',
'sv',
'es_ES',
'fr_CA',
'lt',
'pl',
'cs',
'hr',
'sq',
'el',
'en_GB',
'pt_PT',
'sl',
'fi',
'ro',
'tr_TR',
'th',
'mk_MK',
'zh_TW',
'ru_RU',
'ar',
'fa',
'lv_LV',
'sr',
'sk',
'et',
'bg',
'he',
'km_KH',
'hu',
'fr_CH',
];
/**
* Handle an incoming request.
*
@ -32,7 +74,7 @@ class VendorLocale
}
/*LOCALE SET */
if ($request->has('lang') && is_string($request->input('lang'))) {
if ($request->has('lang') && in_array($request->input('lang', 'en'), $this->locales)) {
$locale = $request->input('lang');
App::setLocale($locale);
} elseif (auth()->guard('vendor')->user()) {

View File

@ -45,10 +45,15 @@ class CreateAccountRequest extends Request
return [
'first_name' => 'string|max:100',
'last_name' => 'string:max:100',
'password' => 'required|string|min:6|max:1000',
'password' => 'required|string|min:6|max:100',
'email' => $email_rules,
'privacy_policy' => 'required|boolean',
'terms_of_service' => 'required|boolean',
'utm_source' => 'sometimes|nullable|string',
'utm_medium' => 'sometimes|nullable|string',
'utm_campaign' => 'sometimes|nullable|string',
'utm_term' => 'sometimes|nullable|string',
'utm_content' => 'sometimes|nullable|string',
];
}

View File

@ -35,9 +35,13 @@ class BulkClientRequest extends Request
$user = auth()->user();
return [
'action' => 'required|string|in:archive,restore,delete,template',
'ids' => ['required','bail','array',Rule::exists('clients', 'id')->where('company_id', $user->company()->id)],
'action' => 'in:archive,restore,delete'
'template' => 'sometimes|string',
'template_id' => 'sometimes|string',
'send_email' => 'sometimes|bool'
];
}
public function prepareForValidation()

View File

@ -28,7 +28,10 @@ class StoreCompanyGatewayRequest extends Request
*/
public function authorize() : bool
{
return auth()->user()->isAdmin();
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->isAdmin();
}
public function rules()
@ -64,6 +67,7 @@ class StoreCompanyGatewayRequest extends Request
if (isset($input['fees_and_limits'])) {
$input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']);
}
}
$this->replace($input);

View File

@ -27,7 +27,10 @@ class UpdateCompanyGatewayRequest extends Request
*/
public function authorize()
{
return auth()->user()->isAdmin();
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->isAdmin();
}
public function rules()

View File

@ -35,9 +35,15 @@ class BulkCreditRequest extends FormRequest
*/
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
return [
'ids' => ['required','bail','array',Rule::exists('credits', 'id')->where('company_id', auth()->user()->company()->id)],
'action' => 'required|bail|in:archive,restore,delete,email,bulk_download,bulk_print,mark_paid,clone_to_credit,history,mark_sent,download,send_email'
'ids' => ['required','bail','array',Rule::exists('credits', 'id')->where('company_id', $user->company()->id)],
'action' => 'required|bail|in:archive,restore,delete,email,bulk_download,bulk_print,mark_paid,clone_to_credit,history,mark_sent,download,send_email,template',
'template' => 'sometimes|string',
'template_id' => 'sometimes|string',
'send_email' => 'sometimes|bool'
];
}

View File

@ -11,8 +11,8 @@
namespace App\Http\Requests\Design;
use App\Models\Account;
use App\Http\Requests\Request;
use App\Models\Account;
use App\Utils\Traits\ChecksEntityStatus;
class UpdateDesignRequest extends Request

View File

@ -43,8 +43,10 @@ class SendEmailRequest extends Request
'template' => 'bail|required',
'entity' => 'bail|required',
'entity_id' => 'bail|required',
'cc_email' => 'bail|sometimes|email|nullable',
'cc_email.*' => 'bail|sometimes|email',
];
}
public function prepareForValidation()
@ -72,6 +74,14 @@ class SendEmailRequest extends Request
$input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity']));
}
if(isset($input['cc_email'])) {
$input['cc_email'] = collect(explode(",", $input['cc_email']))->map(function ($email) {
return trim($email);
})->filter(function ($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
})->slice(0, 4)->toArray();
}
$this->replace($input);
}

View File

@ -28,34 +28,45 @@ class StoreExpenseRequest extends Request
*/
public function authorize() : bool
{
return auth()->user()->can('create', Expense::class);
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->can('create', Expense::class);
}
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = [];
if ($this->number) {
$rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id);
$rules['number'] = Rule::unique('expenses')->where('company_id', $user->company()->id);
}
if ($this->client_id) {
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id;
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.$user->company()->id;
}
$rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
$rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.$user->company()->id.',is_deleted,0';
$rules['payment_date'] = 'bail|nullable|sometimes|date:Y-m-d';
$rules['date'] = 'bail|sometimes|date:Y-m-d';
return $this->globalRules($rules);
}
public function prepareForValidation()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$input = $this->all();
$input = $this->decodePrimaryKeys($input);
if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) {
$input['currency_id'] = (string) auth()->user()->company()->settings->currency_id;
$input['currency_id'] = (string) $user->company()->settings->currency_id;
}
if (array_key_exists('color', $input) && is_null($input['color'])) {
@ -80,7 +91,6 @@ class StoreExpenseRequest extends Request
public function messages()
{
return [
// 'unique' => ctrans('validation.unique', ['attribute' => 'number']),
];
}
}

View File

@ -22,7 +22,10 @@ class ImportRequest extends Request
*/
public function authorize() : bool
{
return auth()->user()->isAdmin();
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->isAdmin();
}
public function rules()

Some files were not shown because too many files have changed in this diff Show More