Merge branch 'master' into master

This commit is contained in:
Cüneyt Şentürk 2021-02-23 22:07:21 +03:00 committed by GitHub
commit f5425ecdb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
284 changed files with 19538 additions and 1384 deletions

View File

@ -0,0 +1,37 @@
name: Translations of Modules
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
sync:
name: Sync
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Sync with Crowdin
uses: crowdin/github-action@master
with:
upload_sources: true
upload_translations: true
download_translations: true
skip_untranslated_files: true
localization_branch_name: 'translations-modules'
commit_message: 'new crowdin translations of modules'
pull_request_title: 'New Crowdin translations of modules'
pull_request_body: 'https://crowdin.com/project/akaunting-apps'
pull_request_labels: 'Translation'
config: 'crowdin_modules.yml'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_APPS_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@ -28,7 +28,7 @@
RewriteRule ^(app|bootstrap|config|database|overrides|resources|routes|storage|tests)/(.*) / [L,R=301]
# Prevent Direct Access To modules/vendor Folders Except Assets
RewriteRule ^(modules|vendor)/(.*)\.((?!ico|gif|jpg|jpeg|png|js|css|less|sass|font|woff|woff2|eot|ttf|svg).)*$ / [L,R=301]
RewriteRule ^(modules|vendor)/(.*)\.((?!ico|gif|jpg|jpeg|png|js\b|css|less|sass|font|woff|woff2|eot|ttf|svg).)*$ / [L,R=301]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d

View File

