v2 first commit
This commit is contained in:
parent
5b23e9c2c4
commit
6d50fa8442
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
||||
; This file is for unifying the coding style for different editors and IDEs.
|
||||
; More information at https://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
@ -4,7 +4,6 @@ APP_LOCALE=en-GB
|
||||
APP_INSTALLED=false
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_SCHEDULE_TIME="09:00"
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
@ -18,7 +17,8 @@ DB_PREFIX=
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=database
|
||||
QUEUE_CONNECTION=sync
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
MAIL_DRIVER=mail
|
||||
MAIL_HOST=localhost
|
||||
@ -28,3 +28,5 @@ MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_NAME=null
|
||||
MAIL_FROM_ADDRESS=null
|
||||
|
||||
FIREWALL_ENABLED=false
|
||||
|
@ -4,7 +4,6 @@ APP_LOCALE=en-GB
|
||||
APP_INSTALLED=false
|
||||
APP_KEY=base64:xBC+BxlC7sXhYAtpTZv8TYAHqoPgsJaXL0S5Id6BbBc=
|
||||
APP_DEBUG=true
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_SCHEDULE_TIME="09:00"
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
@ -14,11 +13,14 @@ DB_PREFIX=
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=database
|
||||
QUEUE_CONNECTION=sync
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
MAIL_DRIVER=mail
|
||||
MAIL_DRIVER=log
|
||||
MAIL_HOST=localhost
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
FIREWALL_ENABLED=false
|
||||
|
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
patreon: akaunting
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,12 +4,14 @@
|
||||
/storage/*.key
|
||||
/vendor
|
||||
/.idea
|
||||
/.vscode
|
||||
/.vagrant
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
.env
|
||||
.env.example
|
||||
robots.txt
|
||||
_ide_helper.php
|
||||
.phpstorm.meta.php
|
||||
/storage/debugbar/*
|
||||
/storage/debugbar/*
|
||||
|
@ -1,9 +1,6 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
|
||||
|
23
Dockerfile
23
Dockerfile
@ -1,23 +0,0 @@
|
||||
FROM php:apache
|
||||
|
||||
RUN apt-get update && apt-get install -y zip libzip-dev libpng-dev \
|
||||
&& docker-php-ext-install pdo_mysql gd zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Composer installation.
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||
RUN composer global require hirak/prestissimo --prefer-dist --no-progress --no-suggest --classmap-authoritative \
|
||||
&& composer clear-cache
|
||||
ENV PATH="${PATH}:/root/.composer/vendor/bin"
|
||||
|
||||
COPY . /var/www/html/
|
||||
|
||||
# Authorize these folders to be edited
|
||||
RUN chmod -R 777 /var/www/html/storage
|
||||
RUN chmod -R 777 /var/www/html/bootstrap/cache
|
||||
|
||||
# Allow rewrite
|
||||
RUN a2enmod rewrite
|
74
README.md
74
README.md
@ -1,8 +1,8 @@
|
||||
# Akaunting™
|
||||
|
||||
  [](https://crowdin.com/project/akaunting)  [](#backers) [](#sponsors)
|
||||
  [](https://crowdin.com/project/akaunting) 
|
||||
|
||||
Akaunting is a free, open source and online accounting software designed for small businesses and freelancers. It is built with modern technologies such as Laravel, Bootstrap, jQuery, RESTful API etc. Thanks to its modular structure, Akaunting provides an awesome App Store for users and developers.
|
||||
Akaunting is a free, open source and online accounting software designed for small businesses and freelancers. It is built with modern technologies such as Laravel, VueJS, Bootstrap 4, RESTful API etc. Thanks to its modular structure, Akaunting provides an awesome App Store for users and developers.
|
||||
|
||||
* [Home](https://akaunting.com) - The house of Akaunting
|
||||
* [Blog](https://akaunting.com/blog) - Get the latest news
|
||||
@ -12,51 +12,25 @@ Akaunting is a free, open source and online accounting software designed for sma
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP 5.6.4 or higher
|
||||
* PHP 7.2 or higher
|
||||
* Database (eg: MySQL, PostgreSQL, SQLite)
|
||||
* Web Server (eg: Apache, Nginx, IIS)
|
||||
* [Other libraries](https://akaunting.com/docs/requirements)
|
||||
|
||||
## Framework
|
||||
|
||||
Akaunting uses [Laravel](http://laravel.com), the best existing PHP framework, as the foundation framework and [Modules](https://nwidart.com/laravel-modules) package for Apps.
|
||||
Akaunting uses [Laravel](http://laravel.com), the best existing PHP framework, as the foundation framework and [Module](https://github.com/akaunting/module) package for Apps.
|
||||
|
||||
## Installation
|
||||
|
||||
* Install [Composer](https://getcomposer.org/download)
|
||||
* Download the [repository](https://github.com/akaunting/akaunting/archive/master.zip) and unzip into your server
|
||||
* Open and point your command line to the directory you unzipped Akaunting
|
||||
* Run the following command: `composer install`
|
||||
* Finally, launch the [installer](https://akaunting.com/docs/installation)
|
||||
|
||||
## Docker
|
||||
|
||||
It is possible to containerise Akaunting using the [`docker-compose`](docker-compose.yml) file. Here are a few commands:
|
||||
|
||||
```
|
||||
# Build the app
|
||||
docker build -t akaunting .
|
||||
|
||||
# Run the app
|
||||
docker-compose up -d
|
||||
|
||||
# Make sure you the dependencies are installed
|
||||
docker-compose exec web composer install
|
||||
|
||||
# Stream logs
|
||||
docker-compose logs -f web
|
||||
|
||||
# Access the container
|
||||
docker-compose exec web /bin/sh
|
||||
|
||||
# Stop & Delete everything
|
||||
docker-compose down -v
|
||||
```
|
||||
* Install [Composer](https://getcomposer.org/download)
|
||||
* Download the [repository](https://github.com/akaunting/akaunting/archive/master.zip) and unzip into your server
|
||||
* Open and point your command line to the directory you unzipped Akaunting
|
||||
* Run the following command: `composer install`
|
||||
* Finally, launch the [installer](https://akaunting.com/docs/installation)
|
||||
|
||||
## Contributing
|
||||
|
||||
Fork the repository, make the code changes then submit a pull request.
|
||||
|
||||
Please, be very clear on your commit messages and pull requests, empty pull request messages may be rejected without reason.
|
||||
|
||||
When contributing code to Akaunting, you must follow the PSR coding standards. The golden rule is: Imitate the existing Akaunting code.
|
||||
@ -77,35 +51,19 @@ If you discover any security related issues, please email security@akaunting.com
|
||||
|
||||
## Credits
|
||||
|
||||
- [Denis Duliçi](https://github.com/denisdulici)
|
||||
- [Cüneyt Şentürk](https://github.com/cuneytsenturk)
|
||||
- [All Contributors](../../contributors)
|
||||
* [Denis Duliçi](https://github.com/denisdulici)
|
||||
* [Cüneyt Şentürk](https://github.com/cuneytsenturk)
|
||||
* [All Contributors](../../contributors)
|
||||
|
||||
## Contributors
|
||||
## Partners
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
[](../../contributors)
|
||||
Each of our partners can help you craft a beautiful, well-architected project. Feel free to get in [contact](https://akaunting.com/contact) with us to become a partner.
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/akaunting#backer)]
|
||||
|
||||
[](https://opencollective.com/akaunting#backers)
|
||||
* [Creative Tim](https://www.creative-tim.com) is our design partner since Akaunting 2.0 version. They create beautiful UI Kits, Templates, and Dashboards built on top of Bootstrap, Vue.js, React, Angular, Node.js, and Laravel.
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/akaunting#sponsor)]
|
||||
|
||||
[](https://opencollective.com/akaunting/sponsor/0/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/1/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/2/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/3/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/4/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/5/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/6/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/7/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/8/website)
|
||||
[](https://opencollective.com/akaunting/sponsor/9/website)
|
||||
Support Akaunting by becoming a sponsor on [Patreon](https://www.patreon.com/akaunting). Your logo will show up here with a link to your website.
|
||||
|
||||
## License
|
||||
|
||||
|
162
app/Abstracts/BulkAction.php
Normal file
162
app/Abstracts/BulkAction.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts;
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class BulkAction
|
||||
{
|
||||
|
||||
public $model = false;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-common-items'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-common-items'
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-common-items'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Duplicate the specified resource.
|
||||
*
|
||||
* @param $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$items = $this->model::find($selected);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the specified resource.
|
||||
*
|
||||
* @param $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function enable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$items = $this->model::find($selected);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->enabled = 1;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the specified resource.
|
||||
*
|
||||
* @param $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$items = $this->model::find($selected);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->enabled = 0;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$items = $this->model::find($selected);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->delete();
|
||||
}
|
||||
|
||||
Artisan::call('cache:clear');
|
||||
}
|
||||
|
||||
public function countRelationships($model, $relationships)
|
||||
{
|
||||
$counter = [];
|
||||
|
||||
foreach ($relationships as $relationship => $text) {
|
||||
if ($c = $model->$relationship()->count()) {
|
||||
$counter[] = $c . ' ' . strtolower(trans_choice('general.' . $text, ($c > 1) ? 2 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
return $counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mass delete relationships with events being fired.
|
||||
*
|
||||
* @param $model
|
||||
* @param $relationships
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteRelationships($model, $relationships)
|
||||
{
|
||||
foreach ((array) $relationships as $relationship) {
|
||||
if (empty($model->$relationship)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$items = $model->$relationship->all();
|
||||
|
||||
if ($items instanceof Collection) {
|
||||
$items = $items->all();
|
||||
}
|
||||
|
||||
foreach ((array) $items as $item) {
|
||||
$item->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Abstracts\Http;
|
||||
|
||||
use Dingo\Api\Exception\ResourceException;
|
||||
use Dingo\Api\Routing\Helpers;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiController extends Controller
|
||||
abstract class ApiController extends Controller
|
||||
{
|
||||
use Helpers;
|
||||
|
||||
/**
|
||||
* Create the response for when a request fails validation.
|
||||
*
|
122
app/Abstracts/Http/Controller.php
Normal file
122
app/Abstracts/Http/Controller.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts\Http;
|
||||
|
||||
use App\Traits\Jobs;
|
||||
use App\Traits\Relationships;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
abstract class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, Jobs, Relationships, ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Instantiate a new controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->setPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign permissions to methods.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setPermissions()
|
||||
{
|
||||
// No need to check for permission in console
|
||||
if (app()->runningInConsole()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$route = app(Route::class);
|
||||
|
||||
// Get the controller array
|
||||
$arr = array_reverse(explode('\\', explode('@', $route->getAction()['uses'])[0]));
|
||||
|
||||
$controller = '';
|
||||
|
||||
// Add folder
|
||||
if (strtolower($arr[1]) != 'controllers') {
|
||||
$controller .= Str::kebab($arr[1]) . '-';
|
||||
}
|
||||
|
||||
// Add module
|
||||
if (isset($arr[3]) && isset($arr[4]) && (strtolower($arr[4]) == 'modules')) {
|
||||
$controller .= Str::kebab($arr[3]) . '-';
|
||||
}
|
||||
|
||||
// Add file
|
||||
$controller .= Str::kebab($arr[0]);
|
||||
|
||||
// Skip ACL
|
||||
$skip = ['common-dashboard', 'portal-dashboard'];
|
||||
if (in_array($controller, $skip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add CRUD permission check
|
||||
$this->middleware('permission:create-' . $controller)->only(['create', 'store', 'duplicate', 'import']);
|
||||
$this->middleware('permission:read-' . $controller)->only(['index', 'show', 'edit', 'export']);
|
||||
$this->middleware('permission:update-' . $controller)->only(['update', 'enable', 'disable']);
|
||||
$this->middleware('permission:delete-' . $controller)->only('destroy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a pagination collection.
|
||||
*
|
||||
* @param array|Collection $items
|
||||
* @param int $perPage
|
||||
* @param int $page
|
||||
* @param array $options
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function paginate($items, $perPage = 15, $page = null, $options = [])
|
||||
{
|
||||
$perPage = $perPage ?: request('limit', setting('default.list_limit', '25'));
|
||||
|
||||
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
|
||||
|
||||
$items = $items instanceof Collection ? $items : Collection::make($items);
|
||||
|
||||
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a job to its appropriate handler and return a response array for ajax calls.
|
||||
*
|
||||
* @param mixed $job
|
||||
* @return mixed
|
||||
*/
|
||||
public function ajaxDispatch($job)
|
||||
{
|
||||
try {
|
||||
$data = $this->dispatch($job);
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'error' => false,
|
||||
'data' => $data,
|
||||
'message' => '',
|
||||
];
|
||||
} catch(\Exception $e) {
|
||||
$response = [
|
||||
'success' => false,
|
||||
'error' => true,
|
||||
'data' => null,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
42
app/Abstracts/Http/FormRequest.php
Normal file
42
app/Abstracts/Http/FormRequest.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts\Http;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
abstract class FormRequest extends BaseFormRequest
|
||||
{
|
||||
/**
|
||||
* Set the company id to the request.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
protected function getValidatorInstance()
|
||||
{
|
||||
// Get request data
|
||||
$data = $this->all();
|
||||
|
||||
// Add active company id
|
||||
$data['company_id'] = session('company_id');
|
||||
|
||||
// Reset the request data
|
||||
$this->getInputSource()->replace($data);
|
||||
|
||||
return parent::getValidatorInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return Arr::has(
|
||||
$this->route() ? $this->all() + $this->route()->parameters() : $this->all(),
|
||||
$offset
|
||||
);
|
||||
}
|
||||
}
|
202
app/Abstracts/Http/PaymentController.php
Normal file
202
app/Abstracts/Http/PaymentController.php
Normal file
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts\Http;
|
||||
|
||||
use App\Http\Requests\Portal\InvoicePayment as PaymentRequest;
|
||||
use App\Models\Income\Invoice;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
|
||||
abstract class PaymentController extends BaseController
|
||||
{
|
||||
public $alias = '';
|
||||
|
||||
public $type = ''; // hosted, redirect
|
||||
|
||||
public $setting = [];
|
||||
|
||||
public $logger = null;
|
||||
|
||||
public $user = null;
|
||||
|
||||
public $module = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(function ($request, $next) {
|
||||
$this->setting = setting($this->alias);
|
||||
$this->setting['code'] = $this->alias;
|
||||
$this->setting['language'] = app()->getLocale();
|
||||
|
||||
$this->logger = $this->getLogger();
|
||||
|
||||
$this->user = user();
|
||||
|
||||
$this->module = module($this->alias);
|
||||
|
||||
return $next($request);
|
||||
});
|
||||
}
|
||||
|
||||
public function show(Invoice $invoice, PaymentRequest $request)
|
||||
{
|
||||
return $this->getInvoiceShow($invoice, 'show');
|
||||
}
|
||||
|
||||
public function signed(Invoice $invoice, PaymentRequest $request)
|
||||
{
|
||||
return $this->getInvoiceShow($invoice, 'signed');
|
||||
}
|
||||
|
||||
public function cancel(Invoice $invoice, $force_redirect = false)
|
||||
{
|
||||
$message = trans('messages.warning.payment_cancel', ['method' => setting($this->alias . '.name')]);
|
||||
|
||||
$this->logger->info($this->module->getName() . ':: Invoice: ' . $invoice->id . ' - Cancel Message: ' . $message);
|
||||
|
||||
flash($message)->warning();
|
||||
|
||||
$invoice_url = $this->getInvoiceUrl($invoice);
|
||||
|
||||
if ($force_redirect || ($this->type == 'redirect')) {
|
||||
return redirect($invoice_url);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => $message,
|
||||
'redirect' => $invoice_url,
|
||||
'success' => false,
|
||||
'data' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function finish($invoice, $request, $force_redirect = false)
|
||||
{
|
||||
$this->dispatchPaidEvent($invoice, $request);
|
||||
|
||||
$this->forgetReference($invoice);
|
||||
|
||||
$message = trans('messages.success.added', ['type' => trans_choice('general.payments', 1)]);
|
||||
|
||||
$this->logger->info($this->module->getName() . ':: Invoice: ' . $invoice->id . ' - Success Message: ' . $message);
|
||||
|
||||
flash($message)->success();
|
||||
|
||||
$invoice_url = $this->getInvoiceUrl($invoice);
|
||||
|
||||
if ($force_redirect || ($this->type == 'redirect')) {
|
||||
return redirect($invoice_url);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => $message,
|
||||
'redirect' => $invoice_url,
|
||||
'success' => true,
|
||||
'data' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getInvoiceShow(Invoice $invoice, $view = 'show')
|
||||
{
|
||||
$this->setContactFirstLastName($invoice);
|
||||
|
||||
$confirm_url = $this->getConfirmUrl($invoice);
|
||||
|
||||
$html = view('partials.portal.payment_method.' . $this->type . '.' . $view, [
|
||||
'setting' => $this->setting,
|
||||
'invoice' => $invoice,
|
||||
'confirm_url' => $confirm_url,
|
||||
])->render();
|
||||
|
||||
return response()->json([
|
||||
'code' => $this->setting['code'],
|
||||
'name' => $this->setting['name'],
|
||||
'description' => trans($this->alias . '::general.description'),
|
||||
'redirect' => false,
|
||||
'html' => $html,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getInvoiceUrl($invoice)
|
||||
{
|
||||
return $this->user
|
||||
? route('portal.invoices.show', $invoice->id)
|
||||
: URL::signedRoute('signed.invoices.show', [$invoice->id, 'company_id' => $invoice->company_id]);
|
||||
}
|
||||
|
||||
public function getConfirmUrl($invoice)
|
||||
{
|
||||
return $this->getModuleUrl($invoice, 'confirm');
|
||||
}
|
||||
|
||||
public function getReturnUrl($invoice)
|
||||
{
|
||||
return $this->getModuleUrl($invoice, 'return');
|
||||
}
|
||||
|
||||
public function getCancelUrl($invoice)
|
||||
{
|
||||
return $this->getModuleUrl($invoice, 'cancel');
|
||||
}
|
||||
|
||||
public function getNotifyUrl($invoice)
|
||||
{
|
||||
return route('portal.invoices.' . $this->alias . '.notify', $invoice->id);
|
||||
}
|
||||
|
||||
public function getModuleUrl($invoice, $suffix)
|
||||
{
|
||||
return $this->user
|
||||
? route('portal.invoices.' . $this->alias . '.' . $suffix, $invoice->id)
|
||||
: URL::signedRoute('signed.invoices.' . $this->alias . '.' . $suffix, [$invoice->id, 'company_id' => $invoice->company_id]);
|
||||
}
|
||||
|
||||
public function getLogger()
|
||||
{
|
||||
$log = new Logger($this->alias);
|
||||
$log->pushHandler(new StreamHandler(storage_path('logs/' . $this->alias . '.log')), Logger::INFO);
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
public function dispatchPaidEvent($invoice, $request)
|
||||
{
|
||||
$request['company_id'] = $invoice->company_id;
|
||||
$request['amount'] = $invoice->amount;
|
||||
$request['payment_method'] = $this->alias;
|
||||
$request['reference'] = $this->getReference($invoice);
|
||||
|
||||
event(new \App\Events\Income\PaymentReceived($invoice, $request));
|
||||
}
|
||||
|
||||
public function setReference($invoice, $reference)
|
||||
{
|
||||
session([
|
||||
$this->alias . '_' . $invoice->id . '_reference' => $reference
|
||||
]);
|
||||
}
|
||||
|
||||
public function getReference($invoice)
|
||||
{
|
||||
return session($this->alias . '_' . $invoice->id . '_reference');
|
||||
}
|
||||
|
||||
public function forgetReference($invoice)
|
||||
{
|
||||
session()->forget($this->alias . '_' . $invoice->id . '_reference');
|
||||
}
|
||||
|
||||
public function setContactFirstLastName(&$invoice)
|
||||
{
|
||||
$contact = explode(" ", $invoice->contact_name);
|
||||
|
||||
$last_name = array_pop($contact);
|
||||
$first_name = implode(" ", $contact);
|
||||
|
||||
$invoice->first_name = $first_name;
|
||||
$invoice->last_name = $last_name;
|
||||
}
|
||||
}
|
28
app/Abstracts/Job.php
Normal file
28
app/Abstracts/Job.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts;
|
||||
|
||||
use App\Abstracts\Http\FormRequest;
|
||||
use App\Traits\Jobs;
|
||||
use App\Traits\Relationships;
|
||||
use App\Traits\Uploads;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
abstract class Job implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, Jobs, Queueable, Relationships, SerializesModels, Uploads;
|
||||
|
||||
public function getRequestInstance($request)
|
||||
{
|
||||
if (!is_array($request)) {
|
||||
return $request;
|
||||
}
|
||||
|
||||
$class = new class() extends FormRequest {};
|
||||
|
||||
return $class->merge($request);
|
||||
}
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
namespace App\Abstracts;
|
||||
|
||||
use App\Scopes\Company;
|
||||
use EloquentFilter\Filterable;
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Kyslik\ColumnSortable\Sortable;
|
||||
use Request;
|
||||
use Route;
|
||||
use Lorisleiva\LaravelSearchString\Concerns\SearchString;
|
||||
|
||||
class Model extends Eloquent
|
||||
abstract class Model extends Eloquent
|
||||
{
|
||||
use Filterable, SoftDeletes, Sortable;
|
||||
use SearchString, SoftDeletes, Sortable;
|
||||
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
@ -38,31 +36,6 @@ class Model extends Eloquent
|
||||
return $this->belongsTo('App\Models\Common\Company');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the filter provider globally.
|
||||
*
|
||||
* @return ModelFilter
|
||||
*/
|
||||
public function modelFilter()
|
||||
{
|
||||
// Check if is api or web
|
||||
if (Request::is('api/*')) {
|
||||
$arr = array_reverse(explode('\\', explode('@', app()['api.router']->currentRouteAction())[0]));
|
||||
$folder = $arr[1];
|
||||
$file = $arr[0];
|
||||
} else {
|
||||
list($folder, $file) = explode('/', Route::current()->uri());
|
||||
}
|
||||
|
||||
if (empty($folder) || empty($file)) {
|
||||
return $this->provideFilter();
|
||||
}
|
||||
|
||||
$class = '\App\Filters\\' . ucfirst($folder) . '\\' . ucfirst($file);
|
||||
|
||||
return $this->provideFilter($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope to only include company data.
|
||||
*
|
||||
@ -88,10 +61,10 @@ class Model extends Eloquent
|
||||
{
|
||||
$request = request();
|
||||
|
||||
$input = $request->input();
|
||||
$limit = $request->get('limit', setting('general.list_limit', '25'));
|
||||
$search = $request->get('search');
|
||||
$limit = $request->get('limit', setting('default.list_limit', '25'));
|
||||
|
||||
return $query->filter($input)->sortable($sort)->paginate($limit);
|
||||
return $query->usingSearchString($search)->sortable($sort)->paginate($limit);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,27 +104,18 @@ class Model extends Eloquent
|
||||
public function scopeAccount($query, $accounts)
|
||||
{
|
||||
if (empty($accounts)) {
|
||||
return;
|
||||
return $query;
|
||||
}
|
||||
|
||||
return $query->whereIn('account_id', (array) $accounts);
|
||||
}
|
||||
|
||||
public function scopeCustomer($query, $customers)
|
||||
public function scopeContact($query, $contacts)
|
||||
{
|
||||
if (empty($customers)) {
|
||||
return;
|
||||
if (empty($contacts)) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
return $query->whereIn('customer_id', (array) $customers);
|
||||
}
|
||||
|
||||
public function scopeVendor($query, $vendors)
|
||||
{
|
||||
if (empty($vendors)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $query->whereIn('vendor_id', (array) $vendors);
|
||||
return $query->whereIn('contact_id', (array) $contacts);
|
||||
}
|
||||
}
|
74
app/Abstracts/Notification.php
Normal file
74
app/Abstracts/Notification.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts;
|
||||
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification as BaseNotification;
|
||||
|
||||
abstract class Notification extends BaseNotification
|
||||
{
|
||||
/**
|
||||
* Create a notification instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->queue = 'high';
|
||||
$this->delay = config('queue.connections.database.delay');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array|string
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', 'database'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the mail representation of the notification.
|
||||
*
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function initMessage()
|
||||
{
|
||||
$message = (new MailMessage)
|
||||
->from(config('mail.from.address'), config('mail.from.name'))
|
||||
->subject($this->getSubject())
|
||||
->view('partials.email.body', ['body' => $this->getBody()]);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function getSubject()
|
||||
{
|
||||
$content = setting('email.' . $this->template . '_subject');
|
||||
|
||||
return $this->replaceTags($content);
|
||||
}
|
||||
|
||||
public function getBody()
|
||||
{
|
||||
$content = setting('email.' . $this->template . '_body');
|
||||
|
||||
return $this->replaceTags($content);
|
||||
}
|
||||
|
||||
public function replaceTags($content)
|
||||
{
|
||||
return preg_replace($this->getTagsPattern(), $this->getTagsReplacement(), $content);
|
||||
}
|
||||
|
||||
public function getTagsPattern()
|
||||
{
|
||||
$pattern = [];
|
||||
|
||||
foreach($this->getTags() as $tag) {
|
||||
$pattern[] = "/" . $tag . "/";
|
||||
}
|
||||
|
||||
return $pattern;
|
||||
}
|
||||
}
|
226
app/Abstracts/Reports/Listener.php
Normal file
226
app/Abstracts/Reports/Listener.php
Normal file
@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts\Reports;
|
||||
|
||||
use App\Events\Common\ReportFilterApplying;
|
||||
use App\Events\Common\ReportFilterShowing;
|
||||
use App\Events\Common\ReportGroupApplying;
|
||||
use App\Events\Common\ReportGroupShowing;
|
||||
use App\Models\Banking\Account;
|
||||
use App\Models\Common\Contact;
|
||||
use App\Models\Setting\Category;
|
||||
use App\Traits\Contacts;
|
||||
use Date;
|
||||
|
||||
abstract class Listener
|
||||
{
|
||||
use Contacts;
|
||||
|
||||
protected $class = '';
|
||||
|
||||
protected $events = [
|
||||
'App\Events\Common\ReportFilterShowing',
|
||||
'App\Events\Common\ReportFilterApplying',
|
||||
'App\Events\Common\ReportGroupShowing',
|
||||
'App\Events\Common\ReportGroupApplying',
|
||||
];
|
||||
|
||||
public function checkClass($event)
|
||||
{
|
||||
return (get_class($event->class) == $this->class);
|
||||
}
|
||||
|
||||
public function getYears()
|
||||
{
|
||||
$now = Date::now();
|
||||
|
||||
$years = [];
|
||||
|
||||
$y = $now->addYears(2);
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$years[$y->year] = $y->year;
|
||||
$y->subYear();
|
||||
}
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
public function getAccounts()
|
||||
{
|
||||
return Account::enabled()->orderBy('name')->pluck('name', 'id')->toArray();
|
||||
}
|
||||
|
||||
public function getItemCategories()
|
||||
{
|
||||
return $this->getCategories('item');
|
||||
}
|
||||
|
||||
public function getIncomeCategories()
|
||||
{
|
||||
return $this->getCategories('income');
|
||||
}
|
||||
|
||||
public function getExpenseCategories()
|
||||
{
|
||||
return $this->getCategories('expense');
|
||||
}
|
||||
|
||||
public function getIncomeExpenseCategories()
|
||||
{
|
||||
return $this->getCategories(['income', 'expense']);
|
||||
}
|
||||
|
||||
public function getCategories($types)
|
||||
{
|
||||
return Category::type($types)->enabled()->orderBy('name')->pluck('name', 'id')->toArray();
|
||||
}
|
||||
|
||||
public function getCustomers()
|
||||
{
|
||||
return $this->getContacts($this->getCustomerTypes());
|
||||
}
|
||||
|
||||
public function getVendors()
|
||||
{
|
||||
return $this->getContacts($this->getVendorTypes());
|
||||
}
|
||||
|
||||
public function getContacts($types)
|
||||
{
|
||||
return Contact::type($types)->enabled()->orderBy('name')->pluck('name', 'id')->toArray();
|
||||
}
|
||||
|
||||
public function applyDateFilter($event)
|
||||
{
|
||||
$event->model->monthsOfYear($event->args['date_field']);
|
||||
}
|
||||
|
||||
public function applySearchStringFilter($event)
|
||||
{
|
||||
$event->model->usingSearchString(request('search'));
|
||||
}
|
||||
|
||||
public function applyAccountGroup($event)
|
||||
{
|
||||
if (($event->model->getTable() != 'invoices') && ($event->model->getTable() != 'bills')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filter = request('accounts', []);
|
||||
|
||||
$event->model->account_id = 0;
|
||||
|
||||
foreach ($event->model->transactions as $transaction) {
|
||||
if (!empty($filter) && !in_array($transaction->account_id, $filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$event->model->account_id = $transaction->account_id;
|
||||
}
|
||||
}
|
||||
|
||||
public function applyCustomerGroup($event)
|
||||
{
|
||||
foreach ($this->getCustomerTypes() as $type) {
|
||||
$id_field = $type . '_id';
|
||||
|
||||
$event->model->$id_field = $event->model->contact_id;
|
||||
}
|
||||
}
|
||||
|
||||
public function applyVendorGroup($event)
|
||||
{
|
||||
foreach ($this->getVendorTypes() as $type) {
|
||||
$id_field = $type . '_id';
|
||||
|
||||
$event->model->$id_field = $event->model->contact_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle filter showing event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handleReportFilterShowing(ReportFilterShowing $event)
|
||||
{
|
||||
if (!$this->checkClass($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->class->filters['years'] = $this->getYears();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle filter applying event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handleReportFilterApplying(ReportFilterApplying $event)
|
||||
{
|
||||
if (!$this->checkClass($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply date
|
||||
$this->applyDateFilter($event);
|
||||
|
||||
// Apply search
|
||||
$this->applySearchStringFilter($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle group showing event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handleReportGroupShowing(ReportGroupShowing $event)
|
||||
{
|
||||
if (!$this->checkClass($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->class->groups['category'] = trans_choice('general.categories', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle group applying event.
|
||||
*
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public function handleReportGroupApplying(ReportGroupApplying $event)
|
||||
{
|
||||
if (!$this->checkClass($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->applyAccountGroup($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the listeners for the subscriber.
|
||||
*
|
||||
* @param \Illuminate\Events\Dispatcher $events
|
||||
*/
|
||||
public function subscribe($events)
|
||||
{
|
||||
$class = get_class($this);
|
||||
|
||||
foreach ($this->events as $event) {
|
||||
$method = 'handle' . (new \ReflectionClass($event))->getShortName();
|
||||
|
||||
if (!method_exists($class, $method)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$events->listen(
|
||||
$event,
|
||||
$class . '@' . $method
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
434
app/Abstracts/Reports/Report.php
Normal file
434
app/Abstracts/Reports/Report.php
Normal file
@ -0,0 +1,434 @@
|
||||
<?php
|
||||
|
||||
namespace App\Abstracts\Reports;
|
||||
|
||||
use App\Exports\Common\Reports as Export;
|
||||
use App\Models\Common\Report as Model;
|
||||
use App\Utilities\Chartjs;
|
||||
use App\Traits\DateTime;
|
||||
use Date;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
abstract class Report
|
||||
{
|
||||
use DateTime;
|
||||
|
||||
public $report;
|
||||
|
||||
public $year;
|
||||
|
||||
public $views = [];
|
||||
|
||||
public $tables = [];
|
||||
|
||||
public $dates = [];
|
||||
|
||||
public $rows = [];
|
||||
|
||||
public $totals = [];
|
||||
|
||||
public $groups = [];
|
||||
|
||||
public $filters = [];
|
||||
|
||||
public $category = 'income-expense';
|
||||
|
||||
public $icon = 'fa fa-chart-pie';
|
||||
|
||||
public $indents = [
|
||||
'table_header' => '0px',
|
||||
'table_rows' => '0px',
|
||||
];
|
||||
|
||||
public $chart = [
|
||||
'line' => [
|
||||
'width' => '0',
|
||||
'height' => '300',
|
||||
'options' => [
|
||||
'color' => '#6da252',
|
||||
],
|
||||
],
|
||||
'dates' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
public function __construct(Model $report = null, $get_totals = true)
|
||||
{
|
||||
$this->setGroups();
|
||||
|
||||
if (!$report) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->report = $report;
|
||||
|
||||
$this->setYear();
|
||||
$this->setViews();
|
||||
$this->setTables();
|
||||
$this->setDates();
|
||||
$this->setFilters();
|
||||
$this->setRows();
|
||||
|
||||
if ($get_totals) {
|
||||
$this->getTotals();
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function getTotals();
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return Str::title(str_replace('_', ' ', Str::snake((new \ReflectionClass($this))->getShortName())));
|
||||
}
|
||||
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function getTotal()
|
||||
{
|
||||
$sum = 0;
|
||||
|
||||
foreach ($this->totals as $total) {
|
||||
$sum += is_array($total) ? array_sum($total) : $total;
|
||||
}
|
||||
|
||||
$total = money($sum, setting('default.currency'), true);
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function getTableRowList()
|
||||
{
|
||||
$group_prl = Str::plural($this->report->group);
|
||||
|
||||
if ($group_filter = request($group_prl)) {
|
||||
$rows = collect($this->filters[$group_prl])->filter(function ($value, $key) use ($group_filter) {
|
||||
return in_array($key, $group_filter);
|
||||
});
|
||||
} else {
|
||||
$rows = $this->filters[$group_prl];
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function getChart()
|
||||
{
|
||||
$chart = new Chartjs();
|
||||
|
||||
$config = $this->chart[$this->report->chart];
|
||||
|
||||
$default_options = [
|
||||
'tooltips' => [
|
||||
'backgroundColor' => '#f5f5f5',
|
||||
'titleFontColor' => '#333',
|
||||
'bodyFontColor' => '#666',
|
||||
'bodySpacing' => 4,
|
||||
'YrPadding' => 12,
|
||||
'mode' => 'nearest',
|
||||
'intersect' => 0,
|
||||
'position' => 'nearest'
|
||||
],
|
||||
|
||||
'responsive' => true,
|
||||
|
||||
'scales' => [
|
||||
'yAxes' => [
|
||||
[
|
||||
'barPercentage' => '1.6',
|
||||
'gridLines' => [
|
||||
'drawBorder' => false,
|
||||
'color' => 'rgba(29,140,248,0.1)',
|
||||
'zeroLineColor' => 'transparent',
|
||||
'borderDash' => [2],
|
||||
'borderDashOffset' => [2],
|
||||
],
|
||||
'ticks' => [
|
||||
'padding' => 10,
|
||||
'fontColor' => '#9e9e9e'
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
'xAxes' => [
|
||||
[
|
||||
'barPercentage' => '1.6',
|
||||
'gridLines' => [
|
||||
'drawBorder' => false,
|
||||
'color' => 'rgba(29,140,248,0.0)',
|
||||
'zeroLineColor' => 'transparent'
|
||||
],
|
||||
'ticks' => [
|
||||
'suggestedMin' => 60,
|
||||
'suggestedMax' => 125,
|
||||
'padding' => 20,
|
||||
'fontColor' => '#9e9e9e'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$options = array_merge($default_options, (array) $config['options']);
|
||||
|
||||
$chart->type($this->report->chart)
|
||||
->width((int) $config['width'])
|
||||
->height((int) $config['height'])
|
||||
->options($options)
|
||||
->labels(!empty($config['dates']) ? array_values($config['dates']) : array_values($this->dates));
|
||||
|
||||
if (!empty($config['datasets'])) {
|
||||
foreach ($config['datasets'] as $dataset) {
|
||||
$chart->dataset($dataset['name'], 'line', array_values($dataset['totals']))
|
||||
->backgroundColor(isset($dataset['backgroundColor']) ? $dataset['backgroundColor'] : '#6da252')
|
||||
->color(isset($dataset['color']) ? $dataset['color'] : '#6da252')
|
||||
->options((array) $dataset['options'])
|
||||
->fill(false);
|
||||
}
|
||||
} else {
|
||||
foreach ($this->totals as $total) {
|
||||
$chart->dataset($this->report->name, 'line', array_values($total))
|
||||
->backgroundColor(isset($config['backgroundColor']) ? $config['backgroundColor'] : '#6da252')
|
||||
->color(isset($config['color']) ? $config['color'] : '#6da252')
|
||||
->options([
|
||||
'borderWidth' => 4,
|
||||
'pointStyle' => 'line',
|
||||
])
|
||||
->fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
return $chart;
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
return view($this->views['show'])->with('class', $this);
|
||||
}
|
||||
|
||||
public function print()
|
||||
{
|
||||
return view($this->views['print'])->with('class', $this);
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
return \Excel::download(new Export($this->views['content'], $this), $this->report->name . '.xlsx');
|
||||
}
|
||||
|
||||
public function setYear()
|
||||
{
|
||||
$this->year = request('year', Date::now()->year);
|
||||
}
|
||||
|
||||
public function setViews()
|
||||
{
|
||||
$this->views = [
|
||||
'chart' => 'partials.reports.chart',
|
||||
'content' => 'partials.reports.content',
|
||||
'content.header' => 'partials.reports.content.header',
|
||||
'content.footer' => 'partials.reports.content.footer',
|
||||
'show' => 'partials.reports.show',
|
||||
'header' => 'partials.reports.header',
|
||||
'filter' => 'partials.reports.filter',
|
||||
'print' => 'partials.reports.print',
|
||||
'table' => 'partials.reports.table',
|
||||
'table.footer' => 'partials.reports.table.footer',
|
||||
'table.header' => 'partials.reports.table.header',
|
||||
'table.rows' => 'partials.reports.table.rows',
|
||||
];
|
||||
}
|
||||
|
||||
public function setTables()
|
||||
{
|
||||
$this->tables = [
|
||||
'default' => 'default'
|
||||
];
|
||||
}
|
||||
|
||||
public function setDates()
|
||||
{
|
||||
$function = 'sub' . ucfirst(str_replace('ly', '', $this->report->period));
|
||||
|
||||
$start = $this->getFinancialStart()->copy()->$function();
|
||||
|
||||
for ($j = 1; $j <= 12; $j++) {
|
||||
switch ($this->report->period) {
|
||||
case 'yearly':
|
||||
$start->addYear();
|
||||
|
||||
$date = $this->getFormattedDate($start);
|
||||
|
||||
$this->dates[$j] = $date;
|
||||
|
||||
foreach ($this->tables as $table) {
|
||||
$this->totals[$table][$date] = 0;
|
||||
}
|
||||
|
||||
$j += 11;
|
||||
|
||||
break;
|
||||
case 'quarterly':
|
||||
$start->addQuarter();
|
||||
|
||||
$date = $this->getFormattedDate($start);
|
||||
|
||||
$this->dates[$j] = $date;
|
||||
|
||||
foreach ($this->tables as $table) {
|
||||
$this->totals[$table][$date] = 0;
|
||||
}
|
||||
|
||||
$j += 2;
|
||||
|
||||
break;
|
||||
default:
|
||||
$start->addMonth();
|
||||
|
||||
$date = $this->getFormattedDate($start);
|
||||
|
||||
$this->dates[$j] = $date;
|
||||
|
||||
foreach ($this->tables as $table) {
|
||||
$this->totals[$table][$date] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setFilters()
|
||||
{
|
||||
event(new \App\Events\Common\ReportFilterShowing($this));
|
||||
}
|
||||
|
||||
public function setGroups()
|
||||
{
|
||||
event(new \App\Events\Common\ReportGroupShowing($this));
|
||||
}
|
||||
|
||||
public function setRows()
|
||||
{
|
||||
$list = $this->getTableRowList();
|
||||
|
||||
foreach ($this->dates as $date) {
|
||||
foreach ($this->tables as $table) {
|
||||
foreach ($list as $id => $name) {
|
||||
$this->rows[$table][$id][$date] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setTotals($items, $date_field, $check_type = false, $table = 'default')
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
// Make groups extensible
|
||||
$item = $this->applyGroups($item);
|
||||
|
||||
$date = $this->getFormattedDate(Date::parse($item->$date_field));
|
||||
|
||||
$id_field = $this->report->group . '_id';
|
||||
|
||||
if (!isset($this->rows[$table][$item->$id_field]) ||
|
||||
!isset($this->rows[$table][$item->$id_field][$date]) ||
|
||||
!isset($this->totals[$table][$date]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$amount = $item->getAmountConvertedToDefault();
|
||||
|
||||
if (!$check_type) {
|
||||
$this->rows[$table][$item->$id_field][$date] += $amount;
|
||||
|
||||
$this->totals[$table][$date] += $amount;
|
||||
} else {
|
||||
$type = (($item->getTable() == 'invoices') || (($item->getTable() == 'transactions') && ($item->type == 'income'))) ? 'income' : 'expense';
|
||||
|
||||
if ($type == 'income') {
|
||||
$this->rows[$table][$item->$id_field][$date] += $amount;
|
||||
|
||||
$this->totals[$table][$date] += $amount;
|
||||
} else {
|
||||
$this->rows[$table][$item->$id_field][$date] -= $amount;
|
||||
|
||||
$this->totals[$table][$date] -= $amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function applyFilters($model, $args = [])
|
||||
{
|
||||
event(new \App\Events\Common\ReportFilterApplying($this, $model, $args));
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function applyGroups($model, $args = [])
|
||||
{
|
||||
event(new \App\Events\Common\ReportGroupApplying($this, $model, $args));
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getFormattedDate($date)
|
||||
{
|
||||
switch ($this->report->period) {
|
||||
case 'yearly':
|
||||
$i = $date->copy()->format($this->getYearlyDateFormat());
|
||||
break;
|
||||
case 'quarterly':
|
||||
$start = $date->copy()->startOfQuarter()->format($this->getQuarterlyDateFormat());
|
||||
$end = $date->copy()->endOfQuarter()->format($this->getQuarterlyDateFormat());
|
||||
|
||||
$i = $start . '-' . $end;
|
||||
break;
|
||||
default:
|
||||
$i = $date->copy()->format($this->getMonthlyDateFormat());
|
||||
break;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
public function getUrl($action = 'print')
|
||||
{
|
||||
$print_url = 'common/reports/' . $this->report->id . '/' . $action . '?year='. $this->year;
|
||||
|
||||
collect(request('accounts'))->each(function($item) use(&$print_url) {
|
||||
$print_url .= '&accounts[]=' . $item;
|
||||
});
|
||||
|
||||
collect(request('customers'))->each(function($item) use(&$print_url) {
|
||||
$print_url .= '&customers[]=' . $item;
|
||||
});
|
||||
|
||||
collect(request('categories'))->each(function($item) use(&$print_url) {
|
||||
$print_url .= '&categories[]=' . $item;
|
||||
});
|
||||
|
||||
return $print_url;
|
||||
}
|
||||
|
||||
public function getPermission()
|
||||
{
|
||||
$permission = 'read-reports-' . Str::kebab((new \ReflectionClass($this))->getShortName());
|
||||
|
||||
return $permission;
|
||||
}
|
||||
|
||||
public function canRead()
|
||||
{
|
||||
return user()->can($this->getPermission());
|
||||
}
|
||||
}
|
20
app/BulkActions/Auth/Permissions.php
Normal file
20
app/BulkActions/Auth/Permissions.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Auth;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Auth\Permission;
|
||||
|
||||
class Permissions extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Permission::class;
|
||||
|
||||
public $actions = [
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-auth-permissions'
|
||||
]
|
||||
];
|
||||
}
|
20
app/BulkActions/Auth/Roles.php
Normal file
20
app/BulkActions/Auth/Roles.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Auth;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Auth\Role;
|
||||
|
||||
class Roles extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Role::class;
|
||||
|
||||
public $actions = [
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-auth-roles'
|
||||
]
|
||||
];
|
||||
}
|
78
app/BulkActions/Auth/Users.php
Normal file
78
app/BulkActions/Auth/Users.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Auth;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Auth\User;
|
||||
use Artisan;
|
||||
|
||||
class Users extends BulkAction
|
||||
{
|
||||
|
||||
public $model = User::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-auth-users'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-auth-users'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-auth-users'
|
||||
]
|
||||
];
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$users = $this->model::find($selected);
|
||||
|
||||
foreach ($users as $user) {
|
||||
// Can't disable yourself
|
||||
if ($user->id == user()->id) {
|
||||
continue;
|
||||
//$this->response->errorMethodNotAllowed(trans('auth.error.self_delete'));
|
||||
}
|
||||
|
||||
$user->enabled = 0;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$users = $this->model::find($selected);
|
||||
|
||||
foreach ($users as $user) {
|
||||
// Can't delete yourself
|
||||
if ($user->id == user()->id) {
|
||||
continue;
|
||||
//$this->response->errorMethodNotAllowed(trans('auth.error.self_delete'));
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
}
|
||||
|
||||
// Can't delete yourself
|
||||
if ($user->id == app(Auth::class)->user()->id) {
|
||||
$this->response->errorMethodNotAllowed(trans('auth.error.self_delete'));
|
||||
}
|
||||
|
||||
Artisan::call('cache:clear');
|
||||
}
|
||||
}
|
98
app/BulkActions/Banking/Accounts.php
Normal file
98
app/BulkActions/Banking/Accounts.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Banking;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Banking\Account;
|
||||
|
||||
class Accounts extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Account::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-banking-accounts'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-banking-accounts'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-banking-accounts'
|
||||
]
|
||||
];
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$accounts = $this->model::find($selected);
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->id == setting('default.account')) {
|
||||
$relationships[] = strtolower(trans_choice('general.companies', 1));
|
||||
}
|
||||
|
||||
if (empty($relationships)) {
|
||||
$account->enabled = 0;
|
||||
$account->save();
|
||||
|
||||
$message = trans('messages.success.disabled', ['type' => $account->name]);
|
||||
|
||||
return $this->itemResponse($account->fresh(), new Transformer(), $message);
|
||||
} else {
|
||||
$message = trans('messages.warning.disabled', ['name' => $account->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$accounts = $this->model::find($selected);
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
if ($relationships = $this->getRelationships($account)) {
|
||||
if ($account->id == setting('default.account')) {
|
||||
$relationships[] = strtolower(trans_choice('general.companies', 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($relationships)) {
|
||||
$account->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $account->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $account->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRelationships($account)
|
||||
{
|
||||
$relationships = $this->countRelationships($account, [
|
||||
'payments' => 'payments',
|
||||
'revenues' => 'revenues',
|
||||
]);
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
92
app/BulkActions/Banking/Reconciliations.php
Normal file
92
app/BulkActions/Banking/Reconciliations.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Banking;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Banking\Reconciliation;
|
||||
use App\Models\Banking\Transaction;
|
||||
|
||||
class Reconciliations extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Reconciliation::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-banking-reconciliations'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-banking-reconciliations'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-banking-reconciliations'
|
||||
]
|
||||
];
|
||||
|
||||
public function enable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$reconciliations = $this->model::find($selected);
|
||||
|
||||
foreach ($reconciliations as $reconciliation) {
|
||||
$reconciliation->enabled = 1;
|
||||
$reconciliation->save();
|
||||
|
||||
Transaction::where('account_id', $reconciliation->account_id)
|
||||
->reconciled()
|
||||
->whereBetween('paid_at', [$reconciliation->started_at, $reconciliation->ended_at])->each(function ($item) {
|
||||
$item->reconciled = 1;
|
||||
$item->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$reconciliations = $this->model::find($selected);
|
||||
|
||||
foreach ($reconciliations as $reconciliation) {
|
||||
$reconciliation->enabled = 0;
|
||||
$reconciliation->save();
|
||||
|
||||
Transaction::where('account_id', $reconciliation->account_id)
|
||||
->reconciled()
|
||||
->whereBetween('paid_at', [$reconciliation->started_at, $reconciliation->ended_at])->each(function ($item) {
|
||||
$item->reconciled = 0;
|
||||
$item->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$reconciliations = $this->model::find($selected);
|
||||
|
||||
foreach ($reconciliations as $reconciliation) {
|
||||
$reconciliation->delete();
|
||||
|
||||
Transaction::where('account_id', $reconciliation->account_id)
|
||||
->reconciled()
|
||||
->whereBetween('paid_at', [$reconciliation->started_at, $reconciliation->ended_at])->each(function ($item) {
|
||||
$item->reconciled = 0;
|
||||
$item->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
38
app/BulkActions/Banking/Transfers.php
Normal file
38
app/BulkActions/Banking/Transfers.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Banking;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Banking\Transfer;
|
||||
|
||||
class Transfers extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Transfer::class;
|
||||
|
||||
public $actions = [
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_action.message.deletes',
|
||||
'permission' => 'delete-banking-transfers'
|
||||
]
|
||||
];
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$transfers = $this->model::find($selected);
|
||||
|
||||
foreach ($transfers as $transfer) {
|
||||
$this->deleteRelationships($transfer, ['expense_transaction', 'income_transaction']);
|
||||
|
||||
$transfer->delete();
|
||||
}
|
||||
}
|
||||
}
|
117
app/BulkActions/Common/Companies.php
Normal file
117
app/BulkActions/Common/Companies.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Common;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Common\Company;
|
||||
|
||||
class Companies extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Company::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-common-companies'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-common-companies'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-common-companies'
|
||||
]
|
||||
];
|
||||
|
||||
public function enable($request)
|
||||
{
|
||||
try {
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$companies = $this->model::find($selected);
|
||||
|
||||
foreach ($companies as $company) {
|
||||
// Check if user can access company
|
||||
$this->owner($company);
|
||||
|
||||
$company->enabled = 1;
|
||||
$company->save();
|
||||
}
|
||||
|
||||
$message = trans('messages.success.enabled', ['type' => $company->name]);
|
||||
|
||||
return $this->itemResponse($company->fresh(), new Transformer(), $message);
|
||||
} catch (\HttpException $e) {
|
||||
$this->response->errorUnauthorized(trans('companies.error.not_user_company'));
|
||||
}
|
||||
}
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
try {
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$companies = $this->model::find($selected);
|
||||
|
||||
foreach ($companies as $company) {
|
||||
// Check if user can access company
|
||||
$this->owner($company);
|
||||
|
||||
$company->enabled = 0;
|
||||
$company->save();
|
||||
}
|
||||
} catch (\HttpException $e) {
|
||||
$this->response->errorUnauthorized(trans('companies.error.not_user_company'));
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$companies = $this->model::find($selected);
|
||||
|
||||
foreach ($companies as $company) {
|
||||
// Can't delete active company
|
||||
if ($company->id == session('company_id')) {
|
||||
$content = trans('companies.error.delete_active');
|
||||
|
||||
return new Response($content, 422);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if user can access company
|
||||
$this->owner($company);
|
||||
|
||||
$company->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $company->name]);
|
||||
|
||||
return new Response($message);
|
||||
} catch (\HttpException $e) {
|
||||
$this->response->errorUnauthorized(trans('companies.error.not_user_company'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function owner(Company $company)
|
||||
{
|
||||
$companies = user()->companies()->pluck('id')->toArray();
|
||||
|
||||
if (in_array($company->id, $companies)) {
|
||||
return new Response('');
|
||||
}
|
||||
|
||||
$this->response->errorUnauthorized(trans('companies.error.not_user_company'));
|
||||
}
|
||||
}
|
91
app/BulkActions/Common/Items.php
Normal file
91
app/BulkActions/Common/Items.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Common;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Common\Items as Export;
|
||||
use App\Models\Common\Item;
|
||||
|
||||
class Items extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Item::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-common-items'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-common-items'
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-common-items',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-common-items'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$items = $this->model::find($selected);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$relationships = $this->countRelationships($item, [
|
||||
'invoice_items' => 'invoices',
|
||||
'bill_items' => 'bills',
|
||||
]);
|
||||
|
||||
if (empty($relationships)) {
|
||||
$item->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $item->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $item->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.items', 2) . '.xlsx');
|
||||
}
|
||||
}
|
102
app/BulkActions/Expenses/Bills.php
Normal file
102
app/BulkActions/Expenses/Bills.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Expenses;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Expenses\Bills as Export;
|
||||
use App\Models\Expense\Bill;
|
||||
use App\Models\Expense\BillHistory;
|
||||
|
||||
class Bills extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Bill::class;
|
||||
|
||||
public $actions = [
|
||||
'received' => [
|
||||
'name' => 'general.received',
|
||||
'message' => '',
|
||||
'permission' => 'update-expenses-bills'
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-expenses-bills',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-expenses-bills'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$bills = $this->model::find($selected);
|
||||
|
||||
foreach ($bills as $bill) {
|
||||
$clone = $bill->duplicate();
|
||||
|
||||
// Add bill history
|
||||
BillHistory::create([
|
||||
'company_id' => session('company_id'),
|
||||
'bill_id' => $clone->id,
|
||||
'status_code' => 'draft',
|
||||
'notify' => 0,
|
||||
'description' => trans('messages.success.added', ['type' => $clone->bill_number]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$bills = $this->model::find($selected);
|
||||
|
||||
foreach ($bills as $bill) {
|
||||
$this->deleteRelationships($bill, ['items', 'item_taxes', 'histories', 'payments', 'recurring', 'totals']);
|
||||
$bill->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.bills', 2) . '.xlsx');
|
||||
}
|
||||
|
||||
public function received($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$bills = $this->model::find($selected);
|
||||
|
||||
foreach ($bills as $bill) {
|
||||
$bill->bill_status_code = 'received';
|
||||
$bill->save();
|
||||
|
||||
// Add bill history
|
||||
BillHistory::create([
|
||||
'company_id' => $bill->company_id,
|
||||
'bill_id' => $bill->id,
|
||||
'status_code' => 'received',
|
||||
'notify' => 0,
|
||||
'description' => trans('bills.mark_recevied'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
77
app/BulkActions/Expenses/Payments.php
Normal file
77
app/BulkActions/Expenses/Payments.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Expenses;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Expenses\Payments as Export;
|
||||
use App\Models\Banking\Transaction;
|
||||
use App\Models\Setting\Category;
|
||||
|
||||
class Payments extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Transaction::class;
|
||||
|
||||
public $actions = [
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-expenses-payments',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-expenses-payments'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$transactions = $this->model::find($selected);
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
$clone = $transaction->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$transactions = $this->model::find($selected);
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
if ($transaction->category->id != Category::transfer()) {
|
||||
$type = $transaction->type;
|
||||
|
||||
$transaction->recurring()->delete();
|
||||
$transaction->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => trans_choice('general.' . \Str::plural($type), 1)]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$this->response->errorUnauthorized();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.payments', 2) . '.xlsx');
|
||||
}
|
||||
}
|
97
app/BulkActions/Expenses/Vendors.php
Normal file
97
app/BulkActions/Expenses/Vendors.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Expenses;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Expenses\Vendors as Export;
|
||||
use App\Models\Common\Contact;
|
||||
|
||||
class Vendors extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Contact::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-expenses-vendors'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-expenses-vendors'
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-expenses-vendors',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-expenses-vendors'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$contacts = $this->model::find($selected);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$clone = $contact->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$contacts = $this->model::find($selected);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
if (!$relationships = $this->getRelationships($contact)) {
|
||||
$contact->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $contact->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $contact->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.vendors', 2) . '.xlsx');
|
||||
}
|
||||
|
||||
protected function getRelationships($contact)
|
||||
{
|
||||
$rels = [
|
||||
'bills' => 'bills',
|
||||
'payments' => 'payments',
|
||||
];
|
||||
|
||||
$relationships = $this->countRelationships($contact, $rels);
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
97
app/BulkActions/Incomes/Customers.php
Normal file
97
app/BulkActions/Incomes/Customers.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Incomes;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Incomes\Customers as Export;
|
||||
use App\Models\Common\Contact;
|
||||
|
||||
class Customers extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Contact::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-incomes-customers'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-incomes-customers'
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-incomes-customers',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.export',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-incomes-customers'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$contacts = $this->model::find($selected);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$clone = $contact->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$contacts = $this->model::find($selected);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
if (!$relationships = $this->getRelationships($contact)) {
|
||||
$contact->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $contact->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $contact->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.customers', 2) . '.xlsx');
|
||||
}
|
||||
|
||||
protected function getRelationships($contact)
|
||||
{
|
||||
$rels = [
|
||||
'invoices' => 'invoices',
|
||||
'revenues' => 'revenues',
|
||||
];
|
||||
|
||||
$relationships = $this->countRelationships($contact, $rels);
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
105
app/BulkActions/Incomes/Invoices.php
Normal file
105
app/BulkActions/Incomes/Invoices.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Incomes;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Events\Income\InvoiceCreated;
|
||||
use App\Events\Income\InvoiceSent;
|
||||
use App\Events\Income\PaymentReceived;
|
||||
use App\Exports\Incomes\Invoices as Export;
|
||||
use App\Models\Income\Invoice;
|
||||
use Date;
|
||||
|
||||
class Invoices extends BulkAction
|
||||
{
|
||||
public $model = Invoice::class;
|
||||
|
||||
public $actions = [
|
||||
'paid' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-incomes-invoices'
|
||||
],
|
||||
'sent' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-incomes-invoices'
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-incomes-invoices',
|
||||
'multiple' => true
|
||||
],
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-incomes-invoices'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$invoices = $this->model::find($selected);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
$clone = $invoice->duplicate();
|
||||
|
||||
event(new InvoiceCreated($clone));
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$invoices = $this->model::find($selected);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
$this->deleteRelationships($invoice, ['items', 'item_taxes', 'histories', 'transactions', 'recurring', 'totals']);
|
||||
$invoice->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.invoices', 2) . '.xlsx');
|
||||
}
|
||||
|
||||
public function sent($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$invoices = $this->model::find($selected);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
event(new InvoiceSent($invoice));
|
||||
|
||||
$message = trans('invoices.messages.marked_sent');
|
||||
}
|
||||
}
|
||||
|
||||
public function paid($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$invoices = $this->model::find($selected);
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
event(new PaymentReceived($invoice, []));
|
||||
}
|
||||
}
|
||||
}
|
77
app/BulkActions/Incomes/Revenues.php
Normal file
77
app/BulkActions/Incomes/Revenues.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Incomes;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Exports\Incomes\Revenues as Export;
|
||||
use App\Models\Banking\Transaction;
|
||||
use App\Models\Setting\Category;
|
||||
|
||||
class Revenues extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Transaction::class;
|
||||
|
||||
public $actions = [
|
||||
'export' => [
|
||||
'name' => 'general.export',
|
||||
'message' => 'bulk_actions.message.exports',
|
||||
],
|
||||
'duplicate' => [
|
||||
'name' => 'general.duplicate',
|
||||
'message' => 'bulk_actions.message.duplicate',
|
||||
'permission' => 'create-incomes-revenues',
|
||||
'multiple' => true
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-incomes-revenues'
|
||||
]
|
||||
];
|
||||
|
||||
public function duplicate($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$transactions = $this->model::find($selected);
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
$clone = $transaction->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$transactions = $this->model::find($selected);
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
if ($transaction->category->id != Category::transfer()) {
|
||||
$type = $transaction->type;
|
||||
|
||||
$transaction->recurring()->delete();
|
||||
$transaction->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => trans_choice('general.' . \Str::plural($type), 1)]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$this->response->errorUnauthorized();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function export($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
return \Excel::download(new Export($selected), trans_choice('general.revenues', 2) . '.xlsx');
|
||||
}
|
||||
}
|
98
app/BulkActions/Settings/Categories.php
Normal file
98
app/BulkActions/Settings/Categories.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Settings;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Setting\Category;
|
||||
|
||||
class Categories extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Category::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-settings-categories'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-settings-categories'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-settings-categories'
|
||||
]
|
||||
];
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$categories = $this->model::find($selected);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
if ($relationships = $this->getRelationships($category)) {
|
||||
$category->enabled = 0;
|
||||
$category->save();
|
||||
|
||||
$message = trans('messages.success.disabled', ['type' => $category->name]);
|
||||
|
||||
return $this->itemResponse($category->fresh(), new Transformer(), $message);
|
||||
} else {
|
||||
$message = trans('messages.warning.disabled', ['name' => $category->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$categories = $this->model::find($selected);
|
||||
|
||||
foreach ($categories as $category) {
|
||||
// Can not delete the last category by type
|
||||
if (Category::where('type', $category->type)->count() == 1) {
|
||||
$message = trans('messages.error.last_category', ['type' => strtolower(trans_choice('general.' . $category->type . 's', 1))]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
|
||||
if (!$relationships = $this->getRelationships($category)) {
|
||||
$category->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $category->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $category->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRelationships($category)
|
||||
{
|
||||
$relationships = $this->countRelationships($category, [
|
||||
'items' => 'items',
|
||||
'invoices' => 'invoices',
|
||||
'revenues' => 'revenues',
|
||||
'bills' => 'bills',
|
||||
'payments' => 'payments',
|
||||
]);
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
96
app/BulkActions/Settings/Currencies.php
Normal file
96
app/BulkActions/Settings/Currencies.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Settings;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Setting\Currency;
|
||||
|
||||
class Currencies extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Currency::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-settings-currencies'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-settings-currencies'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-settings-currencies'
|
||||
]
|
||||
];
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$currencies = $this->model::find($selected);
|
||||
|
||||
foreach ($currencies as $currency) {
|
||||
if (!$relationships = $this->getRelationships($currency)) {
|
||||
$currency->enabled = 0;
|
||||
$currency->save();
|
||||
|
||||
$message = trans('messages.success.disabled', ['type' => $currency->name]);
|
||||
|
||||
return $this->itemResponse($currency->fresh(), new Transformer(), $message);
|
||||
} else {
|
||||
$message = trans('messages.warning.disabled', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$currencies = $this->model::find($selected);
|
||||
|
||||
foreach ($currencies as $currency) {
|
||||
if (!$relationships = $this->getRelationships($currency)) {
|
||||
$currency->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $currency->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $currency->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRelationships($currency)
|
||||
{
|
||||
$relationships = $this->countRelationships($currency, [
|
||||
'accounts' => 'accounts',
|
||||
'customers' => 'customers',
|
||||
'invoices' => 'invoices',
|
||||
'revenues' => 'revenues',
|
||||
'bills' => 'bills',
|
||||
'payments' => 'payments',
|
||||
]);
|
||||
|
||||
if ($currency->code == setting('default.currency')) {
|
||||
$relationships[] = strtolower(trans_choice('general.companies', 1));
|
||||
}
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
89
app/BulkActions/Settings/Taxes.php
Normal file
89
app/BulkActions/Settings/Taxes.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\BulkActions\Settings;
|
||||
|
||||
use App\Abstracts\BulkAction;
|
||||
use App\Models\Setting\Tax;
|
||||
|
||||
class Taxes extends BulkAction
|
||||
{
|
||||
|
||||
public $model = Tax::class;
|
||||
|
||||
public $actions = [
|
||||
'enable' => [
|
||||
'name' => 'general.enable',
|
||||
'message' => 'bulk_actions.message.enable',
|
||||
'permission' => 'update-settings-taxes'
|
||||
],
|
||||
'disable' => [
|
||||
'name' => 'general.disable',
|
||||
'message' => 'bulk_actions.message.disable',
|
||||
'permission' => 'update-settings-taxes'
|
||||
],
|
||||
'delete' => [
|
||||
'name' => 'general.delete',
|
||||
'message' => 'bulk_actions.message.deletes',
|
||||
'permission' => 'delete-settings-taxes'
|
||||
]
|
||||
];
|
||||
|
||||
public function disable($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$taxes = $this->model::find($selected);
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
if (!$relationships = $this->getRelationships($tax)) {
|
||||
$tax->enabled = 0;
|
||||
$tax->save();
|
||||
|
||||
$message = trans('messages.success.disabled', ['type' => $tax->name]);
|
||||
|
||||
return $this->itemResponse($tax->fresh(), new Transformer(), $message);
|
||||
} else {
|
||||
$message = trans('messages.warning.disabled', ['name' => $tax->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($request)
|
||||
{
|
||||
$this->destroy($request);
|
||||
}
|
||||
|
||||
public function destroy($request)
|
||||
{
|
||||
$selected = $request->get('selected', []);
|
||||
|
||||
$taxes = $this->model::find($selected);
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
if (!$relationships = $this->getRelationships($tax)) {
|
||||
$tax->delete();
|
||||
|
||||
$message = trans('messages.success.deleted', ['type' => $tax->name]);
|
||||
|
||||
return new Response($message);
|
||||
} else {
|
||||
$message = trans('messages.warning.deleted', ['name' => $tax->name, 'text' => implode(', ', $relationships)]);
|
||||
|
||||
$this->response->errorUnauthorized($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRelationships($tax)
|
||||
{
|
||||
$relationships = $this->countRelationships($tax, [
|
||||
'items' => 'items',
|
||||
'invoice_items' => 'invoices',
|
||||
'bill_items' => 'bills',
|
||||
]);
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
}
|
@ -41,9 +41,11 @@ class BillReminder extends Command
|
||||
public function handle()
|
||||
{
|
||||
// Get all companies
|
||||
$companies = Company::all();
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
foreach ($companies as $company) {
|
||||
$this->info('Sending bill reminders for ' . $company->name . ' company.');
|
||||
|
||||
// Set company id
|
||||
session(['company_id' => $company->id]);
|
||||
|
||||
@ -51,14 +53,14 @@ class BillReminder extends Command
|
||||
Overrider::load('settings');
|
||||
Overrider::load('currencies');
|
||||
|
||||
$company->setSettings();
|
||||
|
||||
// Don't send reminders if disabled
|
||||
if (!$company->send_bill_reminder) {
|
||||
if (!setting('schedule.send_bill_reminder')) {
|
||||
$this->info('Bill reminders disabled by ' . $company->name . '.');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$days = explode(',', $company->schedule_bill_days);
|
||||
$days = explode(',', setting('schedule.bill_days'));
|
||||
|
||||
foreach ($days as $day) {
|
||||
$day = (int) trim($day);
|
||||
@ -69,6 +71,7 @@ class BillReminder extends Command
|
||||
|
||||
// Unset company_id
|
||||
session()->forget('company_id');
|
||||
setting()->forgetAll();
|
||||
}
|
||||
|
||||
protected function remind($day, $company)
|
||||
@ -77,7 +80,7 @@ class BillReminder extends Command
|
||||
$date = Date::today()->addDays($day)->toDateString();
|
||||
|
||||
// Get upcoming bills
|
||||
$bills = Bill::with('vendor')->accrued()->notPaid()->due($date)->get();
|
||||
$bills = Bill::with('contact')->accrued()->notPaid()->due($date)->cursor();
|
||||
|
||||
foreach ($bills as $bill) {
|
||||
// Notify all users assigned to this company
|
||||
@ -86,7 +89,7 @@ class BillReminder extends Command
|
||||
continue;
|
||||
}
|
||||
|
||||
$user->notify(new Notification($bill));
|
||||
$user->notify(new Notification($bill, 'bill_remind_admin'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,10 +38,9 @@ class CompanySeed extends Command
|
||||
public function handle()
|
||||
{
|
||||
$class = $this->laravel->make('CompanySeeder');
|
||||
|
||||
|
||||
$seeder = $class->setContainer($this->laravel)->setCommand($this);
|
||||
|
||||
|
||||
$seeder->__invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -212,7 +212,8 @@ class Install extends Command
|
||||
}
|
||||
}
|
||||
|
||||
private function createDatabaseTables() {
|
||||
private function createDatabaseTables()
|
||||
{
|
||||
$this->dbHost = $this->option(self::OPT_DB_HOST);
|
||||
$this->dbPort = $this->option(self::OPT_DB_PORT);
|
||||
$this->dbName = $this->option(self::OPT_DB_NAME);
|
||||
|
@ -41,9 +41,11 @@ class InvoiceReminder extends Command
|
||||
public function handle()
|
||||
{
|
||||
// Get all companies
|
||||
$companies = Company::all();
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
foreach ($companies as $company) {
|
||||
$this->info('Sending invoice reminders for ' . $company->name . ' company.');
|
||||
|
||||
// Set company id
|
||||
session(['company_id' => $company->id]);
|
||||
|
||||
@ -51,14 +53,14 @@ class InvoiceReminder extends Command
|
||||
Overrider::load('settings');
|
||||
Overrider::load('currencies');
|
||||
|
||||
$company->setSettings();
|
||||
|
||||
// Don't send reminders if disabled
|
||||
if (!$company->send_invoice_reminder) {
|
||||
if (!setting('schedule.send_invoice_reminder')) {
|
||||
$this->info('Invoice reminders disabled by ' . $company->name . '.');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$days = explode(',', $company->schedule_invoice_days);
|
||||
$days = explode(',', setting('schedule.invoice_days'));
|
||||
|
||||
foreach ($days as $day) {
|
||||
$day = (int) trim($day);
|
||||
@ -69,6 +71,7 @@ class InvoiceReminder extends Command
|
||||
|
||||
// Unset company_id
|
||||
session()->forget('company_id');
|
||||
setting()->forgetAll();
|
||||
}
|
||||
|
||||
protected function remind($day, $company)
|
||||
@ -76,13 +79,13 @@ class InvoiceReminder extends Command
|
||||
// Get due date
|
||||
$date = Date::today()->subDays($day)->toDateString();
|
||||
|
||||
// Get upcoming bills
|
||||
$invoices = Invoice::with('customer')->accrued()->notPaid()->due($date)->get();
|
||||
// Get upcoming invoices
|
||||
$invoices = Invoice::with('contact')->accrued()->notPaid()->due($date)->cursor();
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
// Notify the customer
|
||||
if ($invoice->customer && !empty($invoice->customer_email)) {
|
||||
$invoice->customer->notify(new Notification($invoice));
|
||||
if ($invoice->contact && !empty($invoice->contact_email)) {
|
||||
$invoice->contact->notify(new Notification($invoice, 'invoice_remind_customer'));
|
||||
}
|
||||
|
||||
// Notify all users assigned to this company
|
||||
@ -91,7 +94,7 @@ class InvoiceReminder extends Command
|
||||
continue;
|
||||
}
|
||||
|
||||
$user->notify(new Notification($invoice));
|
||||
$user->notify(new Notification($invoice, 'invoice_remind_admin'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,16 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Events\Expense\BillCreated;
|
||||
use App\Events\Expense\BillRecurring;
|
||||
use App\Events\Income\InvoiceCreated;
|
||||
use App\Events\Income\InvoiceRecurring;
|
||||
use App\Models\Common\Company;
|
||||
use App\Models\Expense\BillHistory;
|
||||
use App\Models\Income\InvoiceHistory;
|
||||
use App\Notifications\Expense\Bill as BillNotification;
|
||||
use App\Notifications\Income\Invoice as InvoiceNotification;
|
||||
use App\Traits\Incomes;
|
||||
use App\Utilities\Overrider;
|
||||
use Carbon\Carbon;
|
||||
use Date;
|
||||
use Illuminate\Console\Command;
|
||||
use Recurr\Rule;
|
||||
use Recurr\Transformer\ArrayTransformer;
|
||||
use Recurr\Transformer\ArrayTransformerConfig;
|
||||
|
||||
class RecurringCheck extends Command
|
||||
{
|
||||
@ -32,7 +30,14 @@ class RecurringCheck extends Command
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check for recurring';
|
||||
|
||||
|
||||
/**
|
||||
* The current day.
|
||||
*
|
||||
* @var Carbon
|
||||
*/
|
||||
protected $today;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*/
|
||||
@ -48,12 +53,12 @@ class RecurringCheck extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->today = Date::today();
|
||||
|
||||
// Get all companies
|
||||
$companies = Company::all();
|
||||
$companies = Company::enabled()->cursor();
|
||||
|
||||
foreach ($companies as $company) {
|
||||
$this->info('Creating recurring records for ' . $company->name . ' company.');
|
||||
|
||||
// Set company id
|
||||
session(['company_id' => $company->id]);
|
||||
|
||||
@ -61,43 +66,11 @@ class RecurringCheck extends Command
|
||||
Overrider::load('settings');
|
||||
Overrider::load('currencies');
|
||||
|
||||
$company->setSettings();
|
||||
$this->today = Date::today();
|
||||
|
||||
foreach ($company->recurring as $recurring) {
|
||||
foreach ($recurring->schedule() as $recur) {
|
||||
$recur_date = Date::parse($recur->getStart()->format('Y-m-d'));
|
||||
|
||||
// Check if should recur today
|
||||
if ($this->today->ne($recur_date)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$model = $recurring->recurable;
|
||||
|
||||
if (!$model) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($recurring->recurable_type) {
|
||||
case 'App\Models\Expense\Bill':
|
||||
$this->recurBill($company, $model);
|
||||
break;
|
||||
case 'App\Models\Income\Invoice':
|
||||
$this->recurInvoice($company, $model);
|
||||
break;
|
||||
case 'App\Models\Expense\Payment':
|
||||
case 'App\Models\Income\Revenue':
|
||||
$model->cloneable_relations = [];
|
||||
|
||||
// Create new record
|
||||
$clone = $model->duplicate();
|
||||
|
||||
$clone->parent_id = $model->id;
|
||||
$clone->paid_at = $this->today->format('Y-m-d');
|
||||
$clone->save();
|
||||
|
||||
break;
|
||||
}
|
||||
foreach ($recurring->schedule() as $schedule) {
|
||||
$this->recur($recurring, $schedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,85 +79,90 @@ class RecurringCheck extends Command
|
||||
session()->forget('company_id');
|
||||
}
|
||||
|
||||
protected function recurInvoice($company, $model)
|
||||
protected function recur($recurring, $schedule)
|
||||
{
|
||||
$model->cloneable_relations = ['items', 'totals'];
|
||||
$schedule_date = Date::parse($schedule->getStart()->format('Y-m-d'));
|
||||
|
||||
// Create new record
|
||||
$clone = $model->duplicate();
|
||||
|
||||
// Set original invoice id
|
||||
$clone->parent_id = $model->id;
|
||||
|
||||
// Days between invoiced and due date
|
||||
$diff_days = Date::parse($clone->due_at)->diffInDays(Date::parse($clone->invoiced_at));
|
||||
|
||||
// Update dates
|
||||
$clone->invoiced_at = $this->today->format('Y-m-d');
|
||||
$clone->due_at = $this->today->addDays($diff_days)->format('Y-m-d');
|
||||
$clone->save();
|
||||
|
||||
// Add invoice history
|
||||
InvoiceHistory::create([
|
||||
'company_id' => session('company_id'),
|
||||
'invoice_id' => $clone->id,
|
||||
'status_code' => 'draft',
|
||||
'notify' => 0,
|
||||
'description' => trans('messages.success.added', ['type' => $clone->invoice_number]),
|
||||
]);
|
||||
|
||||
// Notify the customer
|
||||
if ($clone->customer && !empty($clone->customer_email)) {
|
||||
$clone->customer->notify(new InvoiceNotification($clone));
|
||||
// Check if should recur today
|
||||
if ($this->today->ne($schedule_date)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify all users assigned to this company
|
||||
foreach ($company->users as $user) {
|
||||
if (!$user->can('read-notifications')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$user->notify(new InvoiceNotification($clone));
|
||||
if (!$model = $recurring->recurable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update next invoice number
|
||||
$this->increaseNextInvoiceNumber();
|
||||
switch ($recurring->recurable_type) {
|
||||
case 'App\Models\Expense\Bill':
|
||||
if (!$clone = $this->getDocumentClone($model, 'billed_at')) {
|
||||
break;
|
||||
}
|
||||
|
||||
event(new BillCreated($clone));
|
||||
|
||||
event(new BillRecurring($clone));
|
||||
|
||||
break;
|
||||
case 'App\Models\Income\Invoice':
|
||||
if (!$clone = $this->getDocumentClone($model, 'invoiced_at')) {
|
||||
break;
|
||||
}
|
||||
|
||||
event(new InvoiceCreated($clone));
|
||||
|
||||
event(new InvoiceRecurring($clone));
|
||||
|
||||
break;
|
||||
case 'App\Models\Banking\Transaction':
|
||||
// Skip model created on the same day, but scheduler hasn't run yet
|
||||
if ($this->today->eq(Date::parse($model->paid_at->format('Y-m-d')))) {
|
||||
break;
|
||||
}
|
||||
|
||||
$model->cloneable_relations = [];
|
||||
|
||||
// Create new record
|
||||
$clone = $model->duplicate();
|
||||
|
||||
$clone->parent_id = $model->id;
|
||||
$clone->paid_at = $this->today->format('Y-m-d');
|
||||
$clone->save();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function recurBill($company, $model)
|
||||
/**
|
||||
* Clone the document and return it.
|
||||
*
|
||||
* @param $model
|
||||
* @param $date_field
|
||||
*
|
||||
* @return boolean|object
|
||||
*/
|
||||
protected function getDocumentClone($model, $date_field)
|
||||
{
|
||||
// Skip model created on the same day, but scheduler hasn't run yet
|
||||
if ($this->today->eq(Date::parse($model->$date_field->format('Y-m-d')))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$model->cloneable_relations = ['items', 'totals'];
|
||||
|
||||
// Create new record
|
||||
$clone = $model->duplicate();
|
||||
|
||||
// Set original bill id
|
||||
// Set original model id
|
||||
$clone->parent_id = $model->id;
|
||||
|
||||
// Days between invoiced and due date
|
||||
$diff_days = Date::parse($clone->due_at)->diffInDays(Date::parse($clone->invoiced_at));
|
||||
// Days between issued and due date
|
||||
$diff_days = Date::parse($clone->due_at)->diffInDays(Date::parse($clone->$date_field));
|
||||
|
||||
// Update dates
|
||||
$clone->billed_at = $this->today->format('Y-m-d');
|
||||
$clone->due_at = $this->today->addDays($diff_days)->format('Y-m-d');
|
||||
$clone->$date_field = $this->today->format('Y-m-d');
|
||||
$clone->due_at = $this->today->copy()->addDays($diff_days)->format('Y-m-d');
|
||||
$clone->save();
|
||||
|
||||
// Add bill history
|
||||
BillHistory::create([
|
||||
'company_id' => session('company_id'),
|
||||
'bill_id' => $clone->id,
|
||||
'status_code' => 'draft',
|
||||
'notify' => 0,
|
||||
'description' => trans('messages.success.added', ['type' => $clone->bill_number]),
|
||||
]);
|
||||
|
||||
// Notify all users assigned to this company
|
||||
foreach ($company->users as $user) {
|
||||
if (!$user->can('read-notifications')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$user->notify(new BillNotification($clone));
|
||||
}
|
||||
|
||||
return $clone;
|
||||
}
|
||||
}
|
||||
|
46
app/Console/Commands/UserSeed.php
Normal file
46
app/Console/Commands/UserSeed.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class UserSeed extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:seed {user} {company}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Seed for specific user';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$class = $this->laravel->make('UserSeeder');
|
||||
|
||||
$seeder = $class->setContainer($this->laravel)->setCommand($this);
|
||||
|
||||
$seeder->__invoke();
|
||||
}
|
||||
}
|
@ -12,17 +12,7 @@ class Kernel extends ConsoleKernel
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
Commands\BillReminder::class,
|
||||
Commands\CompanySeed::class,
|
||||
Commands\Install::class,
|
||||
Commands\InvoiceReminder::class,
|
||||
Commands\ModuleDelete::class,
|
||||
Commands\ModuleDisable::class,
|
||||
Commands\ModuleEnable::class,
|
||||
Commands\ModuleInstall::class,
|
||||
Commands\RecurringCheck::class,
|
||||
];
|
||||
protected $commands = [];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
@ -52,5 +42,7 @@ class Kernel extends ConsoleKernel
|
||||
protected function commands()
|
||||
{
|
||||
require base_path('routes/console.php');
|
||||
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
}
|
||||
}
|
||||
|
0
app/Console/Stubs/Modules/assets/js/app.stub
Normal file
0
app/Console/Stubs/Modules/assets/js/app.stub
Normal file
0
app/Console/Stubs/Modules/assets/sass/app.stub
Normal file
0
app/Console/Stubs/Modules/assets/sass/app.stub
Normal file
@ -37,7 +37,7 @@ class $CLASS$ extends Command
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@ -11,5 +11,15 @@
|
||||
"psr-4": {
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Providers\\Main"
|
||||
],
|
||||
"aliases": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
60
app/Console/Stubs/Modules/controller-api.stub
Normal file
60
app/Console/Stubs/Modules/controller-api.stub
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace $CLASS_NAMESPACE$;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class $CLASS$ extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ class $CLASS$ extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('$LOWER_NAME$::index');
|
||||
return view('$ALIAS$::index');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -23,50 +23,57 @@ class $CLASS$ extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('$LOWER_NAME$::create');
|
||||
return view('$ALIAS$::create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
public function show($id)
|
||||
{
|
||||
return view('$LOWER_NAME$::show');
|
||||
return view('$ALIAS$::show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function edit()
|
||||
public function edit($id)
|
||||
{
|
||||
return view('$LOWER_NAME$::edit');
|
||||
return view('$ALIAS$::edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy()
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
9
app/Console/Stubs/Modules/factory.stub
Normal file
9
app/Console/Stubs/Modules/factory.stub
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(Model::class, function (Faker $faker) {
|
||||
return [
|
||||
//
|
||||
];
|
||||
});
|
34
app/Console/Stubs/Modules/job-queued.stub
Normal file
34
app/Console/Stubs/Modules/job-queued.stub
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
class $CLASS$ implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -2,14 +2,12 @@
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
class $CLASS$ implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels, Queueable;
|
||||
use Dispatchable, Queueable;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
|
@ -1,19 +1,14 @@
|
||||
{
|
||||
"name": "$STUDLY_NAME$",
|
||||
"alias": "$LOWER_NAME$",
|
||||
"description": "",
|
||||
"alias": "$ALIAS$",
|
||||
"version": "1.0.0",
|
||||
"category": "payment-gateway",
|
||||
"keywords": [],
|
||||
"category": "accounting",
|
||||
"active": 1,
|
||||
"order": 0,
|
||||
"providers": [
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Providers\\$STUDLY_NAME$ServiceProvider"
|
||||
"$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Providers\\Main"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [
|
||||
"start.php"
|
||||
],
|
||||
"files": [],
|
||||
"requires": [],
|
||||
"settings": []
|
||||
}
|
||||
|
8
app/Console/Stubs/Modules/lang/general.stub
Normal file
8
app/Console/Stubs/Modules/lang/general.stub
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'name' => '$STUDLY_NAME$',
|
||||
'description' => 'This is my awesome module',
|
||||
|
||||
];
|
30
app/Console/Stubs/Modules/listener-duck.stub
Normal file
30
app/Console/Stubs/Modules/listener-duck.stub
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class $CLASS$
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
32
app/Console/Stubs/Modules/listener-queued-duck.stub
Normal file
32
app/Console/Stubs/Modules/listener-queued-duck.stub
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class $CLASS$ implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
33
app/Console/Stubs/Modules/listener-queued.stub
Normal file
33
app/Console/Stubs/Modules/listener-queued.stub
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use $EVENTNAME$;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class $CLASS$ implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param $SHORTEVENTNAME$ $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($SHORTEVENTNAME$ $event)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -21,10 +21,10 @@ class $CLASS$
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \$EVENTNAME$ $event
|
||||
* @param $SHORTEVENTNAME$ $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(\$EVENTNAME$ $event)
|
||||
public function handle($SHORTEVENTNAME$ $event)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class $CLASS$ extends Migration
|
||||
public function up()
|
||||
{
|
||||
Schema::create('$TABLE$', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->bigIncrements('id');
|
||||
$FIELDS$
|
||||
$table->timestamps();
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ class $CLASS$ extends Migration
|
||||
public function down()
|
||||
{
|
||||
Schema::create('$TABLE$', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->bigIncrements('id');
|
||||
$FIELDS$
|
||||
$table->timestamps();
|
||||
});
|
||||
|
17
app/Console/Stubs/Modules/package.stub
Normal file
17
app/Console/Stubs/Modules/package.stub
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run development",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch-poll": "npm run watch -- --watch-poll",
|
||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"prod": "npm run production",
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.1.4",
|
||||
"laravel-mix": "^4.0.7",
|
||||
"laravel-mix-merge-manifest": "^0.1.2"
|
||||
}
|
||||
}
|
20
app/Console/Stubs/Modules/policy.plain.stub
Normal file
20
app/Console/Stubs/Modules/policy.plain.stub
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class $CLASS$
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Create a new policy instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
@ -6,13 +6,6 @@ use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class $CLASS$ extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
|
19
app/Console/Stubs/Modules/resource-collection.stub
Normal file
19
app/Console/Stubs/Modules/resource-collection.stub
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class $CLASS$ extends ResourceCollection
|
||||
{
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
19
app/Console/Stubs/Modules/resource.stub
Normal file
19
app/Console/Stubs/Modules/resource.stub
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Http\Resources\Json\Resource;
|
||||
|
||||
class $CLASS$ extends Resource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace $MODULE_NAMESPACE$\$MODULE$\Providers;
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
|
||||
class $NAME$ extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The root namespace to assume when generating URLs to actions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rootUrlNamespace = '$MODULE_NAMESPACE$\$MODULE$\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @param Router $router
|
||||
* @return void
|
||||
*/
|
||||
public function before(Router $router)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map(Router $router)
|
||||
{
|
||||
// if (!app()->routesAreCached()) {
|
||||
// require __DIR__ . '/Http/routes.php';
|
||||
// }
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
Route::group(['middleware' => 'web', 'prefix' => '$LOWER_NAME$', 'namespace' => '$MODULE_NAMESPACE$\$STUDLY_NAME$\Http\Controllers'], function()
|
||||
{
|
||||
Route::get('/', '$STUDLY_NAME$Controller@index');
|
||||
});
|
10
app/Console/Stubs/Modules/routes/admin.stub
Normal file
10
app/Console/Stubs/Modules/routes/admin.stub
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
Route::group([
|
||||
'middleware' => 'admin',
|
||||
'namespace' => 'Modules\$STUDLY_NAME$\Http\Controllers'
|
||||
], function () {
|
||||
Route::prefix('$ALIAS$')->group(function() {
|
||||
// Route::get('/', 'Main@index');
|
||||
});
|
||||
});
|
10
app/Console/Stubs/Modules/routes/portal.stub
Normal file
10
app/Console/Stubs/Modules/routes/portal.stub
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
Route::group([
|
||||
'prefix' => 'portal',
|
||||
'middleware' => 'portal',
|
||||
'namespace' => 'Modules\$STUDLY_NAME$\Http\Controllers'
|
||||
], function () {
|
||||
// Route::get('invoices/{invoice}/$ALIAS$', 'Main@show')->name('portal.invoices.$ALIAS$.show');
|
||||
// Route::post('invoices/{invoice}/$ALIAS$/confirm', 'Main@confirm')->name('portal.invoices.$ALIAS$.confirm');
|
||||
});
|
40
app/Console/Stubs/Modules/rule.stub
Normal file
40
app/Console/Stubs/Modules/rule.stub
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class $CLASS$ implements Rule
|
||||
{
|
||||
/**
|
||||
* Create a new rule instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the validation rule passes.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation error message.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function message()
|
||||
{
|
||||
return 'The validation error message.';
|
||||
}
|
||||
}
|
@ -2,18 +2,10 @@
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Database\Eloquent\Factory;
|
||||
use Illuminate\Support\ServiceProvider as Provider;
|
||||
|
||||
class $CLASS$ extends ServiceProvider
|
||||
class $NAME$ extends Provider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
@ -21,10 +13,9 @@ class $CLASS$ extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerTranslations();
|
||||
$this->registerConfig();
|
||||
$this->registerViews();
|
||||
$this->registerFactories();
|
||||
$this->loadTranslations();
|
||||
$this->loadViews();
|
||||
$this->loadMigrations();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,68 +25,57 @@ class $CLASS$ extends ServiceProvider
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$this->loadRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register config.
|
||||
* Load views.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConfig()
|
||||
public function loadViews()
|
||||
{
|
||||
$this->publishes([
|
||||
__DIR__.'/../$PATH_CONFIG$/config.php' => config_path('$LOWER_NAME$.php'),
|
||||
], 'config');
|
||||
$this->mergeConfigFrom(
|
||||
__DIR__.'/../$PATH_CONFIG$/config.php', '$LOWER_NAME$'
|
||||
);
|
||||
$this->loadViewsFrom(__DIR__ . '/../Resources/views', '$ALIAS$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register views.
|
||||
* Load translations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerViews()
|
||||
public function loadTranslations()
|
||||
{
|
||||
$viewPath = resource_path('views/modules/$LOWER_NAME$');
|
||||
|
||||
$sourcePath = __DIR__.'/../$PATH_VIEWS$';
|
||||
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath
|
||||
]);
|
||||
|
||||
$this->loadViewsFrom(array_merge(array_map(function ($path) {
|
||||
return $path . '/modules/$LOWER_NAME$';
|
||||
}, \Config::get('view.paths')), [$sourcePath]), '$LOWER_NAME$');
|
||||
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', '$ALIAS$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register translations.
|
||||
* Load migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerTranslations()
|
||||
public function loadMigrations()
|
||||
{
|
||||
$langPath = resource_path('lang/modules/$LOWER_NAME$');
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../$MIGRATIONS_PATH$');
|
||||
}
|
||||
|
||||
if (is_dir($langPath)) {
|
||||
$this->loadTranslationsFrom($langPath, '$LOWER_NAME$');
|
||||
} else {
|
||||
$this->loadTranslationsFrom(__DIR__ .'/../$PATH_LANG$', '$LOWER_NAME$');
|
||||
/**
|
||||
* Load routes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function loadRoutes()
|
||||
{
|
||||
if (app()->routesAreCached()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an additional directory of factories.
|
||||
* @source https://github.com/sebastiaanluca/laravel-resource-flow/blob/develop/src/Modules/ModuleServiceProvider.php#L66
|
||||
*/
|
||||
public function registerFactories()
|
||||
{
|
||||
if (! app()->environment('production')) {
|
||||
app(Factory::class)->load(__DIR__ . '/Database/factories');
|
||||
$routes = [
|
||||
'admin.php',
|
||||
'portal.php',
|
||||
];
|
||||
|
||||
foreach ($routes as $route) {
|
||||
$this->loadRoutesFrom(__DIR__ . '/../$ROUTES_PATH$/' . $route);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$\Database\Seeders;
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Namespaces And Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When a module starting, this file will executed automatically. This helps
|
||||
| to register some namespaces like translator or view. Also this file
|
||||
| will load the routes file for each module. You may also modify
|
||||
| this file as you want.
|
||||
|
|
||||
*/
|
||||
|
||||
if (!app()->routesAreCached()) {
|
||||
require __DIR__ . '/Http/routes.php';
|
||||
}
|
19
app/Console/Stubs/Modules/unit-test.stub
Normal file
19
app/Console/Stubs/Modules/unit-test.stub
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace $NAMESPACE$;
|
||||
|
||||
use Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
class $CLASS$ extends TestCase
|
||||
{
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExample()
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
@extends('$LOWER_NAME$::layouts.master')
|
||||
@extends('layouts.admin')
|
||||
|
||||
@section('content')
|
||||
<h1>Hello World</h1>
|
||||
|
||||
<p>
|
||||
This view is loaded from module: {!! config('$LOWER_NAME$.name') !!}
|
||||
This view is loaded from module: {!! config('$ALIAS$.name') !!}
|
||||
</p>
|
||||
@stop
|
||||
|
@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Module $STUDLY_NAME$</title>
|
||||
</head>
|
||||
<body>
|
||||
@yield('content')
|
||||
</body>
|
||||
</html>
|
14
app/Console/Stubs/Modules/webpack.stub
Normal file
14
app/Console/Stubs/Modules/webpack.stub
Normal file
@ -0,0 +1,14 @@
|
||||
const mix = require('laravel-mix');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mix Asset Management
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
||||
| for your Laravel application. By default, we are compiling the Sass
|
||||
| file for the application as well as bundling up all the JS files.
|
||||
|
|
||||
*/
|
||||
|
||||
mix.js('Resources/assets/js/$ALIAS$.js', 'Assets/js/');
|
26
app/Events/Common/CompanySwitched.php
Normal file
26
app/Events/Common/CompanySwitched.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CompanySwitched
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $company;
|
||||
|
||||
public $old_company_id;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $company
|
||||
* @param $old_company_id
|
||||
*/
|
||||
public function __construct($company, $old_company_id)
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->old_company_id = $old_company_id;
|
||||
}
|
||||
}
|
30
app/Events/Common/ReportFilterApplying.php
Normal file
30
app/Events/Common/ReportFilterApplying.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ReportFilterApplying
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $class;
|
||||
|
||||
public $model;
|
||||
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $class
|
||||
* @param $model
|
||||
* @param $args
|
||||
*/
|
||||
public function __construct($class, $model, $args)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->model = $model;
|
||||
$this->args = $args;
|
||||
}
|
||||
}
|
22
app/Events/Common/ReportFilterShowing.php
Normal file
22
app/Events/Common/ReportFilterShowing.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ReportFilterShowing
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $class;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $class
|
||||
*/
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
}
|
30
app/Events/Common/ReportGroupApplying.php
Normal file
30
app/Events/Common/ReportGroupApplying.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ReportGroupApplying
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $class;
|
||||
|
||||
public $model;
|
||||
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $class
|
||||
* @param $model
|
||||
* @param $args
|
||||
*/
|
||||
public function __construct($class, $model, $args)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->model = $model;
|
||||
$this->args = $args;
|
||||
}
|
||||
}
|
22
app/Events/Common/ReportGroupShowing.php
Normal file
22
app/Events/Common/ReportGroupShowing.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Common;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ReportGroupShowing
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $class;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $class
|
||||
*/
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
class CompanySwitched
|
||||
{
|
||||
public $company;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $company
|
||||
*/
|
||||
public function __construct($company)
|
||||
{
|
||||
$this->company = $company;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Expense;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class BillCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $bill;
|
||||
|
||||
/**
|
22
app/Events/Expense/BillRecurring.php
Normal file
22
app/Events/Expense/BillRecurring.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Expense;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class BillRecurring
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $bill;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $bill
|
||||
*/
|
||||
public function __construct($bill)
|
||||
{
|
||||
$this->bill = $bill;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Expense;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class BillUpdated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $bill;
|
||||
|
||||
/**
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
/**
|
22
app/Events/Income/InvoiceCreating.php
Normal file
22
app/Events/Income/InvoiceCreating.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceCreating
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoicePrinting
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
/**
|
22
app/Events/Income/InvoiceRecurring.php
Normal file
22
app/Events/Income/InvoiceRecurring.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceRecurring
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $invoice
|
||||
*/
|
||||
public function __construct($invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Income;
|
||||
|
||||
class InvoiceUpdated
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceSent
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
/**
|
26
app/Events/Income/InvoiceUpdated.php
Normal file
26
app/Events/Income/InvoiceUpdated.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceUpdated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $invoice
|
||||
* @param $request
|
||||
*/
|
||||
public function __construct($invoice, $request)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
26
app/Events/Income/InvoiceUpdating.php
Normal file
26
app/Events/Income/InvoiceUpdating.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceUpdating
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $invoice
|
||||
* @param $request
|
||||
*/
|
||||
public function __construct($invoice, $request)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
22
app/Events/Income/InvoiceViewed.php
Normal file
22
app/Events/Income/InvoiceViewed.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Income;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InvoiceViewed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $invoice
|
||||
*/
|
||||
public function __construct($invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Income;
|
||||
|
||||
class InvoicePaid
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PaymentReceived
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invoice;
|
||||
|
||||
public $request;
|
30
app/Events/Install/UpdateCopied.php
Normal file
30
app/Events/Install/UpdateCopied.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Install;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class UpdateCopied
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $alias;
|
||||
|
||||
public $old;
|
||||
|
||||
public $new;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $alias
|
||||
* @param $old
|
||||
* @param $new
|
||||
*/
|
||||
public function __construct($alias, $old, $new)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
$this->old = $old;
|
||||
$this->new = $new;
|
||||
}
|
||||
}
|
30
app/Events/Install/UpdateDownloaded.php
Normal file
30
app/Events/Install/UpdateDownloaded.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Install;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class UpdateDownloaded
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $alias;
|
||||
|
||||
public $old;
|
||||
|
||||
public $new;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $alias
|
||||
* @param $old
|
||||
* @param $new
|
||||
*/
|
||||
public function __construct($alias, $old, $new)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
$this->old = $old;
|
||||
$this->new = $new;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Install;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class UpdateFinished
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $alias;
|
||||
|
||||
public $old;
|
30
app/Events/Install/UpdateUnzipped.php
Normal file
30
app/Events/Install/UpdateUnzipped.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events\Install;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class UpdateUnzipped
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $alias;
|
||||
|
||||
public $old;
|
||||
|
||||
public $new;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $alias
|
||||
* @param $old
|
||||
* @param $new
|
||||
*/
|
||||
public function __construct($alias, $old, $new)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
$this->old = $old;
|
||||
$this->new = $new;
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Menu;
|
||||
|
||||
class CustomerMenuCreated
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class AdminCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $menu;
|
||||
|
||||
/**
|
@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
namespace App\Events\Menu;
|
||||
|
||||
class AdminMenuCreated
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class AdminCreating
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $menu;
|
||||
|
||||
/**
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user