added source feature

This commit is contained in:
Denis Duliçi 2021-09-07 10:33:34 +03:00
parent 0a4e066451
commit c59c71b0f9
80 changed files with 475 additions and 63 deletions

View File

@ -58,6 +58,8 @@ abstract class Module extends Command
'module_id' => $this->model->id, 'module_id' => $this->model->id,
'version' => $this->module->get('version'), 'version' => $this->module->get('version'),
'description' => trans('modules.' . $action, ['module' => $this->alias]), 'description' => trans('modules.' . $action, ['module' => $this->alias]),
'created_from' => source_name(),
'created_by' => user_id(),
]); ]);
} }

View File

@ -36,6 +36,7 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow
{ {
$row['company_id'] = company_id(); $row['company_id'] = company_id();
$row['created_by'] = $this->user->id; $row['created_by'] = $this->user->id;
$row['created_from'] = 'import';
// Make enabled field integer // Make enabled field integer
if (isset($row['enabled'])) { if (isset($row['enabled'])) {

View File

@ -4,18 +4,20 @@ namespace App\Abstracts;
use App\Abstracts\Http\FormRequest; use App\Abstracts\Http\FormRequest;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Interfaces\Job\ShouldDelete; use App\Interfaces\Job\ShouldDelete;
use App\Interfaces\Job\ShouldUpdate; use App\Interfaces\Job\ShouldUpdate;
use App\Traits\Jobs; use App\Traits\Jobs;
use App\Traits\Relationships; use App\Traits\Relationships;
use App\Traits\Sources;
use App\Traits\Uploads; use App\Traits\Uploads;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request; use Illuminate\Http\Request;
abstract class Job abstract class Job
{ {
use Jobs, Relationships, Uploads; use Jobs, Relationships, Sources, Uploads;
protected $model; protected $model;
@ -49,6 +51,10 @@ abstract class Job
if ($this instanceof HasOwner) { if ($this instanceof HasOwner) {
$this->setOwner(); $this->setOwner();
} }
if ($this instanceof HasSource) {
$this->setSource();
}
} }
public function bootUpdate(...$arguments): void public function bootUpdate(...$arguments): void
@ -106,4 +112,17 @@ abstract class Job
$this->request->merge(['created_by' => user_id()]); $this->request->merge(['created_by' => user_id()]);
} }
public function setSource(): void
{
if (! $this->request instanceof Request) {
return;
}
if ($this->request->has('created_from')) {
return;
}
$this->request->merge(['created_from' => $this->getSourceName($this->request)]);
}
} }

View File

