mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 03:40:09 -05:00 
			
		
		
		
	Merge branch 'release-4.2.0'
This commit is contained in:
		
						commit
						1633f30a38
					
				@ -73,7 +73,7 @@ class ChargeRenewalInvoices extends Command
 | 
				
			|||||||
                        ->orderBy('id')
 | 
					                        ->orderBy('id')
 | 
				
			||||||
                        ->get();
 | 
					                        ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->info(count($invoices).' invoices found');
 | 
					        $this->info($invoices->count() . ' invoices found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($invoices as $invoice) {
 | 
					        foreach ($invoices as $invoice) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ namespace App\Console\Commands;
 | 
				
			|||||||
use Carbon;
 | 
					use Carbon;
 | 
				
			||||||
use App\Libraries\CurlUtils;
 | 
					use App\Libraries\CurlUtils;
 | 
				
			||||||
use DB;
 | 
					use DB;
 | 
				
			||||||
 | 
					use App;
 | 
				
			||||||
use Exception;
 | 
					use Exception;
 | 
				
			||||||
use Illuminate\Console\Command;
 | 
					use Illuminate\Console\Command;
 | 
				
			||||||
use Mail;
 | 
					use Mail;
 | 
				
			||||||
@ -81,6 +82,7 @@ class CheckData extends Command
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //$this->checkInvoices();
 | 
					        //$this->checkInvoices();
 | 
				
			||||||
 | 
					        $this->checkTranslations();
 | 
				
			||||||
        $this->checkInvoiceBalances();
 | 
					        $this->checkInvoiceBalances();
 | 
				
			||||||
        $this->checkClientBalances();
 | 
					        $this->checkClientBalances();
 | 
				
			||||||
        $this->checkContacts();
 | 
					        $this->checkContacts();
 | 
				
			||||||
@ -115,6 +117,40 @@ class CheckData extends Command
 | 
				
			|||||||
        $this->log .= $str . "\n";
 | 
					        $this->log .= $str . "\n";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function checkTranslations()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $invalid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (cache('languages') as $language) {
 | 
				
			||||||
 | 
					            App::setLocale($language->locale);
 | 
				
			||||||
 | 
					            foreach (trans('texts') as $text) {
 | 
				
			||||||
 | 
					                if (strpos($text, '=') !== false) {
 | 
				
			||||||
 | 
					                    $invalid++;
 | 
				
			||||||
 | 
					                    $this->logMessage($language->locale . ' is invalid: ' . $text);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                preg_match('/(.script)/', strtolower($text), $matches);
 | 
				
			||||||
 | 
					                if (count($matches)) {
 | 
				
			||||||
 | 
					                    foreach ($matches as $match) {
 | 
				
			||||||
 | 
					                        if (in_array($match, ['escript', 'bscript', 'nscript'])) {
 | 
				
			||||||
 | 
					                            continue;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        $invalid++;
 | 
				
			||||||
 | 
					                        $this->logMessage(sprintf('%s is invalid: %s', $language->locale, $text));
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($invalid > 0) {
 | 
				
			||||||
 | 
					            $this->isValid = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        App::setLocale('en');
 | 
				
			||||||
 | 
					        $this->logMessage($invalid . ' invalid text strings');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function checkDraftSentInvoices()
 | 
					    private function checkDraftSentInvoices()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $invoices = Invoice::whereInvoiceStatusId(INVOICE_STATUS_SENT)
 | 
					        $invoices = Invoice::whereInvoiceStatusId(INVOICE_STATUS_SENT)
 | 
				
			||||||
@ -122,9 +158,9 @@ class CheckData extends Command
 | 
				
			|||||||
                        ->withTrashed()
 | 
					                        ->withTrashed()
 | 
				
			||||||
                        ->get();
 | 
					                        ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->logMessage(count($invoices) . ' draft sent invoices');
 | 
					        $this->logMessage($invoices->count() . ' draft sent invoices');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($invoices) > 0) {
 | 
					        if ($invoices->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -190,9 +226,9 @@ class CheckData extends Command
 | 
				
			|||||||
                    ->havingRaw('count(users.id) > 1')
 | 
					                    ->havingRaw('count(users.id) > 1')
 | 
				
			||||||
                    ->get(['users.oauth_user_id']);
 | 
					                    ->get(['users.oauth_user_id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->logMessage(count($users) . ' users with duplicate oauth ids');
 | 
					        $this->logMessage($users->count() . ' users with duplicate oauth ids');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($users) > 0) {
 | 
					        if ($users->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -308,9 +344,9 @@ class CheckData extends Command
 | 
				
			|||||||
                        ->whereNull('contact_key')
 | 
					                        ->whereNull('contact_key')
 | 
				
			||||||
                        ->orderBy('id')
 | 
					                        ->orderBy('id')
 | 
				
			||||||
                        ->get(['id']);
 | 
					                        ->get(['id']);
 | 
				
			||||||
        $this->logMessage(count($contacts) . ' contacts without a contact_key');
 | 
					        $this->logMessage($contacts->count() . ' contacts without a contact_key');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($contacts) > 0) {
 | 
					        if ($contacts->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -339,9 +375,9 @@ class CheckData extends Command
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $clients = $clients->get(['clients.id', 'clients.user_id', 'clients.account_id']);
 | 
					        $clients = $clients->get(['clients.id', 'clients.user_id', 'clients.account_id']);
 | 
				
			||||||
        $this->logMessage(count($clients) . ' clients without any contacts');
 | 
					        $this->logMessage($clients->count() . ' clients without any contacts');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($clients) > 0) {
 | 
					        if ($clients->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -374,9 +410,9 @@ class CheckData extends Command
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $clients = $clients->get(['clients.id', DB::raw('count(contacts.id)')]);
 | 
					        $clients = $clients->get(['clients.id', DB::raw('count(contacts.id)')]);
 | 
				
			||||||
        $this->logMessage(count($clients) . ' clients without a single primary contact');
 | 
					        $this->logMessage($clients->count() . ' clients without a single primary contact');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($clients) > 0) {
 | 
					        if ($clients->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -423,9 +459,9 @@ class CheckData extends Command
 | 
				
			|||||||
                    ->havingRaw('count(invitations.id) = 0')
 | 
					                    ->havingRaw('count(invitations.id) = 0')
 | 
				
			||||||
                    ->get(['invoices.id', 'invoices.user_id', 'invoices.account_id', 'invoices.client_id']);
 | 
					                    ->get(['invoices.id', 'invoices.user_id', 'invoices.account_id', 'invoices.client_id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->logMessage(count($invoices) . ' invoices without any invitations');
 | 
					        $this->logMessage($invoices->count() . ' invoices without any invitations');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($invoices) > 0) {
 | 
					        if ($invoices->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -469,6 +505,10 @@ class CheckData extends Command
 | 
				
			|||||||
                ENTITY_INVOICE,
 | 
					                ENTITY_INVOICE,
 | 
				
			||||||
                ENTITY_CLIENT,
 | 
					                ENTITY_CLIENT,
 | 
				
			||||||
                ENTITY_USER,
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					                ENTITY_TASK_STATUS,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'task_statuses' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            'credits' => [
 | 
					            'credits' => [
 | 
				
			||||||
                ENTITY_CLIENT,
 | 
					                ENTITY_CLIENT,
 | 
				
			||||||
@ -496,6 +536,25 @@ class CheckData extends Command
 | 
				
			|||||||
                ENTITY_USER,
 | 
					                ENTITY_USER,
 | 
				
			||||||
                ENTITY_CLIENT,
 | 
					                ENTITY_CLIENT,
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
 | 
					            'proposals' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					                ENTITY_INVOICE,
 | 
				
			||||||
 | 
					                ENTITY_PROPOSAL_TEMPLATE,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'proposal_categories' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'proposal_templates' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'proposal_snippets' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					                ENTITY_PROPOSAL_CATEGORY,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'proposal_invitations' => [
 | 
				
			||||||
 | 
					                ENTITY_USER,
 | 
				
			||||||
 | 
					                ENTITY_PROPOSAL,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($tables as $table => $entityTypes) {
 | 
					        foreach ($tables as $table => $entityTypes) {
 | 
				
			||||||
@ -512,9 +571,9 @@ class CheckData extends Command
 | 
				
			|||||||
                                ->where("{$table}.{$accountId}", '!=', DB::raw("{$tableName}.account_id"))
 | 
					                                ->where("{$table}.{$accountId}", '!=', DB::raw("{$tableName}.account_id"))
 | 
				
			||||||
                                ->get(["{$table}.id"]);
 | 
					                                ->get(["{$table}.id"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (count($records)) {
 | 
					                if ($records->count()) {
 | 
				
			||||||
                    $this->isValid = false;
 | 
					                    $this->isValid = false;
 | 
				
			||||||
                    $this->logMessage(count($records) . " {$table} records with incorrect {$entityType} account id");
 | 
					                    $this->logMessage($records->count() . " {$table} records with incorrect {$entityType} account id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if ($this->option('fix') == 'true') {
 | 
					                    if ($this->option('fix') == 'true') {
 | 
				
			||||||
                        foreach ($records as $record) {
 | 
					                        foreach ($records as $record) {
 | 
				
			||||||
@ -549,9 +608,9 @@ class CheckData extends Command
 | 
				
			|||||||
                    ->groupBy('clients.id')
 | 
					                    ->groupBy('clients.id')
 | 
				
			||||||
                    ->havingRaw('clients.paid_to_date != sum(coalesce(payments.amount - payments.refunded, 0)) and clients.paid_to_date != 999999999.9999')
 | 
					                    ->havingRaw('clients.paid_to_date != sum(coalesce(payments.amount - payments.refunded, 0)) and clients.paid_to_date != 999999999.9999')
 | 
				
			||||||
                    ->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(coalesce(payments.amount - payments.refunded, 0)) as amount')]);
 | 
					                    ->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(coalesce(payments.amount - payments.refunded, 0)) as amount')]);
 | 
				
			||||||
        $this->logMessage(count($clients) . ' clients with incorrect paid to date');
 | 
					        $this->logMessage($clients->count() . ' clients with incorrect paid to date');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($clients) > 0) {
 | 
					        if ($clients->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -580,9 +639,9 @@ class CheckData extends Command
 | 
				
			|||||||
                    ->havingRaw('(invoices.amount - invoices.balance) != coalesce(sum(payments.amount - payments.refunded), 0)')
 | 
					                    ->havingRaw('(invoices.amount - invoices.balance) != coalesce(sum(payments.amount - payments.refunded), 0)')
 | 
				
			||||||
                    ->get(['invoices.id', 'invoices.amount', 'invoices.balance', DB::raw('coalesce(sum(payments.amount - payments.refunded), 0)')]);
 | 
					                    ->get(['invoices.id', 'invoices.amount', 'invoices.balance', DB::raw('coalesce(sum(payments.amount - payments.refunded), 0)')]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->logMessage(count($invoices) . ' invoices with incorrect balances');
 | 
					        $this->logMessage($invoices->count() . ' invoices with incorrect balances');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($invoices) > 0) {
 | 
					        if ($invoices->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -608,9 +667,9 @@ class CheckData extends Command
 | 
				
			|||||||
        $clients = $clients->groupBy('clients.id', 'clients.balance')
 | 
					        $clients = $clients->groupBy('clients.id', 'clients.balance')
 | 
				
			||||||
                ->orderBy('accounts.company_id', 'DESC')
 | 
					                ->orderBy('accounts.company_id', 'DESC')
 | 
				
			||||||
                ->get(['accounts.company_id', 'clients.account_id', 'clients.id', 'clients.balance', 'clients.paid_to_date', DB::raw('sum(invoices.balance) actual_balance')]);
 | 
					                ->get(['accounts.company_id', 'clients.account_id', 'clients.id', 'clients.balance', 'clients.paid_to_date', DB::raw('sum(invoices.balance) actual_balance')]);
 | 
				
			||||||
        $this->logMessage(count($clients) . ' clients with incorrect balance/activities');
 | 
					        $this->logMessage($clients->count() . ' clients with incorrect balance/activities');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (count($clients) > 0) {
 | 
					        if ($clients->count() > 0) {
 | 
				
			||||||
            $this->isValid = false;
 | 
					            $this->isValid = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -360,6 +360,7 @@ class InitLookup extends Command
 | 
				
			|||||||
        DB::statement('truncate lookup_users');
 | 
					        DB::statement('truncate lookup_users');
 | 
				
			||||||
        DB::statement('truncate lookup_contacts');
 | 
					        DB::statement('truncate lookup_contacts');
 | 
				
			||||||
        DB::statement('truncate lookup_invitations');
 | 
					        DB::statement('truncate lookup_invitations');
 | 
				
			||||||
 | 
					        DB::statement('truncate lookup_proposal_invitations');
 | 
				
			||||||
        DB::statement('truncate lookup_account_tokens');
 | 
					        DB::statement('truncate lookup_account_tokens');
 | 
				
			||||||
        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
 | 
					        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ class RemoveOrphanedDocuments extends Command
 | 
				
			|||||||
        $documents = Document::whereRaw('invoice_id IS NULL AND expense_id IS NULL AND updated_at <= ?', [new DateTime('-1 hour')])
 | 
					        $documents = Document::whereRaw('invoice_id IS NULL AND expense_id IS NULL AND updated_at <= ?', [new DateTime('-1 hour')])
 | 
				
			||||||
            ->get();
 | 
					            ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->info(count($documents).' orphaned document(s) found');
 | 
					        $this->info($documents->count() . ' orphaned document(s) found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($documents as $document) {
 | 
					        foreach ($documents as $document) {
 | 
				
			||||||
            $document->delete();
 | 
					            $document->delete();
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@ class SendRecurringInvoices extends Command
 | 
				
			|||||||
            ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND is_public IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
 | 
					            ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND is_recurring IS TRUE AND is_public IS TRUE AND frequency_id > 0 AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
 | 
				
			||||||
            ->orderBy('id', 'asc')
 | 
					            ->orderBy('id', 'asc')
 | 
				
			||||||
            ->get();
 | 
					            ->get();
 | 
				
			||||||
        $this->info(count($invoices).' recurring invoice(s) found');
 | 
					        $this->info($invoices->count() . ' recurring invoice(s) found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($invoices as $recurInvoice) {
 | 
					        foreach ($invoices as $recurInvoice) {
 | 
				
			||||||
            $shouldSendToday = $recurInvoice->shouldSendToday();
 | 
					            $shouldSendToday = $recurInvoice->shouldSendToday();
 | 
				
			||||||
@ -140,7 +140,7 @@ class SendRecurringInvoices extends Command
 | 
				
			|||||||
                [$today->format('Y-m-d')])
 | 
					                [$today->format('Y-m-d')])
 | 
				
			||||||
            ->orderBy('invoices.id', 'asc')
 | 
					            ->orderBy('invoices.id', 'asc')
 | 
				
			||||||
            ->get();
 | 
					            ->get();
 | 
				
			||||||
        $this->info(count($delayedAutoBillInvoices).' due recurring invoice instance(s) found');
 | 
					        $this->info($delayedAutoBillInvoices->count() . ' due recurring invoice instance(s) found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @var Invoice $invoice */
 | 
					        /** @var Invoice $invoice */
 | 
				
			||||||
        foreach ($delayedAutoBillInvoices as $invoice) {
 | 
					        foreach ($delayedAutoBillInvoices as $invoice) {
 | 
				
			||||||
@ -165,7 +165,7 @@ class SendRecurringInvoices extends Command
 | 
				
			|||||||
                        ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
 | 
					                        ->whereRaw('is_deleted IS FALSE AND deleted_at IS NULL AND start_date <= ? AND (end_date IS NULL OR end_date >= ?)', [$today, $today])
 | 
				
			||||||
                        ->orderBy('id', 'asc')
 | 
					                        ->orderBy('id', 'asc')
 | 
				
			||||||
                        ->get();
 | 
					                        ->get();
 | 
				
			||||||
        $this->info(count($expenses).' recurring expenses(s) found');
 | 
					        $this->info($expenses->count() . ' recurring expenses(s) found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($expenses as $expense) {
 | 
					        foreach ($expenses as $expense) {
 | 
				
			||||||
            $shouldSendToday = $expense->shouldSendToday();
 | 
					            $shouldSendToday = $expense->shouldSendToday();
 | 
				
			||||||
 | 
				
			|||||||
@ -92,7 +92,7 @@ class SendReminders extends Command
 | 
				
			|||||||
    private function chargeLateFees()
 | 
					    private function chargeLateFees()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $accounts = $this->accountRepo->findWithFees();
 | 
					        $accounts = $this->accountRepo->findWithFees();
 | 
				
			||||||
        $this->info(count($accounts) . ' accounts found with fees');
 | 
					        $this->info($accounts->count() . ' accounts found with fees');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($accounts as $account) {
 | 
					        foreach ($accounts as $account) {
 | 
				
			||||||
            if (! $account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
 | 
					            if (! $account->hasFeature(FEATURE_EMAIL_TEMPLATES_REMINDERS)) {
 | 
				
			||||||
@ -100,7 +100,7 @@ class SendReminders extends Command
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $invoices = $this->invoiceRepo->findNeedingReminding($account, false);
 | 
					            $invoices = $this->invoiceRepo->findNeedingReminding($account, false);
 | 
				
			||||||
            $this->info($account->name . ': ' . count($invoices) . ' invoices found');
 | 
					            $this->info($account->name . ': ' . $invoices->count() . ' invoices found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach ($invoices as $invoice) {
 | 
					            foreach ($invoices as $invoice) {
 | 
				
			||||||
                if ($reminder = $account->getInvoiceReminder($invoice, false)) {
 | 
					                if ($reminder = $account->getInvoiceReminder($invoice, false)) {
 | 
				
			||||||
@ -128,7 +128,7 @@ class SendReminders extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // standard reminders
 | 
					            // standard reminders
 | 
				
			||||||
            $invoices = $this->invoiceRepo->findNeedingReminding($account);
 | 
					            $invoices = $this->invoiceRepo->findNeedingReminding($account);
 | 
				
			||||||
            $this->info($account->name . ': ' . count($invoices) . ' invoices found');
 | 
					            $this->info($account->name . ': ' . $invoices->count() . ' invoices found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach ($invoices as $invoice) {
 | 
					            foreach ($invoices as $invoice) {
 | 
				
			||||||
                if ($reminder = $account->getInvoiceReminder($invoice)) {
 | 
					                if ($reminder = $account->getInvoiceReminder($invoice)) {
 | 
				
			||||||
@ -142,7 +142,7 @@ class SendReminders extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // endless reminders
 | 
					            // endless reminders
 | 
				
			||||||
            $invoices = $this->invoiceRepo->findNeedingEndlessReminding($account);
 | 
					            $invoices = $this->invoiceRepo->findNeedingEndlessReminding($account);
 | 
				
			||||||
            $this->info($account->name . ': ' . count($invoices) . ' endless invoices found');
 | 
					            $this->info($account->name . ': ' . $invoices->count() . ' endless invoices found');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach ($invoices as $invoice) {
 | 
					            foreach ($invoices as $invoice) {
 | 
				
			||||||
                if ($invoice->last_sent_date == date('Y-m-d')) {
 | 
					                if ($invoice->last_sent_date == date('Y-m-d')) {
 | 
				
			||||||
@ -159,7 +159,7 @@ class SendReminders extends Command
 | 
				
			|||||||
        $scheduledReports = ScheduledReport::where('send_date', '<=', date('Y-m-d'))
 | 
					        $scheduledReports = ScheduledReport::where('send_date', '<=', date('Y-m-d'))
 | 
				
			||||||
            ->with('user', 'account.company')
 | 
					            ->with('user', 'account.company')
 | 
				
			||||||
            ->get();
 | 
					            ->get();
 | 
				
			||||||
        $this->info(count($scheduledReports) . ' scheduled reports');
 | 
					        $this->info($scheduledReports->count() . ' scheduled reports');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($scheduledReports as $scheduledReport) {
 | 
					        foreach ($scheduledReports as $scheduledReport) {
 | 
				
			||||||
            $user = $scheduledReport->user;
 | 
					            $user = $scheduledReport->user;
 | 
				
			||||||
 | 
				
			|||||||
@ -60,10 +60,10 @@ class SendRenewalInvoices extends Command
 | 
				
			|||||||
        $companies = Company::whereRaw("datediff(plan_expires, curdate()) = 10 and (plan = 'pro' or plan = 'enterprise')")
 | 
					        $companies = Company::whereRaw("datediff(plan_expires, curdate()) = 10 and (plan = 'pro' or plan = 'enterprise')")
 | 
				
			||||||
                        ->orderBy('id')
 | 
					                        ->orderBy('id')
 | 
				
			||||||
                        ->get();
 | 
					                        ->get();
 | 
				
			||||||
        $this->info(count($companies).' companies found renewing in 10 days');
 | 
					        $this->info($companies->count() . ' companies found renewing in 10 days');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($companies as $company) {
 | 
					        foreach ($companies as $company) {
 | 
				
			||||||
            if (! count($company->accounts)) {
 | 
					            if (! $company->accounts->count()) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,10 +28,10 @@ class $CLASS$ extends AuthServiceProvider
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function boot(GateContract $gate)
 | 
					    public function boot()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::boot($gate);
 | 
					        parent::boot();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        $this->registerTranslations();
 | 
					        $this->registerTranslations();
 | 
				
			||||||
        $this->registerConfig();
 | 
					        $this->registerConfig();
 | 
				
			||||||
        $this->registerViews();
 | 
					        $this->registerViews();
 | 
				
			||||||
 | 
				
			|||||||
@ -53,17 +53,5 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
            ->command('ninja:send-reminders --force')
 | 
					            ->command('ninja:send-reminders --force')
 | 
				
			||||||
            ->sendOutputTo($logFile)
 | 
					            ->sendOutputTo($logFile)
 | 
				
			||||||
            ->daily();
 | 
					            ->daily();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (Utils::isNinja()) {
 | 
					 | 
				
			||||||
            $schedule
 | 
					 | 
				
			||||||
                ->command('ninja:send-renewals --force')
 | 
					 | 
				
			||||||
                ->sendOutputTo($logFile)
 | 
					 | 
				
			||||||
                ->daily();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $schedule
 | 
					 | 
				
			||||||
            ->command('updater:check-for-update --prefixVersionWith=v')
 | 
					 | 
				
			||||||
            ->sendOutputTo($logFile)
 | 
					 | 
				
			||||||
            ->daily();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,11 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
    define('ENTITY_RECURRING_EXPENSE', 'recurring_expense');
 | 
					    define('ENTITY_RECURRING_EXPENSE', 'recurring_expense');
 | 
				
			||||||
    define('ENTITY_CUSTOMER', 'customer');
 | 
					    define('ENTITY_CUSTOMER', 'customer');
 | 
				
			||||||
    define('ENTITY_SUBSCRIPTION', 'subscription');
 | 
					    define('ENTITY_SUBSCRIPTION', 'subscription');
 | 
				
			||||||
 | 
					    define('ENTITY_PROPOSAL', 'proposal');
 | 
				
			||||||
 | 
					    define('ENTITY_PROPOSAL_TEMPLATE', 'proposal_template');
 | 
				
			||||||
 | 
					    define('ENTITY_PROPOSAL_SNIPPET', 'proposal_snippet');
 | 
				
			||||||
 | 
					    define('ENTITY_PROPOSAL_CATEGORY', 'proposal_category');
 | 
				
			||||||
 | 
					    define('ENTITY_PROPOSAL_INVITATION', 'proposal_invitation');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    define('INVOICE_TYPE_STANDARD', 1);
 | 
					    define('INVOICE_TYPE_STANDARD', 1);
 | 
				
			||||||
    define('INVOICE_TYPE_QUOTE', 2);
 | 
					    define('INVOICE_TYPE_QUOTE', 2);
 | 
				
			||||||
@ -153,6 +158,7 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
    define('MAX_DOCUMENT_SIZE', env('MAX_DOCUMENT_SIZE', 10000)); // KB
 | 
					    define('MAX_DOCUMENT_SIZE', env('MAX_DOCUMENT_SIZE', 10000)); // KB
 | 
				
			||||||
    define('MAX_EMAIL_DOCUMENTS_SIZE', env('MAX_EMAIL_DOCUMENTS_SIZE', 10000)); // Total KB
 | 
					    define('MAX_EMAIL_DOCUMENTS_SIZE', env('MAX_EMAIL_DOCUMENTS_SIZE', 10000)); // Total KB
 | 
				
			||||||
    define('MAX_ZIP_DOCUMENTS_SIZE', env('MAX_EMAIL_DOCUMENTS_SIZE', 30000)); // Total KB (uncompressed)
 | 
					    define('MAX_ZIP_DOCUMENTS_SIZE', env('MAX_EMAIL_DOCUMENTS_SIZE', 30000)); // Total KB (uncompressed)
 | 
				
			||||||
 | 
					    define('MAX_EMAILS_SENT_PER_HOUR', 90);
 | 
				
			||||||
    define('DOCUMENT_PREVIEW_SIZE', env('DOCUMENT_PREVIEW_SIZE', 300)); // pixels
 | 
					    define('DOCUMENT_PREVIEW_SIZE', env('DOCUMENT_PREVIEW_SIZE', 300)); // pixels
 | 
				
			||||||
    define('DEFAULT_FONT_SIZE', 9);
 | 
					    define('DEFAULT_FONT_SIZE', 9);
 | 
				
			||||||
    define('DEFAULT_HEADER_FONT', 1); // Roboto
 | 
					    define('DEFAULT_HEADER_FONT', 1); // Roboto
 | 
				
			||||||
@ -290,6 +296,7 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
    define('GATEWAY_DWOLLA', 43);
 | 
					    define('GATEWAY_DWOLLA', 43);
 | 
				
			||||||
    define('GATEWAY_CHECKOUT_COM', 47);
 | 
					    define('GATEWAY_CHECKOUT_COM', 47);
 | 
				
			||||||
    define('GATEWAY_CYBERSOURCE', 49);
 | 
					    define('GATEWAY_CYBERSOURCE', 49);
 | 
				
			||||||
 | 
					    define('GATEWAY_PAYTRACE', 56);
 | 
				
			||||||
    define('GATEWAY_WEPAY', 60);
 | 
					    define('GATEWAY_WEPAY', 60);
 | 
				
			||||||
    define('GATEWAY_BRAINTREE', 61);
 | 
					    define('GATEWAY_BRAINTREE', 61);
 | 
				
			||||||
    define('GATEWAY_CUSTOM', 62);
 | 
					    define('GATEWAY_CUSTOM', 62);
 | 
				
			||||||
@ -331,7 +338,7 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
    define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
 | 
					    define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
 | 
				
			||||||
    define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
 | 
					    define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
 | 
				
			||||||
    define('NINJA_DATE', '2000-01-01');
 | 
					    define('NINJA_DATE', '2000-01-01');
 | 
				
			||||||
    define('NINJA_VERSION', '4.1.5' . env('NINJA_VERSION_SUFFIX'));
 | 
					    define('NINJA_VERSION', '4.2.0' . env('NINJA_VERSION_SUFFIX'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'));
 | 
					    define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'));
 | 
				
			||||||
    define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
 | 
					    define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
 | 
				
			||||||
@ -452,6 +459,7 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    define('TEMPLATE_INVOICE', 'invoice');
 | 
					    define('TEMPLATE_INVOICE', 'invoice');
 | 
				
			||||||
    define('TEMPLATE_QUOTE', 'quote');
 | 
					    define('TEMPLATE_QUOTE', 'quote');
 | 
				
			||||||
 | 
					    define('TEMPLATE_PROPOSAL', 'proposal');
 | 
				
			||||||
    define('TEMPLATE_PARTIAL', 'partial');
 | 
					    define('TEMPLATE_PARTIAL', 'partial');
 | 
				
			||||||
    define('TEMPLATE_PAYMENT', 'payment');
 | 
					    define('TEMPLATE_PAYMENT', 'payment');
 | 
				
			||||||
    define('TEMPLATE_REMINDER1', 'reminder1');
 | 
					    define('TEMPLATE_REMINDER1', 'reminder1');
 | 
				
			||||||
@ -517,6 +525,9 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
    define('PLAN_TERM_MONTHLY', 'month');
 | 
					    define('PLAN_TERM_MONTHLY', 'month');
 | 
				
			||||||
    define('PLAN_TERM_YEARLY', 'year');
 | 
					    define('PLAN_TERM_YEARLY', 'year');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    define('SUBSCRIPTION_FORMAT_JSON', 'JSON');
 | 
				
			||||||
 | 
					    define('SUBSCRIPTION_FORMAT_UBL', 'UBL');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Pro
 | 
					    // Pro
 | 
				
			||||||
    define('FEATURE_CUSTOMIZE_INVOICE_DESIGN', 'customize_invoice_design');
 | 
					    define('FEATURE_CUSTOMIZE_INVOICE_DESIGN', 'customize_invoice_design');
 | 
				
			||||||
    define('FEATURE_REMOVE_CREATED_BY', 'remove_created_by');
 | 
					    define('FEATURE_REMOVE_CREATED_BY', 'remove_created_by');
 | 
				
			||||||
@ -602,7 +613,6 @@ if (! defined('APP_NAME')) {
 | 
				
			|||||||
        'dateFormats' => 'App\Models\DateFormat',
 | 
					        'dateFormats' => 'App\Models\DateFormat',
 | 
				
			||||||
        'datetimeFormats' => 'App\Models\DatetimeFormat',
 | 
					        'datetimeFormats' => 'App\Models\DatetimeFormat',
 | 
				
			||||||
        'languages' => 'App\Models\Language',
 | 
					        'languages' => 'App\Models\Language',
 | 
				
			||||||
        'paymentTerms' => 'App\Models\PaymentTerm',
 | 
					 | 
				
			||||||
        'paymentTypes' => 'App\Models\PaymentType',
 | 
					        'paymentTypes' => 'App\Models\PaymentType',
 | 
				
			||||||
        'countries' => 'App\Models\Country',
 | 
					        'countries' => 'App\Models\Country',
 | 
				
			||||||
        'invoiceDesigns' => 'App\Models\InvoiceDesign',
 | 
					        'invoiceDesigns' => 'App\Models\InvoiceDesign',
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								app/Events/SubdomainWasRemoved.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Events/SubdomainWasRemoved.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubdomainWasRemoved extends Event
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SerializesModels;
 | 
				
			||||||
 | 
					    public $account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new event instance.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param $account
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __construct($account)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->account = $account;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Exceptions;
 | 
					namespace App\Exceptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Crawler;
 | 
					 | 
				
			||||||
use Exception;
 | 
					use Exception;
 | 
				
			||||||
use Illuminate\Auth\AuthenticationException;
 | 
					use Illuminate\Auth\AuthenticationException;
 | 
				
			||||||
use Illuminate\Auth\Access\AuthorizationException;
 | 
					use Illuminate\Auth\Access\AuthorizationException;
 | 
				
			||||||
@ -51,11 +50,12 @@ class Handler extends ExceptionHandler
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! class_exists('Utils')) {
 | 
					        // if these classes don't exist the install is broken, maybe due to permissions
 | 
				
			||||||
 | 
					        if (! class_exists('Utils') || ! class_exists('Crawler')) {
 | 
				
			||||||
            return parent::report($e);
 | 
					            return parent::report($e);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Crawler::isCrawler()) {
 | 
					        if (\Crawler::isCrawler()) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -184,12 +184,10 @@ class AccountApiController extends BaseAPIController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $devices = json_decode($account->devices, true);
 | 
					        $devices = json_decode($account->devices, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach($devices as $key => $value)
 | 
					        for($x=0; $x<count($devices); $x++)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if($request->token == $devices[$x]['token'])
 | 
				
			||||||
            if($request->token == $value['token'])
 | 
					                unset($devices[$x]);
 | 
				
			||||||
                unset($devices[$key]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account->devices = json_encode(array_values($devices));
 | 
					        $account->devices = json_encode(array_values($devices));
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -152,7 +152,7 @@ class AccountGatewayController extends BaseController
 | 
				
			|||||||
            'config' => false,
 | 
					            'config' => false,
 | 
				
			||||||
            'gateways' => $gateways,
 | 
					            'gateways' => $gateways,
 | 
				
			||||||
            'creditCardTypes' => $creditCards,
 | 
					            'creditCardTypes' => $creditCards,
 | 
				
			||||||
            'countGateways' => count($currentGateways),
 | 
					            'countGateways' => $currentGateways->count(),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -175,14 +175,18 @@ class AppController extends BaseController
 | 
				
			|||||||
        $_ENV['DB_PASSWORD'] = $db['type']['password'];
 | 
					        $_ENV['DB_PASSWORD'] = $db['type']['password'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($mail) {
 | 
					        if ($mail) {
 | 
				
			||||||
            $_ENV['MAIL_DRIVER'] = $mail['driver'];
 | 
					            $prefix = '';
 | 
				
			||||||
            $_ENV['MAIL_PORT'] = $mail['port'];
 | 
					            if (($user = auth()->user()) && Account::count() > 1) {
 | 
				
			||||||
            $_ENV['MAIL_ENCRYPTION'] = $mail['encryption'];
 | 
					                $prefix = $user->account_id . '_';
 | 
				
			||||||
            $_ENV['MAIL_HOST'] = $mail['host'];
 | 
					            }
 | 
				
			||||||
            $_ENV['MAIL_USERNAME'] = $mail['username'];
 | 
					            $_ENV[$prefix . 'MAIL_DRIVER'] = $mail['driver'];
 | 
				
			||||||
            $_ENV['MAIL_FROM_NAME'] = $mail['from']['name'];
 | 
					            $_ENV[$prefix . 'MAIL_PORT'] = $mail['port'];
 | 
				
			||||||
            $_ENV['MAIL_FROM_ADDRESS'] = $mail['from']['address'];
 | 
					            $_ENV[$prefix . 'MAIL_ENCRYPTION'] = $mail['encryption'];
 | 
				
			||||||
            $_ENV['MAIL_PASSWORD'] = $mail['password'];
 | 
					            $_ENV[$prefix . 'MAIL_HOST'] = $mail['host'];
 | 
				
			||||||
 | 
					            $_ENV[$prefix . 'MAIL_USERNAME'] = $mail['username'];
 | 
				
			||||||
 | 
					            $_ENV[$prefix . 'MAIL_FROM_NAME'] = $mail['from']['name'];
 | 
				
			||||||
 | 
					            $_ENV[$prefix . 'MAIL_FROM_ADDRESS'] = $mail['from']['address'];
 | 
				
			||||||
 | 
					            $_ENV[$prefix . 'MAIL_PASSWORD'] = $mail['password'];
 | 
				
			||||||
            $_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
 | 
					            $_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
 | 
				
			||||||
            $_ENV['MAILGUN_SECRET'] = $mail['mailgun_secret'];
 | 
					            $_ENV['MAILGUN_SECRET'] = $mail['mailgun_secret'];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,6 @@ namespace App\Http\Controllers\Auth;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use Event;
 | 
					use Event;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use App\Models\PasswordReset;
 | 
					 | 
				
			||||||
use App\Events\UserLoggedIn;
 | 
					use App\Events\UserLoggedIn;
 | 
				
			||||||
use App\Http\Controllers\Controller;
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
 | 
					use Illuminate\Foundation\Auth\ResetsPasswords;
 | 
				
			||||||
 | 
				
			|||||||
@ -92,9 +92,11 @@ class BankAccountController extends BaseController
 | 
				
			|||||||
        if ($publicId) {
 | 
					        if ($publicId) {
 | 
				
			||||||
            $bankAccount = BankAccount::scope($publicId)->firstOrFail();
 | 
					            $bankAccount = BankAccount::scope($publicId)->firstOrFail();
 | 
				
			||||||
            if ($username != $bankAccount->username) {
 | 
					            if ($username != $bankAccount->username) {
 | 
				
			||||||
                // TODO update username
 | 
					                $bankAccount->setUsername($username);
 | 
				
			||||||
 | 
					                $bankAccount->save();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $username = Crypt::decrypt($username);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $username = Crypt::decrypt($username);
 | 
					 | 
				
			||||||
            $bankId = $bankAccount->bank_id;
 | 
					            $bankId = $bankAccount->bank_id;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $bankAccount = new BankAccount;
 | 
					            $bankAccount = new BankAccount;
 | 
				
			||||||
 | 
				
			|||||||
@ -99,15 +99,17 @@ class BaseAPIController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $query->with($includes);
 | 
					        $query->with($includes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($updatedAt = intval(Input::get('updated_at'))) {
 | 
					        if (Input::get('updated_at') > 0) {
 | 
				
			||||||
            $query->where('updated_at', '>=', date('Y-m-d H:i:s', $updatedAt));
 | 
					                $updatedAt = intval(Input::get('updated_at'));
 | 
				
			||||||
 | 
					                $query->where('updated_at', '>=', date('Y-m-d H:i:s', $updatedAt));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
        if ($clientPublicId = Input::get('client_id')) {
 | 
					        if (Input::get('client_id') > 0) {
 | 
				
			||||||
            $filter = function ($query) use ($clientPublicId) {
 | 
					                $clientPublicId = Input::get('client_id');
 | 
				
			||||||
 | 
					                $filter = function ($query) use ($clientPublicId) {
 | 
				
			||||||
                $query->where('public_id', '=', $clientPublicId);
 | 
					                $query->where('public_id', '=', $clientPublicId);
 | 
				
			||||||
            };
 | 
					             };
 | 
				
			||||||
            $query->whereHas('client', $filter);
 | 
					             $query->whereHas('client', $filter);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Utils::hasPermission('view_all')) {
 | 
					        if (! Utils::hasPermission('view_all')) {
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ class CalendarController extends BaseController
 | 
				
			|||||||
    public function showCalendar()
 | 
					    public function showCalendar()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'title' => trans('texts.calendar'),
 | 
				
			||||||
            'account' => auth()->user()->account,
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ class LoginController extends Controller
 | 
				
			|||||||
    public function showLoginForm()
 | 
					    public function showLoginForm()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $subdomain = Utils::getSubdomain(\Request::server('HTTP_HOST'));
 | 
					        $subdomain = Utils::getSubdomain(\Request::server('HTTP_HOST'));
 | 
				
			||||||
        $hasAccountIndentifier = request()->account_key || ($subdomain && $subdomain != 'app');
 | 
					        $hasAccountIndentifier = request()->account_key || ($subdomain && ! in_array($subdomain, ['www', 'app']));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! session('contact_key')) {
 | 
					        if (! session('contact_key')) {
 | 
				
			||||||
            if (Utils::isNinja()) {
 | 
					            if (Utils::isNinja()) {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,6 @@ namespace App\Http\Controllers\ClientAuth;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use Password;
 | 
					use Password;
 | 
				
			||||||
use Config;
 | 
					use Config;
 | 
				
			||||||
use App\Models\PasswordReset;
 | 
					 | 
				
			||||||
use App\Http\Controllers\Controller;
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
 | 
					use Illuminate\Foundation\Auth\ResetsPasswords;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
@ -55,14 +54,8 @@ class ResetPasswordController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function showResetForm(Request $request, $token = null)
 | 
					    public function showResetForm(Request $request, $token = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $passwordReset = PasswordReset::whereToken($token)->first();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (! $passwordReset) {
 | 
					 | 
				
			||||||
            return redirect('login')->withMessage(trans('texts.invalid_code'));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return view('clientauth.passwords.reset')->with(
 | 
					        return view('clientauth.passwords.reset')->with(
 | 
				
			||||||
            ['token' => $token, 'email' => $passwordReset->email]
 | 
					            ['token' => $token]
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Events\InvoiceInvitationWasViewed;
 | 
					use App\Events\InvoiceInvitationWasViewed;
 | 
				
			||||||
use App\Events\QuoteInvitationWasViewed;
 | 
					use App\Events\QuoteInvitationWasViewed;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
use App\Models\Contact;
 | 
					use App\Models\Contact;
 | 
				
			||||||
use App\Models\Document;
 | 
					use App\Models\Document;
 | 
				
			||||||
use App\Models\Gateway;
 | 
					use App\Models\Gateway;
 | 
				
			||||||
@ -55,7 +56,7 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        $this->taskRepo = $taskRepo;
 | 
					        $this->taskRepo = $taskRepo;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function view($invitationKey)
 | 
					    public function viewInvoice($invitationKey)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
 | 
					        if (! $invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -76,8 +77,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account->loadLocalizationSettings($client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (! Input::has('phantomjs') && ! session('silent:' . $client->id) && ! Session::has($invitation->invitation_key)
 | 
					        if (! Input::has('phantomjs') && ! session('silent:' . $client->id) && ! Session::has($invitation->invitation_key)
 | 
				
			||||||
            && (! Auth::check() || Auth::user()->account_id != $invoice->account_id)) {
 | 
					            && (! Auth::check() || Auth::user()->account_id != $invoice->account_id)) {
 | 
				
			||||||
            if ($invoice->isType(INVOICE_TYPE_QUOTE)) {
 | 
					            if ($invoice->isType(INVOICE_TYPE_QUOTE)) {
 | 
				
			||||||
@ -117,10 +116,10 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // translate the country names
 | 
					        // translate the country names
 | 
				
			||||||
        if ($invoice->client->country) {
 | 
					        if ($invoice->client->country) {
 | 
				
			||||||
            $invoice->client->country->name = trans('texts.country_' . $invoice->client->country->name);
 | 
					            $invoice->client->country->name = $invoice->client->country->getName();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ($invoice->account->country) {
 | 
					        if ($invoice->account->country) {
 | 
				
			||||||
            $invoice->account->country->name = trans('texts.country_' . $invoice->account->country->name);
 | 
					            $invoice->account->country->name = $invoice->account->country->getName();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [];
 | 
					        $data = [];
 | 
				
			||||||
@ -226,7 +225,7 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        return $pdfString;
 | 
					        return $pdfString;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function sign($invitationKey)
 | 
					    public function authorizeInvoice($invitationKey)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
 | 
					        if (! $invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
 | 
				
			||||||
            return RESULT_FAILURE;
 | 
					            return RESULT_FAILURE;
 | 
				
			||||||
@ -262,13 +261,13 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
            return redirect(request()->url());
 | 
					            return redirect(request()->url());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account->loadLocalizationSettings($client);
 | 
					 | 
				
			||||||
        $color = $account->primary_color ? $account->primary_color : '#0b4d78';
 | 
					        $color = $account->primary_color ? $account->primary_color : '#0b4d78';
 | 
				
			||||||
        $customer = false;
 | 
					        $customer = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
        } elseif (! $account->enable_client_portal_dashboard) {
 | 
					        } elseif (! $account->enable_client_portal_dashboard) {
 | 
				
			||||||
 | 
					            session()->reflash();
 | 
				
			||||||
            return redirect()->to('/client/invoices/');
 | 
					            return redirect()->to('/client/invoices/');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -334,7 +333,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -368,7 +366,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -414,7 +411,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -499,7 +495,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -535,7 +530,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -571,7 +565,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $contact->client->show_tasks_in_portal) {
 | 
					        if (! $contact->client->show_tasks_in_portal) {
 | 
				
			||||||
            return redirect()->to($account->enable_client_portal_dashboard ? '/client/dashboard' : '/client/payment_methods/');
 | 
					            return redirect()->to($account->enable_client_portal_dashboard ? '/client/dashboard' : '/client/payment_methods/');
 | 
				
			||||||
@ -611,7 +604,6 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $account = $contact->account;
 | 
					        $account = $contact->account;
 | 
				
			||||||
        $account->loadLocalizationSettings($contact->client);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account->enable_client_portal) {
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
            return $this->returnError();
 | 
					            return $this->returnError();
 | 
				
			||||||
@ -962,4 +954,65 @@ class ClientPortalController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return Redirect::to('client/invoices/recurring');
 | 
					        return Redirect::to('client/invoices/recurring');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function showDetails()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $contact = $this->getContact()) {
 | 
				
			||||||
 | 
					            return $this->returnError();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'contact' => $contact,
 | 
				
			||||||
 | 
					            'client' => $contact->client,
 | 
				
			||||||
 | 
					            'account' => $contact->account,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return view('invited.details', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function updateDetails(\Illuminate\Http\Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $contact = $this->getContact()) {
 | 
				
			||||||
 | 
					            return $this->returnError();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client = $contact->client;
 | 
				
			||||||
 | 
					        $account = $contact->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (! $account->enable_client_portal) {
 | 
				
			||||||
 | 
					            return $this->returnError();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $rules = [
 | 
				
			||||||
 | 
					            'email' => 'required',
 | 
				
			||||||
 | 
					            'address1' => 'required',
 | 
				
			||||||
 | 
					            'city' => 'required',
 | 
				
			||||||
 | 
					            'state' => 'required',
 | 
				
			||||||
 | 
					            'postal_code' => 'required',
 | 
				
			||||||
 | 
					            'country_id' => 'required',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($client->name) {
 | 
				
			||||||
 | 
					            $rules['name'] = 'required';
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $rules['first_name'] = 'required';
 | 
				
			||||||
 | 
					            $rules['last_name'] = 'required';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if ($account->vat_number || $account->isNinjaAccount()) {
 | 
				
			||||||
 | 
					            $rules['vat_number'] = 'required';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, $rules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $contact->fill(request()->all());
 | 
				
			||||||
 | 
					        $contact->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client->fill(request()->all());
 | 
				
			||||||
 | 
					        $client->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        event(new \App\Events\ClientWasUpdated($client));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect($account->enable_client_portal_dashboard ? '/client/dashboard' : '/client/payment_methods')
 | 
				
			||||||
 | 
					            ->withMessage(trans('texts.updated_client_details'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										70
									
								
								app/Http/Controllers/ClientPortalProposalController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/Http/Controllers/ClientPortalProposalController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use mPDF;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use App\Models\Document;
 | 
				
			||||||
 | 
					use App\Models\Invitation;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\ProposalRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClientPortalProposalController extends BaseController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private $invoiceRepo;
 | 
				
			||||||
 | 
					    private $paymentRepo;
 | 
				
			||||||
 | 
					    private $documentRepo;
 | 
				
			||||||
 | 
					    private $propoosalRepo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ProposalRepository $propoosalRepo)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->propoosalRepo = $propoosalRepo;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function viewProposal($invitationKey)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $invitation = $this->propoosalRepo->findInvitationByKey($invitationKey)) {
 | 
				
			||||||
 | 
					            return $this->returnError(trans('texts.proposal_not_found'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $account = $invitation->account;
 | 
				
			||||||
 | 
					        $proposal = $invitation->proposal;
 | 
				
			||||||
 | 
					        $invoiceInvitation = Invitation::whereContactId($invitation->contact_id)
 | 
				
			||||||
 | 
					                ->whereInvoiceId($proposal->invoice_id)
 | 
				
			||||||
 | 
					                ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'proposal' => $proposal,
 | 
				
			||||||
 | 
					            'account' => $account,
 | 
				
			||||||
 | 
					            'invoiceInvitation' => $invoiceInvitation,
 | 
				
			||||||
 | 
					            'proposalInvitation' => $invitation,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return view('invited.proposal', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function downloadProposal($invitationKey)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $invitation = $this->propoosalRepo->findInvitationByKey($invitationKey)) {
 | 
				
			||||||
 | 
					            return $this->returnError(trans('texts.proposal_not_found'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $proposal = $invitation->proposal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mpdf = new mPDF();
 | 
				
			||||||
 | 
					        $mpdf->WriteHTML($proposal->present()->htmlDocument);
 | 
				
			||||||
 | 
					        $mpdf->Output($proposal->present()->filename, 'D');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getProposalImage($accountKey, $documentKey)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $account = Account::whereAccountKey($accountKey)
 | 
				
			||||||
 | 
					                        ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $document = Document::whereAccountId($account->id)
 | 
				
			||||||
 | 
					                        ->whereDocumentKey($documentKey)
 | 
				
			||||||
 | 
					                        ->whereIsProposal(true)
 | 
				
			||||||
 | 
					                        ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return DocumentController::getDownloadResponse($document);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -43,12 +43,12 @@ class DashboardApiController extends BaseAPIController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'id' => 1,
 | 
					            'id' => 1,
 | 
				
			||||||
            'paidToDate' => count($paidToDate) && $paidToDate[0]->value ? $paidToDate[0]->value : 0,
 | 
					            'paidToDate' => $paidToDate->count() && $paidToDate[0]->value ? $paidToDate[0]->value : 0,
 | 
				
			||||||
            'paidToDateCurrency' => count($paidToDate) && $paidToDate[0]->currency_id ? $paidToDate[0]->currency_id : 0,
 | 
					            'paidToDateCurrency' => $paidToDate->count() && $paidToDate[0]->currency_id ? $paidToDate[0]->currency_id : 0,
 | 
				
			||||||
            'balances' => count($balances) && $balances[0]->value ? $balances[0]->value : 0,
 | 
					            'balances' => $balances->count() && $balances[0]->value ? $balances[0]->value : 0,
 | 
				
			||||||
            'balancesCurrency' => count($balances) && $balances[0]->currency_id ? $balances[0]->currency_id : 0,
 | 
					            'balancesCurrency' => $balances->count() && $balances[0]->currency_id ? $balances[0]->currency_id : 0,
 | 
				
			||||||
            'averageInvoice' => count($averageInvoice) && $averageInvoice[0]->invoice_avg ? $averageInvoice[0]->invoice_avg : 0,
 | 
					            'averageInvoice' => $averageInvoice->count() && $averageInvoice[0]->invoice_avg ? $averageInvoice[0]->invoice_avg : 0,
 | 
				
			||||||
            'averageInvoiceCurrency' => count($averageInvoice) && $averageInvoice[0]->currency_id ? $averageInvoice[0]->currency_id : 0,
 | 
					            'averageInvoiceCurrency' => $averageInvoice->count() && $averageInvoice[0]->currency_id ? $averageInvoice[0]->currency_id : 0,
 | 
				
			||||||
            'invoicesSent' => $metrics ? $metrics->invoices_sent : 0,
 | 
					            'invoicesSent' => $metrics ? $metrics->invoices_sent : 0,
 | 
				
			||||||
            'activeClients' => $metrics ? $metrics->active_clients : 0,
 | 
					            'activeClients' => $metrics ? $metrics->active_clients : 0,
 | 
				
			||||||
            'activities' => $this->createCollection($activities, new ActivityTransformer(), ENTITY_ACTIVITY),
 | 
					            'activities' => $this->createCollection($activities, new ActivityTransformer(), ENTITY_ACTIVITY),
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@ class DashboardController extends BaseController
 | 
				
			|||||||
            'tasks' => $tasks,
 | 
					            'tasks' => $tasks,
 | 
				
			||||||
            'showBlueVinePromo' => $showBlueVinePromo,
 | 
					            'showBlueVinePromo' => $showBlueVinePromo,
 | 
				
			||||||
            'showWhiteLabelExpired' => $showWhiteLabelExpired,
 | 
					            'showWhiteLabelExpired' => $showWhiteLabelExpired,
 | 
				
			||||||
            'showExpenses' => count($expenses) && $account->isModuleEnabled(ENTITY_EXPENSE),
 | 
					            'showExpenses' => $expenses->count() && $account->isModuleEnabled(ENTITY_EXPENSE),
 | 
				
			||||||
            'headerClass' => in_array(\App::getLocale(), ['lt', 'pl', 'cs', 'sl', 'tr_TR']) ? 'in-large' : 'in-thin',
 | 
					            'headerClass' => in_array(\App::getLocale(), ['lt', 'pl', 'cs', 'sl', 'tr_TR']) ? 'in-large' : 'in-thin',
 | 
				
			||||||
            'footerClass' => in_array(\App::getLocale(), ['lt', 'pl', 'cs', 'sl', 'tr_TR']) ? '' : 'in-thin',
 | 
					            'footerClass' => in_array(\App::getLocale(), ['lt', 'pl', 'cs', 'sl', 'tr_TR']) ? '' : 'in-thin',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
				
			|||||||
@ -105,11 +105,20 @@ class DocumentController extends BaseController
 | 
				
			|||||||
                'code' => 400,
 | 
					                'code' => 400,
 | 
				
			||||||
            ], 400);
 | 
					            ], 400);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return Response::json([
 | 
					            if ($request->grapesjs) {
 | 
				
			||||||
                'error' => false,
 | 
					                $response = [
 | 
				
			||||||
                'document' => $doc_array,
 | 
					                    'data' => [
 | 
				
			||||||
                'code' => 200,
 | 
					                        $result->getProposalUrl()
 | 
				
			||||||
            ], 200);
 | 
					                    ]
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $response = [
 | 
				
			||||||
 | 
					                    'error' => false,
 | 
				
			||||||
 | 
					                    'document' => $doc_array,
 | 
				
			||||||
 | 
					                    'code' => 200,
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Response::json($response, 200);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -161,7 +161,7 @@ class HomeController extends BaseController
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                $subject .= '] ';
 | 
					                $subject .= '] ';
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $subject .= 'Self-Host | ';
 | 
					                $subject .= 'Self-Host] | ';
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $subject .= date('M jS, g:ia');
 | 
					            $subject .= date('M jS, g:ia');
 | 
				
			||||||
            $message->to(env('CONTACT_EMAIL', 'contact@invoiceninja.com'))
 | 
					            $message->to(env('CONTACT_EMAIL', 'contact@invoiceninja.com'))
 | 
				
			||||||
 | 
				
			|||||||
@ -68,6 +68,11 @@ class InvoiceApiController extends BaseAPIController
 | 
				
			|||||||
            $invoices->whereInvoiceNumber($invoiceNumber);
 | 
					            $invoices->whereInvoiceNumber($invoiceNumber);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Fllter by status
 | 
				
			||||||
 | 
					        if ($statusId = Input::get('status_id')) {
 | 
				
			||||||
 | 
					            $invoices->where('invoice_status_id', '>=', $statusId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->listResponse($invoices);
 | 
					        return $this->listResponse($invoices);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -403,7 +403,11 @@ class InvoiceController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Auth::user()->confirmed) {
 | 
					        if (! Auth::user()->confirmed) {
 | 
				
			||||||
            $errorMessage = trans(Auth::user()->registered ? 'texts.confirmation_required' : 'texts.registration_required');
 | 
					            if (Auth::user()->registered) {
 | 
				
			||||||
 | 
					                $errorMessage = trans('texts.confirmation_required', ['link' => link_to('/resend_confirmation', trans('texts.click_here'))]);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $errorMessage = trans('texts.registration_required');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Session::flash('error', $errorMessage);
 | 
					            Session::flash('error', $errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Redirect::to('invoices/'.$invoice->public_id.'/edit');
 | 
					            return Redirect::to('invoices/'.$invoice->public_id.'/edit');
 | 
				
			||||||
 | 
				
			|||||||
@ -294,6 +294,7 @@ class NinjaController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $user = Auth::user();
 | 
					        $user = Auth::user();
 | 
				
			||||||
 | 
					        $account = $user->account;
 | 
				
			||||||
        $url = NINJA_APP_URL . '/buy_now';
 | 
					        $url = NINJA_APP_URL . '/buy_now';
 | 
				
			||||||
        $contactKey = $user->primaryAccount()->account_key;
 | 
					        $contactKey = $user->primaryAccount()->account_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -301,9 +302,17 @@ class NinjaController extends BaseController
 | 
				
			|||||||
            'account_key' => NINJA_LICENSE_ACCOUNT_KEY,
 | 
					            'account_key' => NINJA_LICENSE_ACCOUNT_KEY,
 | 
				
			||||||
            'contact_key' => $contactKey,
 | 
					            'contact_key' => $contactKey,
 | 
				
			||||||
            'product_id' => PRODUCT_WHITE_LABEL,
 | 
					            'product_id' => PRODUCT_WHITE_LABEL,
 | 
				
			||||||
            'first_name' => Auth::user()->first_name,
 | 
					            'first_name' => $user->first_name,
 | 
				
			||||||
            'last_name' => Auth::user()->last_name,
 | 
					            'last_name' => $user->last_name,
 | 
				
			||||||
            'email' => Auth::user()->email,
 | 
					            'email' => $user->email,
 | 
				
			||||||
 | 
					            'name' => $account->name,
 | 
				
			||||||
 | 
					            'address1' => $account->address1,
 | 
				
			||||||
 | 
					            'address2' => $account->address2,
 | 
				
			||||||
 | 
					            'city' => $account->city,
 | 
				
			||||||
 | 
					            'state' => $account->state,
 | 
				
			||||||
 | 
					            'postal_code' => $account->postal_code,
 | 
				
			||||||
 | 
					            'country_id' => $account->country_id,
 | 
				
			||||||
 | 
					            'vat_number' => $account->vat_number,
 | 
				
			||||||
            'return_link' => true,
 | 
					            'return_link' => true,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -356,12 +356,14 @@ class OnlinePaymentController extends BaseController
 | 
				
			|||||||
                return redirect()->to("{$failureUrl}/?error=" . $validator->errors()->first());
 | 
					                return redirect()->to("{$failureUrl}/?error=" . $validator->errors()->first());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $data = [
 | 
					            $data = request()->all();
 | 
				
			||||||
                'currency_id' => $account->currency_id,
 | 
					            $data['currency_id'] = $account->currency_id;
 | 
				
			||||||
                'contact' => Input::all(),
 | 
					            $data['custom_value1'] = request()->custom_client1;
 | 
				
			||||||
                'custom_value1' => Input::get('custom_client1'),
 | 
					            $data['custom_value2'] = request()->custom_client2;
 | 
				
			||||||
                'custom_value2' => Input::get('custom_client2'),
 | 
					            $data['contact'] = request()->all();
 | 
				
			||||||
            ];
 | 
					            $data['contact']['custom_value1'] = request()->custom_contact1;
 | 
				
			||||||
 | 
					            $data['contact']['custom_value2'] = request()->custom_contact2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (request()->currency_code) {
 | 
					            if (request()->currency_code) {
 | 
				
			||||||
                $data['currency_code'] = request()->currency_code;
 | 
					                $data['currency_code'] = request()->currency_code;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -425,20 +427,23 @@ class OnlinePaymentController extends BaseController
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (Utils::isNinja()) {
 | 
					        if (Utils::isNinja()) {
 | 
				
			||||||
            $subdomain = Utils::getSubdomain(\Request::server('HTTP_HOST'));
 | 
					            $subdomain = Utils::getSubdomain(\Request::server('HTTP_HOST'));
 | 
				
			||||||
 | 
					            if (! $subdomain || $subdomain == 'app') {
 | 
				
			||||||
 | 
					                exit('Invalid subdomain');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            $account = Account::whereSubdomain($subdomain)->first();
 | 
					            $account = Account::whereSubdomain($subdomain)->first();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $account = Account::first();
 | 
					            $account = Account::first();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account) {
 | 
					        if (! $account) {
 | 
				
			||||||
            exit("Account not found");
 | 
					            exit('Account not found');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $accountGateway = $account->account_gateways()
 | 
					        $accountGateway = $account->account_gateways()
 | 
				
			||||||
            ->whereGatewayId(GATEWAY_STRIPE)->first();
 | 
					            ->whereGatewayId(GATEWAY_STRIPE)->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $account) {
 | 
					        if (! $account) {
 | 
				
			||||||
            exit("Apple merchant id not set");
 | 
					            exit('Apple merchant id not set');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        echo $accountGateway->getConfigField('appleMerchantId');
 | 
					        echo $accountGateway->getConfigField('appleMerchantId');
 | 
				
			||||||
 | 
				
			|||||||
@ -89,16 +89,29 @@ class PaymentController extends BaseController
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function create(PaymentRequest $request)
 | 
					    public function create(PaymentRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $user = auth()->user();
 | 
				
			||||||
 | 
					        $account = $user->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoices = Invoice::scope()
 | 
					        $invoices = Invoice::scope()
 | 
				
			||||||
                    ->invoices()
 | 
					                    ->invoices()
 | 
				
			||||||
                    ->where('invoices.invoice_status_id', '!=', INVOICE_STATUS_PAID)
 | 
					                    ->where('invoices.invoice_status_id', '!=', INVOICE_STATUS_PAID)
 | 
				
			||||||
                    ->with('client', 'invoice_status')
 | 
					                    ->with('client', 'invoice_status')
 | 
				
			||||||
                    ->orderBy('invoice_number')->get();
 | 
					                    ->orderBy('invoice_number')->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $clientPublicId = Input::old('client') ? Input::old('client') : ($request->client_id ?: 0);
 | 
				
			||||||
 | 
					        $invoicePublicId = Input::old('invoice') ? Input::old('invoice') : ($request->invoice_id ?: 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $totalCredit = false;
 | 
				
			||||||
 | 
					        if ($clientPublicId && $client = Client::scope($clientPublicId)->first()) {
 | 
				
			||||||
 | 
					            $totalCredit = $account->formatMoney($client->getTotalCredit(), $client);
 | 
				
			||||||
 | 
					        } elseif ($invoicePublicId && $invoice = Invoice::scope($invoicePublicId)->first()) {
 | 
				
			||||||
 | 
					            $totalCredit = $account->formatMoney($invoice->client->getTotalCredit(), $client);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'account' => Auth::user()->account,
 | 
					            'account' => Auth::user()->account,
 | 
				
			||||||
            'clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0),
 | 
					            'clientPublicId' => $clientPublicId,
 | 
				
			||||||
            'invoicePublicId' => Input::old('invoice') ? Input::old('invoice') : ($request->invoice_id ?: 0),
 | 
					            'invoicePublicId' => $invoicePublicId,
 | 
				
			||||||
            'invoice' => null,
 | 
					            'invoice' => null,
 | 
				
			||||||
            'invoices' => $invoices,
 | 
					            'invoices' => $invoices,
 | 
				
			||||||
            'payment' => null,
 | 
					            'payment' => null,
 | 
				
			||||||
@ -106,7 +119,9 @@ class PaymentController extends BaseController
 | 
				
			|||||||
            'url' => 'payments',
 | 
					            'url' => 'payments',
 | 
				
			||||||
            'title' => trans('texts.new_payment'),
 | 
					            'title' => trans('texts.new_payment'),
 | 
				
			||||||
            'paymentTypeId' => Input::get('paymentTypeId'),
 | 
					            'paymentTypeId' => Input::get('paymentTypeId'),
 | 
				
			||||||
            'clients' => Client::scope()->with('contacts')->orderBy('name')->get(), ];
 | 
					            'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
 | 
				
			||||||
 | 
					            'totalCredit' => $totalCredit,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return View::make('payments.edit', $data);
 | 
					        return View::make('payments.edit', $data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										160
									
								
								app/Http/Controllers/PaymentTermApiController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								app/Http/Controllers/PaymentTermApiController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,160 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Requests\CreatePaymentTermAPIRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\PaymentTermRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\UpdatePaymentTermRequest;
 | 
				
			||||||
 | 
					use App\Libraries\Utils;
 | 
				
			||||||
 | 
					use App\Models\PaymentTerm;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\PaymentTermRepository;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PaymentTermApiController extends BaseAPIController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var PaymentTermRepository
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $paymentTermRepo;
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PAYMENT_TERM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * PaymentTermApiController constructor.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param PaymentTermRepository $paymentTermRepo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __construct(PaymentTermRepository $paymentTermRepo)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::__construct();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->paymentTermRepo = $paymentTermRepo;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @SWG\Get(
 | 
				
			||||||
 | 
					     *   path="/paymentTerms",
 | 
				
			||||||
 | 
					     *   summary="List payment terms",
 | 
				
			||||||
 | 
					     *   operationId="listPaymentTerms",
 | 
				
			||||||
 | 
					     *   tags={"payment terms"},
 | 
				
			||||||
 | 
					     *   @SWG\Response(
 | 
				
			||||||
 | 
					     *     response=200,
 | 
				
			||||||
 | 
					     *     description="A list of payment terms",
 | 
				
			||||||
 | 
					     *      @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/PaymentTerms"))
 | 
				
			||||||
 | 
					     *   ),
 | 
				
			||||||
 | 
					     *   @SWG\Response(
 | 
				
			||||||
 | 
					     *     response="default",
 | 
				
			||||||
 | 
					     *     description="an ""unexpected"" error"
 | 
				
			||||||
 | 
					     *   )
 | 
				
			||||||
 | 
					     * )
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function index()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $paymentTerms = PaymentTerm::scope()
 | 
				
			||||||
 | 
					            ->orWhere('account_id',0)
 | 
				
			||||||
 | 
					            ->orderBy('num_days', 'asc');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->listResponse($paymentTerms);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * @SWG\Get(
 | 
				
			||||||
 | 
					         *   path="/paymentTerms/{payment_term_id}",
 | 
				
			||||||
 | 
					         *   summary="Retrieve a payment term",
 | 
				
			||||||
 | 
					         *   operationId="getPaymentTermId",
 | 
				
			||||||
 | 
					         *   tags={"payment term"},
 | 
				
			||||||
 | 
					         *   @SWG\Parameter(
 | 
				
			||||||
 | 
					         *     in="path",
 | 
				
			||||||
 | 
					         *     name="payment_term_id",
 | 
				
			||||||
 | 
					         *     type="integer",
 | 
				
			||||||
 | 
					         *     required=true
 | 
				
			||||||
 | 
					         *   ),
 | 
				
			||||||
 | 
					         *   @SWG\Response(
 | 
				
			||||||
 | 
					         *     response=200,
 | 
				
			||||||
 | 
					         *     description="A single payment term",
 | 
				
			||||||
 | 
					         *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/PaymentTerms"))
 | 
				
			||||||
 | 
					         *   ),
 | 
				
			||||||
 | 
					         *   @SWG\Response(
 | 
				
			||||||
 | 
					         *     response="default",
 | 
				
			||||||
 | 
					         *     description="an ""unexpected"" error"
 | 
				
			||||||
 | 
					         *   )
 | 
				
			||||||
 | 
					         * )
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function show(PaymentTermRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->itemResponse($request->entity());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * @SWG\Post(
 | 
				
			||||||
 | 
					         *   path="/paymentTerms",
 | 
				
			||||||
 | 
					         *   summary="Create a payment Term",
 | 
				
			||||||
 | 
					         *   operationId="createPaymentTerm",
 | 
				
			||||||
 | 
					         *   tags={"payment term"},
 | 
				
			||||||
 | 
					         *   @SWG\Parameter(
 | 
				
			||||||
 | 
					         *     in="body",
 | 
				
			||||||
 | 
					         *     name="payment term",
 | 
				
			||||||
 | 
					         *     @SWG\Schema(ref="#/definitions/PaymentTerm")
 | 
				
			||||||
 | 
					         *   ),
 | 
				
			||||||
 | 
					         *   @SWG\Response(
 | 
				
			||||||
 | 
					         *     response=200,
 | 
				
			||||||
 | 
					         *     description="New payment Term",
 | 
				
			||||||
 | 
					         *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/PaymentTerm"))
 | 
				
			||||||
 | 
					         *   ),
 | 
				
			||||||
 | 
					         *   @SWG\Response(
 | 
				
			||||||
 | 
					         *     response="default",
 | 
				
			||||||
 | 
					         *     description="an ""unexpected"" error"
 | 
				
			||||||
 | 
					         *   )
 | 
				
			||||||
 | 
					         * )
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					    public function store(CreatePaymentTermAPIRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $paymentTerm = PaymentTerm::createNew();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $paymentTerm->num_days = Utils::parseInt(Input::get('num_days'));
 | 
				
			||||||
 | 
					        $paymentTerm->name = 'Net ' . $paymentTerm->num_days;
 | 
				
			||||||
 | 
					        $paymentTerm->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->itemResponse($paymentTerm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @SWG\Delete(
 | 
				
			||||||
 | 
					     *   path="/paymentTerm/{num_days}",
 | 
				
			||||||
 | 
					     *   summary="Delete a payment term",
 | 
				
			||||||
 | 
					     *   operationId="deletePaymentTerm",
 | 
				
			||||||
 | 
					     *   tags={"payment term"},
 | 
				
			||||||
 | 
					     *   @SWG\Parameter(
 | 
				
			||||||
 | 
					     *     in="path",
 | 
				
			||||||
 | 
					     *     name="num_days",
 | 
				
			||||||
 | 
					     *     type="integer",
 | 
				
			||||||
 | 
					     *     required=true
 | 
				
			||||||
 | 
					     *   ),
 | 
				
			||||||
 | 
					     *   @SWG\Response(
 | 
				
			||||||
 | 
					     *     response=200,
 | 
				
			||||||
 | 
					     *     description="Deleted payment Term",
 | 
				
			||||||
 | 
					     *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/PaymentTerm"))
 | 
				
			||||||
 | 
					     *   ),
 | 
				
			||||||
 | 
					     *   @SWG\Response(
 | 
				
			||||||
 | 
					     *     response="default",
 | 
				
			||||||
 | 
					     *     description="an ""unexpected"" error"
 | 
				
			||||||
 | 
					     *   )
 | 
				
			||||||
 | 
					     * )
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function destroy($numDays)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $paymentTerm = PaymentTerm::where('num_days', $numDays)->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!$paymentTerm || $paymentTerm->account_id == 0)
 | 
				
			||||||
 | 
					            return $this->errorResponse(['message'=>'Cannot delete a default or non existent Payment Term'], 400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->paymentTermRepo->archive($paymentTerm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->itemResponse($paymentTerm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										128
									
								
								app/Http/Controllers/ProposalCategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Http/Controllers/ProposalCategoryController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Requests\CreateProposalCategoryRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\ProposalCategoryRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\UpdateProposalCategoryRequest;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\ProposalCategory;
 | 
				
			||||||
 | 
					use App\Ninja\Datatables\ProposalCategoryDatatable;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\ProposalCategoryRepository;
 | 
				
			||||||
 | 
					use App\Services\ProposalCategoryService;
 | 
				
			||||||
 | 
					use Auth;
 | 
				
			||||||
 | 
					use Input;
 | 
				
			||||||
 | 
					use Session;
 | 
				
			||||||
 | 
					use View;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalCategoryController extends BaseController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $proposalCategoryRepo;
 | 
				
			||||||
 | 
					    protected $proposalCategoryService;
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_CATEGORY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ProposalCategoryRepository $proposalCategoryRepo, ProposalCategoryService $proposalCategoryService)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->proposalCategoryRepo = $proposalCategoryRepo;
 | 
				
			||||||
 | 
					        $this->proposalCategoryService = $proposalCategoryService;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Display a listing of the resource.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Response
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function index()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return View::make('list_wrapper', [
 | 
				
			||||||
 | 
					            'entityType' => ENTITY_PROPOSAL_CATEGORY,
 | 
				
			||||||
 | 
					            'datatable' => new ProposalCategoryDatatable(),
 | 
				
			||||||
 | 
					            'title' => trans('texts.proposal_categories'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDatatable($expensePublicId = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $search = Input::get('sSearch');
 | 
				
			||||||
 | 
					        $userId = Auth::user()->filterId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->proposalCategoryService->getDatatable($search, $userId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function create(ProposalCategoryRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
 | 
					            'category' => null,
 | 
				
			||||||
 | 
					            'method' => 'POST',
 | 
				
			||||||
 | 
					            'url' => 'proposals/categories',
 | 
				
			||||||
 | 
					            'title' => trans('texts.new_proposal_category'),
 | 
				
			||||||
 | 
					            'quotes' => Invoice::scope()->with('client.contacts')->quotes()->orderBy('id')->get(),
 | 
				
			||||||
 | 
					            'templates' => ProposalCategory::scope()->orderBy('name')->get(),
 | 
				
			||||||
 | 
					            'quotePublicId' => $request->quote_id,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/categories.edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function show($publicId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Session::reflash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect("proposals/categories/$publicId/edit");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function edit(ProposalCategoryRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalCategory = $request->entity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
 | 
					            'category' => $proposalCategory,
 | 
				
			||||||
 | 
					            'method' => 'PUT',
 | 
				
			||||||
 | 
					            'url' => 'proposals/categories/' . $proposalCategory->public_id,
 | 
				
			||||||
 | 
					            'title' => trans('texts.edit_proposal_category'),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/categories.edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function store(CreateProposalCategoryRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalCategory = $this->proposalCategoryService->save($request->input());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.created_proposal_category'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalCategory->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function update(UpdateProposalCategoryRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalCategory = $this->proposalCategoryService->save($request->input(), $request->entity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.updated_proposal_category'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        if (in_array($action, ['archive', 'delete', 'restore'])) {
 | 
				
			||||||
 | 
					            return self::bulk();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalCategory->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function bulk()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        $ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $count = $this->proposalCategoryService->bulk($ids, $action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($count > 0) {
 | 
				
			||||||
 | 
					            $field = $count == 1 ? "{$action}d_proposal_category" : "{$action}d_proposal_categories";
 | 
				
			||||||
 | 
					            $message = trans("texts.$field", ['count' => $count]);
 | 
				
			||||||
 | 
					            Session::flash('message', $message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to('/proposals/categories');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										178
									
								
								app/Http/Controllers/ProposalController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								app/Http/Controllers/ProposalController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,178 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Requests\CreateProposalRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\ProposalRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\UpdateProposalRequest;
 | 
				
			||||||
 | 
					use App\Jobs\SendInvoiceEmail;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\Proposal;
 | 
				
			||||||
 | 
					use App\Models\ProposalTemplate;
 | 
				
			||||||
 | 
					use App\Ninja\Mailers\ContactMailer;
 | 
				
			||||||
 | 
					use App\Ninja\Datatables\ProposalDatatable;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\ProposalRepository;
 | 
				
			||||||
 | 
					use App\Services\ProposalService;
 | 
				
			||||||
 | 
					use Auth;
 | 
				
			||||||
 | 
					use Input;
 | 
				
			||||||
 | 
					use Session;
 | 
				
			||||||
 | 
					use View;
 | 
				
			||||||
 | 
					use mPDF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalController extends BaseController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $proposalRepo;
 | 
				
			||||||
 | 
					    protected $proposalService;
 | 
				
			||||||
 | 
					    protected $contactMailer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ProposalRepository $proposalRepo, ProposalService $proposalService, ContactMailer $contactMailer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->proposalRepo = $proposalRepo;
 | 
				
			||||||
 | 
					        $this->proposalService = $proposalService;
 | 
				
			||||||
 | 
					        $this->contactMailer = $contactMailer;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Display a listing of the resource.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Response
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function index()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return View::make('list_wrapper', [
 | 
				
			||||||
 | 
					            'entityType' => ENTITY_PROPOSAL,
 | 
				
			||||||
 | 
					            'datatable' => new ProposalDatatable(),
 | 
				
			||||||
 | 
					            'title' => trans('texts.proposals'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDatatable($expensePublicId = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $search = Input::get('sSearch');
 | 
				
			||||||
 | 
					        $userId = Auth::user()->filterId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->proposalService->getDatatable($search, $userId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function create(ProposalRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $data = array_merge($this->getViewmodel(), [
 | 
				
			||||||
 | 
					            'proposal' => null,
 | 
				
			||||||
 | 
					            'method' => 'POST',
 | 
				
			||||||
 | 
					            'url' => 'proposals',
 | 
				
			||||||
 | 
					            'title' => trans('texts.new_proposal'),
 | 
				
			||||||
 | 
					            'invoices' => Invoice::scope()->with('client.contacts', 'client.country')->unapprovedQuotes()->orderBy('id')->get(),
 | 
				
			||||||
 | 
					            'invoicePublicId' => $request->invoice_id,
 | 
				
			||||||
 | 
					            'templatePublicId' => $request->proposal_template_id,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals.edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function show($publicId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Session::reflash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect("proposals/$publicId/edit");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function edit(ProposalRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposal = $request->entity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = array_merge($this->getViewmodel(), [
 | 
				
			||||||
 | 
					            'proposal' => $proposal,
 | 
				
			||||||
 | 
					            'entity' => $proposal,
 | 
				
			||||||
 | 
					            'method' => 'PUT',
 | 
				
			||||||
 | 
					            'url' => 'proposals/' . $proposal->public_id,
 | 
				
			||||||
 | 
					            'title' => trans('texts.edit_proposal'),
 | 
				
			||||||
 | 
					            'invoices' => Invoice::scope()->with('client.contacts', 'client.country')->unapprovedQuotes($proposal->invoice_id)->orderBy('id')->get(),
 | 
				
			||||||
 | 
					            'invoicePublicId' => $proposal->invoice ? $proposal->invoice->public_id : null,
 | 
				
			||||||
 | 
					            'templatePublicId' => $proposal->proposal_template ? $proposal->proposal_template->public_id : null,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals.edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getViewmodel()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $account = auth()->user()->account;
 | 
				
			||||||
 | 
					        $templates = ProposalTemplate::whereAccountId($account->id)->orderBy('name')->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (! $templates->count()) {
 | 
				
			||||||
 | 
					            $templates = ProposalTemplate::whereNull('account_id')->orderBy('name')->get();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'templates' => $templates,
 | 
				
			||||||
 | 
					            'account' => $account,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function store(CreateProposalRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposal = $this->proposalService->save($request->input());
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($action == 'email') {
 | 
				
			||||||
 | 
					            $this->dispatch(new SendInvoiceEmail($proposal->invoice, auth()->user()->id, false, false, $proposal));
 | 
				
			||||||
 | 
					            Session::flash('message', trans('texts.emailed_proposal'));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Session::flash('message', trans('texts.created_proposal'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposal->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function update(UpdateProposalRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposal = $this->proposalService->save($request->input(), $request->entity());
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (in_array($action, ['archive', 'delete', 'restore'])) {
 | 
				
			||||||
 | 
					            return self::bulk();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($action == 'email') {
 | 
				
			||||||
 | 
					            $this->dispatch(new SendInvoiceEmail($proposal->invoice, auth()->user()->id, false, false, $proposal));
 | 
				
			||||||
 | 
					            Session::flash('message', trans('texts.emailed_proposal'));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Session::flash('message', trans('texts.updated_proposal'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposal->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function bulk()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $action = Input::get('bulk_action') ?: Input::get('action');
 | 
				
			||||||
 | 
					        $ids = Input::get('bulk_public_id') ?: (Input::get('public_id') ?: Input::get('ids'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $count = $this->proposalService->bulk($ids, $action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($count > 0) {
 | 
				
			||||||
 | 
					            $field = $count == 1 ? "{$action}d_proposal" : "{$action}d_proposals";
 | 
				
			||||||
 | 
					            $message = trans("texts.$field", ['count' => $count]);
 | 
				
			||||||
 | 
					            Session::flash('message', $message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to('/proposals');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function download(ProposalRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposal = $request->entity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mpdf = new mPDF();
 | 
				
			||||||
 | 
					        $mpdf->showImageErrors = true;
 | 
				
			||||||
 | 
					        $mpdf->WriteHTML($proposal->present()->htmlDocument);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //$mpdf->Output();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mpdf->Output($proposal->present()->filename, 'D');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										732
									
								
								app/Http/Controllers/ProposalSnippetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										732
									
								
								app/Http/Controllers/ProposalSnippetController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,732 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Requests\CreateProposalSnippetRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\ProposalSnippetRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\UpdateProposalSnippetRequest;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\ProposalSnippet;
 | 
				
			||||||
 | 
					use App\Models\ProposalCategory;
 | 
				
			||||||
 | 
					use App\Ninja\Datatables\ProposalSnippetDatatable;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\ProposalSnippetRepository;
 | 
				
			||||||
 | 
					use App\Services\ProposalSnippetService;
 | 
				
			||||||
 | 
					use Auth;
 | 
				
			||||||
 | 
					use Input;
 | 
				
			||||||
 | 
					use Session;
 | 
				
			||||||
 | 
					use View;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalSnippetController extends BaseController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $proposalSnippetRepo;
 | 
				
			||||||
 | 
					    protected $proposalSnippetService;
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_SNIPPET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ProposalSnippetRepository $proposalSnippetRepo, ProposalSnippetService $proposalSnippetService)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->proposalSnippetRepo = $proposalSnippetRepo;
 | 
				
			||||||
 | 
					        $this->proposalSnippetService = $proposalSnippetService;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Display a listing of the resource.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Response
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function index()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return View::make('list_wrapper', [
 | 
				
			||||||
 | 
					            'entityType' => ENTITY_PROPOSAL_SNIPPET,
 | 
				
			||||||
 | 
					            'datatable' => new ProposalSnippetDatatable(),
 | 
				
			||||||
 | 
					            'title' => trans('texts.proposal_snippets'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDatatable($expensePublicId = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $search = Input::get('sSearch');
 | 
				
			||||||
 | 
					        $userId = Auth::user()->filterId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->proposalSnippetService->getDatatable($search, $userId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function create(ProposalSnippetRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
 | 
					            'snippet' => null,
 | 
				
			||||||
 | 
					            'method' => 'POST',
 | 
				
			||||||
 | 
					            'url' => 'proposals/snippets',
 | 
				
			||||||
 | 
					            'title' => trans('texts.new_proposal_snippet'),
 | 
				
			||||||
 | 
					            'categories' => ProposalCategory::scope()->orderBy('name')->get(),
 | 
				
			||||||
 | 
					            'categoryPublicId' => 0,
 | 
				
			||||||
 | 
					            'icons' => $this->getIcons(),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/snippets/edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function show($publicId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Session::reflash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect("proposals/snippets/$publicId/edit");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function edit(ProposalSnippetRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalSnippet = $request->entity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
 | 
					            'snippet' => $proposalSnippet,
 | 
				
			||||||
 | 
					            'entity' => $proposalSnippet,
 | 
				
			||||||
 | 
					            'method' => 'PUT',
 | 
				
			||||||
 | 
					            'url' => 'proposals/snippets/' . $proposalSnippet->public_id,
 | 
				
			||||||
 | 
					            'title' => trans('texts.edit_proposal_snippet'),
 | 
				
			||||||
 | 
					            'categories' => ProposalCategory::scope()->orderBy('name')->get(),
 | 
				
			||||||
 | 
					            'categoryPublicId' => $proposalSnippet->proposal_category ? $proposalSnippet->proposal_category->public_id : null,
 | 
				
			||||||
 | 
					            'icons' => $this->getIcons(),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/snippets.edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function store(CreateProposalSnippetRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalSnippet = $this->proposalSnippetService->save($request->input());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.created_proposal_snippet'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalSnippet->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function update(UpdateProposalSnippetRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalSnippet = $this->proposalSnippetService->save($request->input(), $request->entity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.updated_proposal_snippet'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        if (in_array($action, ['archive', 'delete', 'restore'])) {
 | 
				
			||||||
 | 
					            return self::bulk();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalSnippet->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function bulk()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        $ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $count = $this->proposalSnippetService->bulk($ids, $action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($count > 0) {
 | 
				
			||||||
 | 
					            $field = $count == 1 ? "{$action}d_proposal_snippet" : "{$action}d_proposal_snippets";
 | 
				
			||||||
 | 
					            $message = trans("texts.$field", ['count' => $count]);
 | 
				
			||||||
 | 
					            Session::flash('message', $message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to('/proposals/snippets');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getIcons() {
 | 
				
			||||||
 | 
					        $data = [];
 | 
				
			||||||
 | 
					        $icons = [
 | 
				
			||||||
 | 
					            ['name'=>'glass','code'=>'f000'],
 | 
				
			||||||
 | 
					            ['name'=>'music','code'=>'f001'],
 | 
				
			||||||
 | 
					            ['name'=>'search','code'=>'f002'],
 | 
				
			||||||
 | 
					            ['name'=>'envelope-o','code'=>'f003'],
 | 
				
			||||||
 | 
					            ['name'=>'heart','code'=>'f004'],
 | 
				
			||||||
 | 
					            ['name'=>'star','code'=>'f005'],
 | 
				
			||||||
 | 
					            ['name'=>'star-o','code'=>'f006'],
 | 
				
			||||||
 | 
					            ['name'=>'user','code'=>'f007'],
 | 
				
			||||||
 | 
					            ['name'=>'film','code'=>'f008'],
 | 
				
			||||||
 | 
					            ['name'=>'th-large','code'=>'f009'],
 | 
				
			||||||
 | 
					            ['name'=>'th','code'=>'f00a'],
 | 
				
			||||||
 | 
					            ['name'=>'th-list','code'=>'f00b'],
 | 
				
			||||||
 | 
					            ['name'=>'check','code'=>'f00c'],
 | 
				
			||||||
 | 
					            ['name'=>'times','code'=>'f00d'],
 | 
				
			||||||
 | 
					            ['name'=>'search-plus','code'=>'f00e'],
 | 
				
			||||||
 | 
					            ['name'=>'search-minus','code'=>'f010'],
 | 
				
			||||||
 | 
					            ['name'=>'power-off','code'=>'f011'],
 | 
				
			||||||
 | 
					            ['name'=>'signal','code'=>'f012'],
 | 
				
			||||||
 | 
					            ['name'=>'cog','code'=>'f013'],
 | 
				
			||||||
 | 
					            ['name'=>'trash-o','code'=>'f014'],
 | 
				
			||||||
 | 
					            ['name'=>'home','code'=>'f015'],
 | 
				
			||||||
 | 
					            ['name'=>'file-o','code'=>'f016'],
 | 
				
			||||||
 | 
					            ['name'=>'clock-o','code'=>'f017'],
 | 
				
			||||||
 | 
					            ['name'=>'road','code'=>'f018'],
 | 
				
			||||||
 | 
					            ['name'=>'download','code'=>'f019'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-o-down','code'=>'f01a'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-o-up','code'=>'f01b'],
 | 
				
			||||||
 | 
					            ['name'=>'inbox','code'=>'f01c'],
 | 
				
			||||||
 | 
					            ['name'=>'play-circle-o','code'=>'f01d'],
 | 
				
			||||||
 | 
					            ['name'=>'repeat','code'=>'f01e'],
 | 
				
			||||||
 | 
					            ['name'=>'refresh','code'=>'f021'],
 | 
				
			||||||
 | 
					            ['name'=>'list-alt','code'=>'f022'],
 | 
				
			||||||
 | 
					            ['name'=>'lock','code'=>'f023'],
 | 
				
			||||||
 | 
					            ['name'=>'flag','code'=>'f024'],
 | 
				
			||||||
 | 
					            ['name'=>'headphones','code'=>'f025'],
 | 
				
			||||||
 | 
					            ['name'=>'volume-off','code'=>'f026'],
 | 
				
			||||||
 | 
					            ['name'=>'volume-down','code'=>'f027'],
 | 
				
			||||||
 | 
					            ['name'=>'volume-up','code'=>'f028'],
 | 
				
			||||||
 | 
					            ['name'=>'qrcode','code'=>'f029'],
 | 
				
			||||||
 | 
					            ['name'=>'barcode','code'=>'f02a'],
 | 
				
			||||||
 | 
					            ['name'=>'tag','code'=>'f02b'],
 | 
				
			||||||
 | 
					            ['name'=>'tags','code'=>'f02c'],
 | 
				
			||||||
 | 
					            ['name'=>'book','code'=>'f02d'],
 | 
				
			||||||
 | 
					            ['name'=>'bookmark','code'=>'f02e'],
 | 
				
			||||||
 | 
					            ['name'=>'print','code'=>'f02f'],
 | 
				
			||||||
 | 
					            ['name'=>'camera','code'=>'f030'],
 | 
				
			||||||
 | 
					            ['name'=>'font','code'=>'f031'],
 | 
				
			||||||
 | 
					            ['name'=>'bold','code'=>'f032'],
 | 
				
			||||||
 | 
					            ['name'=>'italic','code'=>'f033'],
 | 
				
			||||||
 | 
					            ['name'=>'text-height','code'=>'f034'],
 | 
				
			||||||
 | 
					            ['name'=>'text-width','code'=>'f035'],
 | 
				
			||||||
 | 
					            ['name'=>'align-left','code'=>'f036'],
 | 
				
			||||||
 | 
					            ['name'=>'align-center','code'=>'f037'],
 | 
				
			||||||
 | 
					            ['name'=>'align-right','code'=>'f038'],
 | 
				
			||||||
 | 
					            ['name'=>'align-justify','code'=>'f039'],
 | 
				
			||||||
 | 
					            ['name'=>'list','code'=>'f03a'],
 | 
				
			||||||
 | 
					            ['name'=>'outdent','code'=>'f03b'],
 | 
				
			||||||
 | 
					            ['name'=>'indent','code'=>'f03c'],
 | 
				
			||||||
 | 
					            ['name'=>'video-camera','code'=>'f03d'],
 | 
				
			||||||
 | 
					            ['name'=>'picture-o','code'=>'f03e'],
 | 
				
			||||||
 | 
					            ['name'=>'pencil','code'=>'f040'],
 | 
				
			||||||
 | 
					            ['name'=>'map-marker','code'=>'f041'],
 | 
				
			||||||
 | 
					            ['name'=>'adjust','code'=>'f042'],
 | 
				
			||||||
 | 
					            ['name'=>'tint','code'=>'f043'],
 | 
				
			||||||
 | 
					            ['name'=>'pencil-square-o','code'=>'f044'],
 | 
				
			||||||
 | 
					            ['name'=>'share-square-o','code'=>'f045'],
 | 
				
			||||||
 | 
					            ['name'=>'check-square-o','code'=>'f046'],
 | 
				
			||||||
 | 
					            ['name'=>'arrows','code'=>'f047'],
 | 
				
			||||||
 | 
					            ['name'=>'step-backward','code'=>'f048'],
 | 
				
			||||||
 | 
					            ['name'=>'fast-backward','code'=>'f049'],
 | 
				
			||||||
 | 
					            ['name'=>'backward','code'=>'f04a'],
 | 
				
			||||||
 | 
					            ['name'=>'play','code'=>'f04b'],
 | 
				
			||||||
 | 
					            ['name'=>'pause','code'=>'f04c'],
 | 
				
			||||||
 | 
					            ['name'=>'stop','code'=>'f04d'],
 | 
				
			||||||
 | 
					            ['name'=>'forward','code'=>'f04e'],
 | 
				
			||||||
 | 
					            ['name'=>'fast-forward','code'=>'f050'],
 | 
				
			||||||
 | 
					            ['name'=>'step-forward','code'=>'f051'],
 | 
				
			||||||
 | 
					            ['name'=>'eject','code'=>'f052'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-left','code'=>'f053'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-right','code'=>'f054'],
 | 
				
			||||||
 | 
					            ['name'=>'plus-circle','code'=>'f055'],
 | 
				
			||||||
 | 
					            ['name'=>'minus-circle','code'=>'f056'],
 | 
				
			||||||
 | 
					            ['name'=>'times-circle','code'=>'f057'],
 | 
				
			||||||
 | 
					            ['name'=>'check-circle','code'=>'f058'],
 | 
				
			||||||
 | 
					            ['name'=>'question-circle','code'=>'f059'],
 | 
				
			||||||
 | 
					            ['name'=>'info-circle','code'=>'f05a'],
 | 
				
			||||||
 | 
					            ['name'=>'crosshairs','code'=>'f05b'],
 | 
				
			||||||
 | 
					            ['name'=>'times-circle-o','code'=>'f05c'],
 | 
				
			||||||
 | 
					            ['name'=>'check-circle-o','code'=>'f05d'],
 | 
				
			||||||
 | 
					            ['name'=>'ban','code'=>'f05e'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-left','code'=>'f060'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-right','code'=>'f061'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-up','code'=>'f062'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-down','code'=>'f063'],
 | 
				
			||||||
 | 
					            ['name'=>'share','code'=>'f064'],
 | 
				
			||||||
 | 
					            ['name'=>'expand','code'=>'f065'],
 | 
				
			||||||
 | 
					            ['name'=>'compress','code'=>'f066'],
 | 
				
			||||||
 | 
					            ['name'=>'plus','code'=>'f067'],
 | 
				
			||||||
 | 
					            ['name'=>'minus','code'=>'f068'],
 | 
				
			||||||
 | 
					            ['name'=>'asterisk','code'=>'f069'],
 | 
				
			||||||
 | 
					            ['name'=>'exclamation-circle','code'=>'f06a'],
 | 
				
			||||||
 | 
					            ['name'=>'gift','code'=>'f06b'],
 | 
				
			||||||
 | 
					            ['name'=>'leaf','code'=>'f06c'],
 | 
				
			||||||
 | 
					            ['name'=>'fire','code'=>'f06d'],
 | 
				
			||||||
 | 
					            ['name'=>'eye','code'=>'f06e'],
 | 
				
			||||||
 | 
					            ['name'=>'eye-slash','code'=>'f070'],
 | 
				
			||||||
 | 
					            ['name'=>'exclamation-triangle','code'=>'f071'],
 | 
				
			||||||
 | 
					            ['name'=>'plane','code'=>'f072'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar','code'=>'f073'],
 | 
				
			||||||
 | 
					            ['name'=>'random','code'=>'f074'],
 | 
				
			||||||
 | 
					            ['name'=>'comment','code'=>'f075'],
 | 
				
			||||||
 | 
					            ['name'=>'magnet','code'=>'f076'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-up','code'=>'f077'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-down','code'=>'f078'],
 | 
				
			||||||
 | 
					            ['name'=>'retweet','code'=>'f079'],
 | 
				
			||||||
 | 
					            ['name'=>'shopping-cart','code'=>'f07a'],
 | 
				
			||||||
 | 
					            ['name'=>'folder','code'=>'f07b'],
 | 
				
			||||||
 | 
					            ['name'=>'folder-open','code'=>'f07c'],
 | 
				
			||||||
 | 
					            ['name'=>'arrows-v','code'=>'f07d'],
 | 
				
			||||||
 | 
					            ['name'=>'arrows-h','code'=>'f07e'],
 | 
				
			||||||
 | 
					            ['name'=>'bar-chart','code'=>'f080'],
 | 
				
			||||||
 | 
					            ['name'=>'twitter-square','code'=>'f081'],
 | 
				
			||||||
 | 
					            ['name'=>'facebook-square','code'=>'f082'],
 | 
				
			||||||
 | 
					            ['name'=>'camera-retro','code'=>'f083'],
 | 
				
			||||||
 | 
					            ['name'=>'key','code'=>'f084'],
 | 
				
			||||||
 | 
					            ['name'=>'cogs','code'=>'f085'],
 | 
				
			||||||
 | 
					            ['name'=>'comments','code'=>'f086'],
 | 
				
			||||||
 | 
					            ['name'=>'thumbs-o-up','code'=>'f087'],
 | 
				
			||||||
 | 
					            ['name'=>'thumbs-o-down','code'=>'f088'],
 | 
				
			||||||
 | 
					            ['name'=>'star-half','code'=>'f089'],
 | 
				
			||||||
 | 
					            ['name'=>'heart-o','code'=>'f08a'],
 | 
				
			||||||
 | 
					            ['name'=>'sign-out','code'=>'f08b'],
 | 
				
			||||||
 | 
					            ['name'=>'linkedin-square','code'=>'f08c'],
 | 
				
			||||||
 | 
					            ['name'=>'thumb-tack','code'=>'f08d'],
 | 
				
			||||||
 | 
					            ['name'=>'external-link','code'=>'f08e'],
 | 
				
			||||||
 | 
					            ['name'=>'sign-in','code'=>'f090'],
 | 
				
			||||||
 | 
					            ['name'=>'trophy','code'=>'f091'],
 | 
				
			||||||
 | 
					            ['name'=>'github-square','code'=>'f092'],
 | 
				
			||||||
 | 
					            ['name'=>'upload','code'=>'f093'],
 | 
				
			||||||
 | 
					            ['name'=>'lemon-o','code'=>'f094'],
 | 
				
			||||||
 | 
					            ['name'=>'phone','code'=>'f095'],
 | 
				
			||||||
 | 
					            ['name'=>'square-o','code'=>'f096'],
 | 
				
			||||||
 | 
					            ['name'=>'bookmark-o','code'=>'f097'],
 | 
				
			||||||
 | 
					            ['name'=>'phone-square','code'=>'f098'],
 | 
				
			||||||
 | 
					            ['name'=>'twitter','code'=>'f099'],
 | 
				
			||||||
 | 
					            ['name'=>'facebook','code'=>'f09a'],
 | 
				
			||||||
 | 
					            ['name'=>'github','code'=>'f09b'],
 | 
				
			||||||
 | 
					            ['name'=>'unlock','code'=>'f09c'],
 | 
				
			||||||
 | 
					            ['name'=>'credit-card','code'=>'f09d'],
 | 
				
			||||||
 | 
					            ['name'=>'rss','code'=>'f09e'],
 | 
				
			||||||
 | 
					            ['name'=>'hdd-o','code'=>'f0a0'],
 | 
				
			||||||
 | 
					            ['name'=>'bullhorn','code'=>'f0a1'],
 | 
				
			||||||
 | 
					            ['name'=>'bell','code'=>'f0f3'],
 | 
				
			||||||
 | 
					            ['name'=>'certificate','code'=>'f0a3'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-o-right','code'=>'f0a4'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-o-left','code'=>'f0a5'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-o-up','code'=>'f0a6'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-o-down','code'=>'f0a7'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-left','code'=>'f0a8'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-right','code'=>'f0a9'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-up','code'=>'f0aa'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-down','code'=>'f0ab'],
 | 
				
			||||||
 | 
					            ['name'=>'globe','code'=>'f0ac'],
 | 
				
			||||||
 | 
					            ['name'=>'wrench','code'=>'f0ad'],
 | 
				
			||||||
 | 
					            ['name'=>'tasks','code'=>'f0ae'],
 | 
				
			||||||
 | 
					            ['name'=>'filter','code'=>'f0b0'],
 | 
				
			||||||
 | 
					            ['name'=>'briefcase','code'=>'f0b1'],
 | 
				
			||||||
 | 
					            ['name'=>'arrows-alt','code'=>'f0b2'],
 | 
				
			||||||
 | 
					            ['name'=>'users','code'=>'f0c0'],
 | 
				
			||||||
 | 
					            ['name'=>'link','code'=>'f0c1'],
 | 
				
			||||||
 | 
					            ['name'=>'cloud','code'=>'f0c2'],
 | 
				
			||||||
 | 
					            ['name'=>'flask','code'=>'f0c3'],
 | 
				
			||||||
 | 
					            ['name'=>'scissors','code'=>'f0c4'],
 | 
				
			||||||
 | 
					            ['name'=>'files-o','code'=>'f0c5'],
 | 
				
			||||||
 | 
					            ['name'=>'paperclip','code'=>'f0c6'],
 | 
				
			||||||
 | 
					            ['name'=>'floppy-o','code'=>'f0c7'],
 | 
				
			||||||
 | 
					            ['name'=>'square','code'=>'f0c8'],
 | 
				
			||||||
 | 
					            ['name'=>'bars','code'=>'f0c9'],
 | 
				
			||||||
 | 
					            ['name'=>'list-ul','code'=>'f0ca'],
 | 
				
			||||||
 | 
					            ['name'=>'list-ol','code'=>'f0cb'],
 | 
				
			||||||
 | 
					            ['name'=>'strikethrough','code'=>'f0cc'],
 | 
				
			||||||
 | 
					            ['name'=>'underline','code'=>'f0cd'],
 | 
				
			||||||
 | 
					            ['name'=>'table','code'=>'f0ce'],
 | 
				
			||||||
 | 
					            ['name'=>'magic','code'=>'f0d0'],
 | 
				
			||||||
 | 
					            ['name'=>'truck','code'=>'f0d1'],
 | 
				
			||||||
 | 
					            ['name'=>'pinterest','code'=>'f0d2'],
 | 
				
			||||||
 | 
					            ['name'=>'pinterest-square','code'=>'f0d3'],
 | 
				
			||||||
 | 
					            ['name'=>'google-plus-square','code'=>'f0d4'],
 | 
				
			||||||
 | 
					            ['name'=>'google-plus','code'=>'f0d5'],
 | 
				
			||||||
 | 
					            ['name'=>'money','code'=>'f0d6'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-down','code'=>'f0d7'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-up','code'=>'f0d8'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-left','code'=>'f0d9'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-right','code'=>'f0da'],
 | 
				
			||||||
 | 
					            ['name'=>'columns','code'=>'f0db'],
 | 
				
			||||||
 | 
					            ['name'=>'sort','code'=>'f0dc'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-desc','code'=>'f0dd'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-asc','code'=>'f0de'],
 | 
				
			||||||
 | 
					            ['name'=>'envelope','code'=>'f0e0'],
 | 
				
			||||||
 | 
					            ['name'=>'linkedin','code'=>'f0e1'],
 | 
				
			||||||
 | 
					            ['name'=>'undo','code'=>'f0e2'],
 | 
				
			||||||
 | 
					            ['name'=>'gavel','code'=>'f0e3'],
 | 
				
			||||||
 | 
					            ['name'=>'tachometer','code'=>'f0e4'],
 | 
				
			||||||
 | 
					            ['name'=>'comment-o','code'=>'f0e5'],
 | 
				
			||||||
 | 
					            ['name'=>'comments-o','code'=>'f0e6'],
 | 
				
			||||||
 | 
					            ['name'=>'bolt','code'=>'f0e7'],
 | 
				
			||||||
 | 
					            ['name'=>'sitemap','code'=>'f0e8'],
 | 
				
			||||||
 | 
					            ['name'=>'umbrella','code'=>'f0e9'],
 | 
				
			||||||
 | 
					            ['name'=>'clipboard','code'=>'f0ea'],
 | 
				
			||||||
 | 
					            ['name'=>'lightbulb-o','code'=>'f0eb'],
 | 
				
			||||||
 | 
					            ['name'=>'exchange','code'=>'f0ec'],
 | 
				
			||||||
 | 
					            ['name'=>'cloud-download','code'=>'f0ed'],
 | 
				
			||||||
 | 
					            ['name'=>'cloud-upload','code'=>'f0ee'],
 | 
				
			||||||
 | 
					            ['name'=>'user-md','code'=>'f0f0'],
 | 
				
			||||||
 | 
					            ['name'=>'stethoscope','code'=>'f0f1'],
 | 
				
			||||||
 | 
					            ['name'=>'suitcase','code'=>'f0f2'],
 | 
				
			||||||
 | 
					            ['name'=>'bell-o','code'=>'f0a2'],
 | 
				
			||||||
 | 
					            ['name'=>'coffee','code'=>'f0f4'],
 | 
				
			||||||
 | 
					            ['name'=>'cutlery','code'=>'f0f5'],
 | 
				
			||||||
 | 
					            ['name'=>'file-text-o','code'=>'f0f6'],
 | 
				
			||||||
 | 
					            ['name'=>'building-o','code'=>'f0f7'],
 | 
				
			||||||
 | 
					            ['name'=>'hospital-o','code'=>'f0f8'],
 | 
				
			||||||
 | 
					            ['name'=>'ambulance','code'=>'f0f9'],
 | 
				
			||||||
 | 
					            ['name'=>'medkit','code'=>'f0fa'],
 | 
				
			||||||
 | 
					            ['name'=>'fighter-jet','code'=>'f0fb'],
 | 
				
			||||||
 | 
					            ['name'=>'beer','code'=>'f0fc'],
 | 
				
			||||||
 | 
					            ['name'=>'h-square','code'=>'f0fd'],
 | 
				
			||||||
 | 
					            ['name'=>'plus-square','code'=>'f0fe'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-double-left','code'=>'f100'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-double-right','code'=>'f101'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-double-up','code'=>'f102'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-double-down','code'=>'f103'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-left','code'=>'f104'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-right','code'=>'f105'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-up','code'=>'f106'],
 | 
				
			||||||
 | 
					            ['name'=>'angle-down','code'=>'f107'],
 | 
				
			||||||
 | 
					            ['name'=>'desktop','code'=>'f108'],
 | 
				
			||||||
 | 
					            ['name'=>'laptop','code'=>'f109'],
 | 
				
			||||||
 | 
					            ['name'=>'tablet','code'=>'f10a'],
 | 
				
			||||||
 | 
					            ['name'=>'mobile','code'=>'f10b'],
 | 
				
			||||||
 | 
					            ['name'=>'circle-o','code'=>'f10c'],
 | 
				
			||||||
 | 
					            ['name'=>'quote-left','code'=>'f10d'],
 | 
				
			||||||
 | 
					            ['name'=>'quote-right','code'=>'f10e'],
 | 
				
			||||||
 | 
					            ['name'=>'spinner','code'=>'f110'],
 | 
				
			||||||
 | 
					            ['name'=>'circle','code'=>'f111'],
 | 
				
			||||||
 | 
					            ['name'=>'reply','code'=>'f112'],
 | 
				
			||||||
 | 
					            ['name'=>'github-alt','code'=>'f113'],
 | 
				
			||||||
 | 
					            ['name'=>'folder-o','code'=>'f114'],
 | 
				
			||||||
 | 
					            ['name'=>'folder-open-o','code'=>'f115'],
 | 
				
			||||||
 | 
					            ['name'=>'smile-o','code'=>'f118'],
 | 
				
			||||||
 | 
					            ['name'=>'frown-o','code'=>'f119'],
 | 
				
			||||||
 | 
					            ['name'=>'meh-o','code'=>'f11a'],
 | 
				
			||||||
 | 
					            ['name'=>'gamepad','code'=>'f11b'],
 | 
				
			||||||
 | 
					            ['name'=>'keyboard-o','code'=>'f11c'],
 | 
				
			||||||
 | 
					            ['name'=>'flag-o','code'=>'f11d'],
 | 
				
			||||||
 | 
					            ['name'=>'flag-checkered','code'=>'f11e'],
 | 
				
			||||||
 | 
					            ['name'=>'terminal','code'=>'f120'],
 | 
				
			||||||
 | 
					            ['name'=>'code','code'=>'f121'],
 | 
				
			||||||
 | 
					            ['name'=>'reply-all','code'=>'f122'],
 | 
				
			||||||
 | 
					            ['name'=>'star-half-o','code'=>'f123'],
 | 
				
			||||||
 | 
					            ['name'=>'location-arrow','code'=>'f124'],
 | 
				
			||||||
 | 
					            ['name'=>'crop','code'=>'f125'],
 | 
				
			||||||
 | 
					            ['name'=>'code-fork','code'=>'f126'],
 | 
				
			||||||
 | 
					            ['name'=>'chain-broken','code'=>'f127'],
 | 
				
			||||||
 | 
					            ['name'=>'question','code'=>'f128'],
 | 
				
			||||||
 | 
					            ['name'=>'info','code'=>'f129'],
 | 
				
			||||||
 | 
					            ['name'=>'exclamation','code'=>'f12a'],
 | 
				
			||||||
 | 
					            ['name'=>'superscript','code'=>'f12b'],
 | 
				
			||||||
 | 
					            ['name'=>'subscript','code'=>'f12c'],
 | 
				
			||||||
 | 
					            ['name'=>'eraser','code'=>'f12d'],
 | 
				
			||||||
 | 
					            ['name'=>'puzzle-piece','code'=>'f12e'],
 | 
				
			||||||
 | 
					            ['name'=>'microphone','code'=>'f130'],
 | 
				
			||||||
 | 
					            ['name'=>'microphone-slash','code'=>'f131'],
 | 
				
			||||||
 | 
					            ['name'=>'shield','code'=>'f132'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar-o','code'=>'f133'],
 | 
				
			||||||
 | 
					            ['name'=>'fire-extinguisher','code'=>'f134'],
 | 
				
			||||||
 | 
					            ['name'=>'rocket','code'=>'f135'],
 | 
				
			||||||
 | 
					            ['name'=>'maxcdn','code'=>'f136'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-circle-left','code'=>'f137'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-circle-right','code'=>'f138'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-circle-up','code'=>'f139'],
 | 
				
			||||||
 | 
					            ['name'=>'chevron-circle-down','code'=>'f13a'],
 | 
				
			||||||
 | 
					            ['name'=>'html5','code'=>'f13b'],
 | 
				
			||||||
 | 
					            ['name'=>'css3','code'=>'f13c'],
 | 
				
			||||||
 | 
					            ['name'=>'anchor','code'=>'f13d'],
 | 
				
			||||||
 | 
					            ['name'=>'unlock-alt','code'=>'f13e'],
 | 
				
			||||||
 | 
					            ['name'=>'bullseye','code'=>'f140'],
 | 
				
			||||||
 | 
					            ['name'=>'ellipsis-h','code'=>'f141'],
 | 
				
			||||||
 | 
					            ['name'=>'ellipsis-v','code'=>'f142'],
 | 
				
			||||||
 | 
					            ['name'=>'rss-square','code'=>'f143'],
 | 
				
			||||||
 | 
					            ['name'=>'play-circle','code'=>'f144'],
 | 
				
			||||||
 | 
					            ['name'=>'ticket','code'=>'f145'],
 | 
				
			||||||
 | 
					            ['name'=>'minus-square','code'=>'f146'],
 | 
				
			||||||
 | 
					            ['name'=>'minus-square-o','code'=>'f147'],
 | 
				
			||||||
 | 
					            ['name'=>'level-up','code'=>'f148'],
 | 
				
			||||||
 | 
					            ['name'=>'level-down','code'=>'f149'],
 | 
				
			||||||
 | 
					            ['name'=>'check-square','code'=>'f14a'],
 | 
				
			||||||
 | 
					            ['name'=>'pencil-square','code'=>'f14b'],
 | 
				
			||||||
 | 
					            ['name'=>'external-link-square','code'=>'f14c'],
 | 
				
			||||||
 | 
					            ['name'=>'share-square','code'=>'f14d'],
 | 
				
			||||||
 | 
					            ['name'=>'compass','code'=>'f14e'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-square-o-down','code'=>'f150'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-square-o-up','code'=>'f151'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-square-o-right','code'=>'f152'],
 | 
				
			||||||
 | 
					            ['name'=>'eur','code'=>'f153'],
 | 
				
			||||||
 | 
					            ['name'=>'gbp','code'=>'f154'],
 | 
				
			||||||
 | 
					            ['name'=>'usd','code'=>'f155'],
 | 
				
			||||||
 | 
					            ['name'=>'inr','code'=>'f156'],
 | 
				
			||||||
 | 
					            ['name'=>'jpy','code'=>'f157'],
 | 
				
			||||||
 | 
					            ['name'=>'rub','code'=>'f158'],
 | 
				
			||||||
 | 
					            ['name'=>'krw','code'=>'f159'],
 | 
				
			||||||
 | 
					            ['name'=>'btc','code'=>'f15a'],
 | 
				
			||||||
 | 
					            ['name'=>'file','code'=>'f15b'],
 | 
				
			||||||
 | 
					            ['name'=>'file-text','code'=>'f15c'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-alpha-asc','code'=>'f15d'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-alpha-desc','code'=>'f15e'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-amount-asc','code'=>'f160'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-amount-desc','code'=>'f161'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-numeric-asc','code'=>'f162'],
 | 
				
			||||||
 | 
					            ['name'=>'sort-numeric-desc','code'=>'f163'],
 | 
				
			||||||
 | 
					            ['name'=>'thumbs-up','code'=>'f164'],
 | 
				
			||||||
 | 
					            ['name'=>'thumbs-down','code'=>'f165'],
 | 
				
			||||||
 | 
					            ['name'=>'youtube-square','code'=>'f166'],
 | 
				
			||||||
 | 
					            ['name'=>'youtube','code'=>'f167'],
 | 
				
			||||||
 | 
					            ['name'=>'xing','code'=>'f168'],
 | 
				
			||||||
 | 
					            ['name'=>'xing-square','code'=>'f169'],
 | 
				
			||||||
 | 
					            ['name'=>'youtube-play','code'=>'f16a'],
 | 
				
			||||||
 | 
					            ['name'=>'dropbox','code'=>'f16b'],
 | 
				
			||||||
 | 
					            ['name'=>'stack-overflow','code'=>'f16c'],
 | 
				
			||||||
 | 
					            ['name'=>'instagram','code'=>'f16d'],
 | 
				
			||||||
 | 
					            ['name'=>'flickr','code'=>'f16e'],
 | 
				
			||||||
 | 
					            ['name'=>'adn','code'=>'f170'],
 | 
				
			||||||
 | 
					            ['name'=>'bitbucket','code'=>'f171'],
 | 
				
			||||||
 | 
					            ['name'=>'bitbucket-square','code'=>'f172'],
 | 
				
			||||||
 | 
					            ['name'=>'tumblr','code'=>'f173'],
 | 
				
			||||||
 | 
					            ['name'=>'tumblr-square','code'=>'f174'],
 | 
				
			||||||
 | 
					            ['name'=>'long-arrow-down','code'=>'f175'],
 | 
				
			||||||
 | 
					            ['name'=>'long-arrow-up','code'=>'f176'],
 | 
				
			||||||
 | 
					            ['name'=>'long-arrow-left','code'=>'f177'],
 | 
				
			||||||
 | 
					            ['name'=>'long-arrow-right','code'=>'f178'],
 | 
				
			||||||
 | 
					            ['name'=>'apple','code'=>'f179'],
 | 
				
			||||||
 | 
					            ['name'=>'windows','code'=>'f17a'],
 | 
				
			||||||
 | 
					            ['name'=>'android','code'=>'f17b'],
 | 
				
			||||||
 | 
					            ['name'=>'linux','code'=>'f17c'],
 | 
				
			||||||
 | 
					            ['name'=>'dribbble','code'=>'f17d'],
 | 
				
			||||||
 | 
					            ['name'=>'skype','code'=>'f17e'],
 | 
				
			||||||
 | 
					            ['name'=>'foursquare','code'=>'f180'],
 | 
				
			||||||
 | 
					            ['name'=>'trello','code'=>'f181'],
 | 
				
			||||||
 | 
					            ['name'=>'female','code'=>'f182'],
 | 
				
			||||||
 | 
					            ['name'=>'male','code'=>'f183'],
 | 
				
			||||||
 | 
					            ['name'=>'gratipay','code'=>'f184'],
 | 
				
			||||||
 | 
					            ['name'=>'sun-o','code'=>'f185'],
 | 
				
			||||||
 | 
					            ['name'=>'moon-o','code'=>'f186'],
 | 
				
			||||||
 | 
					            ['name'=>'archive','code'=>'f187'],
 | 
				
			||||||
 | 
					            ['name'=>'bug','code'=>'f188'],
 | 
				
			||||||
 | 
					            ['name'=>'vk','code'=>'f189'],
 | 
				
			||||||
 | 
					            ['name'=>'weibo','code'=>'f18a'],
 | 
				
			||||||
 | 
					            ['name'=>'renren','code'=>'f18b'],
 | 
				
			||||||
 | 
					            ['name'=>'pagelines','code'=>'f18c'],
 | 
				
			||||||
 | 
					            ['name'=>'stack-exchange','code'=>'f18d'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-o-right','code'=>'f18e'],
 | 
				
			||||||
 | 
					            ['name'=>'arrow-circle-o-left','code'=>'f190'],
 | 
				
			||||||
 | 
					            ['name'=>'caret-square-o-left','code'=>'f191'],
 | 
				
			||||||
 | 
					            ['name'=>'dot-circle-o','code'=>'f192'],
 | 
				
			||||||
 | 
					            ['name'=>'wheelchair','code'=>'f193'],
 | 
				
			||||||
 | 
					            ['name'=>'vimeo-square','code'=>'f194'],
 | 
				
			||||||
 | 
					            ['name'=>'try','code'=>'f195'],
 | 
				
			||||||
 | 
					            ['name'=>'plus-square-o','code'=>'f196'],
 | 
				
			||||||
 | 
					            ['name'=>'space-shuttle','code'=>'f197'],
 | 
				
			||||||
 | 
					            ['name'=>'slack','code'=>'f198'],
 | 
				
			||||||
 | 
					            ['name'=>'envelope-square','code'=>'f199'],
 | 
				
			||||||
 | 
					            ['name'=>'wordpress','code'=>'f19a'],
 | 
				
			||||||
 | 
					            ['name'=>'openid','code'=>'f19b'],
 | 
				
			||||||
 | 
					            ['name'=>'university','code'=>'f19c'],
 | 
				
			||||||
 | 
					            ['name'=>'graduation-cap','code'=>'f19d'],
 | 
				
			||||||
 | 
					            ['name'=>'yahoo','code'=>'f19e'],
 | 
				
			||||||
 | 
					            ['name'=>'google','code'=>'f1a0'],
 | 
				
			||||||
 | 
					            ['name'=>'reddit','code'=>'f1a1'],
 | 
				
			||||||
 | 
					            ['name'=>'reddit-square','code'=>'f1a2'],
 | 
				
			||||||
 | 
					            ['name'=>'stumbleupon-circle','code'=>'f1a3'],
 | 
				
			||||||
 | 
					            ['name'=>'stumbleupon','code'=>'f1a4'],
 | 
				
			||||||
 | 
					            ['name'=>'delicious','code'=>'f1a5'],
 | 
				
			||||||
 | 
					            ['name'=>'digg','code'=>'f1a6'],
 | 
				
			||||||
 | 
					            ['name'=>'pied-piper','code'=>'f1a7'],
 | 
				
			||||||
 | 
					            ['name'=>'pied-piper-alt','code'=>'f1a8'],
 | 
				
			||||||
 | 
					            ['name'=>'drupal','code'=>'f1a9'],
 | 
				
			||||||
 | 
					            ['name'=>'joomla','code'=>'f1aa'],
 | 
				
			||||||
 | 
					            ['name'=>'language','code'=>'f1ab'],
 | 
				
			||||||
 | 
					            ['name'=>'fax','code'=>'f1ac'],
 | 
				
			||||||
 | 
					            ['name'=>'building','code'=>'f1ad'],
 | 
				
			||||||
 | 
					            ['name'=>'child','code'=>'f1ae'],
 | 
				
			||||||
 | 
					            ['name'=>'paw','code'=>'f1b0'],
 | 
				
			||||||
 | 
					            ['name'=>'spoon','code'=>'f1b1'],
 | 
				
			||||||
 | 
					            ['name'=>'cube','code'=>'f1b2'],
 | 
				
			||||||
 | 
					            ['name'=>'cubes','code'=>'f1b3'],
 | 
				
			||||||
 | 
					            ['name'=>'behance','code'=>'f1b4'],
 | 
				
			||||||
 | 
					            ['name'=>'behance-square','code'=>'f1b5'],
 | 
				
			||||||
 | 
					            ['name'=>'steam','code'=>'f1b6'],
 | 
				
			||||||
 | 
					            ['name'=>'steam-square','code'=>'f1b7'],
 | 
				
			||||||
 | 
					            ['name'=>'recycle','code'=>'f1b8'],
 | 
				
			||||||
 | 
					            ['name'=>'car','code'=>'f1b9'],
 | 
				
			||||||
 | 
					            ['name'=>'taxi','code'=>'f1ba'],
 | 
				
			||||||
 | 
					            ['name'=>'tree','code'=>'f1bb'],
 | 
				
			||||||
 | 
					            ['name'=>'spotify','code'=>'f1bc'],
 | 
				
			||||||
 | 
					            ['name'=>'deviantart','code'=>'f1bd'],
 | 
				
			||||||
 | 
					            ['name'=>'soundcloud','code'=>'f1be'],
 | 
				
			||||||
 | 
					            ['name'=>'database','code'=>'f1c0'],
 | 
				
			||||||
 | 
					            ['name'=>'file-pdf-o','code'=>'f1c1'],
 | 
				
			||||||
 | 
					            ['name'=>'file-word-o','code'=>'f1c2'],
 | 
				
			||||||
 | 
					            ['name'=>'file-excel-o','code'=>'f1c3'],
 | 
				
			||||||
 | 
					            ['name'=>'file-powerpoint-o','code'=>'f1c4'],
 | 
				
			||||||
 | 
					            ['name'=>'file-image-o','code'=>'f1c5'],
 | 
				
			||||||
 | 
					            ['name'=>'file-archive-o','code'=>'f1c6'],
 | 
				
			||||||
 | 
					            ['name'=>'file-audio-o','code'=>'f1c7'],
 | 
				
			||||||
 | 
					            ['name'=>'file-video-o','code'=>'f1c8'],
 | 
				
			||||||
 | 
					            ['name'=>'file-code-o','code'=>'f1c9'],
 | 
				
			||||||
 | 
					            ['name'=>'vine','code'=>'f1ca'],
 | 
				
			||||||
 | 
					            ['name'=>'codepen','code'=>'f1cb'],
 | 
				
			||||||
 | 
					            ['name'=>'jsfiddle','code'=>'f1cc'],
 | 
				
			||||||
 | 
					            ['name'=>'life-ring','code'=>'f1cd'],
 | 
				
			||||||
 | 
					            ['name'=>'circle-o-notch','code'=>'f1ce'],
 | 
				
			||||||
 | 
					            ['name'=>'rebel','code'=>'f1d0'],
 | 
				
			||||||
 | 
					            ['name'=>'empire','code'=>'f1d1'],
 | 
				
			||||||
 | 
					            ['name'=>'git-square','code'=>'f1d2'],
 | 
				
			||||||
 | 
					            ['name'=>'git','code'=>'f1d3'],
 | 
				
			||||||
 | 
					            ['name'=>'hacker-news','code'=>'f1d4'],
 | 
				
			||||||
 | 
					            ['name'=>'tencent-weibo','code'=>'f1d5'],
 | 
				
			||||||
 | 
					            ['name'=>'qq','code'=>'f1d6'],
 | 
				
			||||||
 | 
					            ['name'=>'weixin','code'=>'f1d7'],
 | 
				
			||||||
 | 
					            ['name'=>'paper-plane','code'=>'f1d8'],
 | 
				
			||||||
 | 
					            ['name'=>'paper-plane-o','code'=>'f1d9'],
 | 
				
			||||||
 | 
					            ['name'=>'history','code'=>'f1da'],
 | 
				
			||||||
 | 
					            ['name'=>'circle-thin','code'=>'f1db'],
 | 
				
			||||||
 | 
					            ['name'=>'header','code'=>'f1dc'],
 | 
				
			||||||
 | 
					            ['name'=>'paragraph','code'=>'f1dd'],
 | 
				
			||||||
 | 
					            ['name'=>'sliders','code'=>'f1de'],
 | 
				
			||||||
 | 
					            ['name'=>'share-alt','code'=>'f1e0'],
 | 
				
			||||||
 | 
					            ['name'=>'share-alt-square','code'=>'f1e1'],
 | 
				
			||||||
 | 
					            ['name'=>'bomb','code'=>'f1e2'],
 | 
				
			||||||
 | 
					            ['name'=>'futbol-o','code'=>'f1e3'],
 | 
				
			||||||
 | 
					            ['name'=>'tty','code'=>'f1e4'],
 | 
				
			||||||
 | 
					            ['name'=>'binoculars','code'=>'f1e5'],
 | 
				
			||||||
 | 
					            ['name'=>'plug','code'=>'f1e6'],
 | 
				
			||||||
 | 
					            ['name'=>'slideshare','code'=>'f1e7'],
 | 
				
			||||||
 | 
					            ['name'=>'twitch','code'=>'f1e8'],
 | 
				
			||||||
 | 
					            ['name'=>'yelp','code'=>'f1e9'],
 | 
				
			||||||
 | 
					            ['name'=>'newspaper-o','code'=>'f1ea'],
 | 
				
			||||||
 | 
					            ['name'=>'wifi','code'=>'f1eb'],
 | 
				
			||||||
 | 
					            ['name'=>'calculator','code'=>'f1ec'],
 | 
				
			||||||
 | 
					            ['name'=>'paypal','code'=>'f1ed'],
 | 
				
			||||||
 | 
					            ['name'=>'google-wallet','code'=>'f1ee'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-visa','code'=>'f1f0'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-mastercard','code'=>'f1f1'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-discover','code'=>'f1f2'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-amex','code'=>'f1f3'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-paypal','code'=>'f1f4'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-stripe','code'=>'f1f5'],
 | 
				
			||||||
 | 
					            ['name'=>'bell-slash','code'=>'f1f6'],
 | 
				
			||||||
 | 
					            ['name'=>'bell-slash-o','code'=>'f1f7'],
 | 
				
			||||||
 | 
					            ['name'=>'trash','code'=>'f1f8'],
 | 
				
			||||||
 | 
					            ['name'=>'copyright','code'=>'f1f9'],
 | 
				
			||||||
 | 
					            ['name'=>'at','code'=>'f1fa'],
 | 
				
			||||||
 | 
					            ['name'=>'eyedropper','code'=>'f1fb'],
 | 
				
			||||||
 | 
					            ['name'=>'paint-brush','code'=>'f1fc'],
 | 
				
			||||||
 | 
					            ['name'=>'birthday-cake','code'=>'f1fd'],
 | 
				
			||||||
 | 
					            ['name'=>'area-chart','code'=>'f1fe'],
 | 
				
			||||||
 | 
					            ['name'=>'pie-chart','code'=>'f200'],
 | 
				
			||||||
 | 
					            ['name'=>'line-chart','code'=>'f201'],
 | 
				
			||||||
 | 
					            ['name'=>'lastfm','code'=>'f202'],
 | 
				
			||||||
 | 
					            ['name'=>'lastfm-square','code'=>'f203'],
 | 
				
			||||||
 | 
					            ['name'=>'toggle-off','code'=>'f204'],
 | 
				
			||||||
 | 
					            ['name'=>'toggle-on','code'=>'f205'],
 | 
				
			||||||
 | 
					            ['name'=>'bicycle','code'=>'f206'],
 | 
				
			||||||
 | 
					            ['name'=>'bus','code'=>'f207'],
 | 
				
			||||||
 | 
					            ['name'=>'ioxhost','code'=>'f208'],
 | 
				
			||||||
 | 
					            ['name'=>'angellist','code'=>'f209'],
 | 
				
			||||||
 | 
					            ['name'=>'cc','code'=>'f20a'],
 | 
				
			||||||
 | 
					            ['name'=>'ils','code'=>'f20b'],
 | 
				
			||||||
 | 
					            ['name'=>'meanpath','code'=>'f20c'],
 | 
				
			||||||
 | 
					            ['name'=>'buysellads','code'=>'f20d'],
 | 
				
			||||||
 | 
					            ['name'=>'connectdevelop','code'=>'f20e'],
 | 
				
			||||||
 | 
					            ['name'=>'dashcube','code'=>'f210'],
 | 
				
			||||||
 | 
					            ['name'=>'forumbee','code'=>'f211'],
 | 
				
			||||||
 | 
					            ['name'=>'leanpub','code'=>'f212'],
 | 
				
			||||||
 | 
					            ['name'=>'sellsy','code'=>'f213'],
 | 
				
			||||||
 | 
					            ['name'=>'shirtsinbulk','code'=>'f214'],
 | 
				
			||||||
 | 
					            ['name'=>'simplybuilt','code'=>'f215'],
 | 
				
			||||||
 | 
					            ['name'=>'skyatlas','code'=>'f216'],
 | 
				
			||||||
 | 
					            ['name'=>'cart-plus','code'=>'f217'],
 | 
				
			||||||
 | 
					            ['name'=>'cart-arrow-down','code'=>'f218'],
 | 
				
			||||||
 | 
					            ['name'=>'diamond','code'=>'f219'],
 | 
				
			||||||
 | 
					            ['name'=>'ship','code'=>'f21a'],
 | 
				
			||||||
 | 
					            ['name'=>'user-secret','code'=>'f21b'],
 | 
				
			||||||
 | 
					            ['name'=>'motorcycle','code'=>'f21c'],
 | 
				
			||||||
 | 
					            ['name'=>'street-view','code'=>'f21d'],
 | 
				
			||||||
 | 
					            ['name'=>'heartbeat','code'=>'f21e'],
 | 
				
			||||||
 | 
					            ['name'=>'venus','code'=>'f221'],
 | 
				
			||||||
 | 
					            ['name'=>'mars','code'=>'f222'],
 | 
				
			||||||
 | 
					            ['name'=>'mercury','code'=>'f223'],
 | 
				
			||||||
 | 
					            ['name'=>'transgender','code'=>'f224'],
 | 
				
			||||||
 | 
					            ['name'=>'transgender-alt','code'=>'f225'],
 | 
				
			||||||
 | 
					            ['name'=>'venus-double','code'=>'f226'],
 | 
				
			||||||
 | 
					            ['name'=>'mars-double','code'=>'f227'],
 | 
				
			||||||
 | 
					            ['name'=>'venus-mars','code'=>'f228'],
 | 
				
			||||||
 | 
					            ['name'=>'mars-stroke','code'=>'f229'],
 | 
				
			||||||
 | 
					            ['name'=>'mars-stroke-v','code'=>'f22a'],
 | 
				
			||||||
 | 
					            ['name'=>'mars-stroke-h','code'=>'f22b'],
 | 
				
			||||||
 | 
					            ['name'=>'neuter','code'=>'f22c'],
 | 
				
			||||||
 | 
					            ['name'=>'genderless','code'=>'f22d'],
 | 
				
			||||||
 | 
					            ['name'=>'facebook-official','code'=>'f230'],
 | 
				
			||||||
 | 
					            ['name'=>'pinterest-p','code'=>'f231'],
 | 
				
			||||||
 | 
					            ['name'=>'whatsapp','code'=>'f232'],
 | 
				
			||||||
 | 
					            ['name'=>'server','code'=>'f233'],
 | 
				
			||||||
 | 
					            ['name'=>'user-plus','code'=>'f234'],
 | 
				
			||||||
 | 
					            ['name'=>'user-times','code'=>'f235'],
 | 
				
			||||||
 | 
					            ['name'=>'bed','code'=>'f236'],
 | 
				
			||||||
 | 
					            ['name'=>'viacoin','code'=>'f237'],
 | 
				
			||||||
 | 
					            ['name'=>'train','code'=>'f238'],
 | 
				
			||||||
 | 
					            ['name'=>'subway','code'=>'f239'],
 | 
				
			||||||
 | 
					            ['name'=>'medium','code'=>'f23a'],
 | 
				
			||||||
 | 
					            ['name'=>'y-combinator','code'=>'f23b'],
 | 
				
			||||||
 | 
					            ['name'=>'optin-monster','code'=>'f23c'],
 | 
				
			||||||
 | 
					            ['name'=>'opencart','code'=>'f23d'],
 | 
				
			||||||
 | 
					            ['name'=>'expeditedssl','code'=>'f23e'],
 | 
				
			||||||
 | 
					            ['name'=>'battery-full','code'=>'f240'],
 | 
				
			||||||
 | 
					            ['name'=>'battery-three-quarters','code'=>'f241'],
 | 
				
			||||||
 | 
					            ['name'=>'battery-half','code'=>'f242'],
 | 
				
			||||||
 | 
					            ['name'=>'battery-quarter','code'=>'f243'],
 | 
				
			||||||
 | 
					            ['name'=>'battery-empty','code'=>'f244'],
 | 
				
			||||||
 | 
					            ['name'=>'mouse-pointer','code'=>'f245'],
 | 
				
			||||||
 | 
					            ['name'=>'i-cursor','code'=>'f246'],
 | 
				
			||||||
 | 
					            ['name'=>'object-group','code'=>'f247'],
 | 
				
			||||||
 | 
					            ['name'=>'object-ungroup','code'=>'f248'],
 | 
				
			||||||
 | 
					            ['name'=>'sticky-note','code'=>'f249'],
 | 
				
			||||||
 | 
					            ['name'=>'sticky-note-o','code'=>'f24a'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-jcb','code'=>'f24b'],
 | 
				
			||||||
 | 
					            ['name'=>'cc-diners-club','code'=>'f24c'],
 | 
				
			||||||
 | 
					            ['name'=>'clone','code'=>'f24d'],
 | 
				
			||||||
 | 
					            ['name'=>'balance-scale','code'=>'f24e'],
 | 
				
			||||||
 | 
					            ['name'=>'hourglass-o','code'=>'f250'],
 | 
				
			||||||
 | 
					            ['name'=>'hourglass-start','code'=>'f251'],
 | 
				
			||||||
 | 
					            ['name'=>'hourglass-half','code'=>'f252'],
 | 
				
			||||||
 | 
					            ['name'=>'hourglass-end','code'=>'f253'],
 | 
				
			||||||
 | 
					            ['name'=>'hourglass','code'=>'f254'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-rock-o','code'=>'f255'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-paper-o','code'=>'f256'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-scissors-o','code'=>'f257'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-lizard-o','code'=>'f258'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-spock-o','code'=>'f259'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-pointer-o','code'=>'f25a'],
 | 
				
			||||||
 | 
					            ['name'=>'hand-peace-o','code'=>'f25b'],
 | 
				
			||||||
 | 
					            ['name'=>'trademark','code'=>'f25c'],
 | 
				
			||||||
 | 
					            ['name'=>'registered','code'=>'f25d'],
 | 
				
			||||||
 | 
					            ['name'=>'creative-commons','code'=>'f25e'],
 | 
				
			||||||
 | 
					            ['name'=>'gg','code'=>'f260'],
 | 
				
			||||||
 | 
					            ['name'=>'gg-circle','code'=>'f261'],
 | 
				
			||||||
 | 
					            ['name'=>'tripadvisor','code'=>'f262'],
 | 
				
			||||||
 | 
					            ['name'=>'odnoklassniki','code'=>'f263'],
 | 
				
			||||||
 | 
					            ['name'=>'odnoklassniki-square','code'=>'f264'],
 | 
				
			||||||
 | 
					            ['name'=>'get-pocket','code'=>'f265'],
 | 
				
			||||||
 | 
					            ['name'=>'wikipedia-w','code'=>'f266'],
 | 
				
			||||||
 | 
					            ['name'=>'safari','code'=>'f267'],
 | 
				
			||||||
 | 
					            ['name'=>'chrome','code'=>'f268'],
 | 
				
			||||||
 | 
					            ['name'=>'firefox','code'=>'f269'],
 | 
				
			||||||
 | 
					            ['name'=>'opera','code'=>'f26a'],
 | 
				
			||||||
 | 
					            ['name'=>'internet-explorer','code'=>'f26b'],
 | 
				
			||||||
 | 
					            ['name'=>'television','code'=>'f26c'],
 | 
				
			||||||
 | 
					            ['name'=>'contao','code'=>'f26d'],
 | 
				
			||||||
 | 
					            ['name'=>'500px','code'=>'f26e'],
 | 
				
			||||||
 | 
					            ['name'=>'amazon','code'=>'f270'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar-plus-o','code'=>'f271'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar-minus-o','code'=>'f272'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar-times-o','code'=>'f273'],
 | 
				
			||||||
 | 
					            ['name'=>'calendar-check-o','code'=>'f274'],
 | 
				
			||||||
 | 
					            ['name'=>'industry','code'=>'f275'],
 | 
				
			||||||
 | 
					            ['name'=>'map-pin','code'=>'f276'],
 | 
				
			||||||
 | 
					            ['name'=>'map-signs','code'=>'f277'],
 | 
				
			||||||
 | 
					            ['name'=>'map-o','code'=>'f278'],
 | 
				
			||||||
 | 
					            ['name'=>'map','code'=>'f279'],
 | 
				
			||||||
 | 
					            ['name'=>'commenting','code'=>'f27a'],
 | 
				
			||||||
 | 
					            ['name'=>'commenting-o','code'=>'f27b'],
 | 
				
			||||||
 | 
					            ['name'=>'houzz','code'=>'f27c'],
 | 
				
			||||||
 | 
					            ['name'=>'vimeo','code'=>'f27d'],
 | 
				
			||||||
 | 
					            ['name'=>'black-tie','code'=>'f27e'],
 | 
				
			||||||
 | 
					            ['name'=>'fonticons','code'=>'f280'],
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($icons as $icon) {
 | 
				
			||||||
 | 
					            $data[$icon['name']] = '&#x' . $icon['code'] . ' ' . ucwords(str_replace('-', ' ', $icon['name']));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ksort($data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										173
									
								
								app/Http/Controllers/ProposalTemplateController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								app/Http/Controllers/ProposalTemplateController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,173 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Http\Requests\CreateProposalTemplateRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\ProposalTemplateRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\UpdateProposalTemplateRequest;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\ProposalTemplate;
 | 
				
			||||||
 | 
					use App\Ninja\Datatables\ProposalTemplateDatatable;
 | 
				
			||||||
 | 
					use App\Ninja\Repositories\ProposalTemplateRepository;
 | 
				
			||||||
 | 
					use App\Services\ProposalTemplateService;
 | 
				
			||||||
 | 
					use Auth;
 | 
				
			||||||
 | 
					use Input;
 | 
				
			||||||
 | 
					use Session;
 | 
				
			||||||
 | 
					use View;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalTemplateController extends BaseController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $proposalTemplateRepo;
 | 
				
			||||||
 | 
					    protected $proposalTemplateService;
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_TEMPLATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ProposalTemplateRepository $proposalTemplateRepo, ProposalTemplateService $proposalTemplateService)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->proposalTemplateRepo = $proposalTemplateRepo;
 | 
				
			||||||
 | 
					        $this->proposalTemplateService = $proposalTemplateService;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Display a listing of the resource.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Response
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function index()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return View::make('list_wrapper', [
 | 
				
			||||||
 | 
					            'entityType' => ENTITY_PROPOSAL_TEMPLATE,
 | 
				
			||||||
 | 
					            'datatable' => new ProposalTemplateDatatable(),
 | 
				
			||||||
 | 
					            'title' => trans('texts.proposal_templates'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDatatable($expensePublicId = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $search = Input::get('sSearch');
 | 
				
			||||||
 | 
					        $userId = Auth::user()->filterId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->proposalTemplateService->getDatatable($search, $userId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function create(ProposalTemplateRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $data = array_merge($this->getViewmodel(), [
 | 
				
			||||||
 | 
					            'template' => null,
 | 
				
			||||||
 | 
					            'method' => 'POST',
 | 
				
			||||||
 | 
					            'url' => 'proposals/templates',
 | 
				
			||||||
 | 
					            'title' => trans('texts.new_proposal_template'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/templates/edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getViewmodel()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $customTemplates = ProposalTemplate::scope()->orderBy('name')->get();
 | 
				
			||||||
 | 
					        $defaultTemplates = ProposalTemplate::whereNull('account_id')->orderBy('public_id')->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $options = [];
 | 
				
			||||||
 | 
					        $customLabel = trans('texts.custom');
 | 
				
			||||||
 | 
					        $defaultLabel = trans('texts.default');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($customTemplates as $template) {
 | 
				
			||||||
 | 
					            if (! isset($options[$customLabel])) {
 | 
				
			||||||
 | 
					                $options[$customLabel] = [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $options[trans('texts.custom')][$template->public_id] = $template->name;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        foreach ($defaultTemplates as $template) {
 | 
				
			||||||
 | 
					            if (! isset($options[$defaultLabel])) {
 | 
				
			||||||
 | 
					                $options[$defaultLabel] = [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $options[trans('texts.default')][$template->public_id] = $template->name;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [
 | 
				
			||||||
 | 
					            'account' => auth()->user()->account,
 | 
				
			||||||
 | 
					            'customTemplates' => $customTemplates,
 | 
				
			||||||
 | 
					            'defaultTemplates' => $defaultTemplates,
 | 
				
			||||||
 | 
					            'templateOptions' => $options,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function show($publicId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Session::reflash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect("proposals/templates/$publicId/edit");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function edit(ProposalTemplateRequest $request, $publicId = false, $clone = false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $template = $request->entity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($clone) {
 | 
				
			||||||
 | 
					            $template->id = null;
 | 
				
			||||||
 | 
					            $template->public_id = null;
 | 
				
			||||||
 | 
					            $template->name = '';
 | 
				
			||||||
 | 
					            $template->private_notes = '';
 | 
				
			||||||
 | 
					            $method = 'POST';
 | 
				
			||||||
 | 
					            $url = 'proposals/templates';
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $method = 'PUT';
 | 
				
			||||||
 | 
					            $url = 'proposals/templates/' . $template->public_id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = array_merge($this->getViewmodel(), [
 | 
				
			||||||
 | 
					            'template' => $template,
 | 
				
			||||||
 | 
					            'entity' => $clone ? false : $template,
 | 
				
			||||||
 | 
					            'method' => $method,
 | 
				
			||||||
 | 
					            'url' => $url,
 | 
				
			||||||
 | 
					            'title' => trans('texts.edit_proposal_template'),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return View::make('proposals/templates/edit', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function cloneProposal(ProposalTemplateRequest $request, $publicId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return self::edit($request, $publicId, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function store(CreateProposalTemplateRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalTemplate = $this->proposalTemplateService->save($request->input());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.created_proposal_template'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalTemplate->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function update(UpdateProposalTemplateRequest $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $proposalTemplate = $this->proposalTemplateService->save($request->input(), $request->entity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Session::flash('message', trans('texts.updated_proposal_template'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        if (in_array($action, ['archive', 'delete', 'restore'])) {
 | 
				
			||||||
 | 
					            return self::bulk();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to($proposalTemplate->getRoute());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function bulk()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $action = Input::get('action');
 | 
				
			||||||
 | 
					        $ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $count = $this->proposalTemplateService->bulk($ids, $action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($count > 0) {
 | 
				
			||||||
 | 
					            $field = $count == 1 ? "{$action}d_proposal_template" : "{$action}d_proposal_templates";
 | 
				
			||||||
 | 
					            $message = trans("texts.$field", ['count' => $count]);
 | 
				
			||||||
 | 
					            Session::flash('message', $message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->to('/proposals/templates');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -97,7 +97,7 @@ class QuoteController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
          'entityType' => ENTITY_QUOTE,
 | 
					          'entityType' => ENTITY_QUOTE,
 | 
				
			||||||
          'account' => $account,
 | 
					          'account' => Auth::user()->account->load('country'),
 | 
				
			||||||
          'products' => Product::scope()->orderBy('product_key')->get(),
 | 
					          'products' => Product::scope()->orderBy('product_key')->get(),
 | 
				
			||||||
          'taxRateOptions' => $account->present()->taxRateOptions,
 | 
					          'taxRateOptions' => $account->present()->taxRateOptions,
 | 
				
			||||||
          'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
 | 
					          'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
 | 
				
			||||||
@ -148,6 +148,11 @@ class QuoteController extends BaseController
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $invitation = Invitation::with('invoice.invoice_items', 'invoice.invitations')->where('invitation_key', '=', $invitationKey)->firstOrFail();
 | 
					        $invitation = Invitation::with('invoice.invoice_items', 'invoice.invitations')->where('invitation_key', '=', $invitationKey)->firstOrFail();
 | 
				
			||||||
        $invoice = $invitation->invoice;
 | 
					        $invoice = $invitation->invoice;
 | 
				
			||||||
 | 
					        $account = $invoice->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($account->requiresAuthorization($invoice) && ! session('authorized:' . $invitation->invitation_key)) {
 | 
				
			||||||
 | 
					            return redirect()->to('view/' . $invitation->invitation_key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($invoice->due_date) {
 | 
					        if ($invoice->due_date) {
 | 
				
			||||||
            $carbonDueDate = \Carbon::parse($invoice->due_date);
 | 
					            $carbonDueDate = \Carbon::parse($invoice->due_date);
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,7 @@ class ReportController extends BaseController
 | 
				
			|||||||
            'activity',
 | 
					            'activity',
 | 
				
			||||||
            'aging',
 | 
					            'aging',
 | 
				
			||||||
            'client',
 | 
					            'client',
 | 
				
			||||||
 | 
					            'credit',
 | 
				
			||||||
            'document',
 | 
					            'document',
 | 
				
			||||||
            'expense',
 | 
					            'expense',
 | 
				
			||||||
            'invoice',
 | 
					            'invoice',
 | 
				
			||||||
 | 
				
			|||||||
@ -134,6 +134,7 @@ class SubscriptionController extends BaseController
 | 
				
			|||||||
                $subscription = Subscription::scope($subscriptionPublicId)->firstOrFail();
 | 
					                $subscription = Subscription::scope($subscriptionPublicId)->firstOrFail();
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $subscription = Subscription::createNew();
 | 
					                $subscription = Subscription::createNew();
 | 
				
			||||||
 | 
					                $subscriptionPublicId = $subscription->public_id;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $validator = Validator::make(Input::all(), $rules);
 | 
					            $validator = Validator::make(Input::all(), $rules);
 | 
				
			||||||
@ -154,6 +155,14 @@ class SubscriptionController extends BaseController
 | 
				
			|||||||
            Session::flash('message', $message);
 | 
					            Session::flash('message', $message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
 | 
					        return redirect('/settings/api_tokens');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					        if ($subscriptionPublicId) {
 | 
				
			||||||
 | 
					            return Redirect::to('subscriptions/' . $subscriptionPublicId . '/edit');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return redirect('/settings/api_tokens');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -55,8 +55,16 @@ class TaskKanbanController extends BaseController
 | 
				
			|||||||
                $task->task_status_sort_order = $i++;
 | 
					                $task->task_status_sort_order = $i++;
 | 
				
			||||||
                $task->save();
 | 
					                $task->save();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        // otherwise, check that the tasks orders are correct
 | 
					        // otherwise, check that the orders are correct
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					            for ($i=0; $i<$statuses->count(); $i++) {
 | 
				
			||||||
 | 
					                $status = $statuses[$i];
 | 
				
			||||||
 | 
					                if ($status->sort_order != $i) {
 | 
				
			||||||
 | 
					                    $status->sort_order = $i;
 | 
				
			||||||
 | 
					                    $status->save();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $firstStatus = $statuses[0];
 | 
					            $firstStatus = $statuses[0];
 | 
				
			||||||
            $counts = [];
 | 
					            $counts = [];
 | 
				
			||||||
            foreach ($tasks as $task) {
 | 
					            foreach ($tasks as $task) {
 | 
				
			||||||
 | 
				
			|||||||
@ -118,7 +118,7 @@ class UserController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! Auth::user()->confirmed) {
 | 
					        if (! Auth::user()->confirmed) {
 | 
				
			||||||
            Session::flash('error', trans('texts.confirmation_required'));
 | 
					            Session::flash('error', trans('texts.confirmation_required', ['link' => link_to('/resend_confirmation', trans('texts.click_here'))]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
 | 
					            return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -100,8 +100,8 @@ class ApiCheck
 | 
				
			|||||||
                return Response::json("Please wait {$wait} second(s)", 403, $headers);
 | 
					                return Response::json("Please wait {$wait} second(s)", 403, $headers);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Cache::put("hour_throttle:{$key}", $new_hour_throttle, 10);
 | 
					            Cache::put("hour_throttle:{$key}", $new_hour_throttle, 60);
 | 
				
			||||||
            Cache::put("last_api_request:{$key}", time(), 10);
 | 
					            Cache::put("last_api_request:{$key}", time(), 60);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $next($request);
 | 
					        return $next($request);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ namespace App\Http\Middleware;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Models\Contact;
 | 
					use App\Models\Contact;
 | 
				
			||||||
use App\Models\Invitation;
 | 
					use App\Models\Invitation;
 | 
				
			||||||
 | 
					use App\Models\ProposalInvitation;
 | 
				
			||||||
use Auth;
 | 
					use Auth;
 | 
				
			||||||
use Closure;
 | 
					use Closure;
 | 
				
			||||||
use Session;
 | 
					use Session;
 | 
				
			||||||
@ -25,13 +26,14 @@ class Authenticate
 | 
				
			|||||||
    public function handle($request, Closure $next, $guard = 'user')
 | 
					    public function handle($request, Closure $next, $guard = 'user')
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $authenticated = Auth::guard($guard)->check();
 | 
					        $authenticated = Auth::guard($guard)->check();
 | 
				
			||||||
 | 
					        $invitationKey = $request->invitation_key ?: $request->proposal_invitation_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($guard == 'client') {
 | 
					        if ($guard == 'client') {
 | 
				
			||||||
            if (! empty($request->invitation_key)) {
 | 
					            if (! empty($request->invitation_key) || ! empty($request->proposal_invitation_key)) {
 | 
				
			||||||
                $contact_key = session('contact_key');
 | 
					                $contact_key = session('contact_key');
 | 
				
			||||||
                if ($contact_key) {
 | 
					                if ($contact_key) {
 | 
				
			||||||
                    $contact = $this->getContact($contact_key);
 | 
					                    $contact = $this->getContact($contact_key);
 | 
				
			||||||
                    $invitation = $this->getInvitation($request->invitation_key);
 | 
					                    $invitation = $this->getInvitation($invitationKey, ! empty($request->proposal_invitation_key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (! $invitation) {
 | 
					                    if (! $invitation) {
 | 
				
			||||||
                        return response()->view('error', [
 | 
					                        return response()->view('error', [
 | 
				
			||||||
@ -59,7 +61,7 @@ class Authenticate
 | 
				
			|||||||
            $contact = false;
 | 
					            $contact = false;
 | 
				
			||||||
            if ($contact_key) {
 | 
					            if ($contact_key) {
 | 
				
			||||||
                $contact = $this->getContact($contact_key);
 | 
					                $contact = $this->getContact($contact_key);
 | 
				
			||||||
            } elseif ($invitation = $this->getInvitation($request->invitation_key)) {
 | 
					            } elseif ($invitation = $this->getInvitation($invitationKey, ! empty($request->proposal_invitation_key))) {
 | 
				
			||||||
                $contact = $invitation->contact;
 | 
					                $contact = $invitation->contact;
 | 
				
			||||||
                Session::put('contact_key', $contact->contact_key);
 | 
					                Session::put('contact_key', $contact->contact_key);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -89,6 +91,7 @@ class Authenticate
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if ($authenticated) {
 | 
					            if ($authenticated) {
 | 
				
			||||||
                $request->merge(['contact' => $contact]);
 | 
					                $request->merge(['contact' => $contact]);
 | 
				
			||||||
 | 
					                $account->loadLocalizationSettings($contact->client);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -108,7 +111,7 @@ class Authenticate
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return \Illuminate\Database\Eloquent\Model|null|static
 | 
					     * @return \Illuminate\Database\Eloquent\Model|null|static
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getInvitation($key)
 | 
					    protected function getInvitation($key, $isProposal = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $key) {
 | 
					        if (! $key) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@ -118,7 +121,12 @@ class Authenticate
 | 
				
			|||||||
        list($key) = explode('&', $key);
 | 
					        list($key) = explode('&', $key);
 | 
				
			||||||
        $key = substr($key, 0, RANDOM_KEY_LENGTH);
 | 
					        $key = substr($key, 0, RANDOM_KEY_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invitation = Invitation::withTrashed()->where('invitation_key', '=', $key)->first();
 | 
					        if ($isProposal) {
 | 
				
			||||||
 | 
					            $invitation = ProposalInvitation::withTrashed()->where('invitation_key', '=', $key)->first();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $invitation = Invitation::withTrashed()->where('invitation_key', '=', $key)->first();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($invitation && ! $invitation->is_deleted) {
 | 
					        if ($invitation && ! $invitation->is_deleted) {
 | 
				
			||||||
            return $invitation;
 | 
					            return $invitation;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ use Closure;
 | 
				
			|||||||
use App\Models\LookupAccount;
 | 
					use App\Models\LookupAccount;
 | 
				
			||||||
use App\Models\LookupContact;
 | 
					use App\Models\LookupContact;
 | 
				
			||||||
use App\Models\LookupInvitation;
 | 
					use App\Models\LookupInvitation;
 | 
				
			||||||
 | 
					use App\Models\LookupProposalInvitation;
 | 
				
			||||||
use App\Models\LookupAccountToken;
 | 
					use App\Models\LookupAccountToken;
 | 
				
			||||||
use App\Models\LookupUser;
 | 
					use App\Models\LookupUser;
 | 
				
			||||||
use Auth;
 | 
					use Auth;
 | 
				
			||||||
@ -43,6 +44,8 @@ class DatabaseLookup
 | 
				
			|||||||
        } elseif ($guard == 'contact') {
 | 
					        } elseif ($guard == 'contact') {
 | 
				
			||||||
            if ($key = request()->invitation_key) {
 | 
					            if ($key = request()->invitation_key) {
 | 
				
			||||||
                LookupInvitation::setServerByField('invitation_key', $key);
 | 
					                LookupInvitation::setServerByField('invitation_key', $key);
 | 
				
			||||||
 | 
					            } elseif ($key = request()->proposal_invitation_key) {
 | 
				
			||||||
 | 
					                LookupProposalInvitation::setServerByField('invitation_key', $key);
 | 
				
			||||||
            } elseif ($key = request()->contact_key ?: session('contact_key')) {
 | 
					            } elseif ($key = request()->contact_key ?: session('contact_key')) {
 | 
				
			||||||
                LookupContact::setServerByField('contact_key', $key);
 | 
					                LookupContact::setServerByField('contact_key', $key);
 | 
				
			||||||
            } elseif ($key = request()->account_key) {
 | 
					            } elseif ($key = request()->account_key) {
 | 
				
			||||||
 | 
				
			|||||||
@ -36,8 +36,13 @@ class StartupCheck
 | 
				
			|||||||
        // Set up trusted X-Forwarded-Proto proxies
 | 
					        // Set up trusted X-Forwarded-Proto proxies
 | 
				
			||||||
        // TRUSTED_PROXIES accepts a comma delimited list of subnets
 | 
					        // TRUSTED_PROXIES accepts a comma delimited list of subnets
 | 
				
			||||||
        // ie, TRUSTED_PROXIES='10.0.0.0/8,172.16.0.0/12,192.168.0.0/16'
 | 
					        // ie, TRUSTED_PROXIES='10.0.0.0/8,172.16.0.0/12,192.168.0.0/16'
 | 
				
			||||||
 | 
					        // set TRUSTED_PROXIES=* if you want to trust every proxy.
 | 
				
			||||||
        if (isset($_ENV['TRUSTED_PROXIES'])) {
 | 
					        if (isset($_ENV['TRUSTED_PROXIES'])) {
 | 
				
			||||||
            $request->setTrustedProxies(array_map('trim', explode(',', env('TRUSTED_PROXIES'))));
 | 
					            if (env('TRUSTED_PROXIES') == '*') {
 | 
				
			||||||
 | 
					                $request->setTrustedProxies(['127.0.0.1', $request->server->get('REMOTE_ADDR')]);
 | 
				
			||||||
 | 
					            } else{
 | 
				
			||||||
 | 
					                $request->setTrustedProxies(array_map('trim', explode(',', env('TRUSTED_PROXIES'))));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Ensure all request are over HTTPS in production
 | 
					        // Ensure all request are over HTTPS in production
 | 
				
			||||||
@ -218,7 +223,7 @@ class StartupCheck
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Show message to IE 8 and before users
 | 
					        // Show message to IE 8 and before users
 | 
				
			||||||
        if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
 | 
					        if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
 | 
				
			||||||
            Session::flash('error', trans('texts.old_browser', ['link' => OUTDATE_BROWSER_URL]));
 | 
					            Session::flash('error', trans('texts.old_browser', ['link' => link_to(OUTDATE_BROWSER_URL, trans('texts.newer_browser'), ['target' => '_blank'])]));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $response = $next($request);
 | 
					        $response = $next($request);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										36
									
								
								app/Http/Requests/CreatePaymentTermAPIRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Http/Requests/CreatePaymentTermAPIRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreatePaymentTermAPIRequest extends Request
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user()->can('create', ENTITY_PAYMENT_TERM);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $rules = [
 | 
				
			||||||
 | 
					            'num_days' => 'required|numeric|unique:payment_terms',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $rules;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								app/Http/Requests/CreateProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Http/Requests/CreateProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateProposalCategoryRequest extends ProposalCategoryRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user()->can('create', ENTITY_PROPOSAL_CATEGORY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_categories,name,,id,account_id,%s', $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								app/Http/Requests/CreateProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Http/Requests/CreateProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateProposalRequest extends ProposalRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user()->can('create', ENTITY_PROPOSAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'invoice_id' => 'required',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								app/Http/Requests/CreateProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Http/Requests/CreateProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateProposalSnippetRequest extends ProposalSnippetRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user()->can('create', ENTITY_PROPOSAL_SNIPPET);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_snippets,name,,id,account_id,%s', $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								app/Http/Requests/CreateProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Http/Requests/CreateProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateProposalTemplateRequest extends ProposalTemplateRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user()->can('create', ENTITY_PROPOSAL_TEMPLATE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_templates,name,,id,account_id,%s', $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -35,6 +35,7 @@ class EntityRequest extends Request
 | 
				
			|||||||
        if (! $publicId) {
 | 
					        if (! $publicId) {
 | 
				
			||||||
            $publicId = Input::get('public_id') ?: Input::get('id');
 | 
					            $publicId = Input::get('public_id') ?: Input::get('id');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $publicId) {
 | 
					        if (! $publicId) {
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								app/Http/Requests/PaymentTermRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/Http/Requests/PaymentTermRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PaymentTermRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PAYMENT_TERM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								app/Http/Requests/ProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/Http/Requests/ProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalCategoryRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_CATEGORY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								app/Http/Requests/ProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/Http/Requests/ProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								app/Http/Requests/ProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Http/Requests/ProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\ProposalCategory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalSnippetRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_SNIPPET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sanitize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $input = $this->all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // check if we're creating a new proposal category
 | 
				
			||||||
 | 
					        if ($this->proposal_category_id == '-1') {
 | 
				
			||||||
 | 
					            $data = [
 | 
				
			||||||
 | 
					                'name' => trim($this->proposal_category_name)
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					            if (ProposalCategory::validate($data) === true) {
 | 
				
			||||||
 | 
					                $category = app('App\Ninja\Repositories\ProposalCategoryRepository')->save($data);
 | 
				
			||||||
 | 
					                $input['proposal_category_id'] = $category->id;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $input['proposal_category_id'] = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } elseif ($this->proposal_category_id) {
 | 
				
			||||||
 | 
					            $input['proposal_category_id'] = ProposalCategory::getPrivateId($this->proposal_category_id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->replace($input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->all();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								app/Http/Requests/ProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/Http/Requests/ProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProposalTemplateRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $entityType = ENTITY_PROPOSAL_TEMPLATE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -34,7 +34,7 @@ class UpdateInvoiceAPIRequest extends InvoiceRequest
 | 
				
			|||||||
        $invoiceId = $this->entity()->id;
 | 
					        $invoiceId = $this->entity()->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules = [
 | 
					        $rules = [
 | 
				
			||||||
            'invoice_items' => 'valid_invoice_items',
 | 
					            'invoice_items' => 'required|valid_invoice_items',
 | 
				
			||||||
            'invoice_number' => 'unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
 | 
					            'invoice_number' => 'unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
 | 
				
			||||||
            'discount' => 'positive',
 | 
					            'discount' => 'positive',
 | 
				
			||||||
            //'invoice_date' => 'date',
 | 
					            //'invoice_date' => 'date',
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ class UpdateInvoiceRequest extends InvoiceRequest
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $rules = [
 | 
					        $rules = [
 | 
				
			||||||
            'client' => 'required',
 | 
					            'client' => 'required',
 | 
				
			||||||
            'invoice_items' => 'valid_invoice_items',
 | 
					            'invoice_items' => 'required|valid_invoice_items',
 | 
				
			||||||
            'invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
 | 
					            'invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
 | 
				
			||||||
            'discount' => 'positive',
 | 
					            'discount' => 'positive',
 | 
				
			||||||
            'invoice_date' => 'required',
 | 
					            'invoice_date' => 'required',
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								app/Http/Requests/UpdatePaymentTermRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/Http/Requests/UpdatePaymentTermRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdatePaymentTermRequest extends EntityRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								app/Http/Requests/UpdateProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Http/Requests/UpdateProposalCategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateProposalCategoryRequest extends ProposalCategoryRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->entity() && $this->user()->can('edit', $this->entity());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->entity()) {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_categories,name,,id,account_id,%s', $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								app/Http/Requests/UpdateProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Http/Requests/UpdateProposalRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateProposalRequest extends ProposalRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->entity() && $this->user()->can('edit', $this->entity());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->entity()) {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'invoice_id' => 'required',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								app/Http/Requests/UpdateProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Http/Requests/UpdateProposalSnippetRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateProposalSnippetRequest extends ProposalSnippetRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->entity() && $this->user()->can('edit', $this->entity());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->entity()) {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_snippets,name,%s,id,account_id,%s', $this->entity()->id, $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								app/Http/Requests/UpdateProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Http/Requests/UpdateProposalTemplateRequest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateProposalTemplateRequest extends ProposalTemplateRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function authorize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->entity() && $this->user()->can('edit', $this->entity());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules that apply to the request.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->entity()) {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'name' => sprintf('required|unique:proposal_templates,name,%s,id,account_id,%s', $this->entity()->id, $this->user()->account_id),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								app/Http/ViewComposers/ProposalComposer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/Http/ViewComposers/ProposalComposer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\ViewComposers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\View\View;
 | 
				
			||||||
 | 
					use App\Models\ProposalSnippet;
 | 
				
			||||||
 | 
					use App\Models\Document;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ClientPortalHeaderComposer.php.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright See LICENSE file that was distributed with this source code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ProposalComposer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Bind data to the view.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param View $view
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function compose(View $view)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $snippets = ProposalSnippet::scope()
 | 
				
			||||||
 | 
					            ->with('proposal_category')
 | 
				
			||||||
 | 
					            ->orderBy('name')
 | 
				
			||||||
 | 
					            ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $view->with('snippets', $snippets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $documents = Document::scope()
 | 
				
			||||||
 | 
					            ->whereNull('invoice_id')
 | 
				
			||||||
 | 
					            ->whereNull('expense_id')
 | 
				
			||||||
 | 
					            ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [];
 | 
				
			||||||
 | 
					        foreach ($documents as $document) {
 | 
				
			||||||
 | 
					            $data[] = [
 | 
				
			||||||
 | 
					                'src' => $document->getProposalUrl(),
 | 
				
			||||||
 | 
					                'public_id' => $document->public_id,
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $view->with('documents', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										157
									
								
								app/Jobs/ConvertInvoiceToUbl.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								app/Jobs/ConvertInvoiceToUbl.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Jobs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Jobs\Job;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Generator;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Invoice;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Party;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Address;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Country;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Contact;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\TaxTotal;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\TaxSubTotal;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\TaxCategory;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\TaxScheme;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\InvoiceLine;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\Item;
 | 
				
			||||||
 | 
					use CleverIt\UBL\Invoice\LegalMonetaryTotal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConvertInvoiceToUbl extends Job
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const INVOICE_TYPE_STANDARD = 380;
 | 
				
			||||||
 | 
					    const INVOICE_TYPE_CREDIT = 381;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct($invoice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->invoice = $invoice;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $invoice = $this->invoice;
 | 
				
			||||||
 | 
					        $account = $invoice->account;
 | 
				
			||||||
 | 
					        $client = $invoice->client;
 | 
				
			||||||
 | 
					        $ublInvoice = new Invoice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // invoice
 | 
				
			||||||
 | 
					        $ublInvoice->setId($invoice->invoice_number);
 | 
				
			||||||
 | 
					        $ublInvoice->setIssueDate(date_create($invoice->invoice_date));
 | 
				
			||||||
 | 
					        $ublInvoice->setInvoiceTypeCode($invoice->amount < 0 ? self::INVOICE_TYPE_CREDIT : self::INVOICE_TYPE_STANDARD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $supplierParty = $this->createParty($account, $invoice->user);
 | 
				
			||||||
 | 
					        $ublInvoice->setAccountingSupplierParty($supplierParty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $customerParty = $this->createParty($client, $client->contacts[0]);
 | 
				
			||||||
 | 
					        $ublInvoice->setAccountingCustomerParty($customerParty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // line items
 | 
				
			||||||
 | 
					        $invoiceLine = [];
 | 
				
			||||||
 | 
					        $taxable = $invoice->getTaxable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($invoice->invoice_items as $index => $item) {
 | 
				
			||||||
 | 
					            $itemTaxable = $invoice->getItemTaxable($item, $taxable);
 | 
				
			||||||
 | 
					            $item->setRelation('invoice', $invoice);
 | 
				
			||||||
 | 
					            $invoiceLines[] = $this->createInvoiceLine($index, $item, $itemTaxable);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ublInvoice->setInvoiceLines($invoiceLines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($invoice->hasTaxes()) {
 | 
				
			||||||
 | 
					            $taxtotal = new TaxTotal();
 | 
				
			||||||
 | 
					            $taxAmount1 = $taxAmount2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($invoice->tax_name1 || floatval($invoice->tax_rate1)) {
 | 
				
			||||||
 | 
					                $taxAmount1 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate1, $invoice->tax_name1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($invoice->tax_name2 || floatval($invoice->tax_rate2)) {
 | 
				
			||||||
 | 
					                $taxAmount2 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate2, $invoice->tax_name2);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $taxtotal->setTaxAmount($taxAmount1 + $taxAmount2);
 | 
				
			||||||
 | 
					            $ublInvoice->setTaxTotal($taxtotal);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ublInvoice->setLegalMonetaryTotal((new LegalMonetaryTotal())
 | 
				
			||||||
 | 
					            //->setLineExtensionAmount()
 | 
				
			||||||
 | 
					            ->setTaxExclusiveAmount($taxable)
 | 
				
			||||||
 | 
					            ->setPayableAmount($invoice->balance));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Generator::invoice($ublInvoice, $invoice->client->getCurrencyCode());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function createParty($company, $user)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $party = new Party();
 | 
				
			||||||
 | 
					        $party->setName($company->name);
 | 
				
			||||||
 | 
					        $address = (new Address())
 | 
				
			||||||
 | 
					            ->setCityName($company->city)
 | 
				
			||||||
 | 
					            ->setStreetName($company->address1)
 | 
				
			||||||
 | 
					            ->setBuildingNumber($company->address2)
 | 
				
			||||||
 | 
					            ->setPostalZone($company->postal_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($company->country_id) {
 | 
				
			||||||
 | 
					            $country = new Country();
 | 
				
			||||||
 | 
					            $country->setIdentificationCode($company->country->iso_3166_2);
 | 
				
			||||||
 | 
					            $address->setCountry($country);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $party->setPostalAddress($address);
 | 
				
			||||||
 | 
					        $party->setPhysicalLocation($address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $contact = new Contact();
 | 
				
			||||||
 | 
					        $contact->setElectronicMail($user->email);
 | 
				
			||||||
 | 
					        $party->setContact($contact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $party;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function createInvoiceLine($index, $item, $taxable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $invoiceLine = (new InvoiceLine())
 | 
				
			||||||
 | 
					            ->setId($index + 1)
 | 
				
			||||||
 | 
					            ->setInvoicedQuantity($item->qty)
 | 
				
			||||||
 | 
					            ->setLineExtensionAmount($item->costWithDiscount())
 | 
				
			||||||
 | 
					            ->setItem((new Item())
 | 
				
			||||||
 | 
					                ->setName($item->product_key)
 | 
				
			||||||
 | 
					                ->setDescription($item->description));
 | 
				
			||||||
 | 
					                //->setSellersItemIdentification("1ABCD"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($item->hasTaxes()) {
 | 
				
			||||||
 | 
					            $taxtotal = new TaxTotal();
 | 
				
			||||||
 | 
					            $itemTaxAmount1 = $itemTaxAmount2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($item->tax_name1 || floatval($item->tax_rate1)) {
 | 
				
			||||||
 | 
					                $itemTaxAmount1 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate1, $item->tax_name1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($item->tax_name2 || floatval($item->tax_rate2)) {
 | 
				
			||||||
 | 
					                $itemTaxAmount2 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate2, $item->tax_name2);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $taxtotal->setTaxAmount($itemTaxAmount1 + $itemTaxAmount2);
 | 
				
			||||||
 | 
					            $invoiceLine->setTaxTotal($taxtotal);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $invoiceLine;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function createTaxRate(&$taxtotal, $taxable, $taxRate, $taxName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $invoice = $this->invoice;
 | 
				
			||||||
 | 
					        $taxAmount = $invoice->taxAmount($taxable, $taxRate);
 | 
				
			||||||
 | 
					        $taxScheme = ((new TaxScheme()))->setId($taxName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $taxtotal->addTaxSubTotal((new TaxSubTotal())
 | 
				
			||||||
 | 
					                ->setTaxAmount($taxAmount)
 | 
				
			||||||
 | 
					                ->setTaxableAmount($taxable)
 | 
				
			||||||
 | 
					                ->setTaxCategory((new TaxCategory())
 | 
				
			||||||
 | 
					                    ->setId($taxName)
 | 
				
			||||||
 | 
					                    ->setName($taxName)
 | 
				
			||||||
 | 
					                    ->setTaxScheme($taxScheme)
 | 
				
			||||||
 | 
					                    ->setPercent($taxRate)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $taxAmount;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -46,6 +46,10 @@ class DownloadInvoices extends Job
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle(UserMailer $userMailer)
 | 
					    public function handle(UserMailer $userMailer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (! extension_loaded('GMP')) {
 | 
				
			||||||
 | 
					            die(trans('texts.gmp_required'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.invoice_pdfs')));
 | 
					        $zip = Archive::instance_by_useragent(date('Y-m-d') . '_' . str_replace(' ', '_', trans('texts.invoice_pdfs')));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($this->invoices as $invoice) {
 | 
					        foreach ($this->invoices as $invoice) {
 | 
				
			||||||
@ -54,34 +58,5 @@ class DownloadInvoices extends Job
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $zip->finish();
 | 
					        $zip->finish();
 | 
				
			||||||
        exit;
 | 
					        exit;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
        // if queues are disabled download a zip file
 | 
					 | 
				
			||||||
        if (config('queue.default') === 'sync' || count($this->invoices) <= 10) {
 | 
					 | 
				
			||||||
            $zip = Archive::instance_by_useragent(date('Y-m-d') . '-Invoice_PDFs');
 | 
					 | 
				
			||||||
            foreach ($this->invoices as $invoice) {
 | 
					 | 
				
			||||||
                $zip->add_file($invoice->getFileName(), $invoice->getPDFString());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $zip->finish();
 | 
					 | 
				
			||||||
            exit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // otherwise sends the PDFs in an email
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $data = [];
 | 
					 | 
				
			||||||
            foreach ($this->invoices as $invoice) {
 | 
					 | 
				
			||||||
                $data[] = [
 | 
					 | 
				
			||||||
                    'name' => $invoice->getFileName(),
 | 
					 | 
				
			||||||
                    'data' => $invoice->getPDFString(),
 | 
					 | 
				
			||||||
                ];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $subject = trans('texts.invoices_are_attached');
 | 
					 | 
				
			||||||
            $data = [
 | 
					 | 
				
			||||||
                'documents' => $data
 | 
					 | 
				
			||||||
            ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $userMailer->sendMessage($this->user, $subject, false, $data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        */
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,11 @@ class PurgeAccountData extends Job
 | 
				
			|||||||
            'vendors',
 | 
					            'vendors',
 | 
				
			||||||
            'contacts',
 | 
					            'contacts',
 | 
				
			||||||
            'clients',
 | 
					            'clients',
 | 
				
			||||||
 | 
					            'proposals',
 | 
				
			||||||
 | 
					            'proposal_templates',
 | 
				
			||||||
 | 
					            'proposal_snippets',
 | 
				
			||||||
 | 
					            'proposal_categories',
 | 
				
			||||||
 | 
					            'proposal_invitations',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($tables as $table) {
 | 
					        foreach ($tables as $table) {
 | 
				
			||||||
@ -71,6 +76,7 @@ class PurgeAccountData extends Job
 | 
				
			|||||||
            $lookupAccount = LookupAccount::whereAccountKey($account->account_key)->firstOrFail();
 | 
					            $lookupAccount = LookupAccount::whereAccountKey($account->account_key)->firstOrFail();
 | 
				
			||||||
            DB::table('lookup_contacts')->where('lookup_account_id', '=', $lookupAccount->id)->delete();
 | 
					            DB::table('lookup_contacts')->where('lookup_account_id', '=', $lookupAccount->id)->delete();
 | 
				
			||||||
            DB::table('lookup_invitations')->where('lookup_account_id', '=', $lookupAccount->id)->delete();
 | 
					            DB::table('lookup_invitations')->where('lookup_account_id', '=', $lookupAccount->id)->delete();
 | 
				
			||||||
 | 
					            DB::table('lookup_proposal_invitations')->where('lookup_account_id', '=', $lookupAccount->id)->delete();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            config(['database.default' => $current]);
 | 
					            config(['database.default' => $current]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,11 @@ class SendInvoiceEmail extends Job implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected $server;
 | 
					    protected $server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var Proposal
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $proposal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new job instance.
 | 
					     * Create a new job instance.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@ -51,12 +56,13 @@ class SendInvoiceEmail extends Job implements ShouldQueue
 | 
				
			|||||||
     * @param bool    $reminder
 | 
					     * @param bool    $reminder
 | 
				
			||||||
     * @param mixed   $pdfString
 | 
					     * @param mixed   $pdfString
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function __construct(Invoice $invoice, $userId = false, $reminder = false, $template = false)
 | 
					    public function __construct(Invoice $invoice, $userId = false, $reminder = false, $template = false, $proposal = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->invoice = $invoice;
 | 
					        $this->invoice = $invoice;
 | 
				
			||||||
        $this->userId = $userId;
 | 
					        $this->userId = $userId;
 | 
				
			||||||
        $this->reminder = $reminder;
 | 
					        $this->reminder = $reminder;
 | 
				
			||||||
        $this->template = $template;
 | 
					        $this->template = $template;
 | 
				
			||||||
 | 
					        $this->proposal = $proposal;
 | 
				
			||||||
        $this->server = config('database.default');
 | 
					        $this->server = config('database.default');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,7 +78,7 @@ class SendInvoiceEmail extends Job implements ShouldQueue
 | 
				
			|||||||
            Auth::onceUsingId($this->userId);
 | 
					            Auth::onceUsingId($this->userId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $mailer->sendInvoice($this->invoice, $this->reminder, $this->template);
 | 
					        $mailer->sendInvoice($this->invoice, $this->reminder, $this->template, $this->proposal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (App::runningInConsole() && $this->userId) {
 | 
					        if (App::runningInConsole() && $this->userId) {
 | 
				
			||||||
            Auth::logout();
 | 
					            Auth::logout();
 | 
				
			||||||
 | 
				
			|||||||
@ -61,4 +61,17 @@ class HTMLUtils
 | 
				
			|||||||
            return $previous;
 | 
					            return $previous;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function getEnvForAccount($field, $default = '')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $key = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($user = auth()->user()) {
 | 
				
			||||||
 | 
					            $key .= $user->account->id . '_';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $key .= $field;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return env($key, env($field, $default));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@ class HistoryUtils
 | 
				
			|||||||
    public static function loadHistory($users)
 | 
					    public static function loadHistory($users)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $userIds = [];
 | 
					        $userIds = [];
 | 
				
			||||||
 | 
					        session([RECENTLY_VIEWED => false]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_array($users)) {
 | 
					        if (is_array($users)) {
 | 
				
			||||||
            foreach ($users as $user) {
 | 
					            foreach ($users as $user) {
 | 
				
			||||||
@ -37,7 +38,7 @@ class HistoryUtils
 | 
				
			|||||||
            ACTIVITY_TYPE_VIEW_QUOTE,
 | 
					            ACTIVITY_TYPE_VIEW_QUOTE,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $activities = Activity::with(['client.contacts', 'invoice', 'task', 'expense'])
 | 
					        $activities = Activity::with(['client.contacts', 'invoice', 'task.project', 'expense'])
 | 
				
			||||||
            ->whereIn('user_id', $userIds)
 | 
					            ->whereIn('user_id', $userIds)
 | 
				
			||||||
            ->whereIn('activity_type_id', $activityTypes)
 | 
					            ->whereIn('activity_type_id', $activityTypes)
 | 
				
			||||||
            ->orderBy('id', 'desc')
 | 
					            ->orderBy('id', 'desc')
 | 
				
			||||||
@ -53,6 +54,12 @@ class HistoryUtils
 | 
				
			|||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                $entity->setRelation('client', $activity->client);
 | 
					                $entity->setRelation('client', $activity->client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ($entity->project) {
 | 
				
			||||||
 | 
					                    $project = $entity->project;
 | 
				
			||||||
 | 
					                    $project->setRelation('client', $activity->client);
 | 
				
			||||||
 | 
					                    static::trackViewed($project);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            } elseif ($activity->activity_type_id == ACTIVITY_TYPE_CREATE_EXPENSE || $activity->activity_type_id == ACTIVITY_TYPE_UPDATE_EXPENSE) {
 | 
					            } elseif ($activity->activity_type_id == ACTIVITY_TYPE_CREATE_EXPENSE || $activity->activity_type_id == ACTIVITY_TYPE_UPDATE_EXPENSE) {
 | 
				
			||||||
                $entity = $activity->expense;
 | 
					                $entity = $activity->expense;
 | 
				
			||||||
                if (! $entity) {
 | 
					                if (! $entity) {
 | 
				
			||||||
@ -80,6 +87,8 @@ class HistoryUtils
 | 
				
			|||||||
            ENTITY_QUOTE,
 | 
					            ENTITY_QUOTE,
 | 
				
			||||||
            ENTITY_TASK,
 | 
					            ENTITY_TASK,
 | 
				
			||||||
            ENTITY_EXPENSE,
 | 
					            ENTITY_EXPENSE,
 | 
				
			||||||
 | 
					            ENTITY_PROJECT,
 | 
				
			||||||
 | 
					            ENTITY_PROPOSAL,
 | 
				
			||||||
            //ENTITY_RECURRING_EXPENSE,
 | 
					            //ENTITY_RECURRING_EXPENSE,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,6 +96,10 @@ class HistoryUtils
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($entity->is_deleted) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $object = static::convertToObject($entity);
 | 
					        $object = static::convertToObject($entity);
 | 
				
			||||||
        $history = Session::get(RECENTLY_VIEWED) ?: [];
 | 
					        $history = Session::get(RECENTLY_VIEWED) ?: [];
 | 
				
			||||||
        $accountHistory = isset($history[$entity->account_id]) ? $history[$entity->account_id] : [];
 | 
					        $accountHistory = isset($history[$entity->account_id]) ? $history[$entity->account_id] : [];
 | 
				
			||||||
@ -135,6 +148,9 @@ class HistoryUtils
 | 
				
			|||||||
        } elseif (method_exists($entity, 'client') && $entity->client) {
 | 
					        } elseif (method_exists($entity, 'client') && $entity->client) {
 | 
				
			||||||
            $object->client_id = $entity->client->public_id;
 | 
					            $object->client_id = $entity->client->public_id;
 | 
				
			||||||
            $object->client_name = $entity->client->getDisplayName();
 | 
					            $object->client_name = $entity->client->getDisplayName();
 | 
				
			||||||
 | 
					        } elseif (method_exists($entity, 'invoice') && $entity->invoice) {
 | 
				
			||||||
 | 
					            $object->client_id = $entity->invoice->client->public_id;
 | 
				
			||||||
 | 
					            $object->client_name = $entity->invoice->client->getDisplayName();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $object->client_id = 0;
 | 
					            $object->client_id = 0;
 | 
				
			||||||
            $object->client_name = 0;
 | 
					            $object->client_name = 0;
 | 
				
			||||||
@ -175,7 +191,8 @@ class HistoryUtils
 | 
				
			|||||||
                    $button = '';
 | 
					                    $button = '';
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $str .= sprintf('<li>%s<a href="%s"><div>%s %s</div></a></li>', $button, $link, $icon, $name);
 | 
					                $padding = $str ? 16 : 0;
 | 
				
			||||||
 | 
					                $str .= sprintf('<li style="margin-top: %spx">%s<a href="%s"><div>%s %s</div></a></li>', $padding, $button, $link, $icon, $name);
 | 
				
			||||||
                $lastClientId = $item->client_id;
 | 
					                $lastClientId = $item->client_id;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -364,7 +364,9 @@ class Utils
 | 
				
			|||||||
            if ($field == 'checkbox') {
 | 
					            if ($field == 'checkbox') {
 | 
				
			||||||
                $data[] = $field;
 | 
					                $data[] = $field;
 | 
				
			||||||
            } elseif ($field) {
 | 
					            } elseif ($field) {
 | 
				
			||||||
                if ($module) {
 | 
					                if (substr($field, 0, 1) == '-') {
 | 
				
			||||||
 | 
					                    $data[] = substr($field, 1);
 | 
				
			||||||
 | 
					                } elseif ($module) {
 | 
				
			||||||
                    $data[] = mtrans($module, $field);
 | 
					                    $data[] = mtrans($module, $field);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    $data[] = trans("texts.$field");
 | 
					                    $data[] = trans("texts.$field");
 | 
				
			||||||
@ -564,6 +566,10 @@ class Utils
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if ($type === ENTITY_EXPENSE_CATEGORY) {
 | 
					        if ($type === ENTITY_EXPENSE_CATEGORY) {
 | 
				
			||||||
            return 'expense_categories';
 | 
					            return 'expense_categories';
 | 
				
			||||||
 | 
					        } elseif ($type === ENTITY_PROPOSAL_CATEGORY) {
 | 
				
			||||||
 | 
					            return 'proposal_categories';
 | 
				
			||||||
 | 
					        } elseif ($type === ENTITY_TASK_STATUS) {
 | 
				
			||||||
 | 
					            return 'task_statuses';
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return $type . 's';
 | 
					            return $type . 's';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1087,6 +1093,25 @@ class Utils
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function getCustomLabel($value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (strpos($value, '|') !== false) {
 | 
				
			||||||
 | 
					            return explode('|', $value)[0];
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return $value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function getCustomValues($value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (strpos($value, '|') !== false) {
 | 
				
			||||||
 | 
					            $values = explode(',', explode('|', $value)[1]);
 | 
				
			||||||
 | 
					            return array_combine($values, $values);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return $value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function formatWebsite($link)
 | 
					    public static function formatWebsite($link)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $link) {
 | 
					        if (! $link) {
 | 
				
			||||||
@ -1260,7 +1285,7 @@ class Utils
 | 
				
			|||||||
        $tax1 = round($amount * $taxRate1 / 100, 2);
 | 
					        $tax1 = round($amount * $taxRate1 / 100, 2);
 | 
				
			||||||
        $tax2 = round($amount * $taxRate2 / 100, 2);
 | 
					        $tax2 = round($amount * $taxRate2 / 100, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return round($amount + $tax1 + $tax2, 2);
 | 
					        return round($tax1 + $tax2, 2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function roundSignificant($value, $precision = 2) {
 | 
					    public static function roundSignificant($value, $precision = 2) {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Listeners;
 | 
					namespace App\Listeners;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Events\SubdomainWasRemoved;
 | 
				
			||||||
use App\Events\SubdomainWasUpdated;
 | 
					use App\Events\SubdomainWasUpdated;
 | 
				
			||||||
use App\Ninja\DNS\Cloudflare;
 | 
					use App\Ninja\DNS\Cloudflare;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,4 +20,11 @@ class DNSListener
 | 
				
			|||||||
        if(env("CLOUDFLARE_DNS_ENABLED"))
 | 
					        if(env("CLOUDFLARE_DNS_ENABLED"))
 | 
				
			||||||
            Cloudflare::addDNSRecord($event->account);
 | 
					            Cloudflare::addDNSRecord($event->account);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function removeDNSRecord(SubdomainWasRemoved $event)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(env("CLOUDFLARE_DNS_ENABLED"))
 | 
				
			||||||
 | 
					            Cloudflare::removeDNSRecord($event->account);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -102,7 +102,7 @@ class HandleUserLoggedIn
 | 
				
			|||||||
            if (in_array(config('app.key'), ['SomeRandomString', 'SomeRandomStringSomeRandomString', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'])) {
 | 
					            if (in_array(config('app.key'), ['SomeRandomString', 'SomeRandomStringSomeRandomString', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'])) {
 | 
				
			||||||
                Session::flash('error', trans('texts.error_app_key_set_to_default'));
 | 
					                Session::flash('error', trans('texts.error_app_key_set_to_default'));
 | 
				
			||||||
            } elseif (in_array($appCipher, ['MCRYPT_RIJNDAEL_256', 'MCRYPT_RIJNDAEL_128'])) {
 | 
					            } elseif (in_array($appCipher, ['MCRYPT_RIJNDAEL_256', 'MCRYPT_RIJNDAEL_128'])) {
 | 
				
			||||||
                Session::flash('error', trans('texts.mcrypt_warning'));
 | 
					                Session::flash('error', trans('texts.mcrypt_warning', ['command' => '<code>php artisan ninja:update-key --legacy=true</code>']));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,8 @@ class HandleUserSettingsChanged
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if ($event->user && $event->user->isEmailBeingChanged()) {
 | 
					        if ($event->user && $event->user->isEmailBeingChanged()) {
 | 
				
			||||||
            $this->userMailer->sendConfirmation($event->user);
 | 
					            $this->userMailer->sendConfirmation($event->user);
 | 
				
			||||||
 | 
					            $this->userMailer->sendEmailChanged($event->user);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            Session::flash('warning', trans('texts.verify_email'));
 | 
					            Session::flash('warning', trans('texts.verify_email'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -254,19 +254,30 @@ class SubscriptionListener
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // generate JSON data
 | 
				
			||||||
        $manager = new Manager();
 | 
					        $manager = new Manager();
 | 
				
			||||||
        $manager->setSerializer(new ArraySerializer());
 | 
					        $manager->setSerializer(new ArraySerializer());
 | 
				
			||||||
        $manager->parseIncludes($include);
 | 
					        $manager->parseIncludes($include);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $resource = new Item($entity, $transformer, $entity->getEntityType());
 | 
					        $resource = new Item($entity, $transformer, $entity->getEntityType());
 | 
				
			||||||
        $data = $manager->createData($resource)->toArray();
 | 
					        $jsonData = $manager->createData($resource)->toArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // For legacy Zapier support
 | 
					        // For legacy Zapier support
 | 
				
			||||||
        if (isset($data['client_id'])) {
 | 
					        if (isset($jsonData['client_id'])) {
 | 
				
			||||||
            $data['client_name'] = $entity->client->getDisplayName();
 | 
					            $jsonData['client_name'] = $entity->client->getDisplayName();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($subscriptions as $subscription) {
 | 
					        foreach ($subscriptions as $subscription) {
 | 
				
			||||||
 | 
					            switch ($subscription->format) {
 | 
				
			||||||
 | 
					                case SUBSCRIPTION_FORMAT_JSON:
 | 
				
			||||||
 | 
					                    $data = $jsonData;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case SUBSCRIPTION_FORMAT_UBL:
 | 
				
			||||||
 | 
					                    $data = $ublData;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            self::notifySubscription($subscription, $data);
 | 
					            self::notifySubscription($subscription, $data);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -146,6 +146,7 @@ class Account extends Eloquent
 | 
				
			|||||||
        'invoice_fields',
 | 
					        'invoice_fields',
 | 
				
			||||||
        'invoice_embed_documents',
 | 
					        'invoice_embed_documents',
 | 
				
			||||||
        'document_email_attachment',
 | 
					        'document_email_attachment',
 | 
				
			||||||
 | 
					        'ubl_email_attachment',
 | 
				
			||||||
        'enable_client_portal_dashboard',
 | 
					        'enable_client_portal_dashboard',
 | 
				
			||||||
        'page_size',
 | 
					        'page_size',
 | 
				
			||||||
        'live_preview',
 | 
					        'live_preview',
 | 
				
			||||||
@ -237,6 +238,8 @@ class Account extends Eloquent
 | 
				
			|||||||
        'hours',
 | 
					        'hours',
 | 
				
			||||||
        'id_number',
 | 
					        'id_number',
 | 
				
			||||||
        'invoice',
 | 
					        'invoice',
 | 
				
			||||||
 | 
					        'invoice_date',
 | 
				
			||||||
 | 
					        'invoice_number',
 | 
				
			||||||
        'item',
 | 
					        'item',
 | 
				
			||||||
        'line_total',
 | 
					        'line_total',
 | 
				
			||||||
        'outstanding',
 | 
					        'outstanding',
 | 
				
			||||||
@ -245,6 +248,8 @@ class Account extends Eloquent
 | 
				
			|||||||
        'po_number',
 | 
					        'po_number',
 | 
				
			||||||
        'quantity',
 | 
					        'quantity',
 | 
				
			||||||
        'quote',
 | 
					        'quote',
 | 
				
			||||||
 | 
					        'quote_date',
 | 
				
			||||||
 | 
					        'quote_number',
 | 
				
			||||||
        'rate',
 | 
					        'rate',
 | 
				
			||||||
        'service',
 | 
					        'service',
 | 
				
			||||||
        'subtotal',
 | 
					        'subtotal',
 | 
				
			||||||
@ -500,7 +505,7 @@ class Account extends Eloquent
 | 
				
			|||||||
        if ($gatewayId) {
 | 
					        if ($gatewayId) {
 | 
				
			||||||
            return $this->getGatewayConfig($gatewayId) != false;
 | 
					            return $this->getGatewayConfig($gatewayId) != false;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return count($this->account_gateways) > 0;
 | 
					            return $this->account_gateways->count() > 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1484,6 +1489,14 @@ class Account extends Eloquent
 | 
				
			|||||||
        return $this->hasFeature(FEATURE_PDF_ATTACHMENT) && $this->pdf_email_attachment;
 | 
					        return $this->hasFeature(FEATURE_PDF_ATTACHMENT) && $this->pdf_email_attachment;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function attachUBL()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasFeature(FEATURE_PDF_ATTACHMENT) && $this->ubl_email_attachment;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return mixed
 | 
					     * @return mixed
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -1643,6 +1656,7 @@ class Account extends Eloquent
 | 
				
			|||||||
            ENTITY_EXPENSE,
 | 
					            ENTITY_EXPENSE,
 | 
				
			||||||
            ENTITY_VENDOR,
 | 
					            ENTITY_VENDOR,
 | 
				
			||||||
            ENTITY_PROJECT,
 | 
					            ENTITY_PROJECT,
 | 
				
			||||||
 | 
					            ENTITY_PROPOSAL,
 | 
				
			||||||
        ])) {
 | 
					        ])) {
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1651,6 +1665,8 @@ class Account extends Eloquent
 | 
				
			|||||||
            $entityType = ENTITY_EXPENSE;
 | 
					            $entityType = ENTITY_EXPENSE;
 | 
				
			||||||
        } elseif ($entityType == ENTITY_PROJECT) {
 | 
					        } elseif ($entityType == ENTITY_PROJECT) {
 | 
				
			||||||
            $entityType = ENTITY_TASK;
 | 
					            $entityType = ENTITY_TASK;
 | 
				
			||||||
 | 
					        } elseif ($entityType == ENTITY_PROPOSAL) {
 | 
				
			||||||
 | 
					            $entityType = ENTITY_QUOTE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // note: single & checks bitmask match
 | 
					        // note: single & checks bitmask match
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,7 @@ class AccountEmailSettings extends Eloquent
 | 
				
			|||||||
    public static $templates = [
 | 
					    public static $templates = [
 | 
				
			||||||
        TEMPLATE_INVOICE,
 | 
					        TEMPLATE_INVOICE,
 | 
				
			||||||
        TEMPLATE_QUOTE,
 | 
					        TEMPLATE_QUOTE,
 | 
				
			||||||
 | 
					        TEMPLATE_PROPOSAL,
 | 
				
			||||||
        //TEMPLATE_PARTIAL,
 | 
					        //TEMPLATE_PARTIAL,
 | 
				
			||||||
        TEMPLATE_PAYMENT,
 | 
					        TEMPLATE_PAYMENT,
 | 
				
			||||||
        TEMPLATE_REMINDER1,
 | 
					        TEMPLATE_REMINDER1,
 | 
				
			||||||
 | 
				
			|||||||
@ -268,4 +268,13 @@ class AccountGateway extends EntityModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return \URL::to(env('WEBHOOK_PREFIX', '').'payment_hook/'.$account->account_key.'/'.$this->gateway_id.env('WEBHOOK_SUFFIX', ''));
 | 
					        return \URL::to(env('WEBHOOK_PREFIX', '').'payment_hook/'.$account->account_key.'/'.$this->gateway_id.env('WEBHOOK_SUFFIX', ''));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isTestMode()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->isGateway(GATEWAY_STRIPE)) {
 | 
				
			||||||
 | 
					            return strpos($this->getPublishableStripeKey(), 'test') !== false;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return $this->getConfigField('testMode');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -351,7 +351,7 @@ class Client extends EntityModel
 | 
				
			|||||||
            return $this->name;
 | 
					            return $this->name;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! count($this->contacts)) {
 | 
					        if (! $this->contacts->count()) {
 | 
				
			||||||
            return '';
 | 
					            return '';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -386,6 +386,29 @@ class Client extends EntityModel
 | 
				
			|||||||
        return $this->hasAddress() && env('GOOGLE_MAPS_ENABLED') !== false;
 | 
					        return $this->hasAddress() && env('GOOGLE_MAPS_ENABLED') !== false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function addressesMatch()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $fields = [
 | 
				
			||||||
 | 
					            'address1',
 | 
				
			||||||
 | 
					            'address2',
 | 
				
			||||||
 | 
					            'city',
 | 
				
			||||||
 | 
					            'state',
 | 
				
			||||||
 | 
					            'postal_code',
 | 
				
			||||||
 | 
					            'country_id',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($fields as $field) {
 | 
				
			||||||
 | 
					            if ($this->$field != $this->{'shipping_' . $field}) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return bool
 | 
					     * @return bool
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
@ -131,6 +131,21 @@ class Contact extends EntityModel implements AuthenticatableContract, CanResetPa
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed|string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getSearchName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $name = $this->getFullName();
 | 
				
			||||||
 | 
					        $email = $this->email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($name && $email) {
 | 
				
			||||||
 | 
					            return sprintf('%s <%s>', $name, $email);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return $name ?: $email;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $contact_key
 | 
					     * @param $contact_key
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,6 @@ class Country extends Eloquent
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getName()
 | 
					    public function getName()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->name;
 | 
					        return trans('texts.country_' . $this->name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -272,6 +272,15 @@ class Document extends EntityModel
 | 
				
			|||||||
        return url('client/documents/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
 | 
					        return url('client/documents/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getProposalUrl()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->is_proposal || ! $this->document_key) {
 | 
				
			||||||
 | 
					            return '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return url('proposal/image/'. $this->account->account_key . '/' . $this->document_key . '/' . $this->name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return bool
 | 
					     * @return bool
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
@ -321,6 +321,7 @@ class EntityModel extends Eloquent
 | 
				
			|||||||
            'recurring_expenses' => 'files-o',
 | 
					            'recurring_expenses' => 'files-o',
 | 
				
			||||||
            'credits' => 'credit-card',
 | 
					            'credits' => 'credit-card',
 | 
				
			||||||
            'quotes' => 'file-text-o',
 | 
					            'quotes' => 'file-text-o',
 | 
				
			||||||
 | 
					            'proposals' => 'th-large',
 | 
				
			||||||
            'tasks' => 'clock-o',
 | 
					            'tasks' => 'clock-o',
 | 
				
			||||||
            'expenses' => 'file-image-o',
 | 
					            'expenses' => 'file-image-o',
 | 
				
			||||||
            'vendors' => 'building',
 | 
					            'vendors' => 'building',
 | 
				
			||||||
@ -354,6 +355,15 @@ class EntityModel extends Eloquent
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function getFormUrl($entityType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (in_array($entityType, [ENTITY_PROPOSAL_CATEGORY, ENTITY_PROPOSAL_SNIPPET, ENTITY_PROPOSAL_TEMPLATE])) {
 | 
				
			||||||
 | 
					            return str_replace('_', 's/', Utils::pluralizeEntityType($entityType));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return Utils::pluralizeEntityType($entityType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function getStates($entityType = false)
 | 
					    public static function getStates($entityType = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $data = [];
 | 
					        $data = [];
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ class Expense extends EntityModel
 | 
				
			|||||||
            'vendor',
 | 
					            'vendor',
 | 
				
			||||||
            'amount',
 | 
					            'amount',
 | 
				
			||||||
            'public_notes',
 | 
					            'public_notes',
 | 
				
			||||||
 | 
					            'private_notes',
 | 
				
			||||||
            'expense_category',
 | 
					            'expense_category',
 | 
				
			||||||
            'expense_date',
 | 
					            'expense_date',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
@ -73,7 +74,8 @@ class Expense extends EntityModel
 | 
				
			|||||||
            'category' => 'expense_category',
 | 
					            'category' => 'expense_category',
 | 
				
			||||||
            'client' => 'client',
 | 
					            'client' => 'client',
 | 
				
			||||||
            'vendor' => 'vendor',
 | 
					            'vendor' => 'vendor',
 | 
				
			||||||
            'notes|details' => 'public_notes',
 | 
					            'notes|details^private' => 'public_notes',
 | 
				
			||||||
 | 
					            'notes|details^public' => 'private_notes',
 | 
				
			||||||
            'date' => 'expense_date',
 | 
					            'date' => 'expense_date',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -253,6 +255,11 @@ class Expense extends EntityModel
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function amountWithTax()
 | 
					    public function amountWithTax()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->amount + $this->taxAmount();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function taxAmount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
 | 
					        return Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -2,10 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Models;
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Carbon;
 | 
					 | 
				
			||||||
use Illuminate\Database\Eloquent\SoftDeletes;
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
use Utils;
 | 
					 | 
				
			||||||
use App\Models\LookupInvitation;
 | 
					use App\Models\LookupInvitation;
 | 
				
			||||||
 | 
					use App\Models\Traits\Inviteable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class Invitation.
 | 
					 * Class Invitation.
 | 
				
			||||||
@ -13,6 +12,8 @@ use App\Models\LookupInvitation;
 | 
				
			|||||||
class Invitation extends EntityModel
 | 
					class Invitation extends EntityModel
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use SoftDeletes;
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use Inviteable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @var array
 | 
					     * @var array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -58,102 +59,6 @@ class Invitation extends EntityModel
 | 
				
			|||||||
        return $this->belongsTo('App\Models\Account');
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If we're getting the link for PhantomJS to generate the PDF
 | 
					 | 
				
			||||||
    // we need to make sure it's served from our site
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @param string $type
 | 
					 | 
				
			||||||
     * @param bool   $forceOnsite
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return string
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function getLink($type = 'view', $forceOnsite = false, $forcePlain = false)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (! $this->account) {
 | 
					 | 
				
			||||||
            $this->load('account');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $account = $this->account;
 | 
					 | 
				
			||||||
        $iframe_url = $account->iframe_url;
 | 
					 | 
				
			||||||
        $url = trim(SITE_URL, '/');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (env('REQUIRE_HTTPS')) {
 | 
					 | 
				
			||||||
            $url = str_replace('http://', 'https://', $url);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($account->hasFeature(FEATURE_CUSTOM_URL)) {
 | 
					 | 
				
			||||||
            if (Utils::isNinjaProd() && ! Utils::isReseller()) {
 | 
					 | 
				
			||||||
                $url = $account->present()->clientPortalLink();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($iframe_url && ! $forceOnsite) {
 | 
					 | 
				
			||||||
                return "{$iframe_url}?{$this->invitation_key}";
 | 
					 | 
				
			||||||
            } elseif ($this->account->subdomain && ! $forcePlain) {
 | 
					 | 
				
			||||||
                $url = Utils::replaceSubdomain($url, $account->subdomain);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return "{$url}/{$type}/{$this->invitation_key}";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return bool|string
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function getStatus()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $hasValue = false;
 | 
					 | 
				
			||||||
        $parts = [];
 | 
					 | 
				
			||||||
        $statuses = $this->message_id ? ['sent', 'opened', 'viewed'] : ['sent', 'viewed'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($statuses as $status) {
 | 
					 | 
				
			||||||
            $field = "{$status}_date";
 | 
					 | 
				
			||||||
            $date = '';
 | 
					 | 
				
			||||||
            if ($this->$field && $this->field != '0000-00-00 00:00:00') {
 | 
					 | 
				
			||||||
                $date = Utils::dateToString($this->$field);
 | 
					 | 
				
			||||||
                $hasValue = true;
 | 
					 | 
				
			||||||
                $parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $hasValue ? implode($parts, '<br/>') : false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return mixed
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function getName()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->invitation_key;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @param null $messageId
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function markSent($messageId = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->message_id = $messageId;
 | 
					 | 
				
			||||||
        $this->email_error = null;
 | 
					 | 
				
			||||||
        $this->sent_date = Carbon::now()->toDateTimeString();
 | 
					 | 
				
			||||||
        $this->save();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function isSent()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->sent_date && $this->sent_date != '0000-00-00 00:00:00';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function markViewed()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $invoice = $this->invoice;
 | 
					 | 
				
			||||||
        $client = $invoice->client;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->viewed_date = Carbon::now()->toDateTimeString();
 | 
					 | 
				
			||||||
        $this->save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $invoice->markViewed();
 | 
					 | 
				
			||||||
        $client->markLoggedIn();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function signatureDiv()
 | 
					    public function signatureDiv()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (! $this->signature_base64) {
 | 
					        if (! $this->signature_base64) {
 | 
				
			||||||
 | 
				
			|||||||
@ -451,6 +451,23 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
                     ->where('is_recurring', '=', false);
 | 
					                     ->where('is_recurring', '=', false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param $query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function scopeUnapprovedQuotes($query, $includeInvoiceId = false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $query->quotes()
 | 
				
			||||||
 | 
					                    ->where(function ($query) use ($includeInvoiceId) {
 | 
				
			||||||
 | 
					                        $query->whereId($includeInvoiceId)
 | 
				
			||||||
 | 
					                            ->orWhere(function ($query) {
 | 
				
			||||||
 | 
					                                  $query->where('invoice_status_id', '<', INVOICE_STATUS_APPROVED)
 | 
				
			||||||
 | 
					                                    ->whereNull('quote_invoice_id');
 | 
				
			||||||
 | 
					                              });
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $query
 | 
					     * @param $query
 | 
				
			||||||
     * @param $typeId
 | 
					     * @param $typeId
 | 
				
			||||||
@ -710,11 +727,11 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return string
 | 
					     * @return string
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getFileName()
 | 
					    public function getFileName($extension = 'pdf')
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $entityType = $this->getEntityType();
 | 
					        $entityType = $this->getEntityType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return trans("texts.$entityType") . '_' . $this->invoice_number . '.pdf';
 | 
					        return trans("texts.$entityType") . '_' . $this->invoice_number . '.' . $extension;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -841,6 +858,14 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
        return $this->invoice_status_id >= INVOICE_STATUS_VIEWED;
 | 
					        return $this->invoice_status_id >= INVOICE_STATUS_VIEWED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function isApproved()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->invoice_status_id >= INVOICE_STATUS_APPROVED || $this->quote_invoice_id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return bool
 | 
					     * @return bool
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -1403,21 +1428,12 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
        $paidAmount = $this->getAmountPaid($calculatePaid);
 | 
					        $paidAmount = $this->getAmountPaid($calculatePaid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->tax_name1) {
 | 
					        if ($this->tax_name1) {
 | 
				
			||||||
            if ($account->inclusive_taxes) {
 | 
					            $invoiceTaxAmount = $this->taxAmount($taxable, $this->tax_rate1);
 | 
				
			||||||
                $invoiceTaxAmount = round($taxable - ($taxable / (1 + ($this->tax_rate1 / 100))), 2);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                $invoiceTaxAmount = round($taxable * ($this->tax_rate1 / 100), 2);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $invoicePaidAmount = floatval($this->amount) && $invoiceTaxAmount ? ($paidAmount / $this->amount * $invoiceTaxAmount) : 0;
 | 
					            $invoicePaidAmount = floatval($this->amount) && $invoiceTaxAmount ? ($paidAmount / $this->amount * $invoiceTaxAmount) : 0;
 | 
				
			||||||
            $this->calculateTax($taxes, $this->tax_name1, $this->tax_rate1, $invoiceTaxAmount, $invoicePaidAmount);
 | 
					            $this->calculateTax($taxes, $this->tax_name1, $this->tax_rate1, $invoiceTaxAmount, $invoicePaidAmount);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->tax_name2) {
 | 
					        if ($this->tax_name2) {
 | 
				
			||||||
            if ($account->inclusive_taxes) {
 | 
					            $invoiceTaxAmount = $this->taxAmount($taxable, $this->tax_rate2);
 | 
				
			||||||
                $invoiceTaxAmount = round($taxable - ($taxable / (1 + ($this->tax_rate2 / 100))), 2);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                $invoiceTaxAmount = round($taxable * ($this->tax_rate2 / 100), 2);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $invoicePaidAmount = floatval($this->amount) && $invoiceTaxAmount ? ($paidAmount / $this->amount * $invoiceTaxAmount) : 0;
 | 
					            $invoicePaidAmount = floatval($this->amount) && $invoiceTaxAmount ? ($paidAmount / $this->amount * $invoiceTaxAmount) : 0;
 | 
				
			||||||
            $this->calculateTax($taxes, $this->tax_name2, $this->tax_rate2, $invoiceTaxAmount, $invoicePaidAmount);
 | 
					            $this->calculateTax($taxes, $this->tax_name2, $this->tax_rate2, $invoiceTaxAmount, $invoicePaidAmount);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1426,21 +1442,12 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
            $itemTaxable = $this->getItemTaxable($invoiceItem, $taxable);
 | 
					            $itemTaxable = $this->getItemTaxable($invoiceItem, $taxable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($invoiceItem->tax_name1) {
 | 
					            if ($invoiceItem->tax_name1) {
 | 
				
			||||||
                if ($account->inclusive_taxes) {
 | 
					                $itemTaxAmount = $this->taxAmount($itemTaxable, $invoiceItem->tax_rate1);
 | 
				
			||||||
                    $itemTaxAmount = round($taxable - ($taxable / (1 + ($invoiceItem->tax_rate1 / 100))), 2);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $itemTaxAmount = round($itemTaxable * ($invoiceItem->tax_rate1 / 100), 2);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                $itemPaidAmount = floatval($this->amount) && $itemTaxAmount ? ($paidAmount / $this->amount * $itemTaxAmount) : 0;
 | 
					                $itemPaidAmount = floatval($this->amount) && $itemTaxAmount ? ($paidAmount / $this->amount * $itemTaxAmount) : 0;
 | 
				
			||||||
                $this->calculateTax($taxes, $invoiceItem->tax_name1, $invoiceItem->tax_rate1, $itemTaxAmount, $itemPaidAmount);
 | 
					                $this->calculateTax($taxes, $invoiceItem->tax_name1, $invoiceItem->tax_rate1, $itemTaxAmount, $itemPaidAmount);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($invoiceItem->tax_name2) {
 | 
					            if ($invoiceItem->tax_name2) {
 | 
				
			||||||
                if ($account->inclusive_taxes) {
 | 
					                $itemTaxAmount = $this->taxAmount($itemTaxable, $invoiceItem->tax_rate2);
 | 
				
			||||||
                    $itemTaxAmount = round($taxable - ($taxable / (1 + ($invoiceItem->tax_rate2 / 100))), 2);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $itemTaxAmount = round($itemTaxable * ($invoiceItem->tax_rate2 / 100), 2);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                $itemPaidAmount = floatval($this->amount) && $itemTaxAmount ? ($paidAmount / $this->amount * $itemTaxAmount) : 0;
 | 
					                $itemPaidAmount = floatval($this->amount) && $itemTaxAmount ? ($paidAmount / $this->amount * $itemTaxAmount) : 0;
 | 
				
			||||||
                $this->calculateTax($taxes, $invoiceItem->tax_name2, $invoiceItem->tax_rate2, $itemTaxAmount, $itemPaidAmount);
 | 
					                $this->calculateTax($taxes, $invoiceItem->tax_name2, $invoiceItem->tax_rate2, $itemTaxAmount, $itemPaidAmount);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1449,6 +1456,28 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
        return $taxes;
 | 
					        return $taxes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getTaxTotal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $total = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($this->getTaxes() as $tax) {
 | 
				
			||||||
 | 
					            $total += $tax['amount'];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $total;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function taxAmount($taxable, $rate)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $account = $this->account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($account->inclusive_taxes) {
 | 
				
			||||||
 | 
					            return round($taxable - ($taxable / (1 + ($rate / 100))), 2);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return round($taxable * ($rate / 100), 2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $taxes
 | 
					     * @param $taxes
 | 
				
			||||||
     * @param $name
 | 
					     * @param $name
 | 
				
			||||||
@ -1484,18 +1513,18 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function countDocuments($expenses = false)
 | 
					    public function countDocuments($expenses = false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $count = count($this->documents);
 | 
					        $count = $this->documents->count();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($this->expenses as $expense) {
 | 
					        foreach ($this->expenses as $expense) {
 | 
				
			||||||
            if ($expense->invoice_documents) {
 | 
					            if ($expense->invoice_documents) {
 | 
				
			||||||
                $count += count($expense->documents);
 | 
					                $count += $expense->documents->count();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($expenses) {
 | 
					        if ($expenses) {
 | 
				
			||||||
            foreach ($expenses as $expense) {
 | 
					            foreach ($expenses as $expense) {
 | 
				
			||||||
                if ($expense->invoice_documents) {
 | 
					                if ($expense->invoice_documents) {
 | 
				
			||||||
                    $count += count($expense->documents);
 | 
					                    $count += $expense->documents->count();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1525,7 +1554,7 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
    public function hasExpenseDocuments()
 | 
					    public function hasExpenseDocuments()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        foreach ($this->expenses as $expense) {
 | 
					        foreach ($this->expenses as $expense) {
 | 
				
			||||||
            if ($expense->invoice_documents && count($expense->documents)) {
 | 
					            if ($expense->invoice_documents && $expense->documents->count()) {
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1606,6 +1635,28 @@ class Invoice extends EntityModel implements BalanceAffecting
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function hasTaxes()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->tax_name1 || $this->tax_rate1) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->tax_name2 || $this->tax_rate2) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isLocked()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! config('ninja.lock_sent_invoices')) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->isSent() && ! $this->is_recurring;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Invoice::creating(function ($invoice) {
 | 
					Invoice::creating(function ($invoice) {
 | 
				
			||||||
 | 
				
			|||||||
@ -107,4 +107,33 @@ class InvoiceItem extends EntityModel
 | 
				
			|||||||
            $this->save();
 | 
					            $this->save();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function hasTaxes()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->tax_name1 || $this->tax_rate1) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->tax_name2 || $this->tax_rate2) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function costWithDiscount()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $cost = $this->cost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->discount != 0) {
 | 
				
			||||||
 | 
					            if ($this->invoice->is_amount_discount) {
 | 
				
			||||||
 | 
					                $cost -= $discount / $this->qty;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $cost -= $cost * $discount / 100;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $cost;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										47
									
								
								app/Models/LookupProposalInvitation.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/Models/LookupProposalInvitation.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Eloquent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ExpenseCategory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class LookupProposalInvitation extends LookupModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $fillable = [
 | 
				
			||||||
 | 
					        'lookup_account_id',
 | 
				
			||||||
 | 
					        'invitation_key',
 | 
				
			||||||
 | 
					        'message_id',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function updateInvitation($accountKey, $invitation)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! env('MULTI_DB_ENABLED')) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (! $invitation->message_id) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $current = config('database.default');
 | 
				
			||||||
 | 
					        config(['database.default' => DB_NINJA_LOOKUP]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $lookupAccount = LookupAccount::whereAccountKey($accountKey)
 | 
				
			||||||
 | 
					                            ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $lookupInvitation = LookupProposalInvitation::whereLookupAccountId($lookupAccount->id)
 | 
				
			||||||
 | 
					                                ->whereInvitationKey($invitation->invitation_key)
 | 
				
			||||||
 | 
					                                ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $lookupInvitation->message_id = $invitation->message_id;
 | 
				
			||||||
 | 
					        $lookupInvitation->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        config(['database.default' => $current]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -47,6 +47,8 @@ class Product extends EntityModel
 | 
				
			|||||||
            'product_key',
 | 
					            'product_key',
 | 
				
			||||||
            'notes',
 | 
					            'notes',
 | 
				
			||||||
            'cost',
 | 
					            'cost',
 | 
				
			||||||
 | 
					            'custom_value1',
 | 
				
			||||||
 | 
					            'custom_value2',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +61,8 @@ class Product extends EntityModel
 | 
				
			|||||||
            'product|item' => 'product_key',
 | 
					            'product|item' => 'product_key',
 | 
				
			||||||
            'notes|description|details' => 'notes',
 | 
					            'notes|description|details' => 'notes',
 | 
				
			||||||
            'cost|amount|price' => 'cost',
 | 
					            'cost|amount|price' => 'cost',
 | 
				
			||||||
 | 
					            'custom_value1' => 'custom_value1',
 | 
				
			||||||
 | 
					            'custom_value2' => 'custom_value2',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										107
									
								
								app/Models/Proposal.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								app/Models/Proposal.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ExpenseCategory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Proposal extends EntityModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $dates = ['deleted_at'];
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $presenter = 'App\Ninja\Presenters\ProposalPresenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $fillable = [
 | 
				
			||||||
 | 
					        'private_notes',
 | 
				
			||||||
 | 
					        'html',
 | 
				
			||||||
 | 
					        'css',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    //protected $presenter = 'App\Ninja\Presenters\ProjectPresenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEntityType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ENTITY_PROPOSAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getRoute()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return "/proposals/{$this->public_id}";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function account()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function invoice()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Invoice')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function invitations()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasMany('App\Models\ProposalInvitation')->orderBy('proposal_invitations.contact_id');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function proposal_invitations()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasMany('App\Models\ProposalInvitation')->orderBy('proposal_invitations.contact_id');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function proposal_template()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\ProposalTemplate')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDisplayName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->invoice->invoice_number;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Proposal::creating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Proposal::updating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										71
									
								
								app/Models/ProposalCategory.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/Models/ProposalCategory.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ExpenseCategory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ProposalCategory extends EntityModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $dates = ['deleted_at'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $fillable = [
 | 
				
			||||||
 | 
					        'name',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    //protected $presenter = 'App\Ninja\Presenters\ProjectPresenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEntityType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ENTITY_PROPOSAL_CATEGORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getRoute()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return "/proposals/categories/{$this->public_id}";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function account()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDisplayName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Proposal::creating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Proposal::updating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
							
								
								
									
										85
									
								
								app/Models/ProposalInvitation.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								app/Models/ProposalInvitation.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use App\Models\LookupProposalInvitation;
 | 
				
			||||||
 | 
					use App\Models\Traits\Inviteable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class Invitation.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ProposalInvitation extends EntityModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use Inviteable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $dates = ['deleted_at'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEntityType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ENTITY_PROPOSAL_INVITATION;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function proposal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Proposal')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function contact()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Contact')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function user()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\User')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function account()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ProposalInvitation::creating(function ($invitation)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    LookupProposalInvitation::createNew($invitation->account->account_key, [
 | 
				
			||||||
 | 
					        'invitation_key' => $invitation->invitation_key,
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ProposalInvitation::updating(function ($invitation)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    $dirty = $invitation->getDirty();
 | 
				
			||||||
 | 
					    if (array_key_exists('message_id', $dirty)) {
 | 
				
			||||||
 | 
					        LookupProposalInvitation::updateInvitation($invitation->account->account_key, $invitation);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ProposalInvitation::deleted(function ($invitation)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ($invitation->forceDeleting) {
 | 
				
			||||||
 | 
					        LookupProposalInvitation::deleteWhere([
 | 
				
			||||||
 | 
					            'invitation_key' => $invitation->invitation_key,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										84
									
								
								app/Models/ProposalSnippet.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								app/Models/ProposalSnippet.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ExpenseCategory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ProposalSnippet extends EntityModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $dates = ['deleted_at'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $fillable = [
 | 
				
			||||||
 | 
					        'name',
 | 
				
			||||||
 | 
					        'icon',
 | 
				
			||||||
 | 
					        'private_notes',
 | 
				
			||||||
 | 
					        'proposal_category_id',
 | 
				
			||||||
 | 
					        'html',
 | 
				
			||||||
 | 
					        'css',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $presenter = 'App\Ninja\Presenters\ProposalSnippetPresenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEntityType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ENTITY_PROPOSAL_SNIPPET;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getRoute()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return "/proposals/snippets/{$this->public_id}";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function account()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function proposal_category()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\ProposalCategory')->withTrashed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDisplayName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Proposal::creating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Proposal::updating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
							
								
								
									
										74
									
								
								app/Models/ProposalTemplate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Models/ProposalTemplate.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\SoftDeletes;
 | 
				
			||||||
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ExpenseCategory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ProposalTemplate extends EntityModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use SoftDeletes;
 | 
				
			||||||
 | 
					    use PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $dates = ['deleted_at'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $fillable = [
 | 
				
			||||||
 | 
					        'name',
 | 
				
			||||||
 | 
					        'private_notes',
 | 
				
			||||||
 | 
					        'html',
 | 
				
			||||||
 | 
					        'css',
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $presenter = 'App\Ninja\Presenters\ProposalTemplatePresenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEntityType()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ENTITY_PROPOSAL_TEMPLATE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getRoute()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return "/proposals/templates/{$this->public_id}";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function account()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->belongsTo('App\Models\Account');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getDisplayName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Proposal::creating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Proposal::updating(function ($project) {
 | 
				
			||||||
 | 
					    $project->setNullValues();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
@ -129,7 +129,7 @@ class RecurringExpense extends EntityModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function amountWithTax()
 | 
					    public function amountWithTax()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
 | 
					        return $this->amount + Utils::calculateTaxes($this->amount, $this->tax_rate1, $this->tax_rate2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@ class Subscription extends EntityModel
 | 
				
			|||||||
    protected $fillable = [
 | 
					    protected $fillable = [
 | 
				
			||||||
        'event_id',
 | 
					        'event_id',
 | 
				
			||||||
        'target_url',
 | 
					        'target_url',
 | 
				
			||||||
 | 
					        'format',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -129,17 +129,27 @@ class Task extends EntityModel
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return int
 | 
					     * @return int
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function calcDuration($task)
 | 
					    public static function calcDuration($task, $startTimeCutoff = 0, $endTimeCutoff = 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $duration = 0;
 | 
					        $duration = 0;
 | 
				
			||||||
        $parts = json_decode($task->time_log) ?: [];
 | 
					        $parts = json_decode($task->time_log) ?: [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($parts as $part) {
 | 
					        foreach ($parts as $part) {
 | 
				
			||||||
 | 
					            $startTime = $part[0];
 | 
				
			||||||
            if (count($part) == 1 || ! $part[1]) {
 | 
					            if (count($part) == 1 || ! $part[1]) {
 | 
				
			||||||
                $duration += time() - $part[0];
 | 
					                $endTime = time();
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $duration += $part[1] - $part[0];
 | 
					                $endTime = $part[1];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($startTimeCutoff) {
 | 
				
			||||||
 | 
					                $startTime = max($startTime, $startTimeCutoff);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if ($endTimeCutoff) {
 | 
				
			||||||
 | 
					                $endTime = min($endTime, $endTimeCutoff);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $duration += $endTime - $startTime;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $duration;
 | 
					        return $duration;
 | 
				
			||||||
@ -148,9 +158,9 @@ class Task extends EntityModel
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return int
 | 
					     * @return int
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getDuration()
 | 
					    public function getDuration($startTimeCutoff = 0, $endTimeCutoff = 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return self::calcDuration($this);
 | 
					        return self::calcDuration($this, $startTimeCutoff, $endTimeCutoff);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -230,8 +240,11 @@ class Task extends EntityModel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function scopeDateRange($query, $startDate, $endDate)
 | 
					    public function scopeDateRange($query, $startDate, $endDate)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $query->whereRaw('cast(substring(time_log, 3, 10) as unsigned) >= ' . $startDate->format('U'));
 | 
					        $query->whereRaw('cast(substring(time_log, 3, 10) as unsigned) <= ' . $endDate->modify('+1 day')->format('U'))
 | 
				
			||||||
        $query->whereRaw('cast(substring(time_log, 3, 10) as unsigned) <= ' . $endDate->modify('+1 day')->format('U'));
 | 
					            ->whereRaw('case
 | 
				
			||||||
 | 
					                when is_running then unix_timestamp()
 | 
				
			||||||
 | 
					                else cast(substring(time_log, length(time_log) - 11, 10) as unsigned)
 | 
				
			||||||
 | 
					            end >= ' . $startDate->format('U'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $query;
 | 
					        return $query;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										113
									
								
								app/Models/Traits/Inviteable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								app/Models/Traits/Inviteable.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Models\Traits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Carbon;
 | 
				
			||||||
 | 
					use Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class SendsEmails.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					trait Inviteable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // If we're getting the link for PhantomJS to generate the PDF
 | 
				
			||||||
 | 
					    // we need to make sure it's served from our site
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param string $type
 | 
				
			||||||
 | 
					     * @param bool   $forceOnsite
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getLink($type = 'view', $forceOnsite = false, $forcePlain = false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! $this->account) {
 | 
				
			||||||
 | 
					            $this->load('account');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->proposal_id) {
 | 
				
			||||||
 | 
					            $type = 'proposal';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $account = $this->account;
 | 
				
			||||||
 | 
					        $iframe_url = $account->iframe_url;
 | 
				
			||||||
 | 
					        $url = trim(SITE_URL, '/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (env('REQUIRE_HTTPS')) {
 | 
				
			||||||
 | 
					            $url = str_replace('http://', 'https://', $url);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($account->hasFeature(FEATURE_CUSTOM_URL)) {
 | 
				
			||||||
 | 
					            if (Utils::isNinjaProd() && ! Utils::isReseller()) {
 | 
				
			||||||
 | 
					                $url = $account->present()->clientPortalLink();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($iframe_url && ! $forceOnsite) {
 | 
				
			||||||
 | 
					                return "{$iframe_url}?{$this->invitation_key}";
 | 
				
			||||||
 | 
					            } elseif ($this->account->subdomain && ! $forcePlain) {
 | 
				
			||||||
 | 
					                $url = Utils::replaceSubdomain($url, $account->subdomain);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return "{$url}/{$type}/{$this->invitation_key}";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return bool|string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getStatus()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $hasValue = false;
 | 
				
			||||||
 | 
					        $parts = [];
 | 
				
			||||||
 | 
					        $statuses = $this->message_id ? ['sent', 'opened', 'viewed'] : ['sent', 'viewed'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($statuses as $status) {
 | 
				
			||||||
 | 
					            $field = "{$status}_date";
 | 
				
			||||||
 | 
					            $date = '';
 | 
				
			||||||
 | 
					            if ($this->$field && $this->field != '0000-00-00 00:00:00') {
 | 
				
			||||||
 | 
					                $date = Utils::dateToString($this->$field);
 | 
				
			||||||
 | 
					                $hasValue = true;
 | 
				
			||||||
 | 
					                $parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $hasValue ? implode($parts, '<br/>') : false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return mixed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->invitation_key;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param null $messageId
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function markSent($messageId = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->message_id = $messageId;
 | 
				
			||||||
 | 
					        $this->email_error = null;
 | 
				
			||||||
 | 
					        $this->sent_date = Carbon::now()->toDateTimeString();
 | 
				
			||||||
 | 
					        $this->save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isSent()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->sent_date && $this->sent_date != '0000-00-00 00:00:00';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function markViewed()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->viewed_date = Carbon::now()->toDateTimeString();
 | 
				
			||||||
 | 
					        $this->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->invoice) {
 | 
				
			||||||
 | 
					            $invoice = $this->invoice;
 | 
				
			||||||
 | 
					            $client = $invoice->client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $invoice->markViewed();
 | 
				
			||||||
 | 
					            $client->markLoggedIn();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user