Merge branch 'master' into title-subheading
This commit is contained in:
@@ -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 = [];
|
||||
@@ -105,7 +105,7 @@ abstract class Model extends Eloquent implements Ownable
|
||||
/**
|
||||
* Modules that use the sort parameter in CRUD operations cause an error,
|
||||
* so this sort parameter set back to old value after the query is executed.
|
||||
*
|
||||
*
|
||||
* for Custom Fields module
|
||||
*/
|
||||
$request_sort = $request->get('sort');
|
||||
@@ -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,21 +972,28 @@ 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);
|
||||
}
|
||||
|
||||
protected function getTextDocumentTitle($type, $textDocumentTitle)
|
||||
{
|
||||
{
|
||||
if (! empty($textDocumentTitle)) {
|
||||
return $textDocumentTitle;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -5,12 +5,15 @@ namespace App\Jobs\Auth;
|
||||
use App\Abstracts\Job;
|
||||
use App\Models\Auth\UserInvitation;
|
||||
use App\Notifications\Auth\Invitation as Notification;
|
||||
use App\Traits\Sources;
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
|
||||
class CreateInvitation extends Job
|
||||
{
|
||||
use Sources;
|
||||
|
||||
protected $invitation;
|
||||
|
||||
protected $user;
|
||||
@@ -23,9 +26,17 @@ class CreateInvitation extends Job
|
||||
public function handle(): UserInvitation
|
||||
{
|
||||
\DB::transaction(function () {
|
||||
$invitations = UserInvitation::where('user_id', $this->user->id)->get();
|
||||
|
||||
foreach ($invitations as $invitation) {
|
||||
$invitation->delete();
|
||||
}
|
||||
|
||||
$this->invitation = UserInvitation::create([
|
||||
'user_id' => $this->user->id,
|
||||
'token' => (string) Str::uuid(),
|
||||
'created_by' => user_id(),
|
||||
'created_from' => $this->getSourceName(request()),
|
||||
]);
|
||||
|
||||
$notification = new Notification($this->invitation);
|
||||
|
||||
@@ -12,6 +12,10 @@ class UpdateRole extends Job implements ShouldUpdate
|
||||
{
|
||||
public function handle(): Role
|
||||
{
|
||||
if (in_array($this->model->name, config('roles.defaults', ['admin', 'manager', 'accountant', 'employee']))) {
|
||||
$this->request->name = $this->model->name;
|
||||
}
|
||||
|
||||
event(new RoleUpdating($this->model, $this->request));
|
||||
|
||||
\DB::transaction(function () {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user