@ -4,6 +4,7 @@ namespace App\Abstracts;
use App\Traits\DateTime; use App\Traits\DateTime;
use App\Traits\Owners; use App\Traits\Owners;
use App\Traits\Sources;
use App\Traits\Tenants; use App\Traits\Tenants;
use GeneaLabs\LaravelModelCaching\Traits\Cachable; use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Database\Eloquent\Model as Eloquent; use Illuminate\Database\Eloquent\Model as Eloquent;
@ -14,7 +15,7 @@ use Lorisleiva\LaravelSearchString\Concerns\SearchString;
abstract class Model extends Eloquent implements Ownable abstract class Model extends Eloquent implements Ownable
{ {
use Cachable, DateTime, Owners, SearchString, SoftDeletes, Sortable, Tenants; use Cachable, DateTime, Owners, SearchString, SoftDeletes, Sortable, Sources, Tenants;
protected $tenantable = true; protected $tenantable = true;
@ -211,6 +212,11 @@ abstract class Model extends Eloquent implements Ownable
return $query->whereIn($this->table . '.contact_id', (array) $contacts); return $query->whereIn($this->table . '.contact_id', (array) $contacts);
} }
public function scopeSource($query, $source)
{
return $query->where($this->table . '.created_from', $source);
}
public function scopeIsOwner($query) public function scopeIsOwner($query)
{ {
return $query->where($this->table . '.created_by', user_id()); return $query->where($this->table . '.created_by', user_id());

View File

@ -0,0 +1,8 @@
<?php
namespace App\Interfaces\Job;
interface HasSource
{
//
}

View File

@ -3,10 +3,12 @@
namespace App\Jobs\Auth; namespace App\Jobs\Auth;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Auth\Role; use App\Models\Auth\Role;
class CreateRole extends Job implements ShouldCreate class CreateRole extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Role public function handle(): Role
{ {

View File

@ -3,13 +3,15 @@
namespace App\Jobs\Auth; namespace App\Jobs\Auth;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Events\Auth\UserCreated; use App\Events\Auth\UserCreated;
use App\Events\Auth\UserCreating; use App\Events\Auth\UserCreating;
use App\Models\Auth\User; use App\Models\Auth\User;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
class CreateUser extends Job implements ShouldCreate class CreateUser extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): User public function handle(): User
{ {

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Banking;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Banking\Account; use App\Models\Banking\Account;
class CreateAccount extends Job implements HasOwner, ShouldCreate class CreateAccount extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Account public function handle(): Account
{ {

View File

@ -4,11 +4,12 @@ namespace App\Jobs\Banking;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Banking\Reconciliation; use App\Models\Banking\Reconciliation;
use App\Models\Banking\Transaction; use App\Models\Banking\Transaction;
class CreateReconciliation extends Job implements HasOwner, ShouldCreate class CreateReconciliation extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Reconciliation public function handle(): Reconciliation
{ {

View File

@ -6,10 +6,11 @@ use App\Abstracts\Job;
use App\Events\Banking\TransactionCreated; use App\Events\Banking\TransactionCreated;
use App\Events\Banking\TransactionCreating; use App\Events\Banking\TransactionCreating;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Banking\Transaction; use App\Models\Banking\Transaction;
class CreateTransaction extends Job implements HasOwner, ShouldCreate class CreateTransaction extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Transaction public function handle(): Transaction
{ {

View File

@ -4,6 +4,7 @@ namespace App\Jobs\Banking;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Jobs\Banking\CreateTransaction; use App\Jobs\Banking\CreateTransaction;
use App\Models\Banking\Account; use App\Models\Banking\Account;
@ -11,7 +12,7 @@ use App\Models\Banking\Transfer;
use App\Models\Setting\Category; use App\Models\Setting\Category;
use App\Traits\Currencies; use App\Traits\Currencies;
class CreateTransfer extends Job implements HasOwner, ShouldCreate class CreateTransfer extends Job implements HasOwner, HasSource, ShouldCreate
{ {
use Currencies; use Currencies;

View File

@ -6,11 +6,12 @@ use App\Abstracts\Job;
use App\Events\Common\CompanyCreated; use App\Events\Common\CompanyCreated;
use App\Events\Common\CompanyCreating; use App\Events\Common\CompanyCreating;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Common\Company; use App\Models\Common\Company;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
class CreateCompany extends Job implements HasOwner, ShouldCreate class CreateCompany extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Company public function handle(): Company
{ {

View File

@ -4,13 +4,14 @@ namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Auth\User; use App\Models\Auth\User;
use App\Models\Auth\Role; use App\Models\Auth\Role;
use App\Models\Common\Contact; use App\Models\Common\Contact;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class CreateContact extends Job implements HasOwner, ShouldCreate class CreateContact extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Contact public function handle(): Contact
{ {

View File

@ -4,6 +4,7 @@ namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Jobs\Common\CreateWidget; use App\Jobs\Common\CreateWidget;
use App\Models\Auth\User; use App\Models\Auth\User;
@ -13,7 +14,7 @@ use App\Models\Common\Widget;
use App\Utilities\Widgets; use App\Utilities\Widgets;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
class CreateDashboard extends Job implements HasOwner, ShouldCreate class CreateDashboard extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Dashboard public function handle(): Dashboard
{ {

View File

@ -0,0 +1,21 @@
<?php
namespace App\Jobs\Common;
use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate;
use App\Models\Common\EmailTemplate;
class CreateEmailTemplate extends Job implements HasOwner, HasSource, ShouldCreate
{
public function handle(): EmailTemplate
{
\DB::transaction(function () {
$this->model = EmailTemplate::create($this->request->all());
});
return $this->model;
}
}

View File

@ -4,11 +4,12 @@ namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Jobs\Common\CreateItemTaxes; use App\Jobs\Common\CreateItemTaxes;
use App\Models\Common\Item; use App\Models\Common\Item;
class CreateItem extends Job implements HasOwner, ShouldCreate class CreateItem extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Item public function handle(): Item
{ {

View File

@ -3,11 +3,13 @@
namespace App\Jobs\Common; namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Common\Item; use App\Models\Common\Item;
use App\Models\Common\ItemTax; use App\Models\Common\ItemTax;
class CreateItemTaxes extends Job implements ShouldCreate class CreateItemTaxes extends Job implements HasOwner, HasSource, ShouldCreate
{ {
protected $item; protected $item;
@ -44,6 +46,8 @@ class CreateItemTaxes extends Job implements ShouldCreate
'company_id' => $this->item->company_id, 'company_id' => $this->item->company_id,
'item_id' => $this->item->id, 'item_id' => $this->item->id,
'tax_id' => $tax_id, 'tax_id' => $tax_id,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
} }
}); });

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Common\Report; use App\Models\Common\Report;
class CreateReport extends Job implements HasOwner, ShouldCreate class CreateReport extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Report public function handle(): Report
{ {

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Common;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Common\Widget; use App\Models\Common\Widget;
class CreateWidget extends Job implements HasOwner, ShouldCreate class CreateWidget extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Widget public function handle(): Widget
{ {

View File

@ -6,12 +6,13 @@ use App\Abstracts\Job;
use App\Events\Document\DocumentCreated; use App\Events\Document\DocumentCreated;
use App\Events\Document\DocumentCreating; use App\Events\Document\DocumentCreating;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Jobs\Document\CreateDocumentItemsAndTotals; use App\Jobs\Document\CreateDocumentItemsAndTotals;
use App\Models\Document\Document; use App\Models\Document\Document;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class CreateDocument extends Job implements HasOwner, ShouldCreate class CreateDocument extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Document public function handle(): Document
{ {

View File

@ -3,11 +3,13 @@
namespace App\Jobs\Document; namespace App\Jobs\Document;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Document\Document; use App\Models\Document\Document;
use App\Models\Document\DocumentHistory; use App\Models\Document\DocumentHistory;
class CreateDocumentHistory extends Job implements ShouldCreate class CreateDocumentHistory extends Job implements HasOwner, HasSource, ShouldCreate
{ {
protected $document; protected $document;
@ -35,6 +37,8 @@ class CreateDocumentHistory extends Job implements ShouldCreate
'status' => $this->document->status, 'status' => $this->document->status,
'notify' => $this->notify, 'notify' => $this->notify,
'description' => $description, 'description' => $description,
'created_from' => source_name(),
'created_by' => user_id(),
]); ]);
return $document_history; return $document_history;

View File

@ -3,6 +3,8 @@
namespace App\Jobs\Document; namespace App\Jobs\Document;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Document\Document; use App\Models\Document\Document;
use App\Models\Document\DocumentItem; use App\Models\Document\DocumentItem;
@ -10,7 +12,7 @@ use App\Models\Document\DocumentItemTax;
use App\Models\Setting\Tax; use App\Models\Setting\Tax;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class CreateDocumentItem extends Job implements ShouldCreate class CreateDocumentItem extends Job implements HasOwner, HasSource, ShouldCreate
{ {
protected $document; protected $document;
@ -182,6 +184,8 @@ class CreateDocumentItem extends Job implements ShouldCreate
$this->request['discount_type'] = !empty($this->request['discount_type']) ? $this->request['discount_type'] : 'percentage'; $this->request['discount_type'] = !empty($this->request['discount_type']) ? $this->request['discount_type'] : 'percentage';
$this->request['discount_rate'] = !empty($this->request['discount']) ? $this->request['discount'] : 0; $this->request['discount_rate'] = !empty($this->request['discount']) ? $this->request['discount'] : 0;
$this->request['total'] = round($item_amount, $precision); $this->request['total'] = round($item_amount, $precision);
$this->request['created_from'] = source_name();
$this->request['created_by'] = user_id();
$document_item = DocumentItem::create($this->request); $document_item = DocumentItem::create($this->request);
@ -197,6 +201,8 @@ class CreateDocumentItem extends Job implements ShouldCreate
foreach ($item_taxes as $item_tax) { foreach ($item_taxes as $item_tax) {
$item_tax['document_item_id'] = $document_item->id; $item_tax['document_item_id'] = $document_item->id;
$item_tax['amount'] = round(abs($item_tax['amount']), $precision); $item_tax['amount'] = round(abs($item_tax['amount']), $precision);
$item_tax['created_from'] = $this->request['created_from'];
$item_tax['created_by'] = $this->request['created_by'];
DocumentItemTax::create($item_tax); DocumentItemTax::create($item_tax);
} }

View File

@ -3,6 +3,8 @@
namespace App\Jobs\Document; namespace App\Jobs\Document;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Jobs\Common\CreateItem; use App\Jobs\Common\CreateItem;
use App\Models\Document\Document; use App\Models\Document\Document;
@ -10,7 +12,7 @@ use App\Models\Document\DocumentTotal;
use App\Traits\Currencies; use App\Traits\Currencies;
use App\Traits\DateTime; use App\Traits\DateTime;
class CreateDocumentItemsAndTotals extends Job implements ShouldCreate class CreateDocumentItemsAndTotals extends Job implements HasOwner, HasSource, ShouldCreate
{ {
use Currencies, DateTime; use Currencies, DateTime;
@ -40,6 +42,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'name' => 'invoices.sub_total', 'name' => 'invoices.sub_total',
'amount' => round($sub_total, $precision), 'amount' => round($sub_total, $precision),
'sort_order' => $sort_order, 'sort_order' => $sort_order,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
$this->request['amount'] += $sub_total; $this->request['amount'] += $sub_total;
@ -56,6 +60,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'name' => 'invoices.item_discount', 'name' => 'invoices.item_discount',
'amount' => round($discount_amount_total, $precision), 'amount' => round($discount_amount_total, $precision),
'sort_order' => $sort_order, 'sort_order' => $sort_order,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
$sort_order++; $sort_order++;
@ -76,6 +82,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'name' => 'invoices.discount', 'name' => 'invoices.discount',
'amount' => round($discount_total, $precision), 'amount' => round($discount_total, $precision),
'sort_order' => $sort_order, 'sort_order' => $sort_order,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
$this->request['amount'] -= $discount_total; $this->request['amount'] -= $discount_total;
@ -94,6 +102,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'name' => $tax['name'], 'name' => $tax['name'],
'amount' => round(abs($tax['amount']), $precision), 'amount' => round(abs($tax['amount']), $precision),
'sort_order' => $sort_order, 'sort_order' => $sort_order,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
$this->request['amount'] += $tax['amount']; $this->request['amount'] += $tax['amount'];
@ -109,6 +119,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
$total['type'] = $this->document->type; $total['type'] = $this->document->type;
$total['document_id'] = $this->document->id; $total['document_id'] = $this->document->id;
$total['sort_order'] = $sort_order; $total['sort_order'] = $sort_order;
$total['created_from'] = $this->request['created_from'];
$total['created_by'] = $this->request['created_by'];
if (empty($total['code'])) { if (empty($total['code'])) {
$total['code'] = 'extra'; $total['code'] = 'extra';
@ -140,6 +152,8 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'name' => 'invoices.total', 'name' => 'invoices.total',
'amount' => $this->request['amount'], 'amount' => $this->request['amount'],
'sort_order' => $sort_order, 'sort_order' => $sort_order,
'created_from' => $this->request['created_from'],
'created_by' => $this->request['created_by'],
]); ]);
} }
@ -167,7 +181,7 @@ class CreateDocumentItemsAndTotals extends Job implements ShouldCreate
'description' => $item['description'], 'description' => $item['description'],
'sale_price' => $item['price'], 'sale_price' => $item['price'],
'purchase_price' => $item['price'], 'purchase_price' => $item['price'],
'enabled' => '1' 'enabled' => '1',
]; ];
if (!empty($item['tax_ids'])) { if (!empty($item['tax_ids'])) {

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Setting;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Setting\Category; use App\Models\Setting\Category;
class CreateCategory extends Job implements HasOwner, ShouldCreate class CreateCategory extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Category public function handle(): Category
{ {

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Setting;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Setting\Currency; use App\Models\Setting\Currency;
class CreateCurrency extends Job implements HasOwner, ShouldCreate class CreateCurrency extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Currency public function handle(): Currency
{ {

View File

@ -4,10 +4,11 @@ namespace App\Jobs\Setting;
use App\Abstracts\Job; use App\Abstracts\Job;
use App\Interfaces\Job\HasOwner; use App\Interfaces\Job\HasOwner;
use App\Interfaces\Job\HasSource;
use App\Interfaces\Job\ShouldCreate; use App\Interfaces\Job\ShouldCreate;
use App\Models\Setting\Tax; use App\Models\Setting\Tax;
class CreateTax extends Job implements HasOwner, ShouldCreate class CreateTax extends Job implements HasOwner, HasSource, ShouldCreate
{ {
public function handle(): Tax public function handle(): Tax
{ {

View File

@ -35,6 +35,8 @@ class CreateModuleUpdatedHistory
'module_id' => $model->id, 'module_id' => $model->id,
'version' => $event->new, 'version' => $event->new,
'description' => trans('modules.updated_2', ['module' => $module->getAlias()]), 'description' => trans('modules.updated_2', ['module' => $module->getAlias()]),
'created_from' => source_name(),
'created_by' => user_id(),
]); ]);
} }
} }

View File

@ -20,7 +20,7 @@ class Role extends LaratrustRole
* *
* @var array * @var array
*/ */
protected $fillable = ['name', 'display_name', 'description']; protected $fillable = ['name', 'display_name', 'description', 'created_from', 'created_by'];
/** /**
* Scope to get all rows filtered, sorted and paginated. * Scope to get all rows filtered, sorted and paginated.

View File

@ -5,6 +5,8 @@ namespace App\Models\Auth;
use App\Traits\Tenants; use App\Traits\Tenants;
use App\Notifications\Auth\Reset; use App\Notifications\Auth\Reset;
use App\Traits\Media; use App\Traits\Media;
use App\Traits\Owners;
use App\Traits\Sources;
use App\Traits\Users; use App\Traits\Users;
use App\Utilities\Date; use App\Utilities\Date;
use Illuminate\Contracts\Translation\HasLocalePreference; use Illuminate\Contracts\Translation\HasLocalePreference;
@ -18,7 +20,7 @@ use Lorisleiva\LaravelSearchString\Concerns\SearchString;
class User extends Authenticatable implements HasLocalePreference class User extends Authenticatable implements HasLocalePreference
{ {
use HasFactory, LaratrustUserTrait, Notifiable, SearchString, SoftDeletes, Sortable, Media, Tenants, Users; use HasFactory, LaratrustUserTrait, Media, Notifiable, Owners, SearchString, SoftDeletes, Sortable, Sources, Tenants, Users;
protected $table = 'users'; protected $table = 'users';
@ -27,7 +29,7 @@ class User extends Authenticatable implements HasLocalePreference
* *
* @var array * @var array
*/ */
protected $fillable = ['name', 'email', 'password', 'locale', 'enabled', 'landing_page']; protected $fillable = ['name', 'email', 'password', 'locale', 'enabled', 'landing_page', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.
@ -258,6 +260,30 @@ class User extends Authenticatable implements HasLocalePreference
return (bool) $this->can('read-admin-panel'); return (bool) $this->can('read-admin-panel');
} }
public function scopeSource($query, $source)
{
return $query->where($this->table . '.created_from', $source);
}
public function scopeIsOwner($query)
{
return $query->where($this->table . '.created_by', user_id());
}
public function scopeIsNotOwner($query)
{
return $query->where($this->table . '.created_by', '<>', user_id());
}
public function ownerKey($owner)
{
if ($this->isNotOwnable()) {
return 0;
}
return $this->created_by;
}
/** /**
* Get the user's preferred locale. * Get the user's preferred locale.
* *

View File

@ -25,7 +25,7 @@ class Account extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'name', 'number', 'currency_code', 'opening_balance', 'bank_name', 'bank_phone', 'bank_address', 'enabled', 'created_by']; protected $fillable = ['company_id', 'name', 'number', 'currency_code', 'opening_balance', 'bank_name', 'bank_phone', 'bank_address', 'enabled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -18,7 +18,7 @@ class Reconciliation extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'account_id', 'started_at', 'ended_at', 'closing_balance', 'reconciled', 'created_by']; protected $fillable = ['company_id', 'account_id', 'started_at', 'ended_at', 'closing_balance', 'reconciled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -43,6 +43,7 @@ class Transaction extends Model
'payment_method', 'payment_method',
'reference', 'reference',
'parent_id', 'parent_id',
'created_from',
'created_by', 'created_by',
]; ];

View File

@ -36,7 +36,7 @@ class Transfer extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'expense_transaction_id', 'income_transaction_id', 'created_by']; protected $fillable = ['company_id', 'expense_transaction_id', 'income_transaction_id', 'created_from', 'created_by'];
/** /**
* Sortable columns. * Sortable columns.

View File

@ -10,6 +10,7 @@ use App\Models\Document\Document;
use App\Traits\Contacts; use App\Traits\Contacts;
use App\Traits\Media; use App\Traits\Media;
use App\Traits\Owners; use App\Traits\Owners;
use App\Traits\Sources;
use App\Traits\Tenants; use App\Traits\Tenants;
use App\Traits\Transactions; use App\Traits\Transactions;
use App\Utilities\Overrider; use App\Utilities\Overrider;
@ -21,7 +22,7 @@ use Lorisleiva\LaravelSearchString\Concerns\SearchString;
class Company extends Eloquent implements Ownable class Company extends Eloquent implements Ownable
{ {
use Contacts, Media, Owners, SearchString, SoftDeletes, Sortable, Tenants, Transactions; use Contacts, Media, Owners, SearchString, SoftDeletes, Sortable, Sources, Tenants, Transactions;
protected $table = 'companies'; protected $table = 'companies';
@ -34,7 +35,7 @@ class Company extends Eloquent implements Ownable
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
protected $fillable = ['domain', 'enabled', 'created_by']; protected $fillable = ['domain', 'enabled', 'created_from', 'created_by'];
protected $casts = [ protected $casts = [
'enabled' => 'boolean', 'enabled' => 'boolean',
@ -554,14 +555,19 @@ class Company extends Eloquent implements Ownable
return static::getCurrent() !== null; return static::getCurrent() !== null;
} }
public function scopeSource($query, $source)
{
return $query->where($this->table . '.created_from', $source);
}
public function scopeIsOwner($query) public function scopeIsOwner($query)
{ {
return $query->where('created_by', user_id()); return $query->where($this->table . '.created_by', user_id());
} }
public function scopeIsNotOwner($query) public function scopeIsNotOwner($query)
{ {
return $query->where('created_by', '<>', user_id()); return $query->where($this->table . '.created_by', '<>', user_id());
} }
public function ownerKey($owner) public function ownerKey($owner)

View File

@ -48,6 +48,7 @@ class Contact extends Model
'currency_code', 'currency_code',
'reference', 'reference',
'enabled', 'enabled',
'created_from',
'created_by', 'created_by',
]; ];

View File

@ -18,7 +18,7 @@ class Dashboard extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'name', 'enabled', 'created_by']; protected $fillable = ['company_id', 'name', 'enabled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -13,7 +13,7 @@ class EmailTemplate extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'alias', 'class', 'name', 'subject', 'body', 'params']; protected $fillable = ['company_id', 'alias', 'class', 'name', 'subject', 'body', 'params', 'created_from', 'created_by'];
/** /**
* Scope to only include contacts of a given type. * Scope to only include contacts of a given type.

View File

@ -27,7 +27,7 @@ class Item extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'name', 'description', 'sale_price', 'purchase_price', 'category_id', 'enabled', 'created_by']; protected $fillable = ['company_id', 'name', 'description', 'sale_price', 'purchase_price', 'category_id', 'enabled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -16,7 +16,7 @@ class ItemTax extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'item_id', 'tax_id']; protected $fillable = ['company_id', 'item_id', 'tax_id', 'created_from', 'created_by'];
public function item() public function item()
{ {

View File

@ -2,15 +2,17 @@
namespace App\Models\Common; namespace App\Models\Common;
use App\Traits\Owners;
use App\Traits\Sources;
use App\Traits\Tenants; use App\Traits\Tenants;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Plank\Mediable\Media as BaseMedia; use Plank\Mediable\Media as BaseMedia;
class Media extends BaseMedia class Media extends BaseMedia
{ {
use SoftDeletes, Tenants; use Owners, SoftDeletes, Sources, Tenants;
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
protected $fillable = ['company_id']; protected $fillable = ['company_id', 'created_from', 'created_by'];
} }

View File

@ -16,7 +16,7 @@ class Recurring extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'recurable_id', 'recurable_type', 'frequency', 'interval', 'started_at', 'count']; protected $fillable = ['company_id', 'recurable_id', 'recurable_type', 'frequency', 'interval', 'started_at', 'count', 'created_from', 'created_by'];
/** /**
* Get all of the owning recurable models. * Get all of the owning recurable models.

View File

@ -17,7 +17,7 @@ class Report extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'class', 'name', 'description', 'settings', 'created_by']; protected $fillable = ['company_id', 'class', 'name', 'description', 'settings', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -17,7 +17,7 @@ class Widget extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'dashboard_id', 'class', 'name', 'sort', 'settings', 'created_by']; protected $fillable = ['company_id', 'dashboard_id', 'class', 'name', 'sort', 'settings', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -51,6 +51,7 @@ class Document extends Model
'notes', 'notes',
'footer', 'footer',
'parent_id', 'parent_id',
'created_from',
'created_by', 'created_by',
]; ];

View File

@ -13,7 +13,7 @@ class DocumentHistory extends Model
protected $table = 'document_histories'; protected $table = 'document_histories';
protected $fillable = ['company_id', 'type', 'document_id', 'status', 'notify', 'description']; protected $fillable = ['company_id', 'type', 'document_id', 'status', 'notify', 'description', 'created_from', 'created_by'];
public function document() public function document()
{ {

View File

@ -30,6 +30,8 @@ class DocumentItem extends Model
'tax', 'tax',
'discount_rate', 'discount_rate',
'discount_type', 'discount_type',
'created_from',
'created_by',
]; ];
/** /**

View File

@ -13,7 +13,7 @@ class DocumentItemTax extends Model
protected $table = 'document_item_taxes'; protected $table = 'document_item_taxes';
protected $fillable = ['company_id', 'type', 'document_id', 'document_item_id', 'tax_id', 'name', 'amount']; protected $fillable = ['company_id', 'type', 'document_id', 'document_item_id', 'tax_id', 'name', 'amount', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -13,7 +13,7 @@ class Module extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'alias', 'enabled']; protected $fillable = ['company_id', 'alias', 'enabled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -13,5 +13,5 @@ class ModuleHistory extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'module_id', 'version', 'description']; protected $fillable = ['company_id', 'module_id', 'version', 'description', 'created_from', 'created_by'];
} }

View File

@ -18,7 +18,7 @@ class Category extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'name', 'type', 'color', 'enabled', 'created_by']; protected $fillable = ['company_id', 'name', 'type', 'color', 'enabled', 'created_from', 'created_by',];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

@ -30,6 +30,7 @@ class Currency extends Model
'symbol_first', 'symbol_first',
'decimal_mark', 'decimal_mark',
'thousands_separator', 'thousands_separator',
'created_from',
'created_by', 'created_by',
]; ];

View File

@ -24,7 +24,7 @@ class Tax extends Model
* *
* @var array * @var array
*/ */
protected $fillable = ['company_id', 'name', 'rate', 'type', 'enabled', 'created_by']; protected $fillable = ['company_id', 'name', 'rate', 'type', 'enabled', 'created_from', 'created_by'];
/** /**
* The attributes that should be cast. * The attributes that should be cast.

View File

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

View File

@ -18,6 +18,8 @@ trait Recurring
$frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency']; $frequency = ($request['recurring_frequency'] != 'custom') ? $request['recurring_frequency'] : $request['recurring_custom_frequency'];
$interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval']; $interval = (($request['recurring_frequency'] != 'custom') || ($request['recurring_interval'] < 1)) ? 1 : (int) $request['recurring_interval'];
$started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at']; $started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at'];
$source = !empty($request['created_from']) ? $request['created_from'] : source_name();
$owner = !empty($request['created_by']) ? $request['created_by'] : user_id();
$this->recurring()->create([ $this->recurring()->create([
'company_id' => $this->company_id, 'company_id' => $this->company_id,
@ -25,6 +27,8 @@ trait Recurring
'interval' => $interval, 'interval' => $interval,
'started_at' => $started_at, 'started_at' => $started_at,
'count' => (int) $request['recurring_count'], 'count' => (int) $request['recurring_count'],
'created_from' => $source,
'created_by' => $owner,
]); ]);
} }
@ -40,16 +44,27 @@ trait Recurring
$started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at']; $started_at = !empty($request['paid_at']) ? $request['paid_at'] : $request['issued_at'];
$recurring = $this->recurring(); $recurring = $this->recurring();
$model_exists = $recurring->count();
$function = $recurring->count() ? 'update' : 'create'; $data = [
$recurring->$function([
'company_id' => $this->company_id, 'company_id' => $this->company_id,
'frequency' => $frequency, 'frequency' => $frequency,
'interval' => $interval, 'interval' => $interval,
'started_at' => $started_at, 'started_at' => $started_at,
'count' => (int) $request['recurring_count'], 'count' => (int) $request['recurring_count'],
]); ];
if ($model_exists) {
$recurring->update($data);
} else {
$source = !empty($request['created_from']) ? $request['created_from'] : source_name();
$owner = !empty($request['created_by']) ? $request['created_by'] : user_id();
$recurring->create(array_merge($data, [
'created_from' => $source,
'created_by' => $owner,
]));
}
} }
public function getRecurringSchedule($set_until_date = true) public function getRecurringSchedule($set_until_date = true)

37
app/Traits/Sources.php Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace App\Traits;
trait Sources
{
public function isSourcable(): bool
{
$sourcable = $this->sourcable ?: true;
return ($sourcable === true) && in_array('created_from', $this->getFillable());
}
public function isNotSourcable(): bool
{
return ! $this->isSourcable();
}
public function getSourceName($request = null): string
{
if (app()->runningInConsole()) {
$source = 'console';
}
if (empty($source)) {
$request = $request ?: request();
$source = $request->isApi() ? 'api' : null;
}
if (empty($source)) {
$source = 'ui';
}
return $source;
}
}

View File

@ -22,6 +22,8 @@ trait Uploads
return MediaUploader::makePrivate() return MediaUploader::makePrivate()
->beforeSave(function(MediaModel $media) { ->beforeSave(function(MediaModel $media) {
$media->company_id = company_id(); $media->company_id = company_id();
$media->created_from = source_name();
$media->created_by = user_id();
}) })
->fromSource($file) ->fromSource($file)
->toDirectory($path) ->toDirectory($path)
@ -41,6 +43,8 @@ trait Uploads
return MediaUploader::makePrivate() return MediaUploader::makePrivate()
->beforeSave(function(MediaModel $media) { ->beforeSave(function(MediaModel $media) {
$media->company_id = company_id(); $media->company_id = company_id();
$media->created_from = source_name();
$media->created_by = user_id();
}) })
->importPath($disk, $path); ->importPath($disk, $path);
} }

View File

@ -2,6 +2,7 @@
use App\Models\Common\Company; use App\Models\Common\Company;
use App\Traits\DateTime; use App\Traits\DateTime;
use App\Traits\Sources;
use App\Utilities\Date; use App\Utilities\Date;
use App\Utilities\Widgets; use App\Utilities\Widgets;
@ -38,7 +39,7 @@ if (!function_exists('user_id')) {
if (!function_exists('company_date_format')) { if (!function_exists('company_date_format')) {
/** /**
* Format the given date based on company settings. * Get the date format of company.
* *
* @return string * @return string
*/ */
@ -127,13 +128,30 @@ if (!function_exists('should_queue')) {
} }
} }
if (!function_exists('source_name')) {
/**
* Get the current source.
*
* @return string
*/
function source_name()
{
$tmp = new class() {
use Sources;
};
return $tmp->getSourceName();
}
}
if (!function_exists('cache_prefix')) { if (!function_exists('cache_prefix')) {
/** /**
* Cache system added company_id prefix. * Cache system added company_id prefix.
* *
* @return string * @return string
*/ */
function cache_prefix() { function cache_prefix()
{
return company_id() . '_'; return company_id() . '_';
} }
} }

View File

@ -31,6 +31,7 @@ class Account extends Factory
'bank_phone' => $this->faker->phoneNumber, 'bank_phone' => $this->faker->phoneNumber,
'bank_address' => $this->faker->address, 'bank_address' => $this->faker->address,
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -29,6 +29,7 @@ class Category extends Factory
'type' => $this->faker->randomElement($types), 'type' => $this->faker->randomElement($types),
'color' => $this->faker->hexColor, 'color' => $this->faker->hexColor,
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -39,6 +39,7 @@ class Contact extends Factory
'currency_code' => setting('default.currency'), 'currency_code' => setting('default.currency'),
'reference' => $this->faker->text(5), 'reference' => $this->faker->text(5),
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -47,6 +47,7 @@ class Currency extends Factory
'decimal_mark' => $currency['decimal_mark'], 'decimal_mark' => $currency['decimal_mark'],
'thousands_separator' => $currency['thousands_separator'], 'thousands_separator' => $currency['thousands_separator'],
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -25,6 +25,7 @@ class Dashboard extends Factory
'company_id' => $this->company->id, 'company_id' => $this->company->id,
'name' => $this->faker->text(15), 'name' => $this->faker->text(15),
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -45,6 +45,7 @@ class Document extends AbstractFactory
'currency_rate' => '1', 'currency_rate' => '1',
'notes' => $this->faker->text(5), 'notes' => $this->faker->text(5),
'amount' => '0', 'amount' => '0',
'created_from' => 'factory',
]; ];
} }

View File

@ -29,6 +29,7 @@ class Item extends Factory
'sale_price' => $this->faker->randomFloat(2, 10, 20), 'sale_price' => $this->faker->randomFloat(2, 10, 20),
'category_id' => $this->company->categories()->item()->get()->random(1)->pluck('id')->first(), 'category_id' => $this->company->categories()->item()->get()->random(1)->pluck('id')->first(),
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -34,6 +34,7 @@ class Reconciliation extends Factory
'started_at' => $started_at, 'started_at' => $started_at,
'ended_at' => $ended_at, 'ended_at' => $ended_at,
'reconcile' => $this->faker->boolean ? 1 : 0, 'reconcile' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -28,6 +28,7 @@ class Role extends Factory
'name' => strtolower($name), 'name' => strtolower($name),
'display_name' => $name, 'display_name' => $name,
'description' => $name, 'description' => $name,
'created_from' => 'factory',
]; ];
} }

View File

@ -29,6 +29,7 @@ class Tax extends Factory
'rate' => $this->faker->randomFloat(2, 10, 20), 'rate' => $this->faker->randomFloat(2, 10, 20),
'type' => $this->faker->randomElement($types), 'type' => $this->faker->randomElement($types),
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -41,6 +41,7 @@ class Transaction extends Factory
'category_id' => $this->company->categories()->$category_type()->get()->random(1)->pluck('id')->first(), 'category_id' => $this->company->categories()->$category_type()->get()->random(1)->pluck('id')->first(),
'reference' => $this->faker->text(5), 'reference' => $this->faker->text(5),
'payment_method' => setting('default.payment_method'), 'payment_method' => setting('default.payment_method'),
'created_from' => 'factory',
]; ];
} }

View File

@ -43,6 +43,7 @@ class Transfer extends Factory
'category_id' => Category::transfer(), 'category_id' => Category::transfer(),
'description' => $this->faker->text(20), 'description' => $this->faker->text(20),
'reference' => $this->faker->text(20), 'reference' => $this->faker->text(20),
'created_from' => 'factory',
]; ];
$expense_transaction = Transaction::factory()->create(array_merge($request, [ $expense_transaction = Transaction::factory()->create(array_merge($request, [

View File

@ -34,6 +34,7 @@ class User extends Factory
'companies' => ['1'], 'companies' => ['1'],
'roles' => ['1'], 'roles' => ['1'],
'enabled' => $this->faker->boolean ? 1 : 0, 'enabled' => $this->faker->boolean ? 1 : 0,
'created_from' => 'factory',
]; ];
} }

View File

@ -42,6 +42,7 @@ class Widget extends Factory
'dashboard_id' => $dashboard->id, 'dashboard_id' => $dashboard->id,
'name' => $this->faker->text(15), 'name' => $this->faker->text(15),
'class' => $this->faker->randomElement($this->classes), 'class' => $this->faker->randomElement($this->classes),
'created_from' => 'factory',
]; ];
} }
} }

