mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
init crater
This commit is contained in:
22
.editorconfig
Normal file
22
.editorconfig
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.vue]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.js]
|
||||||
|
indent_size = 2
|
||||||
36
.env.example
Normal file
36
.env.example
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_LOG_LEVEL=debug
|
||||||
|
APP_URL=http://localhost
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=homestead
|
||||||
|
DB_USERNAME=homestead
|
||||||
|
DB_PASSWORD=secret
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=log
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
QUEUE_DRIVER=sync
|
||||||
|
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_DRIVER=smtp
|
||||||
|
MAIL_HOST=mailtrap.io
|
||||||
|
MAIL_PORT=2525
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
|
||||||
|
PUSHER_APP_ID=
|
||||||
|
PUSHER_KEY=
|
||||||
|
PUSHER_SECRET=
|
||||||
|
|
||||||
|
PROXY_OAUTH_CLIENT_ID=2
|
||||||
|
PROXY_OAUTH_CLIENT_SECRET=SECRET-GENERATED-KEY-HERE
|
||||||
|
PROXY_OAUTH_GRANT_TYPE=password
|
||||||
4
.env.testing
Normal file
4
.env.testing
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
APP_ENV=testing
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_KEY=base64:IdDlpLmYyWA9z4Ruj5st1FSYrhCR7lPOscLGCz2Jf4I=
|
||||||
|
DB_CONNECTION=sqlite
|
||||||
10
.eslintrc
Normal file
10
.eslintrc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/recommended",
|
||||||
|
"standard"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"vue/max-attributes-per-line" : 3
|
||||||
|
}
|
||||||
|
}
|
||||||
3
.expo/packager-info.json
Normal file
3
.expo/packager-info.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"devToolsPort": 19002
|
||||||
|
}
|
||||||
7
.expo/settings.json
Normal file
7
.expo/settings.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"hostType": "lan",
|
||||||
|
"lanType": "ip",
|
||||||
|
"dev": true,
|
||||||
|
"minify": false,
|
||||||
|
"urlRandomness": null
|
||||||
|
}
|
||||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* text=auto
|
||||||
|
*.css linguist-vendored
|
||||||
|
*.scss linguist-vendored
|
||||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/node_modules
|
||||||
|
/public/storage
|
||||||
|
/public/hot
|
||||||
|
/storage/*.key
|
||||||
|
/vendor
|
||||||
|
/.idea
|
||||||
|
Homestead.json
|
||||||
|
Homestead.yaml
|
||||||
|
.env
|
||||||
|
public/assets/css/laraspace.css
|
||||||
|
public/assets/js/app.js
|
||||||
|
public/assets/css/laraspace.css.map
|
||||||
|
public/assets/js/app.js.map
|
||||||
|
public/mix-manifest.json
|
||||||
|
public/0.js
|
||||||
|
public/0.js.map
|
||||||
|
public/1.js
|
||||||
|
public/1.js.map
|
||||||
|
public/assets/css/laraspace.css.map
|
||||||
|
public/assets/js/app.js.map
|
||||||
|
.phpunit.result.cache
|
||||||
2
.vscode/settings.json
vendored
Normal file
2
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
{
|
||||||
|
}
|
||||||
12265
_ide_helper.php
Normal file
12265
_ide_helper.php
Normal file
File diff suppressed because it is too large
Load Diff
48
app/Address.php
Normal file
48
app/Address.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Country;
|
||||||
|
use Laraspace\State;
|
||||||
|
use Laraspace\City;
|
||||||
|
|
||||||
|
class Address extends Model
|
||||||
|
{
|
||||||
|
const BILLING_TYPE = 'BILLING';
|
||||||
|
const SHIPPING_TYPE = 'SHIPPING';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'address_street_1',
|
||||||
|
'address_street_2',
|
||||||
|
'city_id',
|
||||||
|
'state_id',
|
||||||
|
'country_id',
|
||||||
|
'zip',
|
||||||
|
'phone',
|
||||||
|
'fax',
|
||||||
|
'type',
|
||||||
|
'user_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function country()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Country::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function state()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(State::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function city()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(City::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/City.php
Normal file
19
app/City.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\State;
|
||||||
|
use Laraspace\Country;
|
||||||
|
|
||||||
|
class City extends Model
|
||||||
|
{
|
||||||
|
public function state()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(State::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function address()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Address::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
app/Company.php
Normal file
36
app/Company.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||||
|
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
|
||||||
|
|
||||||
|
class Company extends Model implements HasMedia
|
||||||
|
{
|
||||||
|
use HasMediaTrait;
|
||||||
|
|
||||||
|
protected $fillable = ['name', 'logo', 'unique_hash'];
|
||||||
|
|
||||||
|
protected $appends=['logo'];
|
||||||
|
|
||||||
|
public function getLogoAttribute()
|
||||||
|
{
|
||||||
|
$logo = $this->getMedia('logo')->first();
|
||||||
|
if ($logo) {
|
||||||
|
return asset($logo->getUrl());
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->hasOne(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function settings()
|
||||||
|
{
|
||||||
|
return $this->hasMany(CompanySetting::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
app/CompanySetting.php
Normal file
48
app/CompanySetting.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\User;
|
||||||
|
|
||||||
|
class CompanySetting extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['company_id', 'option', 'value'];
|
||||||
|
|
||||||
|
public function company()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Company::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setSetting($key, $setting, $company_id)
|
||||||
|
{
|
||||||
|
$old = self::whereOption($key)->whereCompany($company_id)->first();
|
||||||
|
|
||||||
|
if ($old) {
|
||||||
|
$old->value = $setting;
|
||||||
|
$old->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = new CompanySetting();
|
||||||
|
$set->option = $key;
|
||||||
|
$set->value = $setting;
|
||||||
|
$set->company_id = $company_id;
|
||||||
|
$set->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSetting($key, $company_id)
|
||||||
|
{
|
||||||
|
$setting = static::whereOption($key)->whereCompany($company_id)->first();
|
||||||
|
|
||||||
|
if ($setting) {
|
||||||
|
return $setting->value;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('company_id', $company_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
app/Console/Commands/CheckEstimateStatus.php
Normal file
51
app/Console/Commands/CheckEstimateStatus.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Laraspace\Estimate;
|
||||||
|
|
||||||
|
class CheckEstimateStatus extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'check:estimates:status';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Check invoices status.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$date = Carbon::now();
|
||||||
|
$status = array(Estimate::STATUS_ACCEPTED, Estimate::STATUS_REJECTED, Estimate::STATUS_EXPIRED);
|
||||||
|
$estimates = Estimate::whereNotIn('status', $status)->whereDate('expiry_date', '<', $date)->get();
|
||||||
|
|
||||||
|
foreach ($estimates as $estimate) {
|
||||||
|
$estimate->status = Estimate::STATUS_EXPIRED;
|
||||||
|
printf("Estimate %s is EXPIRED \n", $estimate->estimate_number);
|
||||||
|
$estimate->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/Console/Commands/CheckInvoiceStatus.php
Normal file
50
app/Console/Commands/CheckInvoiceStatus.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
|
||||||
|
class CheckInvoiceStatus extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'check:invoices:status';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Check invoices status.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$date = Carbon::now();
|
||||||
|
$invoices = Invoice::where('status', '<>', Invoice::STATUS_COMPLETED)->whereDate('due_date', '<',$date)->get();
|
||||||
|
|
||||||
|
foreach ($invoices as $invoice) {
|
||||||
|
$invoice->status = Invoice::STATUS_OVERDUE;
|
||||||
|
printf("Invoice %s is OVERDUE \n", $invoice->invoice_number);
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/Console/Kernel.php
Normal file
43
app/Console/Kernel.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Console;
|
||||||
|
|
||||||
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
|
class Kernel extends ConsoleKernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The Artisan commands provided by your application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $commands = [
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the application's command schedule.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function schedule(Schedule $schedule)
|
||||||
|
{
|
||||||
|
$schedule->command('check:invoices:status')
|
||||||
|
->daily();
|
||||||
|
|
||||||
|
$schedule->command('check:estimates:status')
|
||||||
|
->daily();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Closure based commands for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function commands()
|
||||||
|
{
|
||||||
|
$this->load(__DIR__.'/Commands');
|
||||||
|
require base_path('routes/console.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Country.php
Normal file
19
app/Country.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\State;
|
||||||
|
use Laraspace\Country;
|
||||||
|
|
||||||
|
class Country extends Model
|
||||||
|
{
|
||||||
|
public function states()
|
||||||
|
{
|
||||||
|
return $this->hasMany(State::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function address()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Address::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/Currency.php
Normal file
17
app/Currency.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Currency extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'code',
|
||||||
|
'symbol',
|
||||||
|
'precision',
|
||||||
|
'thousand_separator',
|
||||||
|
'decimal_separator',
|
||||||
|
'position'
|
||||||
|
];
|
||||||
|
}
|
||||||
225
app/Estimate.php
Normal file
225
app/Estimate.php
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class Estimate extends Model
|
||||||
|
{
|
||||||
|
const STATUS_DRAFT = 'DRAFT';
|
||||||
|
const STATUS_SENT = 'SENT';
|
||||||
|
const STATUS_VIEWED = 'VIEWED';
|
||||||
|
const STATUS_EXPIRED = 'EXPIRED';
|
||||||
|
const STATUS_ACCEPTED = 'ACCEPTED';
|
||||||
|
const STATUS_REJECTED = 'REJECTED';
|
||||||
|
|
||||||
|
protected $dates = [
|
||||||
|
'created_at',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at',
|
||||||
|
'estimate_date',
|
||||||
|
'expiry_date'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'formattedExpiryDate',
|
||||||
|
'formattedEstimateDate'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'estimate_date',
|
||||||
|
'expiry_date',
|
||||||
|
'estimate_number',
|
||||||
|
'user_id',
|
||||||
|
'company_id',
|
||||||
|
'reference_number',
|
||||||
|
'estimate_template_id',
|
||||||
|
'discount',
|
||||||
|
'discount_type',
|
||||||
|
'discount_val',
|
||||||
|
'status',
|
||||||
|
'sub_total',
|
||||||
|
'tax_per_item',
|
||||||
|
'discount_per_item',
|
||||||
|
'total',
|
||||||
|
'tax',
|
||||||
|
'notes',
|
||||||
|
'unique_hash'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'total' => 'float',
|
||||||
|
'tax' => 'float',
|
||||||
|
'sub_total' => 'float'
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function getNextEstimateNumber()
|
||||||
|
{
|
||||||
|
// Get the last created order
|
||||||
|
$lastOrder = Estimate::orderBy('created_at', 'desc')->first();
|
||||||
|
if (!$lastOrder) {
|
||||||
|
// We get here if there is no order at all
|
||||||
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
|
$number = 0;
|
||||||
|
} else {
|
||||||
|
$number = explode("-",$lastOrder->estimate_number);
|
||||||
|
$number = $number[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have ORD000001 in the database then we only want the number
|
||||||
|
// So the substr returns this 000001
|
||||||
|
|
||||||
|
// Add the string in front and higher up the number.
|
||||||
|
// the %05d part makes sure that there are always 6 numbers in the string.
|
||||||
|
// so it adds the missing zero's when needed.
|
||||||
|
|
||||||
|
return sprintf('%06d', intval($number) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function items()
|
||||||
|
{
|
||||||
|
return $this->hasMany('Laraspace\EstimateItem');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Laraspace\User');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Tax::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function estimateTemplate()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Laraspace\EstimateTemplate');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEstimateNumAttribute()
|
||||||
|
{
|
||||||
|
$position = $this->strposX($this->estimate_number, "-", 2) + 1;
|
||||||
|
return substr($this->estimate_number, $position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function strposX($haystack, $needle, $number)
|
||||||
|
{
|
||||||
|
if ($number == '1') {
|
||||||
|
return strpos($haystack, $needle);
|
||||||
|
} elseif ($number > '1') {
|
||||||
|
return strpos(
|
||||||
|
$haystack,
|
||||||
|
$needle,
|
||||||
|
$this->strposX($haystack, $needle, $number - 1) + strlen($needle)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return error_log('Error: Value for parameter $number is out of range');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedExpiryDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->expiry_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedEstimateDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->estimate_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeEstimatesBetween($query, $start, $end)
|
||||||
|
{
|
||||||
|
return $query->whereBetween(
|
||||||
|
'estimates.estimate_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereStatus($query, $status)
|
||||||
|
{
|
||||||
|
return $query->where('estimates.status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereEstimateNumber($query, $estimateNumber)
|
||||||
|
{
|
||||||
|
return $query->where('estimates.estimate_number', $estimateNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereSearch($query, $search)
|
||||||
|
{
|
||||||
|
foreach (explode(' ', $search) as $term) {
|
||||||
|
$query->whereHas('user', function ($query) use ($term) {
|
||||||
|
$query->where('name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('contact_name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('company_name', 'LIKE', '%'.$term.'%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
|
||||||
|
if ($filters->get('search')) {
|
||||||
|
$query->whereSearch($filters->get('search'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('estimate_number')) {
|
||||||
|
$query->whereEstimateNumber($filters->get('estimate_number'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('status')) {
|
||||||
|
$query->whereStatus($filters->get('status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||||
|
$start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date'));
|
||||||
|
$end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date'));
|
||||||
|
$query->estimatesBetween($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('customer_id')) {
|
||||||
|
$query->whereCustomer($filters->get('customer_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||||
|
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'estimate_number';
|
||||||
|
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||||
|
$query->whereOrder($field, $orderBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||||
|
{
|
||||||
|
$query->orderBy($orderByField, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('estimates.company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCustomer($query, $customer_id)
|
||||||
|
{
|
||||||
|
$query->where('estimates.user_id', $customer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteEstimate($id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::find($id);
|
||||||
|
|
||||||
|
if ($estimate->items()->exists()) {
|
||||||
|
$estimate->items()->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($estimate->taxes()->exists()) {
|
||||||
|
$estimate->taxes()->delete();
|
||||||
|
}
|
||||||
|
$estimate->delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/EstimateItem.php
Normal file
50
app/EstimateItem.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class EstimateItem extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'estimate_id',
|
||||||
|
'name',
|
||||||
|
'item_id',
|
||||||
|
'description',
|
||||||
|
'quantity',
|
||||||
|
'company_id',
|
||||||
|
'price',
|
||||||
|
'discount_type',
|
||||||
|
'discount_val',
|
||||||
|
'tax',
|
||||||
|
'total',
|
||||||
|
'discount'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'price' => 'integer',
|
||||||
|
'total' => 'integer',
|
||||||
|
'discount' => 'float',
|
||||||
|
'discount_val' => 'integer',
|
||||||
|
'tax' => 'integer'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function estimate()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Estimate::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function item()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Item::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Tax::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('company_id', $company_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/EstimateTemplate.php
Normal file
20
app/EstimateTemplate.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\Estimate;
|
||||||
|
|
||||||
|
class EstimateTemplate extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['path', 'view', 'name'];
|
||||||
|
|
||||||
|
public function estimates()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Estimate::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPathAttribute($value)
|
||||||
|
{
|
||||||
|
return url($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/Exceptions/Handler.php
Normal file
52
app/Exceptions/Handler.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
|
||||||
|
class Handler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A list of the exception types that are not reported.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $dontReport = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of the inputs that are never flashed for validation exceptions.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $dontFlash = [
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report or log an exception.
|
||||||
|
*
|
||||||
|
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
|
||||||
|
*
|
||||||
|
* @param \Exception $exception
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function report(Exception $exception)
|
||||||
|
{
|
||||||
|
parent::report($exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render an exception into an HTTP response.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Exception $exception
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function render($request, Exception $exception)
|
||||||
|
{
|
||||||
|
return parent::render($request, $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
140
app/Expense.php
Normal file
140
app/Expense.php
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||||
|
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
|
||||||
|
use Laraspace\ExpenseCategory;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class Expense extends Model implements HasMedia
|
||||||
|
{
|
||||||
|
use HasMediaTrait;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'expense_category_id',
|
||||||
|
'amount',
|
||||||
|
'company_id',
|
||||||
|
'expense_date',
|
||||||
|
'notes',
|
||||||
|
'attachment_receipt'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'formattedExpenseDate',
|
||||||
|
'formattedCreatedAt',
|
||||||
|
'receipt'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function category()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ExpenseCategory::class, 'expense_category_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedExpenseDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->expense_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->created_at)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReceiptAttribute($value)
|
||||||
|
{
|
||||||
|
$media = $this->getFirstMedia('receipts');
|
||||||
|
if($media) {
|
||||||
|
return $media->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeExpensesBetween($query, $start, $end)
|
||||||
|
{
|
||||||
|
return $query->whereBetween(
|
||||||
|
'expenses.expense_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCategoryName($query, $search)
|
||||||
|
{
|
||||||
|
foreach (explode(' ', $search) as $term) {
|
||||||
|
$query->whereHas('category', function ($query) use ($term) {
|
||||||
|
$query->where('name', 'LIKE', '%'.$term.'%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereNotes($query, $search)
|
||||||
|
{
|
||||||
|
$query->where('notes', 'LIKE', '%'.$search.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCategory($query, $categoryId)
|
||||||
|
{
|
||||||
|
return $query->where('expenses.expense_category_id', $categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
|
||||||
|
if ($filters->get('expense_category_id')) {
|
||||||
|
$query->whereCategory($filters->get('expense_category_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||||
|
$start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date'));
|
||||||
|
$end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date'));
|
||||||
|
$query->expensesBetween($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||||
|
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'expense_date';
|
||||||
|
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||||
|
$query->whereOrder($field, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('search')) {
|
||||||
|
$query->whereSearch($filters->get('search'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereSearch($query, $search)
|
||||||
|
{
|
||||||
|
foreach (explode(' ', $search) as $term) {
|
||||||
|
$query->whereHas('category', function ($query) use ($term) {
|
||||||
|
$query->where('name', 'LIKE', '%'.$term.'%');
|
||||||
|
})
|
||||||
|
->orWhere('notes', 'LIKE', '%'.$term.'%');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||||
|
{
|
||||||
|
$query->orderBy($orderByField, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('expenses.company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeExpensesAttributes($query)
|
||||||
|
{
|
||||||
|
$query->select(
|
||||||
|
DB::raw('
|
||||||
|
count(*) as expenses_count,
|
||||||
|
sum(amount) as total_amount,
|
||||||
|
expense_category_id'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->groupBy('expense_category_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/ExpenseCategory.php
Normal file
39
app/ExpenseCategory.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class ExpenseCategory extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['name', 'company_id', 'description'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accessors to append to the model's array form.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $appends = ['amount', 'formattedCreatedAt'];
|
||||||
|
|
||||||
|
public function expenses()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Expense::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->created_at)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAmountAttribute()
|
||||||
|
{
|
||||||
|
return $this->expenses()->sum('amount');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('company_id', $company_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
194
app/Http/Controllers/Auth/AccessTokensController.php
Normal file
194
app/Http/Controllers/Auth/AccessTokensController.php
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use Laraspace\Proxy\HttpKernelProxy;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||||
|
use Validator;
|
||||||
|
use Hash;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Auth;
|
||||||
|
use Laraspace\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class AccessTokensController extends Controller
|
||||||
|
{
|
||||||
|
use ThrottlesLogins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool for proxying requests to the existing application.
|
||||||
|
*
|
||||||
|
* @var HttpKernelProxy
|
||||||
|
*/
|
||||||
|
protected $proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(HttpKernelProxy $proxy)
|
||||||
|
{
|
||||||
|
$this->middleware('api')->except(['store', 'update']);
|
||||||
|
$this->proxy = $proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the login username to be used by the controller.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function username()
|
||||||
|
{
|
||||||
|
return 'email';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new access token.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'username' => 'required|email',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($this->hasTooManyLoginAttempts($request)) {
|
||||||
|
$this->fireLockoutEvent($request);
|
||||||
|
|
||||||
|
return $this->sendLockoutResponse($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->requestPasswordGrant($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh an access token.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
$token = $request->cookie('refresh_token');
|
||||||
|
|
||||||
|
if (!$token) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'refresh_token' => trans('oauth.missing_refresh_token')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->proxy->postJson('oauth/token', [
|
||||||
|
'client_id' => config('auth.proxy.client_id'),
|
||||||
|
'client_secret' => config('auth.proxy.client_secret'),
|
||||||
|
'grant_type' => 'refresh_token',
|
||||||
|
'refresh_token' => $token,
|
||||||
|
'scopes' => '[*]',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($response->isSuccessful()) {
|
||||||
|
return $this->sendSuccessResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response($response->getContent(), $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the guard to be used during authentication.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||||
|
*/
|
||||||
|
protected function guard()
|
||||||
|
{
|
||||||
|
return Auth::guard('api');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Request $request)
|
||||||
|
{
|
||||||
|
$accessToken = Auth::user()->token();
|
||||||
|
|
||||||
|
\DB::table('oauth_refresh_tokens')
|
||||||
|
->where('access_token_id', $accessToken->id)
|
||||||
|
->update([
|
||||||
|
'revoked' => true
|
||||||
|
]);
|
||||||
|
|
||||||
|
$accessToken->revoke();
|
||||||
|
|
||||||
|
return response()->json(null, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new access token from a password grant client.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function requestPasswordGrant(Request $request)
|
||||||
|
{
|
||||||
|
$response = $this->proxy->postJson('oauth/token', [
|
||||||
|
'client_id' => config('auth.proxy.client_id'),
|
||||||
|
'client_secret' => config('auth.proxy.client_secret'),
|
||||||
|
'grant_type' => config('auth.proxy.grant_type'),
|
||||||
|
'username' => $request->username,
|
||||||
|
'password' => $request->password,
|
||||||
|
'scopes' => '[*]'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::where('email', $request->username)->first();
|
||||||
|
|
||||||
|
if ($response->isSuccessful()) {
|
||||||
|
$this->clearLoginAttempts($request);
|
||||||
|
return $this->sendSuccessResponse($response, $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->incrementLoginAttempts($request);
|
||||||
|
|
||||||
|
return response($response->getContent(), $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a successful response for requesting an api token.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Response $response
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function sendSuccessResponse(Response $response, $user)
|
||||||
|
{
|
||||||
|
$data = json_decode($response->getContent());
|
||||||
|
|
||||||
|
$content = [
|
||||||
|
'access_token' => $data->access_token,
|
||||||
|
'expires_in' => $data->expires_in,
|
||||||
|
];
|
||||||
|
|
||||||
|
return response($content, $response->getStatusCode())->cookie(
|
||||||
|
'refresh_token',
|
||||||
|
$data->refresh_token,
|
||||||
|
10 * 24 * 60,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isRegistered(Request $request)
|
||||||
|
{
|
||||||
|
if (User::whereEmail($request->email)->first()) {
|
||||||
|
return 'true';
|
||||||
|
} else {
|
||||||
|
return 'false';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
app/Http/Controllers/Auth/ForgotPasswordController.php
Normal file
59
app/Http/Controllers/Auth/ForgotPasswordController.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use Laraspace\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ForgotPasswordController extends Controller
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Reset Controller
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This controller is responsible for handling password reset emails and
|
||||||
|
| includes a trait which assists in sending these notifications from
|
||||||
|
| your application to your users. Feel free to explore this trait.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use SendsPasswordResetEmails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// $this->middleware('guest');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a successful password reset link.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetLinkResponse(Request $request, $response)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Password reset email sent.',
|
||||||
|
'data' => $response,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a failed password reset link.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetLinkFailedResponse(Request $request, $response)
|
||||||
|
{
|
||||||
|
return response('Email could not be sent to this email address.', 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
85
app/Http/Controllers/Auth/ResetPasswordController.php
Normal file
85
app/Http/Controllers/Auth/ResetPasswordController.php
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use Laraspace\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Auth\Events\PasswordReset;
|
||||||
|
|
||||||
|
class ResetPasswordController extends Controller
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Reset Controller
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This controller is responsible for handling password reset requests
|
||||||
|
| and uses a simple trait to include this behavior. You're free to
|
||||||
|
| explore this trait and override any methods you wish to tweak.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use ResetsPasswords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users after resetting their password.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $redirectTo = '/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// $this->middleware('guest');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a successful password reset.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetResponse(Request $request, $response)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Password reset successfully.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the given user's password.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
|
||||||
|
* @param string $password
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function resetPassword($user, $password)
|
||||||
|
{
|
||||||
|
$user->password = \Hash::make($password);
|
||||||
|
|
||||||
|
$user->setRememberToken(Str::random(60));
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
event(new PasswordReset($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a failed password reset.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetFailedResponse(Request $request, $response)
|
||||||
|
{
|
||||||
|
return response('Failed, Invalid Token.', 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
238
app/Http/Controllers/CompanyController.php
Normal file
238
app/Http/Controllers/CompanyController.php
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\Address;
|
||||||
|
use Laraspace\Http\Requests\SettingRequest;
|
||||||
|
use Laraspace\Http\Requests\SettingKeyRequest;
|
||||||
|
use Laraspace\Http\Requests\ProfileRequest;
|
||||||
|
use Laraspace\Http\Requests\CompanyRequest;
|
||||||
|
use Laraspace\Http\Requests\CompanySettingRequest;
|
||||||
|
use Laraspace\Http\Requests\NotificationSettingsRequest;
|
||||||
|
use Laraspace\Space\CurrencyFormatter;
|
||||||
|
use Laraspace\Space\DateFormatter;
|
||||||
|
use Laraspace\Space\TimeZones;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
|
||||||
|
class CompanyController extends Controller
|
||||||
|
{
|
||||||
|
public function getAdmin()
|
||||||
|
{
|
||||||
|
return User::find(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateAdminProfile(ProfileRequest $request)
|
||||||
|
{
|
||||||
|
$verifyEmail = User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if ($verifyEmail) {
|
||||||
|
if ($verifyEmail->id !== $user->id) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'Email already in use'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->name = $request->name;
|
||||||
|
$user->email = $request->email;
|
||||||
|
|
||||||
|
if ($request->has('password')) {
|
||||||
|
$user->password = bcrypt($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAdminCompany()
|
||||||
|
{
|
||||||
|
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateAdminCompany(CompanyRequest $request)
|
||||||
|
{
|
||||||
|
$user = User::find(1);
|
||||||
|
$company = $user->company;
|
||||||
|
$company->name = $request->name;
|
||||||
|
$company->save();
|
||||||
|
|
||||||
|
if ($request->has('logo')) {
|
||||||
|
$company->clearMediaCollection('logo');
|
||||||
|
$company->addMediaFromRequest('logo')->toMediaCollection('logo');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = $request->only(['address_street_1', 'address_street_2', 'city_id', 'state_id', 'country_id', 'zip', 'phone']);
|
||||||
|
$address = Address::updateOrCreate(['user_id' => 1], $fields);
|
||||||
|
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGeneralSettings(Request $request)
|
||||||
|
{
|
||||||
|
$date_formats = DateFormatter::get_list();
|
||||||
|
|
||||||
|
$time_zones = TimeZones::get_list();
|
||||||
|
$fiscal_years = [
|
||||||
|
['key' => 'january-december' , 'value' => '1-12'],
|
||||||
|
['key' => 'february-january' , 'value' => '2-1'],
|
||||||
|
['key' => 'march-february' , 'value' => '3-2'],
|
||||||
|
['key' => 'april-march' , 'value' => '4-3'],
|
||||||
|
['key' => 'may-april' , 'value' => '5-4'],
|
||||||
|
['key' => 'june-may' , 'value' => '6-5'],
|
||||||
|
['key' => 'july-june' , 'value' => '7-6'],
|
||||||
|
['key' => 'august-july' , 'value' => '8-7'],
|
||||||
|
['key' => 'september-august' , 'value' => '9-8'],
|
||||||
|
['key' => 'october-september', 'value' => '10-9'],
|
||||||
|
['key' => 'november-october' , 'value' => '11-10'],
|
||||||
|
['key' => 'december-november', 'value' => '12-11'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$languages = [
|
||||||
|
"en" => "English",
|
||||||
|
"de" => "German",
|
||||||
|
"fr" => "French",
|
||||||
|
"es" => "Spanish"
|
||||||
|
];
|
||||||
|
|
||||||
|
$language = CompanySetting::getSetting('language', $request->header('company'));
|
||||||
|
$carbon_date_format = CompanySetting::getSetting('carbon_date_format', $request->header('company'));
|
||||||
|
$moment_date_format = CompanySetting::getSetting('moment_date_format', $request->header('company'));
|
||||||
|
$time_zone = CompanySetting::getSetting('time_zone', $request->header('company'));
|
||||||
|
$currency = CompanySetting::getSetting('currency', $request->header('company'));
|
||||||
|
$fiscal_year = CompanySetting::getSetting('fiscal_year', $request->header('company'));
|
||||||
|
|
||||||
|
$languages = [
|
||||||
|
["code"=>"en", "name" => "English"],
|
||||||
|
["code"=>"de", "name" => "German"],
|
||||||
|
["code"=>"fr", "name" => "French"],
|
||||||
|
["code"=>"es", "name" => "Spanish"]
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'languages' => $languages,
|
||||||
|
'date_formats' => $date_formats,
|
||||||
|
'time_zones' => $time_zones,
|
||||||
|
'time_zone' => $time_zone,
|
||||||
|
'currencies' => Currency::all(),
|
||||||
|
'fiscal_years' => $fiscal_years,
|
||||||
|
'fiscal_year' => $fiscal_year,
|
||||||
|
'selectedLanguage' => $language,
|
||||||
|
'selectedCurrency' => $currency,
|
||||||
|
'carbon_date_format' => $carbon_date_format,
|
||||||
|
'moment_date_format' => $moment_date_format,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateGeneralSettings(CompanySettingRequest $request)
|
||||||
|
{
|
||||||
|
$sets = [
|
||||||
|
'currency',
|
||||||
|
'time_zone',
|
||||||
|
'language',
|
||||||
|
'carbon_date_format',
|
||||||
|
'fiscal_year',
|
||||||
|
'moment_date_format'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($sets as $key) {
|
||||||
|
CompanySetting::setSetting($key, $request->$key, $request->header('company'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateSetting(SettingRequest $request)
|
||||||
|
{
|
||||||
|
CompanySetting::setSetting($request->key, $request->value, $request->header('company'));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSetting(SettingKeyRequest $request)
|
||||||
|
{
|
||||||
|
$setting = CompanySetting::getSetting($request->key, $request->header('company'));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
$request->key => $setting
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColors(Request $request)
|
||||||
|
{
|
||||||
|
$colors = [
|
||||||
|
'invoice_primary_color',
|
||||||
|
'invoice_column_heading',
|
||||||
|
'invoice_field_label',
|
||||||
|
'invoice_field_value',
|
||||||
|
'invoice_body_text',
|
||||||
|
'invoice_description_text',
|
||||||
|
'invoice_border_color',
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'colorSettings' => $colorSettings
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the company logo to storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function uploadCompanyLogo(Request $request)
|
||||||
|
{
|
||||||
|
$data = json_decode($request->company_logo);
|
||||||
|
|
||||||
|
if($data) {
|
||||||
|
$company = Company::find($request->header('company'));
|
||||||
|
|
||||||
|
if($company) {
|
||||||
|
$company->clearMediaCollection('logo');
|
||||||
|
|
||||||
|
$company->addMediaFromBase64($data->data)
|
||||||
|
->usingFileName($data->name)
|
||||||
|
->toMediaCollection('logo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
app/Http/Controllers/Controller.php
Normal file
12
app/Http/Controllers/Controller.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
|
||||||
|
class Controller extends BaseController
|
||||||
|
{
|
||||||
|
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||||
|
}
|
||||||
233
app/Http/Controllers/CustomersController.php
Normal file
233
app/Http/Controllers/CustomersController.php
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Laraspace\Conversation;
|
||||||
|
use Laraspace\Group;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\Notifications\CustomerAdded;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Address;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class CustomersController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$customers = User::customer()
|
||||||
|
->applyFilters($request->only([
|
||||||
|
'search',
|
||||||
|
'contact_name',
|
||||||
|
'display_name',
|
||||||
|
'phone',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy'
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->select('users.*',
|
||||||
|
DB::raw('sum(invoices.due_amount) as due_amount')
|
||||||
|
)
|
||||||
|
->groupBy('users.id')
|
||||||
|
->leftJoin('invoices', 'users.id', '=', 'invoices.user_id')
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
$siteData = [
|
||||||
|
'customers' => $customers
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($siteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(Requests\CustomerRequest $request)
|
||||||
|
{
|
||||||
|
$verifyEmail = User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
|
||||||
|
$customer = new User();
|
||||||
|
$customer->name = $request->name;
|
||||||
|
$customer->currency_id = $request->currency_id;
|
||||||
|
$customer->company_id = $request->header('company');
|
||||||
|
$customer->email = $request->email;
|
||||||
|
$customer->phone = $request->phone;
|
||||||
|
$customer->company_name = $request->company_name;
|
||||||
|
$customer->contact_name = $request->contact_name;
|
||||||
|
$customer->website = $request->website;
|
||||||
|
$customer->enable_portal = $request->enable_portal;
|
||||||
|
$customer->role = 'customer';
|
||||||
|
$customer->password = Hash::make($request->password);
|
||||||
|
$customer->save();
|
||||||
|
|
||||||
|
if ($request->addresses) {
|
||||||
|
foreach ($request->addresses as $address) {
|
||||||
|
$newAddress = new Address();
|
||||||
|
$newAddress->name = $address["name"];
|
||||||
|
$newAddress->address_street_1 = $address["address_street_1"];
|
||||||
|
$newAddress->address_street_2 = $address["address_street_2"];
|
||||||
|
$newAddress->city_id = $address["city_id"];
|
||||||
|
$newAddress->state_id = $address["state_id"];
|
||||||
|
$newAddress->country_id = $address["country_id"];
|
||||||
|
$newAddress->zip = $address["zip"];
|
||||||
|
$newAddress->phone = $address["phone"];
|
||||||
|
$newAddress->type = $address["type"];
|
||||||
|
$newAddress->user_id = $customer->id;
|
||||||
|
$newAddress->save();
|
||||||
|
$customer->addresses()->save($newAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = User::with('billingAddress', 'shippingAddress')->find($customer->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customer' => $customer,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$customer = User::with([
|
||||||
|
'billingAddress',
|
||||||
|
'shippingAddress',
|
||||||
|
'billingAddress.country',
|
||||||
|
'billingAddress.state',
|
||||||
|
'billingAddress.city',
|
||||||
|
'shippingAddress.country',
|
||||||
|
'shippingAddress.state',
|
||||||
|
'shippingAddress.city',
|
||||||
|
])->find($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customer' => $customer
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$customer = User::with('billingAddress', 'shippingAddress')->findOrFail($id);
|
||||||
|
$currency = $customer->currency;
|
||||||
|
$currencies = Currency::all();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customer' => $customer,
|
||||||
|
'currencies' => $currencies,
|
||||||
|
'currency' => $currency
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update($id, Requests\CustomerRequest $request)
|
||||||
|
{
|
||||||
|
$customer = User::find($id);
|
||||||
|
|
||||||
|
if ($request->email != null) {
|
||||||
|
$verifyEmail = User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
if ($verifyEmail) {
|
||||||
|
if ($verifyEmail->id !== $customer->id) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'Email already in use'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('password')) {
|
||||||
|
$customer->password = Hash::make($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer->name = $request->name;
|
||||||
|
$customer->currency_id = $request->currency_id;
|
||||||
|
$customer->email = $request->email;
|
||||||
|
$customer->phone = $request->phone;
|
||||||
|
$customer->company_name = $request->company_name;
|
||||||
|
$customer->contact_name = $request->contact_name;
|
||||||
|
$customer->website = $request->website;
|
||||||
|
$customer->enable_portal = $request->enable_portal;
|
||||||
|
$customer->save();
|
||||||
|
|
||||||
|
if ($request->addresses) {
|
||||||
|
foreach ($request->addresses as $address) {
|
||||||
|
$newAddress = $customer->addresses()->firstOrNew(['type' => $address["type"]]);
|
||||||
|
$newAddress->name = $address["name"];
|
||||||
|
$newAddress->address_street_1 = $address["address_street_1"];
|
||||||
|
$newAddress->address_street_2 = $address["address_street_2"];
|
||||||
|
$newAddress->city_id = $address["city_id"];
|
||||||
|
$newAddress->state_id = $address["state_id"];
|
||||||
|
$newAddress->country_id = $address["country_id"];
|
||||||
|
$newAddress->zip = $address["zip"];
|
||||||
|
$newAddress->phone = $address["phone"];
|
||||||
|
$newAddress->type = $address["type"];
|
||||||
|
$newAddress->user_id = $customer->id;
|
||||||
|
$newAddress->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = User::with('billingAddress', 'shippingAddress')->find($customer->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customer' => $customer,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
User::deleteCustomer($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
foreach ($request->id as $id) {
|
||||||
|
User::deleteCustomer($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
155
app/Http/Controllers/DashboardController.php
Normal file
155
app/Http/Controllers/DashboardController.php
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
use Laraspace\Estimate;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Laraspace\Payment;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class DashboardController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$invoiceTotals = [];
|
||||||
|
$expenseTotals = [];
|
||||||
|
$receiptTotals = [];
|
||||||
|
$netProfits = [];
|
||||||
|
$i = 0;
|
||||||
|
$months = [];
|
||||||
|
$monthEnds = [];
|
||||||
|
$monthCounter = 0;
|
||||||
|
$fiscalYear = CompanySetting::getSetting('fiscal_year', $request->header('company'));
|
||||||
|
$startDate = Carbon::now();
|
||||||
|
$start = Carbon::now();
|
||||||
|
$end = Carbon::now();
|
||||||
|
$terms = explode('-', $fiscalYear);
|
||||||
|
if ($terms[0] < $start->month) {
|
||||||
|
$startDate->month($terms[0])->startOfMonth();
|
||||||
|
$start->month($terms[0])->startOfMonth();
|
||||||
|
$end->month($terms[0])->endOfMonth();
|
||||||
|
} else {
|
||||||
|
$startDate->subYear()->month($terms[0])->startOfMonth();
|
||||||
|
$start->subYear()->month($terms[0])->startOfMonth();
|
||||||
|
$end->subYear()->month($terms[0])->endOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('previous_year')) {
|
||||||
|
$startDate->subYear()->startOfMonth();
|
||||||
|
$start->subYear()->startOfMonth();
|
||||||
|
$end->subYear()->endOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($monthCounter < 12) {
|
||||||
|
array_push(
|
||||||
|
$invoiceTotals,
|
||||||
|
Invoice::whereBetween(
|
||||||
|
'invoice_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->sum('total')
|
||||||
|
);
|
||||||
|
array_push(
|
||||||
|
$expenseTotals,
|
||||||
|
Expense::whereBetween(
|
||||||
|
'expense_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->sum('amount')
|
||||||
|
);
|
||||||
|
array_push(
|
||||||
|
$receiptTotals,
|
||||||
|
Payment::whereBetween(
|
||||||
|
'payment_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->sum('amount')
|
||||||
|
);
|
||||||
|
array_push(
|
||||||
|
$netProfits,
|
||||||
|
($receiptTotals[$i] - $expenseTotals[$i])
|
||||||
|
);
|
||||||
|
$i++;
|
||||||
|
array_push($months, $start->format('M'));
|
||||||
|
$monthCounter++;
|
||||||
|
$end->startOfMonth();
|
||||||
|
$start->addMonth()->startOfMonth();
|
||||||
|
$end->addMonth()->endOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
$start->subMonth()->endOfMonth();
|
||||||
|
$salesTotal = Invoice::whereCompany($request->header('company'))
|
||||||
|
->whereBetween(
|
||||||
|
'invoice_date',
|
||||||
|
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->sum('total');
|
||||||
|
$totalReceipts = Payment::whereCompany($request->header('company'))
|
||||||
|
->whereBetween(
|
||||||
|
'payment_date',
|
||||||
|
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->sum('amount');
|
||||||
|
$totalExpenses = Expense::whereCompany($request->header('company'))
|
||||||
|
->whereBetween(
|
||||||
|
'expense_date',
|
||||||
|
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->sum('amount');
|
||||||
|
$netProfit = (int)$totalReceipts - (int)$totalExpenses;
|
||||||
|
|
||||||
|
$chartData = [
|
||||||
|
'months' => $months,
|
||||||
|
'invoiceTotals' => $invoiceTotals,
|
||||||
|
'expenseTotals' => $expenseTotals,
|
||||||
|
'receiptTotals' => $receiptTotals,
|
||||||
|
'netProfits' => $netProfits
|
||||||
|
];
|
||||||
|
|
||||||
|
$customersCount = User::customer()->whereCompany($request->header('company'))->get()->count();
|
||||||
|
$invoicesCount = Invoice::whereCompany($request->header('company'))->get()->count();
|
||||||
|
$estimatesCount = Estimate::whereCompany($request->header('company'))->get()->count();
|
||||||
|
$totalDueAmount = Invoice::whereCompany($request->header('company'))->sum('due_amount');
|
||||||
|
$dueInvoices = Invoice::with('user')->whereCompany($request->header('company'))->where('due_amount', '>', 0)->take(5)->latest()->get();
|
||||||
|
$estimates = Estimate::with('user')->whereCompany($request->header('company'))->take(5)->latest()->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'dueInvoices' => $dueInvoices,
|
||||||
|
'estimates' => $estimates,
|
||||||
|
'estimatesCount' => $estimatesCount,
|
||||||
|
'totalDueAmount' => $totalDueAmount,
|
||||||
|
'invoicesCount' => $invoicesCount,
|
||||||
|
'customersCount' => $customersCount,
|
||||||
|
'chartData' => $chartData,
|
||||||
|
'salesTotal' => $salesTotal,
|
||||||
|
'totalReceipts' => $totalReceipts,
|
||||||
|
'totalExpenses' => $totalExpenses,
|
||||||
|
'netProfit' => $netProfit
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpenseChartData(Request $request)
|
||||||
|
{
|
||||||
|
$expensesCategories = Expense::with('category')
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->expensesAttributes()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$amounts = $expensesCategories->pluck('total_amount');
|
||||||
|
$names = $expensesCategories->pluck('category.name');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'amounts' => $amounts,
|
||||||
|
'categories' => $names,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
90
app/Http/Controllers/EnvironmentController.php
Executable file
90
app/Http/Controllers/EnvironmentController.php
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Validator;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Space\EnvironmentManager;
|
||||||
|
use Laraspace\Http\Requests\DatabaseEnvironmentRequest;
|
||||||
|
use Laraspace\Http\Requests\MailEnvironmentRequest;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
|
class EnvironmentController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var EnvironmentManager
|
||||||
|
*/
|
||||||
|
protected $EnvironmentManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param EnvironmentManager $environmentManager
|
||||||
|
*/
|
||||||
|
public function __construct(EnvironmentManager $environmentManager)
|
||||||
|
{
|
||||||
|
$this->EnvironmentManager = $environmentManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param DatabaseEnvironmentRequest $request
|
||||||
|
*/
|
||||||
|
public function saveDatabaseEnvironment(DatabaseEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
$results = $this->EnvironmentManager->saveDatabaseVariables($request);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if(array_key_exists("success", $results)) {
|
||||||
|
Artisan::call('config:clear');
|
||||||
|
Artisan::call('migrate --seed');
|
||||||
|
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']);
|
||||||
|
|
||||||
|
\Storage::disk('local')->put('database_created', 'database_created');
|
||||||
|
|
||||||
|
Setting::setSetting('profile_complete', 3);
|
||||||
|
}
|
||||||
|
return response()->json($results);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'migrate_failed'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param DatabaseEnvironmentRequest $request
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function saveMailEnvironment(MailEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
$results = $this->EnvironmentManager->saveMailVariables($request);
|
||||||
|
|
||||||
|
Setting::setSetting('profile_complete', 4);
|
||||||
|
|
||||||
|
return response()->json($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function getMailDrivers()
|
||||||
|
{
|
||||||
|
$drivers = [
|
||||||
|
'smtp',
|
||||||
|
'mail',
|
||||||
|
'sendmail',
|
||||||
|
'mailgun',
|
||||||
|
'mandrill',
|
||||||
|
'ses',
|
||||||
|
'sparkpost'
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($drivers);
|
||||||
|
}
|
||||||
|
}
|
||||||
463
app/Http/Controllers/EstimatesController.php
Normal file
463
app/Http/Controllers/EstimatesController.php
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Estimate;
|
||||||
|
use Laraspace\EstimateItem;
|
||||||
|
use Laraspace\EstimateTemplate;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Laraspace\Http\Requests\EstimatesRequest;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Validator;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Mail\EstimatePdf;
|
||||||
|
use Laraspace\TaxType;
|
||||||
|
use Laraspace\Tax;
|
||||||
|
|
||||||
|
class EstimatesController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$estimates = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes'
|
||||||
|
])
|
||||||
|
->join('users', 'users.id', '=', 'estimates.user_id')
|
||||||
|
->applyFilters($request->only([
|
||||||
|
'status',
|
||||||
|
'customer_id',
|
||||||
|
'estimate_number',
|
||||||
|
'from_date',
|
||||||
|
'to_date',
|
||||||
|
'search',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy'
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->select('estimates.*', 'users.name')
|
||||||
|
->latest()
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
$siteData = [
|
||||||
|
'estimates' => $estimates,
|
||||||
|
'estimateTotalCount' => Estimate::count()
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($siteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$nextEstimateNumber = 'EST-'.Estimate::getNextEstimateNumber();
|
||||||
|
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
||||||
|
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
||||||
|
$customers = User::where('role', 'customer')->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customers' => $customers,
|
||||||
|
'nextEstimateNumber' => $nextEstimateNumber,
|
||||||
|
'taxes' => Tax::whereCompany($request->header('company'))->latest()->get(),
|
||||||
|
'items' => Item::whereCompany($request->header('company'))->get(),
|
||||||
|
'tax_per_item' => $tax_per_item,
|
||||||
|
'discount_per_item' => $discount_per_item,
|
||||||
|
'estimateTemplates' => EstimateTemplate::all(),
|
||||||
|
'shareable_link' => ''
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(EstimatesRequest $request)
|
||||||
|
{
|
||||||
|
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
||||||
|
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
||||||
|
$status = Estimate::STATUS_DRAFT;
|
||||||
|
$tax_per_item = CompanySetting::getSetting(
|
||||||
|
'tax_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) ? CompanySetting::getSetting(
|
||||||
|
'tax_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) : 'NO';
|
||||||
|
|
||||||
|
if ($request->has('estimateSend')) {
|
||||||
|
$status = Estimate::STATUS_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$discount_per_item = CompanySetting::getSetting(
|
||||||
|
'discount_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) ? CompanySetting::getSetting(
|
||||||
|
'discount_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) : 'NO';
|
||||||
|
|
||||||
|
$estimate = Estimate::create([
|
||||||
|
'estimate_date' => $estimate_date,
|
||||||
|
'expiry_date' => $expiry_date,
|
||||||
|
'estimate_number' => $request->estimate_number,
|
||||||
|
'reference_number' => $request->reference_number,
|
||||||
|
'user_id' => $request->user_id,
|
||||||
|
'company_id' => $request->header('company'),
|
||||||
|
'estimate_template_id' => $request->estimate_template_id,
|
||||||
|
'status' => $status,
|
||||||
|
'discount' => $request->discount,
|
||||||
|
'discount_type' => $request->discount_type,
|
||||||
|
'discount_val' => $request->discount_val,
|
||||||
|
'sub_total' => $request->sub_total,
|
||||||
|
'total' => $request->total,
|
||||||
|
'tax_per_item' => $tax_per_item,
|
||||||
|
'discount_per_item' => $discount_per_item,
|
||||||
|
'tax' => $request->tax,
|
||||||
|
'notes' => $request->notes,
|
||||||
|
'unique_hash' => str_random(60)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$estimateItems = $request->items;
|
||||||
|
|
||||||
|
foreach ($estimateItems as $estimateItem) {
|
||||||
|
$estimateItem['company_id'] = $request->header('company');
|
||||||
|
$item = $estimate->items()->create($estimateItem);
|
||||||
|
|
||||||
|
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
|
||||||
|
foreach ($estimateItem['taxes'] as $tax) {
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
$estimate->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('estimateSend')) {
|
||||||
|
$data['estimate'] = $estimate->toArray();
|
||||||
|
$userId = $data['estimate']['user_id'];
|
||||||
|
$data['user'] = User::find($userId)->toArray();
|
||||||
|
$email = $data['user']['email'];
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$email) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'user_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$notificationEmail) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'notification_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
|
||||||
|
}
|
||||||
|
|
||||||
|
$estimate = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes'
|
||||||
|
])->find($estimate->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'url' => url('/estimates/pdf/'.$estimate->unique_hash),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Request $request, $id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes',
|
||||||
|
'taxes.taxType'
|
||||||
|
])->find($id);
|
||||||
|
|
||||||
|
$siteData = [
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash)
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($siteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Request $request,$id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes',
|
||||||
|
'taxes.taxType'
|
||||||
|
])->find($id);
|
||||||
|
$customers = User::where('role', 'customer')->get();
|
||||||
|
|
||||||
|
return response()->json( [
|
||||||
|
'customers' => $customers,
|
||||||
|
'nextEstimateNumber' => $estimate->estimate_number,
|
||||||
|
'taxes' => Tax::latest()->whereCompany($request->header('company'))->get(),
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'items' => Item::whereCompany($request->header('company'))->latest()->get(),
|
||||||
|
'estimateTemplates' => EstimateTemplate::all(),
|
||||||
|
'tax_per_item' => $estimate->tax_per_item,
|
||||||
|
'discount_per_item' => $estimate->discount_per_item,
|
||||||
|
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(EstimatesRequest $request, $id)
|
||||||
|
{
|
||||||
|
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
||||||
|
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
||||||
|
|
||||||
|
$estimate = Estimate::find($id);
|
||||||
|
$estimate->estimate_date = $estimate_date;
|
||||||
|
$estimate->expiry_date = $expiry_date;
|
||||||
|
$estimate->estimate_number = $request->estimate_number;
|
||||||
|
$estimate->reference_number = $request->reference_number;
|
||||||
|
$estimate->user_id = $request->user_id;
|
||||||
|
$estimate->estimate_template_id = $request->estimate_template_id;
|
||||||
|
$estimate->discount = $request->discount;
|
||||||
|
$estimate->discount_type = $request->discount_type;
|
||||||
|
$estimate->discount_val = $request->discount_val;
|
||||||
|
$estimate->sub_total = $request->sub_total;
|
||||||
|
$estimate->total = $request->total;
|
||||||
|
$estimate->tax = $request->tax;
|
||||||
|
$estimate->notes = $request->notes;
|
||||||
|
$estimate->save();
|
||||||
|
|
||||||
|
$oldItems = $estimate->items->toArray();
|
||||||
|
$oldTaxes = $estimate->taxes->toArray();
|
||||||
|
$estimateItems = $request->items;
|
||||||
|
|
||||||
|
foreach ($oldItems as $oldItem) {
|
||||||
|
EstimateItem::destroy($oldItem['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($oldTaxes as $oldTax) {
|
||||||
|
Tax::destroy($oldTax['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($estimateItems as $estimateItem) {
|
||||||
|
$estimateItem['company_id'] = $request->header('company');
|
||||||
|
$item = $estimate->items()->create($estimateItem);
|
||||||
|
|
||||||
|
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
|
||||||
|
foreach ($estimateItem['taxes'] as $tax) {
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
$estimate->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$estimate = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes'
|
||||||
|
])->find($estimate->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'url' => url('/estimates/pdf/'.$estimate->unique_hash),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
Estimate::deleteEstimate($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendEstimate(Request $request)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::findOrFail($request->id);
|
||||||
|
$estimate->status = Estimate::STATUS_SENT;
|
||||||
|
$estimate->save();
|
||||||
|
|
||||||
|
$data['estimate'] = $estimate->toArray();
|
||||||
|
$userId = $data['estimate']['user_id'];
|
||||||
|
$data['user'] = User::find($userId)->toArray();
|
||||||
|
$email = $data['user']['email'];
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$email) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'user_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$notificationEmail) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'notification_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markEstimateAccepted(Request $request)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::find($request->id);
|
||||||
|
$estimate->status = Estimate::STATUS_ACCEPTED;
|
||||||
|
$estimate->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markEstimateRejected(Request $request)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::find($request->id);
|
||||||
|
$estimate->status = Estimate::STATUS_REJECTED;
|
||||||
|
$estimate->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markEstimateSent(Request $request)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::find($request->id);
|
||||||
|
$estimate->status = Estimate::STATUS_SENT;
|
||||||
|
$estimate->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function estimateToInvoice(Request $request, $id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id);
|
||||||
|
$invoice_date = Carbon::parse($estimate->estimate_date);
|
||||||
|
$due_date = Carbon::parse($estimate->estimate_date)->addDays(7);
|
||||||
|
$tax_per_item = CompanySetting::getSetting(
|
||||||
|
'tax_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) ? CompanySetting::getSetting(
|
||||||
|
'tax_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) : 'NO';
|
||||||
|
$discount_per_item = CompanySetting::getSetting(
|
||||||
|
'discount_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) ? CompanySetting::getSetting(
|
||||||
|
'discount_per_item',
|
||||||
|
$request->header('company')
|
||||||
|
) : 'NO';
|
||||||
|
|
||||||
|
$invoice = Invoice::create([
|
||||||
|
'invoice_date' => $invoice_date,
|
||||||
|
'due_date' => $due_date,
|
||||||
|
'invoice_number' => "INV-".Invoice::getNextInvoiceNumber(),
|
||||||
|
'reference_number' => $estimate->reference_number,
|
||||||
|
'user_id' => $estimate->user_id,
|
||||||
|
'company_id' => $request->header('company'),
|
||||||
|
'invoice_template_id' => 1,
|
||||||
|
'status' => Invoice::STATUS_DRAFT,
|
||||||
|
'paid_status' => Invoice::STATUS_UNPAID,
|
||||||
|
'sub_total' => $estimate->sub_total,
|
||||||
|
'discount' => $estimate->discount,
|
||||||
|
'discount_type' => $estimate->discount_type,
|
||||||
|
'discount_val' => $estimate->discount_val,
|
||||||
|
'total' => $estimate->total,
|
||||||
|
'due_amount' => $estimate->total,
|
||||||
|
'tax_per_item' => $tax_per_item,
|
||||||
|
'discount_per_item' => $discount_per_item,
|
||||||
|
'tax' => $estimate->tax,
|
||||||
|
'notes' => $estimate->notes,
|
||||||
|
'unique_hash' => str_random(60)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoiceItems = $estimate->items->toArray();
|
||||||
|
|
||||||
|
foreach ($invoiceItems as $invoiceItem) {
|
||||||
|
$invoiceItem['company_id'] = $request->header('company');
|
||||||
|
$invoiceItem['name'] = $invoiceItem['name'];
|
||||||
|
$item = $invoice->items()->create($invoiceItem);
|
||||||
|
|
||||||
|
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||||
|
foreach ($invoiceItem['taxes'] as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($estimate->taxes) {
|
||||||
|
foreach ($estimate->taxes->toArray() as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
$invoice->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::with([
|
||||||
|
'items',
|
||||||
|
'user',
|
||||||
|
'invoiceTemplate',
|
||||||
|
'taxes'
|
||||||
|
])->find($invoice->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'invoice' => $invoice
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
foreach ($request->id as $id) {
|
||||||
|
Estimate::deleteEstimate($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
122
app/Http/Controllers/ExpenseCategoryController.php
Normal file
122
app/Http/Controllers/ExpenseCategoryController.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Laraspace\ExpenseCategory;
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Http\Requests\ExpenseCategoryRequest;
|
||||||
|
|
||||||
|
class ExpenseCategoryController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'categories' => $categories
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
// return view('app.categories.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(ExpenseCategoryRequest $request)
|
||||||
|
{
|
||||||
|
$category = new ExpenseCategory();
|
||||||
|
$category->name = $request->name;
|
||||||
|
$category->description = $request->description;
|
||||||
|
$category->company_id = $request->header('company');
|
||||||
|
$category->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'category' => $category,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\ExpenseCategory $ExpenseCategory
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(ExpenseCategory $ExpenseCategory)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\ExpensesCategory $ExpensesCategory
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$category = ExpenseCategory::findOrFail($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'category' => $category
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Laraspace\ExpenseCategory $ExpenseCategory
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(ExpenseCategoryRequest $request, $id)
|
||||||
|
{
|
||||||
|
$category = ExpenseCategory::findOrFail($id);
|
||||||
|
$category->name = $request->name;
|
||||||
|
$category->description = $request->description;
|
||||||
|
$category->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'category' => $category,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\ExpensesCategory $expensesCategory
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$category = ExpenseCategory::find($id);
|
||||||
|
if ($category->expenses() && $category->expenses()->count() > 0) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$category->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
260
app/Http/Controllers/ExpensesController.php
Normal file
260
app/Http/Controllers/ExpensesController.php
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\ExpenseCategory;
|
||||||
|
use Laraspace\Http\Requests\ExpenseRequest;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Intervention\Image\Facades\Image;
|
||||||
|
|
||||||
|
class ExpensesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$expenses = Expense::with('category')
|
||||||
|
->join('expense_categories', 'expense_categories.id', '=', 'expenses.expense_category_id')
|
||||||
|
->applyFilters($request->only([
|
||||||
|
'expense_category_id',
|
||||||
|
'search',
|
||||||
|
'from_date',
|
||||||
|
'to_date',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy'
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->select('expenses.*', 'expense_categories.name')
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'expenses' => $expenses,
|
||||||
|
'currency' => Currency::findOrFail(
|
||||||
|
CompanySetting::getSetting('currency', $request->header('company'))
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'categories' => $categories
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(ExpenseRequest $request)
|
||||||
|
{
|
||||||
|
$expense_date = Carbon::createFromFormat('d/m/Y', $request->expense_date);
|
||||||
|
|
||||||
|
$expense = new Expense();
|
||||||
|
$expense->notes = $request->notes;
|
||||||
|
$expense->expense_category_id = $request->expense_category_id;
|
||||||
|
$expense->amount = $request->amount;
|
||||||
|
$expense->company_id = $request->header('company');
|
||||||
|
$expense->expense_date = $expense_date;
|
||||||
|
$expense->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('attachment_receipt')) {
|
||||||
|
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'expense' => $expense,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\Expense $expense
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(Expense $expense)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(Request $request,$id)
|
||||||
|
{
|
||||||
|
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||||
|
$customers = User::where('role', 'customer')->whereCompany($request->header('company'))->get();
|
||||||
|
$expense = Expense::with('category')->where('id', $id)->first();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'categories' => $categories,
|
||||||
|
'customers' => $customers,
|
||||||
|
'expense' => $expense
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Laraspace\Expense $expense
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(ExpenseRequest $request, Expense $expense)
|
||||||
|
{
|
||||||
|
$expense_date = Carbon::createFromFormat('d/m/Y', $request->expense_date);
|
||||||
|
|
||||||
|
$expense = Expense::findOrFail($expense->id);
|
||||||
|
$expense->notes = $request->notes;
|
||||||
|
$expense->expense_category_id = $request->expense_category_id;
|
||||||
|
$expense->amount = $request->amount;
|
||||||
|
$expense->expense_date = $expense_date;
|
||||||
|
$expense->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('attachment_receipt')) {
|
||||||
|
$expense->clearMediaCollection('receipts');
|
||||||
|
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'expense' => $expense,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\Expense $expense
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Expense $expense)
|
||||||
|
{
|
||||||
|
$expense->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
Expense::destroy($request->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the expense receipts to storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function uploadReceipts(Request $request, $id)
|
||||||
|
{
|
||||||
|
$data = json_decode($request->attachment_receipt);
|
||||||
|
|
||||||
|
if($data) {
|
||||||
|
$expense = Expense::find($id);
|
||||||
|
|
||||||
|
if($expense) {
|
||||||
|
if($request->type === 'edit') {
|
||||||
|
$expense->clearMediaCollection('receipts');
|
||||||
|
}
|
||||||
|
|
||||||
|
$expense->addMediaFromBase64($data->data)
|
||||||
|
->usingFileName($data->name)
|
||||||
|
->toMediaCollection('receipts', 'local');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => 'Expense receipts uploaded successfully'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showReceipt($id)
|
||||||
|
{
|
||||||
|
$expense = Expense::find($id);
|
||||||
|
$imagePath = null;
|
||||||
|
|
||||||
|
if($expense) {
|
||||||
|
$media = $expense->getFirstMedia('receipts');
|
||||||
|
if($media) {
|
||||||
|
$imagePath = $media->getPath();
|
||||||
|
} else {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'receipt_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = \File::mimeType($imagePath);
|
||||||
|
|
||||||
|
$image = 'data:'.$type.';base64,'.base64_encode(file_get_contents($imagePath));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'image' => $image,
|
||||||
|
'type' => $type
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function downloadReceipt($id, $hash)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$expense = Expense::whereCompany($company->id)
|
||||||
|
->where('id', $id)
|
||||||
|
->first();
|
||||||
|
$imagePath = null;
|
||||||
|
|
||||||
|
if($expense) {
|
||||||
|
$media = $expense->getFirstMedia('receipts');
|
||||||
|
if($media) {
|
||||||
|
$imagePath = $media->getPath();
|
||||||
|
$filename = $media->getPath();
|
||||||
|
$type = \File::mimeType($imagePath);
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
'Content-Type' => $type,
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = \Response::download($imagePath, $media->file_name);
|
||||||
|
ob_end_clean();
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'receipt_not_found'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
381
app/Http/Controllers/FrontendController.php
Normal file
381
app/Http/Controllers/FrontendController.php
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\Payment;
|
||||||
|
use Laraspace\PdfSetting;
|
||||||
|
use PDF;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Estimate;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\InvoiceTemplate;
|
||||||
|
use Laraspace\EstimateTemplate;
|
||||||
|
use Auth;
|
||||||
|
use Laraspace\Mail\EstimateViewed;
|
||||||
|
use Laraspace\Mail\InvoiceViewed;
|
||||||
|
|
||||||
|
class FrontendController extends Controller
|
||||||
|
{
|
||||||
|
public function home()
|
||||||
|
{
|
||||||
|
return view('front.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomerEstimatePdf($id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::with(
|
||||||
|
'user',
|
||||||
|
'items',
|
||||||
|
'user.billingAddress',
|
||||||
|
'user.shippingAddress'
|
||||||
|
)
|
||||||
|
->where('unique_hash', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$taxTypes = [];
|
||||||
|
$taxes = [];
|
||||||
|
$labels = [];
|
||||||
|
|
||||||
|
if ($estimate->tax_per_item === 'YES') {
|
||||||
|
foreach ($estimate->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if (!in_array($tax->name, $taxTypes)) {
|
||||||
|
array_push($taxTypes, $tax->name);
|
||||||
|
array_push($labels, $tax->name.' ('.$tax->percent.'%)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($taxTypes as $taxType) {
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach ($estimate->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if($tax->name == $taxType) {
|
||||||
|
$total += $tax->amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($taxes, $total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$estimateTemplate = EstimateTemplate::find($estimate->estimate_template_id);
|
||||||
|
|
||||||
|
$company = Company::find($estimate->company_id);
|
||||||
|
|
||||||
|
$logo = $company->getMedia('logo')->first();
|
||||||
|
|
||||||
|
if($logo) {
|
||||||
|
$logo = $logo->getFullUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($estimate && ($estimate->status == Estimate::STATUS_SENT || $estimate->status == Estimate::STATUS_DRAFT)) {
|
||||||
|
$estimate->status = Estimate::STATUS_VIEWED;
|
||||||
|
$estimate->save();
|
||||||
|
$notifyEstimateViewed = CompanySetting::getSetting(
|
||||||
|
'notify_estimate_viewed',
|
||||||
|
$estimate->company_id
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($notifyEstimateViewed == 'YES') {
|
||||||
|
$data['estimate'] = Estimate::findOrFail($estimate->id)->toArray();
|
||||||
|
$data['user'] = User::find($estimate->user_id)->toArray();
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$estimate->company_id
|
||||||
|
);
|
||||||
|
|
||||||
|
\Mail::to($notificationEmail)->send(new EstimateViewed($data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'invoice_primary_color',
|
||||||
|
'invoice_column_heading',
|
||||||
|
'invoice_field_label',
|
||||||
|
'invoice_field_value',
|
||||||
|
'invoice_body_text',
|
||||||
|
'invoice_description_text',
|
||||||
|
'invoice_border_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($estimate->company_id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'logo' => $logo ?? null,
|
||||||
|
'company_address' => $companyAddress,
|
||||||
|
'colors' => $colorSettings,
|
||||||
|
'labels' => $labels,
|
||||||
|
'taxes' => $taxes
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view);
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomerInvoicePdf($id)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'invoiceTemplate',
|
||||||
|
'taxes'
|
||||||
|
])
|
||||||
|
->where('unique_hash', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$taxTypes = [];
|
||||||
|
$taxes = [];
|
||||||
|
$labels = [];
|
||||||
|
|
||||||
|
if ($invoice->tax_per_item === 'YES') {
|
||||||
|
foreach ($invoice->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if (!in_array($tax->name, $labels)) {
|
||||||
|
array_push($taxTypes, $tax->name);
|
||||||
|
array_push($labels, $tax->name.' ('.$tax->percent.'%)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($taxTypes as $taxType) {
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach ($invoice->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if($tax->name == $taxType) {
|
||||||
|
$total += $tax->amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($taxes, $total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceTemplate = InvoiceTemplate::find($invoice->invoice_template_id);
|
||||||
|
|
||||||
|
$company = Company::find($invoice->company_id);
|
||||||
|
$logo = $company->getMedia('logo')->first();
|
||||||
|
|
||||||
|
if($logo) {
|
||||||
|
$logo = $logo->getFullUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invoice && ($invoice->status == Invoice::STATUS_SENT || $invoice->status == Invoice::STATUS_DRAFT)) {
|
||||||
|
$invoice->status = Invoice::STATUS_VIEWED;
|
||||||
|
$invoice->viewed = true;
|
||||||
|
$invoice->save();
|
||||||
|
$notifyInvoiceViewed = CompanySetting::getSetting(
|
||||||
|
'notify_invoice_viewed',
|
||||||
|
$invoice->company_id
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($notifyInvoiceViewed == 'YES') {
|
||||||
|
$data['invoice'] = Invoice::findOrFail($invoice->id)->toArray();
|
||||||
|
$data['user'] = User::find($invoice->user_id)->toArray();
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$invoice->company_id
|
||||||
|
);
|
||||||
|
|
||||||
|
\Mail::to($notificationEmail)->send(new InvoiceViewed($data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'invoice_primary_color',
|
||||||
|
'invoice_column_heading',
|
||||||
|
'invoice_field_label',
|
||||||
|
'invoice_field_value',
|
||||||
|
'invoice_body_text',
|
||||||
|
'invoice_description_text',
|
||||||
|
'invoice_border_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($invoice->company_id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'colors' => $colorSettings,
|
||||||
|
'company_address' => $companyAddress,
|
||||||
|
'logo' => $logo ?? null,
|
||||||
|
'labels' => $labels,
|
||||||
|
'taxes' => $taxes
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view);
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEstimatePdf($id)
|
||||||
|
{
|
||||||
|
$estimate = Estimate::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'estimateTemplate',
|
||||||
|
'taxes',
|
||||||
|
'taxes.taxType'
|
||||||
|
])
|
||||||
|
->where('unique_hash', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$taxTypes = [];
|
||||||
|
$taxes = [];
|
||||||
|
$labels = [];
|
||||||
|
|
||||||
|
if ($estimate->tax_per_item === 'YES') {
|
||||||
|
foreach ($estimate->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if (!in_array($tax->name, $taxTypes)) {
|
||||||
|
array_push($taxTypes, $tax->name);
|
||||||
|
array_push($labels, $tax->name.' ('.$tax->percent.'%)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($taxTypes as $taxType) {
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach ($estimate->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if($tax->name == $taxType) {
|
||||||
|
$total += $tax->amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($taxes, $total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$estimateTemplate = EstimateTemplate::find($estimate->estimate_template_id);
|
||||||
|
|
||||||
|
$company = Company::find($estimate->company_id);
|
||||||
|
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||||
|
$logo = $company->getMedia('logo')->first();
|
||||||
|
|
||||||
|
if($logo) {
|
||||||
|
$logo = $logo->getFullUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'invoice_primary_color',
|
||||||
|
'invoice_column_heading',
|
||||||
|
'invoice_field_label',
|
||||||
|
'invoice_field_value',
|
||||||
|
'invoice_body_text',
|
||||||
|
'invoice_description_text',
|
||||||
|
'invoice_border_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($estimate->company_id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'estimate' => $estimate,
|
||||||
|
'logo' => $logo ?? null,
|
||||||
|
'company_address' => $companyAddress,
|
||||||
|
'colors' => $colorSettings,
|
||||||
|
'labels' => $labels,
|
||||||
|
'taxes' => $taxes
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view);
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvoicePdf($id)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'invoiceTemplate',
|
||||||
|
'taxes'
|
||||||
|
])
|
||||||
|
->where('unique_hash', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$taxTypes = [];
|
||||||
|
$taxes = [];
|
||||||
|
$labels = [];
|
||||||
|
|
||||||
|
if ($invoice->tax_per_item === 'YES') {
|
||||||
|
foreach ($invoice->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if (!in_array($tax->name, $taxTypes)) {
|
||||||
|
array_push($taxTypes, $tax->name);
|
||||||
|
array_push($labels, $tax->name.' ('.$tax->percent.'%)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($taxTypes as $taxType) {
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach ($invoice->items as $item) {
|
||||||
|
foreach ($item->taxes as $tax) {
|
||||||
|
if($tax->name == $taxType) {
|
||||||
|
$total += $tax->amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($taxes, $total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceTemplate = InvoiceTemplate::find($invoice->invoice_template_id);
|
||||||
|
$company = Company::find($invoice->company_id);
|
||||||
|
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||||
|
|
||||||
|
$logo = $company->getMedia('logo')->first();
|
||||||
|
|
||||||
|
if($logo) {
|
||||||
|
$logo = $logo->getFullUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'invoice_primary_color',
|
||||||
|
'invoice_column_heading',
|
||||||
|
'invoice_field_label',
|
||||||
|
'invoice_field_value',
|
||||||
|
'invoice_body_text',
|
||||||
|
'invoice_description_text',
|
||||||
|
'invoice_border_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($invoice->company_id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'company_address' => $companyAddress,
|
||||||
|
'logo' => $logo ?? null,
|
||||||
|
'colors' => $colorSettings,
|
||||||
|
'labels' => $labels,
|
||||||
|
'taxes' => $taxes
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view);
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
}
|
||||||
443
app/Http/Controllers/InvoicesController.php
Normal file
443
app/Http/Controllers/InvoicesController.php
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\InvoiceTemplate;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\InvoiceItem;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Laraspace\Mail\invoicePdf;
|
||||||
|
use function MongoDB\BSON\toJSON;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Mailgun\Mailgun;
|
||||||
|
use PDF;
|
||||||
|
use Validator;
|
||||||
|
use Laraspace\TaxType;
|
||||||
|
use Laraspace\Tax;
|
||||||
|
|
||||||
|
class InvoicesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$invoices = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])
|
||||||
|
->join('users', 'users.id', '=', 'invoices.user_id')
|
||||||
|
->applyFilters($request->only([
|
||||||
|
'status',
|
||||||
|
'paid_status',
|
||||||
|
'customer_id',
|
||||||
|
'invoice_number',
|
||||||
|
'from_date',
|
||||||
|
'to_date',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy',
|
||||||
|
'search',
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->select('invoices.*', 'users.name')
|
||||||
|
->latest()
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'invoices' => $invoices,
|
||||||
|
'invoiceTotalCount' => Invoice::count()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
||||||
|
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
||||||
|
$nextInvoiceNumber = "INV-".Invoice::getNextInvoiceNumber();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'nextInvoiceNumber' => $nextInvoiceNumber,
|
||||||
|
'items' => Item::with('taxes')->whereCompany($request->header('company'))->get(),
|
||||||
|
'invoiceTemplates' => InvoiceTemplate::all(),
|
||||||
|
'tax_per_item' => $tax_per_item,
|
||||||
|
'discount_per_item' => $discount_per_item
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(Requests\InvoicesRequest $request)
|
||||||
|
{
|
||||||
|
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||||
|
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||||
|
$status = Invoice::STATUS_DRAFT;
|
||||||
|
|
||||||
|
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company')) ?? 'NO';
|
||||||
|
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company')) ?? 'NO';
|
||||||
|
|
||||||
|
if ($request->has('invoiceSend')) {
|
||||||
|
$status = Invoice::STATUS_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::create([
|
||||||
|
'invoice_date' => $invoice_date,
|
||||||
|
'due_date' => $due_date,
|
||||||
|
'invoice_number' => $request->invoice_number,
|
||||||
|
'reference_number' => $request->reference_number,
|
||||||
|
'user_id' => $request->user_id,
|
||||||
|
'company_id' => $request->header('company'),
|
||||||
|
'invoice_template_id' => $request->invoice_template_id,
|
||||||
|
'status' => $status,
|
||||||
|
'paid_status' => Invoice::STATUS_UNPAID,
|
||||||
|
'sub_total' => $request->sub_total,
|
||||||
|
'discount' => $request->discount,
|
||||||
|
'discount_type' => $request->discount_type,
|
||||||
|
'discount_val' => $request->discount_val,
|
||||||
|
'total' => $request->total,
|
||||||
|
'due_amount' => $request->total,
|
||||||
|
'tax_per_item' => $tax_per_item,
|
||||||
|
'discount_per_item' => $discount_per_item,
|
||||||
|
'tax' => $request->tax,
|
||||||
|
'notes' => $request->notes,
|
||||||
|
'unique_hash' => str_random(60)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoiceItems = $request->items;
|
||||||
|
|
||||||
|
foreach ($invoiceItems as $invoiceItem) {
|
||||||
|
$invoiceItem['company_id'] = $request->header('company');
|
||||||
|
$item = $invoice->items()->create($invoiceItem);
|
||||||
|
|
||||||
|
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||||
|
foreach ($invoiceItem['taxes'] as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$invoice->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('invoiceSend')) {
|
||||||
|
$data['invoice'] = Invoice::findOrFail($invoice->id)->toArray();
|
||||||
|
$data['user'] = User::find($request->user_id)->toArray();
|
||||||
|
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
$email = $data['user']['email'];
|
||||||
|
|
||||||
|
if (!$email) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'user_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$notificationEmail) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'notification_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'url' => url('/invoices/pdf/'.$invoice->unique_hash),
|
||||||
|
'invoice' => $invoice
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(Request $request, $id)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'invoiceTemplate',
|
||||||
|
'taxes.taxType'
|
||||||
|
])->find($id);
|
||||||
|
|
||||||
|
$siteData = [
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'shareable_link' => url('/invoices/pdf/' . $invoice->unique_hash)
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($siteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(Request $request,$id)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::with([
|
||||||
|
'items',
|
||||||
|
'items.taxes',
|
||||||
|
'user',
|
||||||
|
'invoiceTemplate',
|
||||||
|
'taxes.taxType'
|
||||||
|
])->find($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'nextInvoiceNumber' => $invoice->invoice_number,
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'invoiceTemplates' => InvoiceTemplate::all(),
|
||||||
|
'tax_per_item' => $invoice->tax_per_item,
|
||||||
|
'discount_per_item' => $invoice->discount_per_item,
|
||||||
|
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(Requests\InvoicesRequest $request, $id)
|
||||||
|
{
|
||||||
|
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||||
|
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||||
|
|
||||||
|
$invoice = Invoice::find($id);
|
||||||
|
$oldAmount = $invoice->total;
|
||||||
|
|
||||||
|
if ($oldAmount != $request->total) {
|
||||||
|
$oldAmount = (int)round($request->total) - (int)$oldAmount;
|
||||||
|
} else {
|
||||||
|
$oldAmount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->due_amount = ($invoice->due_amount + $oldAmount);
|
||||||
|
|
||||||
|
if ($invoice->due_amount == 0 && $invoice->paid_status != Invoice::STATUS_PAID) {
|
||||||
|
$invoice->status = Invoice::STATUS_COMPLETED;
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PAID;
|
||||||
|
} elseif ($invoice->due_amount < 0 && $invoice->paid_status != Invoice::STATUS_UNPAID) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'invalid_due_amount'
|
||||||
|
]);
|
||||||
|
} elseif ($invoice->due_amount != 0 && $invoice->paid_status == Invoice::STATUS_PAID) {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->invoice_date = $invoice_date;
|
||||||
|
$invoice->due_date = $due_date;
|
||||||
|
$invoice->invoice_number = $request->invoice_number;
|
||||||
|
$invoice->reference_number = $request->reference_number;
|
||||||
|
$invoice->user_id = $request->user_id;
|
||||||
|
$invoice->invoice_template_id = $request->invoice_template_id;
|
||||||
|
$invoice->sub_total = $request->sub_total;
|
||||||
|
$invoice->total = $request->total;
|
||||||
|
$invoice->discount = $request->discount;
|
||||||
|
$invoice->discount_type = $request->discount_type;
|
||||||
|
$invoice->discount_val = $request->discount_val;
|
||||||
|
$invoice->tax = $request->tax;
|
||||||
|
$invoice->notes = $request->notes;
|
||||||
|
$invoice->save();
|
||||||
|
|
||||||
|
$oldItems = $invoice->items->toArray();
|
||||||
|
$oldTaxes = $invoice->taxes->toArray();
|
||||||
|
$invoiceItems = $request->items;
|
||||||
|
|
||||||
|
foreach ($oldItems as $oldItem) {
|
||||||
|
InvoiceItem::destroy($oldItem['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($oldTaxes as $oldTax) {
|
||||||
|
Tax::destroy($oldTax['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($invoiceItems as $invoiceItem) {
|
||||||
|
$invoiceItem['company_id'] = $request->header('company');
|
||||||
|
$item = $invoice->items()->create($invoiceItem);
|
||||||
|
|
||||||
|
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||||
|
foreach ($invoiceItem['taxes'] as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
$tax['company_id'] = $request->header('company');
|
||||||
|
|
||||||
|
if ($tax['amount']) {
|
||||||
|
$invoice->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'url' => url('/invoices/pdf/' . $invoice->unique_hash),
|
||||||
|
'invoice' => $invoice,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::find($id);
|
||||||
|
|
||||||
|
if ($invoice->payments()->exists() && $invoice->payments()->count() > 0) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'payment_attached'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::destroy($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
foreach ($request->id as $id) {
|
||||||
|
$invoice = Invoice::find($id);
|
||||||
|
|
||||||
|
if ($invoice->payments()->exists() && $invoice->payments()->count() > 0) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'payment_attached'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice = Invoice::destroy($request->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendInvoice(Request $request)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::findOrFail($request->id);
|
||||||
|
|
||||||
|
if ($invoice->status == Invoice::STATUS_DRAFT) {
|
||||||
|
$invoice->status = Invoice::STATUS_SENT;
|
||||||
|
$invoice->sent = true;
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['invoice'] = $invoice->toArray();
|
||||||
|
$userId = $data['invoice']['user_id'];
|
||||||
|
$data['user'] = User::find($userId)->toArray();
|
||||||
|
$email = $data['user']['email'];
|
||||||
|
$notificationEmail = CompanySetting::getSetting(
|
||||||
|
'notification_email',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$email) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'user_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$notificationEmail) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'notification_email_does_not_exist'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markAsSent(Request $request)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::findOrFail($request->id);
|
||||||
|
$invoice->status = Invoice::STATUS_SENT;
|
||||||
|
$invoice->sent = true;
|
||||||
|
$invoice->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markAsPaid(Request $request)
|
||||||
|
{
|
||||||
|
$invoice = Invoice::findOrFail($request->id);
|
||||||
|
$invoice->status = Invoice::STATUS_COMPLETED;
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PAID;
|
||||||
|
$invoice->due_amount = 0;
|
||||||
|
$invoice->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomersUnpaidInvoices(Request $request, $id)
|
||||||
|
{
|
||||||
|
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
|
||||||
|
->where('user_id', $id)->where('due_amount', '>', 0)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'invoices' => $invoices
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
129
app/Http/Controllers/ItemsController.php
Normal file
129
app/Http/Controllers/ItemsController.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Laraspace\TaxType;
|
||||||
|
use Laraspace\Tax;
|
||||||
|
use Laraspace\User;
|
||||||
|
|
||||||
|
class ItemsController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$items = Item::applyFilters($request->only([
|
||||||
|
'search',
|
||||||
|
'price',
|
||||||
|
'unit',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy'
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->latest()
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'items' => $items,
|
||||||
|
'taxTypes' => TaxType::latest()->get()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Request $request, $id)
|
||||||
|
{
|
||||||
|
$item = Item::with('taxes')->find($id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'item' => $item,
|
||||||
|
'taxes' => Tax::whereCompany($request->header('company'))
|
||||||
|
->latest()
|
||||||
|
->get()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Requests\ItemsRequest $request)
|
||||||
|
{
|
||||||
|
$item = new Item();
|
||||||
|
$item->name = $request->name;
|
||||||
|
$item->unit = $request->unit;
|
||||||
|
$item->description = $request->description;
|
||||||
|
$item->company_id = $request->header('company');
|
||||||
|
$item->price = $request->price;
|
||||||
|
$item->save();
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
$item->taxes()->create($tax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = Item::with('taxes')->find($item->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'item' => $item
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Requests\ItemsRequest $request, $id)
|
||||||
|
{
|
||||||
|
$item = Item::find($id);
|
||||||
|
$item->name = $request->name;
|
||||||
|
$item->unit = $request->unit;
|
||||||
|
$item->description = $request->description;
|
||||||
|
$item->price = $request->price;
|
||||||
|
$item->save();
|
||||||
|
|
||||||
|
if ($request->has('taxes')) {
|
||||||
|
foreach ($request->taxes as $tax) {
|
||||||
|
$item->taxes()->updateOrCreate(
|
||||||
|
['tax_type_id' => $tax['tax_type_id']],
|
||||||
|
['amount' => $tax['amount'], 'percent' => $tax['percent'], 'percent' => $tax['name']]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = Item::with('taxes')->find($item->id);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'item' => $item
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$data = Item::deleteItem($id);
|
||||||
|
|
||||||
|
if (!$data) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'item_attached'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => $data
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
foreach ($request->id as $id) {
|
||||||
|
$item = Item::deleteItem($id);
|
||||||
|
if (!$item) {
|
||||||
|
array_push($items, $id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($items)) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'items' => $items
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Controllers/LocationController.php
Normal file
31
app/Http/Controllers/LocationController.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Country;
|
||||||
|
use Laraspace\State;
|
||||||
|
use Laraspace\City;
|
||||||
|
|
||||||
|
class LocationController extends Controller
|
||||||
|
{
|
||||||
|
public function getCountries()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'countries' => Country::all()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStates($id)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'states' => Country::find($id)->states
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCities($id)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'cities' => State::find($id)->cities
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
224
app/Http/Controllers/OnboardingController.php
Normal file
224
app/Http/Controllers/OnboardingController.php
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\Address;
|
||||||
|
use Laraspace\Http\Requests\ProfileRequest;
|
||||||
|
use Laraspace\Http\Requests\CompanyRequest;
|
||||||
|
use Laraspace\Http\Requests\CompanySettingRequest;
|
||||||
|
use Laraspace\Space\DateFormatter;
|
||||||
|
use Laraspace\Space\TimeZones;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
|
class OnboardingController extends Controller
|
||||||
|
{
|
||||||
|
public function getOnboardingData(Request $request)
|
||||||
|
{
|
||||||
|
if (!\Storage::disk('local')->has('database_created')) {
|
||||||
|
return response()->json([
|
||||||
|
'profile_complete' => '0'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$setting = Setting::getSetting('profile_complete');
|
||||||
|
|
||||||
|
if ($setting !== 'COMPLETED' && $setting < 4){
|
||||||
|
return response()->json([
|
||||||
|
'profile_complete' => $setting
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$date_formats = DateFormatter::get_list();
|
||||||
|
$time_zones = TimeZones::get_list();
|
||||||
|
$languages = [
|
||||||
|
["code"=>"en", "name" => "English"],
|
||||||
|
["code"=>"de", "name" => "German"],
|
||||||
|
];
|
||||||
|
$fiscal_years = [
|
||||||
|
['key' => 'january-december' , 'value' => '1-12'],
|
||||||
|
['key' => 'february-january' , 'value' => '2-1'],
|
||||||
|
['key' => 'march-february' , 'value' => '3-2'],
|
||||||
|
['key' => 'april-march' , 'value' => '4-3'],
|
||||||
|
['key' => 'may-april' , 'value' => '5-4'],
|
||||||
|
['key' => 'june-may' , 'value' => '6-5'],
|
||||||
|
['key' => 'july-june' , 'value' => '7-6'],
|
||||||
|
['key' => 'august-july' , 'value' => '8-7'],
|
||||||
|
['key' => 'september-august' , 'value' => '9-8'],
|
||||||
|
['key' => 'october-september', 'value' => '10-9'],
|
||||||
|
['key' => 'november-october' , 'value' => '11-10'],
|
||||||
|
['key' => 'december-november', 'value' => '12-11'],
|
||||||
|
];
|
||||||
|
$user = User::with([
|
||||||
|
'addresses',
|
||||||
|
'addresses.country',
|
||||||
|
'addresses.state',
|
||||||
|
'addresses.city',
|
||||||
|
'company'
|
||||||
|
])->find(1);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'profile_complete' => $setting,
|
||||||
|
'languages' => $languages,
|
||||||
|
'date_formats' => $date_formats,
|
||||||
|
'time_zones' => $time_zones,
|
||||||
|
'fiscal_years' => $fiscal_years,
|
||||||
|
'currencies' => Currency::all()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function adminProfile(ProfileRequest $request)
|
||||||
|
{
|
||||||
|
$setting = Setting::getSetting('profile_complete');
|
||||||
|
|
||||||
|
if ($setting == '1' || $setting == 'COMPLETED') {
|
||||||
|
return response()->json(['error' => 'Profile already created.']);
|
||||||
|
} else {
|
||||||
|
Setting::setSetting('profile_complete', 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
$user->name = $request->name;
|
||||||
|
$user->email = $request->email;
|
||||||
|
|
||||||
|
if ($request->has('password')) {
|
||||||
|
$user->password = bcrypt($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function adminCompany(CompanyRequest $request)
|
||||||
|
{
|
||||||
|
$setting = Setting::getSetting('profile_complete');
|
||||||
|
|
||||||
|
if ($setting == '6' || $setting == 'COMPLETED') {
|
||||||
|
return response()->json(['error' => 'Company already created.']);
|
||||||
|
} else {
|
||||||
|
Setting::setSetting('profile_complete', 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
$company = $user->company;
|
||||||
|
|
||||||
|
if (!$company) {
|
||||||
|
$company = new Company();
|
||||||
|
}
|
||||||
|
|
||||||
|
$company->name = $request->name;
|
||||||
|
$company->unique_hash = str_random(60);
|
||||||
|
$company->save();
|
||||||
|
$user->company()->associate($company);
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
if ($request->has('logo') && $request->logo !== null && $request->logo !== 'undefined' ) {
|
||||||
|
$company->addMediaFromRequest('logo')->toMediaCollection('logo');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = $request->only([
|
||||||
|
'address_street_1',
|
||||||
|
'address_street_2',
|
||||||
|
'city_id',
|
||||||
|
'state_id',
|
||||||
|
'country_id',
|
||||||
|
'zip',
|
||||||
|
'phone'
|
||||||
|
]);
|
||||||
|
$address = Address::updateOrCreate(['user_id' => 1], $fields);
|
||||||
|
$user = User::with('addresses', 'company')->find(1);
|
||||||
|
|
||||||
|
CompanySetting::setSetting(
|
||||||
|
'notification_email',
|
||||||
|
$user->email,
|
||||||
|
$company->id
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function companySettings(CompanySettingRequest $request)
|
||||||
|
{
|
||||||
|
$setting = Setting::getSetting('profile_complete');
|
||||||
|
|
||||||
|
if($setting == 'COMPLETED') {
|
||||||
|
return response()->json(['error' => 'Settings already saved.']);
|
||||||
|
} else {
|
||||||
|
Setting::setSetting('profile_complete', 'COMPLETED');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::find(1);
|
||||||
|
|
||||||
|
$sets = ['currency',
|
||||||
|
'time_zone',
|
||||||
|
'language',
|
||||||
|
'carbon_date_format',
|
||||||
|
'moment_date_format',
|
||||||
|
'fiscal_year'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($sets as $key) {
|
||||||
|
CompanySetting::setSetting(
|
||||||
|
$key,
|
||||||
|
$request->$key,
|
||||||
|
$user->company_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color' => '#5851D8',
|
||||||
|
'heading_text_color' => '#595959',
|
||||||
|
'section_heading_text_color' => '#040405',
|
||||||
|
'border_color' => '#EAF1FB',
|
||||||
|
'body_text_color' => '#595959',
|
||||||
|
'footer_text_color' => '#595959',
|
||||||
|
'footer_total_color' => '#5851D8',
|
||||||
|
'footer_bg_color' => '#F9FBFF',
|
||||||
|
'date_text_color' => '#A5ACC1',
|
||||||
|
'invoice_primary_color' => '#5851D8',
|
||||||
|
'invoice_column_heading' => '#55547A',
|
||||||
|
'invoice_field_label' => '#55547A',
|
||||||
|
'invoice_field_value' => '#040405',
|
||||||
|
'invoice_body_text' => '#040405',
|
||||||
|
'invoice_description_text' => '#595959',
|
||||||
|
'invoice_border_color' => '#EAF1FB'
|
||||||
|
];
|
||||||
|
foreach ($colors as $key => $value) {
|
||||||
|
CompanySetting::setSetting(
|
||||||
|
$key,
|
||||||
|
$value,
|
||||||
|
$user->company_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting::setSetting('version','1.0.0');
|
||||||
|
|
||||||
|
Artisan::call('passport:install --force');
|
||||||
|
|
||||||
|
$client = DB::table('oauth_clients')->find(2);
|
||||||
|
|
||||||
|
$path = base_path('.env');
|
||||||
|
|
||||||
|
if (file_exists($path)) {
|
||||||
|
file_put_contents($path, str_replace(
|
||||||
|
'PROXY_OAUTH_CLIENT_SECRET='.config('auth.proxy.client_secret'), 'PROXY_OAUTH_CLIENT_SECRET='.$client->secret, file_get_contents($path)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['token'] = $user->createToken('password')->accessToken;
|
||||||
|
|
||||||
|
return response()->json($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
269
app/Http/Controllers/PaymentController.php
Normal file
269
app/Http/Controllers/PaymentController.php
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\Payment;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use function MongoDB\BSON\toJSON;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Http\Requests\PaymentRequest;
|
||||||
|
|
||||||
|
class PaymentController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
|
$payments = Payment::with('user', 'invoice')
|
||||||
|
->join('users', 'users.id', '=', 'payments.user_id')
|
||||||
|
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
||||||
|
->applyFilters($request->only([
|
||||||
|
'search',
|
||||||
|
'payment_number',
|
||||||
|
'payment_mode',
|
||||||
|
'customer_id',
|
||||||
|
'orderByField',
|
||||||
|
'orderBy'
|
||||||
|
]))
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->select('payments.*', 'users.name', 'invoices.invoice_number')
|
||||||
|
->latest()
|
||||||
|
->paginate($limit);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'payments' => $payments
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$nextPaymentNumber = 'PAY-'.Payment::getNextPaymentNumber();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customers' => User::where('role', 'customer')
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->get(),
|
||||||
|
'nextPaymentNumber' => $nextPaymentNumber
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(PaymentRequest $request)
|
||||||
|
{
|
||||||
|
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||||
|
|
||||||
|
if ($request->has('invoice_id') && $request->invoice_id != null) {
|
||||||
|
$invoice = Invoice::find($request->invoice_id);
|
||||||
|
if ($invoice && $invoice->due_amount == $request->amount) {
|
||||||
|
$invoice->status = Invoice::STATUS_COMPLETED;
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PAID;
|
||||||
|
$invoice->due_amount = 0;
|
||||||
|
} elseif ($invoice && $invoice->due_amount != $request->amount) {
|
||||||
|
$invoice->due_amount = (int)$invoice->due_amount - (int)$request->amount;
|
||||||
|
if ($invoice->due_amount < 0) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'invalid_amount'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
|
||||||
|
}
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment = Payment::create([
|
||||||
|
'payment_date' => $payment_date,
|
||||||
|
'payment_number' => $request->payment_number,
|
||||||
|
'user_id' => $request->user_id,
|
||||||
|
'company_id' => $request->header('company'),
|
||||||
|
'invoice_id' => $request->invoice_id,
|
||||||
|
'payment_mode' => $request->payment_mode,
|
||||||
|
'amount' => $request->amount,
|
||||||
|
'notes' => $request->notes,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'payment' => $payment,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(Request $request, $id)
|
||||||
|
{
|
||||||
|
$payment = Payment::with('user', 'invoice')->find($id);
|
||||||
|
|
||||||
|
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
|
||||||
|
->where('user_id', $payment->user_id)->where('due_amount', '>', 0)
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'customers' => User::where('role', 'customer')
|
||||||
|
->whereCompany($request->header('company'))
|
||||||
|
->get(),
|
||||||
|
'nextPaymentNumber' => $payment->payment_number,
|
||||||
|
'payment' => $payment,
|
||||||
|
'invoices' => $invoices
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(PaymentRequest $request, $id)
|
||||||
|
{
|
||||||
|
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||||
|
|
||||||
|
$payment = Payment::find($id);
|
||||||
|
$oldAmount = $payment->amount;
|
||||||
|
|
||||||
|
if ($request->has('invoice_id') && $request->invoice_id && ($oldAmount != $request->amount)) {
|
||||||
|
$amount = (int)$request->amount - (int)$oldAmount;
|
||||||
|
$invoice = Invoice::find($request->invoice_id);
|
||||||
|
$invoice->due_amount = (int)$invoice->due_amount - (int)$amount;
|
||||||
|
|
||||||
|
if ($invoice->due_amount < 0) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'invalid_amount'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invoice->due_amount == 0) {
|
||||||
|
$invoice->status = Invoice::STATUS_COMPLETED;
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PAID;
|
||||||
|
} else {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment->payment_date = $payment_date;
|
||||||
|
$payment->payment_number = $request->payment_number;
|
||||||
|
$payment->user_id = $request->user_id;
|
||||||
|
$payment->invoice_id = $request->invoice_id;
|
||||||
|
$payment->payment_mode = $request->payment_mode;
|
||||||
|
$payment->amount = $request->amount;
|
||||||
|
$payment->notes = $request->notes;
|
||||||
|
$payment->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'payment' => $payment,
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$payment = Payment::find($id);
|
||||||
|
|
||||||
|
if ($payment->invoice_id != null) {
|
||||||
|
$invoice = Invoice::find($payment->invoice_id);
|
||||||
|
$invoice->due_amount = ((int)$invoice->due_amount + (int)$payment->amount);
|
||||||
|
|
||||||
|
if ($invoice->due_amount == $invoice->total) {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_UNPAID;
|
||||||
|
} else {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invoice->due_date < Carbon::now()) {
|
||||||
|
$invoice->status = Invoice::STATUS_OVERDUE;
|
||||||
|
} elseif ($invoice->viewed) {
|
||||||
|
$invoice->status = Invoice::STATUS_VIEWED;
|
||||||
|
} elseif ($invoice->sent) {
|
||||||
|
$invoice->status = Invoice::STATUS_SENT;
|
||||||
|
} else {
|
||||||
|
$invoice->status = Invoice::STATUS_DRAFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(Request $request)
|
||||||
|
{
|
||||||
|
foreach ($request->id as $id) {
|
||||||
|
$payment = Payment::find($id);
|
||||||
|
|
||||||
|
if ($payment->invoice_id != null) {
|
||||||
|
$invoice = Invoice::find($payment->invoice_id);
|
||||||
|
$invoice->due_amount = ((int)$invoice->due_amount + (int)$payment->amount);
|
||||||
|
|
||||||
|
if ($invoice->due_amount == $invoice->total) {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_UNPAID;
|
||||||
|
} else {
|
||||||
|
$invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invoice->due_date < Carbon::now()) {
|
||||||
|
$invoice->status = Invoice::STATUS_OVERDUE;
|
||||||
|
} elseif ($invoice->sent) {
|
||||||
|
$invoice->status = Invoice::STATUS_SENT;
|
||||||
|
} elseif ($invoice->viewed) {
|
||||||
|
$invoice->status = Invoice::STATUS_VIEWED;
|
||||||
|
} else {
|
||||||
|
$invoice->status = Invoice::STATUS_DRAFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/Http/Controllers/PermissionsController.php
Executable file
38
app/Http/Controllers/PermissionsController.php
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Laraspace\Space\PermissionsChecker;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class PermissionsController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PermissionsChecker
|
||||||
|
*/
|
||||||
|
protected $permissions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PermissionsChecker $checker
|
||||||
|
*/
|
||||||
|
public function __construct(PermissionsChecker $checker)
|
||||||
|
{
|
||||||
|
$this->permissions = $checker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the permissions check page.
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function permissions()
|
||||||
|
{
|
||||||
|
$permissions = $this->permissions->check(
|
||||||
|
config('installer.permissions')
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'permissions' => $permissions
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
295
app/Http/Controllers/ReportController.php
Normal file
295
app/Http/Controllers/ReportController.php
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\InvoiceItem;
|
||||||
|
use Laraspace\Expense;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Tax;
|
||||||
|
use PDF;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
class ReportController extends Controller
|
||||||
|
{
|
||||||
|
public function customersSalesReport($hash, Request $request)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$start = Carbon::createFromFormat('d/m/Y', $request->from_date);
|
||||||
|
$end = Carbon::createFromFormat('d/m/Y', $request->to_date);
|
||||||
|
|
||||||
|
$customers = User::with(['invoices' => function ($query) use ($start, $end) {
|
||||||
|
$query->whereBetween(
|
||||||
|
'invoice_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
)
|
||||||
|
->where('paid_status', Invoice::STATUS_PAID);
|
||||||
|
}])
|
||||||
|
->customer()
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->applyInvoiceFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$totalAmount = 0;
|
||||||
|
foreach ($customers as $customer) {
|
||||||
|
$customerTotalAmount = 0;
|
||||||
|
foreach ($customer->invoices as $invoice) {
|
||||||
|
$customerTotalAmount += $invoice->total;
|
||||||
|
}
|
||||||
|
$customer->totalAmount = $customerTotalAmount;
|
||||||
|
$totalAmount += $customerTotalAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
|
$from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat);
|
||||||
|
$to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'customers' => $customers,
|
||||||
|
'totalAmount' => $totalAmount,
|
||||||
|
'colorSettings' => $colorSettings,
|
||||||
|
'company' => $company,
|
||||||
|
'from_date' => $from_date,
|
||||||
|
'to_date' => $to_date
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.reports.sales-customers');
|
||||||
|
|
||||||
|
if ($request->has('download')) {
|
||||||
|
return $pdf->download();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function itemsSalesReport($hash, Request $request)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$items = InvoiceItem::with('item')
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->applyInvoiceFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->itemAttributes()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$totalAmount = 0;
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$totalAmount += $item->total_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
|
$from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat);
|
||||||
|
$to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'items' => $items,
|
||||||
|
'colorSettings' => $colorSettings,
|
||||||
|
'totalAmount' => $totalAmount,
|
||||||
|
'company' => $company,
|
||||||
|
'from_date' => $from_date,
|
||||||
|
'to_date' => $to_date
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.reports.sales-items');
|
||||||
|
|
||||||
|
if ($request->has('download')) {
|
||||||
|
return $pdf->download();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expensesReport($hash, Request $request)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$expenseCategories = Expense::with('category')
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->applyFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->expensesAttributes()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$totalAmount = 0;
|
||||||
|
foreach ($expenseCategories as $category) {
|
||||||
|
$totalAmount += $category->total_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
|
$from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat);
|
||||||
|
$to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'expenseCategories' => $expenseCategories,
|
||||||
|
'colorSettings' => $colorSettings,
|
||||||
|
'totalExpense' => $totalAmount,
|
||||||
|
'company' => $company,
|
||||||
|
'from_date' => $from_date,
|
||||||
|
'to_date' => $to_date
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.reports.expenses');
|
||||||
|
|
||||||
|
if ($request->has('download')) {
|
||||||
|
return $pdf->download();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxSummery($hash, Request $request)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$taxTypes = Tax::with('taxType', 'invoice', 'invoiceItem')
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->whereInvoicesFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->taxAttributes()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$totalAmount = 0;
|
||||||
|
foreach ($taxTypes as $taxType) {
|
||||||
|
$totalAmount += $taxType->total_tax_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
|
$from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat);
|
||||||
|
$to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'taxTypes' => $taxTypes,
|
||||||
|
'totalTaxAmount' => $totalAmount,
|
||||||
|
'colorSettings' => $colorSettings,
|
||||||
|
'company' => $company,
|
||||||
|
'from_date' => $from_date,
|
||||||
|
'to_date' => $to_date
|
||||||
|
]);
|
||||||
|
|
||||||
|
$pdf = PDF::loadView('app.pdf.reports.tax-summary');
|
||||||
|
|
||||||
|
if ($request->has('download')) {
|
||||||
|
return $pdf->download();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function profitLossReport($hash, Request $request)
|
||||||
|
{
|
||||||
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
|
|
||||||
|
$invoicesAmount = Invoice::whereCompany($company->id)
|
||||||
|
->applyFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->wherePaidStatus(Invoice::STATUS_PAID)
|
||||||
|
->sum('total');
|
||||||
|
|
||||||
|
$expenseCategories = Expense::with('category')
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->applyFilters($request->only(['from_date', 'to_date']))
|
||||||
|
->expensesAttributes()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$totalAmount = 0;
|
||||||
|
foreach ($expenseCategories as $category) {
|
||||||
|
$totalAmount += $category->total_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
|
$from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat);
|
||||||
|
$to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat);
|
||||||
|
|
||||||
|
$colors = [
|
||||||
|
'primary_text_color',
|
||||||
|
'heading_text_color',
|
||||||
|
'section_heading_text_color',
|
||||||
|
'border_color',
|
||||||
|
'body_text_color',
|
||||||
|
'footer_text_color',
|
||||||
|
'footer_total_color',
|
||||||
|
'footer_bg_color',
|
||||||
|
'date_text_color'
|
||||||
|
];
|
||||||
|
$colorSettings = CompanySetting::whereIn('option', $colors)
|
||||||
|
->whereCompany($company->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
view()->share([
|
||||||
|
'company' => $company,
|
||||||
|
'income' => $invoicesAmount,
|
||||||
|
'expenseCategories' => $expenseCategories,
|
||||||
|
'totalExpense' => $totalAmount,
|
||||||
|
'colorSettings' => $colorSettings,
|
||||||
|
'company' => $company,
|
||||||
|
'from_date' => $from_date,
|
||||||
|
'to_date' => $to_date
|
||||||
|
]);
|
||||||
|
$pdf = PDF::loadView('app.pdf.reports.profit-loss');
|
||||||
|
|
||||||
|
if ($request->has('download')) {
|
||||||
|
return $pdf->download();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdf->stream();
|
||||||
|
}
|
||||||
|
}
|
||||||
42
app/Http/Controllers/RequirementsController.php
Executable file
42
app/Http/Controllers/RequirementsController.php
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Laraspace\Space\RequirementsChecker;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class RequirementsController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RequirementsChecker
|
||||||
|
*/
|
||||||
|
protected $requirements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RequirementsChecker $checker
|
||||||
|
*/
|
||||||
|
public function __construct(RequirementsChecker $checker)
|
||||||
|
{
|
||||||
|
$this->requirements = $checker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the requirements page.
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function requirements()
|
||||||
|
{
|
||||||
|
$phpSupportInfo = $this->requirements->checkPHPversion(
|
||||||
|
config('installer.core.minPhpVersion')
|
||||||
|
);
|
||||||
|
$requirements = $this->requirements->check(
|
||||||
|
config('installer.requirements')
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'phpSupportInfo' => $phpSupportInfo,
|
||||||
|
'requirements' => $requirements
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Controllers/SettingsController.php
Normal file
19
app/Http/Controllers/SettingsController.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
|
||||||
|
class SettingsController extends Controller
|
||||||
|
{
|
||||||
|
public function getAppVersion(Request $request)
|
||||||
|
{
|
||||||
|
$version = Setting::getSetting('version', $request->header('company'));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'version' => $version,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
126
app/Http/Controllers/TaxTypeController.php
Normal file
126
app/Http/Controllers/TaxTypeController.php
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Laraspace\TaxType;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Http\Requests\TaxTypeRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TaxTypeController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$taxTypes = TaxType::whereCompany($request->header('company'))
|
||||||
|
->latest()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'taxTypes' => $taxTypes
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(TaxTypeRequest $request)
|
||||||
|
{
|
||||||
|
$taxType = new TaxType();
|
||||||
|
$taxType->name = $request->name;
|
||||||
|
$taxType->percent = $request->percent;
|
||||||
|
$taxType->description = $request->description;
|
||||||
|
if ($request->has('compound_tax')) {
|
||||||
|
$taxType->compound_tax = $request->compound_tax;
|
||||||
|
}
|
||||||
|
$taxType->company_id = $request->header('company');
|
||||||
|
$taxType->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'taxType' => $taxType,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\TaxType $taxType
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(TaxType $taxType)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\TaxType $taxType
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function edit(TaxType $taxType)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'taxType' => $taxType
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Laraspace\TaxType $taxType
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(TaxTypeRequest $request, TaxType $taxType)
|
||||||
|
{
|
||||||
|
$taxType->name = $request->name;
|
||||||
|
$taxType->percent = $request->percent;
|
||||||
|
$taxType->description = $request->description;
|
||||||
|
if ($request->has('collective_tax')) {
|
||||||
|
$taxType->collective_tax = $request->collective_tax;
|
||||||
|
}
|
||||||
|
$taxType->compound_tax = $request->compound_tax;
|
||||||
|
$taxType->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'taxType' => $taxType,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \Laraspace\TaxType $taxType
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(TaxType $taxType)
|
||||||
|
{
|
||||||
|
if ($taxType->taxes() && $taxType->taxes()->count() > 0) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$taxType->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
74
app/Http/Controllers/UsersController.php
Normal file
74
app/Http/Controllers/UsersController.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Http\Requests;
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Laraspace\TaxType;
|
||||||
|
use DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Auth;
|
||||||
|
use Laraspace\Company;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
|
||||||
|
class UsersController extends Controller
|
||||||
|
{
|
||||||
|
public function getBootstrap(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$company = $request->header('company') ?? 1;
|
||||||
|
|
||||||
|
$customers = User::with('billingAddress', 'shippingAddress')
|
||||||
|
->customer()
|
||||||
|
->whereCompany($company)
|
||||||
|
->latest()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$currencies = Currency::latest()->get();
|
||||||
|
|
||||||
|
$default_language = CompanySetting::getSetting('language', $company);
|
||||||
|
|
||||||
|
$default_currency = Currency::findOrFail(
|
||||||
|
CompanySetting::getSetting('currency', $company)
|
||||||
|
);
|
||||||
|
|
||||||
|
$moment_date_format = CompanySetting::getSetting(
|
||||||
|
'moment_date_format',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
$fiscal_year = CompanySetting::getSetting(
|
||||||
|
'fiscal_year',
|
||||||
|
$request->header('company')
|
||||||
|
);
|
||||||
|
|
||||||
|
$items = Item::all();
|
||||||
|
|
||||||
|
$taxTypes = TaxType::latest()->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'user' => $user,
|
||||||
|
'customers' => $customers,
|
||||||
|
'currencies' => $currencies,
|
||||||
|
'default_currency' => $default_currency,
|
||||||
|
'default_language' => $default_language,
|
||||||
|
'company' => $user->company,
|
||||||
|
'companies' => Company::all(),
|
||||||
|
'items' => $items,
|
||||||
|
'taxTypes' => $taxTypes,
|
||||||
|
'moment_date_format' => $moment_date_format,
|
||||||
|
'fiscal_year' => $fiscal_year,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ping()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'success' => 'crater-self-hosted'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
81
app/Http/Kernel.php
Normal file
81
app/Http/Kernel.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||||
|
use Laraspace\Http\Middleware\AdminMiddleware;
|
||||||
|
|
||||||
|
class Kernel extends HttpKernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The application's global HTTP middleware stack.
|
||||||
|
*
|
||||||
|
* These middleware are run during every request to your application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $middleware = [
|
||||||
|
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
|
\Laraspace\Http\Middleware\TrimStrings::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||||
|
\Laraspace\Http\Middleware\TrustProxies::class,
|
||||||
|
\Laraspace\Http\Middleware\ConfigMiddleware::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application's route middleware groups.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $middlewareGroups = [
|
||||||
|
'web' => [
|
||||||
|
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
|
||||||
|
\Laraspace\Http\Middleware\EncryptCookies::class,
|
||||||
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
|
\Laraspace\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'api' => [
|
||||||
|
'throttle:60,1',
|
||||||
|
'bindings',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application's route middleware.
|
||||||
|
*
|
||||||
|
* These middleware may be assigned to groups or used individually.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $routeMiddleware = [
|
||||||
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
|
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
'guest' => \Laraspace\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
|
'admin' => AdminMiddleware::class,
|
||||||
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
|
'install' => \Laraspace\Http\Middleware\InstallationMiddleware::class,
|
||||||
|
'redirect-if-installed' => \Laraspace\Http\Middleware\RedirectIfInstalled::class,
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* The priority-sorted list of middleware.
|
||||||
|
*
|
||||||
|
* This forces the listed middleware to always be in the given order.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $middlewarePriority = [
|
||||||
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
|
\App\Http\Middleware\Authenticate::class,
|
||||||
|
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
\Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
29
app/Http/Middleware/AdminMiddleware.php
Normal file
29
app/Http/Middleware/AdminMiddleware.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
use Closure;
|
||||||
|
|
||||||
|
class AdminMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @param null $guard
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next, $guard = null)
|
||||||
|
{
|
||||||
|
if (Auth::guard($guard)->guest() || !Auth::user()->isAdmin()) {
|
||||||
|
if ($request->ajax() || $request->wantsJson()) {
|
||||||
|
return response('Unauthorized.', 401);
|
||||||
|
} else {
|
||||||
|
return response()->json(['error' => 'user_is_not_admin'], 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Http/Middleware/Authenticate.php
Normal file
20
app/Http/Middleware/Authenticate.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||||
|
|
||||||
|
class Authenticate extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the path the user should be redirected to when they are not authenticated.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function redirectTo($request)
|
||||||
|
{
|
||||||
|
if (! $request->expectsJson()) {
|
||||||
|
return route('login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/Http/Middleware/ConfigMiddleware.php
Normal file
28
app/Http/Middleware/ConfigMiddleware.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
|
||||||
|
class ConfigMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next)
|
||||||
|
{
|
||||||
|
if (\Storage::disk('local')->has('installed')) {
|
||||||
|
$setting = CompanySetting::getSetting('time_zone', $request->header('company'));
|
||||||
|
$timezone = config('app.timezone');
|
||||||
|
if ($setting && $setting != null && $setting != $timezone) {
|
||||||
|
config(['app.timezone' => $setting]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Http/Middleware/EncryptCookies.php
Normal file
23
app/Http/Middleware/EncryptCookies.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||||
|
|
||||||
|
class EncryptCookies extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Indicates if cookies should be serialized.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected static $serialize = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The names of the cookies that should not be encrypted.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
31
app/Http/Middleware/InstallationMiddleware.php
Normal file
31
app/Http/Middleware/InstallationMiddleware.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
|
||||||
|
class InstallationMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next)
|
||||||
|
{
|
||||||
|
if (!\Storage::disk('local')->has('database_created')) {
|
||||||
|
return redirect('/on-boarding');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\Storage::disk('local')->has('database_created')) {
|
||||||
|
if (Setting::getSetting('profile_complete') !== 'COMPLETED') {
|
||||||
|
return redirect('/on-boarding');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
25
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class RedirectIfAuthenticated
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @param string|null $guard
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next, $guard = null)
|
||||||
|
{
|
||||||
|
if (Auth::guard($guard)->check()) {
|
||||||
|
return redirect('/admin');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/Http/Middleware/RedirectIfInstalled.php
Normal file
26
app/Http/Middleware/RedirectIfInstalled.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Laraspace\Setting;
|
||||||
|
|
||||||
|
class RedirectIfInstalled
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next)
|
||||||
|
{
|
||||||
|
if (\Storage::disk('local')->has('database_created')) {
|
||||||
|
if (Setting::getSetting('profile_complete') === 'COMPLETED') {
|
||||||
|
return redirect('login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/Http/Middleware/TrimStrings.php
Normal file
17
app/Http/Middleware/TrimStrings.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||||
|
|
||||||
|
class TrimStrings extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The names of the attributes that should not be trimmed.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
}
|
||||||
21
app/Http/Middleware/TrustProxies.php
Normal file
21
app/Http/Middleware/TrustProxies.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||||
|
|
||||||
|
class TrustProxies extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The trusted proxies for this application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $proxies;
|
||||||
|
/**
|
||||||
|
* The current proxy header mappings.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
||||||
|
}
|
||||||
23
app/Http/Middleware/VerifyCsrfToken.php
Normal file
23
app/Http/Middleware/VerifyCsrfToken.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||||
|
|
||||||
|
class VerifyCsrfToken extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $addHttpCookie = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URIs that should be excluded from CSRF verification.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
30
app/Http/Requests/CompanyRequest.php
Normal file
30
app/Http/Requests/CompanyRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CompanyRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'country_id' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/Http/Requests/CompanySettingRequest.php
Normal file
34
app/Http/Requests/CompanySettingRequest.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CompanySettingRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'currency' => 'required',
|
||||||
|
'time_zone' => 'required',
|
||||||
|
'language' => 'required',
|
||||||
|
'fiscal_year' => 'required',
|
||||||
|
'moment_date_format' => 'required',
|
||||||
|
'carbon_date_format' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
41
app/Http/Requests/CustomerRequest.php
Normal file
41
app/Http/Requests/CustomerRequest.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CustomerRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
switch ($this->getMethod()) {
|
||||||
|
case 'POST':
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => 'email|nullable|unique:users,email',
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Http/Requests/DatabaseEnvironmentRequest.php
Normal file
35
app/Http/Requests/DatabaseEnvironmentRequest.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class DatabaseEnvironmentRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'app_url' => 'required|url',
|
||||||
|
'database_connection' => 'required|string|max:50',
|
||||||
|
'database_hostname' => 'required|string|max:50',
|
||||||
|
'database_port' => 'required|numeric',
|
||||||
|
'database_name' => 'required|string|max:50',
|
||||||
|
'database_username' => 'required|string|max:50',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
45
app/Http/Requests/EstimatesRequest.php
Normal file
45
app/Http/Requests/EstimatesRequest.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class EstimatesRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'estimate_date' => 'required',
|
||||||
|
'expiry_date' => 'required',
|
||||||
|
'estimate_number' => 'required|unique:estimates,estimate_number',
|
||||||
|
'user_id' => 'required',
|
||||||
|
'discount' => 'required',
|
||||||
|
'estimate_template_id' => 'required',
|
||||||
|
'items' => 'required|array',
|
||||||
|
'items.*' => 'required|max:255',
|
||||||
|
'items.*.name' => 'required',
|
||||||
|
'items.*.quantity' => 'required|numeric',
|
||||||
|
'items.*.price' => 'required|numeric',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->getMethod() == 'PUT') {
|
||||||
|
$rules['estimate_number'] = $rules['estimate_number'].','.$this->get('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
app/Http/Requests/ExpenseCategoryRequest.php
Normal file
29
app/Http/Requests/ExpenseCategoryRequest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ExpenseCategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/ExpenseRequest.php
Normal file
31
app/Http/Requests/ExpenseRequest.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ExpenseRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'expense_date' => 'required',
|
||||||
|
'expense_category_id' => 'required',
|
||||||
|
'amount' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
45
app/Http/Requests/InvoicesRequest.php
Normal file
45
app/Http/Requests/InvoicesRequest.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class InvoicesRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.s
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'invoice_date' => 'required',
|
||||||
|
'due_date' => 'required',
|
||||||
|
'invoice_number' => 'required|unique:invoices,invoice_number',
|
||||||
|
'user_id' => 'required',
|
||||||
|
'discount' => 'required',
|
||||||
|
'invoice_template_id' => 'required',
|
||||||
|
'items' => 'required|array',
|
||||||
|
'items.*' => 'required|max:255',
|
||||||
|
'items.*.name' => 'required',
|
||||||
|
'items.*.quantity' => 'required|numeric',
|
||||||
|
'items.*.price' => 'required|numeric',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->getMethod() == 'PUT') {
|
||||||
|
$rules['invoice_number'] = $rules['invoice_number'].','.$this->get('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/Http/Requests/ItemsRequest.php
Normal file
30
app/Http/Requests/ItemsRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ItemsRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'price' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Http/Requests/MailEnvironmentRequest.php
Normal file
35
app/Http/Requests/MailEnvironmentRequest.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MailEnvironmentRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'mail_driver' => 'required|string|max:50',
|
||||||
|
'mail_host' => 'required|string|max:50',
|
||||||
|
'mail_port' => 'required|max:50',
|
||||||
|
'mail_username' => 'required|string|max:50',
|
||||||
|
'mail_password' => 'required|string|max:50',
|
||||||
|
'mail_encryption' => 'required|string|max:50',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/Http/Requests/PaymentRequest.php
Normal file
38
app/Http/Requests/PaymentRequest.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class PaymentRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'payment_date' => 'required',
|
||||||
|
'payment_number' => 'required|unique:payments,payment_number',
|
||||||
|
'user_id' => 'required',
|
||||||
|
'amount' => 'required',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->getMethod() == 'PUT') {
|
||||||
|
$rules['payment_number'] = $rules['payment_number'].','.$this->route('payment');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
51
app/Http/Requests/ProfileRequest.php
Normal file
51
app/Http/Requests/ProfileRequest.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Laraspace\User;
|
||||||
|
|
||||||
|
class ProfileRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
$user = User::find(1);
|
||||||
|
|
||||||
|
switch ($this->getMethod()) {
|
||||||
|
case 'POST':
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'password' => 'required',
|
||||||
|
'email' => [
|
||||||
|
'required',
|
||||||
|
'email',
|
||||||
|
Rule::unique('users')->ignore($user->id, 'id')
|
||||||
|
]
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => 'required|email'
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
app/Http/Requests/Request.php
Normal file
9
app/Http/Requests/Request.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
abstract class Request extends FormRequest
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
30
app/Http/Requests/SettingKeyRequest.php
Normal file
30
app/Http/Requests/SettingKeyRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class SettingKeyRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'key' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/SettingRequest.php
Normal file
31
app/Http/Requests/SettingRequest.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class SettingRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'key' => 'required',
|
||||||
|
'value' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/Http/Requests/TaxTypeRequest.php
Normal file
30
app/Http/Requests/TaxTypeRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class TaxTypeRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required',
|
||||||
|
'percent' => 'required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
252
app/Invoice.php
Normal file
252
app/Invoice.php
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\InvoiceTemplate;
|
||||||
|
use Laraspace\Payment;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class Invoice extends Model
|
||||||
|
{
|
||||||
|
const STATUS_DRAFT = 'DRAFT';
|
||||||
|
const STATUS_SENT = 'SENT';
|
||||||
|
const STATUS_VIEWED = 'VIEWED';
|
||||||
|
const STATUS_OVERDUE = 'OVERDUE';
|
||||||
|
const STATUS_COMPLETED = 'COMPLETED';
|
||||||
|
|
||||||
|
const STATUS_UNPAID = 'UNPAID';
|
||||||
|
const STATUS_PARTIALLY_PAID = 'PARTIALLY_PAID';
|
||||||
|
const STATUS_PAID = 'PAID';
|
||||||
|
|
||||||
|
protected $dates = [
|
||||||
|
'created_at',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at',
|
||||||
|
'invoice_date',
|
||||||
|
'due_date'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'total' => 'integer',
|
||||||
|
'tax' => 'integer',
|
||||||
|
'sub_total' => 'integer',
|
||||||
|
'discount' => 'float',
|
||||||
|
'discount_val' => 'integer',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'invoice_date',
|
||||||
|
'due_date',
|
||||||
|
'invoice_number',
|
||||||
|
'reference_number',
|
||||||
|
'user_id',
|
||||||
|
'company_id',
|
||||||
|
'invoice_template_id',
|
||||||
|
'status',
|
||||||
|
'paid_status',
|
||||||
|
'sub_total',
|
||||||
|
'tax_per_item',
|
||||||
|
'discount_per_item',
|
||||||
|
'total',
|
||||||
|
'discount',
|
||||||
|
'discount_type',
|
||||||
|
'discount_val',
|
||||||
|
'due_amount',
|
||||||
|
'tax',
|
||||||
|
'notes',
|
||||||
|
'unique_hash',
|
||||||
|
'sent',
|
||||||
|
'viewed'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'formattedCreatedAt',
|
||||||
|
'formattedInvoiceDate',
|
||||||
|
'formattedDueDate'
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function getNextInvoiceNumber()
|
||||||
|
{
|
||||||
|
// Get the last created order
|
||||||
|
$lastOrder = Invoice::orderBy('created_at', 'desc')->first();
|
||||||
|
if (!$lastOrder) {
|
||||||
|
// We get here if there is no order at all
|
||||||
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
|
$number = 0;
|
||||||
|
} else {
|
||||||
|
$number = explode("-",$lastOrder->invoice_number);
|
||||||
|
$number = $number[1];
|
||||||
|
}
|
||||||
|
// If we have ORD000001 in the database then we only want the number
|
||||||
|
// So the substr returns this 000001
|
||||||
|
|
||||||
|
// Add the string in front and higher up the number.
|
||||||
|
// the %05d part makes sure that there are always 6 numbers in the string.
|
||||||
|
// so it adds the missing zero's when needed.
|
||||||
|
|
||||||
|
return sprintf('%06d', intval($number) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function items()
|
||||||
|
{
|
||||||
|
return $this->hasMany('Laraspace\InvoiceItem');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Tax::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function payments()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Payment::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Laraspace\User');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoiceTemplate()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(InvoiceTemplate::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function strposX($haystack, $needle, $number)
|
||||||
|
{
|
||||||
|
if ($number == '1') {
|
||||||
|
return strpos($haystack, $needle);
|
||||||
|
} elseif ($number > '1') {
|
||||||
|
return strpos(
|
||||||
|
$haystack,
|
||||||
|
$needle,
|
||||||
|
$this->strposX($haystack, $needle, $number - 1) + strlen($needle)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return error_log('Error: Value for parameter $number is out of range');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvoiceNumAttribute()
|
||||||
|
{
|
||||||
|
$position = $this->strposX($this->invoice_number, "-", 2) + 1;
|
||||||
|
return substr($this->invoice_number, $position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->created_at)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedDueDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->due_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedInvoiceDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->invoice_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function currency()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Currency::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereStatus($query, $status)
|
||||||
|
{
|
||||||
|
return $query->where('invoices.status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWherePaidStatus($query, $status)
|
||||||
|
{
|
||||||
|
return $query->where('invoices.paid_status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereInvoiceNumber($query, $invoiceNumber)
|
||||||
|
{
|
||||||
|
return $query->where('invoices.invoice_number', 'LIKE', '%'.$invoiceNumber.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeInvoicesBetween($query, $start, $end)
|
||||||
|
{
|
||||||
|
return $query->whereBetween(
|
||||||
|
'invoices.invoice_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereSearch($query, $search)
|
||||||
|
{
|
||||||
|
foreach (explode(' ', $search) as $term) {
|
||||||
|
$query->whereHas('user', function ($query) use ($term) {
|
||||||
|
$query->where('name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('contact_name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('company_name', 'LIKE', '%'.$term.'%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||||
|
{
|
||||||
|
$query->orderBy($orderByField, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
if ($filters->get('search')) {
|
||||||
|
$query->whereSearch($filters->get('search'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('status')) {
|
||||||
|
if (
|
||||||
|
$filters->get('status') == self::STATUS_UNPAID ||
|
||||||
|
$filters->get('status') == self::STATUS_PARTIALLY_PAID ||
|
||||||
|
$filters->get('status') == self::STATUS_PAID
|
||||||
|
) {
|
||||||
|
$query->wherePaidStatus($filters->get('status'));
|
||||||
|
} else {
|
||||||
|
$query->whereStatus($filters->get('status'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('paid_status')) {
|
||||||
|
$query->wherePaidStatus($filters->get('status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('invoice_number')) {
|
||||||
|
$query->whereInvoiceNumber($filters->get('invoice_number'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||||
|
$start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date'));
|
||||||
|
$end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date'));
|
||||||
|
$query->invoicesBetween($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('customer_id')) {
|
||||||
|
$query->whereCustomer($filters->get('customer_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||||
|
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'invoice_number';
|
||||||
|
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||||
|
$query->whereOrder($field, $orderBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('invoices.company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCustomer($query, $customer_id)
|
||||||
|
{
|
||||||
|
$query->where('invoices.user_id', $customer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
app/InvoiceItem.php
Normal file
84
app/InvoiceItem.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Laraspace\Tax;
|
||||||
|
use Laraspace\Item;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class InvoiceItem extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'invoice_id',
|
||||||
|
'name',
|
||||||
|
'item_id',
|
||||||
|
'description',
|
||||||
|
'company_id',
|
||||||
|
'quantity',
|
||||||
|
'price',
|
||||||
|
'discount_type',
|
||||||
|
'discount_val',
|
||||||
|
'total',
|
||||||
|
'tax',
|
||||||
|
'discount'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'price' => 'integer',
|
||||||
|
'total' => 'integer',
|
||||||
|
'discount' => 'float',
|
||||||
|
'discount_val' => 'integer',
|
||||||
|
'tax' => 'integer'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function invoice()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Invoice::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function item()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Item::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Tax::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeInvoicesBetween($query, $start, $end)
|
||||||
|
{
|
||||||
|
$query->whereHas('invoice', function ($query) use ($start, $end) {
|
||||||
|
$query->whereBetween(
|
||||||
|
'invoice_date',
|
||||||
|
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||||
|
)->where('paid_status', Invoice::STATUS_PAID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyInvoiceFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
|
||||||
|
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||||
|
$start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date'));
|
||||||
|
$end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date'));
|
||||||
|
$query->invoicesBetween($start, $end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeItemAttributes($query)
|
||||||
|
{
|
||||||
|
$query->select(
|
||||||
|
DB::raw('sum(quantity) as total_quantity, sum(total) as total_amount, item_id')
|
||||||
|
)->groupBy('item_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/InvoiceTemplate.php
Normal file
20
app/InvoiceTemplate.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
|
||||||
|
class InvoiceTemplate extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['path', 'view', 'name'];
|
||||||
|
|
||||||
|
public function invoices()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Invoice::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPathAttribute($value)
|
||||||
|
{
|
||||||
|
return url($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
115
app/Item.php
Normal file
115
app/Item.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\InvoiceItem;
|
||||||
|
use Laraspace\EstimateItem;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class Item extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'unit',
|
||||||
|
'price',
|
||||||
|
'company_id',
|
||||||
|
'description'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'price' => 'integer'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'formattedCreatedAt'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function scopeWhereSearch($query, $search)
|
||||||
|
{
|
||||||
|
return $query->where('name', 'LIKE', '%'.$search.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWherePrice($query, $price)
|
||||||
|
{
|
||||||
|
return $query->where('price', $price);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereUnit($query, $unit)
|
||||||
|
{
|
||||||
|
return $query->where('unit', $unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||||
|
{
|
||||||
|
$query->orderBy($orderByField, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
|
||||||
|
if ($filters->get('search')) {
|
||||||
|
$query->whereSearch($filters->get('search'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('price')) {
|
||||||
|
$query->wherePrice($filters->get('price'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('unit')) {
|
||||||
|
$query->whereUnit($filters->get('unit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||||
|
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'name';
|
||||||
|
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||||
|
$query->whereOrder($field, $orderBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->created_at)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function taxes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Tax::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoiceItems()
|
||||||
|
{
|
||||||
|
return $this->hasMany(InvoiceItem::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function estimateItems()
|
||||||
|
{
|
||||||
|
return $this->hasMany(EstimateItem::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteItem($id)
|
||||||
|
{
|
||||||
|
$item = Item::find($id);
|
||||||
|
|
||||||
|
if ($item->taxes()->exists() && $item->taxes()->count() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->invoiceItems()->exists() && $item->invoiceItems()->count() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->estimateItems()->exists() && $item->estimateItems()->count() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$item->delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
app/Mail/EstimatePdf.php
Normal file
37
app/Mail/EstimatePdf.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
class EstimatePdf extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $data = [];
|
||||||
|
|
||||||
|
public $notificationEmail = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data, $notificationEmail)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
$this->notificationEmail = $notificationEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
return $this->from($this->notificationEmail)->markdown('emails.send.estimate', ['data', $this->data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
app/Mail/EstimateViewed.php
Normal file
36
app/Mail/EstimateViewed.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class EstimateViewed extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$email = $this->data['user']['email'];
|
||||||
|
return $this->from($email)->markdown('emails.viewed.estimate', ['data', $this->data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
app/Mail/InvoiceViewed.php
Normal file
36
app/Mail/InvoiceViewed.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class InvoiceViewed extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$email = $this->data['user']['email'];
|
||||||
|
return $this->from($email)->markdown('emails.viewed.invoice', ['data', $this->data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
app/Mail/invoicePdf.php
Normal file
37
app/Mail/invoicePdf.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
class invoicePdf extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $data = [];
|
||||||
|
|
||||||
|
public $notificationEmail = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data, $notificationEmail)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
$this->notificationEmail = $notificationEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
return $this->from($this->notificationEmail)->markdown('emails.send.invoice', ['data', $this->data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
66
app/Notifications/MailResetPasswordNotification.php
Normal file
66
app/Notifications/MailResetPasswordNotification.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Notifications\ResetPassword;
|
||||||
|
|
||||||
|
class MailResetPasswordNotification extends ResetPassword
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($token)
|
||||||
|
{
|
||||||
|
parent::__construct($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['mail'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||||
|
*/
|
||||||
|
public function toMail($notifiable)
|
||||||
|
{
|
||||||
|
$link = url( "/reset-password/". $this->token );
|
||||||
|
|
||||||
|
return ( new MailMessage )
|
||||||
|
->subject('Reset Password Notification')
|
||||||
|
->line("Hello! You are receiving this email because we received a password reset request for your account." )
|
||||||
|
->action('Reset Password', $link )
|
||||||
|
->line("This password reset link will expire in ".config('auth.passwords.users.expire')." minutes" )
|
||||||
|
->line("If you did not request a password reset, no further action is required." );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
141
app/Payment.php
Normal file
141
app/Payment.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Laraspace\User;
|
||||||
|
use Laraspace\Invoice;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Payment extends Model
|
||||||
|
{
|
||||||
|
const PAYMENT_MODE_CHECK = 'CHECK';
|
||||||
|
const PAYMENT_MODE_OTHER = 'OTHER';
|
||||||
|
const PAYMENT_MODE_CASH = 'CASH';
|
||||||
|
const PAYMENT_MODE_CREDIT_CARD = 'CREDIT_CARD';
|
||||||
|
const PAYMENT_MODE_BANK_TRANSFER = 'BANK_TRANSFER';
|
||||||
|
|
||||||
|
protected $dates = ['created_at', 'updated_at', 'payment_date'];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id',
|
||||||
|
'invoice_id',
|
||||||
|
'payment_date',
|
||||||
|
'company_id',
|
||||||
|
'notes',
|
||||||
|
'payment_number',
|
||||||
|
'payment_mode',
|
||||||
|
'amount'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'formattedCreatedAt',
|
||||||
|
'formattedPaymentDate'
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function getNextPaymentNumber()
|
||||||
|
{
|
||||||
|
// Get the last created order
|
||||||
|
$payment = Payment::orderBy('created_at', 'desc')->first();
|
||||||
|
if (!$payment) {
|
||||||
|
// We get here if there is no order at all
|
||||||
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
|
$number = 0;
|
||||||
|
} else {
|
||||||
|
$number = explode("-",$payment->payment_number);
|
||||||
|
$number = $number[1];
|
||||||
|
}
|
||||||
|
// If we have ORD000001 in the database then we only want the number
|
||||||
|
// So the substr returns this 000001
|
||||||
|
|
||||||
|
// Add the string in front and higher up the number.
|
||||||
|
// the %05d part makes sure that there are always 6 numbers in the string.
|
||||||
|
// so it adds the missing zero's when needed.
|
||||||
|
|
||||||
|
return sprintf('%06d', intval($number) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoice()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Invoice::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->created_at)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormattedPaymentDateAttribute($value)
|
||||||
|
{
|
||||||
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
return Carbon::parse($this->payment_date)->format($dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereSearch($query, $search)
|
||||||
|
{
|
||||||
|
foreach (explode(' ', $search) as $term) {
|
||||||
|
$query->whereHas('user', function ($query) use ($term) {
|
||||||
|
$query->where('name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('contact_name', 'LIKE', '%'.$term.'%')
|
||||||
|
->orWhere('company_name', 'LIKE', '%'.$term.'%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopePaymentNumber($query, $paymentNumber)
|
||||||
|
{
|
||||||
|
return $query->where('payments.payment_number', 'LIKE', '%'.$paymentNumber.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopePaymentMode($query, $paymentMode)
|
||||||
|
{
|
||||||
|
return $query->where('payments.payment_mode', $paymentMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeApplyFilters($query, array $filters)
|
||||||
|
{
|
||||||
|
$filters = collect($filters);
|
||||||
|
|
||||||
|
if ($filters->get('search')) {
|
||||||
|
$query->whereSearch($filters->get('search'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('payment_number')) {
|
||||||
|
$query->paymentNumber($filters->get('payment_number'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('payment_mode')) {
|
||||||
|
$query->paymentMode($filters->get('payment_mode'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('customer_id')) {
|
||||||
|
$query->whereCustomer($filters->get('customer_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||||
|
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'payment_number';
|
||||||
|
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||||
|
$query->whereOrder($field, $orderBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||||
|
{
|
||||||
|
$query->orderBy($orderByField, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCompany($query, $company_id)
|
||||||
|
{
|
||||||
|
$query->where('payments.company_id', $company_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereCustomer($query, $customer_id)
|
||||||
|
{
|
||||||
|
$query->where('payments.user_id', $customer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
app/Providers/AppServiceProvider.php
Normal file
33
app/Providers/AppServiceProvider.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Pagination\Paginator;
|
||||||
|
|
||||||
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
Paginator::useBootstrapThree();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
/*ADD THIS LINES*/
|
||||||
|
$this->commands([
|
||||||
|
\Laravel\Passport\Console\InstallCommand::class,
|
||||||
|
\Laravel\Passport\Console\KeysCommand::class,
|
||||||
|
\Laravel\Passport\Console\ClientCommand::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
app/Providers/AuthServiceProvider.php
Normal file
29
app/Providers/AuthServiceProvider.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
use Laravel\Passport\Passport;
|
||||||
|
|
||||||
|
class AuthServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The policy mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $policies = [
|
||||||
|
'Laraspace\Model' => 'Laraspace\Policies\ModelPolicy',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register any authentication / authorization services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerPolicies();
|
||||||
|
|
||||||
|
Passport::routes();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Providers/BroadcastServiceProvider.php
Normal file
20
app/Providers/BroadcastServiceProvider.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class BroadcastServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
Broadcast::routes();
|
||||||
|
Broadcast::routes(["middleware" => 'api.auth']);
|
||||||
|
require base_path('routes/channels.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Providers/EventServiceProvider.php
Normal file
35
app/Providers/EventServiceProvider.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Auth\Events\Registered;
|
||||||
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
|
|
||||||
|
class EventServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The event listener mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $listen = [
|
||||||
|
'Laraspace\Events\SomeEvent' => [
|
||||||
|
'Laraspace\Listeners\EventListener',
|
||||||
|
],
|
||||||
|
Registered::class => [
|
||||||
|
SendEmailVerificationNotification::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register any events for your application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
72
app/Providers/RouteServiceProvider.php
Normal file
72
app/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This namespace is applied to your controller routes.
|
||||||
|
*
|
||||||
|
* In addition, it is set as the URL generator's root namespace.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $namespace = 'Laraspace\Http\Controllers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define your route model bindings, pattern filters, etc.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
|
||||||
|
parent::boot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the routes for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function map()
|
||||||
|
{
|
||||||
|
$this->mapApiRoutes();
|
||||||
|
|
||||||
|
$this->mapWebRoutes();
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "web" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes all receive session state, CSRF protection, etc.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function mapWebRoutes()
|
||||||
|
{
|
||||||
|
Route::middleware('web')
|
||||||
|
->namespace($this->namespace)
|
||||||
|
->group(base_path('routes/web.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "api" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes are typically stateless.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function mapApiRoutes()
|
||||||
|
{
|
||||||
|
Route::prefix('api')
|
||||||
|
->middleware('api')
|
||||||
|
->namespace($this->namespace)
|
||||||
|
->group(base_path('routes/api.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
423
app/Proxy/HttpKernelProxy.php
Normal file
423
app/Proxy/HttpKernelProxy.php
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Proxy;
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
use Illuminate\Contracts\Http\Kernel as HttpKernel;
|
||||||
|
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
||||||
|
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyUploadedFile;
|
||||||
|
|
||||||
|
class HttpKernelProxy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Additional headers for the request.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultHeaders = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional server variables for the request.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $serverVariables = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether redirects should be followed.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $followRedirects = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor for the proxy.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Contracts\Container\Container $app
|
||||||
|
*/
|
||||||
|
public function __construct(Container $app)
|
||||||
|
{
|
||||||
|
$this->app = $app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define additional headers to be sent with the request.
|
||||||
|
*
|
||||||
|
* @param array $headers
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withHeaders(array $headers)
|
||||||
|
{
|
||||||
|
$this->defaultHeaders = array_merge($this->defaultHeaders, $headers);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a header to be sent with the request.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withHeader(string $name, string $value)
|
||||||
|
{
|
||||||
|
$this->defaultHeaders[$name] = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all the configured headers.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function flushHeaders()
|
||||||
|
{
|
||||||
|
$this->defaultHeaders = [];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a set of server variables to be sent with the requests.
|
||||||
|
*
|
||||||
|
* @param array $server
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withServerVariables(array $server)
|
||||||
|
{
|
||||||
|
$this->serverVariables = $server;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically follow any redirects returned from the response.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function followingRedirects()
|
||||||
|
{
|
||||||
|
$this->followRedirects = true;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the referer header to simulate a previous request.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function from(string $url)
|
||||||
|
{
|
||||||
|
return $this->withHeader('referer', $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a GET request.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function get($uri, array $headers = [])
|
||||||
|
{
|
||||||
|
$server = $this->transformHeadersToServerVars($headers);
|
||||||
|
|
||||||
|
return $this->call('GET', $uri, [], [], [], $server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a GET request, expecting a JSON response.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function getJson($uri, array $headers = [])
|
||||||
|
{
|
||||||
|
return $this->json('GET', $uri, [], $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a POST request.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function post($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
$server = $this->transformHeadersToServerVars($headers);
|
||||||
|
|
||||||
|
return $this->call('POST', $uri, $data, [], [], $server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a POST request, expecting a JSON response.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function postJson($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
return $this->json('POST', $uri, $data, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a PUT request.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function put($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
$server = $this->transformHeadersToServerVars($headers);
|
||||||
|
|
||||||
|
return $this->call('PUT', $uri, $data, [], [], $server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a PUT request, expecting a JSON response.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function putJson($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
return $this->json('PUT', $uri, $data, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a PATCH request.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function patch($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
$server = $this->transformHeadersToServerVars($headers);
|
||||||
|
|
||||||
|
return $this->call('PATCH', $uri, $data, [], [], $server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a PATCH request, expecting a JSON response.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function patchJson($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
return $this->json('PATCH', $uri, $data, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a DELETE request.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function delete($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
$server = $this->transformHeadersToServerVars($headers);
|
||||||
|
|
||||||
|
return $this->call('DELETE', $uri, $data, [], [], $server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the given URI with a DELETE request, expecting a JSON response.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function deleteJson($uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
return $this->json('DELETE', $uri, $data, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the given URI with a JSON request.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $data
|
||||||
|
* @param array $headers
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function json($method, $uri, array $data = [], array $headers = [])
|
||||||
|
{
|
||||||
|
$files = $this->extractFilesFromDataArray($data);
|
||||||
|
|
||||||
|
$content = json_encode($data);
|
||||||
|
|
||||||
|
$headers = array_merge([
|
||||||
|
'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
|
||||||
|
'CONTENT_TYPE' => 'application/json',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
], $headers);
|
||||||
|
|
||||||
|
return $this->call(
|
||||||
|
$method,
|
||||||
|
$uri,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
$files,
|
||||||
|
$this->transformHeadersToServerVars($headers),
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the given URI and return the Response.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $parameters
|
||||||
|
* @param array $cookies
|
||||||
|
* @param array $files
|
||||||
|
* @param array $server
|
||||||
|
* @param string $content
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
|
||||||
|
{
|
||||||
|
$kernel = $this->app->make(HttpKernel::class);
|
||||||
|
|
||||||
|
$files = array_merge($files, $this->extractFilesFromDataArray($parameters));
|
||||||
|
|
||||||
|
$symfonyRequest = SymfonyRequest::create(
|
||||||
|
$this->prepareUrlForRequest($uri),
|
||||||
|
$method,
|
||||||
|
$parameters,
|
||||||
|
$cookies,
|
||||||
|
$files,
|
||||||
|
array_replace($this->serverVariables, $server),
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $kernel->handle(
|
||||||
|
$request = Request::createFromBase($symfonyRequest)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->followRedirects) {
|
||||||
|
$response = $this->followRedirects($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
$kernel->terminate($request, $response);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn the given URI into a fully qualified URL.
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function prepareUrlForRequest($uri)
|
||||||
|
{
|
||||||
|
if (Str::startsWith($uri, '/')) {
|
||||||
|
$uri = substr($uri, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Str::startsWith($uri, 'http')) {
|
||||||
|
$uri = config('app.url') . '/' . $uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim($uri, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform headers array to array of $_SERVER vars with HTTP_* format.
|
||||||
|
*
|
||||||
|
* @param array $headers
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function transformHeadersToServerVars(array $headers)
|
||||||
|
{
|
||||||
|
return collect(array_merge($this->defaultHeaders, $headers))->mapWithKeys(function ($value, $name) {
|
||||||
|
$name = strtr(strtoupper($name), '-', '_');
|
||||||
|
|
||||||
|
return [$this->formatServerHeaderKey($name) => $value];
|
||||||
|
})->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the header name for the server array.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function formatServerHeaderKey($name)
|
||||||
|
{
|
||||||
|
if (!Str::startsWith($name, 'HTTP_') && $name != 'CONTENT_TYPE' && $name != 'REMOTE_ADDR') {
|
||||||
|
return 'HTTP_' . $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the file uploads from the given data array.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function extractFilesFromDataArray(&$data)
|
||||||
|
{
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if ($value instanceof SymfonyUploadedFile) {
|
||||||
|
$files[$key] = $value;
|
||||||
|
|
||||||
|
unset($data[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
$files[$key] = $this->extractFilesFromDataArray($value);
|
||||||
|
|
||||||
|
$data[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Follow a redirect chain until a non-redirect is received.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Response $response
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
protected function followRedirects($response)
|
||||||
|
{
|
||||||
|
while ($response->isRedirect()) {
|
||||||
|
$response = $this->get($response->headers->get('Location'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->followRedirects = false;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Setting.php
Normal file
35
app/Setting.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Setting extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
public static function setSetting($key, $setting)
|
||||||
|
{
|
||||||
|
$old = self::whereOption($key)->first();
|
||||||
|
|
||||||
|
if ($old) {
|
||||||
|
$old->value = $setting;
|
||||||
|
$old->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = new Setting();
|
||||||
|
$set->option = $key;
|
||||||
|
$set->value = $setting;
|
||||||
|
$set->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSetting($key)
|
||||||
|
{
|
||||||
|
$setting = static::whereOption($key)->first();
|
||||||
|
|
||||||
|
if ($setting) {
|
||||||
|
return $setting->value;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
app/Space/DateFormatter.php
Normal file
57
app/Space/DateFormatter.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Space;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DateFormatter
|
||||||
|
{
|
||||||
|
protected static $formats = [
|
||||||
|
[
|
||||||
|
"carbon_format" => "Y M d",
|
||||||
|
"moment_format" => "YYYY MMM DD"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "d M Y",
|
||||||
|
"moment_format" => "DD MMM YYYY"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "d/m/Y",
|
||||||
|
"moment_format" => "DD/MM/YYYY"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "d.m.Y",
|
||||||
|
"moment_format" => "DD.MM.YYYY"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "d-m-Y",
|
||||||
|
"moment_format" => "DD-MM-YYYY"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "m/d/Y",
|
||||||
|
"moment_format" => "MM/DD/YYYY"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "Y/m/d",
|
||||||
|
"moment_format" => " YYYY/MM/DD"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"carbon_format" => "Y-m-d",
|
||||||
|
"moment_format" => "YYYY-MM-DD"
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function get_list()
|
||||||
|
{
|
||||||
|
$new = [];
|
||||||
|
|
||||||
|
foreach (static::$formats as $format) {
|
||||||
|
$new[] = array(
|
||||||
|
"display_date" => Carbon::now()->format($format['carbon_format']) ,
|
||||||
|
"carbon_format_value" => $format['carbon_format'],
|
||||||
|
"moment_format_value" => $format['moment_format']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $new;
|
||||||
|
}
|
||||||
|
}
|
||||||
166
app/Space/EnvironmentManager.php
Executable file
166
app/Space/EnvironmentManager.php
Executable file
@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Space;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Laraspace\Http\Requests\DatabaseEnvironmentRequest;
|
||||||
|
use Laraspace\Http\Requests\MailEnvironmentRequest;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
|
class EnvironmentManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $envPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the .env and .env.example paths.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->envPath = base_path('.env');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the form content to the .env file.
|
||||||
|
*
|
||||||
|
* @param DatabaseEnvironmentRequest $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function saveDatabaseVariables(DatabaseEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
$oldDatabaseData =
|
||||||
|
'DB_CONNECTION='.config('database.default')."\n".
|
||||||
|
'DB_HOST='.config('database.connections.'.config('database.default').'.host')."\n".
|
||||||
|
'DB_PORT='.config('database.connections.'.config('database.default').'.port')."\n".
|
||||||
|
'DB_DATABASE='.config('database.connections.'.config('database.default').'.database')."\n".
|
||||||
|
'DB_USERNAME='.config('database.connections.'.config('database.default').'.username')."\n".
|
||||||
|
'DB_PASSWORD='.config('database.connections.'.config('database.default').'.password')."\n\n";
|
||||||
|
|
||||||
|
$newDatabaseData =
|
||||||
|
'DB_CONNECTION='.$request->database_connection."\n".
|
||||||
|
'DB_HOST='.$request->database_hostname."\n".
|
||||||
|
'DB_PORT='.$request->database_port."\n".
|
||||||
|
'DB_DATABASE='.$request->database_name."\n".
|
||||||
|
'DB_USERNAME='.$request->database_username."\n".
|
||||||
|
'DB_PASSWORD='.$request->database_password."\n\n";
|
||||||
|
|
||||||
|
if (! $this->checkDatabaseConnection($request)) {
|
||||||
|
return [
|
||||||
|
'error' => 'connection_failed'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
$oldDatabaseData,
|
||||||
|
$newDatabaseData,
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
'APP_URL='.config('app.url'),
|
||||||
|
'APP_URL='.$request->app_url,
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return [
|
||||||
|
'error' => 'database_variables_save_error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => 'database_variables_save_successfully'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the form content to the .env file.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function saveMailVariables(MailEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
$oldMailData =
|
||||||
|
'MAIL_DRIVER='.config('mail.driver')."\n".
|
||||||
|
'MAIL_HOST='.config('mail.host')."\n".
|
||||||
|
'MAIL_PORT='.config('mail.port')."\n".
|
||||||
|
'MAIL_USERNAME='.config('mail.username')."\n".
|
||||||
|
'MAIL_PASSWORD='.config('mail.password')."\n".
|
||||||
|
'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n";
|
||||||
|
|
||||||
|
$newMailData =
|
||||||
|
'MAIL_DRIVER='.$request->mail_driver."\n".
|
||||||
|
'MAIL_HOST='.$request->mail_host."\n".
|
||||||
|
'MAIL_PORT='.$request->mail_port."\n".
|
||||||
|
'MAIL_USERNAME='.$request->mail_username."\n".
|
||||||
|
'MAIL_PASSWORD='.$request->mail_password."\n".
|
||||||
|
'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n";
|
||||||
|
// dd($newMailData);
|
||||||
|
try {
|
||||||
|
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
$oldMailData,
|
||||||
|
$newMailData,
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
$oldMailData,
|
||||||
|
$newMailData,
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return [
|
||||||
|
'error' => 'mail_variables_save_error'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => 'mail_variables_save_successfully'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param DatabaseEnvironmentRequest $request
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkDatabaseConnection(DatabaseEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
$connection = $request->database_connection;
|
||||||
|
|
||||||
|
$settings = config("database.connections.$connection");
|
||||||
|
|
||||||
|
config([
|
||||||
|
'database' => [
|
||||||
|
'migrations' => 'migrations',
|
||||||
|
'default' => $connection,
|
||||||
|
'connections' => [
|
||||||
|
$connection => array_merge($settings, [
|
||||||
|
'driver' => $connection,
|
||||||
|
'host' => $request->database_hostname,
|
||||||
|
'port' => $request->database_port,
|
||||||
|
'database' => $request->database_name,
|
||||||
|
'username' => $request->database_username,
|
||||||
|
'password' => $request->database_password,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::connection()->getPdo();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
83
app/Space/PermissionsChecker.php
Executable file
83
app/Space/PermissionsChecker.php
Executable file
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Space;
|
||||||
|
|
||||||
|
class PermissionsChecker
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $results = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the result array permissions and errors.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->results['permissions'] = [];
|
||||||
|
|
||||||
|
$this->results['errors'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for the folders permissions.
|
||||||
|
*
|
||||||
|
* @param array $folders
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function check(array $folders)
|
||||||
|
{
|
||||||
|
foreach ($folders as $folder => $permission) {
|
||||||
|
if (! ($this->getPermission($folder) >= $permission)) {
|
||||||
|
$this->addFileAndSetErrors($folder, $permission, false);
|
||||||
|
} else {
|
||||||
|
$this->addFile($folder, $permission, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a folder permission.
|
||||||
|
*
|
||||||
|
* @param $folder
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getPermission($folder)
|
||||||
|
{
|
||||||
|
return substr(sprintf('%o', fileperms(base_path($folder))), -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the file to the list of results.
|
||||||
|
*
|
||||||
|
* @param $folder
|
||||||
|
* @param $permission
|
||||||
|
* @param $isSet
|
||||||
|
*/
|
||||||
|
private function addFile($folder, $permission, $isSet)
|
||||||
|
{
|
||||||
|
array_push($this->results['permissions'], [
|
||||||
|
'folder' => $folder,
|
||||||
|
'permission' => $permission,
|
||||||
|
'isSet' => $isSet,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the file and set the errors.
|
||||||
|
*
|
||||||
|
* @param $folder
|
||||||
|
* @param $permission
|
||||||
|
* @param $isSet
|
||||||
|
*/
|
||||||
|
private function addFileAndSetErrors($folder, $permission, $isSet)
|
||||||
|
{
|
||||||
|
$this->addFile($folder, $permission, $isSet);
|
||||||
|
|
||||||
|
$this->results['errors'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
114
app/Space/RequirementsChecker.php
Executable file
114
app/Space/RequirementsChecker.php
Executable file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Laraspace\Space;
|
||||||
|
|
||||||
|
class RequirementsChecker
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Minimum PHP Version Supported (Override is in installer.php config file).
|
||||||
|
*
|
||||||
|
* @var _minPhpVersion
|
||||||
|
*/
|
||||||
|
private $_minPhpVersion = '7.0.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for the server requirements.
|
||||||
|
*
|
||||||
|
* @param array $requirements
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function check(array $requirements)
|
||||||
|
{
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($requirements as $type => $requirement) {
|
||||||
|
switch ($type) {
|
||||||
|
// check php requirements
|
||||||
|
case 'php':
|
||||||
|
foreach ($requirements[$type] as $requirement) {
|
||||||
|
$results['requirements'][$type][$requirement] = true;
|
||||||
|
|
||||||
|
if (! extension_loaded($requirement)) {
|
||||||
|
$results['requirements'][$type][$requirement] = false;
|
||||||
|
|
||||||
|
$results['errors'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// check apache requirements
|
||||||
|
case 'apache':
|
||||||
|
foreach ($requirements[$type] as $requirement) {
|
||||||
|
// if function doesn't exist we can't check apache modules
|
||||||
|
if (function_exists('apache_get_modules')) {
|
||||||
|
$results['requirements'][$type][$requirement] = true;
|
||||||
|
|
||||||
|
if (! in_array($requirement, apache_get_modules())) {
|
||||||
|
$results['requirements'][$type][$requirement] = false;
|
||||||
|
|
||||||
|
$results['errors'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check PHP version requirement.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function checkPHPversion(string $minPhpVersion = null)
|
||||||
|
{
|
||||||
|
$minVersionPhp = $minPhpVersion;
|
||||||
|
$currentPhpVersion = $this->getPhpVersionInfo();
|
||||||
|
$supported = false;
|
||||||
|
|
||||||
|
if ($minPhpVersion == null) {
|
||||||
|
$minVersionPhp = $this->getMinPhpVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_compare($currentPhpVersion['version'], $minVersionPhp) >= 0) {
|
||||||
|
$supported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$phpStatus = [
|
||||||
|
'full' => $currentPhpVersion['full'],
|
||||||
|
'current' => $currentPhpVersion['version'],
|
||||||
|
'minimum' => $minVersionPhp,
|
||||||
|
'supported' => $supported,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $phpStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current Php version information.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function getPhpVersionInfo()
|
||||||
|
{
|
||||||
|
$currentVersionFull = PHP_VERSION;
|
||||||
|
preg_match("#^\d+(\.\d+)*#", $currentVersionFull, $filtered);
|
||||||
|
$currentVersion = $filtered[0];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'full' => $currentVersionFull,
|
||||||
|
'version' => $currentVersion,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get minimum PHP version ID.
|
||||||
|
*
|
||||||
|
* @return string _minPhpVersion
|
||||||
|
*/
|
||||||
|
protected function getMinPhpVersion()
|
||||||
|
{
|
||||||
|
return $this->_minPhpVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
430
app/Space/TimeZones.php
Normal file
430
app/Space/TimeZones.php
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace\Space;
|
||||||
|
|
||||||
|
class TimeZones
|
||||||
|
{
|
||||||
|
public static function get_list()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['value' => 'Pacific/Midway', 'key' => '(UTC-11:00) Midway'],
|
||||||
|
['value' => 'Pacific/Niue', 'key' => '(UTC-11:00) Niue'],
|
||||||
|
['value' => 'Pacific/Pago_Pago', 'key' => '(UTC-11:00) Pago Pago'],
|
||||||
|
['value' => 'America/Adak', 'key' => '(UTC-10:00) Adak'],
|
||||||
|
['value' => 'Pacific/Honolulu', 'key' => '(UTC-10:00) Honolulu'],
|
||||||
|
['value' => 'Pacific/Johnston', 'key' => '(UTC-10:00) Johnston'],
|
||||||
|
['value' => 'Pacific/Rarotonga', 'key' => '(UTC-10:00) Rarotonga'],
|
||||||
|
['value' => 'Pacific/Tahiti', 'key' => '(UTC-10:00) Tahiti'],
|
||||||
|
['value' => 'Pacific/Marquesas', 'key' => '(UTC-09:30) Marquesas'],
|
||||||
|
['value' => 'America/Anchorage', 'key' => '(UTC-09:00) Anchorage'],
|
||||||
|
['value' => 'Pacific/Gambier', 'key' => '(UTC-09:00) Gambier'],
|
||||||
|
['value' => 'America/Juneau', 'key' => '(UTC-09:00) Juneau'],
|
||||||
|
['value' => 'America/Nome', 'key' => '(UTC-09:00) Nome'],
|
||||||
|
['value' => 'America/Sitka', 'key' => '(UTC-09:00) Sitka'],
|
||||||
|
['value' => 'America/Yakutat', 'key' => '(UTC-09:00) Yakutat'],
|
||||||
|
['value' => 'America/Dawson', 'key' => '(UTC-08:00) Dawson'],
|
||||||
|
['value' => 'America/Los_Angeles', 'key' => '(UTC-08:00) Los Angeles'],
|
||||||
|
['value' => 'America/Metlakatla', 'key' => '(UTC-08:00) Metlakatla'],
|
||||||
|
['value' => 'Pacific/Pitcairn', 'key' => '(UTC-08:00) Pitcairn'],
|
||||||
|
['value' => 'America/Santa_Isabel', 'key' => '(UTC-08:00) Santa Isabel'],
|
||||||
|
['value' => 'America/Tijuana', 'key' => '(UTC-08:00) Tijuana'],
|
||||||
|
['value' => 'America/Vancouver', 'key' => '(UTC-08:00) Vancouver'],
|
||||||
|
['value' => 'America/Whitehorse', 'key' => '(UTC-08:00) Whitehorse'],
|
||||||
|
['value' => 'America/Boise', 'key' => '(UTC-07:00) Boise'],
|
||||||
|
['value' => 'America/Cambridge_Bay', 'key' => '(UTC-07:00) Cambridge Bay'],
|
||||||
|
['value' => 'America/Chihuahua', 'key' => '(UTC-07:00) Chihuahua'],
|
||||||
|
['value' => 'America/Creston', 'key' => '(UTC-07:00) Creston'],
|
||||||
|
['value' => 'America/Dawson_Creek', 'key' => '(UTC-07:00) Dawson Creek'],
|
||||||
|
['value' => 'America/Denver', 'key' => '(UTC-07:00) Denver'],
|
||||||
|
['value' => 'America/Edmonton', 'key' => '(UTC-07:00) Edmonton'],
|
||||||
|
['value' => 'America/Hermosillo', 'key' => '(UTC-07:00) Hermosillo'],
|
||||||
|
['value' => 'America/Inuvik', 'key' => '(UTC-07:00) Inuvik'],
|
||||||
|
['value' => 'America/Mazatlan', 'key' => '(UTC-07:00) Mazatlan'],
|
||||||
|
['value' => 'America/Ojinaga', 'key' => '(UTC-07:00) Ojinaga'],
|
||||||
|
['value' => 'America/Phoenix', 'key' => '(UTC-07:00) Phoenix'],
|
||||||
|
['value' => 'America/Shiprock', 'key' => '(UTC-07:00) Shiprock'],
|
||||||
|
['value' => 'America/Yellowknife', 'key' => '(UTC-07:00) Yellowknife'],
|
||||||
|
['value' => 'America/Bahia_Banderas', 'key' => '(UTC-06:00) Bahia Banderas'],
|
||||||
|
['value' => 'America/Belize', 'key' => '(UTC-06:00) Belize'],
|
||||||
|
['value' => 'America/North_Dakota/Beulah', 'key' => '(UTC-06:00) Beulah'],
|
||||||
|
['value' => 'America/Cancun', 'key' => '(UTC-06:00) Cancun'],
|
||||||
|
['value' => 'America/North_Dakota/Center', 'key' => '(UTC-06:00) Center'],
|
||||||
|
['value' => 'America/Chicago', 'key' => '(UTC-06:00) Chicago'],
|
||||||
|
['value' => 'America/Costa_Rica', 'key' => '(UTC-06:00) Costa Rica'],
|
||||||
|
['value' => 'Pacific/Easter', 'key' => '(UTC-06:00) Easter'],
|
||||||
|
['value' => 'America/El_Salvador', 'key' => '(UTC-06:00) El Salvador'],
|
||||||
|
['value' => 'Pacific/Galapagos', 'key' => '(UTC-06:00) Galapagos'],
|
||||||
|
['value' => 'America/Guatemala', 'key' => '(UTC-06:00) Guatemala'],
|
||||||
|
['value' => 'America/Indiana/Knox', 'key' => '(UTC-06:00) Knox'],
|
||||||
|
['value' => 'America/Managua', 'key' => '(UTC-06:00) Managua'],
|
||||||
|
['value' => 'America/Matamoros', 'key' => '(UTC-06:00) Matamoros'],
|
||||||
|
['value' => 'America/Menominee', 'key' => '(UTC-06:00) Menominee'],
|
||||||
|
['value' => 'America/Merida', 'key' => '(UTC-06:00) Merida'],
|
||||||
|
['value' => 'America/Mexico_City', 'key' => '(UTC-06:00) Mexico City'],
|
||||||
|
['value' => 'America/Monterrey', 'key' => '(UTC-06:00) Monterrey'],
|
||||||
|
['value' => 'America/North_Dakota/New_Salem', 'key' => '(UTC-06:00) New Salem'],
|
||||||
|
['value' => 'America/Rainy_River', 'key' => '(UTC-06:00) Rainy River'],
|
||||||
|
['value' => 'America/Rankin_Inlet', 'key' => '(UTC-06:00) Rankin Inlet'],
|
||||||
|
['value' => 'America/Regina', 'key' => '(UTC-06:00) Regina'],
|
||||||
|
['value' => 'America/Resolute', 'key' => '(UTC-06:00) Resolute'],
|
||||||
|
['value' => 'America/Swift_Current', 'key' => '(UTC-06:00) Swift Current'],
|
||||||
|
['value' => 'America/Tegucigalpa', 'key' => '(UTC-06:00) Tegucigalpa'],
|
||||||
|
['value' => 'America/Indiana/Tell_City', 'key' => '(UTC-06:00) Tell City'],
|
||||||
|
['value' => 'America/Winnipeg', 'key' => '(UTC-06:00) Winnipeg'],
|
||||||
|
['value' => 'America/Atikokan', 'key' => '(UTC-05:00) Atikokan'],
|
||||||
|
['value' => 'America/Bogota', 'key' => '(UTC-05:00) Bogota'],
|
||||||
|
['value' => 'America/Cayman', 'key' => '(UTC-05:00) Cayman'],
|
||||||
|
['value' => 'America/Detroit', 'key' => '(UTC-05:00) Detroit'],
|
||||||
|
['value' => 'America/Grand_Turk', 'key' => '(UTC-05:00) Grand Turk'],
|
||||||
|
['value' => 'America/Guayaquil', 'key' => '(UTC-05:00) Guayaquil'],
|
||||||
|
['value' => 'America/Havana', 'key' => '(UTC-05:00) Havana'],
|
||||||
|
['value' => 'America/Indiana/Indianapolis', 'key' => '(UTC-05:00) Indianapolis'],
|
||||||
|
['value' => 'America/Iqaluit', 'key' => '(UTC-05:00) Iqaluit'],
|
||||||
|
['value' => 'America/Jamaica', 'key' => '(UTC-05:00) Jamaica'],
|
||||||
|
['value' => 'America/Lima', 'key' => '(UTC-05:00) Lima'],
|
||||||
|
['value' => 'America/Kentucky/Louisville', 'key' => '(UTC-05:00) Louisville'],
|
||||||
|
['value' => 'America/Indiana/Marengo', 'key' => '(UTC-05:00) Marengo'],
|
||||||
|
['value' => 'America/Kentucky/Monticello', 'key' => '(UTC-05:00) Monticello'],
|
||||||
|
['value' => 'America/Montreal', 'key' => '(UTC-05:00) Montreal'],
|
||||||
|
['value' => 'America/Nassau', 'key' => '(UTC-05:00) Nassau'],
|
||||||
|
['value' => 'America/New_York', 'key' => '(UTC-05:00) New York'],
|
||||||
|
['value' => 'America/Nipigon', 'key' => '(UTC-05:00) Nipigon'],
|
||||||
|
['value' => 'America/Panama', 'key' => '(UTC-05:00) Panama'],
|
||||||
|
['value' => 'America/Pangnirtung', 'key' => '(UTC-05:00) Pangnirtung'],
|
||||||
|
['value' => 'America/Indiana/Petersburg', 'key' => '(UTC-05:00) Petersburg'],
|
||||||
|
['value' => 'America/Port-au-Prince', 'key' => '(UTC-05:00) Port-au-Prince'],
|
||||||
|
['value' => 'America/Thunder_Bay', 'key' => '(UTC-05:00) Thunder Bay'],
|
||||||
|
['value' => 'America/Toronto', 'key' => '(UTC-05:00) Toronto'],
|
||||||
|
['value' => 'America/Indiana/Vevay', 'key' => '(UTC-05:00) Vevay'],
|
||||||
|
['value' => 'America/Indiana/Vincennes', 'key' => '(UTC-05:00) Vincennes'],
|
||||||
|
['value' => 'America/Indiana/Winamac', 'key' => '(UTC-05:00) Winamac'],
|
||||||
|
['value' => 'America/Caracas', 'key' => '(UTC-04:30) Caracas'],
|
||||||
|
['value' => 'America/Anguilla', 'key' => '(UTC-04:00) Anguilla'],
|
||||||
|
['value' => 'America/Antigua', 'key' => '(UTC-04:00) Antigua'],
|
||||||
|
['value' => 'America/Aruba', 'key' => '(UTC-04:00) Aruba'],
|
||||||
|
['value' => 'America/Asuncion', 'key' => '(UTC-04:00) Asuncion'],
|
||||||
|
['value' => 'America/Barbados', 'key' => '(UTC-04:00) Barbados'],
|
||||||
|
['value' => 'Atlantic/Bermuda', 'key' => '(UTC-04:00) Bermuda'],
|
||||||
|
['value' => 'America/Blanc-Sablon', 'key' => '(UTC-04:00) Blanc-Sablon'],
|
||||||
|
['value' => 'America/Boa_Vista', 'key' => '(UTC-04:00) Boa Vista'],
|
||||||
|
['value' => 'America/Campo_Grande', 'key' => '(UTC-04:00) Campo Grande'],
|
||||||
|
['value' => 'America/Cuiaba', 'key' => '(UTC-04:00) Cuiaba'],
|
||||||
|
['value' => 'America/Curacao', 'key' => '(UTC-04:00) Curacao'],
|
||||||
|
['value' => 'America/Dominica', 'key' => '(UTC-04:00) Dominica'],
|
||||||
|
['value' => 'America/Eirunepe', 'key' => '(UTC-04:00) Eirunepe'],
|
||||||
|
['value' => 'America/Glace_Bay', 'key' => '(UTC-04:00) Glace Bay'],
|
||||||
|
['value' => 'America/Goose_Bay', 'key' => '(UTC-04:00) Goose Bay'],
|
||||||
|
['value' => 'America/Grenada', 'key' => '(UTC-04:00) Grenada'],
|
||||||
|
['value' => 'America/Guadeloupe', 'key' => '(UTC-04:00) Guadeloupe'],
|
||||||
|
['value' => 'America/Guyana', 'key' => '(UTC-04:00) Guyana'],
|
||||||
|
['value' => 'America/Halifax', 'key' => '(UTC-04:00) Halifax'],
|
||||||
|
['value' => 'America/Kralendijk', 'key' => '(UTC-04:00) Kralendijk'],
|
||||||
|
['value' => 'America/La_Paz', 'key' => '(UTC-04:00) La Paz'],
|
||||||
|
['value' => 'America/Lower_Princes', 'key' => '(UTC-04:00) Lower Princes'],
|
||||||
|
['value' => 'America/Manaus', 'key' => '(UTC-04:00) Manaus'],
|
||||||
|
['value' => 'America/Marigot', 'key' => '(UTC-04:00) Marigot'],
|
||||||
|
['value' => 'America/Martinique', 'key' => '(UTC-04:00) Martinique'],
|
||||||
|
['value' => 'America/Moncton', 'key' => '(UTC-04:00) Moncton'],
|
||||||
|
['value' => 'America/Montserrat', 'key' => '(UTC-04:00) Montserrat'],
|
||||||
|
['value' => 'Antarctica/Palmer', 'key' => '(UTC-04:00) Palmer'],
|
||||||
|
['value' => 'America/Port_of_Spain', 'key' => '(UTC-04:00) Port of Spain'],
|
||||||
|
['value' => 'America/Porto_Velho', 'key' => '(UTC-04:00) Porto Velho'],
|
||||||
|
['value' => 'America/Puerto_Rico', 'key' => '(UTC-04:00) Puerto Rico'],
|
||||||
|
['value' => 'America/Rio_Branco', 'key' => '(UTC-04:00) Rio Branco'],
|
||||||
|
['value' => 'America/Santiago', 'key' => '(UTC-04:00) Santiago'],
|
||||||
|
['value' => 'America/Santo_Domingo', 'key' => '(UTC-04:00) Santo Domingo'],
|
||||||
|
['value' => 'America/St_Barthelemy', 'key' => '(UTC-04:00) St. Barthelemy'],
|
||||||
|
['value' => 'America/St_Kitts', 'key' => '(UTC-04:00) St. Kitts'],
|
||||||
|
['value' => 'America/St_Lucia', 'key' => '(UTC-04:00) St. Lucia'],
|
||||||
|
['value' => 'America/St_Thomas', 'key' => '(UTC-04:00) St. Thomas'],
|
||||||
|
['value' => 'America/St_Vincent', 'key' => '(UTC-04:00) St. Vincent'],
|
||||||
|
['value' => 'America/Thule', 'key' => '(UTC-04:00) Thule'],
|
||||||
|
['value' => 'America/Tortola', 'key' => '(UTC-04:00) Tortola'],
|
||||||
|
['value' => 'America/St_Johns', 'key' => '(UTC-03:30) St. Johns'],
|
||||||
|
['value' => 'America/Araguaina', 'key' => '(UTC-03:00) Araguaina'],
|
||||||
|
['value' => 'America/Bahia', 'key' => '(UTC-03:00) Bahia'],
|
||||||
|
['value' => 'America/Belem', 'key' => '(UTC-03:00) Belem'],
|
||||||
|
['value' => 'America/Argentina/Buenos_Aires', 'key' => '(UTC-03:00) Buenos Aires'],
|
||||||
|
['value' => 'America/Argentina/Catamarca', 'key' => '(UTC-03:00) Catamarca'],
|
||||||
|
['value' => 'America/Cayenne', 'key' => '(UTC-03:00) Cayenne'],
|
||||||
|
['value' => 'America/Argentina/Cordoba', 'key' => '(UTC-03:00) Cordoba'],
|
||||||
|
['value' => 'America/Fortaleza', 'key' => '(UTC-03:00) Fortaleza'],
|
||||||
|
['value' => 'America/Godthab', 'key' => '(UTC-03:00) Godthab'],
|
||||||
|
['value' => 'America/Argentina/Jujuy', 'key' => '(UTC-03:00) Jujuy'],
|
||||||
|
['value' => 'America/Argentina/La_Rioja', 'key' => '(UTC-03:00) La Rioja'],
|
||||||
|
['value' => 'America/Maceio', 'key' => '(UTC-03:00) Maceio'],
|
||||||
|
['value' => 'America/Argentina/Mendoza', 'key' => '(UTC-03:00) Mendoza'],
|
||||||
|
['value' => 'America/Miquelon', 'key' => '(UTC-03:00) Miquelon'],
|
||||||
|
['value' => 'America/Montevideo', 'key' => '(UTC-03:00) Montevideo'],
|
||||||
|
['value' => 'America/Paramaribo', 'key' => '(UTC-03:00) Paramaribo'],
|
||||||
|
['value' => 'America/Recife', 'key' => '(UTC-03:00) Recife'],
|
||||||
|
['value' => 'America/Argentina/Rio_Gallegos', 'key' => '(UTC-03:00) Rio Gallegos'],
|
||||||
|
['value' => 'Antarctica/Rothera', 'key' => '(UTC-03:00) Rothera'],
|
||||||
|
['value' => 'America/Argentina/Salta', 'key' => '(UTC-03:00) Salta'],
|
||||||
|
['value' => 'America/Argentina/San_Juan', 'key' => '(UTC-03:00) San Juan'],
|
||||||
|
['value' => 'America/Argentina/San_Luis', 'key' => '(UTC-03:00) San Luis'],
|
||||||
|
['value' => 'America/Santarem', 'key' => '(UTC-03:00) Santarem'],
|
||||||
|
['value' => 'America/Sao_Paulo', 'key' => '(UTC-03:00) Sao Paulo'],
|
||||||
|
['value' => 'Atlantic/Stanley', 'key' => '(UTC-03:00) Stanley'],
|
||||||
|
['value' => 'America/Argentina/Tucuman', 'key' => '(UTC-03:00) Tucuman'],
|
||||||
|
['value' => 'America/Argentina/Ushuaia', 'key' => '(UTC-03:00) Ushuaia'],
|
||||||
|
['value' => 'America/Noronha', 'key' => '(UTC-02:00) Noronha'],
|
||||||
|
['value' => 'Atlantic/South_Georgia', 'key' => '(UTC-02:00) South Georgia'],
|
||||||
|
['value' => 'Atlantic/Azores', 'key' => '(UTC-01:00) Azores'],
|
||||||
|
['value' => 'Atlantic/Cape_Verde', 'key' => '(UTC-01:00) Cape Verde'],
|
||||||
|
['value' => 'America/Scoresbysund', 'key' => '(UTC-01:00) Scoresbysund'],
|
||||||
|
['value' => 'Africa/Abidjan', 'key' => '(UTC+00:00) Abidjan'],
|
||||||
|
['value' => 'Africa/Accra', 'key' => '(UTC+00:00) Accra'],
|
||||||
|
['value' => 'Africa/Bamako', 'key' => '(UTC+00:00) Bamako'],
|
||||||
|
['value' => 'Africa/Banjul', 'key' => '(UTC+00:00) Banjul'],
|
||||||
|
['value' => 'Africa/Bissau', 'key' => '(UTC+00:00) Bissau'],
|
||||||
|
['value' => 'Atlantic/Canary', 'key' => '(UTC+00:00) Canary'],
|
||||||
|
['value' => 'Africa/Casablanca', 'key' => '(UTC+00:00) Casablanca'],
|
||||||
|
['value' => 'Africa/Conakry', 'key' => '(UTC+00:00) Conakry'],
|
||||||
|
['value' => 'Africa/Dakar', 'key' => '(UTC+00:00) Dakar'],
|
||||||
|
['value' => 'America/Danmarkshavn', 'key' => '(UTC+00:00) Danmarkshavn'],
|
||||||
|
['value' => 'Europe/Dublin', 'key' => '(UTC+00:00) Dublin'],
|
||||||
|
['value' => 'Africa/El_Aaiun', 'key' => '(UTC+00:00) El Aaiun'],
|
||||||
|
['value' => 'Atlantic/Faroe', 'key' => '(UTC+00:00) Faroe'],
|
||||||
|
['value' => 'Africa/Freetown', 'key' => '(UTC+00:00) Freetown'],
|
||||||
|
['value' => 'Europe/Guernsey', 'key' => '(UTC+00:00) Guernsey'],
|
||||||
|
['value' => 'Europe/Isle_of_Man', 'key' => '(UTC+00:00) Isle of Man'],
|
||||||
|
['value' => 'Europe/Jersey', 'key' => '(UTC+00:00) Jersey'],
|
||||||
|
['value' => 'Europe/Lisbon', 'key' => '(UTC+00:00) Lisbon'],
|
||||||
|
['value' => 'Africa/Lome', 'key' => '(UTC+00:00) Lome'],
|
||||||
|
['value' => 'Europe/London', 'key' => '(UTC+00:00) London'],
|
||||||
|
['value' => 'Atlantic/Madeira', 'key' => '(UTC+00:00) Madeira'],
|
||||||
|
['value' => 'Africa/Monrovia', 'key' => '(UTC+00:00) Monrovia'],
|
||||||
|
['value' => 'Africa/Nouakchott', 'key' => '(UTC+00:00) Nouakchott'],
|
||||||
|
['value' => 'Africa/Ouagadougou', 'key' => '(UTC+00:00) Ouagadougou'],
|
||||||
|
['value' => 'Atlantic/Reykjavik', 'key' => '(UTC+00:00) Reykjavik'],
|
||||||
|
['value' => 'Africa/Sao_Tome', 'key' => '(UTC+00:00) Sao Tome'],
|
||||||
|
['value' => 'Atlantic/St_Helena', 'key' => '(UTC+00:00) St. Helena'],
|
||||||
|
['value' => 'UTC', 'key' => '(UTC+00:00) UTC'],
|
||||||
|
['value' => 'Africa/Algiers', 'key' => '(UTC+01:00) Algiers'],
|
||||||
|
['value' => 'Europe/Amsterdam', 'key' => '(UTC+01:00) Amsterdam'],
|
||||||
|
['value' => 'Europe/Andorra', 'key' => '(UTC+01:00) Andorra'],
|
||||||
|
['value' => 'Africa/Bangui', 'key' => '(UTC+01:00) Bangui'],
|
||||||
|
['value' => 'Europe/Belgrade', 'key' => '(UTC+01:00) Belgrade'],
|
||||||
|
['value' => 'Europe/Berlin', 'key' => '(UTC+01:00) Berlin'],
|
||||||
|
['value' => 'Europe/Bratislava', 'key' => '(UTC+01:00) Bratislava'],
|
||||||
|
['value' => 'Africa/Brazzaville', 'key' => '(UTC+01:00) Brazzaville'],
|
||||||
|
['value' => 'Europe/Brussels', 'key' => '(UTC+01:00) Brussels'],
|
||||||
|
['value' => 'Europe/Budapest', 'key' => '(UTC+01:00) Budapest'],
|
||||||
|
['value' => 'Europe/Busingen', 'key' => '(UTC+01:00) Busingen'],
|
||||||
|
['value' => 'Africa/Ceuta', 'key' => '(UTC+01:00) Ceuta'],
|
||||||
|
['value' => 'Europe/Copenhagen', 'key' => '(UTC+01:00) Copenhagen'],
|
||||||
|
['value' => 'Africa/Douala', 'key' => '(UTC+01:00) Douala'],
|
||||||
|
['value' => 'Europe/Gibraltar', 'key' => '(UTC+01:00) Gibraltar'],
|
||||||
|
['value' => 'Africa/Kinshasa', 'key' => '(UTC+01:00) Kinshasa'],
|
||||||
|
['value' => 'Africa/Lagos', 'key' => '(UTC+01:00) Lagos'],
|
||||||
|
['value' => 'Africa/Libreville', 'key' => '(UTC+01:00) Libreville'],
|
||||||
|
['value' => 'Europe/Ljubljana', 'key' => '(UTC+01:00) Ljubljana'],
|
||||||
|
['value' => 'Arctic/Longyearbyen', 'key' => '(UTC+01:00) Longyearbyen'],
|
||||||
|
['value' => 'Africa/Luanda', 'key' => '(UTC+01:00) Luanda'],
|
||||||
|
['value' => 'Europe/Luxembourg', 'key' => '(UTC+01:00) Luxembourg'],
|
||||||
|
['value' => 'Europe/Madrid', 'key' => '(UTC+01:00) Madrid'],
|
||||||
|
['value' => 'Africa/Malabo', 'key' => '(UTC+01:00) Malabo'],
|
||||||
|
['value' => 'Europe/Malta', 'key' => '(UTC+01:00) Malta'],
|
||||||
|
['value' => 'Europe/Monaco', 'key' => '(UTC+01:00) Monaco'],
|
||||||
|
['value' => 'Africa/Ndjamena', 'key' => '(UTC+01:00) Ndjamena'],
|
||||||
|
['value' => 'Africa/Niamey', 'key' => '(UTC+01:00) Niamey'],
|
||||||
|
['value' => 'Europe/Oslo', 'key' => '(UTC+01:00) Oslo'],
|
||||||
|
['value' => 'Europe/Paris', 'key' => '(UTC+01:00) Paris'],
|
||||||
|
['value' => 'Europe/Podgorica', 'key' => '(UTC+01:00) Podgorica'],
|
||||||
|
['value' => 'Africa/Porto-Novo', 'key' => '(UTC+01:00) Porto-Novo'],
|
||||||
|
['value' => 'Europe/Prague', 'key' => '(UTC+01:00) Prague'],
|
||||||
|
['value' => 'Europe/Rome', 'key' => '(UTC+01:00) Rome'],
|
||||||
|
['value' => 'Europe/San_Marino', 'key' => '(UTC+01:00) San Marino'],
|
||||||
|
['value' => 'Europe/Sarajevo', 'key' => '(UTC+01:00) Sarajevo'],
|
||||||
|
['value' => 'Europe/Skopje', 'key' => '(UTC+01:00) Skopje'],
|
||||||
|
['value' => 'Europe/Stockholm', 'key' => '(UTC+01:00) Stockholm'],
|
||||||
|
['value' => 'Europe/Tirane', 'key' => '(UTC+01:00) Tirane'],
|
||||||
|
['value' => 'Africa/Tripoli', 'key' => '(UTC+01:00) Tripoli'],
|
||||||
|
['value' => 'Africa/Tunis', 'key' => '(UTC+01:00) Tunis'],
|
||||||
|
['value' => 'Europe/Vaduz', 'key' => '(UTC+01:00) Vaduz'],
|
||||||
|
['value' => 'Europe/Vatican', 'key' => '(UTC+01:00) Vatican'],
|
||||||
|
['value' => 'Europe/Vienna', 'key' => '(UTC+01:00) Vienna'],
|
||||||
|
['value' => 'Europe/Warsaw', 'key' => '(UTC+01:00) Warsaw'],
|
||||||
|
['value' => 'Africa/Windhoek', 'key' => '(UTC+01:00) Windhoek'],
|
||||||
|
['value' => 'Europe/Zagreb', 'key' => '(UTC+01:00) Zagreb'],
|
||||||
|
['value' => 'Europe/Zurich', 'key' => '(UTC+01:00) Zurich'],
|
||||||
|
['value' => 'Europe/Athens', 'key' => '(UTC+02:00) Athens'],
|
||||||
|
['value' => 'Asia/Beirut', 'key' => '(UTC+02:00) Beirut'],
|
||||||
|
['value' => 'Africa/Blantyre', 'key' => '(UTC+02:00) Blantyre'],
|
||||||
|
['value' => 'Europe/Bucharest', 'key' => '(UTC+02:00) Bucharest'],
|
||||||
|
['value' => 'Africa/Bujumbura', 'key' => '(UTC+02:00) Bujumbura'],
|
||||||
|
['value' => 'Africa/Cairo', 'key' => '(UTC+02:00) Cairo'],
|
||||||
|
['value' => 'Europe/Chisinau', 'key' => '(UTC+02:00) Chisinau'],
|
||||||
|
['value' => 'Asia/Damascus', 'key' => '(UTC+02:00) Damascus'],
|
||||||
|
['value' => 'Africa/Gaborone', 'key' => '(UTC+02:00) Gaborone'],
|
||||||
|
['value' => 'Asia/Gaza', 'key' => '(UTC+02:00) Gaza'],
|
||||||
|
['value' => 'Africa/Harare', 'key' => '(UTC+02:00) Harare'],
|
||||||
|
['value' => 'Asia/Hebron', 'key' => '(UTC+02:00) Hebron'],
|
||||||
|
['value' => 'Europe/Helsinki', 'key' => '(UTC+02:00) Helsinki'],
|
||||||
|
['value' => 'Europe/Istanbul', 'key' => '(UTC+02:00) Istanbul'],
|
||||||
|
['value' => 'Asia/Jerusalem', 'key' => '(UTC+02:00) Jerusalem'],
|
||||||
|
['value' => 'Africa/Johannesburg', 'key' => '(UTC+02:00) Johannesburg'],
|
||||||
|
['value' => 'Europe/Kiev', 'key' => '(UTC+02:00) Kiev'],
|
||||||
|
['value' => 'Africa/Kigali', 'key' => '(UTC+02:00) Kigali'],
|
||||||
|
['value' => 'Africa/Lubumbashi', 'key' => '(UTC+02:00) Lubumbashi'],
|
||||||
|
['value' => 'Africa/Lusaka', 'key' => '(UTC+02:00) Lusaka'],
|
||||||
|
['value' => 'Africa/Maputo', 'key' => '(UTC+02:00) Maputo'],
|
||||||
|
['value' => 'Europe/Mariehamn', 'key' => '(UTC+02:00) Mariehamn'],
|
||||||
|
['value' => 'Africa/Maseru', 'key' => '(UTC+02:00) Maseru'],
|
||||||
|
['value' => 'Africa/Mbabane', 'key' => '(UTC+02:00) Mbabane'],
|
||||||
|
['value' => 'Asia/Nicosia', 'key' => '(UTC+02:00) Nicosia'],
|
||||||
|
['value' => 'Europe/Riga', 'key' => '(UTC+02:00) Riga'],
|
||||||
|
['value' => 'Europe/Simferopol', 'key' => '(UTC+02:00) Simferopol'],
|
||||||
|
['value' => 'Europe/Sofia', 'key' => '(UTC+02:00) Sofia'],
|
||||||
|
['value' => 'Europe/Tallinn', 'key' => '(UTC+02:00) Tallinn'],
|
||||||
|
['value' => 'Europe/Uzhgorod', 'key' => '(UTC+02:00) Uzhgorod'],
|
||||||
|
['value' => 'Europe/Vilnius', 'key' => '(UTC+02:00) Vilnius'],
|
||||||
|
['value' => 'Europe/Zaporozhye', 'key' => '(UTC+02:00) Zaporozhye'],
|
||||||
|
['value' => 'Africa/Addis_Ababa', 'key' => '(UTC+03:00) Addis Ababa'],
|
||||||
|
['value' => 'Asia/Aden', 'key' => '(UTC+03:00) Aden'],
|
||||||
|
['value' => 'Asia/Amman', 'key' => '(UTC+03:00) Amman'],
|
||||||
|
['value' => 'Indian/Antananarivo', 'key' => '(UTC+03:00) Antananarivo'],
|
||||||
|
['value' => 'Africa/Asmara', 'key' => '(UTC+03:00) Asmara'],
|
||||||
|
['value' => 'Asia/Baghdad', 'key' => '(UTC+03:00) Baghdad'],
|
||||||
|
['value' => 'Asia/Bahrain', 'key' => '(UTC+03:00) Bahrain'],
|
||||||
|
['value' => 'Indian/Comoro', 'key' => '(UTC+03:00) Comoro'],
|
||||||
|
['value' => 'Africa/Dar_es_Salaam', 'key' => '(UTC+03:00) Dar es Salaam'],
|
||||||
|
['value' => 'Africa/Djibouti', 'key' => '(UTC+03:00) Djibouti'],
|
||||||
|
['value' => 'Africa/Juba', 'key' => '(UTC+03:00) Juba'],
|
||||||
|
['value' => 'Europe/Kaliningrad', 'key' => '(UTC+03:00) Kaliningrad'],
|
||||||
|
['value' => 'Africa/Kampala', 'key' => '(UTC+03:00) Kampala'],
|
||||||
|
['value' => 'Africa/Khartoum', 'key' => '(UTC+03:00) Khartoum'],
|
||||||
|
['value' => 'Asia/Kuwait', 'key' => '(UTC+03:00) Kuwait'],
|
||||||
|
['value' => 'Indian/Mayotte', 'key' => '(UTC+03:00) Mayotte'],
|
||||||
|
['value' => 'Europe/Minsk', 'key' => '(UTC+03:00) Minsk'],
|
||||||
|
['value' => 'Africa/Mogadishu', 'key' => '(UTC+03:00) Mogadishu'],
|
||||||
|
['value' => 'Africa/Nairobi', 'key' => '(UTC+03:00) Nairobi'],
|
||||||
|
['value' => 'Asia/Qatar', 'key' => '(UTC+03:00) Qatar'],
|
||||||
|
['value' => 'Asia/Riyadh', 'key' => '(UTC+03:00) Riyadh'],
|
||||||
|
['value' => 'Antarctica/Syowa', 'key' => '(UTC+03:00) Syowa'],
|
||||||
|
['value' => 'Asia/Tehran', 'key' => '(UTC+03:30) Tehran'],
|
||||||
|
['value' => 'Asia/Baku', 'key' => '(UTC+04:00) Baku'],
|
||||||
|
['value' => 'Asia/Dubai', 'key' => '(UTC+04:00) Dubai'],
|
||||||
|
['value' => 'Indian/Mahe', 'key' => '(UTC+04:00) Mahe'],
|
||||||
|
['value' => 'Indian/Mauritius', 'key' => '(UTC+04:00) Mauritius'],
|
||||||
|
['value' => 'Europe/Moscow', 'key' => '(UTC+04:00) Moscow'],
|
||||||
|
['value' => 'Asia/Muscat', 'key' => '(UTC+04:00) Muscat'],
|
||||||
|
['value' => 'Indian/Reunion', 'key' => '(UTC+04:00) Reunion'],
|
||||||
|
['value' => 'Europe/Samara', 'key' => '(UTC+04:00) Samara'],
|
||||||
|
['value' => 'Asia/Tbilisi', 'key' => '(UTC+04:00) Tbilisi'],
|
||||||
|
['value' => 'Europe/Volgograd', 'key' => '(UTC+04:00) Volgograd'],
|
||||||
|
['value' => 'Asia/Yerevan', 'key' => '(UTC+04:00) Yerevan'],
|
||||||
|
['value' => 'Asia/Kabul', 'key' => '(UTC+04:30) Kabul'],
|
||||||
|
['value' => 'Asia/Aqtau', 'key' => '(UTC+05:00) Aqtau'],
|
||||||
|
['value' => 'Asia/Aqtobe', 'key' => '(UTC+05:00) Aqtobe'],
|
||||||
|
['value' => 'Asia/Ashgabat', 'key' => '(UTC+05:00) Ashgabat'],
|
||||||
|
['value' => 'Asia/Dushanbe', 'key' => '(UTC+05:00) Dushanbe'],
|
||||||
|
['value' => 'Asia/Karachi', 'key' => '(UTC+05:00) Karachi'],
|
||||||
|
['value' => 'Indian/Kerguelen', 'key' => '(UTC+05:00) Kerguelen'],
|
||||||
|
['value' => 'Indian/Maldives', 'key' => '(UTC+05:00) Maldives'],
|
||||||
|
['value' => 'Antarctica/Mawson', 'key' => '(UTC+05:00) Mawson'],
|
||||||
|
['value' => 'Asia/Oral', 'key' => '(UTC+05:00) Oral'],
|
||||||
|
['value' => 'Asia/Samarkand', 'key' => '(UTC+05:00) Samarkand'],
|
||||||
|
['value' => 'Asia/Tashkent', 'key' => '(UTC+05:00) Tashkent'],
|
||||||
|
['value' => 'Asia/Colombo', 'key' => '(UTC+05:30) Colombo'],
|
||||||
|
['value' => 'Asia/Kolkata', 'key' => '(UTC+05:30) Kolkata'],
|
||||||
|
['value' => 'Asia/Kathmandu', 'key' => '(UTC+05:45) Kathmandu'],
|
||||||
|
['value' => 'Asia/Almaty', 'key' => '(UTC+06:00) Almaty'],
|
||||||
|
['value' => 'Asia/Bishkek', 'key' => '(UTC+06:00) Bishkek'],
|
||||||
|
['value' => 'Indian/Chagos', 'key' => '(UTC+06:00) Chagos'],
|
||||||
|
['value' => 'Asia/Dhaka', 'key' => '(UTC+06:00) Dhaka'],
|
||||||
|
['value' => 'Asia/Qyzylorda', 'key' => '(UTC+06:00) Qyzylorda'],
|
||||||
|
['value' => 'Asia/Thimphu', 'key' => '(UTC+06:00) Thimphu'],
|
||||||
|
['value' => 'Antarctica/Vostok', 'key' => '(UTC+06:00) Vostok'],
|
||||||
|
['value' => 'Asia/Yekaterinburg', 'key' => '(UTC+06:00) Yekaterinburg'],
|
||||||
|
['value' => 'Indian/Cocos', 'key' => '(UTC+06:30) Cocos'],
|
||||||
|
['value' => 'Asia/Rangoon', 'key' => '(UTC+06:30) Rangoon'],
|
||||||
|
['value' => 'Asia/Bangkok', 'key' => '(UTC+07:00) Bangkok'],
|
||||||
|
['value' => 'Indian/Christmas', 'key' => '(UTC+07:00) Christmas'],
|
||||||
|
['value' => 'Antarctica/Davis', 'key' => '(UTC+07:00) Davis'],
|
||||||
|
['value' => 'Asia/Ho_Chi_Minh', 'key' => '(UTC+07:00) Ho Chi Minh'],
|
||||||
|
['value' => 'Asia/Hovd', 'key' => '(UTC+07:00) Hovd'],
|
||||||
|
['value' => 'Asia/Jakarta', 'key' => '(UTC+07:00) Jakarta'],
|
||||||
|
['value' => 'Asia/Novokuznetsk', 'key' => '(UTC+07:00) Novokuznetsk'],
|
||||||
|
['value' => 'Asia/Novosibirsk', 'key' => '(UTC+07:00) Novosibirsk'],
|
||||||
|
['value' => 'Asia/Omsk', 'key' => '(UTC+07:00) Omsk'],
|
||||||
|
['value' => 'Asia/Phnom_Penh', 'key' => '(UTC+07:00) Phnom Penh'],
|
||||||
|
['value' => 'Asia/Pontianak', 'key' => '(UTC+07:00) Pontianak'],
|
||||||
|
['value' => 'Asia/Vientiane', 'key' => '(UTC+07:00) Vientiane'],
|
||||||
|
['value' => 'Asia/Brunei', 'key' => '(UTC+08:00) Brunei'],
|
||||||
|
['value' => 'Antarctica/Casey', 'key' => '(UTC+08:00) Casey'],
|
||||||
|
['value' => 'Asia/Choibalsan', 'key' => '(UTC+08:00) Choibalsan'],
|
||||||
|
['value' => 'Asia/Chongqing', 'key' => '(UTC+08:00) Chongqing'],
|
||||||
|
['value' => 'Asia/Harbin', 'key' => '(UTC+08:00) Harbin'],
|
||||||
|
['value' => 'Asia/Hong_Kong', 'key' => '(UTC+08:00) Hong Kong'],
|
||||||
|
['value' => 'Asia/Kashgar', 'key' => '(UTC+08:00) Kashgar'],
|
||||||
|
['value' => 'Asia/Krasnoyarsk', 'key' => '(UTC+08:00) Krasnoyarsk'],
|
||||||
|
['value' => 'Asia/Kuala_Lumpur', 'key' => '(UTC+08:00) Kuala Lumpur'],
|
||||||
|
['value' => 'Asia/Kuching', 'key' => '(UTC+08:00) Kuching'],
|
||||||
|
['value' => 'Asia/Macau', 'key' => '(UTC+08:00) Macau'],
|
||||||
|
['value' => 'Asia/Makassar', 'key' => '(UTC+08:00) Makassar'],
|
||||||
|
['value' => 'Asia/Manila', 'key' => '(UTC+08:00) Manila'],
|
||||||
|
['value' => 'Australia/Perth', 'key' => '(UTC+08:00) Perth'],
|
||||||
|
['value' => 'Asia/Shanghai', 'key' => '(UTC+08:00) Shanghai'],
|
||||||
|
['value' => 'Asia/Singapore', 'key' => '(UTC+08:00) Singapore'],
|
||||||
|
['value' => 'Asia/Taipei', 'key' => '(UTC+08:00) Taipei'],
|
||||||
|
['value' => 'Asia/Ulaanbaatar', 'key' => '(UTC+08:00) Ulaanbaatar'],
|
||||||
|
['value' => 'Asia/Urumqi', 'key' => '(UTC+08:00) Urumqi'],
|
||||||
|
['value' => 'Australia/Eucla', 'key' => '(UTC+08:45) Eucla'],
|
||||||
|
['value' => 'Asia/Dili', 'key' => '(UTC+09:00) Dili'],
|
||||||
|
['value' => 'Asia/Irkutsk', 'key' => '(UTC+09:00) Irkutsk'],
|
||||||
|
['value' => 'Asia/Jayapura', 'key' => '(UTC+09:00) Jayapura'],
|
||||||
|
['value' => 'Pacific/Palau', 'key' => '(UTC+09:00) Palau'],
|
||||||
|
['value' => 'Asia/Pyongyang', 'key' => '(UTC+09:00) Pyongyang'],
|
||||||
|
['value' => 'Asia/Seoul', 'key' => '(UTC+09:00) Seoul'],
|
||||||
|
['value' => 'Asia/Tokyo', 'key' => '(UTC+09:00) Tokyo'],
|
||||||
|
['value' => 'Australia/Adelaide', 'key' => '(UTC+09:30) Adelaide'],
|
||||||
|
['value' => 'Australia/Broken_Hill', 'key' => '(UTC+09:30) Broken Hill'],
|
||||||
|
['value' => 'Australia/Darwin', 'key' => '(UTC+09:30) Darwin'],
|
||||||
|
['value' => 'Australia/Brisbane', 'key' => '(UTC+10:00) Brisbane'],
|
||||||
|
['value' => 'Pacific/Chuuk', 'key' => '(UTC+10:00) Chuuk'],
|
||||||
|
['value' => 'Australia/Currie', 'key' => '(UTC+10:00) Currie'],
|
||||||
|
['value' => 'Antarctica/DumontDUrville', 'key' => '(UTC+10:00) DumontDUrville'],
|
||||||
|
['value' => 'Pacific/Guam', 'key' => '(UTC+10:00) Guam'],
|
||||||
|
['value' => 'Australia/Hobart', 'key' => '(UTC+10:00) Hobart'],
|
||||||
|
['value' => 'Asia/Khandyga', 'key' => '(UTC+10:00) Khandyga'],
|
||||||
|
['value' => 'Australia/Lindeman', 'key' => '(UTC+10:00) Lindeman'],
|
||||||
|
['value' => 'Australia/Melbourne', 'key' => '(UTC+10:00) Melbourne'],
|
||||||
|
['value' => 'Pacific/Port_Moresby', 'key' => '(UTC+10:00) Port Moresby'],
|
||||||
|
['value' => 'Pacific/Saipan', 'key' => '(UTC+10:00) Saipan'],
|
||||||
|
['value' => 'Australia/Sydney', 'key' => '(UTC+10:00) Sydney'],
|
||||||
|
['value' => 'Asia/Yakutsk', 'key' => '(UTC+10:00) Yakutsk'],
|
||||||
|
['value' => 'Australia/Lord_Howe', 'key' => '(UTC+10:30) Lord Howe'],
|
||||||
|
['value' => 'Pacific/Efate', 'key' => '(UTC+11:00) Efate'],
|
||||||
|
['value' => 'Pacific/Guadalcanal', 'key' => '(UTC+11:00) Guadalcanal'],
|
||||||
|
['value' => 'Pacific/Kosrae', 'key' => '(UTC+11:00) Kosrae'],
|
||||||
|
['value' => 'Antarctica/Macquarie', 'key' => '(UTC+11:00) Macquarie'],
|
||||||
|
['value' => 'Pacific/Noumea', 'key' => '(UTC+11:00) Noumea'],
|
||||||
|
['value' => 'Pacific/Pohnpei', 'key' => '(UTC+11:00) Pohnpei'],
|
||||||
|
['value' => 'Asia/Sakhalin', 'key' => '(UTC+11:00) Sakhalin'],
|
||||||
|
['value' => 'Asia/Ust-Nera', 'key' => '(UTC+11:00) Ust-Nera'],
|
||||||
|
['value' => 'Asia/Vladivostok', 'key' => '(UTC+11:00) Vladivostok'],
|
||||||
|
['value' => 'Pacific/Norfolk', 'key' => '(UTC+11:30) Norfolk'],
|
||||||
|
['value' => 'Asia/Anadyr', 'key' => '(UTC+12:00) Anadyr'],
|
||||||
|
['value' => 'Pacific/Auckland', 'key' => '(UTC+12:00) Auckland'],
|
||||||
|
['value' => 'Pacific/Fiji', 'key' => '(UTC+12:00) Fiji'],
|
||||||
|
['value' => 'Pacific/Funafuti', 'key' => '(UTC+12:00) Funafuti'],
|
||||||
|
['value' => 'Asia/Kamchatka', 'key' => '(UTC+12:00) Kamchatka'],
|
||||||
|
['value' => 'Pacific/Kwajalein', 'key' => '(UTC+12:00) Kwajalein'],
|
||||||
|
['value' => 'Asia/Magadan', 'key' => '(UTC+12:00) Magadan'],
|
||||||
|
['value' => 'Pacific/Majuro', 'key' => '(UTC+12:00) Majuro'],
|
||||||
|
['value' => 'Antarctica/McMurdo', 'key' => '(UTC+12:00) McMurdo'],
|
||||||
|
['value' => 'Pacific/Nauru', 'key' => '(UTC+12:00) Nauru'],
|
||||||
|
['value' => 'Antarctica/South_Pole', 'key' => '(UTC+12:00) South Pole'],
|
||||||
|
['value' => 'Pacific/Tarawa', 'key' => '(UTC+12:00) Tarawa'],
|
||||||
|
['value' => 'Pacific/Wake', 'key' => '(UTC+12:00) Wake'],
|
||||||
|
['value' => 'Pacific/Wallis', 'key' => '(UTC+12:00) Wallis'],
|
||||||
|
['value' => 'Pacific/Chatham', 'key' => '(UTC+12:45) Chatham'],
|
||||||
|
['value' => 'Pacific/Apia', 'key' => '(UTC+13:00) Apia'],
|
||||||
|
['value' => 'Pacific/Enderbury', 'key' => '(UTC+13:00) Enderbury'],
|
||||||
|
['value' => 'Pacific/Fakaofo', 'key' => '(UTC+13:00) Fakaofo'],
|
||||||
|
['value' => 'Pacific/Tongatapu', 'key' => '(UTC+13:00) Tongatapu'],
|
||||||
|
['value' => 'Pacific/Kiritimati', 'key' => '(UTC+14:00) Kiritimati'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
62
app/Space/helpers.php
Normal file
62
app/Space/helpers.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
use Laraspace\CompanySetting;
|
||||||
|
use Laraspace\Currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Active Path
|
||||||
|
*
|
||||||
|
* @param $path
|
||||||
|
* @param string $active
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function set_active($path, $active = 'active') {
|
||||||
|
|
||||||
|
return call_user_func_array('Request::is', (array)$path) ? $active : '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $path
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function is_url($path)
|
||||||
|
{
|
||||||
|
return call_user_func_array('Request::is', (array)$path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $string
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function clean_slug($string)
|
||||||
|
{
|
||||||
|
// Replaces all spaces with hyphens.
|
||||||
|
$string = str_replace(' ', '-', $string);
|
||||||
|
|
||||||
|
// Removes special chars.
|
||||||
|
return \Illuminate\Support\Str::lower(preg_replace('/[^A-Za-z0-9\-]/', '', $string));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $money
|
||||||
|
* @return formated_money
|
||||||
|
*/
|
||||||
|
function format_money_pdf($money)
|
||||||
|
{
|
||||||
|
$money = $money / 100;
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', 1));
|
||||||
|
$format_money = number_format(
|
||||||
|
$money,
|
||||||
|
$currency->precision,
|
||||||
|
$currency->decimal_separator,
|
||||||
|
$currency->thousand_separator
|
||||||
|
);
|
||||||
|
|
||||||
|
$currency_with_symbol = '';
|
||||||
|
if ($currency->swap_currency_symbol) {
|
||||||
|
$currency_with_symbol = $format_money.'<span style="font-family: DejaVu Sans;">'.$currency->symbol.'</span>';
|
||||||
|
} else {
|
||||||
|
$currency_with_symbol = '<span style="font-family: DejaVu Sans;">'.$currency->symbol.'</span>'.$format_money;
|
||||||
|
}
|
||||||
|
return $currency_with_symbol;
|
||||||
|
}
|
||||||
25
app/State.php
Normal file
25
app/State.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace Laraspace;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Laraspace\City;
|
||||||
|
use Laraspace\Country;
|
||||||
|
use Laraspace\Address;
|
||||||
|
|
||||||
|
class State extends Model
|
||||||
|
{
|
||||||
|
public function cities()
|
||||||
|
{
|
||||||
|
return $this->hasMany(City::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function country()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Country::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function address()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Address::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user