akaunting 3.0 (the last dance)

This commit is contained in:
Burak Civan
2022-06-01 10:15:55 +03:00
parent cead09f6d4
commit d9c0764572
3812 changed files with 126831 additions and 102949 deletions

View File

@@ -2,6 +2,7 @@
namespace App\Traits;
use App\Models\Setting\Category;
use Illuminate\Support\Str;
trait Categories
@@ -25,4 +26,9 @@ trait Categories
return $types;
}
public function getCategoryWithoutChildren($id)
{
return Category::getWithoutChildren()->find($id);;
}
}

View File

@@ -2,11 +2,16 @@
namespace App\Traits;
use App\Utilities\Chartjs;
use Balping\JsonRaw\Raw;
use Akaunting\Apexcharts\Charts as Apexcharts;
trait Charts
{
public $bar = [
'colors' => [],
'labels' => [],
'values' => [],
];
public $donut = [
'colors' => [],
'labels' => [],
@@ -31,7 +36,7 @@ trait Charts
$this->addToDonut($color, $label, $amount);
}
public function getDonutChart($name, $width = 0, $height = 160, $limit = 10)
public function getDonutChart($name, $width = '100%', $height = 300, $limit = 10)
{
// Show donut prorated if there is no value
if (array_sum($this->donut['values']) == 0) {
@@ -49,216 +54,39 @@ trait Charts
$labels[$id] = $this->donut['labels'][$id];
}
$chart = new Chartjs();
$chart = new Apexcharts();
$chart->type('doughnut')
->width($width)
->height($height)
->options($this->getDonutChartOptions($colors))
->labels(array_values($labels));
$chart->dataset($name, 'doughnut', array_values($values))
->backgroundColor(array_values($colors));
$chart->setType('donut')
->setWidth($width)
->setHeight($height)
->setLabels(array_values($labels))
->setColors(array_values($colors))
->setDataset($name, 'donut', array_values($values));
return $chart;
}
public function getDonutChartOptions($colors)
public function addToBar($color, $label, $value)
{
return [
'color' => array_values($colors),
'cutoutPercentage' => 80,
'legend' => [
'position' => 'right',
],
'tooltips' => [
'backgroundColor' => '#000000',
'titleFontColor' => '#ffffff',
'bodyFontColor' => '#e5e5e5',
'bodySpacing' => 4,
'xPadding' => 12,
'mode' => 'nearest',
'intersect' => 0,
'position' => 'nearest',
],
'scales' => [
'yAxes' => [
'display' => false,
],
'xAxes' => [
'display' => false,
],
],
];
$this->bar['colors'][] = $color;
$this->bar['labels'][] = $label;
$this->bar['values'][] = (int) $value;
}
public function getLineChartOptions($money_format = true)
public function getBarChart($name, $width = '100%', $height = 160)
{
$decimal_mark = str_replace("'", "\\'", config('money.' . setting('default.currency') . '.decimal_mark'));
$thousands_separator = str_replace("'", "\\'", config('money.' . setting('default.currency') . '.thousands_separator'));
$symbol = str_replace("'", "\\'", config('money.' . setting('default.currency') . '.symbol'));
$symbol_first = str_replace("'", "\\'", config('money.' . setting('default.currency') . '.symbol_first'));
$precision = str_replace("'", "\\'", config('money.' . setting('default.currency') . '.precision'));
$chart = new Apexcharts();
$options = [
'tooltips' => [
'backgroundColor' => '#000000',
'titleFontColor' => '#ffffff',
'bodyFontColor' => '#e5e5e5',
'bodySpacing' => 4,
'YrPadding' => 12,
'mode' => 'nearest',
'intersect' => 0,
'position' => 'nearest',
],
'responsive' => true,
'scales' => [
'yAxes' => [[
'barPercentage' => 1.6,
'ticks' => [
'beginAtZero' => true,
'padding' => 10,
'fontColor' => '#9e9e9e',
],
'gridLines' => [
'drawBorder' => false,
'color' => 'rgba(29,140,248,0.1)',
'zeroLineColor' => 'transparent',
'borderDash' => [2],
'borderDashOffset' => [2],
],
]],
'xAxes' => [[
'barPercentage' => 1.6,
'ticks' => [
'suggestedMin' => 60,
'suggestedMax' => 125,
'padding' => 20,
'fontColor' => '#9e9e9e',
],
'gridLines' => [
'drawBorder' => false,
'color' => 'rgba(29,140,248,0.0)',
'zeroLineColor' => 'transparent',
],
]],
],
];
$chart->setType('bar')
->setWidth($width)
->setHeight($height)
->setLabels(array_values($this->bar['labels']))
->setColors($this->bar['colors']);
if ($money_format) {
// for Tooltip money format
$options['tooltips']['callbacks'] = [
'label' => new Raw("function(tooltipItem, data) {
const moneySettings = {
decimal: '" . $decimal_mark . "',
thousands: '". $thousands_separator . "',
symbol: '" . $symbol . "',
isPrefix: '" . $symbol_first . "',
precision: '" . $precision . "',
};
const formattedCurrency = function (input, opt = moneySettings) {
if (typeof input === 'number') {
input = input.toFixed(fixed(opt.precision))
}
function fixed (precision) {
return Math.max(0, Math.min(precision, 20));
};
function toStr(value) {
return value ? value.toString() : '';
};
function numbersToCurrency(numbers, precision) {
var exp = Math.pow(10, precision);
var float = parseFloat(numbers) / exp;
return float.toFixed(fixed(precision));
};
function joinIntegerAndDecimal (integer, decimal, separator) {
return decimal ? integer + separator + decimal : integer;
};
if (typeof input === 'number') {
input = input.toFixed(fixed(opt.precision));
};
var negative = input.indexOf('-') >= 0 ? '-' : '';
var numbers = toStr(input).replace(/\D+/g, '') || '0';
var currency = numbersToCurrency(numbers, opt.precision);
var parts = toStr(currency).split('.');
var integer = parts[0].replace(/(\d)(?=(?:\d{3})+\b)/gm, ('$1' + opt.thousands));
var decimal = parts[1];
if (opt.isPrefix == 1) {
return opt.symbol + negative + joinIntegerAndDecimal(integer, decimal, opt.decimal);
}
return negative + joinIntegerAndDecimal(integer, decimal, opt.decimal) + opt.symbol;
};
return formattedCurrency(tooltipItem.yLabel, moneySettings);
}")
];
// for Y variable money format
$options['scales']['yAxes'][0]['ticks']['callback'] = new Raw("function(value, index, values) {
const moneySettings = {
decimal: '" . $decimal_mark . "',
thousands: '". $thousands_separator . "',
symbol: '" . $symbol . "',
isPrefix: '" . $symbol_first . "',
precision: '" . $precision . "',
};
const formattedCurrency = function (input, opt = moneySettings) {
if (typeof input === 'number') {
input = input.toFixed(fixed(opt.precision))
}
function fixed (precision) {
return Math.max(0, Math.min(precision, 20));
};
function toStr(value) {
return value ? value.toString() : '';
};
function numbersToCurrency(numbers, precision) {
var exp = Math.pow(10, precision);
var float = parseFloat(numbers) / exp;
return float.toFixed(fixed(precision));
};
function joinIntegerAndDecimal (integer, decimal, separator) {
return decimal ? integer + separator + decimal : integer;
};
if (typeof input === 'number') {
input = input.toFixed(fixed(opt.precision));
};
var negative = input.indexOf('-') >= 0 ? '-' : '';
var numbers = toStr(input).replace(/\D+/g, '') || '0';
var currency = numbersToCurrency(numbers, opt.precision);
var parts = toStr(currency).split('.');
var integer = parts[0].replace(/(\d)(?=(?:\d{3})+\b)/gm, ('$1' + opt.thousands));
var decimal = parts[1];
if (opt.isPrefix == 1) {
return opt.symbol + negative + joinIntegerAndDecimal(integer, decimal, opt.decimal);
} else {
return negative + joinIntegerAndDecimal(integer, decimal, opt.decimal) + opt.symbol;
}
};
return formattedCurrency(value, moneySettings);
}");
foreach ($this->bar['values'] as $key => $value) {
$chart->setDataset($this->bar['labels'][$key], 'bar', $value);
}
return $options;
return $chart;
}
}

47
app/Traits/Cloud.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
namespace App\Traits;
use App\Traits\Modules;
trait Cloud
{
use Modules;
public $cloud_host = 'app.akaunting.com';
public function isCloud()
{
return request()->getHost() == $this->cloud_host;
}
public function getCloudRolesPageUrl()
{
if (! $this->isCloud()) {
return 'https://akaunting.com/plans?utm_source=user_role&utm_medium=software&utm_campaign=plg';
}
if ($this->moduleIsEnabled('roles')) {
return route('roles.roles.index');
}
return route('cloud.plans.index', [
'utm_source' => 'user',
'utm_medium' => 'app',
'utm_campaign' => 'roles',
]);
}
public function getCloudBankFeedsUrl()
{
if (! $this->isCloud()) {
return 'https://akaunting.com/features/connect-your-bank?utm_source=bank_feeds_widget&utm_medium=software&utm_campaign=plg';
}
return route('cloud.plans.index', [
'utm_source' => 'widget',
'utm_medium' => 'app',
'utm_campaign' => 'bank_feeds',
]);
}
}

13
app/Traits/Database.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
namespace App\Traits;
trait Database
{
public function databaseDriverIs(string $driver): bool
{
$connection = config('database.default');
return config("database.connections.$connection.driver") === $driver;
}
}

View File

@@ -3,34 +3,54 @@
namespace App\Traits;
use App\Models\Document\Document;
use App\Abstracts\View\Components\Document as DocumentComponent;
use App\Abstracts\View\Components\Documents\Document as DocumentComponent;
use App\Utilities\Date;
use App\Traits\Transactions;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
use Egulias\EmailValidator\Validation\RFCValidation;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
trait Documents
{
use Transactions;
public function isRecurringDocument(): bool
{
$type = $this->type ?? $this->document->type ?? $this->model->type ?? 'invoice';
return Str::endsWith($type, '-recurring');
}
public function isNotRecurringDocument(): bool
{
return ! $this->isRecurring();
}
public function getNextDocumentNumber(string $type): string
{
if ($alias = config('type.' . $type . '.alias')) {
if ($alias = config('type.document.' . $type . '.alias')) {
$type = $alias . '.' . str_replace('-', '_', $type);
}
$prefix = setting("$type.number_prefix");
$next = setting("$type.number_next");
$digit = setting("$type.number_digit");
$prefix = setting($type . '.number_prefix');
$next = setting($type . '.number_next');
$digit = setting($type . '.number_digit');
return $prefix . str_pad($next, $digit, '0', STR_PAD_LEFT);
}
public function increaseNextDocumentNumber(string $type): void
{
if ($alias = config('type.' . $type . '.alias')) {
if ($alias = config('type.document.' . $type . '.alias')) {
$type = $alias . '.' . str_replace('-', '_', $type);
}
$next = setting("$type.number_next", 1) + 1;
$next = setting($type . '.number_next', 1) + 1;
setting(["$type.number_next" => $next]);
setting([$type . '.number_next' => $next]);
setting()->save();
}
@@ -74,6 +94,17 @@ trait Documents
return $statuses;
}
public function getDocumentStatusesForFuture()
{
return [
'draft',
'sent',
'received',
'viewed',
'partial',
];
}
public function getDocumentFileName(Document $document, string $separator = '-', string $extension = 'pdf'): string
{
return $this->getSafeDocumentNumber($document, $separator) . $separator . time() . '.' . $extension;
@@ -86,7 +117,7 @@ trait Documents
protected function getTextDocumentStatuses($type)
{
$default_key = config('type.' . $type . '.translation.prefix') . '.statuses.';
$default_key = config('type.document.' . $type . '.translation.prefix') . '.statuses.';
$translation = DocumentComponent::getTextFromConfig($type, 'document_status', $default_key);
@@ -94,10 +125,10 @@ trait Documents
return $translation;
}
$alias = config('type.' . $type . '.alias');
$alias = config('type.document.' . $type . '.alias');
if (!empty($alias)) {
$translation = $alias . '::' . config('type.' . $type . '.translation.prefix') . '.statuses';
$translation = $alias . '::' . config('type.document.' . $type . '.translation.prefix') . '.statuses';
if (is_array(trans($translation))) {
return $translation . '.';
@@ -110,13 +141,13 @@ trait Documents
protected function getSettingKey($type, $setting_key)
{
$key = '';
$alias = config('type.' . $type . '.alias');
$alias = config('type.document.' . $type . '.alias');
if (!empty($alias)) {
if (! empty($alias)) {
$key .= $alias . '.';
}
$prefix = config('type.' . $type . '.setting.prefix');
$prefix = config('type.document.' . $type . '.setting.prefix');
$key .= $prefix . '.' . $setting_key;
@@ -143,4 +174,80 @@ trait Documents
return $pdf_path;
}
public function getTotalsForFutureDocuments($type = 'invoice', $documents = null)
{
$totals = [
'overdue' => 0,
'open' => 0,
'draft' => 0,
];
$today = Date::today()->toDateString();
$documents = $documents ?: Document::type($type)->with('transactions')->future();
$documents->each(function ($document) use (&$totals, $today) {
if (!in_array($document->status, $this->getDocumentStatusesForFuture())) {
return;
}
$payments = 0;
if ($document->status == 'draft') {
$totals['draft'] += $document->getAmountConvertedToDefault();
return;
}
if ($document->status == 'partial') {
foreach ($document->transactions as $transaction) {
$payments += $transaction->getAmountConvertedToDefault();
}
}
// Check if the document is open or overdue
if ($document->due_at > $today) {
$totals['open'] += $document->getAmountConvertedToDefault() - $payments;
} else {
$totals['overdue'] += $document->getAmountConvertedToDefault() - $payments;
}
});
return $totals;
}
public function canNotifyTheContactOfDocument(Document $document): bool
{
$config = config('type.document.' . $document->type . '.notification');
if (! $config['notify_contact']) {
return false;
}
if (! $document->contact || ($document->contact->enabled == 0)) {
return false;
}
if (empty($document->contact_email)) {
return false;
}
// Check if ietf.org has MX records signaling a server with email capabilites
$validator = new EmailValidator();
$validations = new MultipleValidationWithAnd([
new RFCValidation(),
new DNSCheckValidation(),
]);
if (! $validator->isValid($document->contact_email, $validations)) {
return false;
}
return true;
}
public function getRealTypeOfRecurringDocument(string $recurring_type): string
{
return Str::replace('-recurring', '', $recurring_type);
}
}

View File

@@ -207,7 +207,7 @@ trait Import
public function getCategoryIdFromName($row, $type)
{
$category_id = Category::where('name', $row['category_name'])->pluck('id')->first();
$category_id = Category::withSubCategory()->where('name', $row['category_name'])->pluck('id')->first();
if (!empty($category_id)) {
return $category_id;

View File

@@ -20,7 +20,7 @@ trait Modules
]
];
if (!$response = static::getResponse('POST', 'token/check', $data)) {
if (! $response = static::getResponse('POST', 'token/check', $data)) {
return false;
}
@@ -36,7 +36,7 @@ trait Modules
$items = Cache::get($key);
if (!empty($items)) {
if (! empty($items)) {
return $items;
}
@@ -55,13 +55,28 @@ trait Modules
return $item;
}
public function getModuleIsubscribe($alias)
{
if (! $response = static::getResponse('GET', 'apps/' . $alias . '/isubscribe')) {
return [];
}
$body = json_decode($response->getBody());
if (! is_object($body)) {
return [];
}
return $body;
}
public function getModuleDocumentation($alias, $data = [])
{
$key = 'apps.' . $alias . '.docs.' . $this->getDataKeyOfModules($data);
$documentation = Cache::get($key);
if (!empty($documentation)) {
if (! empty($documentation)) {
return $documentation;
}
@@ -78,7 +93,7 @@ trait Modules
$releases = Cache::get($key);
if (!empty($releases)) {
if (! empty($releases)) {
return $releases;
}
@@ -95,7 +110,7 @@ trait Modules
$reviews = Cache::get($key);
if (!empty($reviews)) {
if (! empty($reviews)) {
return $reviews;
}
@@ -106,13 +121,47 @@ trait Modules
return $reviews;
}
public function getModuleTestimonials($alias, $data = [])
{
$key = 'apps.' . $alias . '.testimonials.' . $this->getDataKeyOfModules($data);
$testimonials = Cache::get($key);
if (! empty($testimonials)) {
return $testimonials;
}
$testimonials = static::getResponseData('GET', 'apps/' . $alias . '/testimonials', $data);
Cache::put($key, $testimonials, Date::now()->addHour());
return $testimonials;
}
public function getBannersOfModules($data = [])
{
$key = 'apps.banners.' . $this->getDataKeyOfModules($data);
$banners = Cache::get($key);
if (! empty($banners)) {
return $banners;
}
$banners = static::getResponseData('GET', 'apps/banners');
Cache::put($key, $banners, Date::now()->addHour());
return $banners;
}
public function getCategoriesOfModules($data = [])
{
$key = 'apps.categories.' . $this->getDataKeyOfModules($data);
$categories = Cache::get($key);
if (!empty($categories)) {
if (! empty($categories)) {
return $categories;
}
@@ -129,7 +178,7 @@ trait Modules
$category = Cache::get($key);
if (!empty($category)) {
if (! empty($category)) {
return $category;
}
@@ -146,7 +195,7 @@ trait Modules
$vendors = Cache::get($key);
if (!empty($vendors)) {
if (! empty($vendors)) {
return $vendors;
}
@@ -163,7 +212,7 @@ trait Modules
$vendor = Cache::get($key);
if (!empty($vendor)) {
if (! empty($vendor)) {
return $vendor;
}
@@ -190,11 +239,11 @@ trait Modules
$installed = [];
Module::all()->each(function($module) use (&$installed) {
if (!$this->moduleExists($module->alias)) {
if (! $this->moduleExists($module->alias)) {
return;
}
if (!$result = $this->getModule($module->alias)) {
if (! $result = $this->getModule($module->alias)) {
return;
}
@@ -212,7 +261,7 @@ trait Modules
$pre_sale = Cache::get($key);
if (!empty($pre_sale)) {
if (! empty($pre_sale)) {
return $pre_sale;
}
@@ -229,7 +278,7 @@ trait Modules
$paid = Cache::get($key);
if (!empty($paid)) {
if (! empty($paid)) {
return $paid;
}
@@ -246,7 +295,7 @@ trait Modules
$new = Cache::get($key);
if (!empty($new)) {
if (! empty($new)) {
return $new;
}
@@ -263,7 +312,7 @@ trait Modules
$free = Cache::get($key);
if (!empty($free)) {
if (! empty($free)) {
return $free;
}
@@ -280,7 +329,7 @@ trait Modules
$featured = Cache::get($key);
if (!empty($featured)) {
if (! empty($featured)) {
return $featured;
}
@@ -291,16 +340,84 @@ trait Modules
return $featured;
}
public function getPopularModules($data = [])
{
$key = 'apps.popular.' . $this->getDataKeyOfModules($data);
$popular = Cache::get($key);
if (! empty($popular)) {
return $popular;
}
$popular = static::getResponseData('GET', 'apps/popular', $data);
Cache::put($key, $popular, Date::now()->addHour());
return $popular;
}
public function getSearchModules($data = [])
{
return static::getResponseData('GET', 'apps/search', $data);
}
public function getTestimonialModules($data = [])
{
$key = 'apps.testimonials.' . $this->getDataKeyOfModules($data);
$testimonials = Cache::get($key);
if (! empty($testimonials)) {
return $testimonials;
}
$testimonials = static::getResponseData('GET', 'apps/testimonials', $data);
Cache::put($key, $testimonials, Date::now()->addHour());
return $testimonials;
}
public function getWidgetsOfModules($data = [])
{
$key = 'apps.widgets.' . $this->getDataKeyOfModules($data);
$widgets = Cache::get($key);
if (! empty($widgets)) {
return $widgets;
}
$widgets = static::getResponseData('GET', 'apps/widgets');
Cache::put($key, $widgets, Date::now()->addHour());
return $widgets;
}
public function getModulesByWidget($alias, $data = [])
{
$key = 'apps.widgets.' . $alias . '.' . $this->getDataKeyOfModules($data);
$widget = Cache::get($key);
if (! empty($widget)) {
return $widget;
}
$widget = static::getResponseData('GET', 'apps/widgets/' . $alias, $data);
Cache::put($key, $widget, Date::now()->addHour());
return $widget;
}
public function getCoreVersion()
{
$data['query'] = Info::all();
if (!$response = static::getResponse('GET', 'core/version', $data)) {
if (! $response = static::getResponse('GET', 'core/version', $data)) {
return [];
}
@@ -309,7 +426,7 @@ trait Modules
public function moduleExists($alias)
{
if (!module($alias) instanceof \Akaunting\Module\Module) {
if (! module($alias) instanceof \Akaunting\Module\Module) {
return false;
}
@@ -340,13 +457,13 @@ trait Modules
$data = Cache::get($key);
if (!empty($data)) {
if (! empty($data)) {
return $data;
}
$data = [];
if (!$suggestions = static::getResponseData('GET', 'apps/suggestions')) {
if (! $suggestions = static::getResponseData('GET', 'apps/suggestions')) {
return $data;
}
@@ -365,13 +482,13 @@ trait Modules
$data = Cache::get($key);
if (!empty($data)) {
if (! empty($data)) {
return $data;
}
$data = [];
if (!$notifications = static::getResponseData('GET', 'apps/notifications')) {
if (! $notifications = static::getResponseData('GET', 'apps/notifications')) {
return $data;
}
@@ -384,6 +501,31 @@ trait Modules
return $data;
}
public function loadTips()
{
$key = 'apps.tips';
$data = Cache::get($key);
if (! empty($data)) {
return $data;
}
$data = [];
if (! $tips = static::getResponseData('GET', 'apps/tips')) {
return $data;
}
foreach ($tips as $tip) {
$data[$tip->path][] = $tip;
}
Cache::put($key, $data, Date::now()->addHour(6));
return $data;
}
public function getSuggestions($path)
{
$key = 'apps.suggestions';
@@ -394,7 +536,7 @@ trait Modules
$data = $this->loadSuggestions();
}
if (!empty($data) && array_key_exists($path, $data)) {
if (! empty($data) && array_key_exists($path, $data)) {
return $data[$path];
}
@@ -411,7 +553,24 @@ trait Modules
$data = $this->loadNotifications();
}
if (!empty($data) && array_key_exists($path, $data)) {
if (! empty($data) && array_key_exists($path, $data)) {
return (array) $data[$path];
}
return [];
}
public function getTips($path): array
{
$key = 'apps.tips';
$data = Cache::get($key);
if (empty($data)) {
$data = $this->loadTips();
}
if (! empty($data) && array_key_exists($path, $data)) {
return (array) $data[$path];
}

View File

@@ -5,6 +5,7 @@ namespace App\Traits;
use App\Models\Auth\Permission;
use App\Models\Auth\Role;
use App\Traits\SearchString;
use App\Traits\Translations;
use App\Utilities\Reports;
use App\Utilities\Widgets;
use Illuminate\Routing\Route;
@@ -13,7 +14,7 @@ use Illuminate\Support\Str;
trait Permissions
{
use SearchString;
use SearchString, Translations;
public function getActionsMap()
{
@@ -248,13 +249,37 @@ trait Permissions
public function createRole($name, $display_name = null, $description = null)
{
$display_name = $display_name ?? Str::title($name);
$alias = !empty($this->alias) ? $this->alias : $name;
if (empty($display_name)) {
$display_name = $this->findTranslation([
'auth.roles.' . Str::replace('-', '_', $name) . '.name',
$alias . '::permissions.roles.' . Str::replace('-', '_', $name) . '.name',
$alias . '::auth.roles.' . Str::replace('-', '_', $name) . '.name',
]);
if (empty($display_name)) {
$display_name = Str::title(Str::replace('-', ' ', $name));
}
}
if (empty($description)) {
$description = $this->findTranslation([
'auth.roles.' . Str::replace('-', '_', $name) . '.description',
$alias . '::permissions.roles.' . Str::replace('-', '_', $name) . '.description',
$alias . '::auth.roles.' . Str::replace('-', '_', $name) . '.description',
]);
if (empty($description)) {
$description = $display_name;
}
}
return Role::firstOrCreate([
'name' => $name,
], [
'display_name' => $display_name,
'description' => $description ?? $display_name,
'description' => $description,
]);
}
@@ -408,24 +433,24 @@ trait Permissions
$table = request()->isApi() ? request()->segment(2) : '';
// Find the proper controller for common API endpoints
if (in_array($table, ['contacts', 'documents', 'transactions'])) {
if (in_array($table, ['contacts', 'documents'])) {
$controller = '';
// Look for type in search variable like api/contacts?search=type:customer
$type = $this->getSearchStringValue('type');
if (!empty($type)) {
$alias = config('type.' . $type . '.alias');
$group = config('type.' . $type . '.group');
$prefix = config('type.' . $type . '.permission.prefix');
if (! empty($type)) {
$alias = config('type.' . Str::singular($table) . '.' . $type . '.alias');
$group = config('type.' . Str::singular($table) . '.' . $type . '.group');
$prefix = config('type.' . Str::singular($table) . '.' . $type . '.permission.prefix');
// if use module set module alias
if (!empty($alias)) {
if (! empty($alias)) {
$controller .= $alias . '-';
}
// if controller in folder it must
if (!empty($group)) {
if (! empty($group)) {
$controller .= $group . '-';
}
@@ -449,7 +474,7 @@ trait Permissions
}
// Add folder
if (!in_array(strtolower($arr[1]), ['api', 'controllers'])) {
if (! in_array(strtolower($arr[1]), ['api', 'controllers'])) {
$controller .= Str::kebab($arr[1]) . '-';
}

View File

@@ -2,6 +2,7 @@
namespace App\Traits;
use App\Models\Common\Recurring as Model;
use App\Utilities\Date;
use Recurr\Rule;
use Recurr\Transformer\ArrayTransformer;
@@ -17,18 +18,25 @@ trait Recurring
$frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency'];
$interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval'];
$started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at'];
$started_at = !empty($request['recurring_started_at']) ? $request['recurring_started_at'] : Date::now();
$status = !empty($request['recurring_status']) ? $request['recurring_status'] : Model::ACTIVE_STATUS;
$limit_by = !empty($request['recurring_limit']) ? $request['recurring_limit'] : 'count';
$limit_count = isset($request['recurring_limit_count']) ? (int) $request['recurring_limit_count'] : 0;
$limit_date = !empty($request['recurring_limit_date']) ? $request['recurring_limit_date'] : null;
$source = !empty($request['created_from']) ? $request['created_from'] : source_name();
$owner = !empty($request['created_by']) ? $request['created_by'] : user_id();
$this->recurring()->create([
'company_id' => $this->company_id,
'frequency' => $frequency,
'interval' => $interval,
'started_at' => $started_at,
'count' => (int) $request['recurring_count'],
'created_from' => $source,
'created_by' => $owner,
'company_id' => $this->company_id,
'frequency' => $frequency,
'interval' => $interval,
'started_at' => $started_at,
'status' => $status,
'limit_by' => $limit_by,
'limit_count' => $limit_count,
'limit_date' => $limit_date,
'created_from' => $source,
'created_by' => $owner,
]);
}
@@ -36,24 +44,34 @@ trait Recurring
{
if (empty($request['recurring_frequency']) || ($request['recurring_frequency'] == 'no')) {
$this->recurring()->delete();
return;
}
$frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency'];
$interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval'];
$started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at'];
$started_at = !empty($request['recurring_started_at']) ? $request['recurring_started_at'] : Date::now();
$limit_by = !empty($request['recurring_limit']) ? $request['recurring_limit'] : 'count';
$limit_count = isset($request['recurring_limit_count']) ? (int) $request['recurring_limit_count'] : 0;
$limit_date = !empty($request['recurring_limit_date']) ? $request['recurring_limit_date'] : null;
$recurring = $this->recurring();
$model_exists = $recurring->count();
$data = [
'company_id' => $this->company_id,
'frequency' => $frequency,
'interval' => $interval,
'started_at' => $started_at,
'count' => (int) $request['recurring_count'],
'company_id' => $this->company_id,
'frequency' => $frequency,
'interval' => $interval,
'started_at' => $started_at,
'limit_by' => $limit_by,
'limit_count' => $limit_count,
'limit_date' => $limit_date,
];
if (! empty($request['recurring_status'])) {
$data['status'] = $request['recurring_status'];
}
if ($model_exists) {
$recurring->update($data);
} else {
@@ -61,13 +79,14 @@ trait Recurring
$owner = !empty($request['created_by']) ? $request['created_by'] : user_id();
$recurring->create(array_merge($data, [
'created_from' => $source,
'created_by' => $owner,
'status' => Model::ACTIVE_STATUS,
'created_from' => $source,
'created_by' => $owner,
]));
}
}
public function getRecurringSchedule($set_until_date = true)
public function getRecurringSchedule()
{
$config = new ArrayTransformerConfig();
$config->enableLastDayOfMonthFix();
@@ -76,10 +95,10 @@ trait Recurring
$transformer = new ArrayTransformer();
$transformer->setConfig($config);
return $transformer->transform($this->getRecurringRule($set_until_date));
return $transformer->transform($this->getRecurringRule());
}
public function getRecurringRule($set_until_date = true)
public function getRecurringRule()
{
$rule = (new Rule())
->setStartDate($this->getRecurringRuleStartDate())
@@ -87,13 +106,11 @@ trait Recurring
->setFreq($this->getRecurringRuleFrequency())
->setInterval($this->getRecurringRuleInterval());
// 0 means infinite
if ($this->count != 0) {
$rule->setCount($this->getRecurringRuleCount());
}
if ($set_until_date) {
if ($this->limit_by == 'date') {
$rule->setUntil($this->getRecurringRuleUntilDate());
} elseif ($this->limit_count != 0) {
// 0 means infinite
$rule->setCount($this->getRecurringRuleCount());
}
return $rule;
@@ -101,12 +118,27 @@ trait Recurring
public function getRecurringRuleStartDate()
{
return new \DateTime($this->started_at, new \DateTimeZone($this->getRecurringRuleTimeZone()));
return $this->getRecurringRuleDate($this->started_at);
}
public function getRecurringRuleUntilDate()
{
return new \DateTime(Date::today()->toDateTimeString(), new \DateTimeZone($this->getRecurringRuleTimeZone()));
return $this->getRecurringRuleDate($this->limit_date);
}
public function getRecurringRuleTodayDate()
{
return $this->getRecurringRuleDate(Date::today()->toDateTimeString());
}
public function getRecurringRuleTomorrowDate()
{
return $this->getRecurringRuleDate(Date::tomorrow()->toDateTimeString());
}
public function getRecurringRuleDate($date)
{
return new \DateTime($date, new \DateTimeZone($this->getRecurringRuleTimeZone()));
}
public function getRecurringRuleTimeZone()
@@ -117,7 +149,7 @@ trait Recurring
public function getRecurringRuleCount()
{
// Fix for humans
return $this->count + 1;
return $this->limit_count + 1;
}
public function getRecurringRuleFrequency()
@@ -153,7 +185,7 @@ trait Recurring
public function getCurrentRecurring()
{
if (!$schedule = $this->getRecurringSchedule()) {
if (! $schedule = $this->getRecurringSchedule()) {
return false;
}
@@ -162,11 +194,11 @@ trait Recurring
public function getNextRecurring()
{
if (!$schedule = $this->getRecurringSchedule()) {
if (! $schedule = $this->getRecurringSchedule()) {
return false;
}
if (!$next = $schedule->next()) {
if (! $next = $schedule->next()) {
return false;
}
@@ -175,7 +207,7 @@ trait Recurring
public function getFirstRecurring()
{
if (!$schedule = $this->getRecurringSchedule()) {
if (! $schedule = $this->getRecurringSchedule()) {
return false;
}
@@ -184,7 +216,7 @@ trait Recurring
public function getLastRecurring()
{
if (!$schedule = $this->getRecurringSchedule()) {
if (! $schedule = $this->getRecurringSchedule()) {
return false;
}

View File

@@ -85,14 +85,6 @@ trait Scopes
$type = $request->get('type') ?: Str::singular((string) $request->segment(3));
if ($type == 'revenue') {
$type = 'income';
}
if ($type == 'payment') {
$type = 'expense';
}
return $type;
}
}

View File

@@ -18,7 +18,7 @@ trait Tenants
public function isTenantable()
{
$tenantable = $this->tenantable ?: true;
$tenantable = $this->tenantable ?? true;
return ($tenantable === true) && in_array('company_id', $this->getFillable());
}

View File

@@ -2,25 +2,48 @@
namespace App\Traits;
use App\Events\Banking\TransactionPrinting;
use App\Models\Banking\Transaction;
use Illuminate\Support\Str;
trait Transactions
{
public function isIncome()
public function isIncome(): bool
{
$type = $this->type ?? $this->transaction->type ?? $this->model->type ?? 'income';
return in_array($type, $this->getIncomeTypes());
}
public function isExpense()
public function isNotIncome(): bool
{
return ! $this->isIncome();
}
public function isExpense(): bool
{
$type = $this->type ?? $this->transaction->type ?? $this->model->type ?? 'expense';
return in_array($type, $this->getExpenseTypes());
}
public function isNotExpense()
{
return ! $this->isExpense();
}
public function isRecurringTransaction(): bool
{
$type = $this->type ?? $this->transaction->type ?? $this->model->type ?? 'income';
return Str::endsWith($type, '-recurring');
}
public function isNotRecurringTransaction(): bool
{
return ! $this->isRecurring();
}
public function getIncomeTypes($return = 'array')
{
return $this->getTransactionTypes('income', $return);
@@ -76,13 +99,13 @@ trait Transactions
protected function getSettingKey($type, $setting_key)
{
$key = '';
$alias = config('type.' . $type . '.alias');
$alias = config('type.transaction.' . $type . '.alias');
if (!empty($alias)) {
$key .= $alias . '.';
}
$prefix = config('type.' . $type . '.setting.prefix');
$prefix = config('type.transaction.' . $type . '.setting.prefix');
$key .= $prefix . '.' . $setting_key;
@@ -91,9 +114,9 @@ trait Transactions
public function storeTransactionPdfAndGetPath($transaction)
{
event(new \App\Events\Banking\TransactionPrinting($transaction));
event(new TransactionPrinting($transaction));
$view = view($transaction->template_path, ['revenue' => $transaction, 'transaction' => $transaction])->render();
$view = view('banking.transactions.print_default', ['transaction' => $transaction])->render();
$html = mb_convert_encoding($view, 'HTML-ENTITIES', 'UTF-8');
$pdf = app('dompdf.wrapper');
@@ -108,4 +131,62 @@ trait Transactions
return $pdf_path;
}
public function getTranslationsForConnect($type = 'income')
{
$document_type = config('type.transaction.' . $type . '.document_type');
$contact_type = config('type.transaction.' . $type . '.contact_type');
return [
'title' => trans('general.connect') . ' ' . trans_choice('general.' . Str::plural($document_type), 1),
'cancel' => trans('general.cancel'),
'save' => trans('general.save'),
'action' => trans('general.actions'),
'document' => trans_choice('general.' . Str::plural($document_type), 1),
'total' => trans('invoices.total'),
'category' => trans_choice('general.categories', 1),
'account' => trans_choice('general.accounts', 1),
'amount' => trans('general.amount'),
'number' => trans_choice('general.numbers', 1),
'notes' => trans_choice('general.notes', 2),
'contact' => trans_choice('general.' . Str::plural($contact_type), 1),
'no_data' => trans('general.no_data'),
'placeholder_search' => trans('general.placeholder.search'),
'add_an' => trans('general.form.add_an', ['field' => trans_choice('general.' . Str::plural($document_type), 1)]),
'transaction' => trans_choice('general.' . Str::plural($type), 1),
'difference' => trans('general.difference'),
];
}
public function getTransactionFormRoutesOfType($type)
{
return [
'contact_index' => route(Str::plural(config('type.transaction.' . $type . '.contact_type')) . '.index'),
'contact_modal' => route('modals.' . Str::plural(config('type.transaction.' . $type . '.contact_type')) . '.create'),
'category_index' => route('modals.categories.create', ['type' => $type]),
'category_modal' => route('categories.index', ['search' => 'type:' . $type]),
];
}
public function getRealTypeOfRecurringTransaction(string $recurring_type): string
{
return Str::replace('-recurring', '', $recurring_type);
}
public function getNextTransactionNumber($suffix = ''): string
{
$prefix = setting('transaction' . $suffix . '.number_prefix');
$next = setting('transaction' . $suffix . '.number_next');
$digit = setting('transaction' . $suffix . '.number_digit');
return $prefix . str_pad($next, $digit, '0', STR_PAD_LEFT);
}
public function increaseNextTransactionNumber($suffix = ''): void
{
$next = setting('transaction' . $suffix . '.number_next', 1) + 1;
setting(['transaction' . $suffix . '.number_next' => $next]);
setting()->save();
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Traits;
use Throwable;
trait Translations
{
public function findTranslation($keys, $number = 2)
{
try {
foreach ($keys as $key) {
if (is_array($key)) {
$tmp = $key;
$key = $tmp[0];
$number = $tmp[1];
}
if ($key != trans_choice($key, $number)) {
return trans_choice($key, $number);
}
if ($key != trans($key)) {
return trans($key);
}
}
} catch (Throwable $e) {
return '';
}
return '';
}
}

View File

@@ -2,6 +2,8 @@
namespace App\Traits;
use App\Models\Auth\UserInvitation;
trait Users
{
/**
@@ -102,8 +104,38 @@ trait Users
$route_name = $user->isCustomer() ? 'portal.dashboard' : $user->landing_page;
$company_id = company_id() ?: optional($this->getFirstCompanyOfUser())->id;
$company_id = company_id() ?: $this->getFirstCompanyOfUser()?->id;
return route($route_name, ['company_id' => $company_id]);
}
/**
* Checks if the given user has a pending invitation for the
* provided Company.
*
* @return bool
*/
public function hasPendingInvitation($company_id = null)
{
$company_id = $company_id ?: company_id();
$invitation = UserInvitation::where('user_id', $this->id)->where('company_id', $company_id)->first();
return $invitation ? true : false;
}
/**
* Returns if the given user has a pending invitation for the
* provided Company.
*
* @return null|UserInvitation
*/
public function getPendingInvitation($company_id = null)
{
$company_id = $company_id ?: company_id();
$invitation = UserInvitation::where('user_id', $this->id)->where('company_id', $company_id)->first();
return $invitation;
}
}

View File

@@ -0,0 +1,755 @@
<?php
namespace App\Traits;
use Akaunting\Module\Module;
use App\Events\Common\BulkActionsAdding;
use App\Traits\Modules;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
trait ViewComponents
{
use Modules;
public function setParentData()
{
$excludes = [
'componentName',
'attributes',
'except',
];
foreach ($this as $key => $value) {
if (in_array($key, $excludes)) {
continue;
}
$this->{$key} = $this->getParentData($key, $value);
}
}
public function getTextFromConfig($type, $config_key, $default_key = '', $trans_type = 'trans')
{
$translation = '';
// if set config translation config_key
if ($translation = config('type.' . static::OBJECT_TYPE . '.' . $type . '.translation.' . $config_key)) {
return $translation;
}
$alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias');
$prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.translation.prefix');
if (! empty($alias)) {
$alias .= '::';
}
// This magic trans key..
$translations = [
'general' => $alias . 'general.' . $default_key,
'prefix' => $alias . $prefix . '.' . $default_key,
'config_general' => $alias . 'general.' . $config_key,
'config_prefix' => $alias . $prefix . '.' . $config_key,
];
switch ($trans_type) {
case 'trans':
foreach ($translations as $trans) {
if (trans($trans) !== $trans) {
return $trans;
}
}
break;
case 'trans_choice':
foreach ($translations as $trans_choice) {
if (trans_choice($trans_choice, 1) !== $trans_choice) {
return $trans_choice;
}
}
break;
}
return $translation;
}
public function getRouteFromConfig($type, $config_key, $config_parameters = [], $modal = false)
{
$route = '';
// if set config trasnlation config_key
if ($route = config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.' . $config_key)) {
return $route;
}
$alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias');
$prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix');
// if use module set module alias
if (! empty($alias)) {
$route .= $alias . '.';
}
if ($modal == true) {
$route .= 'modals.';
}
if (! empty($prefix)) {
$route .= $prefix . '.';
}
$route .= $config_key;
try {
route($route, $config_parameters);
} catch (\Exception $e) {
try {
$route = Str::plural($type, 2) . '.' . $config_key;
route($route, $config_parameters);
} catch (\Exception $e) {
$route = '';
}
}
return $route;
}
public function getPermissionFromConfig($type, $config_key)
{
$permission = '';
// if set config trasnlation config_key
if ($permission = config('type.' . static::OBJECT_TYPE . '.' . $type . '.permission.' . $config_key)) {
return $permission;
}
$alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias');
$group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.group');
$prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.permission.prefix');
$permission = $config_key . '-';
// if use module set module alias
if (! empty($alias)) {
$permission .= $alias . '-';
}
// if controller in folder it must
if (! empty($group)) {
$permission .= $group . '-';
}
$permission .= $prefix;
return $permission;
}
public function getHideFromConfig($type, $config_key)
{
$hide = false;
$hides = config('type.' . static::OBJECT_TYPE . '.' . $type . '.hide');
if (! empty($hides) && (in_array($config_key, $hides))) {
$hide = true;
}
return $hide;
}
public function getClassFromConfig($type, $config_key)
{
$class_key = 'type.' . $type . '.class.' . $config_key;
return config($class_key, '');
}
public function getCategoryFromConfig($type)
{
$category_type = '';
// if set config trasnlation config_key
if ($category_type = config('type.' . static::OBJECT_TYPE . '.' . $type . '.category_type')) {
return $category_type;
}
switch ($type) {
case 'bill':
case 'expense':
case 'purchase':
$category_type = 'expense';
break;
case 'item':
$category_type = 'item';
break;
case 'other':
$category_type = 'other';
break;
case 'transfer':
$category_type = 'transfer';
break;
default:
$category_type = 'income';
break;
}
return $category_type;
}
public function getScriptFromConfig($type, $config_key)
{
$script_key = config('type.' . static::OBJECT_TYPE . '.' . $type . '.script.' . $config_key, '');
return $script_key;
}
protected function getTextPage($type, $textPage)
{
if (! empty($textPage)) {
return $textPage;
}
$config_route_prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix', static::DEFAULT_PLURAL_TYPE);
$page = str_replace('-', '_', $config_route_prefix);
$translation = $this->getTextFromConfig($type, 'page', $page);
if (! empty($translation)) {
return $translation;
}
return 'general.' . $page;
}
protected function getGroup($type, $group)
{
if (! empty($group)) {
return $group;
}
return config('type.' . static::OBJECT_TYPE . '.' . $type . '.group', static::DEFAULT_PLURAL_TYPE);
}
protected function getPage($type, $page)
{
if (! empty($page)) {
return $page;
}
return Str::plural($type);
}
protected function getPermissionCreate($type, $permissionCreate)
{
if (! empty($permissionCreate)) {
return $permissionCreate;
}
$permissionCreate = $this->getPermissionFromConfig($type, 'create');
return $permissionCreate;
}
protected function getPermissionUpdate($type, $permissionUpdate)
{
if (! empty($permissionUpdate)) {
return $permissionUpdate;
}
$permissionUpdate = $this->getPermissionFromConfig($type, 'update');
return $permissionUpdate;
}
protected function getPermissionDelete($type, $permissionDelete)
{
if (! empty($permissionDelete)) {
return $permissionDelete;
}
$permissionDelete = $this->getPermissionFromConfig($type, 'delete');
return $permissionDelete;
}
protected function getIndexRoute($type, $indexRoute)
{
if (! empty($indexRoute)) {
return $indexRoute;
}
$route = $this->getRouteFromConfig($type, 'index');
if (!empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.index';
}
protected function getShowRoute($type, $showRoute)
{
if (! empty($showRoute)) {
return $showRoute;
}
$route = $this->getRouteFromConfig($type, 'show', 1);
if (!empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.show';
}
protected function getCreateRoute($type, $createRoute)
{
if (! empty($createRoute)) {
return $createRoute;
}
$route = $this->getRouteFromConfig($type, 'create');
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.create';
}
protected function getEditRoute($type, $editRoute)
{
if (! empty($editRoute)) {
return $editRoute;
}
$route = $this->getRouteFromConfig($type, 'edit', 1);
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.edit';
}
protected function getDuplicateRoute($type, $duplicateRoute)
{
if (! empty($duplicateRoute)) {
return $duplicateRoute;
}
$route = $this->getRouteFromConfig($type, 'duplicate', 1);
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.duplicate';
}
protected function getDeleteRoute($type, $deleteRoute)
{
if (! empty($deleteRoute)) {
return $deleteRoute;
}
$route = $this->getRouteFromConfig($type, 'destroy', 1);
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.destroy';
}
protected function getCancelRoute($type, $cancelRoute)
{
if (! empty($cancelRoute)) {
return $cancelRoute;
}
$route = $this->getRouteFromConfig($type, 'index');
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.index';
}
protected function getImportRoute($importRoute)
{
if (! empty($importRoute)) {
return $importRoute;
}
$route = 'import.create';
return $route;
}
protected function getImportRouteParameters($type, $importRouteParameters)
{
if (! empty($importRouteParameters)) {
return $importRouteParameters;
}
$alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias');
$group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.group');
$prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix');
if (empty($group) && ! empty($alias)){
$group = $alias;
} else if (empty($group) && empty($alias)) {
$group = 'sales';
}
$importRouteParameters = [
'group' => $group,
'type' => $prefix,
];
return $importRouteParameters;
}
protected function getExportRoute($type, $exportRoute)
{
if (! empty($exportRoute)) {
return $exportRoute;
}
$route = $this->getRouteFromConfig($type, 'export');
if (! empty($route)) {
return $route;
}
return static::DEFAULT_PLURAL_TYPE . '.export';
}
protected function getSearchStringModel($type, $searchStringModel)
{
if (! empty($searchStringModel)) {
return $searchStringModel;
}
$search_string_model = config('type.' . static::OBJECT_TYPE . '.' . $type . '.search_string_model');
if (! empty($search_string_model)) {
return $search_string_model;
}
if ($group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.group')) {
$group = Str::studly(Str::singular($group)) . '\\';
}
$prefix = Str::studly(Str::singular(config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix')));
if ($alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias')) {
$searchStringModel = 'Modules\\' . Str::studly($alias) .'\Models\\' . $group . $prefix;
} else {
$searchStringModel = 'App\Models\\' . $group . $prefix;
}
return $searchStringModel;
}
protected function getBulkActionClass($type, $bulkActionClass)
{
if (! empty($bulkActionClass)) {
return $bulkActionClass;
}
$bulk_actions = config('type.' . static::OBJECT_TYPE . '.' . $type . '.bulk_actions');
if (! empty($bulk_actions)) {
return $bulk_actions;
}
$file_name = '';
if ($group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.group')) {
$file_name .= Str::studly($group) . '\\';
}
if ($prefix = config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix')) {
$file_name .= Str::studly($prefix);
}
if ($alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias')) {
$module = module($alias);
if (! $module instanceof Module) {
$b = new \stdClass();
$b->actions = [];
event(new BulkActionsAdding($b));
return $b->actions;
}
$bulkActionClass = 'Modules\\' . $module->getStudlyName() . '\BulkActions\\' . $file_name;
} else {
$bulkActionClass = 'App\BulkActions\\' . $file_name;
}
return $bulkActionClass;
}
protected function getBulkActionRouteParameters($type, $bulkActionRouteParameters)
{
if (! empty($bulkActionRouteParameters)) {
return $bulkActionRouteParameters;
}
$group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.group');
if (! empty(config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias'))) {
$group = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias');
}
$bulkActionRouteParameters = [
'group' => $group,
'type' => config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix')
];
return $bulkActionRouteParameters;
}
protected function getClassBulkAction($type, $classBulkAction)
{
if (! empty($classBulkAction)) {
return $classBulkAction;
}
$class = $this->getClassFromConfig($type, 'bulk_action');
if (! empty($class)) {
return $class;
}
return 'ltr:pr-6 rtl:pl-6 hidden sm:table-cell';
}
protected function getImageEmptyPage($type, $imageEmptyPage)
{
if (! empty($imageEmptyPage)) {
return $imageEmptyPage;
}
$image_empty_page = config('type.' . static::OBJECT_TYPE . '.' . $type . '.image_empty_page');
if (! empty($image_empty_page)) {
return $image_empty_page;
}
$page = str_replace('-', '_', config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix', 'invoices'));
$image_path = 'public/img/empty_pages/' . $page . '.png';
if ($alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias')) {
$image_path = 'modules/' . Str::studly($alias) . '/Resources/assets/img/empty_pages/' . $page . '.png';
}
return $image_path;
}
protected function getTextEmptyPage($type, $textEmptyPage)
{
if (! empty($textEmptyPage)) {
return $textEmptyPage;
}
$page = str_replace('-', '_', config('type.' . static::OBJECT_TYPE . '.' . $type . '.route.prefix', 'invoices'));
$translation = $this->getTextFromConfig($type, 'empty_page', 'empty.' . $page);
if (! empty($translation)) {
return $translation;
}
return 'general.empty.' . $page;
}
protected function getTextSectionTitle($type, $key, $default_key = '')
{
$translation = $this->getTextFromConfig($type, 'section_'. $key . '_title', $key);
if (! empty($translation)) {
return $translation;
}
if ($default_key) {
return $default_key;
}
return 'general.' . $key;
}
protected function getTextSectionDescription($type, $key, $default_key = '')
{
$translation = $this->getTextFromConfig($type, 'section_'. $key . '_description', 'form_description.' . $key);
if (! empty($translation)) {
return $translation;
}
if ($default_key) {
return $default_key;
}
return 'general.form_description.' . $key;
}
protected function getUrlDocsPath($type, $urlDocsPath)
{
if (! empty($urlDocsPath)) {
return $urlDocsPath;
}
$docs_path = config('type.' . static::OBJECT_TYPE . '.' . $type . '.docs_path');
if (! empty($docs_path)) {
return $docs_path;
}
switch ($type) {
case 'bill':
case 'expense':
case 'purchase':
$docsPath = 'purchases/bills';
break;
case 'vendor':
$docsPath = 'purchases/vendors';
break;
case 'customer':
$docsPath = 'sales/customers';
break;
case 'transaction':
$docsPath = 'banking/transactions';
break;
default:
$docsPath = 'sales/invoices';
break;
}
return 'https://akaunting.com/docs/user-manual/' . $docsPath;
}
public function getSuggestionModule()
{
return !empty($this->suggestions) ? Arr::random($this->suggestions) : false;
}
public function getSuggestionModules()
{
if ((! $user = user()) || $user->cannot('read-modules-home')) {
return [];
}
if (! $path = Route::current()->uri()) {
return [];
}
$path = str_replace('{company_id}/', '', $path);
if (! $suggestions = $this->getSuggestions($path)) {
return [];
}
$modules = [];
foreach ($suggestions->modules as $s_module) {
if ($this->moduleIsEnabled($s_module->alias)) {
continue;
}
$s_module->action_url = company_id() . '/' . $s_module->action_url;
$modules[] = $s_module;
}
if (empty($modules)) {
return [];
}
return $modules;
}
protected function getFormRoute($type, $formRoute, $model = false)
{
if (! empty($formRoute)) {
return $formRoute;
}
$prefix = 'store';
$parameters = [];
if (! empty($model)) {
$prefix = 'update';
$parameters = [$model->id];
}
$route = $this->getRouteFromConfig($type, $prefix, $parameters);
return (! empty($model)) ? [$route, $model->id] : $route;
}
protected function getFormMethod($type, $formMethod, $model = false)
{
if (! empty($formMethod)) {
return $formMethod;
}
$method = 'POST';
if (! empty($model)) {
$method = 'PATCH';
}
return $method;
}
protected function getAlias($type, $alias)
{
if (!empty($alias)) {
return $alias;
}
if ($alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias')) {
return $alias;
}
return 'core';
}
protected function getScriptFolder($type, $folder)
{
if (!empty($folder)) {
return $folder;
}
if ($folder = config('type.' . static::OBJECT_TYPE . '.' . $type . '.script.folder')) {
return $folder;
}
return '';
}
protected function getScriptFile($type, $file)
{
if (!empty($file)) {
return $file;
}
if ($file = config('type.' . static::OBJECT_TYPE . '.' . $type . '.script.file')) {
return $file;
}
return '';
}
}