View File

@ -19,6 +19,127 @@ class CoreV2124 extends Migration
$table->string('zip_code')->nullable()->after('address'); $table->string('zip_code')->nullable()->after('address');
$table->string('city')->nullable()->after('address'); $table->string('city')->nullable()->after('address');
}); });
Schema::table('accounts', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('categories', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('companies', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('contacts', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('reference');
});
Schema::table('currencies', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('dashboards', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('documents', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('parent_id');
});
Schema::table('document_histories', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('description');
$table->string('created_from', 30)->nullable()->after('description');
});
Schema::table('document_items', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('total');
$table->string('created_from', 30)->nullable()->after('total');
});
Schema::table('document_item_taxes', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('amount');
$table->string('created_from', 30)->nullable()->after('amount');
});
Schema::table('document_totals', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('sort_order');
$table->string('created_from', 30)->nullable()->after('sort_order');
});
Schema::table('email_templates', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('params');
$table->string('created_from', 30)->nullable()->after('params');
});
Schema::table('items', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('item_taxes', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('tax_id');
$table->string('created_from', 30)->nullable()->after('tax_id');
});
Schema::table('media', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('original_media_id');
$table->string('created_from', 30)->nullable()->after('original_media_id');
});
Schema::table('mediables', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('order');
$table->string('created_from', 30)->nullable()->after('order');
});
Schema::table('modules', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('enabled');
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('module_histories', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('description');
$table->string('created_from', 30)->nullable()->after('description');
});
Schema::table('reconciliations', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('reconciled');
});
Schema::table('recurring', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('count');
$table->string('created_from', 30)->nullable()->after('count');
});
Schema::table('reports', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('settings');
});
Schema::table('roles', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('description');
$table->string('created_from', 30)->nullable()->after('description');
});
Schema::table('taxes', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('transactions', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('parent_id');
});
Schema::table('transfers', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('income_transaction_id');
});
Schema::table('users', function (Blueprint $table) {
$table->string('created_by', 30)->nullable()->after('enabled');
$table->string('created_from', 30)->nullable()->after('enabled');
});
Schema::table('widgets', function (Blueprint $table) {
$table->string('created_from', 30)->nullable()->after('settings');
});
} }
/** /**
@ -28,8 +149,6 @@ class CoreV2124 extends Migration
*/ */
public function down() public function down()
{ {
Schema::table('contacts', function (Blueprint $table) { //
$table->dropColumn(['country','state', 'zip_code', 'city',]);
});
} }
} }