@ -134,7 +134,7 @@ abstract class BulkAction
try {
$this->dispatch(new UpdateContact($contact, request()->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -147,7 +147,7 @@ abstract class BulkAction
try {
$this->dispatch(new DeleteContact($contact));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -160,7 +160,7 @@ abstract class BulkAction
try {
$this->dispatch(new DeleteTransaction($transaction));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -6,12 +6,18 @@ use App\Abstracts\Http\Response;
use App\Traits\Jobs;
use App\Traits\Permissions;
use App\Traits\Relationships;
use Exception;
use ErrorException;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Exceptions\SheetNotFoundException;
use Maatwebsite\Excel\Facades\Excel;
use Throwable;
abstract class Controller extends BaseController
{
@ -66,4 +72,57 @@ abstract class Controller extends BaseController
return $response;
}
/**
* Import the excel file or catch errors
*
* @param $class
* @param $request
* @param $url
*
* @return mixed
*/
public function importExcel($class, $request)
{
try {
Excel::import($class, $request->file('import'));
$response = [
'success' => true,
'error' => false,
'data' => null,
'message' => '',
];
} catch (SheetNotFoundException | ErrorException | Exception | Throwable $e) {
$message = $e->getMessage();
$response = [
'success' => false,
'error' => true,
'data' => null,
'message' => $message,
];
}
return $response;
}
/**
* Export the excel file or catch errors
*
* @param $class
* @param $file_name
*
* @return mixed
*/
public function exportExcel($class, $file_name, $extension = 'xlsx')
{
try {
return Excel::download($class, Str::filename($file_name) . '.' . $extension);
} catch (ErrorException | Exception | Throwable $e) {
flash($e->getMessage())->error()->important();
return back();
}
}
}

View File

@ -73,7 +73,7 @@ abstract class PaymentController extends BaseController
$this->logger->info($this->module->getName() . ':: Invoice: ' . $invoice->id . ' - Cancel Message: ' . $message);
flash($message)->warning();
flash($message)->warning()->important();
$invoice_url = $this->getInvoiceUrl($invoice);

View File

@ -13,7 +13,6 @@ use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
@ -21,7 +20,7 @@ use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Validators\Failure;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithBatchInserts, WithChunkReading, WithHeadingRow, WithMapping, WithValidation
abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithChunkReading, WithHeadingRow, WithMapping, WithValidation
{
use Importable, ImportHelper;
@ -63,11 +62,6 @@ abstract class Import implements ToModel, SkipsOnError, SkipsOnFailure, WithBatc
return [];
}
public function batchSize(): int
{
return 100;
}
public function chunkSize(): int
{
return 100;

View File

@ -277,44 +277,28 @@ abstract class Report
case 'yearly':
$start->addYear();
$date = $this->getFormattedDate($start);
$this->dates[$j] = $date;
foreach ($this->tables as $table) {
$this->footer_totals[$table][$date] = 0;
}
$j += 11;
break;
case 'quarterly':
$start->addQuarter();
$date = $this->getFormattedDate($start);
$this->dates[$j] = $date;
foreach ($this->tables as $table) {
$this->footer_totals[$table][$date] = 0;
}
$j += 2;
break;
default:
$start->addMonth();
$date = $this->getFormattedDate($start);
$this->dates[$j] = $date;
foreach ($this->tables as $table) {
$this->footer_totals[$table][$date] = 0;
}
break;
}
$date = $this->getFormattedDate($start);
$this->dates[] = $date;
foreach ($this->tables as $table) {
$this->footer_totals[$table][$date] = 0;
}
}
}
@ -387,16 +371,35 @@ abstract class Report
{
switch ($this->getSetting('period')) {
case 'yearly':
$i = $date->copy()->format($this->getYearlyDateFormat());
$financial_year = $this->getFinancialYear($this->year);
if ($date->greaterThanOrEqualTo($financial_year->getStartDate()) && $date->lessThanOrEqualTo($financial_year->getEndDate())) {
if (setting('localisation.financial_denote') == 'begins') {
$i = $financial_year->getStartDate()->copy()->format($this->getYearlyDateFormat());
} else {
$i = $financial_year->getEndDate()->copy()->format($this->getYearlyDateFormat());
}
}
break;
case 'quarterly':
$start = $date->copy()->startOfQuarter()->format($this->getQuarterlyDateFormat($this->year));
$end = $date->copy()->endOfQuarter()->format($this->getQuarterlyDateFormat($this->year));
$quarters = $this->getFinancialQuarters($this->year);
foreach ($quarters as $quarter) {
if ($date->lessThan($quarter->getStartDate()) || $date->greaterThan($quarter->getEndDate())) {
continue;
}
$start = $quarter->getStartDate()->format($this->getQuarterlyDateFormat($this->year));
$end = $quarter->getEndDate()->format($this->getQuarterlyDateFormat($this->year));
}
$i = $start . '-' . $end;
break;
default:
$i = $date->copy()->format($this->getMonthlyDateFormat($this->year));
break;
}

View File

@ -11,7 +11,7 @@ abstract class Document extends Component
{
$translation = '';
// if set config trasnlation config_key
// if set config translation config_key
if ($translation = config('type.' . $type . '.translation.' . $config_key)) {
return $translation;
}

View File

@ -43,6 +43,12 @@ abstract class DocumentForm extends Base
/** @var bool */
public $hideCompanyEdit;
/** @var string */
public $titleSetting;
/** @var string */
public $subheadingSetting;
/** Company Component End */
/** Content Component Start */
@ -72,6 +78,12 @@ abstract class DocumentForm extends Base
/** @var bool */
public $hideButtons;
/** @var string */
public $footerSetting;
/** @var string */
public $notesSetting;
/** Content Component End */
/** Metadata Component Start */
@ -199,10 +211,12 @@ abstract class DocumentForm extends Base
/** Advanced Component End */
/** Company Component Start */
bool $hideLogo = false, bool $hideDocumentTitle = false, bool $hideDocumentSubheading = false, bool $hideCompanyEdit = false,
string $titleSetting = '', string $subheadingSetting = '',
/** Company Component End */
/** Content Component Start */
string $routeStore = '', string $routeUpdate = '', string $formId = 'document', string $formSubmit = 'onSubmit', string $routeCancel = '',
bool $hideCompany = false, bool $hideAdvanced = false, bool $hideFooter = false, bool $hideButtons = false,
string $footerSetting = '', string $notesSetting = '',
/** Content Component End */
/** Metadata Component Start */
$contacts = [], $contact = false, string $contactType = '', string $contactSearchRoute = '', string $contactCreateRoute = '',
@ -234,6 +248,8 @@ abstract class DocumentForm extends Base
$this->hideDocumentTitle = $hideDocumentTitle;
$this->hideDocumentSubheading = $hideDocumentSubheading;
$this->hideCompanyEdit = $hideCompanyEdit;
$this->titleSetting = $this->getTitleSettingValue($titleSetting);
$this->subheadingSetting = $this->getSubheadingSettingValue($subheadingSetting);
/** Company Component End */
/** Content Component Start */
@ -247,6 +263,8 @@ abstract class DocumentForm extends Base
$this->hideAdvanced = $hideAdvanced;
$this->hideFooter = $hideFooter;
$this->hideButtons = $hideButtons;
$this->footerSetting = $this->getFooterSettingValue($footerSetting);
$this->notesSetting = $this->getNotesSettingValue($notesSetting);
/** Content Component End */
/** Metadata Component Start */
@ -537,7 +555,7 @@ abstract class DocumentForm extends Base
if (request()->has($issued_at)) {
$issuedAt = request()->get($issued_at);
} else {
$issuedAt = request()->get('invoiced_at', Date::now()->toDateString());
$issuedAt = request()->get('invoice_at', Date::now()->toDateString());
}
return $issuedAt;
@ -572,20 +590,19 @@ abstract class DocumentForm extends Base
return $document->due_at;
}
$addDays = (setting($type . '.payment_terms', 0)) ? setting($type . '.payment_terms', 0) : setting('invoice.payment_terms', 0);
$issued_at = $type . '_at';
switch ($type) {
case 'bill':
case 'expense':
case 'purchase':
$due_at = request()->get('billed_at', Date::now()->toDateString());
break;
default:
$due_at = Date::parse(request()->get('invoiced_at', Date::now()->toDateString()))->addDays($addDays)->toDateString();
break;
if (request()->has($issued_at)) {
$issuedAt = request()->get($issued_at);
} else {
$issuedAt = Date::now()->toDateString();
}
return $due_at;
$addDays = setting($this->getSettingKey($type, 'payment_terms'), 0) ?: 0;
$dueAt = Date::parse($issuedAt)->addDays($addDays)->toDateString();
return $dueAt;
}
protected function getOrderNumber($type, $document, $orderNumber)
@ -690,8 +707,8 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if (setting($type . '.item_name', 'items') == 'custom') {
if (empty($textItems = setting($type . '.item_name_input'))) {
if (setting($this->getSettingKey($type, 'item_name'), 'items') === 'custom') {
if (empty($textItems = setting($this->getSettingKey($type, 'item_name_input')))) {
$textItems = 'general.items';
}
@ -714,8 +731,8 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if (setting($type . '.quantity_name', 'quantity') == 'custom') {
if (empty($textQuantity = setting($type . '.quantity_name_input'))) {
if (setting($this->getSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
if (empty($textQuantity = setting($this->getSettingKey($type, 'quantity_name_input')))) {
$textQuantity = 'invoices.quantity';
}
@ -738,8 +755,8 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if (setting($type . '.price_name', 'price') == 'custom') {
if (empty($textPrice = setting($type . '.price_name_input'))) {
if (setting($this->getSettingKey($type, 'price_name'), 'price') === 'custom') {
if (empty($textPrice = setting($this->getSettingKey($type, 'price_name_input')))) {
$textPrice = 'invoices.price';
}
@ -794,7 +811,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hideName = setting($type . '.hide_item_name', false)) {
if ($hideName = setting($this->getSettingKey($type, 'hide_item_name'), false)) {
return $hideName;
}
@ -815,7 +832,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hideDescription = setting($type . '.hide_item_description', false)) {
if ($hideDescription = setting($this->getSettingKey($type, 'hide_item_description'), false)) {
return $hideDescription;
}
@ -836,7 +853,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hideQuantity = setting($type . '.hide_quantity', false)) {
if ($hideQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false)) {
return $hideQuantity;
}
@ -857,7 +874,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hidePrice = setting($type . '.hide_price', false)) {
if ($hidePrice = setting($this->getSettingKey($type, 'hide_price'), false)) {
return $hidePrice;
}
@ -878,7 +895,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hideDiscount = setting($type . '.hide_discount', false)) {
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
return $hideDiscount;
}
@ -899,7 +916,7 @@ abstract class DocumentForm extends Base
}
// if you use settting translation
if ($hideAmount = setting($type . '.hide_amount', false)) {
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
return $hideAmount;
}
@ -912,4 +929,40 @@ abstract class DocumentForm extends Base
// @todo what return value invoice or always false??
return setting('invoice.hide_amount', $hideAmount);
}
protected function getTitleSettingValue($titleSetting)
{
if (!empty($titleSetting)) {
return $titleSetting;
}
return setting($this->getSettingKey($this->type, 'title'));
}
protected function getSubheadingSettingValue($subheadingSetting)
{
if (!empty($subheadingSetting)) {
return $subheadingSetting;
}
return setting($this->getSettingKey($this->type, 'subheading'));
}
protected function getFooterSettingValue($footerSetting)
{
if (!empty($footerSetting)) {
return $footerSetting;
}
return setting($this->getSettingKey($this->type, 'footer'));
}
protected function getNotesSettingValue($notesSetting)
{
if (!empty($notesSetting)) {
return $notesSetting;
}
return setting($this->getSettingKey($this->type, 'notes'));
}
}

View File

@ -155,6 +155,12 @@ abstract class DocumentIndex extends Base
/** @var string */
public $routeButtonDelete;
/** @var string */
public $textModalDelete;
/** @var string */
public $valueModalDelete;
/** @var bool */
public $hideButtonShow;
@ -194,7 +200,7 @@ abstract class DocumentIndex extends Base
* @return void
*/
public function __construct(
string $type, $documents = [], $limits = [],
string $type, $documents = [], $limits = [],
string $imageEmptyPage = '', string $textEmptyPage = '', string $textPage = '', string $urlDocsPath = '', $hideEmptyPage = false,
bool $checkPermissionCreate = true, string $createRoute = '', string $importRoute = '', array $importRouteParameters = [], string $exportRoute = '',
bool $hideCreate = false, bool $hideImport = false, bool $hideExport = false, // Advanced
@ -204,6 +210,7 @@ abstract class DocumentIndex extends Base
string $textDocumentNumber = '', string $textContactName = '', string $classAmount = '', string $textIssuedAt = '', string $textDueAt = '', string $textDocumentStatus = '',
bool $checkButtonReconciled = true, bool $checkButtonCancelled = true,
string $routeButtonShow = '', string $routeButtonEdit = '', string $routeButtonDuplicate = '', string $routeButtonCancelled = '', string $routeButtonDelete = '',
string $textModalDelete = '', string $valueModalDelete = 'document_number',
bool $hideDocumentNumber = false, bool $hideContactName = false, bool $hideAmount = false, bool $hideIssuedAt = false, bool $hideDueAt = false, bool $hideStatus = false, bool $hideActions = false,
bool $hideButtonShow = false, bool $hideButtonEdit = false, bool $hideButtonDuplicate = false, bool $hideButtonCancel = false, bool $hideButtonDelete = false,
string $permissionCreate = '', string $permissionUpdate = '', string $permissionDelete = ''
@ -260,6 +267,9 @@ abstract class DocumentIndex extends Base
$this->routeButtonCancelled = $this->getRouteButtonCancelled($type, $routeButtonCancelled);
$this->routeButtonDelete = $this->getRouteButtonDelete($type, $routeButtonDelete);
$this->textModalDelete = $this->getTextModalDelete($type, $textModalDelete);
$this->valueModalDelete = $valueModalDelete;
$this->hideBulkAction = $hideBulkAction;
$this->hideDocumentNumber = $hideDocumentNumber;
$this->hideContactName = $hideContactName;
@ -915,6 +925,19 @@ abstract class DocumentIndex extends Base
return 'invoices.destroy';
}
protected function getTextModalDelete($type, $textModalDelete)
{
if (!empty($textModalDelete)) {
return $textModalDelete;
}
if ($alias = config('type.' . $type . '.alias')) {
return $alias . '::general.' . Str::plural(str_replace('-', '_', $type));
}
return '';
}
protected function getPermissionCreate($type, $permissionCreate)
{
if (!empty($permissionCreate)) {

View File

@ -3,19 +3,21 @@
namespace App\Abstracts\View\Components;
use App\Abstracts\View\Components\Document as Base;
use App\Traits\DateTime;
use App\Models\Common\Media;
use App\Traits\DateTime;
use App\Traits\Documents;
use File;
use Image;
use Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
use Image;
use Intervention\Image\Exception\NotReadableException;
use Storage;
abstract class DocumentShow extends Base
{
use DateTime;
use Documents;
public $type;
@ -28,7 +30,7 @@ abstract class DocumentShow extends Base
public $logo;
/** @var string */
public $backGroundColor;
public $backgroundColor;
/** @var string */
public $signedUrl;
@ -359,7 +361,7 @@ abstract class DocumentShow extends Base
* @return void
*/
public function __construct(
$type, $document, $documentTemplate = '', $logo = '', $backGroundColor = '', string $signedUrl = '', $histories = [], $transactions = [],
$type, $document, $documentTemplate = '', $logo = '', $backgroundColor = '', string $signedUrl = '', $histories = [], $transactions = [],
string $textRecurringType = '', string $textStatusMessage = '', string $textHistories = '', string $textHistoryStatus = '',
string $routeButtonAddNew = '', string $routeButtonEdit = '', string $routeButtonDuplicate = '', string $routeButtonPrint = '', string $routeButtonPdf = '', string $routeButtonCancelled = '', string $routeButtonDelete = '', string $routeButtonCustomize = '', string $routeButtonSent = '',
string $routeButtonReceived = '', string $routeButtonEmail = '', string $routeButtonPaid = '',
@ -387,7 +389,7 @@ abstract class DocumentShow extends Base
$this->document = $document;
$this->documentTemplate = $this->getDocumentTemplate($type, $documentTemplate);
$this->logo = $this->getLogo($logo);
$this->backGroundColor = $backGroundColor;
$this->backgroundColor = $backgroundColor;
$this->signedUrl = $this->getSignedUrl($type, $signedUrl);
$this->histories = ($histories) ? $histories : $document->histories;
@ -578,7 +580,7 @@ abstract class DocumentShow extends Base
$type = $alias . '.' . str_replace('-', '_', $type);
}
$documentTemplate = setting($type . '.template') ?: 'default';
$documentTemplate = setting($this->getSettingKey($type, 'template')) ?: 'default';
return $documentTemplate;
}
@ -1384,7 +1386,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hideName = setting($type . '.hide_item_name', false)) {
if ($hideName = setting($this->getSettingKey($type, 'hide_item_name'), false)) {
return $hideName;
}
@ -1405,7 +1407,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hideDescription = setting($type . '.hide_item_description', false)) {
if ($hideDescription = setting($this->getSettingKey($type, 'hide_item_description'), false)) {
return $hideDescription;
}
@ -1426,7 +1428,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hideQuantity = setting($type . '.hide_quantity', false)) {
if ($hideQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false)) {
return $hideQuantity;
}
@ -1447,7 +1449,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hidePrice = setting($type . '.hide_price', false)) {
if ($hidePrice = setting($this->getSettingKey($type, 'hide_price'), false)) {
return $hidePrice;
}
@ -1468,7 +1470,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hideDiscount = setting($type . '.hide_discount', false)) {
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
return $hideDiscount;
}
@ -1489,7 +1491,7 @@ abstract class DocumentShow extends Base
}
// if you use settting translation
if ($hideAmount = setting($type . '.hide_amount', false)) {
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
return $hideAmount;
}

View File

@ -3,18 +3,19 @@
namespace App\Abstracts\View\Components;
use App\Abstracts\View\Components\Document as Base;
use App\Traits\DateTime;
use App\Models\Common\Media;
use App\Traits\DateTime;
use App\Traits\Documents;
use File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Intervention\Image\Exception\NotReadableException;
use Image;
use Intervention\Image\Exception\NotReadableException;
use Storage;
abstract class DocumentTemplate extends Base
{
use DateTime;
use Documents;
public $type;
@ -29,7 +30,7 @@ abstract class DocumentTemplate extends Base
public $logo;
public $backGroundColor;
public $backgroundColor;
public $hideFooter;
@ -129,7 +130,7 @@ abstract class DocumentTemplate extends Base
$this->document = $document;
$this->documentTemplate = $this->getDocumentTemplate($type, $documentTemplate);
$this->logo = $this->getLogo($logo);
$this->backGroundColor = $this->getBackgroundColor($type, $backgroundColor);
$this->backgroundColor = $this->getBackgroundColor($type, $backgroundColor);
$this->hideFooter = $hideFooter;
$this->hideCompanyLogo = $hideCompanyLogo;
@ -181,7 +182,7 @@ abstract class DocumentTemplate extends Base
return $template;
}
$documentTemplate = setting($type . '.template', 'default');
$documentTemplate = setting($this->getSettingKey($type, 'template'), 'default');
return $documentTemplate;
}
@ -244,7 +245,12 @@ abstract class DocumentTemplate extends Base
return $background_color;
}
$backgroundColor = setting($type . '.color', '#55588b');
if (!empty($alias = config('type.' . $type . '.alias'))) {
$type = $alias . '.' . str_replace('-', '_', $type);
}
$backgroundColor = setting($this->getSettingKey($type, 'color'), '#55588b');
return $backgroundColor;
}
@ -364,8 +370,8 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if (setting($type . '.item_name', 'items') == 'custom') {
if (empty($textItems = setting($type . '.item_name_input'))) {
if (setting($this->getSettingKey($type, 'item_name'), 'items') == 'custom') {
if (empty($textItems = setting($this->getSettingKey($type, 'item_name_input')))) {
$textItems = 'general.items';
}
@ -388,8 +394,8 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if (setting($type . '.quantity_name', 'quantity') == 'custom') {
if (empty($textQuantity = setting($type . '.quantity_name_input'))) {
if (setting($this->getSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
if (empty($textQuantity = setting($this->getSettingKey($type, 'quantity_name_input')))) {
$textQuantity = 'invoices.quantity';
}
@ -412,8 +418,8 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if (setting($type . '.price_name', 'price') == 'custom') {
if (empty($textPrice = setting($type . '.price_name_input'))) {
if (setting($this->getSettingKey($type, 'price_name'), 'price') === 'custom') {
if (empty($textPrice = setting($this->getSettingKey($type, 'price_name_input')))) {
$textPrice = 'invoices.price';
}
@ -468,7 +474,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hideName = setting($type . '.hide_item_name', false)) {
if ($hideName = setting($this->getSettingKey($type, 'hide_item_name'), false)) {
return $hideName;
}
@ -489,7 +495,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hideDescription = setting($type . '.hide_item_description', false)) {
if ($hideDescription = setting($this->getSettingKey($type, 'hide_item_description'), false)) {
return $hideDescription;
}
@ -510,7 +516,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hideQuantity = setting($type . '.hide_quantity', false)) {
if ($hideQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false)) {
return $hideQuantity;
}
@ -531,7 +537,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hidePrice = setting($type . '.hide_price', false)) {
if ($hidePrice = setting($this->getSettingKey($type, 'hide_price'), false)) {
return $hidePrice;
}
@ -552,7 +558,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hideDiscount = setting($type . '.hide_discount', false)) {
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
return $hideDiscount;
}
@ -573,7 +579,7 @@ abstract class DocumentTemplate extends Base
}
// if you use settting translation
if ($hideAmount = setting($type . '.hide_amount', false)) {
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
return $hideAmount;
}

View File

@ -37,7 +37,7 @@ class Users extends BulkAction
try {
$this->dispatch(new UpdateUser($user, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Users extends BulkAction
try {
$this->dispatch(new DeleteUser($user));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Accounts extends BulkAction
try {
$this->dispatch(new UpdateAccount($account, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Accounts extends BulkAction
try {
$this->dispatch(new DeleteAccount($account));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -32,7 +32,7 @@ class Transfers extends BulkAction
try {
$this->dispatch(new DeleteTransfer($transfer));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Companies extends BulkAction
try {
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 1]), session('company_id')));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Companies extends BulkAction
try {
$this->dispatch(new UpdateCompany($company, $request->merge(['enabled' => 0]), session('company_id')));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -63,7 +63,7 @@ class Companies extends BulkAction
try {
$this->dispatch(new DeleteCompany($company, session('company_id')));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Dashboards extends BulkAction
try {
$this->dispatch(new UpdateDashboard($dashboard, $request->merge(['enabled' => 1])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Dashboards extends BulkAction
try {
$this->dispatch(new UpdateDashboard($dashboard, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -63,7 +63,7 @@ class Dashboards extends BulkAction
try {
$this->dispatch(new DeleteDashboard($dashboard));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -46,7 +46,7 @@ class Items extends BulkAction
try {
$this->dispatch(new DeleteItem($item));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -95,7 +95,7 @@ class Bills extends BulkAction
try {
$this->dispatch(new DeleteDocument($bill));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -99,7 +99,7 @@ class Invoices extends BulkAction
try {
$this->dispatch(new DeleteDocument($invoice));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Categories extends BulkAction
try {
$this->dispatch(new UpdateCategory($category, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Categories extends BulkAction
try {
$this->dispatch(new DeleteCategory($category));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Currencies extends BulkAction
try {
$this->dispatch(new UpdateCurrency($currency, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Currencies extends BulkAction
try {
$this->dispatch(new DeleteCurrency($currency));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -37,7 +37,7 @@ class Taxes extends BulkAction
try {
$this->dispatch(new UpdateTax($tax, $request->merge(['enabled' => 0])));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}
@ -50,7 +50,7 @@ class Taxes extends BulkAction
try {
$this->dispatch(new DeleteTax($tax));
} catch (\Exception $e) {
flash($e->getMessage())->error();
flash($e->getMessage())->error()->important();
}
}
}

View File

@ -86,7 +86,7 @@ class Handler extends ExceptionHandler
return response()->json(['error' => 'Not Found'], 404);
}
flash(trans('errors.body.page_not_found'))->error();
flash(trans('errors.body.page_not_found'))->error()->important();
// normal 404 view page feedback
return redirect()

View File

@ -4,12 +4,14 @@ namespace App\Exports\Banking;
use App\Abstracts\Export;
use App\Models\Banking\Transaction as Model;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class Transactions extends Export
class Transactions extends Export implements WithColumnFormatting
{
public function collection()
{
$model = Model::with('account', 'bill', 'category', 'contact', 'invoice')->usingSearchString(request('search'));
$model = Model::with('account', 'category', 'contact', 'document')->usingSearchString(request('search'));
if (!empty($this->ids)) {
$model->whereIn('id', (array) $this->ids);
@ -23,12 +25,7 @@ class Transactions extends Export
$model->account_name = $model->account->name;
$model->contact_email = $model->contact->email;
$model->category_name = $model->category->name;
if ($model->type == 'income') {
$model->invoice_bill_number = $model->invoice->document_number ?? 0;
} else {
$model->invoice_bill_number = $model->bill->document_number ?? 0;
}
$model->invoice_bill_number = $model->document->document_number ?? 0;
return parent::map($model);
}
@ -51,4 +48,11 @@ class Transactions extends Export
'reconciled',
];
}
public function columnFormats(): array
{
return [
'B' => NumberFormat::FORMAT_DATE_YYYYMMDD,
];
}
}

View File

@ -4,8 +4,10 @@ namespace App\Exports\Purchases;
use App\Abstracts\Export;
use App\Models\Banking\Transaction as Model;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class Payments extends Export
class Payments extends Export implements WithColumnFormatting
{
public function collection()
{
@ -45,4 +47,11 @@ class Payments extends Export
'reconciled',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_DATE_YYYYMMDD,
];
}
}

View File

@ -4,8 +4,10 @@ namespace App\Exports\Sales;
use App\Abstracts\Export;
use App\Models\Banking\Transaction as Model;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class Revenues extends Export
class Revenues extends Export implements WithColumnFormatting
{
public function collection()
{
@ -45,4 +47,11 @@ class Revenues extends Export
'reconciled',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_DATE_YYYYMMDD,
];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Exports\Settings;
use App\Abstracts\Export;
use App\Models\Setting\Category as Model;
class Categories extends Export
{
public function collection()
{
$model = Model::usingSearchString(request('search'));
if (!empty($this->ids)) {
$model->whereIn('id', (array) $this->ids);
}
return $model->cursor();
}
public function fields(): array
{
return [
'name',
'type',
'color',
'enabled',
];
}
}

View File

@ -55,7 +55,7 @@ class Permissions extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -96,7 +96,7 @@ class Permissions extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -122,7 +122,7 @@ class Permissions extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -63,7 +63,7 @@ class Roles extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -111,7 +111,7 @@ class Roles extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -137,7 +137,7 @@ class Roles extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -85,7 +85,7 @@ class Users extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -167,7 +167,7 @@ class Users extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -229,7 +229,7 @@ class Users extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -70,7 +70,7 @@ class Accounts extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -117,7 +117,7 @@ class Accounts extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -179,7 +179,7 @@ class Accounts extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -85,7 +85,7 @@ class Reconciliations extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -134,7 +134,7 @@ class Reconciliations extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -160,7 +160,7 @@ class Reconciliations extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -42,13 +42,23 @@ class Transactions extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.transactions', 2)]);
if ($response['success']) {
$response['redirect'] = route('transactions.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.transactions', 2)]);
return redirect()->route('transactions.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['banking', 'transactions']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -71,7 +81,7 @@ class Transactions extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -84,6 +94,6 @@ class Transactions extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.transactions', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.transactions', 2));
}
}

View File

@ -25,64 +25,11 @@ class Transfers extends Controller
*/
public function index()
{
$data = [];
$items = Transfer::with(
$transfers = Transfer::with(
'expense_transaction', 'expense_transaction.account', 'income_transaction', 'income_transaction.account'
)->collect(['expense_transaction.paid_at' => 'desc']);
foreach ($items as $item) {
$income_transaction = $item->income_transaction;
$expense_transaction = $item->expense_transaction;
$name = trans('transfers.messages.delete', [
'from' => $expense_transaction->account->name,
'to' => $income_transaction->account->name,
'amount' => money($expense_transaction->amount, $expense_transaction->currency_code, true)
]);
$data[] = (object) [
'id' => $item->id,
'name' => $name,
'from_account' => $expense_transaction->account->name,
'to_account' => $income_transaction->account->name,
'amount' => $expense_transaction->amount,
'currency_code' => $expense_transaction->currency_code,
'paid_at' => $expense_transaction->paid_at,
];
}
$special_key = [
'expense_transaction.name' => 'from_account',
'income_transaction.name' => 'to_account',
];
$request = request();
if (isset($request['sort']) && array_key_exists($request['sort'], $special_key)) {
$sort_order = [];
foreach ($data as $key => $value) {
$sort = $request['sort'];
if (array_key_exists($request['sort'], $special_key)) {
$sort = $special_key[$request['sort']];
}
$sort_order[$key] = $value->{$sort};
}
$sort_type = (isset($request['order']) && $request['order'] == 'asc') ? SORT_ASC : SORT_DESC;
array_multisort($sort_order, $sort_type, $data);
}
$transfers = $request->expectsJson() ? $data : $this->paginate($data);
$accounts = collect(Account::enabled()->orderBy('name')->pluck('name', 'id'))
->prepend(trans('general.all_type', ['type' => trans_choice('general.accounts', 2)]), '');
return $this->response('banking.transfers.index', compact('transfers', 'accounts'));
return $this->response('banking.transfers.index', compact('transfers'));
}
/**
@ -133,7 +80,35 @@ class Transfers extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
}
/**
* Import the specified resource.
*
* @param ImportRequest $request
*
* @return Response
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
if ($response['success']) {
$response['redirect'] = route('transfers.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.transfers', 2)]);
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['banking', 'transfers']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
@ -190,7 +165,7 @@ class Transfers extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -216,30 +191,12 @@ class Transfers extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
}
/**
* Import the specified resource.
*
* @param ImportRequest $request
*
* @return Response
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$message = trans('messages.success.imported', ['type' => trans_choice('general.transfers', 2)]);
flash($message)->success();
return redirect()->route('transfers.index');
}
/**
* Export the specified resource.
*
@ -247,6 +204,6 @@ class Transfers extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.transfers', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.transfers', 2));
}
}

View File

@ -42,7 +42,7 @@ class BulkActions extends Controller
}
if (isset($bulk_actions->actions[$request->get('handle')]['permission']) && !user()->can($bulk_actions->actions[$request->get('handle')]['permission'])) {
flash(trans('errors.message.403'))->error();
flash(trans('errors.message.403'))->error()->important();
return response()->json([
'success' => false,

View File

@ -75,7 +75,7 @@ class Companies extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
session(['company_id' => $company_id]);
@ -128,7 +128,7 @@ class Companies extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
session(['company_id' => $company_id]);
@ -194,7 +194,7 @@ class Companies extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -110,7 +110,7 @@ class Dashboards extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -156,7 +156,7 @@ class Dashboards extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -220,7 +220,7 @@ class Dashboards extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -78,7 +78,7 @@ class Items extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -111,13 +111,23 @@ class Items extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.items', 2)]);
if ($response['success']) {
$response['redirect'] = route('items.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.items', 2)]);
return redirect()->route('items.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['common', 'items']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -162,7 +172,7 @@ class Items extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -224,7 +234,7 @@ class Items extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -237,7 +247,7 @@ class Items extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.items', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.items', 2));
}
public function autocomplete()

View File

@ -13,6 +13,17 @@ use Illuminate\Support\Facades\Cache;
class Reports extends Controller
{
/**
* Instantiate a new controller instance.
*/
public function __construct()
{
// Add CRUD permission check
$this->middleware('permission:create-common-reports')->only('create', 'store', 'duplicate', 'import');
$this->middleware('permission:read-common-reports')->only('index', 'show', 'export');
$this->middleware('permission:update-common-reports')->only('edit', 'update', 'enable', 'disable');
$this->middleware('permission:delete-common-reports')->only('destroy');
}
/**
* Display a listing of the resource.
*
@ -101,7 +112,7 @@ class Reports extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -163,7 +174,7 @@ class Reports extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -189,7 +200,7 @@ class Reports extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -142,7 +142,7 @@ class Uploads extends Controller
if (!$path = $this->getPath($media)) {
$message = trans('messages.warning.deleted', ['name' => $media->basename, 'text' => $media->basename]);
flash($message)->warning();
flash($message)->warning()->important();
return $return;
}

View File

@ -4,10 +4,13 @@ namespace App\Http\Controllers\Modals;
use App\Abstracts\Http\Controller;
use App\Http\Requests\Setting\Setting as Request;
use App\Traits\Documents;
class DocumentItemColumns extends Controller
{
public $skip_keys = ['company_id', '_method', '_token', '_prefix', '_template', 'type'];
use Documents;
public $skip_keys = ['company_id', '_method', '_token', '_template', 'type'];
public function __construct()
{
@ -54,12 +57,35 @@ class DocumentItemColumns extends Controller
'90' => trans('settings.invoice.due_days', ['days' => 90]),
];
$item_name = setting($this->getSettingKey($type, 'item_name'));
$item_name_input = setting($this->getSettingKey($type, 'item_name_input'));
$price_name = setting($this->getSettingKey($type, 'price_name'));
$price_name_input = setting($this->getSettingKey($type, 'price_name_input'));
$quantity_name = setting($this->getSettingKey($type, 'quantity_name'));
$quantity_name_input = setting($this->getSettingKey($type, 'quantity_name_input'));
$hide_item_name = setting($this->getSettingKey($type, 'hide_item_name'));
$hide_item_description = setting($this->getSettingKey($type, 'hide_item_description'));
$hide_quantity = setting($this->getSettingKey($type, 'hide_quantity'));
$hide_price = setting($this->getSettingKey($type, 'hide_price'));
$hide_amount = setting($this->getSettingKey($type, 'hide_amount'));
$html = view('modals.documents.item_columns', compact(
'type',
'item_names',
'price_names',
'quantity_names',
'payment_terms'
'payment_terms',
'item_name',
'item_name_input',
'price_name',
'price_name_input',
'quantity_name',
'quantity_name_input',
'hide_item_name',
'hide_item_description',
'hide_quantity',
'hide_price',
'hide_amount',
))->render();
return response()->json([
@ -80,7 +106,7 @@ class DocumentItemColumns extends Controller
public function update(Request $request)
{
$fields = $request->all();
$prefix = $request->get('_prefix', 'invoice');
$type = $request->get('type', 'invoice');
$company_id = $request->get('company_id');
if (empty($company_id)) {
@ -88,7 +114,7 @@ class DocumentItemColumns extends Controller
}
foreach ($fields as $key => $value) {
$real_key = $prefix . '.' . $key;
$real_key = $this->getSettingKey($type, $key);
// Don't process unwanted keys
if (in_array($key, $this->skip_keys)) {

View File

@ -259,7 +259,7 @@ class Item extends Controller
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
$json = [
'success' => false,
@ -285,7 +285,7 @@ class Item extends Controller
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
}
return redirect()->route('apps.app.show', $alias)->send();
@ -304,7 +304,7 @@ class Item extends Controller
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
}
return redirect()->route('apps.app.show', $alias)->send();
@ -323,7 +323,7 @@ class Item extends Controller
} catch (\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
}
return redirect()->route('apps.app.show', $alias)->send();

View File

@ -95,7 +95,7 @@ class Bills extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -128,19 +128,23 @@ class Bills extends Controller
*/
public function import(ImportRequest $request)
{
try {
\Excel::import(new Import(), $request->file('import'));
} catch (\Maatwebsite\Excel\Exceptions\SheetNotFoundException $e) {
flash($e->getMessage())->error()->important();
$response = $this->importExcel(new Import, $request);
return redirect()->route('import.create', ['purchases', 'bills']);
if ($response['success']) {
$response['redirect'] = route('bills.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.bills', 1)]);
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'bills']);
$message = $response['message'];
flash($message)->error()->important();
}
$message = trans('messages.success.imported', ['type' => trans_choice('general.bills', 2)]);
flash($message)->success();
return redirect()->route('bills.index');
return response()->json($response);
}
/**
@ -178,7 +182,7 @@ class Bills extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -204,7 +208,7 @@ class Bills extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -217,7 +221,7 @@ class Bills extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.bills', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.bills', 2));
}
/**
@ -314,7 +318,7 @@ class Bills extends Controller
} catch(\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
}
return redirect()->back();

View File

@ -66,7 +66,17 @@ class Payments extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('purchases.payments.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'vendors', 'categories', 'payment_methods'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('purchases.payments.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'vendors', 'categories', 'payment_methods', 'file_types'));
}
/**
@ -91,7 +101,7 @@ class Payments extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -124,13 +134,23 @@ class Payments extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.payments', 2)]);
if ($response['success']) {
$response['redirect'] = route('payments.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.payments', 2)]);
return redirect()->route('payments.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'payments']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -164,7 +184,17 @@ class Payments extends Controller
$date_format = $this->getCompanyDateFormat();
return view('purchases.payments.edit', compact('payment', 'accounts', 'currencies', 'currency', 'vendors', 'categories', 'payment_methods', 'date_format'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('purchases.payments.edit', compact('payment', 'accounts', 'currencies', 'currency', 'vendors', 'categories', 'payment_methods', 'date_format', 'file_types'));
}
/**
@ -190,7 +220,7 @@ class Payments extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -216,7 +246,7 @@ class Payments extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -229,6 +259,6 @@ class Payments extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.payments', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.payments', 2));
}
}

View File

@ -128,7 +128,7 @@ class Vendors extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -161,13 +161,23 @@ class Vendors extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.vendors', 2)]);
if ($response['success']) {
$response['redirect'] = route('vendors.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.vendors', 2)]);
return redirect()->route('vendors.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['purchases', 'vendors']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -207,7 +217,7 @@ class Vendors extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -269,7 +279,7 @@ class Vendors extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -282,7 +292,7 @@ class Vendors extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.vendors', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.vendors', 2));
}
public function currency(Contact $vendor)

View File

@ -126,7 +126,7 @@ class Customers extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -159,13 +159,23 @@ class Customers extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 2)]);
if ($response['success']) {
$response['redirect'] = route('customers.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 1)]);
return redirect()->route('customers.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'customers']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -205,7 +215,7 @@ class Customers extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -267,7 +277,7 @@ class Customers extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -280,7 +290,7 @@ class Customers extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.customers', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.customers', 2));
}
public function currency(Contact $customer)

View File

@ -13,7 +13,6 @@ use App\Jobs\Document\DuplicateDocument;
use App\Jobs\Document\UpdateDocument;
use App\Models\Document\Document;
use App\Notifications\Sale\Invoice as Notification;
use App\Models\Setting\Currency;
use App\Traits\Documents;
use File;
@ -95,7 +94,7 @@ class Invoices extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -128,19 +127,23 @@ class Invoices extends Controller
*/
public function import(ImportRequest $request)
{
try {
\Excel::import(new Import(), $request->file('import'));
} catch (\Maatwebsite\Excel\Exceptions\SheetNotFoundException $e) {
flash($e->getMessage())->error()->important();
$response = $this->importExcel(new Import, $request);
return redirect()->route('import.create', ['sales', 'invoices']);
if ($response['success']) {
$response['redirect'] = route('invoices.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.invoices', 2)]);
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'invoices']);
$message = $response['message'];
flash($message)->error()->important();
}
$message = trans('messages.success.imported', ['type' => trans_choice('general.invoices', 2)]);
flash($message)->success();
return redirect()->route('invoices.index');
return response()->json($response);
}
/**
@ -178,7 +181,7 @@ class Invoices extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -204,7 +207,7 @@ class Invoices extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -217,7 +220,7 @@ class Invoices extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.invoices', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.invoices', 2));
}
/**
@ -364,7 +367,7 @@ class Invoices extends Controller
} catch(\Exception $e) {
$message = $e->getMessage();
flash($message)->error();
flash($message)->error()->important();
}
return redirect()->back();

View File

@ -66,7 +66,17 @@ class Revenues extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('sales.revenues.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'customers', 'categories', 'payment_methods'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('sales.revenues.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'customers', 'categories', 'payment_methods', 'file_types'));
}
/**
@ -91,7 +101,7 @@ class Revenues extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -124,13 +134,23 @@ class Revenues extends Controller
*/
public function import(ImportRequest $request)
{
\Excel::import(new Import(), $request->file('import'));
$response = $this->importExcel(new Import, $request);
$message = trans('messages.success.imported', ['type' => trans_choice('general.revenues', 2)]);
if ($response['success']) {
$response['redirect'] = route('revenues.index');
flash($message)->success();
$message = trans('messages.success.imported', ['type' => trans_choice('general.revenues', 2)]);
return redirect()->route('revenues.index');
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['sales', 'revenues']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
}
/**
@ -164,7 +184,17 @@ class Revenues extends Controller
$date_format = $this->getCompanyDateFormat();
return view('sales.revenues.edit', compact('revenue', 'accounts', 'currencies', 'currency', 'customers', 'categories', 'payment_methods', 'date_format'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('sales.revenues.edit', compact('revenue', 'accounts', 'currencies', 'currency', 'customers', 'categories', 'payment_methods', 'date_format', 'file_types'));
}
/**
@ -190,7 +220,7 @@ class Revenues extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -216,7 +246,7 @@ class Revenues extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -229,6 +259,6 @@ class Revenues extends Controller
*/
public function export()
{
return \Excel::download(new Export(), \Str::filename(trans_choice('general.revenues', 2)) . '.xlsx');
return $this->exportExcel(new Export, trans_choice('general.revenues', 2));
}
}

View File

@ -3,14 +3,19 @@
namespace App\Http\Controllers\Settings;
use App\Abstracts\Http\Controller;
use App\Exports\Settings\Categories as Export;
use App\Http\Requests\Common\Import as ImportRequest;
use App\Http\Requests\Setting\Category as Request;
use App\Imports\Settings\Categories as Import;
use App\Jobs\Setting\CreateCategory;
use App\Jobs\Setting\DeleteCategory;
use App\Jobs\Setting\UpdateCategory;
use App\Models\Setting\Category;
use App\Traits\Categories as Helper;
class Categories extends Controller
{
use Helper;
/**
* Display a listing of the resource.
@ -23,12 +28,7 @@ class Categories extends Controller
$transfer_id = Category::transfer();
$types = collect([
'expense' => trans_choice('general.expenses', 1),
'income' => trans_choice('general.incomes', 1),
'item' => trans_choice('general.items', 1),
'other' => trans_choice('general.others', 1),
]);
$types = $this->getCategoryTypes();
return $this->response('settings.categories.index', compact('categories', 'types', 'transfer_id'));
}
@ -50,12 +50,7 @@ class Categories extends Controller
*/
public function create()
{
$types = [
'expense' => trans_choice('general.expenses', 1),
'income' => trans_choice('general.incomes', 1),
'item' => trans_choice('general.items', 1),
'other' => trans_choice('general.others', 1),
];
$types = $this->getCategoryTypes();
return view('settings.categories.create', compact('types'));
}
@ -82,7 +77,35 @@ class Categories extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
}
/**
* Import the specified resource.
*
* @param ImportRequest $request
*
* @return Response
*/
public function import(ImportRequest $request)
{
$response = $this->importExcel(new Import, $request);
if ($response['success']) {
$response['redirect'] = route('categories.index');
$message = trans('messages.success.imported', ['type' => trans_choice('general.categories', 2)]);
flash($message)->success();
} else {
$response['redirect'] = route('import.create', ['settings', 'categories']);
$message = $response['message'];
flash($message)->error()->important();
}
return response()->json($response);
@ -97,12 +120,7 @@ class Categories extends Controller
*/
public function edit(Category $category)
{
$types = [
'expense' => trans_choice('general.expenses', 1),
'income' => trans_choice('general.incomes', 1),
'item' => trans_choice('general.items', 1),
'other' => trans_choice('general.others', 1),
];
$types = $this->getCategoryTypes();
$type_disabled = (Category::where('type', $category->type)->count() == 1) ?: false;
@ -132,7 +150,7 @@ class Categories extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -194,12 +212,22 @@ class Categories extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
}
/**
* Export the specified resource.
*
* @return Response
*/
public function export()
{
return $this->exportExcel(new Export, trans_choice('general.categories', 2));
}
public function category(Request $request)
{
$category = $this->dispatch(new CreateCategory($request));

View File

@ -90,7 +90,7 @@ class Currencies extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -158,7 +158,7 @@ class Currencies extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -220,7 +220,7 @@ class Currencies extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -41,12 +41,18 @@ class Localisation extends Controller
'both' => trans('settings.localisation.discount_location.both'),
];
$financial_denote_options = [
'begins' => trans('settings.localisation.financial_denote.begins'),
'ends' => trans('settings.localisation.financial_denote.ends'),
];
return view('settings.localisation.edit', compact(
'timezones',
'date_formats',
'date_separators',
'percent_positions',
'discount_locations'
'discount_locations',
'financial_denote_options'
));
}
}

View File

@ -88,7 +88,7 @@ class Taxes extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -143,7 +143,7 @@ class Taxes extends Controller
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -205,7 +205,7 @@ class Taxes extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -68,7 +68,7 @@ class Currencies extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -95,7 +95,7 @@ class Currencies extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -121,7 +121,7 @@ class Currencies extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -55,7 +55,7 @@ class Taxes extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -82,7 +82,7 @@ class Taxes extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);
@ -108,7 +108,7 @@ class Taxes extends Controller
} else {
$message = $response['message'];
flash($message)->error();
flash($message)->error()->important();
}
return response()->json($response);

View File

@ -148,6 +148,7 @@ class Kernel extends HttpKernel
'company.currencies' => \App\Http\Middleware\LoadCurrencies::class,
'company.settings' => \App\Http\Middleware\LoadSettings::class,
'company.signed' => \App\Http\Middleware\SignedCompany::class,
'dropzone' => \App\Http\Middleware\Dropzone::class,
'header.x' => \App\Http\Middleware\AddXHeader::class,
'menu.admin' => \App\Http\Middleware\AdminMenu::class,
'menu.portal' => \App\Http\Middleware\PortalMenu::class,

View File

@ -0,0 +1,65 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Arr;
class Dropzone
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!in_array($request->method(), ['POST', 'PATCH'])) {
return $next($request);
}
$multiple = false;
foreach ($request->all() as $key => $value) {
if (!is_array($value)) {
continue;
}
$files = [];
$uploaded = [];
foreach ($value as $index => $parameter) {
// single file uploaded..
if (!is_array($parameter) && !$multiple) {
if (!Arr::has($value, 'dropzone')) {
continue;
}
$request->request->set('uploaded_' . $key, $value);
unset($request[$key]);
break;
}
// multiple file uploaded..
if (!Arr::has($parameter, 'dropzone')) {
$files[] = $parameter;
continue;
}
$multiple = true;
$uploaded[] = $parameter;
}
if ($multiple && $uploaded) {
$request->request->set('uploaded_' . $key, $uploaded);
$request->request->set($key, $files);
}
}
return $next($request);
}
}

View File

@ -19,95 +19,65 @@ class Money
*/
public function handle($request, Closure $next)
{
if ($request->method() == 'POST' || $request->method() == 'PATCH') {
$amount = $request->get('amount');
$document_number = $request->get('document_number');
$sale_price = $request->get('sale_price');
$purchase_price = $request->get('purchase_price');
$opening_balance = $request->get('opening_balance');
$items = $request->get('items');
if (($request->method() != 'POST') && ($request->method() != 'PATCH')) {
return $next($request);
}
if (!empty($amount)) {
try {
$amount = money($amount)->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
$parameters = [
'amount',
'sale_price',
'purchase_price',
'opening_balance',
];
$amount = 0;
}
$request->request->set('amount', $amount);
foreach ($parameters as $parameter) {
if (!$request->has($parameter)) {
continue;
}
if (isset($document_number) || !empty($items)) {
if (!empty($items)) {
foreach ($items as $key => $item) {
if (!isset($item['price'])) {
continue;
}
$money_format = $request->get($parameter);
try {
$amount = money($item['price'])->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
if ($parameter == 'sale_price' || $parameter == 'purchase_price') {
$money_format = Str::replaceFirst(',', '.', $money_format);
}
$amount = 0;
}
$amount = $this->getAmount($money_format);
$items[$key]['price'] = $amount;
$request->request->set($parameter, $amount);
}
$document_number = $request->get('document_number');
$items = $request->get('items');
if (isset($document_number) || !empty($items)) {
if (!empty($items)) {
foreach ($items as $key => $item) {
if (!isset($item['price'])) {
continue;
}
$request->request->set('items', $items);
}
}
$amount = $this->getAmount($item['price']);
if (isset($opening_balance)) {
try {
$amount = money($opening_balance)->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
$amount = 0;
$items[$key]['price'] = $amount;
}
$opening_balance = $amount;
$request->request->set('opening_balance', $opening_balance);
}
if (isset($sale_price)) {
$sale_price = Str::replaceFirst(',', '.', $sale_price);
try {
$amount = money($sale_price)->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
$amount = 0;
}
$sale_price = $amount;
$request->request->set('sale_price', $sale_price);
}
if (isset($purchase_price)) {
$purchase_price = Str::replaceFirst(',', '.', $purchase_price);
try {
$amount = money($purchase_price)->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
$amount = 0;
}
$purchase_price = $amount;
$request->request->set('purchase_price', $purchase_price);
$request->request->set('items', $items);
}
}
return $next($request);
}
protected function getAmount($money_format)
{
try {
$amount = money($money_format)->getAmount();
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
logger($e->getMessage());
$amount = 0;
}
return $amount;
}
}

View File

@ -41,7 +41,7 @@ class Transaction extends FormRequest
'contact_id' => 'nullable|integer',
'category_id' => 'required|integer',
'payment_method' => 'required|string',
'attachment' => $attachment,
'attachment.*' => $attachment,
];
}

View File

@ -23,7 +23,6 @@ class Contact extends FormRequest
*/
public function rules()
{
$email = '';
$required = '';
@ -32,7 +31,9 @@ class Contact extends FormRequest
// Check if store or update
if ($this->getMethod() == 'PATCH') {
$id = is_numeric($this->$type) ? $this->$type : $this->$type->getAttribute('id');
$model = $this->isApi() ? 'contact' : $type;
$id = is_numeric($this->$model) ? $this->$model : $this->$model->getAttribute('id');
} else {
$id = null;
}

View File

@ -31,8 +31,8 @@ class Item extends FormRequest
return [
'name' => 'required|string',
'sale_price' => 'required|amount',
'purchase_price' => 'required|amount',
'sale_price' => 'required',
'purchase_price' => 'required',
'tax_ids' => 'nullable|array',
'category_id' => 'nullable|integer',
'enabled' => 'integer|boolean',

View File

@ -32,7 +32,9 @@ class Document extends FormRequest
// Check if store or update
if ($this->getMethod() == 'PATCH') {
$id = is_numeric($this->$type) ? $this->$type : $this->{$type}->getAttribute('id');
$model = $this->isApi() ? 'document' : $type;
$id = is_numeric($this->$model) ? $this->$model : $this->{$model}->getAttribute('id');
} else {
$id = null;
}
@ -87,9 +89,9 @@ class Document extends FormRequest
public function messages()
{
return [
'items.*.name.required' => trans('validation.required', ['attribute' => mb_strtolower(trans('general.name'))]),
'items.*.quantity.required' => trans('validation.required', ['attribute' => mb_strtolower(trans('invoices.quantity'))]),
'items.*.price.required' => trans('validation.required', ['attribute' => mb_strtolower(trans('invoices.price'))]),
'items.*.name.required' => trans('validation.required', ['attribute' => Str::lower(trans('general.name'))]),
'items.*.quantity.required' => trans('validation.required', ['attribute' => Str::lower(trans('invoices.quantity'))]),
'items.*.price.required' => trans('validation.required', ['attribute' => Str::lower(trans('invoices.price'))]),
'items.*.currency.required' => trans('validation.custom.invalid_currency'),
'items.*.currency.string' => trans('validation.custom.invalid_currency'),
];

View File

@ -8,7 +8,6 @@ use App\Models\Banking\Transfer as Model;
use App\Models\Setting\Category;
use App\Traits\Currencies;
use App\Utilities\Date;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
class Transfers extends Import
{
@ -23,7 +22,7 @@ class Transfers extends Import
{
$row = parent::map($row);
$row['transferred_at'] = Date::parse(ExcelDate::excelToDateTimeObject($row['transferred_at']))->format('Y-m-d');
$row['transferred_at'] = Date::parse($row['transferred_at'])->format('Y-m-d');
$row['from_account_id'] = $this->getFromAccountId($row);
$row['to_account_id'] = $this->getToAccountId($row);
$row['expense_transaction_id'] = $this->getExpenseTransactionId($row);

View File

@ -12,7 +12,6 @@ use Maatwebsite\Excel\Concerns\WithMultipleSheets;
class Invoices implements WithMultipleSheets
{
public function sheets(): array
{
return [

View File

@ -0,0 +1,20 @@
<?php
namespace App\Imports\Settings;
use App\Abstracts\Import;
use App\Http\Requests\Setting\Category as Request;
use App\Models\Setting\Category as Model;
class Categories extends Import
{
public function model(array $row)
{
return new Model($row);
}
public function rules(): array
{
return (new Request())->rules();
}
}

View File

@ -37,9 +37,11 @@ class CreateTransaction extends Job
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, 'transactions');
$this->transaction->attachMedia($media, 'attachment');
$this->transaction->attachMedia($media, 'attachment');
}
}
// Recurring

View File

@ -37,9 +37,15 @@ class UpdateTransaction extends Job
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
$this->deleteMediaModel($this->transaction, 'attachment', $this->request);
$this->transaction->attachMedia($media, 'attachment');
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, 'transactions');
$this->transaction->attachMedia($media, 'attachment');
}
} elseif (!$this->request->file('attachment') && $this->transaction->attachment) {
$this->deleteMediaModel($this->transaction, 'attachment', $this->request);
}
// Recurring

View File

@ -46,13 +46,15 @@ class UpdateDocument extends Job
\DB::transaction(function () {
// Upload attachment
if ($this->request->file('attachment')) {
$this->document->delete_attachment();
$this->deleteMediaModel($this->document, 'attachment', $this->request);
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, Str::plural($this->document->type));
$this->document->attachMedia($media, 'attachment');
}
} elseif (!$this->request->file('attachment') && $this->document->attachment) {
$this->deleteMediaModel($this->document, 'attachment', $this->request);
}
$this->deleteRelationships($this->document, ['items', 'item_taxes', 'totals']);
@ -60,6 +62,7 @@ class UpdateDocument extends Job
$this->dispatch(new CreateDocumentItemsAndTotals($this->document, $this->request));
$this->document->paid_amount = $this->document->paid;
event(new PaidAmountCalculated($this->document));
if ($this->document->paid_amount > 0) {

View File

@ -22,7 +22,7 @@ class Login
if (!$company) {
app('App\Http\Controllers\Auth\Login')->logout();
flash(trans('auth.error.no_company'))->error();
flash(trans('auth.error.no_company'))->error()->important();
return;
}

View File

@ -32,13 +32,13 @@ class CreateDocumentTransaction
$type = Str::plural($event->document->type);
if (empty($user)) {
flash($message)->error();
flash($message)->error()->important();
redirect()->route("signed.$type.show", $document->id)->send();
}
if ($user->can('read-client-portal')) {
flash($message)->error();
flash($message)->error()->important();
redirect()->route("portal.$type.show", $document->id)->send();
}

View File

@ -3,11 +3,15 @@
namespace App\Listeners\Document;
use App\Events\Document\DocumentCreated as Event;
use App\Models\Common\Company;
use App\Traits\Documents;
use App\Traits\Uploads;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class SettingFieldCreated
{
use Documents;
use Documents, Uploads;
/**
* Handle the event.
@ -18,6 +22,7 @@ class SettingFieldCreated
public function handle(Event $event)
{
$request = $event->request;
$document = $event->document;
if (!$request->has('setting')) {
return;
@ -28,6 +33,10 @@ class SettingFieldCreated
foreach ($fields as $key => $value) {
if ($key == 'company_logo') {
if (Arr::has($value, 'dropzone')) {
continue;
}
setting()->set('company.logo', $value);
continue;
@ -38,6 +47,31 @@ class SettingFieldCreated
setting()->set($real_key, $value);
}
$files = $request->file('setting', []);
if ($files) {
$company = Company::find($document->company_id);
foreach ($files as $key => $value) {
// Upload attachment
$media = $this->getMedia($value, 'settings');
$company->attachMedia($media, Str::snake($real_key));
$value = $media->id;
if ($key == 'company_logo') {
setting()->set('company.logo', $value);
continue;
}
$real_key = $type . '.' . $key;
setting()->set($real_key, $value);
}
}
// Save all settings
setting()->save();
}

View File

@ -3,11 +3,15 @@
namespace App\Listeners\Document;
use App\Events\Document\DocumentUpdated as Event;
use App\Models\Common\Company;
use App\Traits\Uploads;
use App\Traits\Documents;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class SettingFieldUpdated
{
use Documents;
use Documents, Uploads;
/**
* Handle the event.
@ -18,6 +22,7 @@ class SettingFieldUpdated
public function handle(Event $event)
{
$request = $event->request;
$document = $event->document;
if (!$request->has('setting')) {
return;
@ -28,6 +33,10 @@ class SettingFieldUpdated
foreach ($fields as $key => $value) {
if ($key == 'company_logo') {
if (Arr::has($value, 'dropzone')) {
continue;
}
setting()->set('company.logo', $value);
continue;
@ -38,6 +47,31 @@ class SettingFieldUpdated
setting()->set($real_key, $value);
}
$files = $request->file('setting', []);
if ($files) {
$company = Company::find($document->company_id);
foreach ($files as $key => $value) {
// Upload attachment
$media = $this->getMedia($value, 'settings');
$company->attachMedia($media, Str::snake($real_key));
$value = $media->id;
if ($key == 'company_logo') {
setting()->set('company.logo', $value);
continue;
}
$real_key = $type . '.' . $key;
setting()->set($real_key, $value);
}
}
// Save all settings
setting()->save();
}

View File

@ -20,7 +20,7 @@ class FinishInstallation
{
$module = module($event->alias);
Artisan::call('migrate', ['--force' => true]);
Artisan::call('module:migrate', ['alias' => $event->alias, '--force' => true]);
$this->attachDefaultModulePermissions($module);
}

View File

@ -6,11 +6,12 @@ use App\Events\Module\Installed as Event;
use App\Jobs\Install\DownloadModule;
use App\Jobs\Install\InstallModule;
use App\Traits\Jobs;
use App\Traits\Modules;
use Illuminate\Support\Facades\App;
class InstallExtraModules
{
use Jobs;
use Jobs, Modules;
/**
* Handle the event.
@ -24,9 +25,11 @@ class InstallExtraModules
return;
}
$module = module($event->alias);
if ($event->alias == 'core') {
return;
}
$extra_modules = $module->get('extra-modules');
$extra_modules = module($event->alias)->get('extra-modules');
if (empty($extra_modules)) {
return;
@ -38,8 +41,15 @@ class InstallExtraModules
continue;
}
// Check if module is already installed
if ($this->moduleIsEnabled($alias)) {
continue;
}
try {
$this->dispatch(new DownloadModule($alias, $event->company_id));
if (!$this->moduleExists($alias)) {
$this->dispatch(new DownloadModule($alias, $event->company_id));
}
$this->dispatch(new InstallModule($alias, $event->company_id, $event->locale));
} catch (\Exception $e) {

View File

@ -0,0 +1,68 @@
<?php
namespace App\Listeners\Module;
use App\Events\Install\UpdateFinished as Event;
use App\Utilities\Console;
use App\Utilities\Versions;
use Illuminate\Support\Facades\App;
class UpdateExtraModules
{
/**
* Handle the event.
*
* @param $event
* @return void
*/
public function handle(Event $event)
{
if (App::environment('testing')) {
return;
}
if ($event->alias == 'core') {
return;
}
$extra_modules = module($event->alias)->get('extra-modules');
if (empty($extra_modules)) {
return;
}
foreach ($extra_modules as $alias => $level) {
// Don't update if the module is "suggested"
if ($level != 'required') {
continue;
}
$extra_module = module($alias);
if (empty($extra_module)) {
continue;
}
$installed_version = $extra_module->get('version');
$latest_version = Versions::latest($alias);
// Skip if no update available
if (version_compare($installed_version, $latest_version, '>=')) {
continue;
}
$company_id = session('company_id');
$command = "update {$alias} {$company_id} {$latest_version}";
if (true !== $result = Console::run($command)) {
$message = !empty($result) ? $result : trans('modules.errors.finish', ['module' => $alias]);
logger($message);
// Stop the propagation of event if the required module failed to update
return false;
}
}
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace App\Listeners\Update\V21;
use App\Abstracts\Listeners\Update as Listener;
use App\Events\Install\UpdateFinished as Event;
use App\Models\Common\Company;
use App\Utilities\Overrider;
class Version213 extends Listener
{
const ALIAS = 'core';
const VERSION = '2.1.3';
/**
* Handle the event.
*
* @param $event
* @return void
*/
public function handle(Event $event)
{
if ($this->skipThisUpdate($event)) {
return;
}
$this->updateCompanies();
}
protected function updateCompanies()
{
$company_id = session('company_id');
$companies = Company::cursor();
foreach ($companies as $company) {
session(['company_id' => $company->id]);
$this->updateSettings($company);
}
setting()->forgetAll();
session(['company_id' => $company_id]);
Overrider::load('settings');
}
public function updateSettings($company)
{
// Set the active company settings
setting()->setExtraColumns(['company_id' => $company->id]);
setting()->forgetAll();
setting()->load(true);
$company_logo = setting('company.logo');
if (is_array($company_logo)) {
setting()->set('company.logo', $company_logo['id']);
}
setting()->save();
}
}

View File

@ -3,6 +3,7 @@
namespace App\Models\Banking;
use App\Abstracts\Model;
use App\Models\Common\Media as MediaModel;
use App\Models\Setting\Category;
use App\Scopes\Transaction as Scope;
use App\Traits\Currencies;
@ -320,7 +321,16 @@ class Transaction extends Model
return false;
}
return $this->getMedia('attachment')->last();
return $this->getMedia('attachment')->all();
}
public function delete_attachment()
{
if ($attachments = $this->attachment) {
foreach ($attachments as $file) {
MediaModel::where('id', $file->id)->delete();
}
}
}
/**

View File

@ -5,10 +5,11 @@ namespace App\Models\Banking;
use App\Abstracts\Model;
use App\Traits\Currencies;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Znck\Eloquent\Traits\BelongsToThrough;
class Transfer extends Model
{
use HasFactory, Currencies;
use BelongsToThrough, Currencies, HasFactory;
protected $table = 'transfers';
@ -33,7 +34,13 @@ class Transfer extends Model
public function expense_account()
{
return $this->belongsTo('App\Models\Banking\Account', 'expense_transaction.account_id', 'id')->withDefault(['name' => trans('general.na')]);
return $this->belongsToThrough(
'App\Models\Banking\Account',
'App\Models\Banking\Transaction',
null,
'',
['App\Models\Banking\Transaction' => 'expense_transaction_id']
)->withDefault(['name' => trans('general.na')]);
}
public function income_transaction()
@ -43,7 +50,13 @@ class Transfer extends Model
public function income_account()
{
return $this->belongsTo('App\Models\Banking\Account', 'income_transaction.account_id', 'id')->withDefault(['name' => trans('general.na')]);
return $this->belongsToThrough(
'App\Models\Banking\Account',
'App\Models\Banking\Transaction',
null,
'',
['App\Models\Banking\Transaction' => 'income_transaction_id']
)->withDefault(['name' => trans('general.na')]);
}
/**

View File

@ -14,6 +14,7 @@ class Event extends Provider
protected $listen = [
'App\Events\Install\UpdateFinished' => [
'App\Listeners\Update\CreateModuleUpdatedHistory',
'App\Listeners\Module\UpdateExtraModules',
'App\Listeners\Update\V20\Version200',
'App\Listeners\Update\V20\Version203',
'App\Listeners\Update\V20\Version205',
@ -26,6 +27,7 @@ class Event extends Provider
'App\Listeners\Update\V20\Version2023',
'App\Listeners\Update\V20\Version2024',
'App\Listeners\Update\V21\Version210',
'App\Listeners\Update\V21\Version213',
],
'Illuminate\Auth\Events\Login' => [
'App\Listeners\Auth\Login',

28
app/Traits/Categories.php Normal file
View File

@ -0,0 +1,28 @@
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait Categories
{
public function getCategoryTypes()
{
$types = [];
$configs = config('type.category');
foreach ($configs as $type => $attr) {
$plural_type = Str::plural($type);
$name = $attr['translation']['prefix'] . '.' . $plural_type;
if (!empty($attr['alias'])) {
$name = $attr['alias'] . '::' . $name;
}
$types[$type] = trans_choice($name, 1);
}
return $types;
}
}

View File

@ -3,6 +3,7 @@
namespace App\Traits;
use App\Traits\SearchString;
use Carbon\CarbonPeriod;
use Date;
trait DateTime
@ -49,8 +50,8 @@ trait DateTime
$start = Date::parse($year . '-01-01')->startOfDay()->format('Y-m-d H:i:s');
$end = Date::parse($year . '-12-31')->endOfDay()->format('Y-m-d H:i:s');
} else {
$start = $financial_start->format('Y-m-d H:i:s');
$end = $financial_start->addYear(1)->subDays(1)->format('Y-m-d H:i:s');
$start = $financial_start->startOfDay()->format('Y-m-d H:i:s');
$end = $financial_start->addYear(1)->subDays(1)->endOfDay()->format('Y-m-d H:i:s');
}
return $query->whereBetween($field, [$start, $end]);
@ -109,14 +110,32 @@ trait DateTime
$financial_start = Date::create($year, $month, $day);
// Check if FS is in last calendar year
if ($now->diffInDays($financial_start, false) > 0) {
if ((setting('localisation.financial_denote') == 'ends') && ($financial_start->dayOfYear != 1)) {
$financial_start->subYear();
}
return $financial_start;
}
public function getFinancialYear($year = null)
{
$start = $this->getFinancialStart($year);
return CarbonPeriod::create($start, $start->copy()->addYear()->subDay()->endOfDay());
}
public function getFinancialQuarters($year = null)
{
$quarters = [];
$start = $this->getFinancialStart($year);
for ($i = 0; $i < 4; $i++) {
$quarters[] = CarbonPeriod::create($start->copy()->addQuarters($i), $start->copy()->addQuarters($i + 1)->subDay()->endOfDay());
}
return $quarters;
}
public function getMonthlyDateFormat($year = null)
{
$format = 'M';

View File

@ -83,7 +83,7 @@ trait Documents
{
return Str::slug($document->document_number, $separator, language()->getShortCode());
}
protected function getTextDocumentStatuses($type)
{
$default_key = config('type.' . $type . '.translation.prefix') . '.statuses.';
@ -106,4 +106,21 @@ trait Documents
return 'documents.statuses.';
}
protected function getSettingKey($type, $setting_key)
{
$key = '';
$alias = config('type.' . $type . '.alias');
if (!empty($alias)) {
$key .= $alias . '.';
}
$prefix = config('type.' . $type . '.setting.prefix');
$key .= $prefix . '.' . $setting_key;
return $key;
}
}

View File

@ -64,6 +64,10 @@ trait Import
{
$id = isset($row['document_id']) ? $row['document_id'] : null;
if (empty($id) && !empty($row['document_number'])) {
$id = Document::number($row['document_number'])->pluck('id')->first();
}
if (empty($id) && !empty($row['invoice_number'])) {
$id = Document::invoice()->number($row['invoice_number'])->pluck('id')->first();
}

View File

@ -4,13 +4,9 @@ namespace App\Traits;
use App\Models\Module\Module;
use App\Traits\SiteApi;
use App\Utilities\Console;
use App\Utilities\Info;
use Cache;
use Date;
use File;
use Illuminate\Support\Str;
use ZipArchive;
trait Modules
{

View File

@ -145,7 +145,7 @@ trait Omnipay
$invoice_url = $this->getInvoiceUrl($invoice);
flash($message)->error();
flash($message)->error()->important();
if ($force_redirect) {
return redirect($invoice_url);

View File

@ -3,10 +3,10 @@
namespace App\Traits;
use MediaUploader;
use App\Models\Common\Media as MediaModel;
trait Uploads
{
public function getUploadedFilePath($file, $folder = 'settings', $company_id = null)
{
$path = '';
@ -63,4 +63,35 @@ trait Uploads
return MediaUploader::importPath($disk, $path);
}
public function deleteMediaModel($model, $parameter, $request = null)
{
$medias = $model->$parameter;
if (!$medias) {
return;
}
$already_uploaded = [];
if ($request && isset($request['uploaded_' . $parameter])) {
$uploaded = $request['uploaded_' . $parameter];
if (count($medias) == count($uploaded)) {
return;
}
foreach ($uploaded as $old_media) {
$already_uploaded[] = $old_media['id'];
}
}
foreach ((array)$medias as $media) {
if (in_array($media->id, $already_uploaded)) {
continue;
}
MediaModel::where('id', $media->id)->delete();
}
}
}

View File

@ -3,12 +3,17 @@
namespace App\Utilities;
use App\Models\Document\Document;
use App\Traits\DateTime;
use Date;
class Recurring
{
use DateTime;
public static function reflect(&$items, $issued_date_field)
{
$financial_year = (new static)->getFinancialYear();
foreach ($items as $key => $item) {
// @todo cache recurrings
if (!$item->recurring || !empty($item->parent_id)) {
@ -18,18 +23,17 @@ class Recurring
foreach ($item->recurring->getRecurringSchedule(false) as $schedule) {
$issued = Date::parse($item->$issued_date_field);
$start = $schedule->getStart();
if ($issued->format('Y') != $start->format('Y')) {
continue;
}
$start_date = Date::parse($start->format('Y-m-d'));
if (($issued->format('Y-m') == $start->format('Y-m')) && ($issued->format('d') >= $start->format('d'))) {
continue;
}
$clone = clone $item;
if ($start_date->lessThan($financial_year->getStartDate()) || $start_date->greaterThan($financial_year->getEndDate())) {
continue;
}
$start_date = Date::parse($start->format('Y-m-d'));
$clone = clone $item;
if ($clone instanceof Document) {
// Days between invoiced/billed and due date

View File

@ -3,7 +3,7 @@
namespace App\View\Components\Documents\Form;
use App\Abstracts\View\Components\DocumentForm as Component;
use Illuminate\Support\Str;
use App\Models\Common\Company as Model;
class Company extends Component
{
@ -14,7 +14,7 @@ class Company extends Component
*/
public function render()
{
$company = user()->companies()->first();
$company = Model::find(session('company_id'));
$inputNameType = config('type.' . $this->type . '.route.parameter');

View File

@ -0,0 +1,146 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\Support\Str;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
class EmptyPage extends Component
{
/** @var string */
public $page;
/** @var string */
public $group;
/** @var string */
public $imageEmptyPage;
/** @var string */
public $textEmptyPage;
/** @var string */
public $textPage;
/** @var string */
public $urlDocsPath;
/** @var bool */
public $checkPermissionCreate;
/** @var string */
public $permissionCreate;
/** @var string */
public $routeCreate;
/**
* Create a new component instance.
*
* @return void
*/
public function __construct(
string $page, string $group = '', string $imageEmptyPage = '', string $textEmptyPage = '', string $textPage = '',
string $urlDocsPath = '', bool $checkPermissionCreate = true, string $permissionCreate = '', string $routeCreate = ''
) {
$this->page = $page;
$this->group = $group;
$this->imageEmptyPage = $this->getImageEmptyPage($page, $imageEmptyPage);
$this->textEmptyPage = $this->getTextEmptyPage($page, $textEmptyPage);
$this->textPage = $this->getTextPage($page, $textPage);
$this->urlDocsPath = $this->getUrlDocsPath($page, $group, $urlDocsPath);
$this->checkPermissionCreate = $checkPermissionCreate;
$this->permissionCreate = $this->getPermissionCreate($page, $group, $permissionCreate);
$this->routeCreate = $this->getRouteCreate($page, $routeCreate);
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|string
*/
public function render()
{
return view('components.empty-page');
}
protected function getImageEmptyPage($page, $imageEmptyPage)
{
if ($imageEmptyPage) {
return $imageEmptyPage;
}
return 'public/img/empty_pages/' . $page . '.png';
}
protected function getTextEmptyPage($page, $textEmptyPage)
{
if ($textEmptyPage) {
return $textEmptyPage;
}
return 'general.empty.' . $page;
}
protected function getTextPage($page, $textPage)
{
if ($textPage) {
return $textPage;
}
return 'general.' . $page;
}
protected function getUrlDocsPath($page, $group, $urlDocsPath)
{
if ($urlDocsPath) {
return $urlDocsPath;
}
$docs_path = $page;
if (!empty($group)) {
$docs_path = $group . '/' . $page;
}
return 'https://akaunting.com/docs/user-manual/' . $page;
}
protected function getPermissionCreate($page, $group, $permissionCreate)
{
if ($permissionCreate) {
return $permissionCreate;
}
$pages = [
'reconciliations' => 'create-banking-reconciliations',
'transfers' => 'create-banking-transfers',
'payments' => 'create-purchases-payments',
'vendors' => 'create-purchases-vendors',
'customers' => 'create-sales-customers',
'revenues' => 'create-sales-revenues',
'taxes' => 'create-settings-taxes',
'items' => 'create-common-items',
];
if (array_key_exists($page, $pages)) {
$permissionCreate = $pages[$page];
}
if (empty($permissionCreate) && !empty($group)) {
$permissionCreate = 'create-' . $group . '-' . $page;
}
return $permissionCreate;
}
protected function getRouteCreate($page, $routeCreate)
{
if ($routeCreate) {
return $routeCreate;
}
return $page . '.create';
}
}

View File

@ -2,17 +2,21 @@
namespace App\View\Components;
use Illuminate\View\Component;
use App\Traits\DateTime;
use Illuminate\Support\Str;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Illuminate\View\Component;
class SearchString extends Component
{
use DateTime;
public $filters;
/** string */
public $model;
public $date_format;
/**
* Create a new component instance.
*
@ -22,6 +26,7 @@ class SearchString extends Component
{
$this->model = $model;
$this->filters = $filters;
$this->date_format = $this->getCompanyDateFormat();
}
/**
@ -33,26 +38,26 @@ class SearchString extends Component
{
if (empty($this->filters)) {
$search_string = config('search-string');
$this->filters = [];
if (!empty($search_string[$this->model])) {
$columns = $search_string[$this->model]['columns'];
foreach ($columns as $column => $options) {
// This column skip for filter
if (!empty($options['searchable'])) {
continue;
}
if (!is_array($options)) {
$column = $options;
}
if (!$this->isFilter($column, $options)) {
continue;
}
$this->filters[] = [
'key' => $this->getFilterKey($column, $options),
'value' => $this->getFilterName($column, $options),
@ -80,6 +85,10 @@ class SearchString extends Component
protected function getFilterKey($column, $options)
{
if (isset($options['key'])) {
$column = $options['key'];
}
if (isset($options['relationship'])) {
$column .= '.id';
}
@ -101,19 +110,29 @@ class SearchString extends Component
$plural = Str::plural($column, 2);
if (trans_choice('general.' . $plural, 1) !== 'general.' . $plural) {
return trans_choice('general.' . $plural, 1);
} elseif (trans_choice('search_string.columns.' . $plural, 1) !== 'search_string.columns.' . $plural) {
return trans_choice('search_string.columns.' . $plural, 1);
if (strpos($this->model, 'Modules') !== false) {
$module_class = explode('\\', $this->model);
$prefix = Str::kebab($module_class[1]) . '::';
$translation_keys[] = $prefix . 'general.';
$translation_keys[] = $prefix . 'search_string.columns.';
}
$name = trans('general.' . $column);
$translation_keys[] = 'general.';
$translation_keys[] = 'search_string.columns.';
if ($name == 'general.' . $column) {
$name = trans('search_string.columns.' . $column);
foreach ($translation_keys as $translation_key) {
if (trans_choice($translation_key . $plural, 1) !== $translation_key . $plural) {
return trans_choice($translation_key . $plural, 1);
}
if (trans($translation_key . $column) !== $translation_key . $column) {
return trans($translation_key . $column);
}
}
return $name;
return $column;
}
protected function getFilterType($options)
@ -149,7 +168,7 @@ class SearchString extends Component
if (strpos($this->model, 'Modules') !== false) {
$module_class = explode('\\', $this->model);
$url .= Str::slug($module_class[1], '-') . '::';
$url .= Str::kebab($module_class[1]) . '::';
}
if (strpos($column, '_id') !== false) {

View File

@ -36,7 +36,7 @@ class SelectItemButton extends Component
public function render()
{
$items = Item::enabled()->orderBy('name')->take(setting('default.select_limit'))->get();
$price_type= $this->getPriceType($this->type, $this->isSale, $this->isPurchase);
$price_type = $this->getPriceType($this->type, $this->isSale, $this->isPurchase);
foreach ($items as $item) {
$price = $item->{$price_type . '_price'};
@ -44,7 +44,7 @@ class SelectItemButton extends Component
$item->price = $price;
}
$price = ($this->isPurchase) ? 'purchase_price' : 'sale_price';
$price = $price_type . '_price';
return view('components.select-item-button', compact('items', 'price'));
}
@ -55,7 +55,7 @@ class SelectItemButton extends Component
return 'sale';
}
if (!empty($is_sale)) {
if (!empty($is_purchase)) {
return 'purchase';
}

View File

@ -29,16 +29,16 @@
"dingo/api": "3.0.*",
"doctrine/dbal": "2.11.*",
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^1.0",
"fruitcake/laravel-cors": "^2.0",
"genealabs/laravel-model-caching": "0.11.*",
"graham-campbell/markdown": "13.1.*",
"guzzlehttp/guzzle": "^7.0",
"guzzlehttp/guzzle": "^7.0.1",
"intervention/image": "2.5.*",
"intervention/imagecache": "^2.5",
"kyslik/column-sortable": "^6.0",
"laracasts/flash": "3.2.*",
"laravel/framework": "^8.0",
"laravel/tinker": "^2.0",
"laravel/framework": "^8.12",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.0",
"laravelcollective/html": "6.2.*",
"league/oauth2-client": "2.6.*",
@ -57,9 +57,9 @@
"require-dev": {
"beyondcode/laravel-dump-server": "^1.5",
"brianium/paratest": "^6.1",
"facade/ignition": "^2.3",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"mockery/mockery": "^1.3.1",
"mockery/mockery": "^1.4.2",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.3",
"wnx/laravel-stats": "^2.5"

565
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ return [
| This options indicates the allowed languages.
|
*/
'allowed' => ['ar-SA', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-ES', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-US', 'es-AR', 'es-ES', 'es-MX', 'fa-IR', 'fr-FR', 'he-IL', 'hi-IN', 'hr-HR', 'hu-HU', 'id-ID', 'is-IS', 'it-IT', 'ja-JP', 'ka-GE', 'ko-KR', 'lt-LT', 'lv-LV', 'mk-MK', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-NL', 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sk-SK', 'sr-RS', 'sq-AL', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'ur-PK', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-TW'],
'allowed' => ['ar-SA', 'az-AZ', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-ES', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-US', 'es-AR', 'es-ES', 'es-MX', 'fa-IR', 'fr-FR', 'he-IL', 'hi-IN', 'hr-HR', 'hu-HU', 'id-ID', 'is-IS', 'it-IT', 'ja-JP', 'ka-GE', 'ko-KR', 'lt-LT', 'lv-LV', 'mk-MK', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-NL', 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sk-SK', 'sr-RS', 'sq-AL', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'ur-PK', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-TW'],
/*
|--------------------------------------------------------------------------
@ -134,6 +134,7 @@ return [
*/
'all' => [
['short' => 'ar', 'long' => 'ar-SA', 'english' => 'Arabic', 'native' => 'العربية'],
['short' => 'az', 'long' => 'az-AZ', 'english' => 'Azerbaijani', 'native' => 'Azərbaycan'],
['short' => 'bg', 'long' => 'bg-BG', 'english' => 'Bulgarian', 'native' => 'български'],
['short' => 'bn', 'long' => 'bn-BD', 'english' => 'Bengali', 'native' => 'বাংলা'],
['short' => 'bs', 'long' => 'bs-BA', 'english' => 'Bosnian', 'native' => 'Bosanski'],

View File

@ -98,9 +98,7 @@ return [
'route' => 'currencies.index'
],
'document_id',
'contact_id' => [
'route' => 'customers.index'
],
'contact_id',
'description' => ['searchable' => true],
'payment_method',
'reference',
@ -111,9 +109,23 @@ return [
],
],
App\Models\Banking\Transfer::class => [
'columns' => [
'expense_account' => [
'relationship' => true,
'route' => 'accounts.index',
],
'income_account' => [
'relationship' => true,
'route' => 'accounts.index',
],
],
],
App\Models\Common\Company::class => [
'columns' => [
'domain' => ['searchable' => true],
'settings.value' => ['searchable' => true],
'enabled' => ['boolean' => true],
],
],
@ -162,15 +174,16 @@ return [
'document_number' => ['searchable' => true],
'order_number' => ['searchable' => true],
'status',
'issued_at' => ['date' => true],
'issued_at' => [
'key' => '/^(invoiced_at|billed_at)$/',
'date' => true,
],
'due_at' => ['date' => true],
'amount',
'currency_code' => [
'route' => 'currencies.index'
],
'contact_id' => [
'route' => 'vendors.index'
],
'contact_id',
'contact_name' => ['searchable' => true],
'contact_email' => ['searchable' => true],
'contact_tax_number',
@ -183,7 +196,7 @@ return [
],
],
App\Models\Purchase\Bill::class => [
'App\Models\Purchase\Bill' => [
'columns' => [
'document_number' => ['searchable' => true],
'order_number' => ['searchable' => true],
@ -212,24 +225,32 @@ return [
],
],
App\Models\Purchase\Vendor::class => [
'App\Models\Purchase\Payment' => [
'columns' => [
'type',
'name' => ['searchable' => true],
'email' => ['searchable' => true],
'tax_number' => ['searchable' => true],
'phone' => ['searchable' => true],
'address' => ['searchable' => true],
'website' => ['searchable' => true],
'account_id' => [
'route' => 'accounts.index'
],
'paid_at' => ['date' => true],
'amount',
'currency_code' => [
'route' => 'currencies.index'
],
'document_id',
'contact_id' => [
'route' => 'vendors.index'
],
'description' => ['searchable' => true],
'payment_method',
'reference',
'enabled' => ['boolean' => true],
'category_id' => [
'route' => ['categories.index', 'search=type:expense']
],
'parent_id',
],
],
App\Models\Sale\Invoice::class => [
'App\Models\Sale\Invoice' => [
'columns' => [
'document_number' => ['searchable' => true],
'order_number' => ['searchable' => true],
@ -258,6 +279,31 @@ return [
],
],
'App\Models\Sale\Revenue' => [
'columns' => [
'type',
'account_id' => [
'route' => 'accounts.index'
],
'paid_at' => ['date' => true],
'amount',
'currency_code' => [
'route' => 'currencies.index'
],
'document_id',
'contact_id' => [
'route' => 'customers.index'
],
'description' => ['searchable' => true],
'payment_method',
'reference',
'category_id' => [
'route' => ['categories.index', 'search=type:income']
],
'parent_id',
],
],
App\Models\Setting\Category::class => [
'columns' => [
'name' => ['searchable' => true],

View File

@ -98,6 +98,7 @@ return [
'fallback' => [
'localisation' => [
'financial_start' => env('SETTING_FALLBACK_LOCALISATION_FINANCIAL_START', '01-01'),
'financial_denote' => env('SETTING_FALLBACK_LOCALISATION_FINANCIAL_DENOTE', 'ends'),
'timezone' => env('SETTING_FALLBACK_LOCALISATION_TIMEZONE', 'Europe/London'),
'date_format' => env('SETTING_FALLBACK_LOCALISATION_DATE_FORMAT', 'd M Y'),
'date_separator' => env('SETTING_FALLBACK_LOCALISATION_DATE_SEPARATOR', 'space'),

View File

@ -6,86 +6,121 @@ return [
// Documents
Document::INVOICE_TYPE => [
'alias' => '', // core empty but module write own alias
'group' => 'sales', // controller folder name for permission and route
'alias' => '', // core empty but module write own alias
'group' => 'sales', // controller folder name for permission and route
'route' => [
'prefix' => 'invoices', // core use with group + prefix, module ex. estimates
'parameter' => 'invoice', // sales/invoices/{parameter}/edit
//'create' => 'invoices.create', // if you change route, you can write full path
'prefix' => 'invoices', // core use with group + prefix, module ex. estimates
'parameter' => 'invoice', // sales/invoices/{parameter}/edit
//'create' => 'invoices.create', // if you change route, you can write full path
],
'permission' => [
'prefix' => 'invoices', // this controller file name.
//'create' => 'create-sales-invoices', // if you change action permission key, you can write full permission
'prefix' => 'invoices', // this controller file name.
//'create' => 'create-sales-invoices', // if you change action permission key, you can write full permission
],
'translation' => [
'prefix' => 'invoices', // this translation file name.
'add_contact' => 'general.customers', //
'issued_at' => 'invoices.invoice_date',
'due_at' => 'invoices.due_date',
'prefix' => 'invoices', // this translation file name.
'add_contact' => 'general.customers', //
'issued_at' => 'invoices.invoice_date',
'due_at' => 'invoices.due_date',
],
'category_type' => 'income',
'transaction_type' => 'income',
'contact_type' => 'customer', // use contact type
'hide' => [], // for document items
'class' => [],
'setting' => [
'prefix' => 'invoice',
],
'category_type' => 'income',
'transaction_type' => 'income',
'contact_type' => 'customer', // use contact type
'hide' => [], // for document items
'class' => [],
],
Document::BILL_TYPE => [
'alias' => '',
'group' => 'purchases',
'alias' => '',
'group' => 'purchases',
'route' => [
'prefix' => 'bills',
'parameter' => 'bill',
//'create' => 'bilss.create',
'prefix' => 'bills',
'parameter' => 'bill',
//'create' => 'bilss.create',
],
'permission' => [
'prefix' => 'bills',
//'create' => 'create-purchases-bills',
'prefix' => 'bills',
//'create' => 'create-purchases-bills',
],
'translation' => [
'prefix' => 'bills',
'issued_at' => 'bills.bill_date',
'due_at' => 'bills.due_date',
'translation' => [
'prefix' => 'bills',
'issued_at' => 'bills.bill_date',
'due_at' => 'bills.due_date',
],
'category_type' => 'expense',
'transaction_type' => 'expense',
'contact_type' => 'vendor',
'hide' => [],
'setting' => [
'prefix' => 'bill',
],
'category_type' => 'expense',
'transaction_type' => 'expense',
'contact_type' => 'vendor',
'hide' => [],
],
// Contacts
'customer' => [
'group' => 'sales',
'group' => 'sales',
'permission' => [
'prefix' => 'customers',
//'create' => 'create-sales-customers',
'prefix' => 'customers',
//'create' => 'create-sales-customers',
],
],
'vendor' => [
'group' => 'purchases',
'group' => 'purchases',
'permission' => [
'prefix' => 'vendors',
//'create' => 'create-purchases-vendors',
'prefix' => 'vendors',
//'create' => 'create-purchases-vendors',
],
],
// Transactions
'income' => [
'group' => 'sales',
'group' => 'sales',
'permission' => [
'prefix' => 'revenues',
//'create' => 'create-sales-revenues',
'prefix' => 'revenues',
//'create' => 'create-sales-revenues',
],
'contact_type' => 'customer',
'contact_type' => 'customer',
],
'expense' => [
'group' => 'purchases',
'group' => 'purchases',
'permission' => [
'prefix' => 'payments',
//'create' => 'create-purchases-payments',
'prefix' => 'payments',
//'create' => 'create-purchases-payments',
],
'contact_type' => 'vendor',
'contact_type' => 'vendor',
],
// Categories
'category' => [
'income' => [
'alias' => '',
'translation' => [
'prefix' => 'general',
],
],
'expense' => [
'alias' => '',
'translation' => [
'prefix' => 'general',
],
],
'item' => [
'alias' => '',
'translation' => [
'prefix' => 'general',
],
],
'other' => [
'alias' => '',
'translation' => [
'prefix' => 'general',
],
],
],
];

View File

@ -10,15 +10,15 @@ return [
'minor' => '1',
'patch' => '0',
'patch' => '3',
'build' => '',
'status' => 'Stable',
'date' => '26-January-2020',
'date' => '15-February-2020',
'time' => '18:00',
'time' => '15:00',
'zone' => 'GMT +3',

22
crowdin_modules.yml Normal file
View File

@ -0,0 +1,22 @@
"project_id_env": CROWDIN_PROJECT_ID
"api_token_env": CROWDIN_PERSONAL_TOKEN
"preserve_hierarchy": true
"files": [
{
"source": "modules/OfflinePayments/Resources/lang/en-GB/general.php",
"dest": "offline-payments/general.php",
"translation": "modules/OfflinePayments/Resources/lang/%locale%/offline-payments/general.php",
"translation_replace": {
"offline-payments/": ""
}
},
{
"source": "modules/PaypalStandard/Resources/lang/en-GB/general.php",
"dest": "paypal-standard/general.php",
"translation": "modules/PaypalStandard/Resources/lang/%locale%/paypal-standard/general.php",
"translation_replace": {
"paypal-standard/": ""
}
}
]

View File

@ -8,7 +8,7 @@ use App\Traits\Transactions;
class Transaction extends Factory
{
use Transactions;
use Transactions;
/**
* The name of the factory's corresponding model.
@ -25,21 +25,23 @@ class Transaction extends Factory
public function definition()
{
$types = array_merge($this->getIncomeTypes(), $this->getExpenseTypes());
$type = $this->faker->randomElement($types);
$type = $this->faker->randomElement($types);
return [
'company_id' => $this->company->id,
'type' => $type,
'account_id' => setting('default.account'),
'paid_at' => $this->faker->dateTimeBetween(now()->startOfYear(), now()->endOfYear())->format('Y-m-d H:i:s'),
'amount' => $this->faker->randomFloat(2, 1, 1000),
'currency_code' => setting('default.currency'),
'currency_rate' => '1.0',
'description' => $this->faker->text(5),
'category_id' => $this->company->categories()->type($type)->get()->random(1)->pluck('id')->first(),
'reference' => $this->faker->text(5),
'payment_method' => setting('default.payment_method'),
];
$category_type = in_array($type, $this->getIncomeTypes()) ? 'income' : 'expense';
return [
'company_id' => $this->company->id,
'type' => $type,
'account_id' => setting('default.account'),
'paid_at' => $this->faker->dateTimeBetween(now()->startOfYear(), now()->endOfYear())->format('Y-m-d H:i:s'),
'amount' => $this->faker->randomFloat(2, 1, 1000),
'currency_code' => setting('default.currency'),
'currency_rate' => '1.0',
'description' => $this->faker->text(5),
'category_id' => $this->company->categories()->$category_type()->get()->random(1)->pluck('id')->first(),
'reference' => $this->faker->text(5),
'payment_method' => setting('default.payment_method'),
];
}
/**

Some files were not shown because too many files have changed in this diff Show More