mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
Compare commits
304 Commits
1.0.0
...
Geoffry304
| Author | SHA1 | Date | |
|---|---|---|---|
| a0a46d306e | |||
| 8f0af3dcd6 | |||
| 53860378b9 | |||
| e8e44c5dc8 | |||
| ac33164342 | |||
| 5c7c0d84ea | |||
| 7ca725ac37 | |||
| 510a4b3dbb | |||
| 25114009e3 | |||
| 79c16d74ce | |||
| 742e1e445a | |||
| 386f96d60e | |||
| 82d85af672 | |||
| 4d1b267688 | |||
| bc99ad63a6 | |||
| 4bb44f8c93 | |||
| c72265ed50 | |||
| b8958c9eb6 | |||
| e33e314cb7 | |||
| 84cebee9da | |||
| 34d3cf7ae8 | |||
| 93d0da836a | |||
| fd51276948 | |||
| d6274854ba | |||
| ea4bd1a31d | |||
| 286e047963 | |||
| be16f48f3d | |||
| ebea1e0813 | |||
| cc8d08f829 | |||
| aacffc22eb | |||
| d71ca4ffb9 | |||
| 186004f7f8 | |||
| c2eb22d666 | |||
| af189b15b6 | |||
| 1c19be85c3 | |||
| 4bb4362d23 | |||
| f6f66b3ae6 | |||
| b4ccecbcf1 | |||
| 92f1f196bb | |||
| ee14070a7b | |||
| 8ce7e14a02 | |||
| 3401ca049e | |||
| 5dcc7b9efd | |||
| 06a538bb81 | |||
| 7ab0419f27 | |||
| a7275aaa42 | |||
| bc4e6a05ea | |||
| ca170f5a87 | |||
| 3baeb72892 | |||
| 22e7e96dfa | |||
| fcfd1ddb7a | |||
| daf8c9265b | |||
| 406d098172 | |||
| 824d2e3e8d | |||
| 3cd975dbbd | |||
| 8e50c36a71 | |||
| b499741ab4 | |||
| 84f8d281a7 | |||
| b409cdb913 | |||
| fb49332de9 | |||
| 13e56105e3 | |||
| f68e86e4cf | |||
| da996c1f33 | |||
| 0990ce4678 | |||
| bb6fb2f49d | |||
| 400296575e | |||
| d58c790b1f | |||
| c674c2ab9e | |||
| d79692cf3b | |||
| 353c2479f1 | |||
| 0176a854b8 | |||
| 00548ea908 | |||
| 09e335a8a7 | |||
| 53e2ed253f | |||
| 06b035d9ac | |||
| 5c88cbcc42 | |||
| d9b175a676 | |||
| f5b9bc95c6 | |||
| 586dcdea0d | |||
| 50957fc179 | |||
| c725e4744b | |||
| 7479ce237e | |||
| 84420441c0 | |||
| ac96721e87 | |||
| db4c7f5e32 | |||
| 87dc78eea0 | |||
| e9c2898056 | |||
| b9c4570137 | |||
| 8e2525cc6c | |||
| 8862a93f23 | |||
| 82efd88920 | |||
| 0ef528d296 | |||
| 4c33a5d88c | |||
| d64d06181b | |||
| ef9cf2db22 | |||
| 96c295a003 | |||
| 22528f5b66 | |||
| 1cd9c72537 | |||
| 7253b43eb4 | |||
| 181964cf03 | |||
| 5914245ae4 | |||
| 1bf3d28d4e | |||
| dbcbd93ace | |||
| 1729c6a308 | |||
| 019493cbfa | |||
| 60540ba966 | |||
| 601ad419ec | |||
| 80e7bab891 | |||
| f5c8befbf0 | |||
| 09c984baa7 | |||
| 0d93260672 | |||
| 3e9e217f92 | |||
| 3cd8859c62 | |||
| 4493b4a419 | |||
| 79e3e70bd6 | |||
| 56a955befd | |||
| 496c28f80d | |||
| 7a59f3fe0c | |||
| 3d6875a532 | |||
| 15bf380f4f | |||
| 0b910db039 | |||
| 0e5e8f602f | |||
| d9db0f9401 | |||
| c0da7c7339 | |||
| 7e7599b4a7 | |||
| 99cd88e6c6 | |||
| 053a06229c | |||
| 1a6e8280a8 | |||
| 125e8be83c | |||
| 4d89ca2101 | |||
| e8aee3bb32 | |||
| d3c7ca75f0 | |||
| 694d5f56d5 | |||
| a48439785c | |||
| 7c9bd84f00 | |||
| bd5a93d81c | |||
| 858e10953b | |||
| 3617032735 | |||
| 75ddc51b1e | |||
| 1dfa36e396 | |||
| d9e9a5a540 | |||
| ea6e11c324 | |||
| f55dfe0b46 | |||
| 3eac3b8af5 | |||
| 2b2bd4351a | |||
| b9c32bbdc1 | |||
| bceffbf6a0 | |||
| 7c6a40374d | |||
| d04e142a3e | |||
| f11436736b | |||
| 9271ceba45 | |||
| c88eb24265 | |||
| 5eb0a04378 | |||
| d926073095 | |||
| a691969025 | |||
| 7df06fb005 | |||
| 45db850025 | |||
| 18a50315ba | |||
| bce1b4bb3e | |||
| ddd204105f | |||
| e030d4b9d0 | |||
| 302968225a | |||
| e59bf288ce | |||
| b1fcd90b62 | |||
| ddb0ff1b8a | |||
| ce99fa3d82 | |||
| e28c89085d | |||
| 34f7e33abc | |||
| 80be7a492d | |||
| 387cb4490d | |||
| 09829a559e | |||
| b06fc5f0b9 | |||
| 5f7401f622 | |||
| 4f6dae919b | |||
| 36be395579 | |||
| 79e77f9e16 | |||
| cbf0af2120 | |||
| 92f754e888 | |||
| a6896eaa01 | |||
| 01f3646869 | |||
| b2918e9dbb | |||
| 0a064ec5ba | |||
| 5f0b4b3496 | |||
| 17b59f0d19 | |||
| 283b910cc3 | |||
| 81739827c0 | |||
| 90edc3a85e | |||
| 655c2a7849 | |||
| ca833d174e | |||
| 33e8381fc4 | |||
| 9b5125d440 | |||
| 2899021804 | |||
| d8f6d03d1e | |||
| c474e98925 | |||
| 799d212d9b | |||
| 9424dc6c27 | |||
| fa15502ce7 | |||
| 1f4d3bf784 | |||
| 3692373cd2 | |||
| 7bba576dca | |||
| 05454af593 | |||
| 74fe481ed5 | |||
| 1cd654b0cc | |||
| f4a4c05b61 | |||
| 24637bff4a | |||
| 887ad9a73d | |||
| 339099bd34 | |||
| 9b9761aa5a | |||
| 0c71356f59 | |||
| e539bb501d | |||
| 2fcd169270 | |||
| 00c917853c | |||
| 122c4f478f | |||
| edc0e115e4 | |||
| b388e7a237 | |||
| 6e3ed9b4f6 | |||
| 338dbb26a1 | |||
| f10e5e9d11 | |||
| 3a046b638c | |||
| 36242c516a | |||
| 14d71fedb3 | |||
| c8843eb544 | |||
| 7fe9a4c2a2 | |||
| 37f2b6dfc7 | |||
| c90c14312a | |||
| b5b861bb36 | |||
| ab041743a2 | |||
| 9bcec9bd75 | |||
| 7b697a477e | |||
| 146cf835b9 | |||
| ec87e72547 | |||
| bf2e8c9c99 | |||
| b6096aadfa | |||
| 1cbc41c3ce | |||
| f4ca6d4b73 | |||
| 66649590e5 | |||
| 1e8cc475ca | |||
| 98d76a2f92 | |||
| 7b50148c43 | |||
| aef6da8b7b | |||
| 0fb14afc08 | |||
| dad71b04dd | |||
| 80014b02b5 | |||
| 7c2a6700eb | |||
| 7e81013b15 | |||
| f0107129fb | |||
| 04cce64859 | |||
| 3b7637f3cf | |||
| 7333746948 | |||
| 0fa6049298 | |||
| 64be6ce957 | |||
| 0e075c03d8 | |||
| 5de195b56b | |||
| cd60f1b096 | |||
| 8058f9b022 | |||
| a484506029 | |||
| a69f99dc61 | |||
| c3583c98be | |||
| 813e574425 | |||
| ac431ca815 | |||
| 3158955d00 | |||
| dbc5950294 | |||
| 00a218fe87 | |||
| 4a92469465 | |||
| cd67ebd487 | |||
| 6853d0bb57 | |||
| 9afc19268a | |||
| f6faf10d43 | |||
| b061102c23 | |||
| e8b8cd9f04 | |||
| 9f4b5e02e8 | |||
| 1c84c1f843 | |||
| 23beb5cac7 | |||
| 2fb2f1fcc0 | |||
| 7c1529f890 | |||
| 8b54b48805 | |||
| 07601a7130 | |||
| 7fd1224502 | |||
| 1d56bd9f36 | |||
| a8783cc929 | |||
| 841ff06005 | |||
| 3a54167ec7 | |||
| bc18f9b198 | |||
| 6741f9849d | |||
| 14c0f7f486 | |||
| 095f3c0b31 | |||
| f2ad8286d7 | |||
| 18ad27d513 | |||
| 06807275b9 | |||
| 2ad39bfbd6 | |||
| 9f38947fe7 | |||
| 81c1e78bed | |||
| dd0817709b | |||
| 66a1156d5c | |||
| 1be2c7122e | |||
| e9218e4d21 | |||
| 812afc2dab | |||
| 4ec34550ed | |||
| 8bc5ea2d5e | |||
| ca6ab997de | |||
| 8b05909b74 | |||
| 1e6372cbb1 | |||
| d29c343911 | |||
| f3ef51bffb |
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@ -0,0 +1,10 @@
|
||||
.dockerignore
|
||||
.gitignore
|
||||
*.md
|
||||
.git/
|
||||
.idea/
|
||||
.DS_Store/
|
||||
docker-compose.*
|
||||
LICENSE
|
||||
nginx.conf
|
||||
yarn.lock
|
||||
@ -1,15 +1,15 @@
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:kgk/4DW1vEVy7aEvet5FPp5un6PIGe/so8H0mvoUtW0=
|
||||
APP_DEBUG=false
|
||||
APP_DEBUG=true
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_URL=http://crater.test
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_HOST=db
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=crater
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=bytefury
|
||||
DB_USERNAME=crater
|
||||
DB_PASSWORD="crater"
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
|
||||
12
.eslintrc
12
.eslintrc
@ -2,9 +2,17 @@
|
||||
"root": true,
|
||||
"extends": [
|
||||
"plugin:vue/recommended",
|
||||
"standard"
|
||||
"eslint:recommended",
|
||||
"prettier/vue",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"vue/max-attributes-per-line" : 3
|
||||
"vue/max-attributes-per-line": ["error", {
|
||||
"singleline": 10,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Please complete the following information:**
|
||||
- Crater version:
|
||||
- PHP version:
|
||||
- Database type and version:
|
||||
|
||||
**Optional info**
|
||||
- OS: [e.g. Ubuntu]
|
||||
- Browser: [e.g. chrome, safari]
|
||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,3 +11,5 @@ Homestead.yaml
|
||||
.rnd
|
||||
/.expo
|
||||
/.vscode
|
||||
docker-compose.yml
|
||||
docker-compose.yaml
|
||||
|
||||
5
.prettierrc.json
Normal file
5
.prettierrc.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2
|
||||
}
|
||||
53
Dockerfile
Normal file
53
Dockerfile
Normal file
@ -0,0 +1,53 @@
|
||||
##### STAGE 1 #####
|
||||
|
||||
FROM composer as composer
|
||||
|
||||
# Copy composer files from project root into composer container's working dir
|
||||
COPY composer.* /app/
|
||||
|
||||
# Copy database directory for autoloader optimization
|
||||
COPY database /app/database
|
||||
|
||||
# Run composer to build dependencies in vendor folder
|
||||
RUN composer install --no-scripts --no-suggest --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
# Copy everything from project root into composer container's working dir
|
||||
COPY . /app
|
||||
|
||||
RUN composer dump-autoload --optimize --classmap-authoritative
|
||||
|
||||
##### STAGE 2 #####
|
||||
|
||||
FROM php:7.3.12-fpm-alpine
|
||||
|
||||
# Use the default production configuration
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
RUN apk add --no-cache libpng-dev libxml2-dev oniguruma-dev libzip-dev gnu-libiconv && \
|
||||
docker-php-ext-install bcmath ctype json gd mbstring pdo pdo_mysql tokenizer xml zip
|
||||
|
||||
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php
|
||||
|
||||
# Set container's working dir
|
||||
WORKDIR /app
|
||||
|
||||
# Copy everything from project root into php container's working dir
|
||||
COPY . /app
|
||||
|
||||
# Copy vendor folder from composer container into php container
|
||||
COPY --from=composer /app/vendor /app/vendor
|
||||
|
||||
RUN touch database/database.sqlite && \
|
||||
cp .env.example .env && \
|
||||
php artisan config:cache && \
|
||||
php artisan passport:keys && \
|
||||
php artisan key:generate && \
|
||||
chown -R www-data:www-data . && \
|
||||
chmod -R 755 . && \
|
||||
chmod -R 775 storage/framework/ && \
|
||||
chmod -R 775 storage/logs/ && \
|
||||
chmod -R 775 bootstrap/cache/
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
CMD ["php-fpm", "--nodaemonize"]
|
||||
@ -4,20 +4,18 @@ namespace Crater;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\User;
|
||||
use Crater\Country;
|
||||
use Crater\State;
|
||||
use Crater\City;
|
||||
|
||||
class Address extends Model
|
||||
{
|
||||
const BILLING_TYPE = 'BILLING';
|
||||
const SHIPPING_TYPE = 'SHIPPING';
|
||||
const BILLING_TYPE = 'billing';
|
||||
const SHIPPING_TYPE = 'shipping';
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'address_street_1',
|
||||
'address_street_2',
|
||||
'city_id',
|
||||
'state_id',
|
||||
'city',
|
||||
'state',
|
||||
'country_id',
|
||||
'zip',
|
||||
'phone',
|
||||
@ -35,14 +33,4 @@ class Address extends Model
|
||||
{
|
||||
return $this->belongsTo(Country::class);
|
||||
}
|
||||
|
||||
public function state()
|
||||
{
|
||||
return $this->belongsTo(State::class);
|
||||
}
|
||||
|
||||
public function city()
|
||||
{
|
||||
return $this->belongsTo(City::class);
|
||||
}
|
||||
}
|
||||
|
||||
18
app/City.php
18
app/City.php
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\State;
|
||||
|
||||
class City extends Model
|
||||
{
|
||||
public function state()
|
||||
{
|
||||
return $this->belongsTo(State::class);
|
||||
}
|
||||
|
||||
public function address()
|
||||
{
|
||||
return $this->hasMany(Address::class);
|
||||
}
|
||||
}
|
||||
51
app/Console/Commands/ResetApp.php
Normal file
51
app/Console/Commands/ResetApp.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class ResetApp extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'reset:app';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clean database, database_created and public/storage folder';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->confirm('Do you wish to continue? This will delete your tables')) {
|
||||
Artisan::call('migrate:reset --force');
|
||||
|
||||
\Storage::disk('local')->delete('database_created');
|
||||
|
||||
// $file = new Filesystem;
|
||||
// $file->cleanDirectory('public/storage');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
|
||||
Commands\ResetApp::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@ -2,15 +2,9 @@
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\State;
|
||||
|
||||
class Country extends Model
|
||||
{
|
||||
public function states()
|
||||
{
|
||||
return $this->hasMany(State::class);
|
||||
}
|
||||
|
||||
public function address()
|
||||
{
|
||||
return $this->hasMany(Address::class);
|
||||
|
||||
@ -49,15 +49,20 @@ class Estimate extends Model
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'total' => 'float',
|
||||
'tax' => 'float',
|
||||
'sub_total' => 'float'
|
||||
'total' => 'integer',
|
||||
'tax' => 'integer',
|
||||
'sub_total' => 'integer',
|
||||
'discount' => 'float',
|
||||
'discount_val' => 'integer',
|
||||
];
|
||||
|
||||
public static function getNextEstimateNumber()
|
||||
public static function getNextEstimateNumber($value)
|
||||
{
|
||||
// Get the last created order
|
||||
$lastOrder = Estimate::orderBy('created_at', 'desc')->first();
|
||||
// Get the last created order
|
||||
$lastOrder = Estimate::where('estimate_number', 'LIKE', $value . '-%')
|
||||
->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.
|
||||
@ -99,10 +104,16 @@ class Estimate extends Model
|
||||
|
||||
public function getEstimateNumAttribute()
|
||||
{
|
||||
$position = $this->strposX($this->estimate_number, "-", 2) + 1;
|
||||
$position = $this->strposX($this->estimate_number, "-", 1) + 1;
|
||||
return substr($this->estimate_number, $position);
|
||||
}
|
||||
|
||||
public function getEstimatePrefixAttribute()
|
||||
{
|
||||
$prefix = explode("-",$this->estimate_number)[0];
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
private function strposX($haystack, $needle, $number)
|
||||
{
|
||||
if ($number == '1') {
|
||||
|
||||
@ -24,6 +24,7 @@ class EstimateItem extends Model
|
||||
'price' => 'integer',
|
||||
'total' => 'integer',
|
||||
'discount' => 'float',
|
||||
'quantity' => 'float',
|
||||
'discount_val' => 'integer',
|
||||
'tax' => 'integer'
|
||||
];
|
||||
|
||||
@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
|
||||
use Crater\ExpenseCategory;
|
||||
use Crater\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@ -16,6 +17,7 @@ class Expense extends Model implements HasMedia
|
||||
'expense_category_id',
|
||||
'amount',
|
||||
'company_id',
|
||||
'user_id',
|
||||
'expense_date',
|
||||
'notes',
|
||||
'attachment_receipt'
|
||||
@ -32,6 +34,11 @@ class Expense extends Model implements HasMedia
|
||||
return $this->belongsTo(ExpenseCategory::class, 'expense_category_id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getFormattedExpenseDateAttribute($value)
|
||||
{
|
||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||
@ -81,6 +88,11 @@ class Expense extends Model implements HasMedia
|
||||
return $query->where('expenses.expense_category_id', $categoryId);
|
||||
}
|
||||
|
||||
public function scopeWhereUser($query, $user_id)
|
||||
{
|
||||
return $query->where('expenses.user_id', $user_id);
|
||||
}
|
||||
|
||||
public function scopeApplyFilters($query, array $filters)
|
||||
{
|
||||
$filters = collect($filters);
|
||||
@ -89,6 +101,10 @@ class Expense extends Model implements HasMedia
|
||||
$query->whereCategory($filters->get('expense_category_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('user_id')) {
|
||||
$query->whereUser($filters->get('user_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'));
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
@ -20,11 +21,22 @@ use Crater\CompanySetting;
|
||||
|
||||
class CompanyController extends Controller
|
||||
{
|
||||
/**
|
||||
* Retrive the Admin account.
|
||||
* @return \Crater\User
|
||||
*/
|
||||
public function getAdmin()
|
||||
{
|
||||
return User::find(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Admin profile.
|
||||
* Includes name, email and (or) password
|
||||
*
|
||||
* @param \Crater\Http\Requests\ProfileRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function updateAdminProfile(ProfileRequest $request)
|
||||
{
|
||||
$verifyEmail = User::where('email', $request->email)->first();
|
||||
@ -54,15 +66,30 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get Admin Account alongside the country from the addresses table and
|
||||
* The company from companies table
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getAdminCompany()
|
||||
{
|
||||
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
|
||||
$user = User::with(['addresses', 'addresses.country', 'company'])->find(1);
|
||||
|
||||
return response()->json([
|
||||
'user' => $user
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update Admin Company Details
|
||||
* @param \Crater\Http\Requests\CompanyRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function updateAdminCompany(CompanyRequest $request)
|
||||
{
|
||||
$user = User::find(1);
|
||||
@ -75,9 +102,9 @@ class CompanyController extends Controller
|
||||
$company->addMediaFromRequest('logo')->toMediaCollection('logo');
|
||||
}
|
||||
|
||||
$fields = $request->only(['address_street_1', 'address_street_2', 'city_id', 'state_id', 'country_id', 'zip', 'phone']);
|
||||
$fields = $request->only(['address_street_1', 'address_street_2', 'city', 'state', 'country_id', 'zip', 'phone']);
|
||||
$address = Address::updateOrCreate(['user_id' => 1], $fields);
|
||||
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
|
||||
$user = User::with(['addresses', 'addresses.country', 'company'])->find(1);
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
@ -85,23 +112,28 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve General App Settings
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
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' => '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' => 'november-october', 'value' => '11-10'],
|
||||
['key' => 'december-november', 'value' => '12-11'],
|
||||
];
|
||||
|
||||
@ -112,10 +144,17 @@ class CompanyController extends Controller
|
||||
$currency = CompanySetting::getSetting('currency', $request->header('company'));
|
||||
$fiscal_year = CompanySetting::getSetting('fiscal_year', $request->header('company'));
|
||||
|
||||
$languages = [
|
||||
["code"=>"en", "name" => "English"],
|
||||
["code"=>"fr", "name" => "French"],
|
||||
["code"=>"es", "name" => "Spanish"]
|
||||
$languages = [ // alphabetical order
|
||||
["code" => "pt_BR", "name" => "Brazilian Portuguese"],
|
||||
["code" => "en", "name" => "English"],
|
||||
["code" => "fr", "name" => "French"],
|
||||
["code" => "de", "name" => "German"],
|
||||
["code" => "it", "name" => "Italian"],
|
||||
["code" => "es", "name" => "Spanish"],
|
||||
["code" => "ar", "name" => "العربية"],
|
||||
["code" => "de", "name" => "German"],
|
||||
["code" => "pt_BR", "name" => "Brazilian Portuguese"],
|
||||
["code" => "nl", "name" => "Dutch"]
|
||||
];
|
||||
|
||||
return response()->json([
|
||||
@ -133,6 +172,13 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update General App Settings
|
||||
* @param \Crater\Http\Requests\CompanySettingRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function updateGeneralSettings(CompanySettingRequest $request)
|
||||
{
|
||||
$sets = [
|
||||
@ -153,6 +199,63 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function getCustomizeSetting(Request $request)
|
||||
{
|
||||
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
|
||||
$invoice_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
|
||||
|
||||
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
|
||||
$estimate_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
|
||||
|
||||
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
|
||||
$payment_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company'));
|
||||
|
||||
return response()->json([
|
||||
'invoice_prefix' => $invoice_prefix,
|
||||
'invoice_auto_generate' => $invoice_auto_generate,
|
||||
'estimate_prefix' => $estimate_prefix,
|
||||
'estimate_auto_generate' => $estimate_auto_generate,
|
||||
'payment_prefix' => $payment_prefix,
|
||||
'payment_auto_generate' => $payment_auto_generate,
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateCustomizeSetting(Request $request)
|
||||
{
|
||||
$sets = [];
|
||||
|
||||
if ($request->type == "PAYMENTS") {
|
||||
$sets = [
|
||||
'payment_prefix'
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->type == "INVOICES") {
|
||||
$sets = [
|
||||
'invoice_prefix',
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->type == "ESTIMATES") {
|
||||
$sets = [
|
||||
'estimate_prefix',
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($sets as $key) {
|
||||
CompanySetting::setSetting($key, $request->$key, $request->header('company'));
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific Company Setting
|
||||
* @param \Crater\Http\Requests\SettingRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function updateSetting(SettingRequest $request)
|
||||
{
|
||||
CompanySetting::setSetting($request->key, $request->value, $request->header('company'));
|
||||
@ -162,6 +265,11 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Specific Company Setting
|
||||
* @param \Crater\Http\Requests\SettingKeyRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getSetting(SettingKeyRequest $request)
|
||||
{
|
||||
$setting = CompanySetting::getSetting($request->key, $request->header('company'));
|
||||
@ -171,6 +279,12 @@ class CompanyController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve App Colors
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getColors(Request $request)
|
||||
{
|
||||
$colors = [
|
||||
@ -205,16 +319,16 @@ class CompanyController extends Controller
|
||||
* Upload the company logo to storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function uploadCompanyLogo(Request $request)
|
||||
{
|
||||
$data = json_decode($request->company_logo);
|
||||
|
||||
if($data) {
|
||||
if ($data) {
|
||||
$company = Company::find($request->header('company'));
|
||||
|
||||
if($company) {
|
||||
if ($company) {
|
||||
$company->clearMediaCollection('logo');
|
||||
|
||||
$company->addMediaFromBase64($data->data)
|
||||
@ -227,4 +341,32 @@ class CompanyController extends Controller
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the Admin Avatar to public storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function uploadAdminAvatar(Request $request)
|
||||
{
|
||||
$data = json_decode($request->admin_avatar);
|
||||
|
||||
if ($data) {
|
||||
$user = auth()->user();
|
||||
|
||||
if ($user) {
|
||||
$user->clearMediaCollection('admin_avatar');
|
||||
|
||||
$user->addMediaFromBase64($data->data)
|
||||
->usingFileName($data->name)
|
||||
->toMediaCollection('admin_avatar');
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class CustomersController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
@ -53,7 +53,7 @@ class CustomersController extends Controller
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Requests\CustomerRequest $request)
|
||||
{
|
||||
@ -80,8 +80,8 @@ class CustomersController extends Controller
|
||||
$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->city = $address["city"];
|
||||
$newAddress->state = $address["state"];
|
||||
$newAddress->country_id = $address["country_id"];
|
||||
$newAddress->zip = $address["zip"];
|
||||
$newAddress->phone = $address["phone"];
|
||||
@ -104,7 +104,7 @@ class CustomersController extends Controller
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
@ -112,11 +112,7 @@ class CustomersController extends Controller
|
||||
'billingAddress',
|
||||
'shippingAddress',
|
||||
'billingAddress.country',
|
||||
'billingAddress.state',
|
||||
'billingAddress.city',
|
||||
'shippingAddress.country',
|
||||
'shippingAddress.state',
|
||||
'shippingAddress.city',
|
||||
])->find($id);
|
||||
|
||||
return response()->json([
|
||||
@ -128,7 +124,7 @@ class CustomersController extends Controller
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
@ -148,7 +144,7 @@ class CustomersController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update($id, Requests\CustomerRequest $request)
|
||||
{
|
||||
@ -160,6 +156,7 @@ class CustomersController extends Controller
|
||||
if ($verifyEmail) {
|
||||
if ($verifyEmail->id !== $customer->id) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Email already in use'
|
||||
]);
|
||||
}
|
||||
@ -180,14 +177,15 @@ class CustomersController extends Controller
|
||||
$customer->enable_portal = $request->enable_portal;
|
||||
$customer->save();
|
||||
|
||||
$customer->addresses()->delete();
|
||||
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->city = $address["city"];
|
||||
$newAddress->state = $address["state"];
|
||||
$newAddress->country_id = $address["country_id"];
|
||||
$newAddress->zip = $address["zip"];
|
||||
$newAddress->phone = $address["phone"];
|
||||
@ -206,10 +204,10 @@ class CustomersController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* Remove the specified Customer along side all his/her resources (ie. Estimates, Invoices, Payments and Addresses)
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
@ -220,6 +218,13 @@ class CustomersController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a list of Customers along side all their resources (ie. Estimates, Invoices, Payments and Addresses)
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function delete(Request $request)
|
||||
{
|
||||
foreach ($request->id as $id) {
|
||||
|
||||
@ -15,6 +15,12 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrieve Dashboard details
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$invoiceTotals = [];
|
||||
@ -30,7 +36,8 @@ class DashboardController extends Controller
|
||||
$start = Carbon::now();
|
||||
$end = Carbon::now();
|
||||
$terms = explode('-', $fiscalYear);
|
||||
if ($terms[0] < $start->month) {
|
||||
|
||||
if ($terms[0] <= $start->month) {
|
||||
$startDate->month($terms[0])->startOfMonth();
|
||||
$start->month($terms[0])->startOfMonth();
|
||||
$end->month($terms[0])->endOfMonth();
|
||||
@ -87,6 +94,7 @@ class DashboardController extends Controller
|
||||
}
|
||||
|
||||
$start->subMonth()->endOfMonth();
|
||||
|
||||
$salesTotal = Invoice::whereCompany($request->header('company'))
|
||||
->whereBetween(
|
||||
'invoice_date',
|
||||
@ -137,6 +145,11 @@ class DashboardController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive Expense Chart data
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getExpenseChartData(Request $request)
|
||||
{
|
||||
$expensesCategories = Expense::with('category')
|
||||
|
||||
@ -33,10 +33,14 @@ class EnvironmentController extends Controller
|
||||
*/
|
||||
public function saveDatabaseEnvironment(DatabaseEnvironmentRequest $request)
|
||||
{
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('cache:clear');
|
||||
|
||||
$results = $this->EnvironmentManager->saveDatabaseVariables($request);
|
||||
|
||||
if(array_key_exists("success", $results)) {
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('storage:link');
|
||||
Artisan::call('key:generate --force');
|
||||
Artisan::call('migrate --seed --force');
|
||||
|
||||
@ -56,25 +56,43 @@ class EstimatesController extends Controller
|
||||
|
||||
public function create(Request $request)
|
||||
{
|
||||
$nextEstimateNumber = 'EST-'.Estimate::getNextEstimateNumber();
|
||||
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
|
||||
$estimate_num_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
|
||||
|
||||
$nextEstimateNumberAttribute = null;
|
||||
$nextEstimateNumber = Estimate::getNextEstimateNumber($estimate_prefix);
|
||||
|
||||
if ($estimate_num_auto_generate == "YES") {
|
||||
$nextEstimateNumberAttribute = $nextEstimateNumber;
|
||||
}
|
||||
|
||||
$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,
|
||||
'nextEstimateNumberAttribute' => $nextEstimateNumberAttribute,
|
||||
'nextEstimateNumber' => $estimate_prefix.'-'.$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' => ''
|
||||
'shareable_link' => '',
|
||||
'estimate_prefix' => $estimate_prefix
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(EstimatesRequest $request)
|
||||
{
|
||||
$estimate_number = explode("-",$request->estimate_number);
|
||||
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
|
||||
|
||||
Validator::make($number_attributes, [
|
||||
'estimate_number' => 'required|unique:estimates,estimate_number'
|
||||
])->validate();
|
||||
|
||||
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
||||
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
||||
$status = Estimate::STATUS_DRAFT;
|
||||
@ -101,7 +119,7 @@ class EstimatesController extends Controller
|
||||
$estimate = Estimate::create([
|
||||
'estimate_date' => $estimate_date,
|
||||
'expiry_date' => $expiry_date,
|
||||
'estimate_number' => $request->estimate_number,
|
||||
'estimate_number' => $number_attributes['estimate_number'],
|
||||
'reference_number' => $request->reference_number,
|
||||
'user_id' => $request->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
@ -127,7 +145,7 @@ class EstimatesController extends Controller
|
||||
|
||||
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
|
||||
foreach ($estimateItem['taxes'] as $tax) {
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
@ -137,7 +155,7 @@ class EstimatesController extends Controller
|
||||
|
||||
if ($request->has('taxes')) {
|
||||
foreach ($request->taxes as $tax) {
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$estimate->taxes()->create($tax);
|
||||
}
|
||||
@ -150,10 +168,6 @@ class EstimatesController extends Controller
|
||||
$data['user'] = User::find($userId)->toArray();
|
||||
$data['company'] = Company::find($estimate->company_id);
|
||||
$email = $data['user']['email'];
|
||||
$notificationEmail = CompanySetting::getSetting(
|
||||
'notification_email',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
@ -161,13 +175,7 @@ class EstimatesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$notificationEmail) {
|
||||
return response()->json([
|
||||
'error' => 'notification_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
|
||||
\Mail::to($email)->send(new EstimatePdf($data));
|
||||
}
|
||||
|
||||
$estimate = Estimate::with([
|
||||
@ -216,26 +224,33 @@ class EstimatesController extends Controller
|
||||
|
||||
return response()->json( [
|
||||
'customers' => $customers,
|
||||
'nextEstimateNumber' => $estimate->estimate_number,
|
||||
'nextEstimateNumber' => $estimate->getEstimateNumAttribute(),
|
||||
'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)
|
||||
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash),
|
||||
'estimate_prefix' => $estimate->getEstimatePrefixAttribute()
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(EstimatesRequest $request, $id)
|
||||
{
|
||||
$estimate_number = explode("-",$request->estimate_number);
|
||||
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
|
||||
Validator::make($number_attributes, [
|
||||
'estimate_number' => 'required|unique:estimates,estimate_number'.','.$id
|
||||
])->validate();
|
||||
|
||||
$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->estimate_number = $number_attributes['estimate_number'];
|
||||
$estimate->reference_number = $request->reference_number;
|
||||
$estimate->user_id = $request->user_id;
|
||||
$estimate->estimate_template_id = $request->estimate_template_id;
|
||||
@ -266,7 +281,7 @@ class EstimatesController extends Controller
|
||||
|
||||
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
|
||||
foreach ($estimateItem['taxes'] as $tax) {
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
@ -276,7 +291,7 @@ class EstimatesController extends Controller
|
||||
|
||||
if ($request->has('taxes')) {
|
||||
foreach ($request->taxes as $tax) {
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$estimate->taxes()->create($tax);
|
||||
}
|
||||
@ -315,10 +330,6 @@ class EstimatesController extends Controller
|
||||
$data['company'] = Company::find($estimate->company_id);
|
||||
|
||||
$email = $data['user']['email'];
|
||||
$notificationEmail = CompanySetting::getSetting(
|
||||
'notification_email',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
@ -326,13 +337,7 @@ class EstimatesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$notificationEmail) {
|
||||
return response()->json([
|
||||
'error' => 'notification_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
|
||||
\Mail::to($email)->send(new EstimatePdf($data));
|
||||
|
||||
if ($estimate->status == Estimate::STATUS_DRAFT) {
|
||||
$estimate->status = Estimate::STATUS_SENT;
|
||||
@ -381,6 +386,10 @@ class EstimatesController extends Controller
|
||||
{
|
||||
$estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id);
|
||||
$invoice_date = Carbon::parse($estimate->estimate_date);
|
||||
$invoice_prefix = CompanySetting::getSetting(
|
||||
'invoice_prefix',
|
||||
$request->header('company')
|
||||
);
|
||||
$due_date = Carbon::parse($estimate->estimate_date)->addDays(7);
|
||||
$tax_per_item = CompanySetting::getSetting(
|
||||
'tax_per_item',
|
||||
@ -400,7 +409,7 @@ class EstimatesController extends Controller
|
||||
$invoice = Invoice::create([
|
||||
'invoice_date' => $invoice_date,
|
||||
'due_date' => $due_date,
|
||||
'invoice_number' => "INV-".Invoice::getNextInvoiceNumber(),
|
||||
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
|
||||
'reference_number' => $estimate->reference_number,
|
||||
'user_id' => $estimate->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
|
||||
@ -17,16 +17,18 @@ class ExpensesController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$expenses = Expense::with('category')
|
||||
->leftJoin('users', 'users.id', '=', 'expenses.user_id')
|
||||
->join('expense_categories', 'expense_categories.id', '=', 'expenses.expense_category_id')
|
||||
->applyFilters($request->only([
|
||||
'expense_category_id',
|
||||
'user_id',
|
||||
'search',
|
||||
'from_date',
|
||||
'to_date',
|
||||
@ -34,11 +36,16 @@ class ExpensesController extends Controller
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('expenses.*', 'expense_categories.name')
|
||||
->select('expenses.*', 'expense_categories.name', 'users.name as user_name')
|
||||
->paginate($limit);
|
||||
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'expenses' => $expenses,
|
||||
'customers' => $customers,
|
||||
'currency' => Currency::findOrFail(
|
||||
CompanySetting::getSetting('currency', $request->header('company'))
|
||||
)
|
||||
@ -48,14 +55,18 @@ class ExpensesController extends Controller
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'categories' => $categories
|
||||
'categories' => $categories,
|
||||
'customers' => $customers
|
||||
]);
|
||||
}
|
||||
|
||||
@ -63,7 +74,7 @@ class ExpensesController extends Controller
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(ExpenseRequest $request)
|
||||
{
|
||||
@ -72,6 +83,7 @@ class ExpensesController extends Controller
|
||||
$expense = new Expense();
|
||||
$expense->notes = $request->notes;
|
||||
$expense->expense_category_id = $request->expense_category_id;
|
||||
$expense->user_id = $request->user_id;
|
||||
$expense->amount = $request->amount;
|
||||
$expense->company_id = $request->header('company');
|
||||
$expense->expense_date = $expense_date;
|
||||
@ -91,7 +103,7 @@ class ExpensesController extends Controller
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Crater\Expense $expense
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(Expense $expense)
|
||||
{
|
||||
@ -102,12 +114,14 @@ class ExpensesController extends Controller
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function edit(Request $request,$id)
|
||||
{
|
||||
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||
$customers = User::where('role', 'customer')->whereCompany($request->header('company'))->get();
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
$expense = Expense::with('category')->where('id', $id)->first();
|
||||
|
||||
return response()->json([
|
||||
@ -122,7 +136,7 @@ class ExpensesController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Crater\Expense $expense
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(ExpenseRequest $request, Expense $expense)
|
||||
{
|
||||
@ -132,6 +146,7 @@ class ExpensesController extends Controller
|
||||
$expense->notes = $request->notes;
|
||||
$expense->expense_category_id = $request->expense_category_id;
|
||||
$expense->amount = $request->amount;
|
||||
$expense->user_id = $request->user_id;
|
||||
$expense->expense_date = $expense_date;
|
||||
$expense->save();
|
||||
|
||||
@ -150,7 +165,7 @@ class ExpensesController extends Controller
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \Crater\Expense $expense
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy(Expense $expense)
|
||||
{
|
||||
@ -175,7 +190,7 @@ class ExpensesController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function uploadReceipts(Request $request, $id)
|
||||
{
|
||||
@ -200,6 +215,12 @@ class ExpensesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrive details of an expense receipt from storage.
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function showReceipt($id)
|
||||
{
|
||||
$expense = Expense::find($id);
|
||||
@ -226,6 +247,14 @@ class ExpensesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Download an expense receipt from storage.
|
||||
* @param int $id
|
||||
* @param strig $hash
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function downloadReceipt($id, $hash)
|
||||
{
|
||||
$company = Company::where('unique_hash', $hash)->first();
|
||||
|
||||
@ -6,6 +6,7 @@ use Crater\Invoice;
|
||||
use PDF;
|
||||
use Crater\CompanySetting;
|
||||
use Crater\Estimate;
|
||||
use Crater\Payment;
|
||||
use Crater\User;
|
||||
use Crater\Company;
|
||||
use Crater\InvoiceTemplate;
|
||||
@ -90,7 +91,7 @@ class FrontendController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
|
||||
$colors = [
|
||||
'invoice_primary_color',
|
||||
@ -118,6 +119,11 @@ class FrontendController extends Controller
|
||||
return $pdf->stream();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function getCustomerInvoicePdf($id)
|
||||
{
|
||||
$invoice = Invoice::with([
|
||||
@ -189,7 +195,7 @@ class FrontendController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
|
||||
$colors = [
|
||||
'invoice_primary_color',
|
||||
@ -262,7 +268,7 @@ class FrontendController extends Controller
|
||||
$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);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
$logo = $company->getMedia('logo')->first();
|
||||
|
||||
if($logo) {
|
||||
@ -338,7 +344,7 @@ class FrontendController extends Controller
|
||||
|
||||
$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);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
|
||||
$logo = $company->getMedia('logo')->first();
|
||||
|
||||
@ -371,4 +377,34 @@ class FrontendController extends Controller
|
||||
|
||||
return $pdf->stream();
|
||||
}
|
||||
|
||||
public function getPaymentPdf($id)
|
||||
{
|
||||
$payment = Payment::with([
|
||||
'user',
|
||||
'invoice',
|
||||
'paymentMethod'
|
||||
])
|
||||
->where('unique_hash', $id)
|
||||
->first();
|
||||
|
||||
$company = Company::find($payment->company_id);
|
||||
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
|
||||
|
||||
$logo = $company->getMedia('logo')->first();
|
||||
|
||||
if($logo) {
|
||||
$logo = $logo->getFullUrl();
|
||||
}
|
||||
|
||||
view()->share([
|
||||
'payment' => $payment,
|
||||
'company_address' => $companyAddress,
|
||||
'logo' => $logo ?? null
|
||||
]);
|
||||
|
||||
$pdf = PDF::loadView('app.pdf.payment.payment');
|
||||
|
||||
return $pdf->stream();
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ use Crater\Invoice;
|
||||
use Crater\InvoiceItem;
|
||||
use Carbon\Carbon;
|
||||
use Crater\Item;
|
||||
use Crater\Mail\invoicePdf;
|
||||
use Crater\Mail\InvoicePdf;
|
||||
use function MongoDB\BSON\toJSON;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Crater\User;
|
||||
@ -27,7 +27,7 @@ class InvoicesController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
@ -60,20 +60,30 @@ class InvoicesController extends Controller
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
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();
|
||||
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
|
||||
$invoice_num_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
|
||||
|
||||
$nextInvoiceNumberAttribute = null;
|
||||
$nextInvoiceNumber = Invoice::getNextInvoiceNumber($invoice_prefix);
|
||||
|
||||
if ($invoice_num_auto_generate == "YES") {
|
||||
$nextInvoiceNumberAttribute = $nextInvoiceNumber;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'nextInvoiceNumber' => $nextInvoiceNumber,
|
||||
'nextInvoiceNumberAttribute' => $nextInvoiceNumberAttribute,
|
||||
'nextInvoiceNumber' => $invoice_prefix.'-'.$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
|
||||
'discount_per_item' => $discount_per_item,
|
||||
'invoice_prefix' => $invoice_prefix
|
||||
]);
|
||||
}
|
||||
|
||||
@ -81,10 +91,17 @@ class InvoicesController extends Controller
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Requests\InvoicesRequest $request)
|
||||
{
|
||||
$invoice_number = explode("-",$request->invoice_number);
|
||||
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
|
||||
|
||||
Validator::make($number_attributes, [
|
||||
'invoice_number' => 'required|unique:invoices,invoice_number'
|
||||
])->validate();
|
||||
|
||||
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||
$status = Invoice::STATUS_DRAFT;
|
||||
@ -99,7 +116,7 @@ class InvoicesController extends Controller
|
||||
$invoice = Invoice::create([
|
||||
'invoice_date' => $invoice_date,
|
||||
'due_date' => $due_date,
|
||||
'invoice_number' => $request->invoice_number,
|
||||
'invoice_number' => $number_attributes['invoice_number'],
|
||||
'reference_number' => $request->reference_number,
|
||||
'user_id' => $request->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
@ -128,8 +145,7 @@ class InvoicesController extends Controller
|
||||
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||
foreach ($invoiceItem['taxes'] as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
@ -140,7 +156,7 @@ class InvoicesController extends Controller
|
||||
foreach ($request->taxes as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$invoice->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
@ -151,11 +167,6 @@ class InvoicesController extends Controller
|
||||
$data['user'] = User::find($request->user_id)->toArray();
|
||||
$data['company'] = Company::find($invoice->company_id);
|
||||
|
||||
$notificationEmail = CompanySetting::getSetting(
|
||||
'notification_email',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
$email = $data['user']['email'];
|
||||
|
||||
if (!$email) {
|
||||
@ -164,13 +175,7 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$notificationEmail) {
|
||||
return response()->json([
|
||||
'error' => 'notification_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
|
||||
\Mail::to($email)->send(new InvoicePdf($data));
|
||||
}
|
||||
|
||||
$invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id);
|
||||
@ -185,7 +190,7 @@ class InvoicesController extends Controller
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
@ -209,7 +214,7 @@ class InvoicesController extends Controller
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function edit(Request $request,$id)
|
||||
{
|
||||
@ -222,12 +227,13 @@ class InvoicesController extends Controller
|
||||
])->find($id);
|
||||
|
||||
return response()->json([
|
||||
'nextInvoiceNumber' => $invoice->invoice_number,
|
||||
'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(),
|
||||
'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)
|
||||
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash),
|
||||
'invoice_prefix' => $invoice->getInvoicePrefixAttribute()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -236,10 +242,17 @@ class InvoicesController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(Requests\InvoicesRequest $request, $id)
|
||||
{
|
||||
$invoice_number = explode("-",$request->invoice_number);
|
||||
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
|
||||
|
||||
Validator::make($number_attributes, [
|
||||
'invoice_number' => 'required|unique:invoices,invoice_number'.','.$id
|
||||
])->validate();
|
||||
|
||||
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||
|
||||
@ -268,7 +281,7 @@ class InvoicesController extends Controller
|
||||
|
||||
$invoice->invoice_date = $invoice_date;
|
||||
$invoice->due_date = $due_date;
|
||||
$invoice->invoice_number = $request->invoice_number;
|
||||
$invoice->invoice_number = $number_attributes['invoice_number'];
|
||||
$invoice->reference_number = $request->reference_number;
|
||||
$invoice->user_id = $request->user_id;
|
||||
$invoice->invoice_template_id = $request->invoice_template_id;
|
||||
@ -292,7 +305,6 @@ class InvoicesController extends Controller
|
||||
foreach ($oldTaxes as $oldTax) {
|
||||
Tax::destroy($oldTax['id']);
|
||||
}
|
||||
|
||||
foreach ($invoiceItems as $invoiceItem) {
|
||||
$invoiceItem['company_id'] = $request->header('company');
|
||||
$item = $invoice->items()->create($invoiceItem);
|
||||
@ -300,8 +312,7 @@ class InvoicesController extends Controller
|
||||
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
|
||||
foreach ($invoiceItem['taxes'] as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
@ -312,7 +323,7 @@ class InvoicesController extends Controller
|
||||
foreach ($request->taxes as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
if (gettype($tax['amount']) !== "NULL") {
|
||||
$invoice->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
@ -331,7 +342,7 @@ class InvoicesController extends Controller
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
@ -369,6 +380,14 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mail a specific invoice to the correponding cusitomer's email address.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sendInvoice(Request $request)
|
||||
{
|
||||
$invoice = Invoice::findOrFail($request->id);
|
||||
@ -378,10 +397,6 @@ class InvoicesController extends Controller
|
||||
$data['user'] = User::find($userId)->toArray();
|
||||
$data['company'] = Company::find($invoice->company_id);
|
||||
$email = $data['user']['email'];
|
||||
$notificationEmail = CompanySetting::getSetting(
|
||||
'notification_email',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
@ -389,13 +404,7 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$notificationEmail) {
|
||||
return response()->json([
|
||||
'error' => 'notification_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
|
||||
\Mail::to($email)->send(new InvoicePdf($data));
|
||||
|
||||
if ($invoice->status == Invoice::STATUS_DRAFT) {
|
||||
$invoice->status = Invoice::STATUS_SENT;
|
||||
@ -409,6 +418,13 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark a specific invoice as sent.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function markAsSent(Request $request)
|
||||
{
|
||||
$invoice = Invoice::findOrFail($request->id);
|
||||
@ -421,6 +437,13 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark a specific invoice as paid.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function markAsPaid(Request $request)
|
||||
{
|
||||
$invoice = Invoice::findOrFail($request->id);
|
||||
@ -434,6 +457,14 @@ class InvoicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrive a specified user's unpaid invoices from storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getCustomersUnpaidInvoices(Request $request, $id)
|
||||
{
|
||||
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
|
||||
@ -445,4 +476,94 @@ class InvoicesController extends Controller
|
||||
'invoices' => $invoices
|
||||
]);
|
||||
}
|
||||
|
||||
public function cloneInvoice(Request $request)
|
||||
{
|
||||
$oldInvoice = Invoice::with([
|
||||
'items.taxes',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes.taxType'
|
||||
])
|
||||
->find($request->id);
|
||||
|
||||
$date = Carbon::now();
|
||||
$invoice_prefix = CompanySetting::getSetting(
|
||||
'invoice_prefix',
|
||||
$request->header('company')
|
||||
);
|
||||
$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' => $date,
|
||||
'due_date' => $date,
|
||||
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
|
||||
'reference_number' => $oldInvoice->reference_number,
|
||||
'user_id' => $oldInvoice->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_template_id' => 1,
|
||||
'status' => Invoice::STATUS_DRAFT,
|
||||
'paid_status' => Invoice::STATUS_UNPAID,
|
||||
'sub_total' => $oldInvoice->sub_total,
|
||||
'discount' => $oldInvoice->discount,
|
||||
'discount_type' => $oldInvoice->discount_type,
|
||||
'discount_val' => $oldInvoice->discount_val,
|
||||
'total' => $oldInvoice->total,
|
||||
'due_amount' => $oldInvoice->total,
|
||||
'tax_per_item' => $oldInvoice->tax_per_item,
|
||||
'discount_per_item' => $oldInvoice->discount_per_item,
|
||||
'tax' => $oldInvoice->tax,
|
||||
'notes' => $oldInvoice->notes,
|
||||
'unique_hash' => str_random(60)
|
||||
]);
|
||||
|
||||
$invoiceItems = $oldInvoice->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 ($oldInvoice->taxes) {
|
||||
foreach ($oldInvoice->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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,14 +14,17 @@ class ItemsController extends Controller
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$items = Item::applyFilters($request->only([
|
||||
$items = Item::with(['taxes'])
|
||||
->leftJoin('units', 'units.id', '=', 'items.unit_id')
|
||||
->applyFilters($request->only([
|
||||
'search',
|
||||
'price',
|
||||
'unit',
|
||||
'unit_id',
|
||||
'orderByField',
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('items.*', 'units.name as unit_name')
|
||||
->latest()
|
||||
->paginate($limit);
|
||||
|
||||
@ -33,7 +36,7 @@ class ItemsController extends Controller
|
||||
|
||||
public function edit(Request $request, $id)
|
||||
{
|
||||
$item = Item::with('taxes')->find($id);
|
||||
$item = Item::with(['taxes', 'unit'])->find($id);
|
||||
|
||||
return response()->json([
|
||||
'item' => $item,
|
||||
@ -43,11 +46,18 @@ class ItemsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create Item.
|
||||
*
|
||||
* @param Crater\Http\Requests\ItemsRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Requests\ItemsRequest $request)
|
||||
{
|
||||
$item = new Item();
|
||||
$item->name = $request->name;
|
||||
$item->unit = $request->unit;
|
||||
$item->unit_id = $request->unit_id;
|
||||
$item->description = $request->description;
|
||||
$item->company_id = $request->header('company');
|
||||
$item->price = $request->price;
|
||||
@ -67,11 +77,18 @@ class ItemsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing Item.
|
||||
*
|
||||
* @param Crater\Http\Requests\ItemsRequest $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(Requests\ItemsRequest $request, $id)
|
||||
{
|
||||
$item = Item::find($id);
|
||||
$item->name = $request->name;
|
||||
$item->unit = $request->unit;
|
||||
$item->unit_id = $request->unit_id;
|
||||
$item->description = $request->description;
|
||||
$item->price = $request->price;
|
||||
$item->save();
|
||||
@ -96,6 +113,13 @@ class ItemsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete an existing Item.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$data = Item::deleteItem($id);
|
||||
@ -111,12 +135,20 @@ class ItemsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Delete a list of existing Items.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function delete(Request $request)
|
||||
{
|
||||
$items = [];
|
||||
foreach ($request->id as $id) {
|
||||
$item = Item::deleteItem($id);
|
||||
if (!$item) {
|
||||
if ($item) {
|
||||
array_push($items, $id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,29 +3,19 @@ namespace Crater\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Country;
|
||||
use Crater\State;
|
||||
use Crater\City;
|
||||
|
||||
class LocationController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrive a list of Countries.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,13 @@ use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class OnboardingController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrieve Onboarding data.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getOnboardingData(Request $request)
|
||||
{
|
||||
if (!\Storage::disk('local')->has('database_created')) {
|
||||
@ -37,9 +44,14 @@ class OnboardingController extends Controller
|
||||
$date_formats = DateFormatter::get_list();
|
||||
$time_zones = TimeZones::get_list();
|
||||
$languages = [
|
||||
["code"=>"ar", "name" => "Arabic"],
|
||||
["code"=>"en", "name" => "English"],
|
||||
["code"=>"fr", "name" => "French"],
|
||||
["code"=>"es", "name" => "Spanish"]
|
||||
["code"=>"es", "name" => "Spanish"],
|
||||
["code"=>"ar", "name" => "العربية"],
|
||||
["code"=>"de", "name" => "German"],
|
||||
["code"=>"pt-br", "name" => "Portuguese (Brazilian)"],
|
||||
["code"=>"it", "name" => "Italian"],
|
||||
];
|
||||
$fiscal_years = [
|
||||
['key' => 'january-december' , 'value' => '1-12'],
|
||||
@ -58,8 +70,6 @@ class OnboardingController extends Controller
|
||||
$user = User::with([
|
||||
'addresses',
|
||||
'addresses.country',
|
||||
'addresses.state',
|
||||
'addresses.city',
|
||||
'company'
|
||||
])->find(1);
|
||||
|
||||
@ -74,6 +84,13 @@ class OnboardingController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup Admin Profile.
|
||||
*
|
||||
* @param \Crater\Http\Requests\ProfileRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function adminProfile(ProfileRequest $request)
|
||||
{
|
||||
$setting = Setting::getSetting('profile_complete');
|
||||
@ -99,6 +116,44 @@ class OnboardingController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Admin Avatar.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function uploadAdminAvatar(Request $request)
|
||||
{
|
||||
$setting = Setting::getSetting('profile_complete');
|
||||
|
||||
if ($setting == '1' || $setting == 'COMPLETED') {
|
||||
return response()->json(['error' => 'Profile already created.']);
|
||||
}
|
||||
$data = json_decode($request->admin_avatar);
|
||||
|
||||
if($data) {
|
||||
$user = User::find($data->id);
|
||||
if($user) {
|
||||
$user->clearMediaCollection('admin_avatar');
|
||||
|
||||
$user->addMediaFromBase64($data->data)
|
||||
->usingFileName($data->name)
|
||||
->toMediaCollection('admin_avatar');
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Admin Company.
|
||||
*
|
||||
* @param \Crater\Http\Requests\CompanyRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function adminCompany(CompanyRequest $request)
|
||||
{
|
||||
$setting = Setting::getSetting('profile_complete');
|
||||
@ -130,8 +185,8 @@ class OnboardingController extends Controller
|
||||
$fields = $request->only([
|
||||
'address_street_1',
|
||||
'address_street_2',
|
||||
'city_id',
|
||||
'state_id',
|
||||
'city',
|
||||
'state',
|
||||
'country_id',
|
||||
'zip',
|
||||
'phone'
|
||||
@ -150,6 +205,13 @@ class OnboardingController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup Company Settings.
|
||||
*
|
||||
* @param \Crater\Http\Requests\CompanySettingRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function companySettings(CompanySettingRequest $request)
|
||||
{
|
||||
$setting = Setting::getSetting('profile_complete');
|
||||
@ -178,6 +240,45 @@ class OnboardingController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
$invoices = [
|
||||
'invoice_auto_generate' => 'YES',
|
||||
'invoice_prefix' => 'INV'
|
||||
];
|
||||
|
||||
foreach ($invoices as $key => $value) {
|
||||
CompanySetting::setSetting(
|
||||
$key,
|
||||
$value,
|
||||
$user->company_id
|
||||
);
|
||||
}
|
||||
|
||||
$estimates = [
|
||||
'estimate_prefix' => 'EST',
|
||||
'estimate_auto_generate' => 'YES'
|
||||
];
|
||||
|
||||
foreach ($estimates as $key => $value) {
|
||||
CompanySetting::setSetting(
|
||||
$key,
|
||||
$value,
|
||||
$user->company_id
|
||||
);
|
||||
}
|
||||
|
||||
$payments = [
|
||||
'payment_prefix' => 'PAY',
|
||||
'payment_auto_generate' => 'YES'
|
||||
];
|
||||
|
||||
foreach ($payments as $key => $value) {
|
||||
CompanySetting::setSetting(
|
||||
$key,
|
||||
$value,
|
||||
$user->company_id
|
||||
);
|
||||
}
|
||||
|
||||
$colors = [
|
||||
'primary_text_color' => '#5851D8',
|
||||
'heading_text_color' => '#595959',
|
||||
@ -208,13 +309,24 @@ class OnboardingController extends Controller
|
||||
|
||||
Artisan::call('passport:install --force');
|
||||
|
||||
Artisan::call('db:seed', ['--class' => 'PaymentMethodSeeder', '--force' => true]);
|
||||
|
||||
Artisan::call('db:seed', ['--class' => 'UnitSeeder', '--force' => true]);
|
||||
|
||||
$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)
|
||||
'PROXY_OAUTH_CLIENT_SECRET='.config('auth.proxy.client_secret'),
|
||||
'PROXY_OAUTH_CLIENT_SECRET='.$client->secret,
|
||||
file_get_contents($path)
|
||||
));
|
||||
file_put_contents($path, str_replace(
|
||||
'APP_DEBUG=true',
|
||||
'APP_DEBUG=false',
|
||||
file_get_contents($path)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@ -4,12 +4,16 @@ namespace Crater\Http\Controllers;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\CompanySetting;
|
||||
use Crater\Currency;
|
||||
use Crater\Company;
|
||||
use Crater\Invoice;
|
||||
use Crater\Payment;
|
||||
use Crater\PaymentMethod;
|
||||
use Carbon\Carbon;
|
||||
use function MongoDB\BSON\toJSON;
|
||||
use Crater\User;
|
||||
use Crater\Http\Requests\PaymentRequest;
|
||||
use Validator;
|
||||
use Crater\Mail\PaymentPdf;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
@ -22,19 +26,20 @@ class PaymentController extends Controller
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$payments = Payment::with('user', 'invoice')
|
||||
$payments = Payment::with(['user', 'invoice', 'paymentMethod'])
|
||||
->join('users', 'users.id', '=', 'payments.user_id')
|
||||
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
||||
->leftJoin('payment_methods', 'payment_methods.id', '=', 'payments.payment_method_id')
|
||||
->applyFilters($request->only([
|
||||
'search',
|
||||
'payment_number',
|
||||
'payment_mode',
|
||||
'payment_method_id',
|
||||
'customer_id',
|
||||
'orderByField',
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('payments.*', 'users.name', 'invoices.invoice_number')
|
||||
->select('payments.*', 'users.name', 'invoices.invoice_number', 'payment_methods.name as payment_mode')
|
||||
->latest()
|
||||
->paginate($limit);
|
||||
|
||||
@ -50,13 +55,27 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$nextPaymentNumber = 'PAY-'.Payment::getNextPaymentNumber();
|
||||
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
|
||||
$payment_num_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company'));
|
||||
|
||||
|
||||
$nextPaymentNumberAttribute = null;
|
||||
$nextPaymentNumber = Payment::getNextPaymentNumber($payment_prefix);
|
||||
|
||||
if ($payment_num_auto_generate == "YES") {
|
||||
$nextPaymentNumberAttribute = $nextPaymentNumber;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'customers' => User::where('role', 'customer')
|
||||
->whereCompany($request->header('company'))
|
||||
->get(),
|
||||
'nextPaymentNumber' => $nextPaymentNumber
|
||||
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get(),
|
||||
'nextPaymentNumberAttribute' => $nextPaymentNumberAttribute,
|
||||
'nextPaymentNumber' => $payment_prefix.'-'.$nextPaymentNumber,
|
||||
'payment_prefix' => $payment_prefix
|
||||
]);
|
||||
}
|
||||
|
||||
@ -68,6 +87,13 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function store(PaymentRequest $request)
|
||||
{
|
||||
$payment_number = explode("-",$request->payment_number);
|
||||
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
|
||||
|
||||
Validator::make($number_attributes, [
|
||||
'payment_number' => 'required|unique:payments,payment_number'
|
||||
])->validate();
|
||||
|
||||
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||
|
||||
if ($request->has('invoice_id') && $request->invoice_id != null) {
|
||||
@ -90,17 +116,19 @@ class PaymentController extends Controller
|
||||
|
||||
$payment = Payment::create([
|
||||
'payment_date' => $payment_date,
|
||||
'payment_number' => $request->payment_number,
|
||||
'payment_number' => $number_attributes['payment_number'],
|
||||
'user_id' => $request->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_id' => $request->invoice_id,
|
||||
'payment_mode' => $request->payment_mode,
|
||||
'payment_method_id' => $request->payment_method_id,
|
||||
'amount' => $request->amount,
|
||||
'notes' => $request->notes,
|
||||
'unique_hash' => str_random(60)
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
@ -113,7 +141,12 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
//
|
||||
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +157,7 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, $id)
|
||||
{
|
||||
$payment = Payment::with('user', 'invoice')->find($id);
|
||||
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
|
||||
|
||||
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
|
||||
->where('user_id', $payment->user_id)->where('due_amount', '>', 0)
|
||||
@ -135,7 +168,12 @@ class PaymentController extends Controller
|
||||
'customers' => User::where('role', 'customer')
|
||||
->whereCompany($request->header('company'))
|
||||
->get(),
|
||||
'nextPaymentNumber' => $payment->payment_number,
|
||||
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get(),
|
||||
'nextPaymentNumber' => $payment->getPaymentNumAttribute(),
|
||||
'payment_prefix' => $payment->getPaymentPrefixAttribute(),
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'payment' => $payment,
|
||||
'invoices' => $invoices
|
||||
]);
|
||||
@ -150,6 +188,13 @@ class PaymentController extends Controller
|
||||
*/
|
||||
public function update(PaymentRequest $request, $id)
|
||||
{
|
||||
$payment_number = explode("-",$request->payment_number);
|
||||
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
|
||||
|
||||
Validator::make($number_attributes, [
|
||||
'payment_number' => 'required|unique:payments,payment_number'.','.$id
|
||||
])->validate();
|
||||
|
||||
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||
|
||||
$payment = Payment::find($id);
|
||||
@ -178,16 +223,17 @@ class PaymentController extends Controller
|
||||
}
|
||||
|
||||
$payment->payment_date = $payment_date;
|
||||
$payment->payment_number = $request->payment_number;
|
||||
$payment->payment_number = $number_attributes['payment_number'];
|
||||
$payment->user_id = $request->user_id;
|
||||
$payment->invoice_id = $request->invoice_id;
|
||||
$payment->payment_mode = $request->payment_mode;
|
||||
$payment->payment_method_id = $request->payment_method_id;
|
||||
$payment->amount = $request->amount;
|
||||
$payment->notes = $request->notes;
|
||||
$payment->save();
|
||||
|
||||
return response()->json([
|
||||
'payment' => $payment,
|
||||
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
@ -249,4 +295,27 @@ class PaymentController extends Controller
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public function sendPayment(Request $request)
|
||||
{
|
||||
$payment = Payment::findOrFail($request->id);
|
||||
|
||||
$data['payment'] = $payment->toArray();
|
||||
$userId = $data['payment']['user_id'];
|
||||
$data['user'] = User::find($userId)->toArray();
|
||||
$data['company'] = Company::find($payment->company_id);
|
||||
$email = $data['user']['email'];
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
'error' => 'user_email_does_not_exist'
|
||||
]);
|
||||
}
|
||||
|
||||
\Mail::to($email)->send(new PaymentPdf($data));
|
||||
|
||||
return response()->json([
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
119
app/Http/Controllers/PaymentMethodController.php
Normal file
119
app/Http/Controllers/PaymentMethodController.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Controllers;
|
||||
|
||||
use Crater\PaymentMethod;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Http\Requests\PaymentMethodRequest;
|
||||
|
||||
class PaymentMethodController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethods' => $paymentMethods
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(PaymentMethodRequest $request)
|
||||
{
|
||||
$paymentMethod = new PaymentMethod;
|
||||
$paymentMethod->name = $request->name;
|
||||
$paymentMethod->company_id = $request->header('company');
|
||||
$paymentMethod->save();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(PaymentMethod $paymentMethod)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(PaymentMethod $paymentMethod)
|
||||
{
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(PaymentMethodRequest $request, PaymentMethod $paymentMethod)
|
||||
{
|
||||
$paymentMethod->name = $request->name;
|
||||
$paymentMethod->company_id = $request->header('company');
|
||||
$paymentMethod->save();
|
||||
|
||||
return response()->json([
|
||||
'paymentMethod' => $paymentMethod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \Crater\PaymentMethod $paymentMethod
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(PaymentMethod $paymentMethod)
|
||||
{
|
||||
$payments = $paymentMethod->payments;
|
||||
|
||||
if ($payments->count() > 0) {
|
||||
return response()->json([
|
||||
'error' => 'payments_attached'
|
||||
]);
|
||||
}
|
||||
|
||||
$paymentMethod->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => 'Payment method deleted successfully'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -83,8 +83,7 @@ class ReportController extends Controller
|
||||
{
|
||||
$company = Company::where('unique_hash', $hash)->first();
|
||||
|
||||
$items = InvoiceItem::with('item')
|
||||
->whereCompany($company->id)
|
||||
$items = InvoiceItem::whereCompany($company->id)
|
||||
->applyInvoiceFilters($request->only(['from_date', 'to_date']))
|
||||
->itemAttributes()
|
||||
->get();
|
||||
|
||||
@ -4,9 +4,18 @@ namespace Crater\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Setting;
|
||||
use Crater\Mail\TestMail;
|
||||
use Mail;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrive App Version.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getAppVersion(Request $request)
|
||||
{
|
||||
$version = Setting::getSetting('version');
|
||||
@ -16,4 +25,18 @@ class SettingsController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function testEmailConfig(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'to' => 'required|email',
|
||||
'subject' => 'required',
|
||||
'message' => 'required'
|
||||
]);
|
||||
|
||||
Mail::to($request->to)->send(new TestMail($request->subject, $request->message));
|
||||
|
||||
return response()->json([
|
||||
'success' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
119
app/Http/Controllers/UnitController.php
Normal file
119
app/Http/Controllers/UnitController.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Controllers;
|
||||
|
||||
use Crater\Unit;
|
||||
use Illuminate\Http\Request;
|
||||
use Crater\Http\Requests\UnitRequest;
|
||||
|
||||
class UnitController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$units = Unit::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'units' => $units
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(UnitRequest $request)
|
||||
{
|
||||
$unit = new Unit;
|
||||
$unit->name = $request->name;
|
||||
$unit->company_id = $request->header('company');
|
||||
$unit->save();
|
||||
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Unit $unit)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Unit $unit)
|
||||
{
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UnitRequest $request, Unit $unit)
|
||||
{
|
||||
$unit->name = $request->name;
|
||||
$unit->company_id = $request->header('company');
|
||||
$unit->save();
|
||||
|
||||
return response()->json([
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \Crater\Unit $unit
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Unit $unit)
|
||||
{
|
||||
$items = $unit->items;
|
||||
|
||||
if ($items->count() > 0) {
|
||||
return response()->json([
|
||||
'error' => 'items_attached'
|
||||
]);
|
||||
}
|
||||
|
||||
$unit->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => 'Unit deleted successfully'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@ use Crater\User;
|
||||
use Crater\Currency;
|
||||
use Crater\Setting;
|
||||
use Crater\Item;
|
||||
use Crater\PaymentMethod;
|
||||
use Crater\Unit;
|
||||
use Crater\TaxType;
|
||||
use DB;
|
||||
use Carbon\Carbon;
|
||||
@ -46,10 +48,18 @@ class UsersController extends Controller
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
$items = Item::all();
|
||||
$items = Item::with('taxes')->get();
|
||||
|
||||
$taxTypes = TaxType::latest()->get();
|
||||
|
||||
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
$units = Unit::whereCompany($request->header('company'))
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
'customers' => $customers,
|
||||
@ -61,6 +71,8 @@ class UsersController extends Controller
|
||||
'items' => $items,
|
||||
'taxTypes' => $taxTypes,
|
||||
'moment_date_format' => $moment_date_format,
|
||||
'paymentMethods' => $paymentMethods,
|
||||
'units' => $units,
|
||||
'fiscal_year' => $fiscal_year,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@ class CustomerRequest extends FormRequest
|
||||
'name' => 'required',
|
||||
'addresses.*.address_street_1' => 'max:255',
|
||||
'addresses.*.address_street_2' => 'max:255',
|
||||
'email' => 'email|nullable|unique:users,email,'.$this->id
|
||||
];
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -25,11 +25,11 @@ class DatabaseEnvironmentRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'app_url' => 'required|url',
|
||||
'database_connection' => 'required|string|max:50',
|
||||
'database_hostname' => 'required|string|max:50',
|
||||
'database_connection' => 'required|string',
|
||||
'database_hostname' => 'required|string',
|
||||
'database_port' => 'required|numeric',
|
||||
'database_name' => 'required|string|max:50',
|
||||
'database_username' => 'required|string|max:50',
|
||||
'database_name' => 'required|string',
|
||||
'database_username' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@ class EstimatesRequest extends FormRequest
|
||||
$rules = [
|
||||
'estimate_date' => 'required',
|
||||
'expiry_date' => 'required',
|
||||
'estimate_number' => 'required|unique:estimates,estimate_number',
|
||||
'user_id' => 'required',
|
||||
'discount' => 'required',
|
||||
'discount_val' => 'required',
|
||||
@ -41,10 +40,6 @@ class EstimatesRequest extends FormRequest
|
||||
'items.*.price' => 'required'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$rules['estimate_number'] = $rules['estimate_number'].','.$this->get('id');
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@ class InvoicesRequest extends FormRequest
|
||||
$rules = [
|
||||
'invoice_date' => 'required',
|
||||
'due_date' => 'required',
|
||||
'invoice_number' => 'required|unique:invoices,invoice_number',
|
||||
'user_id' => 'required',
|
||||
'discount' => 'required',
|
||||
'discount_val' => 'required',
|
||||
@ -41,10 +40,6 @@ class InvoicesRequest extends FormRequest
|
||||
'items.*.price' => 'required'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$rules['invoice_number'] = $rules['invoice_number'].','.$this->get('id');
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,55 +26,52 @@ class MailEnvironmentRequest extends FormRequest
|
||||
switch ($this->get('mail_driver')) {
|
||||
case 'smtp':
|
||||
return [
|
||||
'mail_driver' => 'required|string|max:50',
|
||||
'mail_host' => 'required|string|max:50',
|
||||
'mail_port' => 'required|max:50',
|
||||
'mail_driver' => 'required|string',
|
||||
'mail_host' => 'required|string',
|
||||
'mail_port' => 'required',
|
||||
'mail_username' => 'required|string',
|
||||
'mail_password' => 'required|string',
|
||||
'mail_encryption' => 'required|string|max:50',
|
||||
'from_name' => 'required|string|max:50',
|
||||
'from_mail' => 'required|string|max:50',
|
||||
'mail_encryption' => 'required|string',
|
||||
'from_name' => 'required|string',
|
||||
'from_mail' => 'required|string',
|
||||
];
|
||||
break;
|
||||
|
||||
case 'mailgun':
|
||||
return [
|
||||
'mail_driver' => 'required|string|max:50',
|
||||
'mail_host' => 'required|string|max:50',
|
||||
'mail_port' => 'required|max:50',
|
||||
'mail_driver' => 'required|string',
|
||||
'mail_mailgun_domain' => 'required|string',
|
||||
'mail_mailgun_secret' => 'required|string',
|
||||
'mail_mailgun_endpoint' => 'required|string',
|
||||
'mail_encryption' => 'required|string|max:50',
|
||||
'from_name' => 'required|string|max:50',
|
||||
'from_mail' => 'required|string|max:50',
|
||||
'from_name' => 'required|string',
|
||||
'from_mail' => 'required|string',
|
||||
];
|
||||
break;
|
||||
|
||||
case 'ses':
|
||||
return [
|
||||
'mail_driver' => 'required|string|max:50',
|
||||
'mail_host' => 'required|string|max:50',
|
||||
'mail_port' => 'required|max:50',
|
||||
'mail_driver' => 'required|string',
|
||||
'mail_host' => 'required|string',
|
||||
'mail_port' => 'required',
|
||||
'mail_ses_key' => 'required|string',
|
||||
'mail_ses_secret' => 'required|string',
|
||||
'mail_encryption' => 'required|string|max:50',
|
||||
'from_name' => 'required|string|max:50',
|
||||
'from_mail' => 'required|string|max:50',
|
||||
'mail_encryption' => 'required|string',
|
||||
'from_name' => 'required|string',
|
||||
'from_mail' => 'required|string',
|
||||
];
|
||||
break;
|
||||
|
||||
case 'mail':
|
||||
return [
|
||||
'from_name' => 'required|string|max:50',
|
||||
'from_mail' => 'required|string|max:50',
|
||||
'from_name' => 'required|string',
|
||||
'from_mail' => 'required|string',
|
||||
];
|
||||
break;
|
||||
|
||||
case 'sendmail':
|
||||
return [
|
||||
'from_name' => 'required|string|max:50',
|
||||
'from_mail' => 'required|string|max:50',
|
||||
'from_name' => 'required|string',
|
||||
'from_mail' => 'required|string',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
40
app/Http/Requests/PaymentMethodRequest.php
Normal file
40
app/Http/Requests/PaymentMethodRequest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PaymentMethodRequest 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()
|
||||
{
|
||||
$data = [
|
||||
'name' => 'required|unique:payment_methods,name'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$data['name'] = [
|
||||
'required',
|
||||
Rule::unique('payment_methods')->ignore($this->route('payment_method'), 'id')
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@ -24,15 +24,10 @@ class PaymentRequest extends FormRequest
|
||||
{
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ class ProfileRequest extends FormRequest
|
||||
case 'POST':
|
||||
return [
|
||||
'name' => 'required',
|
||||
'password' => 'required',
|
||||
'password' => 'required|min:8',
|
||||
'address_street_1' => 'max:255',
|
||||
'address_street_2' => 'max:255',
|
||||
'email' => [
|
||||
|
||||
40
app/Http/Requests/UnitRequest.php
Normal file
40
app/Http/Requests/UnitRequest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UnitRequest 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()
|
||||
{
|
||||
$data = [
|
||||
'name' => 'required|unique:units,name'
|
||||
];
|
||||
|
||||
if ($this->getMethod() == 'PUT') {
|
||||
$data['name'] = [
|
||||
'required',
|
||||
Rule::unique('units')->ignore($this->route('unit'), 'id')
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@ -66,10 +66,14 @@ class Invoice extends Model
|
||||
'formattedDueDate'
|
||||
];
|
||||
|
||||
public static function getNextInvoiceNumber()
|
||||
public static function getNextInvoiceNumber($value)
|
||||
{
|
||||
// Get the last created order
|
||||
$lastOrder = Invoice::orderBy('created_at', 'desc')->first();
|
||||
$lastOrder = Invoice::where('invoice_number', 'LIKE', $value . '-%')
|
||||
->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.
|
||||
@ -82,7 +86,7 @@ class Invoice extends Model
|
||||
// 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.
|
||||
// the %06d 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);
|
||||
@ -143,10 +147,15 @@ class Invoice extends Model
|
||||
|
||||
public function getInvoiceNumAttribute()
|
||||
{
|
||||
$position = $this->strposX($this->invoice_number, "-", 2) + 1;
|
||||
$position = $this->strposX($this->invoice_number, "-", 1) + 1;
|
||||
return substr($this->invoice_number, $position);
|
||||
}
|
||||
|
||||
public function getInvoicePrefixAttribute () {
|
||||
$prefix = explode("-", $this->invoice_number)[0];
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
public function getFormattedCreatedAtAttribute($value)
|
||||
{
|
||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||
|
||||
@ -30,6 +30,7 @@ class InvoiceItem extends Model
|
||||
'price' => 'integer',
|
||||
'total' => 'integer',
|
||||
'discount' => 'float',
|
||||
'quantity' => 'float',
|
||||
'discount_val' => 'integer',
|
||||
'tax' => 'integer'
|
||||
];
|
||||
@ -78,7 +79,8 @@ class InvoiceItem extends Model
|
||||
public function scopeItemAttributes($query)
|
||||
{
|
||||
$query->select(
|
||||
DB::raw('sum(quantity) as total_quantity, sum(total) as total_amount, item_id')
|
||||
)->groupBy('item_id');
|
||||
DB::raw('sum(quantity) as total_quantity, sum(total) as total_amount, invoice_items.name')
|
||||
)->groupBy('invoice_items.name');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
19
app/Item.php
19
app/Item.php
@ -24,19 +24,24 @@ class Item extends Model
|
||||
'formattedCreatedAt'
|
||||
];
|
||||
|
||||
public function unit()
|
||||
{
|
||||
return $this->belongsTo(Unit::class);
|
||||
}
|
||||
|
||||
public function scopeWhereSearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'LIKE', '%'.$search.'%');
|
||||
return $query->where('items.name', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
public function scopeWherePrice($query, $price)
|
||||
{
|
||||
return $query->where('price', $price);
|
||||
return $query->where('items.price', $price);
|
||||
}
|
||||
|
||||
public function scopeWhereUnit($query, $unit)
|
||||
public function scopeWhereUnit($query, $unit_id)
|
||||
{
|
||||
return $query->where('unit', $unit);
|
||||
return $query->where('items.unit_id', $unit_id);
|
||||
}
|
||||
|
||||
public function scopeWhereOrder($query, $orderByField, $orderBy)
|
||||
@ -56,8 +61,8 @@ class Item extends Model
|
||||
$query->wherePrice($filters->get('price'));
|
||||
}
|
||||
|
||||
if ($filters->get('unit')) {
|
||||
$query->whereUnit($filters->get('unit'));
|
||||
if ($filters->get('unit_id')) {
|
||||
$query->whereUnit($filters->get('unit_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||
@ -80,7 +85,7 @@ class Item extends Model
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
$query->where('items.company_id', $company_id);
|
||||
}
|
||||
|
||||
public function invoiceItems()
|
||||
|
||||
@ -12,10 +12,10 @@ class Listener
|
||||
* @param $event
|
||||
* @return boolean
|
||||
*/
|
||||
protected function check($event)
|
||||
protected function isListenerFired($event)
|
||||
{
|
||||
// Do not apply to the same or newer versions
|
||||
if (version_compare(static::VERSION, $event->old, '>')) {
|
||||
if (version_compare(static::VERSION, $event->old, '<=')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
115
app/Listeners/Updates/v1/Version110.php
Normal file
115
app/Listeners/Updates/v1/Version110.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v1;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Setting;
|
||||
use Crater\Currency;
|
||||
|
||||
class Version110 extends Listener
|
||||
{
|
||||
const VERSION = '1.1.0';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add currencies
|
||||
$this->addCurrencies();
|
||||
|
||||
// Update Crater app version
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
|
||||
private function addCurrencies() {
|
||||
|
||||
$currencies = [
|
||||
'13' => [
|
||||
'symbol' => 'S$'
|
||||
],
|
||||
'16' => [
|
||||
'symbol' => '₫'
|
||||
],
|
||||
'17' => [
|
||||
'symbol' => 'Fr.'
|
||||
],
|
||||
'21' => [
|
||||
'symbol' => '฿'
|
||||
],
|
||||
'22' => [
|
||||
'symbol' => '₦'
|
||||
],
|
||||
'26' => [
|
||||
'symbol' => 'HK$'
|
||||
],
|
||||
'35' => [
|
||||
'symbol' => 'NAƒ'
|
||||
],
|
||||
'38' => [
|
||||
'symbol' => 'GH₵'
|
||||
],
|
||||
'39' => [
|
||||
'symbol' => 'Лв.'
|
||||
],
|
||||
'42' => [
|
||||
'symbol' => 'RON'
|
||||
],
|
||||
'44' => [
|
||||
'symbol' => 'SِAR'
|
||||
],
|
||||
'46' => [
|
||||
'symbol' => 'Rf'
|
||||
],
|
||||
'47' => [
|
||||
'symbol' => '₡'
|
||||
],
|
||||
'54' => [
|
||||
'symbol' => 'د.ت'
|
||||
],
|
||||
'55' => [
|
||||
'symbol' => '₽'
|
||||
],
|
||||
'57' => [
|
||||
'symbol' => 'ر.ع.'
|
||||
],
|
||||
'58' => [
|
||||
'symbol' => '₴'
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
foreach ($currencies as $key => $currency) {
|
||||
Currency::updateOrCreate(['id' => $key], $currency);
|
||||
}
|
||||
|
||||
Currency::create([
|
||||
'name' => 'Kuwaiti Dinar',
|
||||
'code' => 'KWD',
|
||||
'symbol' => 'KWD ',
|
||||
'precision' => '3',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
109
app/Listeners/Updates/v2/Version200.php
Normal file
109
app/Listeners/Updates/v2/Version200.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v2;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Setting;
|
||||
use Crater\Address;
|
||||
|
||||
class Version200 extends Listener
|
||||
{
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace state and city id to name
|
||||
$this->replaceStateAndCityName();
|
||||
|
||||
// Drop states and cities foreign key
|
||||
$this->dropForeignKey();
|
||||
|
||||
// Remove states and cities tables
|
||||
$this->dropSchemas();
|
||||
|
||||
// Delete state & city models, migrations & seeders
|
||||
$this->deleteFiles();
|
||||
|
||||
// Update Crater app version
|
||||
$this->updateVersion();
|
||||
}
|
||||
|
||||
private function replaceStateAndCityName() {
|
||||
\Schema::table('addresses', function (Blueprint $table) {
|
||||
$table->string('state')->nullable();
|
||||
$table->string('city')->nullable();
|
||||
});
|
||||
|
||||
$addresses = \Crater\Address::all();
|
||||
foreach ($addresses as $add) {
|
||||
$city = \Crater\City::find($add->city_id);
|
||||
if($city) {
|
||||
$add->city = $city->name;
|
||||
}
|
||||
|
||||
$state = \Crater\State::find($add->state_id);
|
||||
if($state) {
|
||||
$add->state = $state->name;
|
||||
}
|
||||
|
||||
$add->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function dropForeignKey() {
|
||||
\Schema::table('addresses', function (Blueprint $table) {
|
||||
$table->dropForeign('addresses_state_id_foreign');
|
||||
$table->dropForeign('addresses_city_id_foreign');
|
||||
$table->dropColumn('state_id');
|
||||
$table->dropColumn('city_id');
|
||||
});
|
||||
}
|
||||
|
||||
private function dropSchemas() {
|
||||
\Schema::disableForeignKeyConstraints();
|
||||
|
||||
\Schema::dropIfExists('states');
|
||||
\Schema::dropIfExists('cities');
|
||||
|
||||
\Schema::enableForeignKeyConstraints();
|
||||
}
|
||||
|
||||
private function deleteFiles() {
|
||||
\File::delete(
|
||||
database_path('migrations/2017_05_06_172817_create_cities_table.php'),
|
||||
database_path('migrations/2017_05_06_173711_create_states_table.php'),
|
||||
database_path('seeds/StatesTableSeeder.php'),
|
||||
database_path('seeds/CitiesTableSeeder.php'),
|
||||
app_path('City.php'),
|
||||
app_path('State.php')
|
||||
);
|
||||
}
|
||||
|
||||
private function updateVersion() {
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
}
|
||||
87
app/Listeners/Updates/v2/Version201.php
Normal file
87
app/Listeners/Updates/v2/Version201.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v2;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Setting;
|
||||
|
||||
class Version201 extends Listener
|
||||
{
|
||||
const VERSION = '2.0.1';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the language files
|
||||
$this->removeLanguageFiles();
|
||||
|
||||
// Change estimate & invoice migrations
|
||||
$this->changeMigrations();
|
||||
|
||||
// Update Crater app version
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
|
||||
private function removeLanguageFiles() {
|
||||
$en = resource_path('assets/js/plugins/en.js');
|
||||
$es = resource_path('assets/js/plugins/es.js');
|
||||
$fr = resource_path('assets/js/plugins/fr.js');
|
||||
|
||||
if(file_exists($en)) {
|
||||
unlink($en);
|
||||
}
|
||||
|
||||
if(file_exists($es)) {
|
||||
unlink($es);
|
||||
}
|
||||
|
||||
if(file_exists($fr)) {
|
||||
unlink($fr);
|
||||
}
|
||||
}
|
||||
|
||||
private function changeMigrations()
|
||||
{
|
||||
\Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->decimal('discount', 15, 2)->nullable()->change();
|
||||
});
|
||||
|
||||
\Schema::table('estimates', function (Blueprint $table) {
|
||||
$table->decimal('discount', 15, 2)->nullable()->change();
|
||||
});
|
||||
|
||||
\Schema::table('invoice_items', function (Blueprint $table) {
|
||||
$table->decimal('quantity', 15, 2)->change();
|
||||
$table->decimal('discount', 15, 2)->nullable()->change();
|
||||
});
|
||||
|
||||
\Schema::table('estimate_items', function (Blueprint $table) {
|
||||
$table->decimal('quantity', 15, 2)->change();
|
||||
$table->decimal('discount', 15, 2)->nullable()->change();
|
||||
$table->unsignedBigInteger('discount_val')->nullable()->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
40
app/Listeners/Updates/v2/Version202.php
Normal file
40
app/Listeners/Updates/v2/Version202.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v2;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Setting;
|
||||
|
||||
class Version202 extends Listener
|
||||
{
|
||||
const VERSION = '2.0.2';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Crater app version
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
}
|
||||
64
app/Listeners/Updates/v2/Version210.php
Normal file
64
app/Listeners/Updates/v2/Version210.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v2;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Setting;
|
||||
use Crater\CompanySetting;
|
||||
|
||||
class Version210 extends Listener
|
||||
{
|
||||
const VERSION = '2.1.0';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add initial auto generate value
|
||||
$this->addAutoGenerateSettings();
|
||||
|
||||
// Update Crater app version
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
|
||||
private function addAutoGenerateSettings()
|
||||
{
|
||||
$settings = [
|
||||
'invoice_auto_generate' => 'YES',
|
||||
'invoice_prefix' => 'INV',
|
||||
'estimate_prefix' => 'EST',
|
||||
'estimate_auto_generate' => 'YES',
|
||||
'payment_prefix' => 'PAY',
|
||||
'payment_auto_generate' => 'YES'
|
||||
];
|
||||
|
||||
foreach ($settings as $key => $value) {
|
||||
CompanySetting::setSetting(
|
||||
$key,
|
||||
$value,
|
||||
auth()->user()->company->id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
app/Listeners/Updates/v3/Version300.php
Normal file
162
app/Listeners/Updates/v3/Version300.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v3;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Setting;
|
||||
use Crater\Unit;
|
||||
use Crater\PaymentMethod;
|
||||
use Crater\Currency;
|
||||
use Crater\Payment;
|
||||
use Crater\Item;
|
||||
use Crater\User;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class Version300 extends Listener
|
||||
{
|
||||
const VERSION = '3.0.0';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->changeMigrations();
|
||||
|
||||
$this->addSeederData();
|
||||
|
||||
$this->databaseChanges();
|
||||
|
||||
$this->changeMigrations(true);
|
||||
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
|
||||
public function changeMigrations($removeColumn = false)
|
||||
{
|
||||
if ($removeColumn) {
|
||||
\Schema::table('items', function (Blueprint $table) {
|
||||
$table->dropColumn('unit');
|
||||
});
|
||||
|
||||
\Schema::table('payments', function (Blueprint $table) {
|
||||
$table->dropColumn('payment_mode');
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
\Schema::create('units', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
\Schema::table('items', function (Blueprint $table) {
|
||||
$table->integer('unit_id')->unsigned()->nullable();
|
||||
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
|
||||
});
|
||||
|
||||
\Schema::create('payment_methods', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
\Schema::table('payments', function (Blueprint $table) {
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('payment_method_id')->unsigned()->nullable();
|
||||
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addSeederData()
|
||||
{
|
||||
$company_id = User::where('role', 'admin')->first()->company_id;
|
||||
|
||||
Unit::create(['name' => 'box', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'cm', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'dz', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'ft', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'g', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'in', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'kg', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'km', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'lb', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'mg', 'company_id' => $company_id]);
|
||||
Unit::create(['name' => 'pc', 'company_id' => $company_id]);
|
||||
|
||||
PaymentMethod::create(['name' => 'Cash', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Check', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => $company_id]);
|
||||
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => $company_id]);
|
||||
|
||||
Currency::create([
|
||||
'name' => 'Serbian Dinar',
|
||||
'code' => 'RSD',
|
||||
'symbol' => 'RSD',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
]);
|
||||
}
|
||||
|
||||
public function databaseChanges()
|
||||
{
|
||||
$payments = Payment::all();
|
||||
|
||||
if ($payments) {
|
||||
foreach ($payments as $payment) {
|
||||
$payment->unique_hash = str_random(60);
|
||||
$payment->save();
|
||||
|
||||
$paymentMethod = PaymentMethod::where('name', $payment->payment_mode)
|
||||
->first();
|
||||
|
||||
if ($paymentMethod) {
|
||||
$payment->payment_method_id = $paymentMethod->id;
|
||||
$payment->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = Item::all();
|
||||
|
||||
if ($items) {
|
||||
foreach ($items as $item) {
|
||||
$unit = Unit::where('name', $item->unit)
|
||||
->first();
|
||||
|
||||
if ($unit) {
|
||||
$item->unit_id = $unit->id;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
app/Listeners/Updates/v3/Version301.php
Normal file
51
app/Listeners/Updates/v3/Version301.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v3;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Crater\Setting;
|
||||
use Crater\Currency;
|
||||
|
||||
class Version301 extends Listener
|
||||
{
|
||||
const VERSION = '3.0.1';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
if ($this->isListenerFired($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Currency::create([
|
||||
'name' => 'Kyrgyzstani som',
|
||||
'code' => 'KGS',
|
||||
'symbol' => 'С̲ ',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
]);
|
||||
|
||||
// Update Crater app version
|
||||
Setting::setSetting('version', static::VERSION);
|
||||
}
|
||||
}
|
||||
36
app/Listeners/Updates/v3/Version310.php
Normal file
36
app/Listeners/Updates/v3/Version310.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Listeners\Updates\v3;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Crater\Listeners\Updates\Listener;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Crater\Events\UpdateFinished;
|
||||
|
||||
class Version310
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(UpdateFinished $event)
|
||||
{
|
||||
\Schema::table('expenses', function (Blueprint $table) {
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -12,17 +12,14 @@ class EstimatePdf extends Mailable
|
||||
|
||||
public $data = [];
|
||||
|
||||
public $notificationEmail = '';
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($data, $notificationEmail)
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->notificationEmail = $notificationEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,6 +29,9 @@ class EstimatePdf extends Mailable
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->from($this->notificationEmail)->markdown('emails.send.estimate', ['data', $this->data]);
|
||||
$company = $this->data['company']['name'];
|
||||
|
||||
return $this->subject("Estimate from $company")
|
||||
->markdown('emails.send.estimate', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ class EstimateViewed extends Mailable
|
||||
public function build()
|
||||
{
|
||||
$email = $this->data['user']['email'];
|
||||
return $this->from($email)->markdown('emails.viewed.estimate', ['data', $this->data]);
|
||||
$name = $this->data['user']['name'];
|
||||
return $this->from($email, $name)
|
||||
->markdown('emails.viewed.estimate', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,23 +6,20 @@ use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class invoicePdf extends Mailable
|
||||
class InvoicePdf extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $data = [];
|
||||
|
||||
public $notificationEmail = '';
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($data, $notificationEmail)
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->notificationEmail = $notificationEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,6 +29,9 @@ class invoicePdf extends Mailable
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->from($this->notificationEmail)->markdown('emails.send.invoice', ['data', $this->data]);
|
||||
$company = $this->data['company']['name'];
|
||||
|
||||
return $this->subject("Invoice from $company")
|
||||
->markdown('emails.send.invoice', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,8 @@ class InvoiceViewed extends Mailable
|
||||
public function build()
|
||||
{
|
||||
$email = $this->data['user']['email'];
|
||||
return $this->from($email)->markdown('emails.viewed.invoice', ['data', $this->data]);
|
||||
$name = $this->data['user']['name'];
|
||||
return $this->from($email, $name)
|
||||
->markdown('emails.viewed.invoice', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
|
||||
38
app/Mail/PaymentPdf.php
Normal file
38
app/Mail/PaymentPdf.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PaymentPdf 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()
|
||||
{
|
||||
$company = $this->data['company']['name'];
|
||||
|
||||
return $this->subject("Payment from $company")
|
||||
->markdown('emails.send.payment', ['data', $this->data]);
|
||||
}
|
||||
}
|
||||
38
app/Mail/TestMail.php
Normal file
38
app/Mail/TestMail.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace Crater\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class TestMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
public $subject;
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param $subject
|
||||
* @param $message
|
||||
*/
|
||||
public function __construct($subject, $message)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->subject($this->subject)->markdown('emails.test')->with([
|
||||
'my_message' => $this->message
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ use Crater\User;
|
||||
use Crater\Invoice;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\PaymentMethod;
|
||||
|
||||
class Payment extends Model
|
||||
{
|
||||
@ -19,9 +20,11 @@ class Payment extends Model
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'invoice_id',
|
||||
'payment_method_id',
|
||||
'payment_date',
|
||||
'company_id',
|
||||
'notes',
|
||||
'unique_hash',
|
||||
'payment_number',
|
||||
'payment_mode',
|
||||
'amount'
|
||||
@ -32,10 +35,34 @@ class Payment extends Model
|
||||
'formattedPaymentDate'
|
||||
];
|
||||
|
||||
public static function getNextPaymentNumber()
|
||||
|
||||
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 getPaymentNumAttribute()
|
||||
{
|
||||
$position = $this->strposX($this->payment_number, "-", 1) + 1;
|
||||
return substr($this->payment_number, $position);
|
||||
}
|
||||
|
||||
public static function getNextPaymentNumber($value)
|
||||
{
|
||||
// Get the last created order
|
||||
$payment = Payment::orderBy('created_at', 'desc')->first();
|
||||
$payment = Payment::where('payment_number', 'LIKE', $value . '-%')
|
||||
->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.
|
||||
@ -54,6 +81,12 @@ class Payment extends Model
|
||||
return sprintf('%06d', intval($number) + 1);
|
||||
}
|
||||
|
||||
public function getPaymentPrefixAttribute ()
|
||||
{
|
||||
$prefix= explode("-",$this->payment_number)[0];
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
public function invoice()
|
||||
{
|
||||
return $this->belongsTo(Invoice::class);
|
||||
@ -64,6 +97,11 @@ class Payment extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function paymentMethod()
|
||||
{
|
||||
return $this->belongsTo(PaymentMethod::class);
|
||||
}
|
||||
|
||||
public function getFormattedCreatedAtAttribute($value)
|
||||
{
|
||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||
@ -92,9 +130,9 @@ class Payment extends Model
|
||||
return $query->where('payments.payment_number', 'LIKE', '%'.$paymentNumber.'%');
|
||||
}
|
||||
|
||||
public function scopePaymentMode($query, $paymentMode)
|
||||
public function scopePaymentMethod($query, $paymentMethodId)
|
||||
{
|
||||
return $query->where('payments.payment_mode', $paymentMode);
|
||||
return $query->where('payments.payment_method_id', $paymentMethodId);
|
||||
}
|
||||
|
||||
public function scopeApplyFilters($query, array $filters)
|
||||
@ -109,8 +147,8 @@ class Payment extends Model
|
||||
$query->paymentNumber($filters->get('payment_number'));
|
||||
}
|
||||
|
||||
if ($filters->get('payment_mode')) {
|
||||
$query->paymentMode($filters->get('payment_mode'));
|
||||
if ($filters->get('payment_method_id')) {
|
||||
$query->paymentMethod($filters->get('payment_method_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('customer_id')) {
|
||||
|
||||
25
app/PaymentMethod.php
Normal file
25
app/PaymentMethod.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PaymentMethod extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'company_id'];
|
||||
|
||||
public function payments()
|
||||
{
|
||||
return $this->hasMany(Payment::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,14 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Crater\Events\UpdateFinished;
|
||||
use Crater\Listeners\Updates\v1\Version110;
|
||||
use Crater\Listeners\Updates\v2\Version200;
|
||||
use Crater\Listeners\Updates\v2\Version201;
|
||||
use Crater\Listeners\Updates\v2\Version202;
|
||||
use Crater\Listeners\Updates\v2\Version210;
|
||||
use Crater\Listeners\Updates\v3\Version300;
|
||||
use Crater\Listeners\Updates\v3\Version301;
|
||||
use Crater\Listeners\Updates\v3\Version310;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -15,6 +23,14 @@ class EventServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $listen = [
|
||||
UpdateFinished::class=> [
|
||||
Version110::class,
|
||||
Version200::class,
|
||||
Version201::class,
|
||||
Version202::class,
|
||||
Version210::class,
|
||||
Version300::class,
|
||||
Version301::class,
|
||||
Version310::class,
|
||||
],
|
||||
Registered::class => [
|
||||
SendEmailVerificationNotification::class,
|
||||
|
||||
@ -38,7 +38,7 @@ class EnvironmentManager
|
||||
'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";
|
||||
'DB_PASSWORD="'.config('database.connections.'.config('database.default').'.password')."\"\n\n";
|
||||
|
||||
$newDatabaseData =
|
||||
'DB_CONNECTION='.$request->database_connection."\n".
|
||||
@ -46,19 +46,23 @@ class EnvironmentManager
|
||||
'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";
|
||||
'DB_PASSWORD="'.$request->database_password."\"\n\n";
|
||||
|
||||
if (! $this->checkDatabaseConnection($request)) {
|
||||
try {
|
||||
|
||||
return [
|
||||
'error' => 'connection_failed'
|
||||
];
|
||||
} else {
|
||||
if(count(DB::connection()->select('SHOW TABLES'))) {
|
||||
$this->checkDatabaseConnection($request);
|
||||
|
||||
if(\Schema::hasTable('users') ) {
|
||||
return [
|
||||
'error' => 'database_should_be_empty'
|
||||
];
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
return [
|
||||
'error_message' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
@ -118,8 +122,6 @@ class EnvironmentManager
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} catch (Exception $e) {
|
||||
return [
|
||||
'error' => 'mail_variables_save_error'
|
||||
@ -316,12 +318,6 @@ class EnvironmentManager
|
||||
],
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::connection()->getPdo();
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
return DB::connection()->getPdo();
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,13 @@ class Updater
|
||||
$data = null;
|
||||
$path = null;
|
||||
|
||||
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update';
|
||||
if(env('APP_ENV') === 'development')
|
||||
{
|
||||
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update&is_dev=1';
|
||||
} else {
|
||||
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update';
|
||||
}
|
||||
|
||||
|
||||
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
|
||||
|
||||
@ -115,7 +121,12 @@ class Updater
|
||||
public static function checkForUpdate()
|
||||
{
|
||||
$data = null;
|
||||
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update';
|
||||
if(env('APP_ENV') === 'development')
|
||||
{
|
||||
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update&is_dev=1';
|
||||
} else {
|
||||
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update';
|
||||
}
|
||||
|
||||
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
|
||||
|
||||
|
||||
@ -41,10 +41,14 @@ function clean_slug($string)
|
||||
* @param $money
|
||||
* @return formated_money
|
||||
*/
|
||||
function format_money_pdf($money)
|
||||
function format_money_pdf($money, $currency = null)
|
||||
{
|
||||
$money = $money / 100;
|
||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', 1));
|
||||
|
||||
if (!$currency) {
|
||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', 1));
|
||||
}
|
||||
|
||||
$format_money = number_format(
|
||||
$money,
|
||||
$currency->precision,
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\City;
|
||||
use Crater\Country;
|
||||
use Crater\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);
|
||||
}
|
||||
}
|
||||
26
app/Unit.php
Normal file
26
app/Unit.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Crater;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\Item;
|
||||
|
||||
class Unit extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'company_id'];
|
||||
|
||||
public function items()
|
||||
{
|
||||
return $this->hasMany(Item::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany($query, $company_id)
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
}
|
||||
}
|
||||
18
app/User.php
18
app/User.php
@ -9,6 +9,7 @@ use carbon\carbon;
|
||||
use Crater\MemberLoan;
|
||||
use Crater\Address;
|
||||
use Crater\Payment;
|
||||
use Crater\Expense;
|
||||
use Crater\Company;
|
||||
use Crater\Notifications\MailResetPasswordNotification;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||
@ -51,7 +52,8 @@ class User extends Authenticatable implements HasMedia
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'formattedCreatedAt'
|
||||
'formattedCreatedAt',
|
||||
'avatar'
|
||||
];
|
||||
|
||||
/**
|
||||
@ -104,6 +106,11 @@ class User extends Authenticatable implements HasMedia
|
||||
return $this->hasMany(Address::class);
|
||||
}
|
||||
|
||||
public function expenses()
|
||||
{
|
||||
return $this->hasMany(Expense::class);
|
||||
}
|
||||
|
||||
public function billingAddress()
|
||||
{
|
||||
return $this->hasOne(Address::class)->where('type', Address::BILLING_TYPE);
|
||||
@ -244,4 +251,13 @@ class User extends Authenticatable implements HasMedia
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAvatarAttribute()
|
||||
{
|
||||
$avatar = $this->getMedia('admin_avatar')->first();
|
||||
if ($avatar) {
|
||||
return asset($avatar->getUrl());
|
||||
}
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "laravel/laravel",
|
||||
"description": "The Laravel Framework.",
|
||||
"name": "bytefury/crater",
|
||||
"description": "Free & Open Source Invoice App for Freelancers & Small Businesses. https://craterapp.com",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"laravel"
|
||||
@ -10,6 +10,7 @@
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"barryvdh/laravel-dompdf": "^0.8.1",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"intervention/image": "^2.3",
|
||||
@ -52,11 +53,20 @@
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"initial-setup": [
|
||||
"test -f .env || (cp .env.example .env; php artisan key:generate 2>/dev/null; exit 0)"
|
||||
],
|
||||
"pre-install-cmd": [
|
||||
"@initial-setup"
|
||||
],
|
||||
"pre-update-cmd": [
|
||||
"@initial-setup"
|
||||
],
|
||||
"post-root-package-install": [
|
||||
"php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
"@initial-setup"
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"php artisan key:generate --ansi"
|
||||
"@initial-setup"
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
|
||||
484
composer.lock
generated
484
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2a5e8d91a2be3144e2812dd708dc14b7",
|
||||
"content-hash": "e7cf4f0a8e1e7d60cc72b34ed4c730ce",
|
||||
"packages": [
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
@ -158,6 +158,247 @@
|
||||
"description": "implementation of xdg base directory specification for php",
|
||||
"time": "2014-10-24T07:27:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "v1.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/cache.git",
|
||||
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/d4374ae95b36062d02ef310100ed33d78738d76c",
|
||||
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": ">2.2,<2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"alcaeus/mongo-php-adapter": "^1.1",
|
||||
"doctrine/coding-standard": "^4.0",
|
||||
"mongodb/mongodb": "^1.1",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"predis/predis": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Caching library offering an object-oriented API for many cache backends",
|
||||
"homepage": "https://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching"
|
||||
],
|
||||
"time": "2019-10-28T09:31:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "v2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/dbal.git",
|
||||
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
|
||||
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/cache": "^1.0",
|
||||
"doctrine/event-manager": "^1.0",
|
||||
"ext-pdo": "*",
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"jetbrains/phpstorm-stubs": "^2019.1",
|
||||
"phpstan/phpstan": "^0.11.3",
|
||||
"phpunit/phpunit": "^8.4.1",
|
||||
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
||||
},
|
||||
"bin": [
|
||||
"bin/doctrine-dbal"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.10.x-dev",
|
||||
"dev-develop": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
|
||||
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
|
||||
"keywords": [
|
||||
"abstraction",
|
||||
"database",
|
||||
"db2",
|
||||
"dbal",
|
||||
"mariadb",
|
||||
"mssql",
|
||||
"mysql",
|
||||
"oci8",
|
||||
"oracle",
|
||||
"pdo",
|
||||
"pgsql",
|
||||
"postgresql",
|
||||
"queryobject",
|
||||
"sasql",
|
||||
"sql",
|
||||
"sqlanywhere",
|
||||
"sqlite",
|
||||
"sqlserver",
|
||||
"sqlsrv"
|
||||
],
|
||||
"time": "2019-11-03T16:50:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/event-manager",
|
||||
"version": "v1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/event-manager.git",
|
||||
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3",
|
||||
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": "<2.9@dev"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^4.0",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\": "lib/Doctrine/Common"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Doctrine Event Manager component",
|
||||
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
|
||||
"keywords": [
|
||||
"event",
|
||||
"eventdispatcher",
|
||||
"eventmanager"
|
||||
],
|
||||
"time": "2018-06-11T11:59:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/inflector",
|
||||
"version": "v1.3.0",
|
||||
@ -5307,247 +5548,6 @@
|
||||
],
|
||||
"time": "2019-05-27T17:52:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "v1.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/cache.git",
|
||||
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/d4374ae95b36062d02ef310100ed33d78738d76c",
|
||||
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": ">2.2,<2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"alcaeus/mongo-php-adapter": "^1.1",
|
||||
"doctrine/coding-standard": "^4.0",
|
||||
"mongodb/mongodb": "^1.1",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"predis/predis": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Caching library offering an object-oriented API for many cache backends",
|
||||
"homepage": "https://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching"
|
||||
],
|
||||
"time": "2019-10-28T09:31:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "v2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/dbal.git",
|
||||
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
|
||||
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/cache": "^1.0",
|
||||
"doctrine/event-manager": "^1.0",
|
||||
"ext-pdo": "*",
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"jetbrains/phpstorm-stubs": "^2019.1",
|
||||
"phpstan/phpstan": "^0.11.3",
|
||||
"phpunit/phpunit": "^8.4.1",
|
||||
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
||||
},
|
||||
"bin": [
|
||||
"bin/doctrine-dbal"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.10.x-dev",
|
||||
"dev-develop": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
|
||||
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
|
||||
"keywords": [
|
||||
"abstraction",
|
||||
"database",
|
||||
"db2",
|
||||
"dbal",
|
||||
"mariadb",
|
||||
"mssql",
|
||||
"mysql",
|
||||
"oci8",
|
||||
"oracle",
|
||||
"pdo",
|
||||
"pgsql",
|
||||
"postgresql",
|
||||
"queryobject",
|
||||
"sasql",
|
||||
"sql",
|
||||
"sqlanywhere",
|
||||
"sqlite",
|
||||
"sqlserver",
|
||||
"sqlsrv"
|
||||
],
|
||||
"time": "2019-11-03T16:50:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/event-manager",
|
||||
"version": "v1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/event-manager.git",
|
||||
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3",
|
||||
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": "<2.9@dev"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^4.0",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\": "lib/Doctrine/Common"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Doctrine Event Manager component",
|
||||
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
|
||||
"keywords": [
|
||||
"event",
|
||||
"eventdispatcher",
|
||||
"eventmanager"
|
||||
],
|
||||
"time": "2018-06-11T11:59:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.2.0",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@ return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Crater Requirements
|
||||
| Crater Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
'version' => '1.0.0',
|
||||
'version' => '3.0.0',
|
||||
|
||||
];
|
||||
|
||||
@ -51,7 +51,7 @@ return [
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'strict' => false,
|
||||
'engine' => null,
|
||||
],
|
||||
|
||||
|
||||
244
config/dompdf.php
Normal file
244
config/dompdf.php
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set some default values. It is possible to add all defines that can be set
|
||||
| in dompdf_config.inc.php. You can also override the entire config file.
|
||||
|
|
||||
*/
|
||||
'show_warnings' => false, // Throw an Exception on warnings from dompdf
|
||||
'orientation' => 'portrait',
|
||||
'defines' => array(
|
||||
/**
|
||||
* The location of the DOMPDF font directory
|
||||
*
|
||||
* The location of the directory where DOMPDF will store fonts and font metrics
|
||||
* Note: This directory must exist and be writable by the webserver process.
|
||||
* *Please note the trailing slash.*
|
||||
*
|
||||
* Notes regarding fonts:
|
||||
* Additional .afm font metrics can be added by executing load_font.php from command line.
|
||||
*
|
||||
* Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
|
||||
* be embedded in the pdf file or the PDF may not display correctly. This can significantly
|
||||
* increase file size unless font subsetting is enabled. Before embedding a font please
|
||||
* review your rights under the font license.
|
||||
*
|
||||
* Any font specification in the source HTML is translated to the closest font available
|
||||
* in the font directory.
|
||||
*
|
||||
* The pdf standard "Base 14 fonts" are:
|
||||
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
|
||||
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
|
||||
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
|
||||
* Symbol, ZapfDingbats.
|
||||
*/
|
||||
"font_dir" => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
|
||||
|
||||
/**
|
||||
* The location of the DOMPDF font cache directory
|
||||
*
|
||||
* This directory contains the cached font metrics for the fonts used by DOMPDF.
|
||||
* This directory can be the same as DOMPDF_FONT_DIR
|
||||
*
|
||||
* Note: This directory must exist and be writable by the webserver process.
|
||||
*/
|
||||
"font_cache" => storage_path('fonts/'),
|
||||
|
||||
/**
|
||||
* The location of a temporary directory.
|
||||
*
|
||||
* The directory specified must be writeable by the webserver process.
|
||||
* The temporary directory is required to download remote images and when
|
||||
* using the PFDLib back end.
|
||||
*/
|
||||
"temp_dir" => sys_get_temp_dir(),
|
||||
|
||||
/**
|
||||
* ==== IMPORTANT ====
|
||||
*
|
||||
* dompdf's "chroot": Prevents dompdf from accessing system files or other
|
||||
* files on the webserver. All local files opened by dompdf must be in a
|
||||
* subdirectory of this directory. DO NOT set it to '/' since this could
|
||||
* allow an attacker to use dompdf to read any files on the server. This
|
||||
* should be an absolute path.
|
||||
* This is only checked on command line call by dompdf.php, but not by
|
||||
* direct class use like:
|
||||
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
|
||||
*/
|
||||
"chroot" => realpath(base_path()),
|
||||
|
||||
/**
|
||||
* Whether to enable font subsetting or not.
|
||||
*/
|
||||
"enable_font_subsetting" => false,
|
||||
|
||||
/**
|
||||
* The PDF rendering backend to use
|
||||
*
|
||||
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
|
||||
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
|
||||
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
|
||||
* Canvas_Factory} ultimately determines which rendering class to instantiate
|
||||
* based on this setting.
|
||||
*
|
||||
* Both PDFLib & CPDF rendering backends provide sufficient rendering
|
||||
* capabilities for dompdf, however additional features (e.g. object,
|
||||
* image and font support, etc.) differ between backends. Please see
|
||||
* {@link PDFLib_Adapter} for more information on the PDFLib backend
|
||||
* and {@link CPDF_Adapter} and lib/class.pdf.php for more information
|
||||
* on CPDF. Also see the documentation for each backend at the links
|
||||
* below.
|
||||
*
|
||||
* The GD rendering backend is a little different than PDFLib and
|
||||
* CPDF. Several features of CPDF and PDFLib are not supported or do
|
||||
* not make any sense when creating image files. For example,
|
||||
* multiple pages are not supported, nor are PDF 'objects'. Have a
|
||||
* look at {@link GD_Adapter} for more information. GD support is
|
||||
* experimental, so use it at your own risk.
|
||||
*
|
||||
* @link http://www.pdflib.com
|
||||
* @link http://www.ros.co.nz/pdf
|
||||
* @link http://www.php.net/image
|
||||
*/
|
||||
"pdf_backend" => "CPDF",
|
||||
|
||||
/**
|
||||
* PDFlib license key
|
||||
*
|
||||
* If you are using a licensed, commercial version of PDFlib, specify
|
||||
* your license key here. If you are using PDFlib-Lite or are evaluating
|
||||
* the commercial version of PDFlib, comment out this setting.
|
||||
*
|
||||
* @link http://www.pdflib.com
|
||||
*
|
||||
* If pdflib present in web server and auto or selected explicitely above,
|
||||
* a real license code must exist!
|
||||
*/
|
||||
//"DOMPDF_PDFLIB_LICENSE" => "your license key here",
|
||||
|
||||
/**
|
||||
* html target media view which should be rendered into pdf.
|
||||
* List of types and parsing rules for future extensions:
|
||||
* http://www.w3.org/TR/REC-html40/types.html
|
||||
* screen, tty, tv, projection, handheld, print, braille, aural, all
|
||||
* Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
|
||||
* Note, even though the generated pdf file is intended for print output,
|
||||
* the desired content might be different (e.g. screen or projection view of html file).
|
||||
* Therefore allow specification of content here.
|
||||
*/
|
||||
"default_media_type" => "screen",
|
||||
|
||||
/**
|
||||
* The default paper size.
|
||||
*
|
||||
* North America standard is "letter"; other countries generally "a4"
|
||||
*
|
||||
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
|
||||
*/
|
||||
"default_paper_size" => "a4",
|
||||
|
||||
/**
|
||||
* The default font family
|
||||
*
|
||||
* Used if no suitable fonts can be found. This must exist in the font folder.
|
||||
* @var string
|
||||
*/
|
||||
"default_font" => "DejaVu Sans",
|
||||
|
||||
/**
|
||||
* Image DPI setting
|
||||
*
|
||||
* This setting determines the default DPI setting for images and fonts. The
|
||||
* DPI may be overridden for inline images by explictly setting the
|
||||
* image's width & height style attributes (i.e. if the image's native
|
||||
* width is 600 pixels and you specify the image's width as 72 points,
|
||||
* the image will have a DPI of 600 in the rendered PDF. The DPI of
|
||||
* background images can not be overridden and is controlled entirely
|
||||
* via this parameter.
|
||||
*
|
||||
* For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
|
||||
* If a size in html is given as px (or without unit as image size),
|
||||
* this tells the corresponding size in pt.
|
||||
* This adjusts the relative sizes to be similar to the rendering of the
|
||||
* html page in a reference browser.
|
||||
*
|
||||
* In pdf, always 1 pt = 1/72 inch
|
||||
*
|
||||
* Rendering resolution of various browsers in px per inch:
|
||||
* Windows Firefox and Internet Explorer:
|
||||
* SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
|
||||
* Linux Firefox:
|
||||
* about:config *resolution: Default:96
|
||||
* (xorg screen dimension in mm and Desktop font dpi settings are ignored)
|
||||
*
|
||||
* Take care about extra font/image zoom factor of browser.
|
||||
*
|
||||
* In images, <img> size in pixel attribute, img css style, are overriding
|
||||
* the real image dimension in px for rendering.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
"dpi" => 96,
|
||||
|
||||
/**
|
||||
* Enable inline PHP
|
||||
*
|
||||
* If this setting is set to true then DOMPDF will automatically evaluate
|
||||
* inline PHP contained within <script type="text/php"> ... </script> tags.
|
||||
*
|
||||
* Enabling this for documents you do not trust (e.g. arbitrary remote html
|
||||
* pages) is a security risk. Set this option to false if you wish to process
|
||||
* untrusted documents.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_php" => false,
|
||||
|
||||
/**
|
||||
* Enable inline Javascript
|
||||
*
|
||||
* If this setting is set to true then DOMPDF will automatically insert
|
||||
* JavaScript code contained within <script type="text/javascript"> ... </script> tags.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_javascript" => true,
|
||||
|
||||
/**
|
||||
* Enable remote file access
|
||||
*
|
||||
* If this setting is set to true, DOMPDF will access remote sites for
|
||||
* images and CSS files as required.
|
||||
* This is required for part of test case www/test/image_variants.html through www/examples.php
|
||||
*
|
||||
* Attention!
|
||||
* This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
|
||||
* allowing remote access to dompdf.php or on allowing remote html code to be passed to
|
||||
* $dompdf = new DOMPDF(, $dompdf->load_html(...,
|
||||
* This allows anonymous users to download legally doubtful internet content which on
|
||||
* tracing back appears to being downloaded by your server, or allows malicious php code
|
||||
* in remote html pages to be executed by your server with your account privileges.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_remote" => true,
|
||||
|
||||
/**
|
||||
* A ratio applied to the fonts height to be more like browsers' line height
|
||||
*/
|
||||
"font_height_ratio" => 1.1,
|
||||
|
||||
/**
|
||||
* Use the more-than-experimental HTML5 Lib parser
|
||||
*/
|
||||
"enable_html5_parser" => true,
|
||||
),
|
||||
|
||||
|
||||
);
|
||||
@ -10,9 +10,9 @@ $factory->define(Address::class, function (Faker $faker) {
|
||||
'name' => $faker->name,
|
||||
'address_street_1' => $faker->streetAddress,
|
||||
'address_street_2' => $faker->streetAddress,
|
||||
'city_id' => 5909,
|
||||
'state_id' => 42,
|
||||
'country_id' => 1,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->state,
|
||||
'country_id' => 231,
|
||||
'zip' => $faker->postcode,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'fax' => $faker->phoneNumber,
|
||||
|
||||
16
database/migrations/2017_05_06_173711_create_states_table.php → database/migrations/2017_04_11_064308_create_units_table.php
Executable file → Normal file
16
database/migrations/2017_05_06_173711_create_states_table.php → database/migrations/2017_04_11_064308_create_units_table.php
Executable file → Normal file
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateStatesTable extends Migration
|
||||
class CreateUnitsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
@ -13,10 +13,12 @@ class CreateStatesTable extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('states', function (Blueprint $table) {
|
||||
$table->increments('id')->index();
|
||||
Schema::create('units', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('country_id');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -27,6 +29,6 @@ class CreateStatesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('states');
|
||||
Schema::dropIfExists('units');
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,8 @@ class CreateItemsTable extends Migration
|
||||
$table->unsignedBigInteger('price');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('unit_id')->unsigned()->nullable();
|
||||
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ class CreateInvoicesTable extends Migration
|
||||
$table->string('discount_per_item');
|
||||
$table->text('notes')->nullable();
|
||||
$table->string('discount_type')->nullable();
|
||||
$table->unsignedBigInteger('discount')->nullable();
|
||||
$table->decimal('discount', 15, 2)->nullable();
|
||||
$table->unsignedBigInteger('discount_val')->nullable();
|
||||
$table->unsignedBigInteger('sub_total');
|
||||
$table->unsignedBigInteger('total');
|
||||
|
||||
@ -18,10 +18,10 @@ class CreateInvoiceItemsTable extends Migration
|
||||
$table->string('name');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('discount_type');
|
||||
$table->unsignedBigInteger('quantity');
|
||||
$table->unsignedBigInteger('price');
|
||||
$table->decimal('quantity', 15, 2);
|
||||
$table->decimal('discount', 15, 2)->nullable();
|
||||
$table->unsignedBigInteger('discount_val');
|
||||
$table->unsignedBigInteger('discount');
|
||||
$table->unsignedBigInteger('tax');
|
||||
$table->unsignedBigInteger('total');
|
||||
$table->integer('invoice_id')->unsigned();
|
||||
|
||||
@ -23,8 +23,8 @@ class CreateEstimatesTable extends Migration
|
||||
$table->string('tax_per_item');
|
||||
$table->string('discount_per_item');
|
||||
$table->string('notes')->nullable();
|
||||
$table->decimal('discount', 15, 2)->nullable();
|
||||
$table->string('discount_type')->nullable();
|
||||
$table->unsignedBigInteger('discount')->nullable();
|
||||
$table->unsignedBigInteger('discount_val')->nullable();
|
||||
$table->unsignedBigInteger('sub_total');
|
||||
$table->unsignedBigInteger('total');
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCitiesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cities', function (Blueprint $table) {
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id')->index();
|
||||
$table->string('name');
|
||||
$table->integer('state_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cities');
|
||||
}
|
||||
}
|
||||
@ -18,9 +18,9 @@ class CreateEstimateItemsTable extends Migration
|
||||
$table->string('name');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('discount_type');
|
||||
$table->unsignedBigInteger('quantity');
|
||||
$table->unsignedBigInteger('discount');
|
||||
$table->unsignedBigInteger('discount_val');
|
||||
$table->decimal('quantity', 15, 2);
|
||||
$table->decimal('discount', 15, 2)->nullable();
|
||||
$table->unsignedBigInteger('discount_val')->nullable();
|
||||
$table->unsignedBigInteger('price');
|
||||
$table->unsignedBigInteger('tax');
|
||||
$table->unsignedBigInteger('total');
|
||||
|
||||
@ -30,6 +30,6 @@ class CreateExpenseCategoriesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('expenses_categories');
|
||||
Schema::dropIfExists('expense_categories');
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ class CreateExpensesTable extends Migration
|
||||
$table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -18,10 +18,8 @@ class CreateAddressesTable extends Migration
|
||||
$table->string('name')->nullable();
|
||||
$table->string('address_street_1')->nullable();
|
||||
$table->string('address_street_2')->nullable();
|
||||
$table->integer('city_id')->unsigned()->nullable();
|
||||
$table->foreign('city_id')->references('id')->on('cities');
|
||||
$table->integer('state_id')->unsigned()->nullable();
|
||||
$table->foreign('state_id')->references('id')->on('states');
|
||||
$table->string('city')->nullable();
|
||||
$table->string('state')->nullable();
|
||||
$table->integer('country_id')->unsigned()->nullable();
|
||||
$table->foreign('country_id')->references('id')->on('countries');
|
||||
$table->string('zip')->nullable();
|
||||
@ -41,6 +39,6 @@ class CreateAddressesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('address');
|
||||
Schema::dropIfExists('addresses');
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePaymentMethodsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('payment_methods', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('payment_methods');
|
||||
}
|
||||
}
|
||||
@ -16,16 +16,18 @@ class CreatePaymentsTable extends Migration
|
||||
Schema::create('payments', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('payment_number');
|
||||
$table->string('payment_mode')->nullable();
|
||||
$table->date('payment_date');
|
||||
$table->text('notes')->nullable();
|
||||
$table->unsignedBigInteger('amount');
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->integer('invoice_id')->unsigned()->nullable();
|
||||
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('payment_method_id')->unsigned()->nullable();
|
||||
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@ class CreateMediaTable extends Migration
|
||||
$table->string('mime_type')->nullable();
|
||||
$table->string('disk');
|
||||
$table->unsignedInteger('size');
|
||||
$table->json('manipulations');
|
||||
$table->json('custom_properties');
|
||||
$table->json('responsive_images');
|
||||
$table->text('manipulations');
|
||||
$table->text('custom_properties');
|
||||
$table->text('responsive_images');
|
||||
$table->unsignedInteger('order_column')->nullable();
|
||||
$table->nullableTimestamps();
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -122,7 +122,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Singapore Dollar',
|
||||
'code' => 'SGD',
|
||||
'symbol' => '',
|
||||
'symbol' => 'S$',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -147,7 +147,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Vietnamese Dong',
|
||||
'code' => 'VND',
|
||||
'symbol' => '',
|
||||
'symbol' => '₫',
|
||||
'precision' => '0',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
@ -155,7 +155,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Swiss Franc',
|
||||
'code' => 'CHF',
|
||||
'symbol' => '',
|
||||
'symbol' => 'Fr.',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '\'',
|
||||
'decimal_separator' => '.'
|
||||
@ -187,7 +187,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Thai Baht',
|
||||
'code' => 'THB',
|
||||
'symbol' => '',
|
||||
'symbol' => '฿',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -195,7 +195,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Nigerian Naira',
|
||||
'code' => 'NGN',
|
||||
'symbol' => '',
|
||||
'symbol' => '₦',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -227,7 +227,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Hong Kong Dollar',
|
||||
'code' => 'HKD',
|
||||
'symbol' => '',
|
||||
'symbol' => 'HK$',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -299,7 +299,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Netherlands Antillean Guilder',
|
||||
'code' => 'ANG',
|
||||
'symbol' => '',
|
||||
'symbol' => 'NAƒ',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
@ -323,7 +323,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Ghanaian Cedi',
|
||||
'code' => 'GHS',
|
||||
'symbol' => '',
|
||||
'symbol' => 'GH₵',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -331,7 +331,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Bulgarian Lev',
|
||||
'code' => 'BGN',
|
||||
'symbol' => '',
|
||||
'symbol' => 'Лв.',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ' ',
|
||||
'decimal_separator' => '.'
|
||||
@ -355,7 +355,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Romanian New Leu',
|
||||
'code' => 'RON',
|
||||
'symbol' => '',
|
||||
'symbol' => 'RON',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -371,7 +371,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Saudi Riyal',
|
||||
'code' => 'SAR',
|
||||
'symbol' => '',
|
||||
'symbol' => 'SِAR',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -387,7 +387,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Maldivian Rufiyaa',
|
||||
'code' => 'MVR',
|
||||
'symbol' => '',
|
||||
'symbol' => 'Rf',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -395,7 +395,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Costa Rican Colón',
|
||||
'code' => 'CRC',
|
||||
'symbol' => '',
|
||||
'symbol' => '₡',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -454,7 +454,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Tunisian Dinar',
|
||||
'code' => 'TND',
|
||||
'symbol' => '',
|
||||
'symbol' => 'د.ت',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -462,7 +462,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Russian Ruble',
|
||||
'code' => 'RUB',
|
||||
'symbol' => '',
|
||||
'symbol' => '₽',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -479,7 +479,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Omani Rial',
|
||||
'code' => 'OMR',
|
||||
'symbol' => '',
|
||||
'symbol' => 'ر.ع.',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -487,7 +487,7 @@ class CurrenciesTableSeeder extends Seeder
|
||||
[
|
||||
'name' => 'Ukrainian Hryvnia',
|
||||
'code' => 'UAH',
|
||||
'symbol' => '',
|
||||
'symbol' => '₴',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => ',',
|
||||
'decimal_separator' => '.'
|
||||
@ -524,6 +524,22 @@ class CurrenciesTableSeeder extends Seeder
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
],
|
||||
[
|
||||
'name' => 'Serbian Dinar',
|
||||
'code' => 'RSD',
|
||||
'symbol' => 'RSD',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
],
|
||||
[
|
||||
'name' => 'Kyrgyzstani som',
|
||||
'code' => 'KGS',
|
||||
'symbol' => 'С̲ ',
|
||||
'precision' => '2',
|
||||
'thousand_separator' => '.',
|
||||
'decimal_separator' => ','
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($currencies as $currency) {
|
||||
|
||||
@ -14,8 +14,6 @@ class DatabaseSeeder extends Seeder
|
||||
$this->call(CurrenciesTableSeeder::class);
|
||||
$this->call(RoleSeeder::class);
|
||||
$this->call(CountriesTableSeeder::class);
|
||||
$this->call(StatesTableSeeder::class);
|
||||
$this->call(CitiesTableSeeder::class);
|
||||
$this->call(EstimateTemplateSeeder::class);
|
||||
$this->call(InvoiceTemplateSeeder::class);
|
||||
}
|
||||
|
||||
20
database/seeds/PaymentMethodSeeder.php
Normal file
20
database/seeds/PaymentMethodSeeder.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Crater\PaymentMethod;
|
||||
|
||||
class PaymentMethodSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
PaymentMethod::create(['name' => 'Cash', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Check', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => 1]);
|
||||
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => 1]);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
27
database/seeds/UnitSeeder.php
Normal file
27
database/seeds/UnitSeeder.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Crater\Unit;
|
||||
|
||||
class UnitSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Unit::create(['name' => 'box', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'cm', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'dz', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'ft', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'g', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'in', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'kg', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'km', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'lb', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'mg', 'company_id' => 1]);
|
||||
Unit::create(['name' => 'pc', 'company_id' => 1]);
|
||||
}
|
||||
}
|
||||
40
docker-compose.yaml.example
Normal file
40
docker-compose.yaml.example
Normal file
@ -0,0 +1,40 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
|
||||
web:
|
||||
image: nginx
|
||||
depends_on:
|
||||
- php
|
||||
ports:
|
||||
- 8080:80
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- app:/app
|
||||
restart: always
|
||||
|
||||
php:
|
||||
build: .
|
||||
depends_on:
|
||||
- db
|
||||
expose:
|
||||
- 9000
|
||||
volumes:
|
||||
- app:/app
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: mariadb
|
||||
restart: always
|
||||
volumes:
|
||||
- db:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_USER: crater
|
||||
MYSQL_PASSWORD: crater
|
||||
MYSQL_DATABASE: crater
|
||||
MYSQL_ROOT_PASSWORD: crater
|
||||
|
||||
volumes:
|
||||
app:
|
||||
db:
|
||||
|
||||
53
nginx.conf
Normal file
53
nginx.conf
Normal file
@ -0,0 +1,53 @@
|
||||
worker_processes 8;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 4096;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
root /app/public;
|
||||
index index.php;
|
||||
charset utf-8;
|
||||
|
||||
access_log off;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /robots.txt { access_log off; log_not_found off; }
|
||||
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
add_header Content-Security-Policy "frame-ancestors 'self'";
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
}
|
||||
}
|
||||
}
|
||||
5531
package-lock.json
generated
5531
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@ -8,19 +8,16 @@
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^8.2.3",
|
||||
"browser-sync": "^2.26.7",
|
||||
"browser-sync-webpack-plugin": "^2.0.1",
|
||||
"babel-eslint": "^8.2.6",
|
||||
"cross-env": "^5.1",
|
||||
"css-loader": "^0.28.8",
|
||||
"eslint": "^4.14.0",
|
||||
"eslint-config-standard": "^11.0.0-beta.0",
|
||||
"eslint-plugin-import": "^2.11.0",
|
||||
"eslint-plugin-node": "^5.2.1",
|
||||
"eslint-plugin-promise": "^3.6.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"eslint-plugin-vue": "^4.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-prettier": "^6.10.1",
|
||||
"eslint-loader": "^3.0.3",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"eslint-plugin-vue": "^4.7.1",
|
||||
"laravel-mix": "^5.0.0",
|
||||
"prettier": "^2.0.2",
|
||||
"resolve-url-loader": "3.1.0",
|
||||
"sass": "^1.22.9",
|
||||
"sass-loader": "7.*",
|
||||
@ -35,19 +32,14 @@
|
||||
"axios": "^0.19",
|
||||
"bootstrap": "^4.1.0",
|
||||
"chart.js": "^2.7.3",
|
||||
"cross-env": "^5.1.4",
|
||||
"easy-pie-chart": "^2.1.7",
|
||||
"fs": "0.0.1-security",
|
||||
"guid": "0.0.12",
|
||||
"lodash": "^4.17.13",
|
||||
"moment": "^2.18.1",
|
||||
"npm": "^6.4.1",
|
||||
"popper.js": "^1.12.9",
|
||||
"sweet-modal-vue": "^2.0.0",
|
||||
"sweetalert": "^2.1.2",
|
||||
"toastr": "^2.1.4",
|
||||
"upgrade": "^1.1.0",
|
||||
"v-money": "^0.8.1",
|
||||
"v-tooltip": "^2.0.2",
|
||||
"vue": "^2.5.17",
|
||||
"vue-avatar-cropper": "^1.0.5",
|
||||
"vue-i18n": "^8.14.0",
|
||||
|
||||
2
public/assets/css/crater.css
vendored
2
public/assets/css/crater.css
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user