mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
commit
6558bfcce9
@ -95,13 +95,14 @@ module.exports = function(grunt) {
|
|||||||
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.no.min.js',
|
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.no.min.js',
|
||||||
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.es.min.js',
|
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.es.min.js',
|
||||||
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.sv.min.js',
|
'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.sv.min.js',
|
||||||
'public/vendor/typeahead.js/dist/typeahead.min.js',
|
'public/vendor/typeahead.js/dist/typeahead.jquery.min.js',
|
||||||
'public/vendor/accounting/accounting.min.js',
|
'public/vendor/accounting/accounting.min.js',
|
||||||
'public/vendor/spectrum/spectrum.js',
|
'public/vendor/spectrum/spectrum.js',
|
||||||
'public/vendor/jspdf/dist/jspdf.min.js',
|
'public/vendor/jspdf/dist/jspdf.min.js',
|
||||||
'public/vendor/moment/min/moment.min.js',
|
'public/vendor/moment/min/moment.min.js',
|
||||||
'public/vendor/moment-timezone/builds/moment-timezone-with-data.min.js',
|
'public/vendor/moment-timezone/builds/moment-timezone-with-data.min.js',
|
||||||
'public/vendor/stacktrace-js/dist/stacktrace-with-polyfills.min.js',
|
'public/vendor/stacktrace-js/dist/stacktrace-with-polyfills.min.js',
|
||||||
|
'public/vendor/fuse.js/src/fuse.min.js',
|
||||||
//'public/vendor/moment-duration-format/lib/moment-duration-format.js',
|
//'public/vendor/moment-duration-format/lib/moment-duration-format.js',
|
||||||
//'public/vendor/handsontable/dist/jquery.handsontable.full.min.js',
|
//'public/vendor/handsontable/dist/jquery.handsontable.full.min.js',
|
||||||
//'public/vendor/pdfmake/build/pdfmake.min.js',
|
//'public/vendor/pdfmake/build/pdfmake.min.js',
|
||||||
|
@ -47,13 +47,16 @@ class Handler extends ExceptionHandler {
|
|||||||
if ($e instanceof ModelNotFoundException) {
|
if ($e instanceof ModelNotFoundException) {
|
||||||
return Redirect::to('/');
|
return Redirect::to('/');
|
||||||
} elseif ($e instanceof \Illuminate\Session\TokenMismatchException) {
|
} elseif ($e instanceof \Illuminate\Session\TokenMismatchException) {
|
||||||
// https://gist.github.com/jrmadsen67/bd0f9ad0ef1ed6bb594e
|
// prevent loop since the page auto-submits
|
||||||
return redirect()
|
if ($request->path() != 'get_started') {
|
||||||
->back()
|
// https://gist.github.com/jrmadsen67/bd0f9ad0ef1ed6bb594e
|
||||||
->withInput($request->except('password', '_token'))
|
return redirect()
|
||||||
->with([
|
->back()
|
||||||
'warning' => trans('texts.token_expired')
|
->withInput($request->except('password', '_token'))
|
||||||
]);
|
->with([
|
||||||
|
'warning' => trans('texts.token_expired')
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In production, except for maintenance mode, we'll show a custom error screen
|
// In production, except for maintenance mode, we'll show a custom error screen
|
||||||
|
@ -684,6 +684,8 @@ class AccountController extends BaseController
|
|||||||
$account->custom_invoice_taxes2 = Input::get('custom_invoice_taxes2') ? true : false;
|
$account->custom_invoice_taxes2 = Input::get('custom_invoice_taxes2') ? true : false;
|
||||||
$account->custom_invoice_text_label1 = trim(Input::get('custom_invoice_text_label1'));
|
$account->custom_invoice_text_label1 = trim(Input::get('custom_invoice_text_label1'));
|
||||||
$account->custom_invoice_text_label2 = trim(Input::get('custom_invoice_text_label2'));
|
$account->custom_invoice_text_label2 = trim(Input::get('custom_invoice_text_label2'));
|
||||||
|
$account->custom_invoice_item_label1 = trim(Input::get('custom_invoice_item_label1'));
|
||||||
|
$account->custom_invoice_item_label2 = trim(Input::get('custom_invoice_item_label2'));
|
||||||
|
|
||||||
$account->invoice_number_counter = Input::get('invoice_number_counter');
|
$account->invoice_number_counter = Input::get('invoice_number_counter');
|
||||||
$account->quote_number_prefix = Input::get('quote_number_prefix');
|
$account->quote_number_prefix = Input::get('quote_number_prefix');
|
||||||
@ -692,6 +694,7 @@ class AccountController extends BaseController
|
|||||||
$account->invoice_footer = Input::get('invoice_footer');
|
$account->invoice_footer = Input::get('invoice_footer');
|
||||||
$account->quote_terms = Input::get('quote_terms');
|
$account->quote_terms = Input::get('quote_terms');
|
||||||
$account->auto_convert_quote = Input::get('auto_convert_quote');
|
$account->auto_convert_quote = Input::get('auto_convert_quote');
|
||||||
|
$account->recurring_invoice_number_prefix = Input::get('recurring_invoice_number_prefix');
|
||||||
|
|
||||||
if (Input::has('recurring_hour')) {
|
if (Input::has('recurring_hour')) {
|
||||||
$account->recurring_hour = Input::get('recurring_hour');
|
$account->recurring_hour = Input::get('recurring_hour');
|
||||||
|
@ -251,7 +251,11 @@ class AppController extends BaseController
|
|||||||
'PaymentLibraries',
|
'PaymentLibraries',
|
||||||
'Fonts',
|
'Fonts',
|
||||||
'Banks',
|
'Banks',
|
||||||
'InvoiceStatus'
|
'InvoiceStatus',
|
||||||
|
'Currencies',
|
||||||
|
'DateFormats',
|
||||||
|
'InvoiceDesigns',
|
||||||
|
'PaymentTerms',
|
||||||
] as $seeder) {
|
] as $seeder) {
|
||||||
Artisan::call('db:seed', array('--force' => true, '--class' => "{$seeder}Seeder"));
|
Artisan::call('db:seed', array('--force' => true, '--class' => "{$seeder}Seeder"));
|
||||||
}
|
}
|
||||||
|
@ -114,11 +114,7 @@ class ReportController extends BaseController
|
|||||||
} else {
|
} else {
|
||||||
$params['columns'] = [];
|
$params['columns'] = [];
|
||||||
$params['displayData'] = [];
|
$params['displayData'] = [];
|
||||||
$params['reportTotals'] = [
|
$params['reportTotals'] = [];
|
||||||
'amount' => [],
|
|
||||||
'balance' => [],
|
|
||||||
'paid' => [],
|
|
||||||
];
|
|
||||||
$params['labels'] = [];
|
$params['labels'] = [];
|
||||||
$params['datasets'] = [];
|
$params['datasets'] = [];
|
||||||
$params['scaleStepWidth'] = 100;
|
$params['scaleStepWidth'] = 100;
|
||||||
|
@ -48,6 +48,9 @@ class StartupCheck
|
|||||||
$file = storage_path() . '/version.txt';
|
$file = storage_path() . '/version.txt';
|
||||||
$version = @file_get_contents($file);
|
$version = @file_get_contents($file);
|
||||||
if ($version != NINJA_VERSION) {
|
if ($version != NINJA_VERSION) {
|
||||||
|
if (version_compare(phpversion(), '5.5.9', '<')) {
|
||||||
|
dd('Please update PHP to >= 5.5.9');
|
||||||
|
}
|
||||||
$handle = fopen($file, 'w');
|
$handle = fopen($file, 'w');
|
||||||
fwrite($handle, NINJA_VERSION);
|
fwrite($handle, NINJA_VERSION);
|
||||||
fclose($handle);
|
fclose($handle);
|
||||||
|
@ -72,7 +72,7 @@ class Utils
|
|||||||
|
|
||||||
public static function requireHTTPS()
|
public static function requireHTTPS()
|
||||||
{
|
{
|
||||||
if (Request::root() === 'http://ninja.dev:8000') {
|
if (Request::root() === 'http://ninja.dev' || Request::root() === 'http://ninja.dev:8000') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,12 +455,16 @@ class Invoice extends EntityModel implements BalanceAffecting
|
|||||||
'show_item_taxes',
|
'show_item_taxes',
|
||||||
'custom_invoice_text_label1',
|
'custom_invoice_text_label1',
|
||||||
'custom_invoice_text_label2',
|
'custom_invoice_text_label2',
|
||||||
|
'custom_invoice_item_label1',
|
||||||
|
'custom_invoice_item_label2',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($this->invoice_items as $invoiceItem) {
|
foreach ($this->invoice_items as $invoiceItem) {
|
||||||
$invoiceItem->setVisible([
|
$invoiceItem->setVisible([
|
||||||
'product_key',
|
'product_key',
|
||||||
'notes',
|
'notes',
|
||||||
|
'custom_value1',
|
||||||
|
'custom_value2',
|
||||||
'cost',
|
'cost',
|
||||||
'qty',
|
'qty',
|
||||||
'tax_name',
|
'tax_name',
|
||||||
|
@ -74,8 +74,7 @@ class AccountRepository
|
|||||||
{
|
{
|
||||||
$data = $this->getAccountSearchData();
|
$data = $this->getAccountSearchData();
|
||||||
|
|
||||||
$type = trans('texts.navigation');
|
$data['navigation'] = $this->getNavigationSearchData();
|
||||||
$data[$type] = $this->getNavigationSearchData();
|
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@ -83,10 +82,10 @@ class AccountRepository
|
|||||||
private function getAccountSearchData()
|
private function getAccountSearchData()
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
trans('texts.clients') => [],
|
'clients' => [],
|
||||||
trans('texts.contacts') => [],
|
'contacts' => [],
|
||||||
trans('texts.invoices') => [],
|
'invoices' => [],
|
||||||
trans('texts.quotes') => [],
|
'quotes' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$clients = Client::scope()
|
$clients = Client::scope()
|
||||||
@ -95,26 +94,31 @@ class AccountRepository
|
|||||||
|
|
||||||
foreach ($clients as $client) {
|
foreach ($clients as $client) {
|
||||||
if ($client->name) {
|
if ($client->name) {
|
||||||
$data[trans('texts.clients')][] = [
|
$data['clients'][] = [
|
||||||
'value' => $client->name,
|
'value' => $client->name,
|
||||||
'tokens' => explode(' ', $client->name),
|
|
||||||
'url' => $client->present()->url,
|
'url' => $client->present()->url,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($client->contacts as $contact) {
|
foreach ($client->contacts as $contact) {
|
||||||
$data[trans('texts.contacts')][] = [
|
if ($contact->getFullName()) {
|
||||||
'value' => $contact->getDisplayName(),
|
$data['contacts'][] = [
|
||||||
'tokens' => explode(' ', $contact->getFullName() . ' ' . $contact->email),
|
'value' => $contact->getDisplayName(),
|
||||||
'url' => $client->present()->url,
|
'url' => $client->present()->url,
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
if ($contact->email) {
|
||||||
|
$data[trans('texts.contacts')][] = [
|
||||||
|
'value' => $contact->email,
|
||||||
|
'url' => $client->present()->url,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($client->invoices as $invoice) {
|
foreach ($client->invoices as $invoice) {
|
||||||
$entityType = $invoice->getEntityType();
|
$entityType = $invoice->getEntityType();
|
||||||
$data[trans("texts.{$entityType}s")][] = [
|
$data["{$entityType}s"][] = [
|
||||||
'value' => $invoice->getDisplayName() . ': ' . $client->getDisplayName(),
|
'value' => $invoice->getDisplayName() . ': ' . $client->getDisplayName(),
|
||||||
'tokens' => explode(' ', $invoice->invoice_number . ' ' . intval($invoice->invoice_number) . ' ' . $client->getDisplayName()),
|
|
||||||
'url' => $invoice->present()->url,
|
'url' => $invoice->present()->url,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ class InvoiceRepository extends BaseRepository
|
|||||||
|
|
||||||
foreach ($data['invoice_items'] as $item) {
|
foreach ($data['invoice_items'] as $item) {
|
||||||
$item = (array) $item;
|
$item = (array) $item;
|
||||||
if (!$item['cost'] && !$item['product_key'] && !$item['notes']) {
|
if (empty($item['cost']) && empty($item['product_key']) && empty($item['notes']) && empty($item['custom_value1']) && empty($item['custom_value2'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +439,13 @@ class InvoiceRepository extends BaseRepository
|
|||||||
$invoiceItem->qty = Utils::parseFloat($item['qty']);
|
$invoiceItem->qty = Utils::parseFloat($item['qty']);
|
||||||
$invoiceItem->tax_rate = 0;
|
$invoiceItem->tax_rate = 0;
|
||||||
|
|
||||||
|
if (isset($item['custom_value1'])) {
|
||||||
|
$invoiceItem->custom_value1 = $item['custom_value1'];
|
||||||
|
}
|
||||||
|
if (isset($item['custom_value2'])) {
|
||||||
|
$invoiceItem->custom_value2 = $item['custom_value2'];
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($item['tax_rate']) && isset($item['tax_name']) && $item['tax_name']) {
|
if (isset($item['tax_rate']) && isset($item['tax_name']) && $item['tax_name']) {
|
||||||
$invoiceItem['tax_rate'] = Utils::parseFloat($item['tax_rate']);
|
$invoiceItem['tax_rate'] = Utils::parseFloat($item['tax_rate']);
|
||||||
$invoiceItem['tax_name'] = trim($item['tax_name']);
|
$invoiceItem['tax_name'] = trim($item['tax_name']);
|
||||||
@ -603,7 +610,7 @@ class InvoiceRepository extends BaseRepository
|
|||||||
$invoice = Invoice::createNew($recurInvoice);
|
$invoice = Invoice::createNew($recurInvoice);
|
||||||
$invoice->client_id = $recurInvoice->client_id;
|
$invoice->client_id = $recurInvoice->client_id;
|
||||||
$invoice->recurring_invoice_id = $recurInvoice->id;
|
$invoice->recurring_invoice_id = $recurInvoice->id;
|
||||||
$invoice->invoice_number = 'R'.$recurInvoice->account->getNextInvoiceNumber($recurInvoice);
|
$invoice->invoice_number = $recurInvoice->account->recurring_invoice_number_prefix . $recurInvoice->account->getNextInvoiceNumber($recurInvoice);
|
||||||
$invoice->amount = $recurInvoice->amount;
|
$invoice->amount = $recurInvoice->amount;
|
||||||
$invoice->balance = $recurInvoice->amount;
|
$invoice->balance = $recurInvoice->amount;
|
||||||
$invoice->invoice_date = date_create()->format('Y-m-d');
|
$invoice->invoice_date = date_create()->format('Y-m-d');
|
||||||
|
@ -4,7 +4,6 @@ use stdClass;
|
|||||||
use Utils;
|
use Utils;
|
||||||
use URL;
|
use URL;
|
||||||
use Hash;
|
use Hash;
|
||||||
use App\Models\Gateway;
|
|
||||||
use App\Models\BankSubaccount;
|
use App\Models\BankSubaccount;
|
||||||
use App\Models\Vendor;
|
use App\Models\Vendor;
|
||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
@ -37,7 +36,7 @@ class BankAccountService extends BaseService
|
|||||||
|
|
||||||
public function loadBankAccounts($bankId, $username, $password, $includeTransactions = true)
|
public function loadBankAccounts($bankId, $username, $password, $includeTransactions = true)
|
||||||
{
|
{
|
||||||
if ( ! $bankId || ! $username || ! $password) {
|
if (! $bankId || ! $username || ! $password) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,12 +46,13 @@ class BankAccountService extends BaseService
|
|||||||
->withTrashed()
|
->withTrashed()
|
||||||
->get(['transaction_id'])
|
->get(['transaction_id'])
|
||||||
->toArray();
|
->toArray();
|
||||||
$expenses = array_flip(array_map(function($val) {
|
$expenses = array_flip(array_map(function ($val) {
|
||||||
return $val['transaction_id'];
|
return $val['transaction_id'];
|
||||||
}, $expenses));
|
}, $expenses));
|
||||||
|
|
||||||
|
$vendorMap = $this->createVendorMap();
|
||||||
$bankAccounts = BankSubaccount::scope()
|
$bankAccounts = BankSubaccount::scope()
|
||||||
->whereHas('bank_account', function($query) use ($bankId) {
|
->whereHas('bank_account', function ($query) use ($bankId) {
|
||||||
$query->where('bank_id', '=', $bankId);
|
$query->where('bank_id', '=', $bankId);
|
||||||
})
|
})
|
||||||
->get();
|
->get();
|
||||||
@ -64,13 +64,13 @@ class BankAccountService extends BaseService
|
|||||||
$finance = new Finance();
|
$finance = new Finance();
|
||||||
$finance->banks[$bankId] = $bank->getOFXBank($finance);
|
$finance->banks[$bankId] = $bank->getOFXBank($finance);
|
||||||
$finance->banks[$bankId]->logins[] = new Login($finance->banks[$bankId], $username, $password);
|
$finance->banks[$bankId]->logins[] = new Login($finance->banks[$bankId], $username, $password);
|
||||||
|
|
||||||
foreach ($finance->banks as $bank) {
|
foreach ($finance->banks as $bank) {
|
||||||
foreach ($bank->logins as $login) {
|
foreach ($bank->logins as $login) {
|
||||||
$login->setup();
|
$login->setup();
|
||||||
foreach ($login->accounts as $account) {
|
foreach ($login->accounts as $account) {
|
||||||
$account->setup($includeTransactions);
|
$account->setup($includeTransactions);
|
||||||
if ($account = $this->parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions)) {
|
if ($account = $this->parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions, $vendorMap)) {
|
||||||
$data[] = $account;
|
$data[] = $account;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,9 +83,9 @@ class BankAccountService extends BaseService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions)
|
private function parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions, $vendorMap)
|
||||||
{
|
{
|
||||||
$obj = new stdClass;
|
$obj = new stdClass();
|
||||||
$obj->account_name = '';
|
$obj->account_name = '';
|
||||||
|
|
||||||
// look up bank account name
|
// look up bank account name
|
||||||
@ -106,7 +106,7 @@ class BankAccountService extends BaseService
|
|||||||
$obj->balance = Utils::formatMoney($account->ledgerBalance, CURRENCY_DOLLAR);
|
$obj->balance = Utils::formatMoney($account->ledgerBalance, CURRENCY_DOLLAR);
|
||||||
|
|
||||||
if ($includeTransactions) {
|
if ($includeTransactions) {
|
||||||
$ofxParser = new \OfxParser\Parser;
|
$ofxParser = new \OfxParser\Parser();
|
||||||
$ofx = $ofxParser->loadFromString($account->response);
|
$ofx = $ofxParser->loadFromString($account->response);
|
||||||
|
|
||||||
$obj->start_date = $ofx->BankAccount->Statement->startDate;
|
$obj->start_date = $ofx->BankAccount->Statement->startDate;
|
||||||
@ -121,7 +121,13 @@ class BankAccountService extends BaseService
|
|||||||
if ($transaction->amount >= 0) {
|
if ($transaction->amount >= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$transaction->vendor = $this->prepareValue(substr($transaction->name, 0, 20));
|
|
||||||
|
// if vendor has already been imported use current name
|
||||||
|
$vendorName = trim(substr($transaction->name, 0, 20));
|
||||||
|
$key = strtolower($vendorName);
|
||||||
|
$vendor = isset($vendorMap[$key]) ? $vendorMap[$key] : null;
|
||||||
|
|
||||||
|
$transaction->vendor = $vendor ? $vendor->name : $this->prepareValue($vendorName);
|
||||||
$transaction->info = $this->prepareValue(substr($transaction->name, 20));
|
$transaction->info = $this->prepareValue(substr($transaction->name, 20));
|
||||||
$transaction->memo = $this->prepareValue($transaction->memo);
|
$transaction->memo = $this->prepareValue($transaction->memo);
|
||||||
$transaction->date = \Auth::user()->account->formatDate($transaction->date);
|
$transaction->date = \Auth::user()->account->formatDate($transaction->date);
|
||||||
@ -133,15 +139,13 @@ class BankAccountService extends BaseService
|
|||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function prepareValue($value) {
|
private function prepareValue($value)
|
||||||
|
{
|
||||||
return ucwords(strtolower(trim($value)));
|
return ucwords(strtolower(trim($value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function importExpenses($bankId, $input) {
|
private function createVendorMap()
|
||||||
$countVendors = 0;
|
{
|
||||||
$countExpenses = 0;
|
|
||||||
|
|
||||||
// create a vendor map
|
|
||||||
$vendorMap = [];
|
$vendorMap = [];
|
||||||
$vendors = Vendor::scope()
|
$vendors = Vendor::scope()
|
||||||
->withTrashed()
|
->withTrashed()
|
||||||
@ -151,6 +155,15 @@ class BankAccountService extends BaseService
|
|||||||
$vendorMap[strtolower($vendor->transaction_name)] = $vendor;
|
$vendorMap[strtolower($vendor->transaction_name)] = $vendor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $vendorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importExpenses($bankId, $input)
|
||||||
|
{
|
||||||
|
$vendorMap = $this->createVendorMap();
|
||||||
|
$countVendors = 0;
|
||||||
|
$countExpenses = 0;
|
||||||
|
|
||||||
foreach ($input as $transaction) {
|
foreach ($input as $transaction) {
|
||||||
$vendorName = $transaction['vendor'];
|
$vendorName = $transaction['vendor'];
|
||||||
$key = strtolower($vendorName);
|
$key = strtolower($vendorName);
|
||||||
@ -165,7 +178,7 @@ class BankAccountService extends BaseService
|
|||||||
$field => $info,
|
$field => $info,
|
||||||
'name' => $vendorName,
|
'name' => $vendorName,
|
||||||
'transaction_name' => $transaction['vendor_orig'],
|
'transaction_name' => $transaction['vendor_orig'],
|
||||||
'vendorcontact' => []
|
'vendorcontact' => [],
|
||||||
]);
|
]);
|
||||||
$vendorMap[$key] = $vendor;
|
$vendorMap[$key] = $vendor;
|
||||||
$vendorMap[$transaction['vendor_orig']] = $vendor;
|
$vendorMap[$transaction['vendor_orig']] = $vendor;
|
||||||
@ -191,7 +204,8 @@ class BankAccountService extends BaseService
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function determineInfoField($value) {
|
private function determineInfoField($value)
|
||||||
|
{
|
||||||
if (preg_match("/^[0-9\-\(\)\.]+$/", $value)) {
|
if (preg_match("/^[0-9\-\(\)\.]+$/", $value)) {
|
||||||
return 'work_phone';
|
return 'work_phone';
|
||||||
} elseif (strpos($value, '.') !== false) {
|
} elseif (strpos($value, '.') !== false) {
|
||||||
@ -215,7 +229,7 @@ class BankAccountService extends BaseService
|
|||||||
'bank_name',
|
'bank_name',
|
||||||
function ($model) {
|
function ($model) {
|
||||||
return link_to("bank_accounts/{$model->public_id}/edit", $model->bank_name);
|
return link_to("bank_accounts/{$model->public_id}/edit", $model->bank_name);
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'bank_library_id',
|
'bank_library_id',
|
||||||
@ -233,9 +247,8 @@ class BankAccountService extends BaseService
|
|||||||
uctrans('texts.edit_bank_account'),
|
uctrans('texts.edit_bank_account'),
|
||||||
function ($model) {
|
function ($model) {
|
||||||
return URL::to("bank_accounts/{$model->public_id}/edit");
|
return URL::to("bank_accounts/{$model->public_id}/edit");
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php namespace app\Services;
|
<?php namespace App\Services;
|
||||||
|
|
||||||
use stdClass;
|
use stdClass;
|
||||||
use Excel;
|
use Excel;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"underscore": "1.7.0",
|
"underscore": "1.7.0",
|
||||||
"jspdf": "1.0.272",
|
"jspdf": "1.0.272",
|
||||||
"bootstrap-datepicker": "1.4.0",
|
"bootstrap-datepicker": "1.4.0",
|
||||||
"typeahead.js": "0.9.3",
|
"typeahead.js": "0.11.1",
|
||||||
"accounting": "0.3.2",
|
"accounting": "0.3.2",
|
||||||
"spectrum": "1.3.4",
|
"spectrum": "1.3.4",
|
||||||
"d3": "3.4.11",
|
"d3": "3.4.11",
|
||||||
@ -25,7 +25,8 @@
|
|||||||
"moment-timezone": "~0.4.0",
|
"moment-timezone": "~0.4.0",
|
||||||
"quill": "~0.20.0",
|
"quill": "~0.20.0",
|
||||||
"datetimepicker": "~2.4.5",
|
"datetimepicker": "~2.4.5",
|
||||||
"stacktrace-js": "~1.0.1"
|
"stacktrace-js": "~1.0.1",
|
||||||
|
"fuse.js": "~2.0.2"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"jquery": "~1.11"
|
"jquery": "~1.11"
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddCustomInvoiceFields extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function($table) {
|
||||||
|
$table->string('custom_invoice_item_label1')->nullable();
|
||||||
|
$table->string('custom_invoice_item_label2')->nullable();
|
||||||
|
$table->string('recurring_invoice_number_prefix')->default('R');
|
||||||
|
$table->boolean('enable_client_portal')->default(true);
|
||||||
|
$table->text('invoice_fields')->nullable();
|
||||||
|
$table->text('devices')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('invoice_items', function($table) {
|
||||||
|
$table->string('custom_value1')->nullable();
|
||||||
|
$table->string('custom_value2')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function($table) {
|
||||||
|
$table->dropColumn('custom_invoice_item_label1');
|
||||||
|
$table->dropColumn('custom_invoice_item_label2');
|
||||||
|
$table->dropColumn('recurring_invoice_number_prefix');
|
||||||
|
$table->dropColumn('enable_client_portal');
|
||||||
|
$table->dropColumn('invoice_fields');
|
||||||
|
$table->dropColumn('devices');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('accounts', function($table) {
|
||||||
|
$table->dropColumn('custom_value1');
|
||||||
|
$table->dropColumn('custom_value2');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||||
|
use App\Models\Country;
|
||||||
|
|
||||||
class CountriesSeeder extends Seeder {
|
class CountriesSeeder extends Seeder {
|
||||||
|
|
||||||
@ -13,25 +14,156 @@ class CountriesSeeder extends Seeder {
|
|||||||
//Empty the countries table
|
//Empty the countries table
|
||||||
DB::table('countries')->delete();
|
DB::table('countries')->delete();
|
||||||
|
|
||||||
//Get all of the countries
|
if (DB::table('countries')->count() == 0) {
|
||||||
$countries = Countries::getList();
|
//Get all of the countries
|
||||||
foreach ($countries as $countryId => $country){
|
$countries = Countries::getList();
|
||||||
DB::table('countries')->insert(array(
|
foreach ($countries as $countryId => $country){
|
||||||
'id' => $countryId,
|
DB::table('countries')->insert(array(
|
||||||
'capital' => ((isset($country['capital'])) ? $country['capital'] : null),
|
'id' => $countryId,
|
||||||
'citizenship' => ((isset($country['citizenship'])) ? $country['citizenship'] : null),
|
'capital' => ((isset($country['capital'])) ? $country['capital'] : null),
|
||||||
'country_code' => $country['country-code'],
|
'citizenship' => ((isset($country['citizenship'])) ? $country['citizenship'] : null),
|
||||||
'currency' => ((isset($country['currency'])) ? $country['currency'] : null),
|
'country_code' => $country['country-code'],
|
||||||
'currency_code' => ((isset($country['currency_code'])) ? $country['currency_code'] : null),
|
'currency' => ((isset($country['currency'])) ? $country['currency'] : null),
|
||||||
'currency_sub_unit' => ((isset($country['currency_sub_unit'])) ? $country['currency_sub_unit'] : null),
|
'currency_code' => ((isset($country['currency_code'])) ? $country['currency_code'] : null),
|
||||||
'full_name' => ((isset($country['full_name'])) ? $country['full_name'] : null),
|
'currency_sub_unit' => ((isset($country['currency_sub_unit'])) ? $country['currency_sub_unit'] : null),
|
||||||
'iso_3166_2' => $country['iso_3166_2'],
|
'full_name' => ((isset($country['full_name'])) ? $country['full_name'] : null),
|
||||||
'iso_3166_3' => $country['iso_3166_3'],
|
'iso_3166_2' => $country['iso_3166_2'],
|
||||||
'name' => $country['name'],
|
'iso_3166_3' => $country['iso_3166_3'],
|
||||||
'region_code' => $country['region-code'],
|
'name' => $country['name'],
|
||||||
'sub_region_code' => $country['sub-region-code'],
|
'region_code' => $country['region-code'],
|
||||||
'eea' => (bool)$country['eea']
|
'sub_region_code' => $country['sub-region-code'],
|
||||||
));
|
'eea' => (bool)$country['eea']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: http://www.bitboost.com/ref/international-address-formats.html
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Linguistic_issues_concerning_the_euro
|
||||||
|
$countries = [
|
||||||
|
'AR' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'AT' => [ // Austria
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'BE' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'BG' => [ // Belgium
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'CH' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'CZ' => [ // Czech Republic
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'DE' => [ // Germany
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'DK' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'EE' => [ // Estonia
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'ES' => [ // Spain
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'FI' => [ // Finland
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'FR' => [ // France
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'GR' => [ // Greece
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'HR' => [ // Croatia
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'HU' => [ // Hungary
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'GL' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'IE' => [ // Ireland
|
||||||
|
'thousand_separator' => ',',
|
||||||
|
'decimal_separator' => '.',
|
||||||
|
],
|
||||||
|
'IL' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'IS' => [ // Iceland
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'IT' => [ // Italy
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'LT' => [ // Lithuania
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'LU' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'MY' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'MX' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'NL' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
'PL' => [ // Poland
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'PT' => [ // Portugal
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'RO' => [ // Romania
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'SE' => [ // Sweden
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'SI' => [ // Slovenia
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'SK' => [ // Slovakia
|
||||||
|
'swap_currency_symbol' => true,
|
||||||
|
],
|
||||||
|
'UY' => [
|
||||||
|
'swap_postal_code' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($countries as $code => $data) {
|
||||||
|
$country = Country::where('iso_3166_2', '=', $code)->first();
|
||||||
|
if (isset($data['swap_postal_code'])) {
|
||||||
|
$country->swap_postal_code = true;
|
||||||
|
}
|
||||||
|
if (isset($data['swap_currency_symbol'])) {
|
||||||
|
$country->swap_currency_symbol = true;
|
||||||
|
}
|
||||||
|
if (isset($data['thousand_separator'])) {
|
||||||
|
$country->thousand_separator = $data['thousand_separator'];
|
||||||
|
}
|
||||||
|
if (isset($data['decimal_separator'])) {
|
||||||
|
$country->decimal_separator = $data['decimal_separator'];
|
||||||
|
}
|
||||||
|
$country->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
69
database/seeds/CurrenciesSeeder.php
Normal file
69
database/seeds/CurrenciesSeeder.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Currency;
|
||||||
|
|
||||||
|
class CurrenciesSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
$currencies = [
|
||||||
|
['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => '', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'West African Franc', 'code' => 'XOF', 'symbol' => 'CFA ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Chinese Renminbi', 'code' => 'CNY', 'symbol' => 'RMB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Rwandan Franc', 'code' => 'RWF', 'symbol' => 'RF ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Tanzanian Shilling', 'code' => 'TZS', 'symbol' => 'TSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Netherlands Antillean Guilder', 'code' => 'ANG', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Trinidad and Tobago Dollar', 'code' => 'TTD', 'symbol' => 'TT$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'East Caribbean Dollar', 'code' => 'XCD', 'symbol' => 'EC$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Ghanaian Cedi', 'code' => 'GHS', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Bulgarian Lev', 'code' => 'BGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Aruban Florin', 'code' => 'AWG', 'symbol' => 'Afl. ', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Turkish Lira', 'code' => 'TRY', 'symbol' => 'TL ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
||||||
|
['name' => 'Romanian New Leu', 'code' => 'RON', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($currencies as $currency) {
|
||||||
|
$record = Currency::whereCode($currency['code'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->name = $currency['name'];
|
||||||
|
$record->symbol = $currency['symbol'];
|
||||||
|
$record->thousand_separator = $currency['thousand_separator'];
|
||||||
|
$record->decimal_separator = $currency['decimal_separator'];
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
|
Currency::create($currency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,5 +19,9 @@ class DatabaseSeeder extends Seeder
|
|||||||
$this->call('FontsSeeder');
|
$this->call('FontsSeeder');
|
||||||
$this->call('BanksSeeder');
|
$this->call('BanksSeeder');
|
||||||
$this->call('InvoiceStatusSeeder');
|
$this->call('InvoiceStatusSeeder');
|
||||||
|
$this->call('CurrenciesSeeder');
|
||||||
|
$this->call('DateFormatsSeeder');
|
||||||
|
$this->call('InvoiceDesignsSeeder');
|
||||||
|
$this->call('PaymentTermsSeeder');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
102
database/seeds/DateFormatsSeeder.php
Normal file
102
database/seeds/DateFormatsSeeder.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\DateFormat;
|
||||||
|
use App\Models\DatetimeFormat;
|
||||||
|
|
||||||
|
class DateFormatsSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
// Date formats
|
||||||
|
$formats = [
|
||||||
|
['format' => 'd/M/Y', 'picker_format' => 'dd/M/yyyy', 'label' => '10/Mar/2013'],
|
||||||
|
['format' => 'd-M-Y', 'picker_format' => 'dd-M-yyyy', 'label' => '10-Mar-2013'],
|
||||||
|
['format' => 'd/F/Y', 'picker_format' => 'dd/MM/yyyy', 'label' => '10/March/2013'],
|
||||||
|
['format' => 'd-F-Y', 'picker_format' => 'dd-MM-yyyy', 'label' => '10-March-2013'],
|
||||||
|
['format' => 'M j, Y', 'picker_format' => 'M d, yyyy', 'label' => 'Mar 10, 2013'],
|
||||||
|
['format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013'],
|
||||||
|
['format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013'],
|
||||||
|
['format' => 'Y-m-d', 'picker_format' => 'yyyy-mm-dd', 'label' => '2013-03-10'],
|
||||||
|
['format' => 'd-m-Y', 'picker_format' => 'dd-mm-yyyy', 'label' => '20-03-2013'],
|
||||||
|
['format' => 'm/d/Y', 'picker_format' => 'mm/dd/yyyy', 'label' => '03/20/2013']
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
$record = DateFormat::whereLabel($format['label'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->format = $format['format'];
|
||||||
|
$record->picker_format = $format['picker_format'];
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
|
DateFormat::create($format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date/time formats
|
||||||
|
$formats = [
|
||||||
|
[
|
||||||
|
'format' => 'd/M/Y g:i a',
|
||||||
|
'format_moment' => 'DD/MMM/YYYY h:mm:ss a',
|
||||||
|
'label' => '10/Mar/2013'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'd-M-Y g:i a',
|
||||||
|
'format_moment' => 'DD-MMM-YYYY h:mm:ss a',
|
||||||
|
'label' => '10-Mar-2013'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'd/F/Y g:i a',
|
||||||
|
'format_moment' => 'DD/MMMM/YYYY h:mm:ss a',
|
||||||
|
'label' => '10/March/2013'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'd-F-Y g:i a',
|
||||||
|
'format_moment' => 'DD-MMMM-YYYY h:mm:ss a',
|
||||||
|
'label' => '10-March-2013'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'M j, Y g:i a',
|
||||||
|
'format_moment' => 'MMM D, YYYY h:mm:ss a',
|
||||||
|
'label' => 'Mar 10, 2013 6:15 pm'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'F j, Y g:i a',
|
||||||
|
'format_moment' => 'MMMM D, YYYY h:mm:ss a',
|
||||||
|
'label' => 'March 10, 2013 6:15 pm'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'D M jS, Y g:i a',
|
||||||
|
'format_moment' => 'ddd MMM Do, YYYY h:mm:ss a',
|
||||||
|
'label' => 'Mon March 10th, 2013 6:15 pm'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'Y-m-d g:i a',
|
||||||
|
'format_moment' => 'YYYY-MMM-DD h:mm:ss a',
|
||||||
|
'label' => '2013-03-10 6:15 pm'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'd-m-Y g:i a',
|
||||||
|
'format_moment' => 'DD-MM-YYYY h:mm:ss a',
|
||||||
|
'label' => '20-03-2013 6:15 pm'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'format' => 'm/d/Y g:i a',
|
||||||
|
'format_moment' => 'MM/DD/YYYY h:mm:ss a',
|
||||||
|
'label' => '03/20/2013 6:15 pm'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
$record = DatetimeFormat::whereLabel($format['label'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->format = $format['format'];
|
||||||
|
$record->format_moment = $format['format_moment'];
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
|
DatetimeFormat::create($format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
database/seeds/InvoiceDesignsSeeder.php
Normal file
43
database/seeds/InvoiceDesignsSeeder.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\InvoiceDesign;
|
||||||
|
|
||||||
|
class InvoiceDesignsSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
$designs = [
|
||||||
|
'Clean',
|
||||||
|
'Bold',
|
||||||
|
'Modern',
|
||||||
|
'Plain',
|
||||||
|
'Business',
|
||||||
|
'Creative',
|
||||||
|
'Elegant',
|
||||||
|
'Hipster',
|
||||||
|
'Playful',
|
||||||
|
'Photo',
|
||||||
|
];
|
||||||
|
|
||||||
|
for ($i=0; $i<count($designs); $i++) {
|
||||||
|
$design = $designs[$i];
|
||||||
|
$fileName = storage_path() . '/templates/' . strtolower($design) . '.js';
|
||||||
|
if (file_exists($fileName)) {
|
||||||
|
$pdfmake = file_get_contents($fileName);
|
||||||
|
if ($pdfmake) {
|
||||||
|
$record = InvoiceDesign::whereName($design)->first();
|
||||||
|
if (!$record) {
|
||||||
|
$record = new InvoiceDesign;
|
||||||
|
$record->id = $i + 1;
|
||||||
|
$record->name = $design;
|
||||||
|
}
|
||||||
|
$record->pdfmake = $pdfmake;
|
||||||
|
$record->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,16 +14,6 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
Eloquent::unguard();
|
Eloquent::unguard();
|
||||||
|
|
||||||
$this->createGateways();
|
|
||||||
$this->createPaymentTerms();
|
|
||||||
$this->createDateFormats();
|
|
||||||
$this->createDatetimeFormats();
|
|
||||||
$this->createInvoiceDesigns();
|
|
||||||
$this->updateLocalization();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createGateways() {
|
|
||||||
|
|
||||||
$gateways = [
|
$gateways = [
|
||||||
['name' => 'BeanStream', 'provider' => 'BeanStream', 'payment_library_id' => 2],
|
['name' => 'BeanStream', 'provider' => 'BeanStream', 'payment_library_id' => 2],
|
||||||
['name' => 'Psigate', 'provider' => 'Psigate', 'payment_library_id' => 2],
|
['name' => 'Psigate', 'provider' => 'Psigate', 'payment_library_id' => 2],
|
||||||
@ -71,334 +61,4 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createPaymentTerms() {
|
|
||||||
|
|
||||||
$paymentTerms = [
|
|
||||||
['num_days' => -1, 'name' => 'Net 0'],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($paymentTerms as $paymentTerm) {
|
|
||||||
if (!DB::table('payment_terms')->where('name', '=', $paymentTerm['name'])->get()) {
|
|
||||||
PaymentTerm::create($paymentTerm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$currencies = [
|
|
||||||
['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => '', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'West African Franc', 'code' => 'XOF', 'symbol' => 'CFA ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Chinese Renminbi', 'code' => 'CNY', 'symbol' => 'RMB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Rwandan Franc', 'code' => 'RWF', 'symbol' => 'RF ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Tanzanian Shilling', 'code' => 'TZS', 'symbol' => 'TSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Netherlands Antillean Guilder', 'code' => 'ANG', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Trinidad and Tobago Dollar', 'code' => 'TTD', 'symbol' => 'TT$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'East Caribbean Dollar', 'code' => 'XCD', 'symbol' => 'EC$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Ghanaian Cedi', 'code' => 'GHS', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Bulgarian Lev', 'code' => 'BGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Aruban Florin', 'code' => 'AWG', 'symbol' => 'Afl. ', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'],
|
|
||||||
['name' => 'Turkish Lira', 'code' => 'TRY', 'symbol' => 'TL ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
|
|
||||||
['name' => 'Romanian New Leu', 'code' => 'RON', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($currencies as $currency) {
|
|
||||||
$record = Currency::whereCode($currency['code'])->first();
|
|
||||||
if ($record) {
|
|
||||||
$record->name = $currency['name'];
|
|
||||||
$record->symbol = $currency['symbol'];
|
|
||||||
$record->thousand_separator = $currency['thousand_separator'];
|
|
||||||
$record->decimal_separator = $currency['decimal_separator'];
|
|
||||||
$record->save();
|
|
||||||
} else {
|
|
||||||
Currency::create($currency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createDateFormats() {
|
|
||||||
|
|
||||||
$formats = [
|
|
||||||
['format' => 'd/M/Y', 'picker_format' => 'dd/M/yyyy', 'label' => '10/Mar/2013'],
|
|
||||||
['format' => 'd-M-Y', 'picker_format' => 'dd-M-yyyy', 'label' => '10-Mar-2013'],
|
|
||||||
['format' => 'd/F/Y', 'picker_format' => 'dd/MM/yyyy', 'label' => '10/March/2013'],
|
|
||||||
['format' => 'd-F-Y', 'picker_format' => 'dd-MM-yyyy', 'label' => '10-March-2013'],
|
|
||||||
['format' => 'M j, Y', 'picker_format' => 'M d, yyyy', 'label' => 'Mar 10, 2013'],
|
|
||||||
['format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013'],
|
|
||||||
['format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013'],
|
|
||||||
['format' => 'Y-m-d', 'picker_format' => 'yyyy-mm-dd', 'label' => '2013-03-10'],
|
|
||||||
['format' => 'd-m-Y', 'picker_format' => 'dd-mm-yyyy', 'label' => '20-03-2013'],
|
|
||||||
['format' => 'm/d/Y', 'picker_format' => 'mm/dd/yyyy', 'label' => '03/20/2013']
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($formats as $format) {
|
|
||||||
$record = DateFormat::whereLabel($format['label'])->first();
|
|
||||||
if ($record) {
|
|
||||||
$record->format = $format['format'];
|
|
||||||
$record->picker_format = $format['picker_format'];
|
|
||||||
$record->save();
|
|
||||||
} else {
|
|
||||||
DateFormat::create($format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createDatetimeFormats() {
|
|
||||||
|
|
||||||
$formats = [
|
|
||||||
[
|
|
||||||
'format' => 'd/M/Y g:i a',
|
|
||||||
'format_moment' => 'DD/MMM/YYYY h:mm:ss a',
|
|
||||||
'label' => '10/Mar/2013'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'd-M-Y g:i a',
|
|
||||||
'format_moment' => 'DD-MMM-YYYY h:mm:ss a',
|
|
||||||
'label' => '10-Mar-2013'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'd/F/Y g:i a',
|
|
||||||
'format_moment' => 'DD/MMMM/YYYY h:mm:ss a',
|
|
||||||
'label' => '10/March/2013'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'd-F-Y g:i a',
|
|
||||||
'format_moment' => 'DD-MMMM-YYYY h:mm:ss a',
|
|
||||||
'label' => '10-March-2013'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'M j, Y g:i a',
|
|
||||||
'format_moment' => 'MMM D, YYYY h:mm:ss a',
|
|
||||||
'label' => 'Mar 10, 2013 6:15 pm'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'F j, Y g:i a',
|
|
||||||
'format_moment' => 'MMMM D, YYYY h:mm:ss a',
|
|
||||||
'label' => 'March 10, 2013 6:15 pm'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'D M jS, Y g:i a',
|
|
||||||
'format_moment' => 'ddd MMM Do, YYYY h:mm:ss a',
|
|
||||||
'label' => 'Mon March 10th, 2013 6:15 pm'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'Y-m-d g:i a',
|
|
||||||
'format_moment' => 'YYYY-MMM-DD h:mm:ss a',
|
|
||||||
'label' => '2013-03-10 6:15 pm'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'd-m-Y g:i a',
|
|
||||||
'format_moment' => 'DD-MM-YYYY h:mm:ss a',
|
|
||||||
'label' => '20-03-2013 6:15 pm'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'format' => 'm/d/Y g:i a',
|
|
||||||
'format_moment' => 'MM/DD/YYYY h:mm:ss a',
|
|
||||||
'label' => '03/20/2013 6:15 pm'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($formats as $format) {
|
|
||||||
$record = DatetimeFormat::whereLabel($format['label'])->first();
|
|
||||||
if ($record) {
|
|
||||||
$record->format = $format['format'];
|
|
||||||
$record->format_moment = $format['format_moment'];
|
|
||||||
$record->save();
|
|
||||||
} else {
|
|
||||||
DatetimeFormat::create($format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createInvoiceDesigns() {
|
|
||||||
$designs = [
|
|
||||||
'Clean',
|
|
||||||
'Bold',
|
|
||||||
'Modern',
|
|
||||||
'Plain',
|
|
||||||
'Business',
|
|
||||||
'Creative',
|
|
||||||
'Elegant',
|
|
||||||
'Hipster',
|
|
||||||
'Playful',
|
|
||||||
'Photo',
|
|
||||||
];
|
|
||||||
|
|
||||||
for ($i=0; $i<count($designs); $i++) {
|
|
||||||
$design = $designs[$i];
|
|
||||||
$fileName = storage_path() . '/templates/' . strtolower($design) . '.js';
|
|
||||||
if (file_exists($fileName)) {
|
|
||||||
$pdfmake = file_get_contents($fileName);
|
|
||||||
if ($pdfmake) {
|
|
||||||
$record = InvoiceDesign::whereName($design)->first();
|
|
||||||
if (!$record) {
|
|
||||||
$record = new InvoiceDesign;
|
|
||||||
$record->id = $i + 1;
|
|
||||||
$record->name = $design;
|
|
||||||
}
|
|
||||||
$record->pdfmake = $pdfmake;
|
|
||||||
$record->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function updateLocalization() {
|
|
||||||
// Source: http://www.bitboost.com/ref/international-address-formats.html
|
|
||||||
// Source: https://en.wikipedia.org/wiki/Linguistic_issues_concerning_the_euro
|
|
||||||
$countries = [
|
|
||||||
'AR' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'AT' => [ // Austria
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'BE' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'BG' => [ // Belgium
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'CH' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'CZ' => [ // Czech Republic
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'DE' => [ // Germany
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'DK' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'EE' => [ // Estonia
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'ES' => [ // Spain
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'FI' => [ // Finland
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'FR' => [ // France
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'GR' => [ // Greece
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'HR' => [ // Croatia
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'HU' => [ // Hungary
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'GL' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'IE' => [ // Ireland
|
|
||||||
'thousand_separator' => ',',
|
|
||||||
'decimal_separator' => '.',
|
|
||||||
],
|
|
||||||
'IL' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'IS' => [ // Iceland
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'IT' => [ // Italy
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'LT' => [ // Lithuania
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'LU' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'MY' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'MX' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'NL' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
'PL' => [ // Poland
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'PT' => [ // Portugal
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'RO' => [ // Romania
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'SE' => [ // Sweden
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'SI' => [ // Slovenia
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'SK' => [ // Slovakia
|
|
||||||
'swap_currency_symbol' => true,
|
|
||||||
],
|
|
||||||
'UY' => [
|
|
||||||
'swap_postal_code' => true,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($countries as $code => $data) {
|
|
||||||
$country = Country::where('iso_3166_2', '=', $code)->first();
|
|
||||||
if (isset($data['swap_postal_code'])) {
|
|
||||||
$country->swap_postal_code = true;
|
|
||||||
}
|
|
||||||
if (isset($data['swap_currency_symbol'])) {
|
|
||||||
$country->swap_currency_symbol = true;
|
|
||||||
}
|
|
||||||
if (isset($data['thousand_separator'])) {
|
|
||||||
$country->thousand_separator = $data['thousand_separator'];
|
|
||||||
}
|
|
||||||
if (isset($data['decimal_separator'])) {
|
|
||||||
$country->decimal_separator = $data['decimal_separator'];
|
|
||||||
}
|
|
||||||
$country->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
22
database/seeds/PaymentTermsSeeder.php
Normal file
22
database/seeds/PaymentTermsSeeder.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\PaymentTerm;
|
||||||
|
|
||||||
|
class PaymentTermsSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
$paymentTerms = [
|
||||||
|
['num_days' => -1, 'name' => 'Net 0'],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($paymentTerms as $paymentTerm) {
|
||||||
|
if (!DB::table('payment_terms')->where('name', '=', $paymentTerm['name'])->get()) {
|
||||||
|
PaymentTerm::create($paymentTerm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
125
public/css/built.css
vendored
125
public/css/built.css
vendored
@ -2054,89 +2054,76 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
|
|||||||
.combobox-container:not(.combobox-selected) .fa-times {
|
.combobox-container:not(.combobox-selected) .fa-times {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.twitter-typeahead .tt-query,
|
/**********************************************************
|
||||||
.twitter-typeahead .tt-hint {
|
* typeahead.js v0.11.1 - twitter bootstrap v3.3.5 *
|
||||||
margin-bottom: 0;
|
**********************************************************/
|
||||||
|
|
||||||
|
/*root typeahead class*/
|
||||||
|
.twitter-typeahead {
|
||||||
|
display: inherit !important;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-dropdown-menu {
|
.twitter-typeahead .tt-input[disabled] {
|
||||||
min-width: 160px;
|
background-color : #eeeeee !important;
|
||||||
margin-top: 2px;
|
|
||||||
padding: 5px 0;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border: 1px solid rgba(0,0,0,.2);
|
|
||||||
*border-right-width: 2px;
|
|
||||||
*border-bottom-width: 2px;
|
|
||||||
-webkit-border-radius: 6px;
|
|
||||||
-moz-border-radius: 6px;
|
|
||||||
border-radius: 6px;
|
|
||||||
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
-webkit-background-clip: padding-box;
|
|
||||||
-moz-background-clip: padding;
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion {
|
/*Added to input that's initialized into a typeahead*/
|
||||||
display: block;
|
.twitter-typeahead .tt-input {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to hint input.*/
|
||||||
|
.twitter-typeahead .hint {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to menu element*/
|
||||||
|
.twitter-typeahead .tt-menu {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: none;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius:4px;
|
||||||
|
|
||||||
|
-moz-box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
-webkit-box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to dataset elements*/
|
||||||
|
.twitter-typeahead .tt-dataset {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*dded to suggestion elements*/
|
||||||
|
.twitter-typeahead .tt-suggestion {
|
||||||
padding: 3px 20px;
|
padding: 3px 20px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion.tt-is-under-cursor {
|
/*Added to menu element when it contains no content*/
|
||||||
color: #fff;
|
.twitter-typeahead .tt-empty {
|
||||||
background-color: #0081c2;
|
background-color: white;
|
||||||
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
|
|
||||||
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion.tt-is-under-cursor a {
|
/*Added to menu element when it is opened*/
|
||||||
color: #fff;
|
.twitter-typeahead .tt-open {
|
||||||
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion p {
|
/*Added to suggestion element when menu cursor moves to said suggestion*/
|
||||||
margin: 0;
|
.twitter-typeahead .tt-suggestion:hover,
|
||||||
|
.twitter-typeahead .tt-suggestion:focus,
|
||||||
|
.twitter-typeahead .tt-cursor {
|
||||||
|
cursor: hand !important;
|
||||||
|
background-color: #337ab7;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*Added to the element that wraps highlighted text*/
|
||||||
.tt-hint {
|
.twitter-typeahead .tt-highlight {
|
||||||
padding: 6px 12px;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.twitter-typeahead .tt-hint
|
|
||||||
{
|
|
||||||
display: block;
|
|
||||||
height: 34px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.428571429;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius:4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter-typeahead .hint-small
|
|
||||||
{
|
|
||||||
height: 30px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
border-radius: 3px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter-typeahead .hint-large
|
|
||||||
{
|
|
||||||
height: 45px;
|
|
||||||
padding: 10px 16px;
|
|
||||||
font-size: 18px;
|
|
||||||
border-radius: 6px;
|
|
||||||
line-height: 1.33;
|
|
||||||
}
|
}
|
||||||
body { background: #f8f8f8 !important;
|
body { background: #f8f8f8 !important;
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
|
125
public/css/typeahead.js-bootstrap.css
vendored
125
public/css/typeahead.js-bootstrap.css
vendored
@ -1,84 +1,71 @@
|
|||||||
.twitter-typeahead .tt-query,
|
/**********************************************************
|
||||||
.twitter-typeahead .tt-hint {
|
* typeahead.js v0.11.1 - twitter bootstrap v3.3.5 *
|
||||||
margin-bottom: 0;
|
**********************************************************/
|
||||||
|
|
||||||
|
/*root typeahead class*/
|
||||||
|
.twitter-typeahead {
|
||||||
|
display: inherit !important;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-dropdown-menu {
|
.twitter-typeahead .tt-input[disabled] {
|
||||||
min-width: 160px;
|
background-color : #eeeeee !important;
|
||||||
margin-top: 2px;
|
|
||||||
padding: 5px 0;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border: 1px solid rgba(0,0,0,.2);
|
|
||||||
*border-right-width: 2px;
|
|
||||||
*border-bottom-width: 2px;
|
|
||||||
-webkit-border-radius: 6px;
|
|
||||||
-moz-border-radius: 6px;
|
|
||||||
border-radius: 6px;
|
|
||||||
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
|
||||||
-webkit-background-clip: padding-box;
|
|
||||||
-moz-background-clip: padding;
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion {
|
/*Added to input that's initialized into a typeahead*/
|
||||||
display: block;
|
.twitter-typeahead .tt-input {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to hint input.*/
|
||||||
|
.twitter-typeahead .hint {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to menu element*/
|
||||||
|
.twitter-typeahead .tt-menu {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: none;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius:4px;
|
||||||
|
|
||||||
|
-moz-box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
-webkit-box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
box-shadow: 12px 14px 30px -7px #616161;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Added to dataset elements*/
|
||||||
|
.twitter-typeahead .tt-dataset {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*dded to suggestion elements*/
|
||||||
|
.twitter-typeahead .tt-suggestion {
|
||||||
padding: 3px 20px;
|
padding: 3px 20px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion.tt-is-under-cursor {
|
/*Added to menu element when it contains no content*/
|
||||||
color: #fff;
|
.twitter-typeahead .tt-empty {
|
||||||
background-color: #0081c2;
|
background-color: white;
|
||||||
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
|
|
||||||
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
|
|
||||||
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion.tt-is-under-cursor a {
|
/*Added to menu element when it is opened*/
|
||||||
color: #fff;
|
.twitter-typeahead .tt-open {
|
||||||
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tt-suggestion p {
|
/*Added to suggestion element when menu cursor moves to said suggestion*/
|
||||||
margin: 0;
|
.twitter-typeahead .tt-suggestion:hover,
|
||||||
|
.twitter-typeahead .tt-suggestion:focus,
|
||||||
|
.twitter-typeahead .tt-cursor {
|
||||||
|
cursor: hand !important;
|
||||||
|
background-color: #337ab7;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*Added to the element that wraps highlighted text*/
|
||||||
.tt-hint {
|
.twitter-typeahead .tt-highlight {
|
||||||
padding: 6px 12px;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.twitter-typeahead .tt-hint
|
|
||||||
{
|
|
||||||
display: block;
|
|
||||||
height: 34px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.428571429;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius:4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter-typeahead .hint-small
|
|
||||||
{
|
|
||||||
height: 30px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
border-radius: 3px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.twitter-typeahead .hint-large
|
|
||||||
{
|
|
||||||
height: 45px;
|
|
||||||
padding: 10px 16px;
|
|
||||||
font-size: 18px;
|
|
||||||
border-radius: 6px;
|
|
||||||
line-height: 1.33;
|
|
||||||
}
|
}
|
@ -259,7 +259,21 @@ NINJA.notesAndTerms = function(invoice)
|
|||||||
NINJA.invoiceColumns = function(invoice)
|
NINJA.invoiceColumns = function(invoice)
|
||||||
{
|
{
|
||||||
var account = invoice.account;
|
var account = invoice.account;
|
||||||
var columns = ["15%", "*"];
|
var columns = [];
|
||||||
|
|
||||||
|
if (invoice.has_product_key) {
|
||||||
|
columns.push("15%");
|
||||||
|
}
|
||||||
|
|
||||||
|
columns.push("*")
|
||||||
|
|
||||||
|
if (account.custom_invoice_item_label1) {
|
||||||
|
columns.push("10%");
|
||||||
|
}
|
||||||
|
if (account.custom_invoice_item_label2) {
|
||||||
|
columns.push("10%");
|
||||||
|
}
|
||||||
|
|
||||||
var count = 3;
|
var count = 3;
|
||||||
if (account.hide_quantity == '1') {
|
if (account.hide_quantity == '1') {
|
||||||
count--;
|
count--;
|
||||||
@ -270,6 +284,7 @@ NINJA.invoiceColumns = function(invoice)
|
|||||||
for (var i=0; i<count; i++) {
|
for (var i=0; i<count; i++) {
|
||||||
columns.push("14%");
|
columns.push("14%");
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,16 +308,28 @@ NINJA.taxWidth = function(invoice)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NINJA.invoiceLines = function(invoice) {
|
NINJA.invoiceLines = function(invoice) {
|
||||||
|
var account = invoice.account;
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var shownItem = false;
|
var shownItem = false;
|
||||||
var hideQuantity = invoice.account.hide_quantity == '1';
|
var hideQuantity = invoice.account.hide_quantity == '1';
|
||||||
var showItemTaxes = invoice.account.show_item_taxes == '1';
|
var showItemTaxes = invoice.account.show_item_taxes == '1';
|
||||||
|
|
||||||
var grid = [[
|
var grid = [[]];
|
||||||
{text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']},
|
|
||||||
{text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']},
|
if (invoice.has_product_key) {
|
||||||
{text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}
|
grid[0].push({text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']});
|
||||||
]];
|
}
|
||||||
|
|
||||||
|
grid[0].push({text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']});
|
||||||
|
|
||||||
|
if (account.custom_invoice_item_label1) {
|
||||||
|
grid[0].push({text: account.custom_invoice_item_label1, style: ['tableHeader', 'custom1TableHeader']});
|
||||||
|
}
|
||||||
|
if (account.custom_invoice_item_label2) {
|
||||||
|
grid[0].push({text: account.custom_invoice_item_label2, style: ['tableHeader', 'custom2TableHeader']});
|
||||||
|
}
|
||||||
|
|
||||||
|
grid[0].push({text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']});
|
||||||
|
|
||||||
if (!hideQuantity) {
|
if (!hideQuantity) {
|
||||||
grid[0].push({text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']});
|
grid[0].push({text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']});
|
||||||
@ -349,8 +376,16 @@ NINJA.invoiceLines = function(invoice) {
|
|||||||
|
|
||||||
rowStyle = (i % 2 == 0) ? 'odd' : 'even';
|
rowStyle = (i % 2 == 0) ? 'odd' : 'even';
|
||||||
|
|
||||||
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
|
if (invoice.has_product_key) {
|
||||||
|
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
|
||||||
|
}
|
||||||
row.push({style:["notes", rowStyle], stack:[{text:notes || ' '}]});
|
row.push({style:["notes", rowStyle], stack:[{text:notes || ' '}]});
|
||||||
|
if (account.custom_invoice_item_label1) {
|
||||||
|
row.push({style:["customValue1", rowStyle], text:item.custom_value1 || ' '});
|
||||||
|
}
|
||||||
|
if (account.custom_invoice_item_label2) {
|
||||||
|
row.push({style:["customValue2", rowStyle], text:item.custom_value2 || ' '});
|
||||||
|
}
|
||||||
row.push({style:["cost", rowStyle], text:cost});
|
row.push({style:["cost", rowStyle], text:cost});
|
||||||
if (!hideQuantity) {
|
if (!hideQuantity) {
|
||||||
row.push({style:["quantity", rowStyle], text:qty || ' '});
|
row.push({style:["quantity", rowStyle], text:qty || ' '});
|
||||||
|
@ -589,6 +589,7 @@ function calculateAmounts(invoice) {
|
|||||||
var total = 0;
|
var total = 0;
|
||||||
var hasTaxes = false;
|
var hasTaxes = false;
|
||||||
var taxes = {};
|
var taxes = {};
|
||||||
|
invoice.has_product_key = false;
|
||||||
|
|
||||||
// sum line item
|
// sum line item
|
||||||
for (var i=0; i<invoice.invoice_items.length; i++) {
|
for (var i=0; i<invoice.invoice_items.length; i++) {
|
||||||
@ -604,6 +605,12 @@ function calculateAmounts(invoice) {
|
|||||||
var taxRate = 0;
|
var taxRate = 0;
|
||||||
var taxName = '';
|
var taxName = '';
|
||||||
|
|
||||||
|
if (item.product_key) {
|
||||||
|
invoice.has_product_key = true;
|
||||||
|
} else if (invoice.invoice_items.length == 1 && !item.qty) {
|
||||||
|
invoice.has_product_key = true;
|
||||||
|
}
|
||||||
|
|
||||||
// the object structure differs if it's read from the db or created by knockoutJS
|
// the object structure differs if it's read from the db or created by knockoutJS
|
||||||
if (item.tax && parseFloat(item.tax.rate)) {
|
if (item.tax && parseFloat(item.tax.rate)) {
|
||||||
taxRate = parseFloat(item.tax.rate);
|
taxRate = parseFloat(item.tax.rate);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja) - $30
|
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja) - $30
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
* PHP >= 5.4.0
|
* PHP >= 5.5.9
|
||||||
* MCrypt PHP Extension
|
* MCrypt PHP Extension
|
||||||
* MySQL
|
* MySQL
|
||||||
|
|
||||||
@ -68,6 +68,8 @@ We're using the [Git-Flow](http://nvie.com/posts/a-successful-git-branching-mode
|
|||||||
* [patricktalmadge/bootstrapper](https://github.com/patricktalmadge/bootstrapper) - Laravel Twitter Bootstrap Bundle
|
* [patricktalmadge/bootstrapper](https://github.com/patricktalmadge/bootstrapper) - Laravel Twitter Bootstrap Bundle
|
||||||
* [danielfarrell/bootstrap-combobox](https://github.com/danielfarrell/bootstrap-combobox) - A combobox plugin
|
* [danielfarrell/bootstrap-combobox](https://github.com/danielfarrell/bootstrap-combobox) - A combobox plugin
|
||||||
* [eternicode/bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) - A datepicker for @twitter bootstrap
|
* [eternicode/bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) - A datepicker for @twitter bootstrap
|
||||||
|
* [twitter/typeahead.js](https://github.com/twitter/typeahead.js) - a fast and fully-featured autocomplete library
|
||||||
|
* [krisk/Fuse](https://github.com/krisk/Fuse) - Lightweight fuzzy-search, in JavaScript
|
||||||
* [knockout/knockout](https://github.com/knockout/knockout) - Knockout makes it easier to create rich, responsive UIs with JavaScript
|
* [knockout/knockout](https://github.com/knockout/knockout) - Knockout makes it easier to create rich, responsive UIs with JavaScript
|
||||||
* [rniemeyer/knockout-sortable](https://github.com/rniemeyer/knockout-sortable) - A Knockout.js binding to connect observableArrays with jQuery UI sortable functionality
|
* [rniemeyer/knockout-sortable](https://github.com/rniemeyer/knockout-sortable) - A Knockout.js binding to connect observableArrays with jQuery UI sortable functionality
|
||||||
* [bpampuch/pdfmake](https://github.com/bpampuch/pdfmake) - Client/server side PDF printing in pure JavaScript
|
* [bpampuch/pdfmake](https://github.com/bpampuch/pdfmake) - Client/server side PDF printing in pure JavaScript
|
||||||
|
@ -845,10 +845,10 @@ $LANG = array(
|
|||||||
'subdomain_help' => 'Customize the invoice link subdomain or display the invoice on your own website.',
|
'subdomain_help' => 'Customize the invoice link subdomain or display the invoice on your own website.',
|
||||||
'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.',
|
'invoice_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the invoice number.',
|
||||||
'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.',
|
'quote_number_help' => 'Specify a prefix or use a custom pattern to dynamically set the quote number.',
|
||||||
'custom_client_fields_helps' => 'Add a text input to the client create/edit page and display the label and value on the PDF.',
|
'custom_client_fields_helps' => 'Add a field when creating a client and display the label and value on the PDF.',
|
||||||
'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.',
|
'custom_account_fields_helps' => 'Add a label and value to the company details section of the PDF.',
|
||||||
'custom_invoice_fields_helps' => 'Add a text input to the invoice create/edit page and display the label and value on the PDF.',
|
'custom_invoice_fields_helps' => 'Add a field when creating an invoice and display the label and value on the PDF.',
|
||||||
'custom_invoice_charges_helps' => 'Add a text input to the invoice create/edit page and include the charge in the invoice subtotals.',
|
'custom_invoice_charges_helps' => 'Add a field when creating an invoice and include the charge in the invoice subtotals.',
|
||||||
'token_expired' => 'Validation token was expired. Please try again.',
|
'token_expired' => 'Validation token was expired. Please try again.',
|
||||||
'invoice_link' => 'Invoice Link',
|
'invoice_link' => 'Invoice Link',
|
||||||
'button_confirmation_message' => 'Click to confirm your email address.',
|
'button_confirmation_message' => 'Click to confirm your email address.',
|
||||||
@ -1045,7 +1045,10 @@ $LANG = array(
|
|||||||
'new_product' => 'New Product',
|
'new_product' => 'New Product',
|
||||||
'new_tax_rate' => 'New Tax Rate',
|
'new_tax_rate' => 'New Tax Rate',
|
||||||
'invoiced_amount' => 'Invoiced Amount',
|
'invoiced_amount' => 'Invoiced Amount',
|
||||||
|
'invoice_item_fields' => 'Invoice Item Fields',
|
||||||
|
'custom_invoice_item_fields_help' => 'Add a field when creating an invoice item and display the label and value on the PDF.',
|
||||||
|
'recurring_invoice_number' => 'Recurring Invoice Number',
|
||||||
|
'recurring_invoice_number_prefix_help' => 'Speciy a prefix to be added to the invoice number for recurring invoices. The default value is \'R\'.'
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
@ -269,6 +269,7 @@
|
|||||||
processData: false,
|
processData: false,
|
||||||
contentType: 'application/json; charset=utf-8',
|
contentType: 'application/json; charset=utf-8',
|
||||||
success: function (result) {
|
success: function (result) {
|
||||||
|
NINJA.formIsChanged = false;
|
||||||
model.importResults(result);
|
model.importResults(result);
|
||||||
model.setPage('done');
|
model.setPage('done');
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,15 @@
|
|||||||
|
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
||||||
<li role="presentation" class="active"><a href="#invoiceNumber" aria-controls="invoiceNumber" role="tab" data-toggle="tab">{{ trans('texts.invoice_number') }}</a></li>
|
<li role="presentation" class="active">
|
||||||
<li role="presentation"><a href="#quoteNumber" aria-controls="quoteNumber" role="tab" data-toggle="tab">{{ trans('texts.quote_number') }}</a></li>
|
<a href="#invoiceNumber" aria-controls="invoiceNumber" role="tab" data-toggle="tab">{{ trans('texts.invoice_number') }}</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="#quoteNumber" aria-controls="quoteNumber" role="tab" data-toggle="tab">{{ trans('texts.quote_number') }}</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="#recurringInvoiceNumber" aria-controls="recurringInvoiceNumber" role="tab" data-toggle="tab">{{ trans('texts.recurring_invoice_number') }}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
@ -92,6 +99,15 @@
|
|||||||
trans('texts.next_quote_number', ['number' => $account->previewNextInvoiceNumber(ENTITY_QUOTE)])) !!}
|
trans('texts.next_quote_number', ['number' => $account->previewNextInvoiceNumber(ENTITY_QUOTE)])) !!}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="recurringInvoiceNumber">
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
{!! Former::text('recurring_invoice_number_prefix')
|
||||||
|
->label(trans('texts.prefix'))
|
||||||
|
->help(trans('texts.recurring_invoice_number_prefix_help')) !!}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -108,10 +124,21 @@
|
|||||||
|
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
<ul class="nav nav-tabs" role="tablist" style="border: none">
|
||||||
<li role="presentation" class="active"><a href="#clientFields" aria-controls="clientFields" role="tab" data-toggle="tab">{{ trans('texts.client_fields') }}</a></li>
|
<li role="presentation" class="active">
|
||||||
<li role="presentation"><a href="#companyFields" aria-controls="companyFields" role="tab" data-toggle="tab">{{ trans('texts.company_fields') }}</a></li>
|
<a href="#clientFields" aria-controls="clientFields" role="tab" data-toggle="tab">{{ trans('texts.client_fields') }}</a>
|
||||||
<li role="presentation"><a href="#invoiceFields" aria-controls="invoiceFields" role="tab" data-toggle="tab">{{ trans('texts.invoice_fields') }}</a></li>
|
</li>
|
||||||
<li role="presentation"><a href="#invoiceCharges" aria-controls="invoiceCharges" role="tab" data-toggle="tab">{{ trans('texts.invoice_charges') }}</a></li>
|
<li role="presentation">
|
||||||
|
<a href="#companyFields" aria-controls="companyFields" role="tab" data-toggle="tab">{{ trans('texts.company_fields') }}</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="#invoiceFields" aria-controls="invoiceFields" role="tab" data-toggle="tab">{{ trans('texts.invoice_fields') }}</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="#invoiceItemFields" aria-controls="invoiceItemFields" role="tab" data-toggle="tab">{{ trans('texts.invoice_item_fields') }}</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="#invoiceCharges" aria-controls="invoiceCharges" role="tab" data-toggle="tab">{{ trans('texts.invoice_charges') }}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
@ -153,6 +180,17 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="invoiceItemFields">
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
{!! Former::text('custom_invoice_item_label1')
|
||||||
|
->label(trans('texts.field_label')) !!}
|
||||||
|
{!! Former::text('custom_invoice_item_label2')
|
||||||
|
->label(trans('texts.field_label'))
|
||||||
|
->help(trans('texts.custom_invoice_item_fields_help')) !!}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div role="tabpanel" class="tab-pane" id="invoiceCharges">
|
<div role="tabpanel" class="tab-pane" id="invoiceCharges">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
|
@ -259,37 +259,84 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showSearch() {
|
function showSearch() {
|
||||||
$('#search').typeahead('setQuery', '');
|
console.log('showSearch..');
|
||||||
|
//$('#search').typeahead('setQuery', '');
|
||||||
$('#navbar-options').hide();
|
$('#navbar-options').hide();
|
||||||
$('#search-form').show();
|
$('#search-form').show();
|
||||||
|
|
||||||
if (window.hasOwnProperty('searchData')) {
|
if (window.hasOwnProperty('loadedSearchData')) {
|
||||||
|
console.log('has data');
|
||||||
$('#search').focus();
|
$('#search').focus();
|
||||||
} else {
|
} else {
|
||||||
trackEvent('/activity', '/search');
|
trackEvent('/activity', '/search');
|
||||||
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
||||||
console.log(data);
|
window.loadedSearchData = true;
|
||||||
window.searchData = true;
|
|
||||||
var datasets = [];
|
$('#search').typeahead({
|
||||||
for (var type in data)
|
hint: true,
|
||||||
|
highlight: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
if (!data.hasOwnProperty(type)) continue;
|
name: 'data',
|
||||||
datasets.push({
|
display: 'value',
|
||||||
name: type,
|
source: searchData(data['clients']),
|
||||||
header: ' <b>' + type + '</b>',
|
templates: {
|
||||||
local: data[type]
|
header: ' <b>{{ trans('texts.clients') }}</b>'
|
||||||
});
|
}
|
||||||
}
|
},
|
||||||
if (datasets.length == 0) {
|
{
|
||||||
return;
|
name: 'data',
|
||||||
}
|
display: 'value',
|
||||||
$('#search').typeahead(datasets).on('typeahead:selected', function(element, datum, name) {
|
source: searchData(data['contacts']),
|
||||||
|
templates: {
|
||||||
|
header: ' <b>{{ trans('texts.contacts') }}</b>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'data',
|
||||||
|
display: 'value',
|
||||||
|
source: searchData(data['invoices']),
|
||||||
|
templates: {
|
||||||
|
header: ' <b>{{ trans('texts.contacts') }}</b>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'data',
|
||||||
|
display: 'value',
|
||||||
|
source: searchData(data['quotes']),
|
||||||
|
templates: {
|
||||||
|
header: ' <b>{{ trans('texts.quotes') }}</b>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'data',
|
||||||
|
display: 'value',
|
||||||
|
source: searchData(data['navigation']),
|
||||||
|
templates: {
|
||||||
|
header: ' <b>{{ trans('texts.navigation') }}</b>'
|
||||||
|
}
|
||||||
|
}).on('typeahead:selected', function(element, datum, name) {
|
||||||
window.location = datum.url;
|
window.location = datum.url;
|
||||||
}).focus().typeahead('setQuery', $('#search').val());
|
}).focus();
|
||||||
|
|
||||||
|
//.typeahead('setQuery', $('#search').val());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function searchData(data) {
|
||||||
|
return function findMatches(q, cb) {
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
keys: ['value'],
|
||||||
|
}
|
||||||
|
var fuse = new Fuse(data, options);
|
||||||
|
var matches = fuse.search(q);
|
||||||
|
|
||||||
|
cb(matches);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function hideSearch() {
|
function hideSearch() {
|
||||||
$('#search-form').hide();
|
$('#search-form').hide();
|
||||||
$('#navbar-options').show();
|
$('#navbar-options').show();
|
||||||
|
@ -189,6 +189,12 @@
|
|||||||
<th style="min-width:32px;" class="hide-border"></th>
|
<th style="min-width:32px;" class="hide-border"></th>
|
||||||
<th style="min-width:160px">{{ $invoiceLabels['item'] }}</th>
|
<th style="min-width:160px">{{ $invoiceLabels['item'] }}</th>
|
||||||
<th style="width:100%">{{ $invoiceLabels['description'] }}</th>
|
<th style="width:100%">{{ $invoiceLabels['description'] }}</th>
|
||||||
|
@if ($account->custom_invoice_item_label1)
|
||||||
|
<th style="min-width:120px">{{ $account->custom_invoice_item_label1 }}</th>
|
||||||
|
@endif
|
||||||
|
@if ($account->custom_invoice_item_label2)
|
||||||
|
<th style="min-width:120px">{{ $account->custom_invoice_item_label2 }}</th>
|
||||||
|
@endif
|
||||||
<th style="min-width:120px" data-bind="text: costLabel">{{ $invoiceLabels['unit_cost'] }}</th>
|
<th style="min-width:120px" data-bind="text: costLabel">{{ $invoiceLabels['unit_cost'] }}</th>
|
||||||
<th style="{{ $account->hide_quantity ? 'display:none' : 'min-width:120px' }}" data-bind="text: qtyLabel">{{ $invoiceLabels['quantity'] }}</th>
|
<th style="{{ $account->hide_quantity ? 'display:none' : 'min-width:120px' }}" data-bind="text: qtyLabel">{{ $invoiceLabels['quantity'] }}</th>
|
||||||
<th style="min-width:120px;display:none;" data-bind="visible: $root.invoice_item_taxes.show">{{ trans('texts.tax') }}</th>
|
<th style="min-width:120px;display:none;" data-bind="visible: $root.invoice_item_taxes.show">{{ trans('texts.tax') }}</th>
|
||||||
@ -215,6 +221,16 @@
|
|||||||
<input type="text" data-bind="value: task_public_id, attr: {name: 'invoice_items[' + $index() + '][task_public_id]'}" style="display: none"/>
|
<input type="text" data-bind="value: task_public_id, attr: {name: 'invoice_items[' + $index() + '][task_public_id]'}" style="display: none"/>
|
||||||
<input type="text" data-bind="value: expense_public_id, attr: {name: 'invoice_items[' + $index() + '][expense_public_id]'}" style="display: none"/>
|
<input type="text" data-bind="value: expense_public_id, attr: {name: 'invoice_items[' + $index() + '][expense_public_id]'}" style="display: none"/>
|
||||||
</td>
|
</td>
|
||||||
|
@if ($account->custom_invoice_item_label1)
|
||||||
|
<td>
|
||||||
|
<input data-bind="value: custom_value1, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[' + $index() + '][custom_value1]'}" class="form-control invoice-item"/>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
@if ($account->custom_invoice_item_label2)
|
||||||
|
<td>
|
||||||
|
<input data-bind="value: custom_value2, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[' + $index() + '][custom_value2]'}" class="form-control invoice-item"/>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
<td>
|
<td>
|
||||||
<input data-bind="value: prettyCost, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[' + $index() + '][cost]'}"
|
<input data-bind="value: prettyCost, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[' + $index() + '][cost]'}"
|
||||||
style="text-align: right" class="form-control invoice-item"/>
|
style="text-align: right" class="form-control invoice-item"/>
|
||||||
@ -243,7 +259,7 @@
|
|||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="hide-border"/>
|
<td class="hide-border"/>
|
||||||
<td class="hide-border" colspan="2" rowspan="6" style="vertical-align:top">
|
<td class="hide-border" colspan="{{ 2 + ($account->custom_invoice_item_label1 ? 1 : 0) + ($account->custom_invoice_item_label2 ? 1 : 0) }}" rowspan="6" style="vertical-align:top">
|
||||||
<br/>
|
<br/>
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
|
|
||||||
|
@ -714,6 +714,8 @@ function ItemModel(data) {
|
|||||||
self.notes = ko.observable('');
|
self.notes = ko.observable('');
|
||||||
self.cost = ko.observable(0);
|
self.cost = ko.observable(0);
|
||||||
self.qty = ko.observable(0);
|
self.qty = ko.observable(0);
|
||||||
|
self.custom_value1 = ko.observable('');
|
||||||
|
self.custom_value2 = ko.observable('');
|
||||||
self.tax_name = ko.observable('');
|
self.tax_name = ko.observable('');
|
||||||
self.tax_rate = ko.observable(0);
|
self.tax_rate = ko.observable(0);
|
||||||
self.task_public_id = ko.observable('');
|
self.task_public_id = ko.observable('');
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
@if (!Auth::user()->isPro())
|
@if (!Auth::user()->isPro())
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
$('form.warn-on-exit').find('input, select, button').prop('disabled', true);
|
$('form.warn-on-exit').find('input, button').prop('disabled', true);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
@ -128,12 +128,12 @@
|
|||||||
|
|
||||||
var arc = d3.svg.arc()
|
var arc = d3.svg.arc()
|
||||||
.innerRadius(function(d) { return d.r })
|
.innerRadius(function(d) { return d.r })
|
||||||
.outerRadius(function(d) { return d.r - 5 })
|
.outerRadius(function(d) { return d.r - 8 })
|
||||||
.startAngle(0);
|
.startAngle(0);
|
||||||
|
|
||||||
var fullArc = d3.svg.arc()
|
var fullArc = d3.svg.arc()
|
||||||
.innerRadius(function(d) { return d.r })
|
.innerRadius(function(d) { return d.r - 1 })
|
||||||
.outerRadius(function(d) { return d.r - 5 })
|
.outerRadius(function(d) { return d.r - 7 })
|
||||||
.startAngle(0)
|
.startAngle(0)
|
||||||
.endAngle(2 * Math.PI);
|
.endAngle(2 * Math.PI);
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h2>Invoice Ninja Setup</h2>
|
<h2>Invoice Ninja Setup</h2>
|
||||||
@if (version_compare(phpversion(), '5.4.0', '<'))
|
@if (version_compare(phpversion(), '5.5.9', '<'))
|
||||||
<div class="alert alert-warning">Warning: The application requires PHP >= 5.4.0</div>
|
<div class="alert alert-warning">Warning: The application requires PHP >= 5.5.9</div>
|
||||||
@endif
|
@endif
|
||||||
@if (!function_exists('proc_open'))
|
@if (!function_exists('proc_open'))
|
||||||
<div class="alert alert-warning">Warning: <a href="http://php.net/manual/en/function.proc-open.php" target="_blank">proc_open</a> must be enabled.</div>
|
<div class="alert alert-warning">Warning: <a href="http://php.net/manual/en/function.proc-open.php" target="_blank">proc_open</a> must be enabled.</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user