akaunting 3.0 (the last dance)
This commit is contained in:
@@ -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);;
|
||||
}
|
||||
}
|
||||
|
@@ -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
47
app/Traits/Cloud.php
Normal 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
13
app/Traits/Database.php
Normal 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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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];
|
||||
}
|
||||
|
||||
|
@@ -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]) . '-';
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
34
app/Traits/Translations.php
Normal file
34
app/Traits/Translations.php
Normal 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 '';
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
755
app/Traits/ViewComponents.php
Normal file
755
app/Traits/ViewComponents.php
Normal 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 '';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user