mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-04 17:14:36 -04:00
Merge pull request #5693 from turbo124/v5-develop
Fixes for attaching documents and pdfs
This commit is contained in:
commit
4251a57d87
@ -104,9 +104,9 @@ class ForgotPasswordController extends Controller
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
//MultiDB::userFindAndSetDb($request->input('email'));
|
||||
MultiDB::userFindAndSetDb($request->input('email'));
|
||||
|
||||
$user = MultiDB::hasUser(['email' => $request->input('email')]);
|
||||
// $user = MultiDB::hasUser(['email' => $request->input('email')]);
|
||||
|
||||
$this->validateEmail($request);
|
||||
|
||||
|
64
app/Http/Controllers/ExportController.php
Normal file
64
app/Http/Controllers/ExportController.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Export\StoreExportRequest;
|
||||
use App\Jobs\Company\CompanyExport;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class ExportController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/export",
|
||||
* operationId="getExport",
|
||||
* tags={"export"},
|
||||
* summary="Export data from the system",
|
||||
* description="Export data from the system",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function index(StoreExportRequest $request)
|
||||
{
|
||||
|
||||
CompanyExport::dispatch(auth()->user()->getCompany(), auth()->user());
|
||||
|
||||
return response()->json(['message' => 'Processing'], 200);
|
||||
|
||||
}
|
||||
}
|
39
app/Http/Requests/Export/StoreExportRequest.php
Normal file
39
app/Http/Requests/Export/StoreExportRequest.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
|
||||
namespace App\Http\Requests\Export;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class StoreExportRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
471
app/Jobs/Company/CompanyExport.php
Normal file
471
app/Jobs/Company/CompanyExport.php
Normal file
@ -0,0 +1,471 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Company;
|
||||
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Jobs\Util\UnlinkFile;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\DownloadBackup;
|
||||
use App\Mail\DownloadInvoices;
|
||||
use App\Models\Company;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
use App\Models\User;
|
||||
use App\Models\VendorContact;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class CompanyExport implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
|
||||
|
||||
public $company;
|
||||
|
||||
private $export_format;
|
||||
|
||||
private $export_data = [];
|
||||
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param Company $company
|
||||
* @param User $user
|
||||
* @param string $custom_token_name
|
||||
*/
|
||||
public function __construct(Company $company, User $user, $export_format = 'json')
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->user = $user;
|
||||
$this->export_format = $export_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return CompanyToken|null
|
||||
*/
|
||||
public function handle() : void
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
$this->export_data['app_version'] = config('ninja.app_version');
|
||||
|
||||
$this->export_data['activities'] = $this->company->all_activities->map(function ($activity){
|
||||
|
||||
$activity = $this->transformArrayOfKeys($activity, [
|
||||
'user_id',
|
||||
'company_id',
|
||||
'client_id',
|
||||
'client_contact_id',
|
||||
'account_id',
|
||||
'project_id',
|
||||
'vendor_id',
|
||||
'payment_id',
|
||||
'invoice_id',
|
||||
'credit_id',
|
||||
'invitation_id',
|
||||
'task_id',
|
||||
'expense_id',
|
||||
'token_id',
|
||||
'quote_id',
|
||||
'subscription_id',
|
||||
'recurring_invoice_id'
|
||||
]);
|
||||
|
||||
return $activity;
|
||||
|
||||
})->makeHidden(['id'])->toArray();
|
||||
|
||||
$this->export_data['backups'] = $this->company->all_activities()->with('backup')->cursor()->map(function ($activity){
|
||||
|
||||
$backup = $activity->backup;
|
||||
|
||||
if(!$backup)
|
||||
return;
|
||||
|
||||
$backup->activity_id = $this->encodePrimaryKey($backup->activity_id);
|
||||
|
||||
return $backup;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['client_contacts'] = $this->company->client_contacts->map(function ($client_contact){
|
||||
|
||||
$client_contact = $this->transformArrayOfKeys($client_contact, ['id', 'company_id', 'user_id',' client_id']);
|
||||
|
||||
return $client_contact;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['client_gateway_tokens'] = $this->company->client_gateway_tokens->map(function ($client_gateway_token){
|
||||
|
||||
$client_gateway_token = $this->transformArrayOfKeys($client_gateway_token, ['id', 'company_id', 'client_id']);
|
||||
|
||||
return $client_gateway_token;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['clients'] = $this->company->clients->map(function ($client){
|
||||
|
||||
$client = $this->transformArrayOfKeys($client, ['id', 'company_id', 'user_id',' assigned_user_id', 'group_settings_id']);
|
||||
|
||||
return $client;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$temp_co = $this->company;
|
||||
$temp_co->id = $this->encodePrimaryKey($temp_co->id);
|
||||
$temp_co->account_id = $this->encodePrimaryKey($temp_co->account_id);
|
||||
|
||||
$this->export_data['company'] = $temp_co->toArray();
|
||||
|
||||
$this->export_data['company_gateways'] = $this->company->company_gateways->map(function ($company_gateway){
|
||||
|
||||
$company_gateway = $this->transformArrayOfKeys($company_gateway, ['company_id', 'user_id']);
|
||||
|
||||
return $company_gateway;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['company_tokens'] = $this->company->tokens->map(function ($token){
|
||||
|
||||
$token = $this->transformArrayOfKeys($token, ['company_id', 'account_id', 'user_id']);
|
||||
|
||||
return $token;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['company_ledger'] = $this->company->ledger->map(function ($ledger){
|
||||
|
||||
$ledger = $this->transformArrayOfKeys($ledger, ['activity_id', 'client_id', 'company_id', 'account_id', 'user_id','company_ledgerable_id']);
|
||||
|
||||
return $ledger;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['company_users'] = $this->company->company_users->map(function ($company_user){
|
||||
|
||||
$company_user = $this->transformArrayOfKeys($company_user, ['company_id', 'account_id', 'user_id']);
|
||||
|
||||
return $company_user;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['credits'] = $this->company->credits->map(function ($credit){
|
||||
|
||||
$credit = $this->transformBasicEntities($credit);
|
||||
$credit = $this->transformArrayOfKeys($credit, ['recurring_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id','invoice_id']);
|
||||
|
||||
return $credit;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['credit_invitations'] = CreditInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($credit){
|
||||
|
||||
$credit = $this->transformArrayOfKeys($credit, ['company_id', 'user_id', 'client_contact_id', 'recurring_invoice_id']);
|
||||
|
||||
return $credit;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['designs'] = $this->company->user_designs->makeHidden(['id'])->toArray();
|
||||
|
||||
$this->export_data['documents'] = $this->company->documents->map(function ($document){
|
||||
|
||||
$document = $this->transformArrayOfKeys($document, ['user_id', 'assigned_user_id', 'company_id', 'project_id', 'vendor_id']);
|
||||
|
||||
return $document;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['expense_categories'] = $this->company->expenses->map(function ($expense_category){
|
||||
|
||||
$expense_category = $this->transformArrayOfKeys($expense_category, ['user_id', 'company_id']);
|
||||
|
||||
return $expense_category;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['expenses'] = $this->company->expenses->map(function ($expense){
|
||||
|
||||
$expense = $this->transformBasicEntities($expense);
|
||||
$expense = $this->transformArrayOfKeys($expense, ['vendor_id', 'invoice_id', 'client_id', 'category_id', 'recurring_expense_id','project_id']);
|
||||
|
||||
return $expense;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['group_settings'] = $this->company->group_settings->map(function ($gs){
|
||||
|
||||
$gs = $this->transformArrayOfKeys($gs, ['user_id', 'company_id']);
|
||||
|
||||
return $gs;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['invoices'] = $this->company->invoices->map(function ($invoice){
|
||||
|
||||
$invoice = $this->transformBasicEntities($invoice);
|
||||
$invoice = $this->transformArrayOfKeys($invoice, ['recurring_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id']);
|
||||
|
||||
return $invoice;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['invoice_invitations'] = InvoiceInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($invoice){
|
||||
|
||||
$invoice = $this->transformArrayOfKeys($invoice, ['company_id', 'user_id', 'client_contact_id', 'recurring_invoice_id']);
|
||||
|
||||
return $invoice;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['payment_terms'] = $this->company->user_payment_terms->map(function ($term){
|
||||
|
||||
$term = $this->transformArrayOfKeys($term, ['user_id', 'company_id']);
|
||||
|
||||
return $term;
|
||||
|
||||
})->makeHidden(['id'])->toArray();
|
||||
|
||||
$this->export_data['paymentables'] = $this->company->payments()->with('paymentables')->cursor()->map(function ($paymentable){
|
||||
|
||||
$paymentable = $this->transformArrayOfKeys($paymentable, ['payment_id','paymentable_id']);
|
||||
|
||||
return $paymentable;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['payments'] = $this->company->payments->map(function ($payment){
|
||||
|
||||
$payment = $this->transformBasicEntities($payment);
|
||||
$payment = $this->transformArrayOfKeys($payment, ['client_id','project_id', 'vendor_id', 'client_contact_id', 'invitation_id', 'company_gateway_id']);
|
||||
|
||||
return $project;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['projects'] = $this->company->projects->map(function ($project){
|
||||
|
||||
$project = $this->transformBasicEntities($project);
|
||||
$project = $this->transformArrayOfKeys($project, ['client_id']);
|
||||
|
||||
return $project;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['quotes'] = $this->company->quotes->map(function ($quote){
|
||||
|
||||
$quote = $this->transformBasicEntities($quote);
|
||||
$quote = $this->transformArrayOfKeys($quote, ['invoice_id','recurring_id','client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id']);
|
||||
|
||||
return $quote;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['quote_invitations'] = QuoteInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($quote){
|
||||
|
||||
$quote = $this->transformArrayOfKeys($quote, ['company_id', 'user_id', 'client_contact_id', 'recurring_invoice_id']);
|
||||
|
||||
return $quote;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['recurring_invoices'] = $this->company->recurring_invoices->map(function ($ri){
|
||||
|
||||
$ri = $this->transformBasicEntities($ri);
|
||||
$ri = $this->transformArrayOfKeys($ri, ['client_id', 'vendor_id', 'project_id', 'design_id', 'subscription_id']);
|
||||
return $ri;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['recurring_invoice_invitations'] = RecurringInvoiceInvitation::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($ri){
|
||||
|
||||
$ri = $this->transformArrayOfKeys($ri, ['company_id', 'user_id', 'client_contact_id', 'recurring_invoice_id']);
|
||||
|
||||
return $ri;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['subscriptions'] = $this->company->subscriptions->map(function ($subscription){
|
||||
|
||||
$subscription = $this->transformBasicEntities($subscription);
|
||||
$subscription->group_id = $this->encodePrimaryKey($subscription->group_id);
|
||||
|
||||
return $subscription;
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['system_logs'] = $this->company->system_logs->map(function ($log){
|
||||
|
||||
$log->client_id = $this->encodePrimaryKey($log->client_id);
|
||||
$log->company_id = $this->encodePrimaryKey($log->company_id);
|
||||
|
||||
return $log;
|
||||
|
||||
})->makeHidden(['id'])->toArray();
|
||||
|
||||
$this->export_data['tasks'] = $this->company->tasks->map(function ($task){
|
||||
|
||||
$task = $this->transformBasicEntities($task);
|
||||
$task = $this->transformArrayOfKeys($task, ['client_id', 'invoice_id', 'project_id', 'status_id']);
|
||||
|
||||
return $task;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['task_statuses'] = $this->company->task_statuses->map(function ($status){
|
||||
|
||||
$status->id = $this->encodePrimaryKey($status->id);
|
||||
$status->user_id = $this->encodePrimaryKey($status->user_id);
|
||||
$status->company_id = $this->encodePrimaryKey($status->company_id);
|
||||
|
||||
return $status;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['tax_rates'] = $this->company->tax_rates->map(function ($rate){
|
||||
|
||||
$rate->company_id = $this->encodePrimaryKey($rate->company_id);
|
||||
$rate->user_id = $this->encodePrimaryKey($rate->user_id);
|
||||
|
||||
return $rate;
|
||||
|
||||
})->makeHidden(['id'])->toArray();
|
||||
|
||||
$this->export_data['users'] = $this->company->users->map(function ($user){
|
||||
|
||||
$user->account_id = $this->encodePrimaryKey($user->account_id);
|
||||
$user->id = $this->encodePrimaryKey($user->id);
|
||||
|
||||
return $user;
|
||||
|
||||
})->makeHidden(['ip'])->toArray();
|
||||
|
||||
$this->export_data['vendors'] = $this->company->vendors->map(function ($vendor){
|
||||
|
||||
return $this->transformBasicEntities($vendor);
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
$this->export_data['vendor_contacts'] = VendorContact::where('company_id', $this->company->id)->withTrashed()->cursor()->map(function ($vendor){
|
||||
|
||||
$vendor = $this->transformBasicEntities($vendor);
|
||||
$vendor->vendor_id = $this->encodePrimaryKey($vendor->vendor_id);
|
||||
|
||||
return $vendor;
|
||||
|
||||
})->toArray();
|
||||
|
||||
$this->export_data['webhooks'] = $this->company->webhooks->map(function ($hook){
|
||||
|
||||
$hook->user_id = $this->encodePrimaryKey($hook->user_id);
|
||||
$hook->company_id = $this->encodePrimaryKey($hook->company_id);
|
||||
|
||||
return $hook;
|
||||
|
||||
})->makeHidden(['id'])->toArray();
|
||||
|
||||
//write to tmp and email to owner();
|
||||
|
||||
$this->zipAndSend();
|
||||
}
|
||||
|
||||
private function transformBasicEntities($model)
|
||||
{
|
||||
|
||||
return $this->transformArrayOfKeys($model, ['id', 'user_id', 'assigned_user_id', 'company_id']);
|
||||
|
||||
}
|
||||
|
||||
private function transformArrayOfKeys($model, $keys)
|
||||
{
|
||||
|
||||
foreach($keys as $key){
|
||||
$model->{$key} = $this->encodePrimaryKey($model->{$key});
|
||||
}
|
||||
|
||||
return $model;
|
||||
|
||||
}
|
||||
|
||||
private function zipAndSend()
|
||||
{
|
||||
nlog("zipping");
|
||||
|
||||
$tempStream = fopen('php://memory', 'w+');
|
||||
|
||||
$options = new Archive();
|
||||
$options->setOutputStream($tempStream);
|
||||
|
||||
$file_name = date('Y-m-d').'_'.str_replace(' ', '_', $this->company->present()->name() . '_' . $this->company->company_key .'.zip');
|
||||
|
||||
$zip = new ZipStream($file_name, $options);
|
||||
|
||||
$fp = tmpfile();
|
||||
fwrite($fp, json_encode($this->export_data));
|
||||
rewind($fp);
|
||||
$zip->addFileFromStream('backup.json', $fp);
|
||||
|
||||
$zip->finish();
|
||||
|
||||
$path = 'backups/';
|
||||
|
||||
nlog($path.$file_name);
|
||||
|
||||
Storage::disk(config('filesystems.default'))->put($path.$file_name, $tempStream);
|
||||
// fclose($fp);
|
||||
|
||||
nlog(Storage::disk(config('filesystems.default'))->url($path.$file_name));
|
||||
|
||||
fclose($tempStream);
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new DownloadBackup(Storage::disk(config('filesystems.default'))->url($path.$file_name), $this->company);
|
||||
$nmo->to_user = $this->user;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->company = $this->company;
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
|
||||
UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1));
|
||||
}
|
||||
|
||||
}
|
@ -54,7 +54,9 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
public $nmo;
|
||||
|
||||
public function __construct(NinjaMailerObject $nmo)
|
||||
public $override;
|
||||
|
||||
public function __construct(NinjaMailerObject $nmo, bool $override = false)
|
||||
{
|
||||
|
||||
$this->nmo = $nmo;
|
||||
@ -64,7 +66,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
public function handle()
|
||||
{
|
||||
/*If we are migrating data we don't want to fire any emails*/
|
||||
if ($this->nmo->company->is_disabled)
|
||||
if ($this->nmo->company->is_disabled && !$this->override)
|
||||
return true;
|
||||
|
||||
/*Set the correct database*/
|
||||
@ -83,6 +85,10 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$this->nmo->mailable->replyTo($this->nmo->settings->reply_to_email, $reply_to_name);
|
||||
|
||||
}
|
||||
else {
|
||||
$this->nmo->mailable->replyTo($this->nmo->company->owner()->email, $this->nmo->company->owner()->present()->name());
|
||||
}
|
||||
|
||||
|
||||
if (strlen($this->nmo->settings->bcc_email) > 1) {
|
||||
nlog('bcc list available');
|
||||
|
@ -55,9 +55,6 @@ class UserEmailChanged implements ShouldQueue
|
||||
public function handle()
|
||||
{
|
||||
nlog("notifying user of email change");
|
||||
|
||||
if ($this->company->is_disabled)
|
||||
return true;
|
||||
|
||||
//Set DB
|
||||
MultiDB::setDb($this->company->db);
|
||||
@ -78,7 +75,7 @@ class UserEmailChanged implements ShouldQueue
|
||||
$nmo->company = $this->company;
|
||||
$nmo->to_user = $this->old_user;
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
|
||||
// $nmo->to_user = $this->new_user;
|
||||
// NinjaMailerJob::dispatch($nmo);
|
||||
|
@ -209,6 +209,9 @@ class Import implements ShouldQueue
|
||||
$this->{$method}($data[$import]);
|
||||
}
|
||||
|
||||
if(Ninja::isHosted())
|
||||
$this->processNinjaTokens($data['ninja_tokens']);
|
||||
|
||||
$this->setInitialCompanyLedgerBalances();
|
||||
|
||||
// $this->fixClientBalances();
|
||||
@ -1636,6 +1639,10 @@ class Import implements ShouldQueue
|
||||
return $response->getBody();
|
||||
}
|
||||
|
||||
private function processNinjaTokens(array $data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* In V4 we use negative invoices (credits) and add then into the client balance. In V5, these sit off ledger and are applied later.
|
||||
This next section will check for credit balances and reduce the client balance so that the V5 balances are correct
|
||||
|
@ -129,13 +129,12 @@ class MultiDB
|
||||
}
|
||||
|
||||
foreach (self::$dbs as $db) {
|
||||
|
||||
self::setDB($db);
|
||||
|
||||
$user = User::where($data)->withTrashed()->first();
|
||||
|
||||
if ($user) {
|
||||
if ($user = User::where($data)->withTrashed()->first())
|
||||
return $user;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self::setDefaultDatabase();
|
||||
|
41
app/Mail/DownloadBackup.php
Normal file
41
app/Mail/DownloadBackup.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Company;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DownloadBackup extends Mailable
|
||||
{
|
||||
// use Queueable, SerializesModels;
|
||||
|
||||
public $file_path;
|
||||
|
||||
public $company;
|
||||
|
||||
public function __construct($file_path, Company $company)
|
||||
{
|
||||
$this->file_path = $file_path;
|
||||
|
||||
$this->company = $company;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||
->subject(ctrans('texts.download_backup_subject'))
|
||||
->markdown(
|
||||
'email.admin.download_files',
|
||||
[
|
||||
'url' => $this->file_path,
|
||||
'logo' => $this->company->present()->logo,
|
||||
'whitelabel' => $this->company->account->isPaid() ? true : false,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ class TemplateEmail extends Mailable
|
||||
});
|
||||
|
||||
//conditionally attach files
|
||||
if ($settings->pdf_email_attachment !== false && ! empty($this->build_email->getAttachments())) {
|
||||
// if ($settings->pdf_email_attachment !== false && ! empty($this->build_email->getAttachments())) {
|
||||
|
||||
//hosted | plan check here
|
||||
foreach ($this->build_email->getAttachments() as $file) {
|
||||
@ -118,7 +118,7 @@ class TemplateEmail extends Mailable
|
||||
$this->attach($file['path'], ['as' => $file['name'], 'mime' => $file['mime']]);
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -150,6 +150,11 @@ class Company extends BaseModel
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
public function client_contacts()
|
||||
{
|
||||
return $this->hasMany(ClientContact::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->hasManyThrough(User::class, CompanyUser::class, 'company_id', 'id', 'id', 'user_id');
|
||||
@ -203,6 +208,12 @@ class Company extends BaseModel
|
||||
return $this->hasMany(Vendor::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function all_activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
|
||||
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(300);
|
||||
@ -301,11 +312,21 @@ class Company extends BaseModel
|
||||
return $this->hasMany(Design::class)->whereCompanyId($this->id)->orWhere('company_id', null);
|
||||
}
|
||||
|
||||
public function user_designs()
|
||||
{
|
||||
return $this->hasMany(Design::class);
|
||||
}
|
||||
|
||||
public function payment_terms()
|
||||
{
|
||||
return $this->hasMany(PaymentTerm::class)->whereCompanyId($this->id)->orWhere('company_id', null);
|
||||
}
|
||||
|
||||
public function user_payment_terms()
|
||||
{
|
||||
return $this->hasMany(PaymentTerm::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo
|
||||
*/
|
||||
|
@ -415,6 +415,8 @@ class Invoice extends BaseModel
|
||||
CreateEntityPdf::dispatchNow($invitation);
|
||||
}
|
||||
|
||||
nlog($storage_path);
|
||||
|
||||
return $storage_path;
|
||||
}
|
||||
|
||||
|
@ -102,8 +102,6 @@ class SOFORT
|
||||
{
|
||||
$server_response = $this->stripe->payment_hash->data;
|
||||
|
||||
PaymentFailureMailer::dispatch($this->stripe->client, $server_response->redirect_status, $this->stripe->client->company, $server_response->amount);
|
||||
|
||||
PaymentFailureMailer::dispatch(
|
||||
$this->stripe->client,
|
||||
$server_response,
|
||||
|
@ -82,9 +82,20 @@ class SystemHealth
|
||||
'mail_mailer' => (string)self::checkMailMailer(),
|
||||
'flutter_renderer' => (string)config('ninja.flutter_canvas_kit'),
|
||||
'jobs_pending' => (int) Queue::size(),
|
||||
'pdf_engine' => (string) self::getPdfEngine(),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPdfEngine()
|
||||
{
|
||||
if(config('ninja.invoiceninja_hosted_pdf_generation'))
|
||||
return 'Invoice Ninja Hosted PDF Generator';
|
||||
elseif(config('ninja.phantomjs_pdf_generation'))
|
||||
return 'Phantom JS Web Generator';
|
||||
else
|
||||
return 'SnapPDF PDF Generator';
|
||||
}
|
||||
|
||||
public static function checkMailMailer()
|
||||
{
|
||||
return config('mail.default');
|
||||
|
@ -2861,6 +2861,7 @@ $LANG = [
|
||||
'my_invoices' => 'My Invoices',
|
||||
'mobile_refresh_warning' => 'If you\'re using the mobile app you may need to do a full refresh.',
|
||||
'enable_proposals_for_background' => 'To upload a background image :link to enable the proposals module.',
|
||||
|
||||
|
||||
];
|
||||
|
||||
|
@ -4248,6 +4248,7 @@ $LANG = array(
|
||||
'activity_104' => ':user restored recurring invoice :recurring_invoice',
|
||||
'new_login_detected' => 'New login detected for your account.',
|
||||
'new_login_description' => 'You recently logged in to your Invoice Ninja account from a new location or device:<br><br><b>IP:</b> :ip<br><b>Time:</b> :time<br><b>Email:</b> :email',
|
||||
'download_backup_subject' => 'Your company backup is ready for download',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -75,6 +75,8 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
|
||||
Route::put('expenses/{expense}/upload', 'ExpenseController@upload');
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk')->name('expenses.bulk');
|
||||
|
||||
Route::post('export', 'ExportController@index')->name('export.index');
|
||||
|
||||
Route::resource('expense_categories', 'ExpenseCategoryController'); // name = (expense_categories. index / create / show / update / destroy / edit
|
||||
Route::post('expense_categories/bulk', 'ExpenseCategoryController@bulk')->name('expense_categories.bulk');
|
||||
|
||||
|
49
tests/Feature/Export/ExportCompanyTest.php
Normal file
49
tests/Feature/Export/ExportCompanyTest.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
namespace Tests\Feature\Export;
|
||||
|
||||
use App\Jobs\Company\CompanyExport;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use League\Csv\Writer;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class ExportCompanyTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use MockAccountData;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
// $this->faker = \Faker\Factory::create();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
}
|
||||
|
||||
public function testCompanyExport()
|
||||
{
|
||||
CompanyExport::dispatchNow($this->company, $this->company->users->first());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user