View File

@ -36,6 +36,7 @@ class Accounts extends Seeder
'currency_code' => 'USD', 'currency_code' => 'USD',
'bank_name' => trans('demo.accounts.cash'), 'bank_name' => trans('demo.accounts.cash'),
'enabled' => '1', 'enabled' => '1',
'created_from' => 'seed',
])); ]));
setting()->set('default.account', $account->id); setting()->set('default.account', $account->id);

View File

@ -70,6 +70,8 @@ class Categories extends Seeder
$income_category_id = $expense_category_id = 0; $income_category_id = $expense_category_id = 0;
foreach ($rows as $row) { foreach ($rows as $row) {
$row['created_from'] = 'seed';
$category = $this->dispatch(new CreateCategory($row)); $category = $this->dispatch(new CreateCategory($row));
switch ($category->type) { switch ($category->type) {

View File

@ -78,6 +78,8 @@ class Currencies extends Seeder
]; ];
foreach ($rows as $row) { foreach ($rows as $row) {
$row['created_from'] = 'seed';
$this->dispatch(new CreateCurrency($row)); $this->dispatch(new CreateCurrency($row));
} }
} }

View File

@ -45,6 +45,7 @@ class Dashboards extends Seeder
'App\Widgets\LatestExpenses', 'App\Widgets\LatestExpenses',
], ],
'users' => $user_id, 'users' => $user_id,
'created_from' => 'seed',
])); ]));
} }
} }

