Merge branch 'master' into title-subheading
This commit is contained in:
commit
797ee71f6b
7
.github/workflows/tests.yml
vendored
7
.github/workflows/tests.yml
vendored
@ -1,10 +1,11 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
@ -15,11 +16,11 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['8.0', '8.1']
|
||||
php: ['8.1', '8.2']
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache Composer
|
||||
uses: actions/cache@v1
|
||||
|
@ -3,24 +3,24 @@
|
||||
[](https://github.com/akaunting/akaunting/releases)
|
||||

|
||||
[](https://crowdin.com/project/akaunting)
|
||||
[](https://github.com/akaunting/akaunting/actions)
|
||||
[](https://github.com/akaunting/akaunting/actions)
|
||||
[](LICENSE.txt)
|
||||
|
||||
Akaunting is a free, open source and online accounting software designed for small businesses and freelancers. It is built with modern technologies such as Laravel, VueJS, Tailwind, RESTful API etc. Thanks to its modular structure, Akaunting provides an awesome App Store for users and developers.
|
||||
|
||||
* [Home](https://akaunting.com) - The house of Akaunting
|
||||
* [Forum](https://akaunting.com/forum) - Ask for support
|
||||
* [Documentation](https://akaunting.com/docs) - Learn how to use
|
||||
* [Documentation](https://akaunting.com/hc/docs) - Learn how to use
|
||||
* [Developer Portal](https://developer.akaunting.com) - Generate passive income
|
||||
* [App Store](https://akaunting.com/apps) - Extend your Akaunting
|
||||
* [Translations](https://crowdin.com/project/akaunting) - Help us translate Akaunting
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP 8.0 or higher
|
||||
* PHP 8.1 or higher
|
||||
* Database (eg: MySQL, PostgreSQL, SQLite)
|
||||
* Web Server (eg: Apache, Nginx, IIS)
|
||||
* [Other libraries](https://akaunting.com/docs/requirements)
|
||||
* [Other libraries](https://akaunting.com/hc/docs/on-premise/requirements/)
|
||||
|
||||
## Framework
|
||||
|
||||
|
@ -15,9 +15,10 @@ use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
|
||||
|
||||
abstract class Export implements FromCollection, HasLocalePreference, ShouldAutoSize, ShouldQueue, WithHeadings, WithMapping, WithTitle
|
||||
abstract class Export implements FromCollection, HasLocalePreference, ShouldAutoSize, ShouldQueue, WithHeadings, WithMapping, WithTitle, WithStrictNullComparison
|
||||
{
|
||||
use Exportable;
|
||||
|
||||
@ -48,13 +49,18 @@ abstract class Export implements FromCollection, HasLocalePreference, ShouldAuto
|
||||
{
|
||||
$map = [];
|
||||
|
||||
$date_fields = ['paid_at', 'invoiced_at', 'billed_at', 'due_at', 'issued_at', 'created_at', 'transferred_at'];
|
||||
$date_fields = ['paid_at', 'invoiced_at', 'billed_at', 'due_at', 'issued_at', 'transferred_at'];
|
||||
|
||||
$evil_chars = ['=', '+', '-', '@'];
|
||||
|
||||
foreach ($this->fields as $field) {
|
||||
$value = $model->$field;
|
||||
|
||||
// created_by is equal to the owner id. Therefore, the value in export is owner email.
|
||||
if ($field == 'created_by') {
|
||||
$value = $model->owner->email ?? null;
|
||||
}
|
||||
|
||||
if (in_array($field, $date_fields)) {
|
||||
$value = ExcelDate::PHPToExcel(Date::parse($value)->format('Y-m-d'));
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Abstracts;
|
||||
|
||||
use App\Abstracts\Http\FormRequest;
|
||||
use App\Traits\Import as ImportHelper;
|
||||
use App\Traits\Sources;
|
||||
use App\Utilities\Date;
|
||||
@ -11,6 +12,7 @@ use Illuminate\Contracts\Translation\HasLocalePreference;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Maatwebsite\Excel\Concerns\Importable;
|
||||
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
|
||||
use Maatwebsite\Excel\Concerns\ToModel;
|
||||
@ -27,6 +29,8 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow
|
||||
|
||||
public $user;
|
||||
|
||||
public $request_class = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->user = user();
|
||||
@ -35,7 +39,12 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow
|
||||
public function map($row): array
|
||||
{
|
||||
$row['company_id'] = company_id();
|
||||
$row['created_by'] = $this->user->id;
|
||||
|
||||
// created_by is equal to the owner id. Therefore, the value in export is owner email.
|
||||
if (isset($row['created_by'])) {
|
||||
$row['created_by'] = $this->getCreatedById($row);
|
||||
}
|
||||
|
||||
$row['created_from'] = $this->getSourcePrefix() . 'import';
|
||||
|
||||
// Make enabled field integer
|
||||
@ -48,7 +57,7 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow
|
||||
$row['reconciled'] = (int) $row['reconciled'];
|
||||
}
|
||||
|
||||
$date_fields = ['paid_at', 'invoiced_at', 'billed_at', 'due_at', 'issued_at', 'created_at', 'transferred_at'];
|
||||
$date_fields = ['paid_at', 'invoiced_at', 'billed_at', 'due_at', 'issued_at', 'transferred_at'];
|
||||
foreach ($date_fields as $date_field) {
|
||||
if (!isset($row[$date_field])) {
|
||||
continue;
|
||||
@ -70,6 +79,49 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* You can override this method to add custom rules for each row.
|
||||
*/
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate each row data.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function withValidator($validator)
|
||||
{
|
||||
$condition = class_exists($this->request_class)
|
||||
? ! ($request = new $this->request_class) instanceof FormRequest
|
||||
: true;
|
||||
|
||||
if ($condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($validator->getData() as $row => $data) {
|
||||
$request->initialize(request: $data);
|
||||
|
||||
$rules = $this->prepareRules($request->rules());
|
||||
|
||||
try {
|
||||
Validator::make($data, $rules)->validate();
|
||||
} catch (ValidationException $e) {
|
||||
foreach ($e->validator->failed() as $attribute => $value) {
|
||||
foreach ($value as $rule => $params) {
|
||||
$validator->addFailure($row . '.' . $attribute, $rule, $params);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return config('excel.imports.chunk_size');
|
||||
|
@ -20,6 +20,6 @@ abstract class ImportMultipleSheets implements ShouldQueue, WithChunkReading, Wi
|
||||
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 100;
|
||||
return config('excel.imports.chunk_size');
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ abstract class Model extends Eloquent implements Ownable
|
||||
|
||||
protected $tenantable = true;
|
||||
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
protected $casts = [
|
||||
'enabled' => 'boolean',
|
||||
'amount' => 'double',
|
||||
'enabled' => 'boolean',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
|
||||
public $allAttributes = [];
|
||||
@ -117,7 +117,8 @@ abstract class Model extends Eloquent implements Ownable
|
||||
}
|
||||
|
||||
$request->merge(['sort' => $request_sort]);
|
||||
$request->offsetUnset('direction');
|
||||
// This line disabled because broken sortable issue.
|
||||
//$request->offsetUnset('direction');
|
||||
$limit = (int) $request->get('limit', setting('default.list_limit', '25'));
|
||||
|
||||
return $query->paginate($limit);
|
||||
|
@ -222,7 +222,9 @@ abstract class Report
|
||||
foreach ($tmp_values as $id => $value) {
|
||||
$labels[$id] = $this->row_names[$table_key][$id];
|
||||
|
||||
$colors[$id] = ($group == 'category') ? Category::withSubCategory()->find($id)?->colorHexCode : '#' . dechex(rand(0x000000, 0xFFFFFF));
|
||||
$colors[$id] = ($group == 'category')
|
||||
? Category::withSubCategory()->find($id)?->colorHexCode
|
||||
: $this->randHexColor();
|
||||
|
||||
$values[$id] = round(($value * 100 / $total), 0);
|
||||
}
|
||||
@ -642,4 +644,14 @@ abstract class Report
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function randHexColorPart(): string
|
||||
{
|
||||
return str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
public function randHexColor(): string
|
||||
{
|
||||
return '#' . $this->randHexColorPart() . $this->randHexColorPart() . $this->randHexColorPart();
|
||||
}
|
||||
}
|
||||
|
@ -283,8 +283,8 @@ abstract class Index extends Component
|
||||
$items[] = [
|
||||
'title' => ($key == 'overdue') ? trans('general.overdue') : trans('documents.statuses.' . $key),
|
||||
//'href' => route($route, ['search' => 'status:' . $key]),
|
||||
'amount' => money($total, default_currency(), true)->formatForHumans(),
|
||||
'tooltip' => money($total, default_currency(), true)->format(),
|
||||
'amount' => money($total)->formatForHumans(),
|
||||
'tooltip' => money($total)->format(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Abstracts\View\Components\Documents;
|
||||
|
||||
use App\Abstracts\View\Component;
|
||||
use App\Interfaces\Utility\DocumentNumber;
|
||||
use App\Models\Common\Contact;
|
||||
use App\Models\Document\Document;
|
||||
use App\Models\Setting\Currency;
|
||||
@ -163,30 +164,45 @@ abstract class Form extends Component
|
||||
/** @var bool */
|
||||
public $hideItemName;
|
||||
|
||||
/** @var bool */
|
||||
public $hideSettingItemName;
|
||||
|
||||
/** @var string */
|
||||
public $textItemName;
|
||||
|
||||
/** @var bool */
|
||||
public $hideItemDescription;
|
||||
|
||||
/** @var bool */
|
||||
public $hideSettingItemDescription;
|
||||
|
||||
/** @var string */
|
||||
public $textItemDescription;
|
||||
|
||||
/** @var bool */
|
||||
public $hideItemQuantity;
|
||||
|
||||
/** @var bool */
|
||||
public $hideSettingItemQuantity;
|
||||
|
||||
/** @var string */
|
||||
public $textItemQuantity;
|
||||
|
||||
/** @var bool */
|
||||
public $hideItemPrice;
|
||||
|
||||
/** @var bool */
|
||||
public $hideSettingItemPrice;
|
||||
|
||||
/** @var string */
|
||||
public $textItemPrice;
|
||||
|
||||
/** @var bool */
|
||||
public $hideItemAmount;
|
||||
|
||||
/** @var bool */
|
||||
public $hideSettingItemAmount;
|
||||
|
||||
/** @var string */
|
||||
public $textItemAmount;
|
||||
|
||||
@ -276,8 +292,8 @@ abstract class Form extends Component
|
||||
bool $hideDocumentTitle = false, bool $hideDocumentSubheading = false, string $title = '', string $subheading = '',
|
||||
bool $hideIssuedAt = false, string $textIssuedAt = '', string $issuedAt = '', bool $hideDueAt = false, string $textDueAt = '', string $dueAt = '', $periodDueAt = '',
|
||||
bool $hideDocumentNumber = false, string $textDocumentNumber = '', string $documentNumber = '', bool $hideOrderNumber = false, string $textOrderNumber = '', string $orderNumber = '',
|
||||
bool $hideEditItemColumns = false, bool $hideItems = false, bool $hideItemName = false, string $textItemName = '', bool $hideItemDescription = false, string $textItemDescription = '',
|
||||
bool $hideItemQuantity = false, string $textItemQuantity = '', bool $hideItemPrice = false, string $textItemPrice = '', bool $hideItemAmount = false, string $textItemAmount = '',
|
||||
bool $hideEditItemColumns = false, bool $hideItems = false, bool $hideItemName = false, bool $hideSettingItemName = false, string $textItemName = '', bool $hideItemDescription = false, bool $hideSettingItemDescription = false, string $textItemDescription = '',
|
||||
bool $hideItemQuantity = false, bool $hideSettingItemQuantity = false, string $textItemQuantity = '', bool $hideItemPrice = false, bool $hideSettingItemPrice = false, string $textItemPrice = '', bool $hideItemAmount = false, bool $hideSettingItemAmount = false, string $textItemAmount = '',
|
||||
bool $hideDiscount = false, bool $isSalePrice = false, bool $isPurchasePrice = false, int $searchCharLimit = 0, string $notes = '',
|
||||
bool $showRecurring = false,
|
||||
bool $hideAdvanced = false, string $textSectionAdvancedTitle = '', string $textSectionAdvancedDescription = '',
|
||||
@ -290,9 +306,11 @@ abstract class Form extends Component
|
||||
|
||||
$this->model = ! empty($model) ? $model : $document;
|
||||
$this->document = $this->model;
|
||||
$this->currencies = $this->getCurrencies($currencies);
|
||||
$this->currency = $this->getCurrency($document, $currency, $currency_code);
|
||||
|
||||
$this->currency_code = ! empty($this->currency) ? $this->currency->code : default_currency();
|
||||
$this->currency = $this->getCurrency($document, $currency, $currency_code);
|
||||
$this->currencies = $this->getCurrencies($currencies);
|
||||
|
||||
$this->taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
||||
|
||||
/* -- Content Start -- */
|
||||
@ -357,18 +375,23 @@ abstract class Form extends Component
|
||||
|
||||
$this->hideItems = $this->getHideItems($type, $hideItems, $hideItemName, $hideItemDescription);
|
||||
$this->hideItemName = $this->getHideItemName($type, $hideItemName);
|
||||
$this->hideSettingItemName = $this->getHideSettingItemName($type, $hideSettingItemName);
|
||||
$this->textItemName = $this->getTextItemName($type, $textItemName);
|
||||
|
||||
$this->hideItemDescription = $this->getHideItemDescription($type, $hideItemDescription);
|
||||
$this->hideSettingItemDescription = $this->getHideSettingItemDescription($type, $hideSettingItemDescription);
|
||||
$this->textItemDescription = $this->getTextItemDescription($type, $textItemDescription);
|
||||
|
||||
$this->hideItemQuantity = $this->getHideItemQuantity($type, $hideItemQuantity);
|
||||
$this->hideSettingItemQuantity = $this->getHideSettingItemQuantity($type, $hideSettingItemQuantity);
|
||||
$this->textItemQuantity = $this->getTextItemQuantity($type, $textItemQuantity);
|
||||
|
||||
$this->hideItemPrice = $this->getHideItemPrice($type, $hideItemPrice);
|
||||
$this->hideSettingItemPrice = $this->getHideSettingItemPrice($type, $hideSettingItemPrice);
|
||||
$this->textItemPrice = $this->getTextItemPrice($type, $textItemPrice);
|
||||
|
||||
$this->hideItemAmount = $this->getHideItemAmount($type, $hideItemAmount);
|
||||
$this->hideSettingItemAmount = $this->getHideSettingItemAmount($type, $hideSettingItemAmount);
|
||||
$this->textItemAmount = $this->getTextItemAmount($type, $textItemAmount);
|
||||
|
||||
$this->hideDiscount = $this->getHideDiscount($type, $hideDiscount);
|
||||
@ -763,7 +786,7 @@ abstract class Form extends Component
|
||||
$issuedAt = Date::now()->toDateString();
|
||||
}
|
||||
|
||||
$addDays = setting($this->getSettingKey($type, 'payment_terms'), 0) ?: 0;
|
||||
$addDays = setting($this->getDocumentSettingKey($type, 'payment_terms'), 0) ?: 0;
|
||||
|
||||
$dueAt = Date::parse($issuedAt)->addDays($addDays)->toDateString();
|
||||
|
||||
@ -815,10 +838,14 @@ abstract class Form extends Component
|
||||
return $document->document_number;
|
||||
}
|
||||
|
||||
$document_number = $this->getNextDocumentNumber($type);
|
||||
$contact = ($this->contact instanceof Contact) ? $this->contact : null;
|
||||
|
||||
$utility = app(DocumentNumber::class);
|
||||
|
||||
$document_number = $utility->getNextNumber($type, $contact);
|
||||
|
||||
if (empty($document_number)) {
|
||||
$document_number = $this->getNextDocumentNumber(Document::INVOICE_TYPE);
|
||||
$document_number = $utility->getNextNumber(Document::INVOICE_TYPE, $contact);
|
||||
}
|
||||
|
||||
return $document_number;
|
||||
@ -869,25 +896,35 @@ abstract class Form extends Component
|
||||
return $hideItems;
|
||||
}
|
||||
|
||||
protected function getHideItemName($type, $hideItemName)
|
||||
protected function getHideItemName($type, $hideItemName): bool
|
||||
{
|
||||
if (! empty($hideItemName)) {
|
||||
return $hideItemName;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemName = setting($this->getSettingKey($type, 'item_name'), false) && $hideItemName == 'hide') {
|
||||
return $hideItemName;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'name');
|
||||
|
||||
if ($hide) {
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.item_name', $hideItemName) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideSettingItemName($type, $hideSettingItemName): bool
|
||||
{
|
||||
if (! empty($hideSettingItemName)) {
|
||||
return $hideSettingItemName;
|
||||
}
|
||||
|
||||
$hideItemName = setting($this->getDocumentSettingKey($type, 'item_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemName === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getTextItemName($type, $textItemName)
|
||||
@ -897,18 +934,18 @@ abstract class Form extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'item_name'), 'items') === 'custom') {
|
||||
if (empty($textItemName = setting($this->getSettingKey($type, 'item_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'item_name'), 'items') === 'custom') {
|
||||
if (empty($textItemName = setting($this->getDocumentSettingKey($type, 'item_name_input')))) {
|
||||
$textItemName = 'general.items';
|
||||
}
|
||||
|
||||
return $textItemName;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'item_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'item_name'))) != setting($this->getSettingKey($type, 'item_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'item_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'item_name'))) != setting($this->getDocumentSettingKey($type, 'item_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'item_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'item_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'items');
|
||||
@ -920,25 +957,33 @@ abstract class Form extends Component
|
||||
return 'general.items';
|
||||
}
|
||||
|
||||
protected function getHideItemDescription($type, $hideItemDescription)
|
||||
protected function getHideItemDescription($type, $hideItemDescription): bool
|
||||
{
|
||||
if (! empty($hideItemDescription)) {
|
||||
return $hideItemDescription;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemDescription = setting($this->getSettingKey($type, 'hide_item_description'), false) && $hideItemDescription == 'hide') {
|
||||
return $hideItemDescription;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'description');
|
||||
|
||||
if ($hide) {
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_item_description', $hideItemDescription);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideSettingItemDescription($type, $hideSettingItemDescription): bool
|
||||
{
|
||||
if (! empty($hideSettingItemDescription)) {
|
||||
return $hideSettingItemDescription;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_item_description'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getTextItemDescription($type, $textItemDescription)
|
||||
@ -956,25 +1001,35 @@ abstract class Form extends Component
|
||||
return 'general.description';
|
||||
}
|
||||
|
||||
protected function getHideItemQuantity($type, $hideItemQuantity)
|
||||
protected function getHideItemQuantity($type, $hideItemQuantity): bool
|
||||
{
|
||||
if (! empty($hideItemQuantity)) {
|
||||
return $hideItemQuantity;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false) && $hideItemQuantity == 'hide') {
|
||||
return $hideItemQuantity;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'quantity');
|
||||
|
||||
if ($hide) {
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.quantity_name', $hideItemQuantity) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideSettingItemQuantity($type, $hideSettingItemQuantity): bool
|
||||
{
|
||||
if (! empty($hideSettingItemQuantity)) {
|
||||
return $hideSettingItemQuantity;
|
||||
}
|
||||
|
||||
$hideItemQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemQuantity === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getTextItemQuantity($type, $textItemQuantity)
|
||||
@ -984,18 +1039,18 @@ abstract class Form extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textItemQuantity = setting($this->getSettingKey($type, 'quantity_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textItemQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name_input')))) {
|
||||
$textItemQuantity = 'invoices.quantity';
|
||||
}
|
||||
|
||||
return $textItemQuantity;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'quantity_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'quantity_name'))) != setting($this->getSettingKey($type, 'quantity_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'quantity_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'quantity_name'))) != setting($this->getDocumentSettingKey($type, 'quantity_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'quantity_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'quantity_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'quantity');
|
||||
@ -1007,25 +1062,35 @@ abstract class Form extends Component
|
||||
return 'invoices.quantity';
|
||||
}
|
||||
|
||||
protected function getHideItemPrice($type, $hideItemPrice)
|
||||
protected function getHideItemPrice($type, $hideItemPrice): bool
|
||||
{
|
||||
if (! empty($hideItemPrice)) {
|
||||
return $hideItemPrice;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemPrice = setting($this->getSettingKey($type, 'hide_price'), false) && $hideItemPrice == 'hide') {
|
||||
return $hideItemPrice;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'price');
|
||||
|
||||
if ($hide) {
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.price_name', $hideItemPrice) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideSettingItemPrice($type, $hideSettingItemPrice): bool
|
||||
{
|
||||
if (! empty($hideSettingItemPrice)) {
|
||||
return $hideSettingItemPrice;
|
||||
}
|
||||
|
||||
$hideItemPrice = setting($this->getDocumentSettingKey($type, 'price_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideItemPrice === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getTextItemPrice($type, $textItemPrice)
|
||||
@ -1035,18 +1100,18 @@ abstract class Form extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textItemPrice = setting($this->getSettingKey($type, 'price_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textItemPrice = setting($this->getDocumentSettingKey($type, 'price_name_input')))) {
|
||||
$textItemPrice = 'invoices.price';
|
||||
}
|
||||
|
||||
return $textItemPrice;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'price_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'price_name'))) != setting($this->getSettingKey($type, 'price_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'price_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'price_name'))) != setting($this->getDocumentSettingKey($type, 'price_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'price_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'price_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'price');
|
||||
@ -1058,25 +1123,33 @@ abstract class Form extends Component
|
||||
return 'invoices.price';
|
||||
}
|
||||
|
||||
protected function getHideItemAmount($type, $hideItemAmount)
|
||||
protected function getHideItemAmount($type, $hideItemAmount): bool
|
||||
{
|
||||
if (! empty($hideItemAmount)) {
|
||||
return $hideItemAmount;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
|
||||
return $hideAmount;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'amount');
|
||||
|
||||
if ($hide) {
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_amount', $hideAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideSettingItemAmount($type, $hideSettingItemAmount): bool
|
||||
{
|
||||
if (! empty($hideSettingItemAmount)) {
|
||||
return $hideSettingItemAmount;
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_amount'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getTextItemAmount($type, $textItemAmount)
|
||||
@ -1101,7 +1174,7 @@ abstract class Form extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
|
||||
if ($hideDiscount = setting($this->getDocumentSettingKey($type, 'hide_discount'), false)) {
|
||||
return $hideDiscount;
|
||||
}
|
||||
|
||||
@ -1122,7 +1195,7 @@ abstract class Form extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($settingCharLimit = setting($this->getSettingKey($type, 'item_search_chart_limit'), false)) {
|
||||
if ($settingCharLimit = setting($this->getDocumentSettingKey($type, 'item_search_chart_limit'), false)) {
|
||||
return $settingCharLimit;
|
||||
}
|
||||
|
||||
@ -1146,7 +1219,7 @@ abstract class Form extends Component
|
||||
return $this->document->notes;
|
||||
}
|
||||
|
||||
return setting($this->getSettingKey($this->type, 'notes'));
|
||||
return setting($this->getDocumentSettingKey($this->type, 'notes'));
|
||||
}
|
||||
|
||||
protected function getTextSectionAdvancedTitle($type, $textSectionAdvancedTitle)
|
||||
@ -1177,7 +1250,7 @@ abstract class Form extends Component
|
||||
return $this->document->title;
|
||||
}
|
||||
|
||||
return setting($this->getSettingKey($type, 'title'));
|
||||
return setting($this->getDocumentSettingKey($type, 'title'));
|
||||
}
|
||||
|
||||
protected function getSubheadingValue($type, $subheading)
|
||||
@ -1190,7 +1263,7 @@ abstract class Form extends Component
|
||||
return $this->document->subheading;
|
||||
}
|
||||
|
||||
return setting($this->getSettingKey($type, 'subheading'));
|
||||
return setting($this->getDocumentSettingKey($type, 'subheading'));
|
||||
}
|
||||
|
||||
protected function getFooterValue($footer)
|
||||
@ -1203,7 +1276,7 @@ abstract class Form extends Component
|
||||
return $this->document->footer;
|
||||
}
|
||||
|
||||
return setting($this->getSettingKey($this->type, 'footer'));
|
||||
return setting($this->getDocumentSettingKey($this->type, 'footer'));
|
||||
}
|
||||
|
||||
protected function getTypeCategory($type, $typeCategory)
|
||||
|
@ -392,8 +392,8 @@ abstract class Index extends Component
|
||||
foreach ($totals as $key => $total) {
|
||||
$title = ($key == 'overdue') ? trans('general.overdue') : trans('documents.statuses.' . $key);
|
||||
$href = route($route, ['search' => 'status:' . $key]);
|
||||
$amount = money($total, default_currency(), true)->formatForHumans();
|
||||
$tooltip = money($total, default_currency(), true)->format();
|
||||
$amount = money($total)->formatForHumans();
|
||||
$tooltip = money($total)->format();
|
||||
|
||||
$items[] = [
|
||||
'title' => $title,
|
||||
|
@ -11,7 +11,6 @@ use App\Abstracts\View\Component;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\Exception\NotReadableException;
|
||||
use Image;
|
||||
@ -742,9 +741,7 @@ abstract class Show extends Component
|
||||
return $textRecurringType;
|
||||
}
|
||||
|
||||
$default_key = config('type.' . static::OBJECT_TYPE . '.' . $type . '.translation.prefix');
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'recurring_tye', $default_key);
|
||||
$translation = config('type.' . static::OBJECT_TYPE . '.' . $type . '.translation.tab_document');
|
||||
|
||||
if (! empty($translation)) {
|
||||
return $translation;
|
||||
@ -910,7 +907,7 @@ abstract class Show extends Component
|
||||
return $template;
|
||||
}
|
||||
|
||||
$documentTemplate = setting($this->getSettingKey($type, 'template'), 'default');
|
||||
$documentTemplate = setting($this->getDocumentSettingKey($type, 'template'), 'default');
|
||||
|
||||
return $documentTemplate;
|
||||
}
|
||||
@ -928,7 +925,7 @@ abstract class Show extends Component
|
||||
if (! empty($media)) {
|
||||
$path = $media->getDiskPath();
|
||||
|
||||
if (Storage::missing($path)) {
|
||||
if (! $media->fileExists()) {
|
||||
return $logo;
|
||||
}
|
||||
} else {
|
||||
@ -941,7 +938,7 @@ abstract class Show extends Component
|
||||
$height = setting('invoice.logo_size_height');
|
||||
|
||||
if ($media) {
|
||||
$image->make(Storage::get($path))->resize($width, $height)->encode();
|
||||
$image->make($media->contents())->resize($width, $height)->encode();
|
||||
} else {
|
||||
$image->make($path)->resize($width, $height)->encode();
|
||||
}
|
||||
@ -975,15 +972,22 @@ abstract class Show extends Component
|
||||
return $backgroundColor;
|
||||
}
|
||||
|
||||
if ($background_color = config('type.' . static::OBJECT_TYPE . '.' . $type . '.color', false)) {
|
||||
return $background_color;
|
||||
// checking setting color
|
||||
$key = $this->getDocumentSettingKey($type, 'color');
|
||||
|
||||
if (! empty(setting($key))) {
|
||||
$backgroundColor = setting($key);
|
||||
}
|
||||
|
||||
if (! empty($alias = config('type.' . static::OBJECT_TYPE . '.' . $type . '.alias'))) {
|
||||
$type = $alias . '.' . str_replace('-', '_', $type);
|
||||
// checking config color
|
||||
if (empty($backgroundColor) && $background_color = config('type.document.' . $type . '.color', false)) {
|
||||
$backgroundColor = $background_color;
|
||||
}
|
||||
|
||||
$backgroundColor = setting($this->getSettingKey($type, 'color'), '#55588b');
|
||||
// set default color
|
||||
if (empty($backgroundColor)) {
|
||||
$backgroundColor = '#55588b';
|
||||
}
|
||||
|
||||
return $this->getHexCodeOfTailwindClass($backgroundColor);
|
||||
}
|
||||
@ -998,7 +1002,7 @@ abstract class Show extends Component
|
||||
return $this->document->title;
|
||||
}
|
||||
|
||||
$key = $this->getSettingKey($type, 'title');
|
||||
$key = $this->getDocumentSettingKey($type, 'title');
|
||||
|
||||
if (! empty(setting($key))) {
|
||||
return setting($key);
|
||||
@ -1023,7 +1027,7 @@ abstract class Show extends Component
|
||||
return $this->document->subheading;
|
||||
}
|
||||
|
||||
$key = $this->getSettingKey($type, 'subheading');
|
||||
$key = $this->getDocumentSettingKey($type, 'subheading');
|
||||
|
||||
if (!empty(setting($key))) {
|
||||
return setting($key);
|
||||
@ -1153,8 +1157,8 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'item_name'), 'items') == 'custom') {
|
||||
if (empty($textItems = setting($this->getSettingKey($type, 'item_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'item_name'), 'items') == 'custom') {
|
||||
if (empty($textItems = setting($this->getDocumentSettingKey($type, 'item_name_input')))) {
|
||||
$textItems = 'general.items';
|
||||
}
|
||||
|
||||
@ -1177,8 +1181,8 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textQuantity = setting($this->getSettingKey($type, 'quantity_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name_input')))) {
|
||||
$textQuantity = 'invoices.quantity';
|
||||
}
|
||||
|
||||
@ -1201,8 +1205,8 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textPrice = setting($this->getSettingKey($type, 'price_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textPrice = setting($this->getDocumentSettingKey($type, 'price_name_input')))) {
|
||||
$textPrice = 'invoices.price';
|
||||
}
|
||||
|
||||
@ -1256,9 +1260,11 @@ abstract class Show extends Component
|
||||
return $hideName;
|
||||
}
|
||||
|
||||
$hideName = setting($this->getDocumentSettingKey($type, 'item_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideName = setting($this->getSettingKey($type, 'item_name'), false) && $hideName == 'hide') {
|
||||
return $hideName;
|
||||
if ($hideName === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'name');
|
||||
@ -1267,8 +1273,7 @@ abstract class Show extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.item_name', $hideName) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideDescription($type, $hideDescription)
|
||||
@ -1278,8 +1283,8 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideDescription = setting($this->getSettingKey($type, 'hide_item_description'), false)) {
|
||||
return $hideDescription;
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_item_description'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'description');
|
||||
@ -1288,8 +1293,7 @@ abstract class Show extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_item_description', $hideDescription);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideQuantity($type, $hideQuantity)
|
||||
@ -1298,9 +1302,11 @@ abstract class Show extends Component
|
||||
return $hideQuantity;
|
||||
}
|
||||
|
||||
$hideQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false) && $hideQuantity == 'hide') {
|
||||
return $hideQuantity;
|
||||
if ($hideQuantity === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'quantity');
|
||||
@ -1309,8 +1315,7 @@ abstract class Show extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.quantity_name', $hideQuantity) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHidePrice($type, $hidePrice)
|
||||
@ -1319,9 +1324,11 @@ abstract class Show extends Component
|
||||
return $hidePrice;
|
||||
}
|
||||
|
||||
$hidePrice = setting($this->getDocumentSettingKey($type, 'price_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hidePrice = setting($this->getSettingKey($type, 'hide_price'), false) && $hidePrice == 'hide') {
|
||||
return $hidePrice;
|
||||
if ($hidePrice === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'price');
|
||||
@ -1330,8 +1337,7 @@ abstract class Show extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.price_name', $hidePrice) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideDiscount($type, $hideDiscount)
|
||||
@ -1341,7 +1347,7 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
|
||||
if ($hideDiscount = setting($this->getDocumentSettingKey($type, 'hide_discount'), false)) {
|
||||
return $hideDiscount;
|
||||
}
|
||||
|
||||
@ -1362,8 +1368,8 @@ abstract class Show extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
|
||||
return $hideAmount;
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_amount'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'amount');
|
||||
@ -1372,7 +1378,6 @@ abstract class Show extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_amount', $hideAmount);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ use App\Traits\Tailwind;
|
||||
use App\Traits\ViewComponents;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\Exception\NotReadableException;
|
||||
use Image;
|
||||
@ -210,7 +209,7 @@ abstract class Template extends Component
|
||||
return $template;
|
||||
}
|
||||
|
||||
$documentTemplate = setting($this->getSettingKey($type, 'template'), 'default');
|
||||
$documentTemplate = setting($this->getDocumentSettingKey($type, 'template'), 'default');
|
||||
|
||||
return $documentTemplate;
|
||||
}
|
||||
@ -228,7 +227,7 @@ abstract class Template extends Component
|
||||
if (! empty($media)) {
|
||||
$path = $media->getDiskPath();
|
||||
|
||||
if (Storage::missing($path)) {
|
||||
if (! $media->fileExists()) {
|
||||
return $logo;
|
||||
}
|
||||
} else {
|
||||
@ -241,7 +240,7 @@ abstract class Template extends Component
|
||||
$height = setting('invoice.logo_size_height');
|
||||
|
||||
if ($media) {
|
||||
$image->make(Storage::get($path))->resize($width, $height)->encode();
|
||||
$image->make($media->contents())->resize($width, $height)->encode();
|
||||
} else {
|
||||
$image->make($path)->resize($width, $height)->encode();
|
||||
}
|
||||
@ -275,16 +274,22 @@ abstract class Template extends Component
|
||||
return $backgroundColor;
|
||||
}
|
||||
|
||||
if ($background_color = config('type.document.' . $type . '.color', false)) {
|
||||
return $background_color;
|
||||
// checking setting color
|
||||
$key = $this->getDocumentSettingKey($type, 'color');
|
||||
|
||||
if (! empty(setting($key))) {
|
||||
$backgroundColor = setting($key);
|
||||
}
|
||||
|
||||
|
||||
if (! empty($alias = config('type.document.' . $type . '.alias'))) {
|
||||
$type = $alias . '.' . str_replace('-', '_', $type);
|
||||
// checking config color
|
||||
if (empty($backgroundColor) && $background_color = config('type.document.' . $type . '.color', false)) {
|
||||
$backgroundColor = $background_color;
|
||||
}
|
||||
|
||||
$backgroundColor = setting($this->getSettingKey($type, 'color'), '#55588b');
|
||||
// set default color
|
||||
if (empty($backgroundColor)) {
|
||||
$backgroundColor = '#55588b';
|
||||
}
|
||||
|
||||
return $this->getHexCodeOfTailwindClass($backgroundColor);
|
||||
}
|
||||
@ -299,7 +304,7 @@ abstract class Template extends Component
|
||||
return $this->document->title;
|
||||
}
|
||||
|
||||
$key = $this->getSettingKey($type, 'title');
|
||||
$key = $this->getDocumentSettingKey($type, 'title');
|
||||
|
||||
if (! empty(setting($key))) {
|
||||
return setting($key);
|
||||
@ -324,7 +329,7 @@ abstract class Template extends Component
|
||||
return $this->document->subheading;
|
||||
}
|
||||
|
||||
$key = $this->getSettingKey($type, 'subheading');
|
||||
$key = $this->getDocumentSettingKey($type, 'subheading');
|
||||
|
||||
if (! empty(setting($key))) {
|
||||
return setting($key);
|
||||
@ -454,18 +459,18 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'item_name'), 'items') === 'custom') {
|
||||
if (empty($textItems = setting($this->getSettingKey($type, 'item_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'item_name'), 'items') === 'custom') {
|
||||
if (empty($textItems = setting($this->getDocumentSettingKey($type, 'item_name_input')))) {
|
||||
$textItems = 'general.items';
|
||||
}
|
||||
|
||||
return $textItems;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'item_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'item_name'))) != setting($this->getSettingKey($type, 'item_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'item_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'item_name'))) != setting($this->getDocumentSettingKey($type, 'item_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'item_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'item_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'items');
|
||||
@ -484,18 +489,18 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textQuantity = setting($this->getSettingKey($type, 'quantity_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'quantity_name'), 'quantity') === 'custom') {
|
||||
if (empty($textQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name_input')))) {
|
||||
$textQuantity = 'invoices.quantity';
|
||||
}
|
||||
|
||||
return $textQuantity;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'quantity_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'quantity_name'))) != setting($this->getSettingKey($type, 'quantity_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'quantity_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'quantity_name'))) != setting($this->getDocumentSettingKey($type, 'quantity_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'quantity_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'quantity_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'quantity');
|
||||
@ -514,18 +519,18 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if (setting($this->getSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textPrice = setting($this->getSettingKey($type, 'price_name_input')))) {
|
||||
if (setting($this->getDocumentSettingKey($type, 'price_name'), 'price') === 'custom') {
|
||||
if (empty($textPrice = setting($this->getDocumentSettingKey($type, 'price_name_input')))) {
|
||||
$textPrice = 'invoices.price';
|
||||
}
|
||||
|
||||
return $textPrice;
|
||||
}
|
||||
|
||||
if (setting($this->getSettingKey($type, 'price_name')) !== null
|
||||
&& (trans(setting($this->getSettingKey($type, 'price_name'))) != setting($this->getSettingKey($type, 'price_name')))
|
||||
if (setting($this->getDocumentSettingKey($type, 'price_name')) !== null
|
||||
&& (trans(setting($this->getDocumentSettingKey($type, 'price_name'))) != setting($this->getDocumentSettingKey($type, 'price_name')))
|
||||
) {
|
||||
return setting($this->getSettingKey($type, 'price_name'));
|
||||
return setting($this->getDocumentSettingKey($type, 'price_name'));
|
||||
}
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'price');
|
||||
@ -592,9 +597,11 @@ abstract class Template extends Component
|
||||
return $hideName;
|
||||
}
|
||||
|
||||
$hideName = setting($this->getDocumentSettingKey($type, 'item_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideName = setting($this->getSettingKey($type, 'item_name'), false) && $hideName == 'hide') {
|
||||
return $hideName;
|
||||
if ($hideName === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'name');
|
||||
@ -603,8 +610,7 @@ abstract class Template extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.item_name', $hideName) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideDescription($type, $hideDescription)
|
||||
@ -614,8 +620,8 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideDescription = setting($this->getSettingKey($type, 'hide_item_description'), false)) {
|
||||
return $hideDescription;
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_item_description'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'description');
|
||||
@ -624,8 +630,7 @@ abstract class Template extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_item_description', $hideDescription);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideQuantity($type, $hideQuantity)
|
||||
@ -634,9 +639,11 @@ abstract class Template extends Component
|
||||
return $hideQuantity;
|
||||
}
|
||||
|
||||
$hideQuantity = setting($this->getDocumentSettingKey($type, 'quantity_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideQuantity = setting($this->getSettingKey($type, 'hide_quantity'), false) && $hideQuantity == 'hide') {
|
||||
return $hideQuantity;
|
||||
if ($hideQuantity === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'quantity');
|
||||
@ -645,8 +652,7 @@ abstract class Template extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.quantity_name', $hideQuantity) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHidePrice($type, $hidePrice)
|
||||
@ -655,9 +661,11 @@ abstract class Template extends Component
|
||||
return $hidePrice;
|
||||
}
|
||||
|
||||
$hidePrice = setting($this->getDocumentSettingKey($type, 'price_name'), false);
|
||||
|
||||
// if you use settting translation
|
||||
if ($hidePrice = setting($this->getSettingKey($type, 'hide_price'), false) && $hidePrice == 'hide') {
|
||||
return $hidePrice;
|
||||
if ($hidePrice === 'hide') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'price');
|
||||
@ -666,8 +674,7 @@ abstract class Template extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.price_name', $hidePrice) == 'hide' ? true : false;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHideDiscount($type, $hideDiscount)
|
||||
@ -677,7 +684,7 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideDiscount = setting($this->getSettingKey($type, 'hide_discount'), false)) {
|
||||
if ($hideDiscount = setting($this->getDocumentSettingKey($type, 'hide_discount'), false)) {
|
||||
return $hideDiscount;
|
||||
}
|
||||
|
||||
@ -698,8 +705,8 @@ abstract class Template extends Component
|
||||
}
|
||||
|
||||
// if you use settting translation
|
||||
if ($hideAmount = setting($this->getSettingKey($type, 'hide_amount'), false)) {
|
||||
return $hideAmount;
|
||||
if (setting($this->getDocumentSettingKey($type, 'hide_amount'), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hide = $this->getHideFromConfig($type, 'amount');
|
||||
@ -708,8 +715,7 @@ abstract class Template extends Component
|
||||
return $hide;
|
||||
}
|
||||
|
||||
// @todo what return value invoice or always false??
|
||||
return setting('invoice.hide_amount', $hideAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getPrint($print)
|
||||
|
@ -9,7 +9,6 @@ use App\Traits\Transactions;
|
||||
use App\Utilities\Modules;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\Facades\Image;
|
||||
@ -483,7 +482,7 @@ abstract class Show extends Component
|
||||
return $template;
|
||||
}
|
||||
|
||||
$transactionTemplate = setting($this->getSettingKey($type, 'template')) ?: 'default';
|
||||
$transactionTemplate = setting($this->getTransactionSettingKey($type, 'template')) ?: 'default';
|
||||
|
||||
return $transactionTemplate;
|
||||
}
|
||||
@ -501,7 +500,7 @@ abstract class Show extends Component
|
||||
if (! empty($media)) {
|
||||
$path = $media->getDiskPath();
|
||||
|
||||
if (Storage::missing($path)) {
|
||||
if (! $media->fileExists()) {
|
||||
return $logo;
|
||||
}
|
||||
} else {
|
||||
@ -514,7 +513,7 @@ abstract class Show extends Component
|
||||
$height = setting('invoice.logo_size_height');
|
||||
|
||||
if ($media) {
|
||||
$image->make(Storage::get($path))->resize($width, $height)->encode();
|
||||
$image->make($media->contents())->resize($width, $height)->encode();
|
||||
} else {
|
||||
$image->make($path)->resize($width, $height)->encode();
|
||||
}
|
||||
@ -1114,9 +1113,7 @@ abstract class Show extends Component
|
||||
return $textRecurringType;
|
||||
}
|
||||
|
||||
$default_key = config('type.transaction.' . $type . '.translation.transactions');
|
||||
|
||||
$translation = $this->getTextFromConfig($type, 'recurring_type', $default_key);
|
||||
$translation = config('type.transaction.' . $type . '.translation.transactions');
|
||||
|
||||
if (! empty($translation)) {
|
||||
return $translation;
|
||||
|
@ -9,7 +9,6 @@ use App\Traits\Transactions;
|
||||
use App\Utilities\Modules;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\Facades\Image;
|
||||
use Intervention\Image\Exception\NotReadableException;
|
||||
@ -277,7 +276,7 @@ abstract class Template extends Component
|
||||
if (!empty($media)) {
|
||||
$path = $media->getDiskPath();
|
||||
|
||||
if (Storage::missing($path)) {
|
||||
if (! $media->fileExists()) {
|
||||
return $logo;
|
||||
}
|
||||
} else {
|
||||
@ -290,7 +289,7 @@ abstract class Template extends Component
|
||||
$height = setting('invoice.logo_size_height');
|
||||
|
||||
if ($media) {
|
||||
$image->make(Storage::get($path))->resize($width, $height)->encode();
|
||||
$image->make($media->contents())->resize($width, $height)->encode();
|
||||
} else {
|
||||
$image->make($path)->resize($width, $height)->encode();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class Bills extends BulkAction
|
||||
],
|
||||
'cancelled' => [
|
||||
'icon' => 'cancel',
|
||||
'name' => 'general.cancel',
|
||||
'name' => 'documents.actions.cancel',
|
||||
'message' => 'bulk_actions.message.cancelled',
|
||||
'permission' => 'update-purchases-bills',
|
||||
],
|
||||
@ -67,7 +67,7 @@ class Bills extends BulkAction
|
||||
$bills = $this->getSelectedRecords($request);
|
||||
|
||||
foreach ($bills as $bill) {
|
||||
if ($bill->status == 'cancelled') {
|
||||
if (in_array($bill->status, ['cancelled', 'draft'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class Invoices extends BulkAction
|
||||
],
|
||||
'cancelled' => [
|
||||
'icon' => 'cancel',
|
||||
'name' => 'general.cancel',
|
||||
'name' => 'documents.actions.cancel',
|
||||
'message' => 'bulk_actions.message.cancelled',
|
||||
'permission' => 'update-sales-invoices',
|
||||
],
|
||||
@ -67,7 +67,7 @@ class Invoices extends BulkAction
|
||||
$invoices = $this->getSelectedRecords($request);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
if ($invoice->status == 'cancelled') {
|
||||
if (in_array($invoice->status, ['cancelled', 'draft'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classifiers;
|
||||
|
||||
use Wnx\LaravelStats\ReflectionClass;
|
||||
use Wnx\LaravelStats\Contracts\Classifier;
|
||||
|
||||
class Transformer implements Classifier
|
||||
{
|
||||
public function name(): string
|
||||
{
|
||||
return 'Transformers';
|
||||
}
|
||||
|
||||
public function satisfies(ReflectionClass $class): bool
|
||||
{
|
||||
return $class->isSubclassOf(\League\Fractal\TransformerAbstract::class);
|
||||
}
|
||||
|
||||
public function countsTowardsApplicationCode(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function countsTowardsTests(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -125,6 +125,6 @@ class DownloadModule extends Command
|
||||
$version = Versions::getLatestVersion($url, $current);
|
||||
}
|
||||
|
||||
return $version;
|
||||
return $version?->latest;
|
||||
}
|
||||
}
|
||||
|
@ -71,12 +71,18 @@ class RecurringCheck extends Command
|
||||
|
||||
$company_name = !empty($recur->company->name) ? $recur->company->name : 'Missing Company Name : ' . $recur->company->id;
|
||||
|
||||
$template = $recur->recurable()->where('company_id', $recur->company_id)->first();
|
||||
|
||||
// Check if company is disabled
|
||||
if (! $recur->company->enabled) {
|
||||
$this->info($company_name . ' company is disabled. Skipping...');
|
||||
|
||||
if (Date::parse($recur->company->updated_at)->format('Y-m-d') > Date::now()->subMonth(3)->format('Y-m-d')) {
|
||||
$recur->delete();
|
||||
|
||||
if ($template) {
|
||||
$template->delete();
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@ -98,12 +104,16 @@ class RecurringCheck extends Command
|
||||
|
||||
$recur->delete();
|
||||
|
||||
if ($template) {
|
||||
$template->delete();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
company($recur->company_id)->makeCurrent();
|
||||
|
||||
if (! $template = $recur->recurable) {
|
||||
if (! $template) {
|
||||
$this->info('Missing model.');
|
||||
|
||||
$recur->delete();
|
||||
|
@ -68,6 +68,14 @@ class Update extends Command
|
||||
|
||||
$this->old = $this->getOldVersion();
|
||||
|
||||
if (version_compare($this->old, $this->new, '>=')) {
|
||||
$message = 'The current version for the ' . $this->alias . ' is the latest version!';
|
||||
|
||||
$this->info($message);
|
||||
|
||||
return self::CMD_SUCCESS;
|
||||
}
|
||||
|
||||
company($this->company)->makeCurrent();
|
||||
|
||||
if (!$path = $this->download()) {
|
||||
@ -91,7 +99,7 @@ class Update extends Command
|
||||
|
||||
public function getNewVersion()
|
||||
{
|
||||
return ($this->argument('new') == 'latest') ? Versions::latest($this->alias) : $this->argument('new');
|
||||
return ($this->argument('new') == 'latest') ? Versions::latest($this->alias)?->latest : $this->argument('new');
|
||||
}
|
||||
|
||||
public function getOldVersion()
|
||||
|
23
app/Events/Common/DatesFormating.php
Normal file
23
app/Events/Common/DatesFormating.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
|
||||
class DatesFormating extends Event
|
||||
{
|
||||
public $columns;
|
||||
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $request
|
||||
*/
|
||||
public function __construct($columns, $request)
|
||||
{
|
||||
$this->columns = $columns;
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
20
app/Events/Document/DocumentDeleted.php
Normal file
20
app/Events/Document/DocumentDeleted.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Document;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
|
||||
class DocumentDeleted extends Event
|
||||
{
|
||||
public $document;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $document
|
||||
*/
|
||||
public function __construct($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
}
|
20
app/Events/Document/DocumentDeleting.php
Normal file
20
app/Events/Document/DocumentDeleting.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Document;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
|
||||
class DocumentDeleting extends Event
|
||||
{
|
||||
public $document;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $document
|
||||
*/
|
||||
public function __construct($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
}
|
20
app/Events/Document/DocumentSending.php
Normal file
20
app/Events/Document/DocumentSending.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Document;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
|
||||
class DocumentSending extends Event
|
||||
{
|
||||
public $document;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $document
|
||||
*/
|
||||
public function __construct($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
}
|
51
app/Events/Email/InvalidEmailDetected.php
Normal file
51
app/Events/Email/InvalidEmailDetected.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Email;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\Common\Contact;
|
||||
|
||||
class InvalidEmailDetected extends Event
|
||||
{
|
||||
public $email;
|
||||
|
||||
public $error;
|
||||
|
||||
public $contact = null;
|
||||
|
||||
public $user = null;
|
||||
|
||||
public function __construct(string $email, string $error)
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
$this->error = $error;
|
||||
|
||||
$this->setContact();
|
||||
|
||||
$this->setUser();
|
||||
}
|
||||
|
||||
public function setContact()
|
||||
{
|
||||
$contact = Contact::email($this->email)->enabled()->first();
|
||||
|
||||
if (empty($contact)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->contact = $contact;
|
||||
}
|
||||
|
||||
public function setUser()
|
||||
{
|
||||
$user = User::email($this->email)->enabled()->first();
|
||||
|
||||
if (empty($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
15
app/Events/Email/TooManyEmailsSent.php
Normal file
15
app/Events/Email/TooManyEmailsSent.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Email;
|
||||
|
||||
use App\Abstracts\Event;
|
||||
|
||||
class TooManyEmailsSent extends Event
|
||||
{
|
||||
public $user_id;
|
||||
|
||||
public function __construct(int $user_id)
|
||||
{
|
||||
$this->user_id = $user_id;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Akaunting\Money\Exceptions\UnexpectedAmountException;
|
||||
use App\Events\Email\InvalidEmailDetected;
|
||||
use App\Exceptions\Http\Resource as ResourceException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
@ -15,6 +16,7 @@ use Illuminate\View\ViewException;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException as MailerHttpTransportException;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
@ -72,6 +74,14 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
public function report(Throwable $exception)
|
||||
{
|
||||
if ($exception instanceof MailerHttpTransportException) {
|
||||
$email = $this->handleMailerExceptions($exception);
|
||||
|
||||
if (! empty($email)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
parent::report($exception);
|
||||
}
|
||||
|
||||
@ -194,6 +204,24 @@ class Handler extends ExceptionHandler
|
||||
}
|
||||
}
|
||||
|
||||
if ($exception instanceof MailerHttpTransportException) {
|
||||
$email = $this->handleMailerExceptions($exception);
|
||||
|
||||
if (! empty($email)) {
|
||||
$message = trans('notifications.menu.invalid_email.description', ['email' => $email]);
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'error' => $message,
|
||||
], $exception->getCode());
|
||||
}
|
||||
|
||||
return response()->view('errors.403', [
|
||||
'message' => $message,
|
||||
], $exception->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
||||
@ -214,6 +242,28 @@ class Handler extends ExceptionHandler
|
||||
return new Response($response, $this->getStatusCode($exception), $this->getHeaders($exception));
|
||||
}
|
||||
|
||||
protected function handleMailerExceptions(MailerHttpTransportException $exception): string
|
||||
{
|
||||
/**
|
||||
* Couldn't access the SentMessage object to get the email address
|
||||
* https://symfony.com/doc/current/mailer.html#debugging-emails
|
||||
*
|
||||
* https://codespeedy.com/extract-email-addresses-from-a-string-in-php
|
||||
* https://phpliveregex.com/p/IMG
|
||||
*/
|
||||
preg_match("/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}/", $exception->getMessage(), $matches);
|
||||
|
||||
if (empty($matches[0])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$email = $matches[0];
|
||||
|
||||
event(new InvalidEmailDetected($email, $exception->getMessage()));
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the replacements array by gathering the keys and values.
|
||||
*
|
||||
|
@ -22,6 +22,8 @@ class BillItems extends Export
|
||||
|
||||
$model->bill_number = $document->document_number;
|
||||
$model->item_name = $model->item->name;
|
||||
$model->item_description = $model->item->description;
|
||||
$model->item_type = $model->item->type;
|
||||
|
||||
return parent::map($model);
|
||||
}
|
||||
@ -31,6 +33,8 @@ class BillItems extends Export
|
||||
return [
|
||||
'bill_number',
|
||||
'item_name',
|
||||
'item_description',
|
||||
'item_type',
|
||||
'quantity',
|
||||
'price',
|
||||
'total',
|
||||
|
@ -22,6 +22,8 @@ class Customers extends Export
|
||||
|
||||
$model->country = $country;
|
||||
|
||||
$model->can_login = $model->user_id ? true : false;
|
||||
|
||||
return parent::map($model);
|
||||
}
|
||||
|
||||
@ -41,6 +43,7 @@ class Customers extends Export
|
||||
'currency_code',
|
||||
'reference',
|
||||
'enabled',
|
||||
'can_login',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ class InvoiceItems extends Export
|
||||
|
||||
$model->invoice_number = $document->document_number;
|
||||
$model->item_name = $model->item->name;
|
||||
$model->item_description = $model->item->description;
|
||||
$model->item_type = $model->item->type;
|
||||
|
||||
return parent::map($model);
|
||||
}
|
||||
@ -31,6 +33,8 @@ class InvoiceItems extends Export
|
||||
return [
|
||||
'invoice_number',
|
||||
'item_name',
|
||||
'item_description',
|
||||
'item_type',
|
||||
'quantity',
|
||||
'price',
|
||||
'total',
|
||||
|
@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
|
||||
use App\Abstracts\Http\Controller;
|
||||
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\Auth\Forgot as Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class Forgot extends Controller
|
||||
@ -42,13 +42,11 @@ class Forgot extends Controller
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Http\Requests\Auth\Forgot $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validateEmail($request);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
@ -96,7 +94,7 @@ class Forgot extends Controller
|
||||
'error' => true,
|
||||
'message' => trans('passwords.user'),
|
||||
'data' => null,
|
||||
'redirect' => null,
|
||||
'redirect' => route('forgot'),
|
||||
];
|
||||
|
||||
return response()->json($response);
|
||||
|
@ -4,7 +4,8 @@ namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Request as BaseRequest;
|
||||
use App\Http\Requests\Auth\Reset as Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@ -29,17 +30,22 @@ class Reset extends Controller
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
public function create(Request $request, $token = null)
|
||||
public function create(BaseRequest $request, $token = null)
|
||||
{
|
||||
return view('auth.reset.create')->with(
|
||||
['token' => $token, 'email' => $request->email]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param \App\Http\Requests\Auth\Reset $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validate($request, $this->rules(), $this->validationErrorMessages());
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
// will update the password on an actual user model and persist it to the
|
||||
// database. Otherwise we will parse the error and return the response.
|
||||
|
@ -47,9 +47,19 @@ class Users extends Controller
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
public function show(User $user)
|
||||
{
|
||||
return redirect()->route('users.index');
|
||||
$u = new \stdClass();
|
||||
$u->role = $user->roles()->first();
|
||||
$u->landing_pages = [];
|
||||
|
||||
event(new LandingPageShowing($u));
|
||||
|
||||
$landing_pages = $u->landing_pages;
|
||||
|
||||
$companies = $user->companies()->collect();
|
||||
|
||||
return view('auth.users.show', compact('user', 'landing_pages', 'companies'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +77,13 @@ class Users extends Controller
|
||||
$landing_pages = $u->landing_pages;
|
||||
|
||||
$roles = Role::all()->reject(function ($r) {
|
||||
return $r->hasPermission('read-client-portal');
|
||||
$status = $r->hasPermission('read-client-portal');
|
||||
|
||||
if ($r->name == 'employee') {
|
||||
$status = true;
|
||||
}
|
||||
|
||||
return $status;
|
||||
})->pluck('display_name', 'id');
|
||||
|
||||
$companies = user()->companies()->take(setting('default.select_limit'))->get()->sortBy('name')->pluck('name', 'id');
|
||||
@ -89,7 +105,7 @@ class Users extends Controller
|
||||
$response = $this->ajaxDispatch(new CreateUser($request));
|
||||
|
||||
if ($response['success']) {
|
||||
$response['redirect'] = route('users.index');
|
||||
$response['redirect'] = route('users.show', $response['data']->id);
|
||||
|
||||
$message = trans('messages.success.invited', ['type' => trans_choice('general.users', 1)]);
|
||||
|
||||
@ -129,12 +145,21 @@ class Users extends Controller
|
||||
if ($user->isCustomer()) {
|
||||
// Show only roles with customer permission
|
||||
$roles = Role::all()->reject(function ($r) {
|
||||
return !$r->hasPermission('read-client-portal');
|
||||
return ! $r->hasPermission('read-client-portal');
|
||||
})->pluck('display_name', 'id');
|
||||
} else if ($user->isEmployee()) {
|
||||
// Show only roles with employee permission
|
||||
$roles = Role::where('name', 'employee')->get()->pluck('display_name', 'id');
|
||||
} else {
|
||||
// Don't show roles with customer permission
|
||||
$roles = Role::all()->reject(function ($r) {
|
||||
return $r->hasPermission('read-client-portal');
|
||||
$status = $r->hasPermission('read-client-portal');
|
||||
|
||||
if ($r->name == 'employee') {
|
||||
$status = true;
|
||||
}
|
||||
|
||||
return $status;
|
||||
})->pluck('display_name', 'id');
|
||||
}
|
||||
|
||||
@ -176,7 +201,7 @@ class Users extends Controller
|
||||
$response = $this->ajaxDispatch(new UpdateUser($user, $request));
|
||||
|
||||
if ($response['success']) {
|
||||
$response['redirect'] = user()->can('read-auth-users') ? route('users.index') : route('users.edit', $user->id);
|
||||
$response['redirect'] = user()->can('read-auth-users') ? route('users.show', $user->id) : route('users.edit', $user->id);
|
||||
|
||||
$message = trans('messages.success.updated', ['type' => $user->name]);
|
||||
|
||||
@ -341,8 +366,6 @@ class Users extends Controller
|
||||
{
|
||||
$response = $this->ajaxDispatch(new CreateInvitation($user, company()));
|
||||
|
||||
$response['redirect'] = route('users.index');
|
||||
|
||||
if ($response['success']) {
|
||||
$message = trans('messages.success.invited', ['type' => trans_choice('general.users', 1)]);
|
||||
|
||||
@ -353,7 +376,7 @@ class Users extends Controller
|
||||
flash($message)->error()->important();
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return redirect()->route('users.index');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,16 +35,16 @@ class Accounts extends Controller
|
||||
*/
|
||||
public function show(Account $account)
|
||||
{
|
||||
$transactions = Transaction::with('category', 'contact', 'document')->where('account_id', $account->id)->collect(['paid_at'=> 'desc']);
|
||||
$transactions = Transaction::with('category', 'contact', 'contact.media', 'document', 'document.totals', 'document.media', 'recurring', 'media')->where('account_id', $account->id)->collect(['paid_at'=> 'desc']);
|
||||
|
||||
$transfers = Transfer::with('expense_transaction', 'expense_transaction.account', 'income_transaction', 'income_transaction.account')
|
||||
->whereHas('expense_transaction', fn ($query) => $query->where('account_id', $account->id))
|
||||
->orWhereHas('income_transaction', fn ($query) => $query->where('account_id', $account->id))
|
||||
->collect(['expense_transaction.paid_at' => 'desc']);
|
||||
|
||||
$incoming_amount = money($account->income_balance, $account->currency_code, true);
|
||||
$outgoing_amount = money($account->expense_balance, $account->currency_code, true);
|
||||
$current_amount = money($account->balance, $account->currency_code, true);
|
||||
$incoming_amount = money($account->income_balance, $account->currency_code);
|
||||
$outgoing_amount = money($account->expense_balance, $account->currency_code);
|
||||
$current_amount = money($account->balance, $account->currency_code);
|
||||
|
||||
$summary_amounts = [
|
||||
'incoming_exact' => $incoming_amount->format(),
|
||||
|
@ -24,8 +24,8 @@ class Reconciliations extends Controller
|
||||
{
|
||||
$reconciliations = Reconciliation::with('account')->collect();
|
||||
|
||||
$reconciled_amount = money($reconciliations->where('reconciled', 1)->sum('closing_balance'), default_currency(), true);
|
||||
$in_progress_amount = money($reconciliations->where('reconciled', 0)->sum('closing_balance'), default_currency(), true);
|
||||
$reconciled_amount = money($reconciliations->where('reconciled', 1)->sum('closing_balance'));
|
||||
$in_progress_amount = money($reconciliations->where('reconciled', 0)->sum('closing_balance'));
|
||||
|
||||
$summary_amounts = [
|
||||
'amount_exact' => $reconciled_amount->format(),
|
||||
@ -246,9 +246,9 @@ class Reconciliations extends Controller
|
||||
|
||||
$difference = $closing_balance - $cleared_amount;
|
||||
|
||||
$json->closing_balance = money($closing_balance, $currency_code, true)->format();
|
||||
$json->cleared_amount = money($cleared_amount, $currency_code, true)->format();
|
||||
$json->difference = money($difference, $currency_code, true)->format();
|
||||
$json->closing_balance = money($closing_balance, $currency_code)->format();
|
||||
$json->cleared_amount = money($cleared_amount, $currency_code)->format();
|
||||
$json->difference = money($difference, $currency_code)->format();
|
||||
$json->difference_raw = (int) $difference;
|
||||
|
||||
return response()->json($json);
|
||||
|
@ -63,9 +63,9 @@ class RecurringTransactions extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$type = request()->get('type', 'income-recurring');
|
||||
$real_type = request()->get('real_type', $this->getRealTypeOfRecurringTransaction($type));
|
||||
$contact_type = config('type.transaction.' . $real_type . '.contact_type');
|
||||
$type = $this->getTypeRecurringTransaction(request()->get('type', 'income-recurring'));
|
||||
$real_type = $this->getTypeTransaction(request()->get('real_type', $this->getRealTypeOfRecurringTransaction($type)));
|
||||
$contact_type = config('type.transaction.' . $real_type . '.contact_type', 'customer');
|
||||
|
||||
$number = $this->getNextTransactionNumber('-recurring');
|
||||
|
||||
@ -139,8 +139,8 @@ class RecurringTransactions extends Controller
|
||||
public function edit(Transaction $recurring_transaction)
|
||||
{
|
||||
$type = $recurring_transaction->type;
|
||||
$real_type = request()->get('real_type', $this->getRealTypeOfRecurringTransaction($type));
|
||||
$contact_type = config('type.transaction.' . $real_type . '.contact_type');
|
||||
$real_type = $this->getTypeTransaction(request()->get('real_type', $this->getRealTypeOfRecurringTransaction($type)));
|
||||
$contact_type = config('type.transaction.' . $real_type . '.contact_type', 'customer');
|
||||
|
||||
$number = $this->getNextTransactionNumber('-recurring');
|
||||
|
||||
|
@ -56,9 +56,9 @@ class Transactions extends Controller
|
||||
|
||||
$totals['profit'] = $totals['income'] - $totals['expense'];
|
||||
|
||||
$incoming_amount = money($totals['income'], default_currency(), true);
|
||||
$expense_amount = money($totals['expense'], default_currency(), true);
|
||||
$profit_amount = money($totals['profit'], default_currency(), true);
|
||||
$incoming_amount = money($totals['income']);
|
||||
$expense_amount = money($totals['expense']);
|
||||
$profit_amount = money($totals['profit']);
|
||||
|
||||
$summary_amounts = [
|
||||
'incoming_exact' => $incoming_amount->format(),
|
||||
@ -98,10 +98,10 @@ class Transactions extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$type = request()->get('type', 'income');
|
||||
$type = $this->getTypeTransaction(request()->get('type', 'income'));
|
||||
$real_type = $this->getRealTypeTransaction($type);
|
||||
|
||||
$number = $this->getNextTransactionNumber();
|
||||
$number = $this->getNextTransactionNumber($type);
|
||||
|
||||
$contact_type = config('type.transaction.' . $type . '.contact_type');
|
||||
|
||||
|
@ -61,19 +61,28 @@ class BulkActions extends Controller
|
||||
|
||||
$result = $bulk_actions->{$handle}($request);
|
||||
|
||||
$message = trans($bulk_actions->messages['general'], ['type' => $handle, 'count' => count($request->get('selected'))]);
|
||||
$count = count($request->get('selected'));
|
||||
$not_passed = 0;
|
||||
|
||||
if (array_key_exists($handle, $bulk_actions->messages)) {
|
||||
flash()->messages->each(function ($message) use (&$not_passed) {
|
||||
if (in_array($message->level, ['danger', 'warning'])) {
|
||||
$not_passed++;
|
||||
}
|
||||
});
|
||||
|
||||
$message = trans($bulk_actions->messages['general'], ['type' => $handle, 'count' => $count - $not_passed]);
|
||||
|
||||
if (array_key_exists($handle, $bulk_actions->messages) && $not_passed === 0) {
|
||||
$message = trans($bulk_actions->messages[$handle], ['type' => $page]);
|
||||
}
|
||||
|
||||
if (! empty($result) && ($result instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse)) {
|
||||
flash($message)->success();
|
||||
$level = $not_passed > 0 ? 'info' : 'success';
|
||||
|
||||
flash($message)->{$level}();
|
||||
|
||||
if (! empty($result) && ($result instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse)) {
|
||||
return $result;
|
||||
} elseif (! empty($result) && ($result instanceof RedirectResponse)) {
|
||||
flash($message)->success();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'redirect' => $result->getTargetUrl(),
|
||||
@ -82,8 +91,6 @@ class BulkActions extends Controller
|
||||
'message' => ''
|
||||
]);
|
||||
} else {
|
||||
flash($message)->success();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'redirect' => true,
|
||||
|
@ -16,6 +16,15 @@ class Companies extends Controller
|
||||
{
|
||||
use Uploads, Users;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Add CRUD permission checks to all methods only remove index method for all companies list.
|
||||
$this->middleware('permission:create-common-companies')->only('create', 'store', 'duplicate', 'import');
|
||||
$this->middleware('permission:read-common-companies')->only('show', 'edit', 'export');
|
||||
$this->middleware('permission:update-common-companies')->only('update', 'enable', 'disable');
|
||||
$this->middleware('permission:delete-common-companies')->only('destroy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
|
@ -34,6 +34,22 @@ class Uploads extends Controller
|
||||
return $this->streamMedia($media);
|
||||
}
|
||||
|
||||
public function inline($id)
|
||||
{
|
||||
try {
|
||||
$media = Media::find($id);
|
||||
} catch (\Exception $e) {
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
// Get file path
|
||||
if (!$this->getMediaPathOnStorage($media)) {
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
return $this->streamMedia($media, 'inline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified resource.
|
||||
*
|
||||
|
@ -15,7 +15,12 @@ class Database extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('install.database.create');
|
||||
return view('install.database.create', [
|
||||
'host' => env('DB_HOST' , 'localhost'),
|
||||
'username' => env('DB_USERNAME', ''),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'database' => env('DB_DATABASE', ''),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,9 +39,10 @@ class Database extends Controller
|
||||
$database = $request['database'];
|
||||
$username = $request['username'];
|
||||
$password = $request['password'];
|
||||
$prefix = config("database.connections.$connection.prefix", null);
|
||||
|
||||
// Check database connection
|
||||
if (!Installer::createDbTables($host, $port, $database, $username, $password)) {
|
||||
if (!Installer::createDbTables($host, $port, $database, $username, $password, $prefix)) {
|
||||
$response = [
|
||||
'status' => null,
|
||||
'success' => false,
|
||||
|
@ -14,7 +14,15 @@ class Language extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('install.language.create');
|
||||
$locale = config('app.locale');
|
||||
|
||||
$lang_allowed = language()->allowed();
|
||||
|
||||
if (! $locale || ! array_key_exists($locale, $lang_allowed)) {
|
||||
$locale = 'en-GB';
|
||||
}
|
||||
|
||||
return view('install.language.create', compact('locale', 'lang_allowed'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,11 +29,13 @@ class Settings extends Controller
|
||||
public function store(Request $request)
|
||||
{
|
||||
DB::transaction(function () use ($request) {
|
||||
$locale = session('locale') ?? config('app.locale');
|
||||
|
||||
// Create company
|
||||
Installer::createCompany($request->get('company_name'), $request->get('company_email'), session('locale'));
|
||||
Installer::createCompany($request->get('company_name'), $request->get('company_email'), $locale);
|
||||
|
||||
// Create user
|
||||
Installer::createUser($request->get('user_email'), $request->get('user_password'), session('locale'));
|
||||
Installer::createUser($request->get('user_email'), $request->get('user_password'), $locale);
|
||||
});
|
||||
|
||||
// Make the final touches
|
||||
|
@ -48,7 +48,9 @@ class Updates extends Controller
|
||||
$m->name = $row->getName();
|
||||
$m->alias = $row->get('alias');
|
||||
$m->installed = $row->get('version');
|
||||
$m->latest = $updates[$alias];
|
||||
$m->latest = $updates[$alias]->latest;
|
||||
$m->errors = $updates[$alias]->errors;
|
||||
$m->message = $updates[$alias]->message;
|
||||
|
||||
$modules[] = $m;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class Currencies extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$currency = config('money.' . $request->get('code'));
|
||||
$currency = config('money.currencies.' . $request->get('code'));
|
||||
|
||||
$request['precision'] = (int) $currency['precision'];
|
||||
$request['symbol'] = $currency['symbol'];
|
||||
|
@ -32,22 +32,22 @@ class DocumentItemColumns extends Controller
|
||||
|
||||
$item_names = [
|
||||
'hide' => trans('settings.invoice.hide.item_name'),
|
||||
'settings.invoice.item' => trans('settings.' . $type . '.item'),
|
||||
'settings.invoice.product' => trans('settings.' . $type . '.product'),
|
||||
'settings.invoice.service' => trans('settings.' . $type . '.service'),
|
||||
'settings.invoice.item' => trans('settings.invoice.item'),
|
||||
'settings.invoice.product' => trans('settings.invoice.product'),
|
||||
'settings.invoice.service' => trans('settings.invoice.service'),
|
||||
'custom' => trans('settings.invoice.custom'),
|
||||
];
|
||||
|
||||
$price_names = [
|
||||
'hide' => trans('settings.invoice.hide.price'),
|
||||
'settings.invoice.price' => trans('settings.' . $type . '.price'),
|
||||
'settings.invoice.rate' => trans('settings.' . $type . '.rate'),
|
||||
'settings.invoice.price' => trans('settings.invoice.price'),
|
||||
'settings.invoice.rate' => trans('settings.invoice.rate'),
|
||||
'custom' => trans('settings.invoice.custom'),
|
||||
];
|
||||
|
||||
$quantity_names = [
|
||||
'hide' => trans('settings.invoice.hide.quantity'),
|
||||
'settings.invoice.quantity' => trans('settings.' . $type . '.quantity'),
|
||||
'settings.invoice.quantity' => trans('settings.invoice.quantity'),
|
||||
'custom' => trans('settings.invoice.custom'),
|
||||
];
|
||||
|
||||
@ -60,17 +60,17 @@ 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'));
|
||||
$item_name = setting($this->getDocumentSettingKey($type, 'item_name'));
|
||||
$item_name_input = setting($this->getDocumentSettingKey($type, 'item_name_input'));
|
||||
$price_name = setting($this->getDocumentSettingKey($type, 'price_name'));
|
||||
$price_name_input = setting($this->getDocumentSettingKey($type, 'price_name_input'));
|
||||
$quantity_name = setting($this->getDocumentSettingKey($type, 'quantity_name'));
|
||||
$quantity_name_input = setting($this->getDocumentSettingKey($type, 'quantity_name_input'));
|
||||
$hide_item_name = setting($this->getDocumentSettingKey($type, 'hide_item_name'));
|
||||
$hide_item_description = setting($this->getDocumentSettingKey($type, 'hide_item_description'));
|
||||
$hide_quantity = setting($this->getDocumentSettingKey($type, 'hide_quantity'));
|
||||
$hide_price = setting($this->getDocumentSettingKey($type, 'hide_price'));
|
||||
$hide_amount = setting($this->getDocumentSettingKey($type, 'hide_amount'));
|
||||
|
||||
$html = view('modals.documents.item_columns', compact(
|
||||
'type',
|
||||
@ -117,7 +117,7 @@ class DocumentItemColumns extends Controller
|
||||
}
|
||||
|
||||
foreach ($fields as $key => $value) {
|
||||
$real_key = $this->getSettingKey($type, $key);
|
||||
$real_key = $this->getDocumentSettingKey($type, $key);
|
||||
|
||||
// Don't process unwanted keys
|
||||
if (in_array($key, $this->skip_keys)) {
|
||||
|
@ -51,9 +51,9 @@ class DocumentTransactions extends Controller
|
||||
$document->{$document_total->code} = $document_total->amount;
|
||||
}
|
||||
|
||||
$total = money($document->total, $currency->code, true)->format();
|
||||
$total = money($document->total, $currency->code)->format();
|
||||
|
||||
$document->grand_total = money($total, $currency->code)->getAmount();
|
||||
$document->grand_total = money($total, $currency->code, false)->getAmount();
|
||||
|
||||
if (! empty($paid)) {
|
||||
$document->grand_total = round($document->total - $paid, $currency->precision);
|
||||
@ -140,7 +140,7 @@ class DocumentTransactions extends Controller
|
||||
|
||||
$number = $transaction->number;
|
||||
|
||||
$document->grand_total = money($transaction->amount, $currency->code)->getAmount();
|
||||
$document->grand_total = money($transaction->amount, $currency->code, false)->getAmount();
|
||||
|
||||
$document->paid_at = $transaction->paid_at;
|
||||
|
||||
|
@ -242,16 +242,30 @@ class Item extends Controller
|
||||
$this->dispatch(new InstallModule($request['alias'], company_id()));
|
||||
|
||||
$name = module($request['alias'])->getName();
|
||||
$module_routes = module_attribute($request['alias'], 'routes', []);
|
||||
|
||||
$message = trans('modules.installed', ['module' => $name]);
|
||||
|
||||
flash($message)->success();
|
||||
|
||||
$redirect = route('apps.app.show', $request['alias']);
|
||||
|
||||
// Get module.json redirect route
|
||||
if (! empty($module_routes['redirect_after_install'])) {
|
||||
if (is_array($module_routes['redirect_after_install'])) {
|
||||
$route = array_shift($module_routes['redirect_after_install']);
|
||||
|
||||
$redirect = route($route, $module_routes['redirect_after_install']);
|
||||
} else {
|
||||
$redirect = route($module_routes['redirect_after_install']);
|
||||
}
|
||||
}
|
||||
|
||||
$json = [
|
||||
'success' => true,
|
||||
'error' => false,
|
||||
'message' => null,
|
||||
'redirect' => route('apps.app.show', $request['alias']),
|
||||
'redirect' => $redirect,
|
||||
'data' => [
|
||||
'name' => $name,
|
||||
'alias' => $request['alias'],
|
||||
|
@ -194,20 +194,19 @@ class Tiles extends Controller
|
||||
case 'paid':
|
||||
$response = $this->getPaidModules($data);
|
||||
|
||||
$last_page = $response->last_page;
|
||||
$last_page = ! empty($response) ? $response->last_page : 1;
|
||||
$modules = $this->prepareModules($response);
|
||||
break;
|
||||
case 'new':
|
||||
$response = $this->getNewModules($data);
|
||||
|
||||
$last_page = $response->last_page;
|
||||
$last_page = ! empty($response) ? $response->last_page : 1;
|
||||
$modules = $this->prepareModules($response);
|
||||
|
||||
break;
|
||||
case 'free':
|
||||
$response = $this->getFreeModules($data);
|
||||
|
||||
$last_page = $response->last_page;
|
||||
$last_page = ! empty($response) ? $response->last_page : 1;
|
||||
$modules = $this->prepareModules($response);
|
||||
break;
|
||||
case 'search':
|
||||
@ -215,7 +214,7 @@ class Tiles extends Controller
|
||||
|
||||
$response = $this->getSearchModules($data);
|
||||
|
||||
$last_page = $response->last_page;
|
||||
$last_page = ! empty($response) ? $response->last_page : 1;
|
||||
$modules = $this->prepareModules($response);
|
||||
break;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ use App\Exports\Purchases\Bills as Export;
|
||||
use App\Http\Requests\Common\Import as ImportRequest;
|
||||
use App\Http\Requests\Document\Document as Request;
|
||||
use App\Imports\Purchases\Bills as Import;
|
||||
use App\Jobs\Banking\CreateBankingDocumentTransaction;
|
||||
use App\Jobs\Document\CreateDocument;
|
||||
use App\Jobs\Document\DeleteDocument;
|
||||
use App\Jobs\Document\DuplicateDocument;
|
||||
@ -31,7 +30,7 @@ class Bills extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$bills = Document::bill()->with('contact', 'transactions')->collect(['issued_at' => 'desc']);
|
||||
$bills = Document::bill()->with('contact', 'items', 'item_taxes', 'last_history', 'transactions', 'totals', 'histories', 'media')->collect(['issued_at' => 'desc']);
|
||||
|
||||
return $this->response('purchases.bills.index', compact('bills'));
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class Vendors extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$vendors = Contact::with('bills.transactions')->vendor()->collect();
|
||||
$vendors = Contact::with('bills.histories', 'bills.totals', 'bills.transactions', 'media')->vendor()->collect();
|
||||
|
||||
return $this->response('purchases.vendors.index', compact('vendors'));
|
||||
}
|
||||
@ -152,7 +152,7 @@ class Vendors extends Controller
|
||||
$response = $this->ajaxDispatch(new UpdateContact($vendor, $request));
|
||||
|
||||
if ($response['success']) {
|
||||
$response['redirect'] = route('vendors.index');
|
||||
$response['redirect'] = route('vendors.show', $response['data']->id);
|
||||
|
||||
$message = trans('messages.success.updated', ['type' => $vendor->name]);
|
||||
|
||||
|
@ -30,7 +30,7 @@ class Customers extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$customers = Contact::customer()->with('invoices.transactions')->collect();
|
||||
$customers = Contact::customer()->with('invoices.histories', 'invoices.totals', 'invoices.transactions', 'media')->collect();
|
||||
|
||||
return $this->response('sales.customers.index', compact('customers'));
|
||||
}
|
||||
@ -152,7 +152,7 @@ class Customers extends Controller
|
||||
$response = $this->ajaxDispatch(new UpdateContact($customer, $request));
|
||||
|
||||
if ($response['success']) {
|
||||
$response['redirect'] = route('customers.index');
|
||||
$response['redirect'] = route('customers.show', $response['data']->id);
|
||||
|
||||
$message = trans('messages.success.updated', ['type' => $customer->name]);
|
||||
|
||||
|
@ -10,9 +10,9 @@ use App\Imports\Sales\Invoices as Import;
|
||||
use App\Jobs\Document\CreateDocument;
|
||||
use App\Jobs\Document\DeleteDocument;
|
||||
use App\Jobs\Document\DuplicateDocument;
|
||||
use App\Jobs\Document\SendDocument;
|
||||
use App\Jobs\Document\UpdateDocument;
|
||||
use App\Models\Document\Document;
|
||||
use App\Notifications\Sale\Invoice as Notification;
|
||||
use App\Traits\Documents;
|
||||
|
||||
class Invoices extends Controller
|
||||
@ -31,7 +31,7 @@ class Invoices extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$invoices = Document::invoice()->with('contact', 'transactions')->collect(['document_number'=> 'desc']);
|
||||
$invoices = Document::invoice()->with('contact', 'items', 'item_taxes', 'last_history', 'transactions', 'totals', 'histories', 'media')->collect(['document_number'=> 'desc']);
|
||||
|
||||
return $this->response('sales.invoices.index', compact('invoices'));
|
||||
}
|
||||
@ -260,12 +260,17 @@ class Invoices extends Controller
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
// Notify the customer
|
||||
$invoice->contact->notify(new Notification($invoice, 'invoice_new_customer', true));
|
||||
$response = $this->ajaxDispatch(new SendDocument($invoice));
|
||||
|
||||
event(new \App\Events\Document\DocumentSent($invoice));
|
||||
if ($response['success']) {
|
||||
$message = trans('documents.messages.email_sent', ['type' => trans_choice('general.invoices', 1)]);
|
||||
|
||||
flash(trans('documents.messages.email_sent', ['type' => trans_choice('general.invoices', 1)]))->success();
|
||||
flash($message)->success();
|
||||
} else {
|
||||
$message = $response['message'];
|
||||
|
||||
flash($message)->error()->important();
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ class Categories extends Controller
|
||||
$query->withSubcategory();
|
||||
}
|
||||
|
||||
$categories = $query->collect();
|
||||
|
||||
$types = $this->getCategoryTypes();
|
||||
|
||||
$categories = $query->type(array_keys($types))->collect();
|
||||
|
||||
return $this->response('settings.categories.index', compact('categories', 'types'));
|
||||
}
|
||||
|
||||
@ -173,7 +173,9 @@ class Categories extends Controller
|
||||
];
|
||||
});
|
||||
|
||||
return view('settings.categories.edit', compact('category', 'types', 'type_disabled', 'categories'));
|
||||
$parent_categories = $categories[$category->type] ?? [];
|
||||
|
||||
return view('settings.categories.edit', compact('category', 'types', 'type_disabled', 'categories', 'parent_categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,13 +232,13 @@ class Currencies extends Controller
|
||||
|
||||
$code = request('code');
|
||||
|
||||
$currencies = Currency::all()->pluck('rate', 'code');
|
||||
|
||||
if ($code) {
|
||||
$currency = config('money.' . $code);
|
||||
$currencies = Currency::all()->pluck('rate', 'code');
|
||||
|
||||
$currency = config('money.currencies.' . $code);
|
||||
|
||||
$currency['rate'] = isset($currencies[$code]) ? $currencies[$code] : null;
|
||||
$currency['symbol_first'] = $currency['symbol_first'] ? 1 : 0;
|
||||
$currency['symbol_first'] = ! empty($currency['symbol_first']) ? 1 : 0;
|
||||
|
||||
$json = (object) $currency;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Settings;
|
||||
|
||||
use App\Abstracts\Http\SettingController;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Setting\Category;
|
||||
use App\Models\Setting\Tax;
|
||||
|
||||
@ -10,6 +11,8 @@ class Defaults extends SettingController
|
||||
{
|
||||
public function edit()
|
||||
{
|
||||
$accounts = Account::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
||||
|
||||
$sales_categories = Category::income()->enabled()->orderBy('name')->take(setting('default.select_limit'))->get();
|
||||
|
||||
$sale_category_id = setting('default.income_category');
|
||||
@ -37,6 +40,7 @@ class Defaults extends SettingController
|
||||
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
||||
|
||||
return view('settings.default.edit', compact(
|
||||
'accounts',
|
||||
'sales_categories',
|
||||
'purchases_categories',
|
||||
'taxes',
|
||||
|
@ -16,7 +16,7 @@ class Kernel extends HttpKernel
|
||||
protected $middleware = [
|
||||
\App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
@ -141,13 +141,13 @@ class Kernel extends HttpKernel
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
* The application's middleware aliases.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
* Aliases may be used to conveniently assign middleware to routes and groups.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, class-string|string>
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
protected $middlewareAliases = [
|
||||
// Laravel
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
|
@ -26,11 +26,11 @@ class Browser extends Component
|
||||
$this->status = false;
|
||||
}
|
||||
} elseif (Str::contains($user_agent, 'Edg')) {
|
||||
// $view = 'livewire.notification.browser.chrome';
|
||||
} elseif (Str::contains($user_agent, 'Safari')) {
|
||||
// $view = 'livewire.notification.browser.edge';
|
||||
} elseif (Str::contains($user_agent, 'Chrome')) {
|
||||
} elseif (Str::contains($user_agent, 'Safari')) {
|
||||
// $view = 'livewire.notification.browser.safari';
|
||||
} elseif (Str::contains($user_agent, 'Chrome')) {
|
||||
// $view = 'livewire.notification.browser.chrome';
|
||||
} elseif (Str::contains($user_agent, 'Opera')) {
|
||||
// $view = 'livewire.notification.browser.opera';
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Events\Common\DatesFormating;
|
||||
use Closure;
|
||||
use Date;
|
||||
|
||||
@ -10,14 +11,29 @@ class DateFormat
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (($request->method() == 'POST') || ($request->method() == 'PATCH')) {
|
||||
$fields = ['paid_at', 'due_at', 'issued_at', 'started_at', 'ended_at', 'expire_at'];
|
||||
$columns = new \stdClass();
|
||||
$columns->fields = [
|
||||
'paid_at',
|
||||
'due_at',
|
||||
'issued_at',
|
||||
'started_at',
|
||||
'ended_at',
|
||||
'expire_at',
|
||||
'recurring_started_at',
|
||||
'recurring_limit_date',
|
||||
];
|
||||
|
||||
event(new DatesFormating($columns, $request));
|
||||
|
||||
$fields = $columns->fields;
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$date = $request->get($field);
|
||||
@ -27,7 +43,7 @@ class DateFormat
|
||||
}
|
||||
|
||||
if (Date::parse($date)->format('H:i:s') == '00:00:00') {
|
||||
$new_date = Date::parse($date)->format('Y-m-d') . ' ' . Date::now()->format('H:i:s');
|
||||
$new_date = Date::parse($date)->format('Y-m-d') . ' ' . Date::now()->format('H:i:s');
|
||||
} else {
|
||||
$new_date = Date::parse($date)->toDateTimeString();
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class Money
|
||||
|
||||
$amount = $item['price'];
|
||||
|
||||
if (strpos($item['price'], config('money.' . $currency_code . '.symbol')) !== false) {
|
||||
if (strpos($item['price'], config('money.currencies.' . $currency_code . '.symbol')) !== false) {
|
||||
$amount = $this->getAmount($item['price'], $currency_code);
|
||||
}
|
||||
|
||||
@ -101,11 +101,11 @@ class Money
|
||||
protected function getAmount($money_format, $currency_code)
|
||||
{
|
||||
try {
|
||||
if (config('money.' . $currency_code . '.decimal_mark') !== '.') {
|
||||
$money_format = Str::replaceFirst('.', config('money.' . $currency_code . '.decimal_mark'), $money_format);
|
||||
if (config('money.currencies.' . $currency_code . '.decimal_mark') !== '.') {
|
||||
$money_format = Str::replaceFirst('.', config('money.currencies.' . $currency_code . '.decimal_mark'), $money_format);
|
||||
}
|
||||
|
||||
$amount = money($money_format, $currency_code)->getAmount();
|
||||
$amount = money($money_format, $currency_code, false)->getAmount();
|
||||
} catch (InvalidArgumentException | OutOfBoundsException | UnexpectedValueException $e) {
|
||||
report($e);
|
||||
|
||||
|
30
app/Http/Requests/Auth/Forgot.php
Normal file
30
app/Http/Requests/Auth/Forgot.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Auth;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class Forgot extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
];
|
||||
}
|
||||
}
|
32
app/Http/Requests/Auth/Reset.php
Normal file
32
app/Http/Requests/Auth/Reset.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Auth;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class Reset extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'token' => 'required',
|
||||
'email' => 'required|email',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
];
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ class Transaction extends FormRequest
|
||||
}
|
||||
|
||||
// Get company id
|
||||
$company_id = (int) $this->request->get('company_id');
|
||||
$company_id = (int) $this->request->get('company_id', company_id());
|
||||
|
||||
$attachment = 'nullable';
|
||||
|
||||
@ -37,7 +37,7 @@ class Transaction extends FormRequest
|
||||
$attachment = 'mimes:' . config('filesystems.mimes') . '|between:0,' . config('filesystems.max_size') * 1024;
|
||||
}
|
||||
|
||||
return [
|
||||
$rules = [
|
||||
'type' => 'required|string',
|
||||
'number' => 'required|string|unique:transactions,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL',
|
||||
'account_id' => 'required|integer',
|
||||
@ -53,6 +53,29 @@ class Transaction extends FormRequest
|
||||
'recurring_count' => 'gte:0',
|
||||
'recurring_interval' => 'exclude_unless:recurring_frequency,custom|gt:0',
|
||||
];
|
||||
|
||||
// Is Recurring
|
||||
if ($this->request->has('recurring_frequency')) {
|
||||
// first line of the recurring rule
|
||||
if ($this->request->get('recurring_frequency') == 'custom') {
|
||||
$rules['recurring_interval'] = 'required|gte:1';
|
||||
$rules['recurring_custom_frequency'] = 'required|string|in:daily,weekly,monthly,yearly';
|
||||
}
|
||||
|
||||
// second line of the recurring rule
|
||||
$rules['recurring_started_at'] = 'required|date_format:Y-m-d H:i:s';
|
||||
|
||||
switch($this->request->get('recurring_limit')) {
|
||||
case 'date':
|
||||
$rules['recurring_limit_date'] = 'required|date_format:Y-m-d H:i:s|after_or_equal:recurring_started_at';
|
||||
break;
|
||||
case 'count':
|
||||
$rules['recurring_limit_count'] = 'required|gte:0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function withValidator($validator)
|
||||
@ -61,6 +84,18 @@ class Transaction extends FormRequest
|
||||
$paid_at = Date::parse($this->request->get('paid_at'))->format('Y-m-d');
|
||||
|
||||
$this->request->set('paid_at', $paid_at);
|
||||
|
||||
if ($this->request->get('recurring_started_at')) {
|
||||
$recurring_started_at = Date::parse($this->request->get('recurring_started_at'))->format('Y-m-d');
|
||||
|
||||
$this->request->set('recurring_started_at', $recurring_started_at);
|
||||
}
|
||||
|
||||
if ($this->request->get('recurring_limit_date')) {
|
||||
$recurring_limit_date = Date::parse($this->request->get('recurring_limit_date'))->format('Y-m-d');
|
||||
|
||||
$this->request->set('recurring_limit_date', $recurring_limit_date);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,10 @@ class CustomMail extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'to' => 'required|email',
|
||||
'subject' => 'required|string',
|
||||
'body' => 'required|string',
|
||||
'to' => 'required|email',
|
||||
'subject' => 'required|string',
|
||||
'body' => 'required|string',
|
||||
'attachments.*' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class Item extends FormRequest
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => 'required|string',
|
||||
'type' => 'required|string|in:product,service',
|
||||
'name' => 'required|string',
|
||||
'sale_price' => $sale_price . '|regex:/^(?=.*?[0-9])[0-9.,]+$/',
|
||||
'purchase_price' => $purchase_price . '|regex:/^(?=.*?[0-9])[0-9.,]+$/',
|
||||
|
@ -48,6 +48,7 @@ class Document extends FormRequest
|
||||
$rules = [
|
||||
'type' => 'required|string',
|
||||
'document_number' => 'required|string|unique:documents,NULL,' . $id . ',id,type,' . $type . ',company_id,' . $company_id . ',deleted_at,NULL',
|
||||
//'status' => 'required|string|in:draft,paid,partial,sent,received,viewed,cancelled',
|
||||
'status' => 'required|string',
|
||||
'issued_at' => 'required|date_format:Y-m-d H:i:s|before_or_equal:due_at',
|
||||
'due_at' => 'required|date_format:Y-m-d H:i:s|after_or_equal:issued_at',
|
||||
@ -65,6 +66,27 @@ class Document extends FormRequest
|
||||
'recurring_interval' => 'exclude_unless:recurring_frequency,custom|gt:0',
|
||||
];
|
||||
|
||||
// Is Recurring
|
||||
if ($this->request->has('recurring_frequency')) {
|
||||
// first line of the recurring rule
|
||||
if ($this->request->get('recurring_frequency') == 'custom') {
|
||||
$rules['recurring_interval'] = 'required|gte:1';
|
||||
$rules['recurring_custom_frequency'] = 'required|string|in:daily,weekly,monthly,yearly';
|
||||
}
|
||||
|
||||
// second line of the recurring rule
|
||||
$rules['recurring_started_at'] = 'required|date_format:Y-m-d H:i:s';
|
||||
|
||||
switch($this->request->get('recurring_limit')) {
|
||||
case 'date':
|
||||
$rules['recurring_limit_date'] = 'required|date_format:Y-m-d H:i:s|after_or_equal:recurring_started_at';
|
||||
break;
|
||||
case 'count':
|
||||
$rules['recurring_limit_count'] = 'required|gte:0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$items = $this->request->all('items');
|
||||
|
||||
if ($items) {
|
||||
@ -93,6 +115,18 @@ class Document extends FormRequest
|
||||
|
||||
$this->request->set('issued_at', $issued_at);
|
||||
$this->request->set('due_at', $due_at);
|
||||
|
||||
if ($this->request->has('recurring_started_at')) {
|
||||
$recurring_started_at = Date::parse($this->request->get('recurring_started_at'))->format('Y-m-d');
|
||||
|
||||
$this->request->set('recurring_started_at', $recurring_started_at);
|
||||
}
|
||||
|
||||
if ($this->request->has('recurring_limit_date')) {
|
||||
$recurring_limit_date = Date::parse($this->request->get('recurring_limit_date'))->format('Y-m-d');
|
||||
|
||||
$this->request->set('recurring_limit_date', $recurring_limit_date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,11 @@ class Category extends FormRequest
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$types = collect(config('type.category'))->keys();
|
||||
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'type' => 'required|string',
|
||||
'type' => 'required|string|in:' . $types->implode(','),
|
||||
'color' => 'required|string',
|
||||
];
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ class Setting extends FormRequest
|
||||
$rules['number_digit'] = 'required|integer|min:1|max:20';
|
||||
}
|
||||
|
||||
if ($this->request->has('number_next')) {
|
||||
$rules['number_next'] = 'required|integer';
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@ class Tax extends FormRequest
|
||||
$enabled = 'nullable';
|
||||
}
|
||||
|
||||
$company_id = (int) $this->request->get('company_id');
|
||||
$company_id = (int) $this->request->get('company_id', company_id());
|
||||
|
||||
$type = 'required|string';
|
||||
$type = 'required|string|in:fixed,normal,inclusive,withholding,compound';
|
||||
|
||||
if (!empty($this->request->get('type')) && $this->request->get('type') == 'compound') {
|
||||
$type .= '|unique:taxes,NULL,' . $id . ',id,company_id,' . $company_id . ',type,compound,deleted_at,NULL';
|
||||
@ -32,7 +32,7 @@ class Tax extends FormRequest
|
||||
|
||||
return [
|
||||
'name' => 'required|string',
|
||||
'rate' => 'required|min:0|max:100',
|
||||
'rate' => 'required|numeric|min:0|max:100',
|
||||
'type' => $type,
|
||||
'enabled' => $enabled,
|
||||
];
|
||||
|
@ -22,9 +22,9 @@ class Account extends JsonResource
|
||||
'number' => $this->number,
|
||||
'currency_code' => $this->currency_code,
|
||||
'opening_balance' => $this->opening_balance,
|
||||
'opening_balance_formatted' => money($this->opening_balance, $this->currency_code, true)->format(),
|
||||
'opening_balance_formatted' => money($this->opening_balance, $this->currency_code)->format(),
|
||||
'current_balance' => $this->balance,
|
||||
'current_balance_formatted' => money($this->balance, $this->currency_code, true)->format(),
|
||||
'current_balance_formatted' => money($this->balance, $this->currency_code)->format(),
|
||||
'bank_name' => $this->bank_name,
|
||||
'bank_phone' => $this->bank_phone,
|
||||
'bank_address' => $this->bank_address,
|
||||
|
@ -22,7 +22,7 @@ class Reconciliation extends JsonResource
|
||||
'started_at' => $this->started_at->toIso8601String(),
|
||||
'ended_at' => $this->ended_at->toIso8601String(),
|
||||
'closing_balance' => $this->closing_balance,
|
||||
'closing_balance_formatted' => money($this->closing_balance, default_currency(), true)->format(),
|
||||
'closing_balance_formatted' => money($this->closing_balance)->format(),
|
||||
'reconciled' => $this->reconciled,
|
||||
'created_from' => $this->created_from,
|
||||
'created_by' => $this->created_by,
|
||||
|
@ -25,7 +25,7 @@ class Transaction extends JsonResource
|
||||
'account_id' => $this->account_id,
|
||||
'paid_at' => $this->paid_at->toIso8601String(),
|
||||
'amount' => $this->amount,
|
||||
'amount_formatted' => money($this->amount, $this->currency_code, true)->format(),
|
||||
'amount_formatted' => money($this->amount, $this->currency_code)->format(),
|
||||
'currency_code' => $this->currency_code,
|
||||
'currency_rate' => $this->currency_rate,
|
||||
'document_id' => $this->document_id,
|
||||
|
@ -25,7 +25,7 @@ class Transfer extends JsonResource
|
||||
'to_account' => $income_transaction->account->name,
|
||||
'to_account_id' => $income_transaction->account->id,
|
||||
'amount' => $expense_transaction->amount,
|
||||
'amount_formatted' => money($expense_transaction->amount, $expense_transaction->currency_code, true)->format(),
|
||||
'amount_formatted' => money($expense_transaction->amount, $expense_transaction->currency_code)->format(),
|
||||
'currency_code' => $expense_transaction->currency_code,
|
||||
'paid_at' => $expense_transaction->paid_at ? $expense_transaction->paid_at->toIso8601String() : '',
|
||||
'created_from' => $this->created_from,
|
||||
|
@ -23,9 +23,9 @@ class Item extends JsonResource
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'sale_price' => $this->sale_price,
|
||||
'sale_price_formatted' => money($this->sale_price, default_currency(), true)->format(),
|
||||
'sale_price_formatted' => money((double) $this->sale_price)->format(),
|
||||
'purchase_price' => $this->purchase_price,
|
||||
'purchase_price_formatted' => money($this->purchase_price, default_currency(), true)->format(),
|
||||
'purchase_price_formatted' => money((double) $this->purchase_price)->format(),
|
||||
'category_id' => $this->category_id,
|
||||
'picture' => $this->picture,
|
||||
'enabled' => $this->enabled,
|
||||
|
@ -8,6 +8,7 @@ use App\Http\Resources\Document\DocumentHistory;
|
||||
use App\Http\Resources\Document\DocumentItem;
|
||||
use App\Http\Resources\Document\DocumentItemTax;
|
||||
use App\Http\Resources\Document\DocumentTotal;
|
||||
use App\Http\Resources\Setting\Category;
|
||||
use App\Http\Resources\Setting\Currency;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@ -31,7 +32,8 @@ class Document extends JsonResource
|
||||
'issued_at' => $this->issued_at ? $this->issued_at->toIso8601String() : '',
|
||||
'due_at' => $this->due_at ? $this->due_at->toIso8601String() : '',
|
||||
'amount' => $this->amount,
|
||||
'amount_formatted' => money($this->amount, $this->currency_code, true)->format(),
|
||||
'amount_formatted' => money($this->amount, $this->currency_code)->format(),
|
||||
'category_id' => $this->category_id,
|
||||
'currency_code' => $this->currency_code,
|
||||
'currency_rate' => $this->currency_rate,
|
||||
'contact_id' => $this->contact_id,
|
||||
@ -50,6 +52,7 @@ class Document extends JsonResource
|
||||
'created_by' => $this->created_by,
|
||||
'created_at' => $this->created_at ? $this->created_at->toIso8601String() : '',
|
||||
'updated_at' => $this->updated_at ? $this->updated_at->toIso8601String() : '',
|
||||
'category' => new Category($this->category),
|
||||
'currency' => new Currency($this->currency),
|
||||
'contact' => new Contact($this->contact),
|
||||
'histories' => [static::$wrap => DocumentHistory::collection($this->histories)],
|
||||
|
@ -22,10 +22,11 @@ class DocumentItem extends JsonResource
|
||||
'document_id' => $this->document_id,
|
||||
'item_id' => $this->item_id,
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'price' => $this->price,
|
||||
'price_formatted' => money($this->price, $this->document->currency_code, true)->format(),
|
||||
'price_formatted' => money($this->price, $this->document->currency_code)->format(),
|
||||
'total' => $this->total,
|
||||
'total_formatted' => money($this->total, $this->document->currency_code, true)->format(),
|
||||
'total_formatted' => money($this->total, $this->document->currency_code)->format(),
|
||||
'created_from' => $this->created_from,
|
||||
'created_by' => $this->created_by,
|
||||
'created_at' => $this->created_at ? $this->created_at->toIso8601String() : '',
|
||||
|
@ -24,7 +24,7 @@ class DocumentItemTax extends JsonResource
|
||||
'tax_id' => $this->tax_id,
|
||||
'name' => $this->name,
|
||||
'amount' => $this->amount,
|
||||
'amount_formatted' => money($this->amount, $this->document->currency_code, true)->format(),
|
||||
'amount_formatted' => money($this->amount, $this->document->currency_code)->format(),
|
||||
'created_from' => $this->created_from,
|
||||
'created_by' => $this->created_by,
|
||||
'created_at' => $this->created_at ? $this->created_at->toIso8601String() : '',
|
||||
|
@ -22,7 +22,7 @@ class DocumentTotal extends JsonResource
|
||||
'code' => $this->code,
|
||||
'name' => $this->name,
|
||||
'amount' => $this->amount,
|
||||
'amount_formatted' => money($this->amount, $this->document->currency_code, true)->format(),
|
||||
'amount_formatted' => money($this->amount, $this->document->currency_code)->format(),
|
||||
'sort_order' => $this->sort_order,
|
||||
'created_from' => $this->created_from,
|
||||
'created_by' => $this->created_by,
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model;
|
||||
|
||||
class Transactions extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -17,17 +19,12 @@ class Transactions extends Import
|
||||
{
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['currency_code'] = $this->getCurrencyCode($row);
|
||||
$row['account_id'] = $this->getAccountId($row);
|
||||
$row['category_id'] = $this->getCategoryId($row);
|
||||
$row['contact_id'] = $this->getContactId($row);
|
||||
$row['currency_code'] = $this->getCurrencyCode($row);
|
||||
$row['document_id'] = $this->getDocumentId($row);
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ class Transfers extends Import
|
||||
$row = parent::map($row);
|
||||
|
||||
$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['from_currency_code'] = $this->getFromCurrencyCode($row);
|
||||
$row['to_currency_code'] = $this->getToCurrencyCode($row);
|
||||
$row['from_account_id'] = $this->getFromAccountId($row);
|
||||
$row['to_account_id'] = $this->getToAccountId($row);
|
||||
$row['expense_transaction_id'] = $this->getExpenseTransactionId($row);
|
||||
$row['income_transaction_id'] = $this->getIncomeTransactionId($row);
|
||||
|
||||
@ -41,10 +41,10 @@ class Transfers extends Import
|
||||
return [
|
||||
'from_account_id' => 'required|integer',
|
||||
'from_currency_code' => 'required|string|currency',
|
||||
'from_currency_rate' => 'required',
|
||||
'from_currency_rate' => 'required|gt:0',
|
||||
'to_account_id' => 'required|integer',
|
||||
'to_currency_code' => 'required|string|currency',
|
||||
'to_currency_rate' => 'required',
|
||||
'to_currency_rate' => 'required|gt:0',
|
||||
'amount' => 'required|amount',
|
||||
'transferred_at' => 'required|date_format:Y-m-d',
|
||||
'payment_method' => 'required|string',
|
||||
|
@ -4,11 +4,12 @@ namespace App\Imports\Common\Sheets;
|
||||
|
||||
use App\Abstracts\Import;
|
||||
use App\Http\Requests\Common\ItemTax as Request;
|
||||
use App\Models\Common\Item;
|
||||
use App\Models\Common\ItemTax as Model;
|
||||
|
||||
class ItemTaxes extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -16,21 +17,16 @@ class ItemTaxes extends Import
|
||||
|
||||
public function map($row): array
|
||||
{
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['item_id'] = (int) Item::where('name', $row['item_name'])->value('id');
|
||||
|
||||
if ($this->isEmpty($row, 'item_id')) {
|
||||
if ($this->isEmpty($row, 'item_name')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['item_id'] = $this->getItemId($row);
|
||||
|
||||
$row['tax_id'] = $this->getTaxId($row);
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Common\Item as Model;
|
||||
|
||||
class Items extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -25,9 +27,4 @@ class Items extends Import
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentHistory as Model;
|
||||
|
||||
class BillHistories extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class BillHistories extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::bill()->number($row['bill_number'])->pluck('id')->first();
|
||||
@ -31,10 +35,8 @@ class BillHistories extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = 'required|string';
|
||||
|
||||
unset($rules['bill_id']);
|
||||
|
@ -11,6 +11,8 @@ use App\Models\Document\DocumentItemTax as Model;
|
||||
|
||||
class BillItemTaxes extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -22,6 +24,8 @@ class BillItemTaxes extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::bill()->number($row['bill_number'])->pluck('id')->first();
|
||||
@ -44,10 +48,8 @@ class BillItemTaxes extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = 'required|string';
|
||||
|
||||
unset($rules['bill_id']);
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentItem as Model;
|
||||
|
||||
class BillItems extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class BillItems extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::bill()->number($row['bill_number'])->pluck('id')->first();
|
||||
@ -30,6 +34,8 @@ class BillItems extends Import
|
||||
$row['name'] = $row['item_name'];
|
||||
}
|
||||
|
||||
$row['description'] = !empty($row['item_description']) ? $row['item_description'] : '';
|
||||
|
||||
$row['tax'] = (double) $row['tax'];
|
||||
$row['tax_id'] = 0;
|
||||
$row['type'] = Document::BILL_TYPE;
|
||||
@ -37,10 +43,8 @@ class BillItems extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = 'required|string';
|
||||
|
||||
unset($rules['bill_id']);
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentTotal as Model;
|
||||
|
||||
class BillTotals extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class BillTotals extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::bill()->number($row['bill_number'])->pluck('id')->first();
|
||||
@ -28,10 +32,8 @@ class BillTotals extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = 'required|string';
|
||||
|
||||
unset($rules['bill_id']);
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model;
|
||||
|
||||
class BillTransactions extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -19,6 +21,8 @@ class BillTransactions extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['type'] = 'expense';
|
||||
@ -32,10 +36,8 @@ class BillTransactions extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = 'required|string';
|
||||
|
||||
return $rules;
|
||||
|
@ -9,6 +9,8 @@ use Illuminate\Support\Str;
|
||||
|
||||
class Bills extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class Bills extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['bill_number'] = (string) $row['bill_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$country = array_search($row['contact_country'], trans('countries'));
|
||||
@ -35,16 +39,14 @@ class Bills extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['bill_number'] = Str::replaceFirst('unique:documents,NULL', 'unique:documents,document_number', $rules['document_number']);
|
||||
$rules['billed_at'] = $rules['issued_at'];
|
||||
$rules['currency_rate'] = 'required';
|
||||
$rules['currency_rate'] = 'required|gt:0';
|
||||
|
||||
unset($rules['document_number'], $rules['issued_at'], $rules['type']);
|
||||
|
||||
return $this->replaceForBatchRules($rules);
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Common\Contact as Model;
|
||||
|
||||
class Vendors extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -26,9 +28,4 @@ class Vendors extends Import
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,14 @@
|
||||
namespace App\Imports\Sales;
|
||||
|
||||
use App\Abstracts\Import;
|
||||
use App\Models\Auth\User;
|
||||
use App\Http\Requests\Common\Contact as Request;
|
||||
use App\Models\Common\Contact as Model;
|
||||
|
||||
class Customers extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -24,11 +27,10 @@ class Customers extends Import
|
||||
$row['currency_code'] = $this->getCurrencyCode($row);
|
||||
$row['user_id'] = null;
|
||||
|
||||
if (isset($row['can_login']) && isset($row['email'])) {
|
||||
$row['user_id'] = User::where('email', $row['email'])->first()?->id ?? null;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentHistory as Model;
|
||||
|
||||
class InvoiceHistories extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class InvoiceHistories extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::invoice()->number($row['invoice_number'])->pluck('id')->first();
|
||||
@ -31,10 +35,8 @@ class InvoiceHistories extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = 'required|string';
|
||||
|
||||
unset($rules['invoice_id']);
|
||||
|
@ -11,6 +11,8 @@ use App\Models\Document\DocumentItemTax as Model;
|
||||
|
||||
class InvoiceItemTaxes extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -22,6 +24,8 @@ class InvoiceItemTaxes extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::invoice()->number($row['invoice_number'])->pluck('id')->first();
|
||||
@ -44,10 +48,8 @@ class InvoiceItemTaxes extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = 'required|string';
|
||||
|
||||
unset($rules['invoice_id']);
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentItem as Model;
|
||||
|
||||
class InvoiceItems extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,16 +22,20 @@ class InvoiceItems extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::invoice()->number($row['invoice_number'])->pluck('id')->first();
|
||||
|
||||
if (empty($row['item_id']) && !empty($row['item_name'])) {
|
||||
if (empty($row['item_id']) && ! empty($row['item_name'])) {
|
||||
$row['item_id'] = $this->getItemIdFromName($row);
|
||||
|
||||
$row['name'] = $row['item_name'];
|
||||
}
|
||||
|
||||
$row['description'] = !empty($row['item_description']) ? $row['item_description'] : '';
|
||||
|
||||
$row['tax'] = (double) $row['tax'];
|
||||
$row['tax_id'] = 0;
|
||||
$row['type'] = Document::INVOICE_TYPE;
|
||||
@ -37,10 +43,8 @@ class InvoiceItems extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = 'required|string';
|
||||
|
||||
unset($rules['invoice_id']);
|
||||
|
@ -9,6 +9,8 @@ use App\Models\Document\DocumentTotal as Model;
|
||||
|
||||
class InvoiceTotals extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class InvoiceTotals extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['document_id'] = (int) Document::invoice()->number($row['invoice_number'])->pluck('id')->first();
|
||||
@ -28,10 +32,8 @@ class InvoiceTotals extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = 'required|string';
|
||||
|
||||
unset($rules['invoice_id']);
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model;
|
||||
|
||||
class InvoiceTransactions extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -19,23 +21,23 @@ class InvoiceTransactions extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$row['type'] = 'income';
|
||||
$row['currency_code'] = $this->getCurrencyCode($row);
|
||||
$row['account_id'] = $this->getAccountId($row);
|
||||
$row['category_id'] = $this->getCategoryId($row, 'income');
|
||||
$row['contact_id'] = $this->getContactId($row, 'customer');
|
||||
$row['currency_code'] = $this->getCurrencyCode($row);
|
||||
$row['document_id'] = $this->getDocumentId($row);
|
||||
$row['number'] = $row['transaction_number'];
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = 'required|string';
|
||||
|
||||
return $rules;
|
||||
|
@ -9,6 +9,8 @@ use Illuminate\Support\Str;
|
||||
|
||||
class Invoices extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -20,6 +22,8 @@ class Invoices extends Import
|
||||
return [];
|
||||
}
|
||||
|
||||
$row['invoice_number'] = (string) $row['invoice_number'];
|
||||
|
||||
$row = parent::map($row);
|
||||
|
||||
$country = array_search($row['contact_country'], trans('countries'));
|
||||
@ -35,16 +39,14 @@ class Invoices extends Import
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
public function prepareRules(array $rules): array
|
||||
{
|
||||
$rules = (new Request())->rules();
|
||||
|
||||
$rules['invoice_number'] = Str::replaceFirst('unique:documents,NULL', 'unique:documents,document_number', $rules['document_number']);
|
||||
$rules['invoiced_at'] = $rules['issued_at'];
|
||||
$rules['currency_rate'] = 'required';
|
||||
$rules['currency_rate'] = 'required|gt:0';
|
||||
|
||||
unset($rules['document_number'], $rules['issued_at'], $rules['type']);
|
||||
|
||||
return $this->replaceForBatchRules($rules);
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use App\Models\Setting\Category as Model;
|
||||
|
||||
class Categories extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
@ -21,9 +23,4 @@ class Categories extends Import
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,10 @@ use App\Models\Setting\Tax as Model;
|
||||
|
||||
class Taxes extends Import
|
||||
{
|
||||
public $request_class = Request::class;
|
||||
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Model($row);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return (new Request())->rules();
|
||||
}
|
||||
}
|
||||
|
12
app/Interfaces/Utility/DocumentNumber.php
Normal file
12
app/Interfaces/Utility/DocumentNumber.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Interfaces\Utility;
|
||||
|
||||
use App\Models\Common\Contact;
|
||||
|
||||
interface DocumentNumber
|
||||
{
|
||||
public function getNextNumber(string $type, ?Contact $contact): string;
|
||||
|
||||
public function increaseNextNumber(string $type, ?Contact $contact): void;
|
||||
}
|
12
app/Interfaces/Utility/TransactionNumber.php
Normal file
12
app/Interfaces/Utility/TransactionNumber.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Interfaces\Utility;
|
||||
|
||||
use App\Models\Common\Contact;
|
||||
|
||||
interface TransactionNumber
|
||||
{
|
||||
public function getNextNumber(string $type, string $suffix, ?Contact $contact): string;
|
||||
|
||||
public function increaseNextNumber(string $type, string $suffix, ?Contact $contact): void;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user