View File

@ -3,11 +3,14 @@
namespace Database\Seeds; namespace Database\Seeds;
use App\Abstracts\Model; use App\Abstracts\Model;
use App\Models\Common\EmailTemplate; use App\Jobs\Common\CreateEmailTemplate;
use App\Traits\Jobs;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
class EmailTemplates extends Seeder class EmailTemplates extends Seeder
{ {
use Jobs;
/** /**
* Run the database seeds. * Run the database seeds.
* *
@ -80,14 +83,15 @@ class EmailTemplates extends Seeder
]; ];
foreach ($templates as $template) { foreach ($templates as $template) {
EmailTemplate::create([ $this->dispatch(new CreateEmailTemplate([
'company_id' => $company_id, 'company_id' => $company_id,
'alias' => $template['alias'], 'alias' => $template['alias'],
'class' => $template['class'], 'class' => $template['class'],
'name' => $template['name'], 'name' => $template['name'],
'subject' => trans('email_templates.' . $template['alias'] . '.subject'), 'subject' => trans('email_templates.' . $template['alias'] . '.subject'),
'body' => trans('email_templates.' . $template['alias'] . '.body'), 'body' => trans('email_templates.' . $template['alias'] . '.body'),
]); 'created_from' => 'seed',
]));
} }
} }
} }

View File

@ -68,6 +68,8 @@ class Reports extends Seeder
]; ];
foreach ($rows as $row) { foreach ($rows as $row) {
$row['created_from'] = 'seed';
$this->dispatch(new CreateReport($row)); $this->dispatch(new CreateReport($row));
} }
} }

View File

@ -43,6 +43,8 @@ class InstallCommand extends Command
'company_id' => $this->company_id, 'company_id' => $this->company_id,
'alias' => $this->alias, 'alias' => $this->alias,
'enabled' => '1', 'enabled' => '1',
'created_from' => source_name(),
'created_by' => user_id(),
]); ]);
$this->createHistory('installed'); $this->createHistory('installed');

View File

@ -0,0 +1,46 @@
<?php
namespace Tests\Feature\Common;
use Tests\Feature\FeatureTestCase;
use App\Jobs\Setting\CreateCategory;
class SourcesTest extends FeatureTestCase
{
public function testItShouldHaveAutoSource()
{
$request = $this->getRequest();
$category = $this->dispatch(new CreateCategory($request));
$this->assertDatabaseHas('categories', [
'id' => $category->id,
'created_from' => 'console',
]);
}
public function testItShouldHaveManualSource()
{
$request = $this->getRequest();
$request['created_from'] = 'manual';
$category = $this->dispatch(new CreateCategory($request));
$this->assertDatabaseHas('categories', [
'id' => $category->id,
'created_from' => 'manual',
]);
}
public function getRequest()
{
return [
'company_id' => $this->company->id,
'name' => $this->faker->text(15),
'type' => 'income',
'color' => $this->faker->hexColor,
'enabled' => $this->faker->boolean ? 1 : 0,
];
}
}